From 20204e3c48f048264c48a7170fd5fb35f706c75e Mon Sep 17 00:00:00 2001 From: fincs Date: Sat, 6 Oct 2018 16:47:25 +0200 Subject: [PATCH] NvFence: fix regression on 1.x --- nx/source/nvidia/fence.c | 51 ++++++++++++++++++++++------ nx/source/nvidia/ioctl/nvhost-ctrl.c | 4 +-- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/nx/source/nvidia/fence.c b/nx/source/nvidia/fence.c index 16ac1a5d..b1ba4980 100644 --- a/nx/source/nvidia/fence.c +++ b/nx/source/nvidia/fence.c @@ -3,6 +3,7 @@ #include "arm/atomics.h" #include "kernel/svc.h" #include "kernel/event.h" +#include "kernel/detect.h" #include "services/nv.h" #include "nvidia/fence.h" @@ -91,7 +92,20 @@ void nvFenceExit(void) } } -Result nvFenceWait(NvFence* f, s32 timeout_us) +static Result _nvFenceEventWaitCommon(Event* event, u32 event_id, s32 timeout_us) +{ + u64 timeout_ns = U64_MAX; + if (timeout_us >= 0) + timeout_ns = (u64)1000*timeout_us; + Result rc = eventWait(event, timeout_ns); + if ((rc & 0x3FFFFF) == 0xEA01) { // timeout + nvioctlNvhostCtrl_EventSignal(g_ctrl_fd, event_id); + rc = MAKERESULT(Module_LibnxNvidia, LibnxNvidiaError_Timeout); + } + return rc; +} + +static Result _nvFenceWait_200(NvFence* f, s32 timeout_us) { Result rc = MAKERESULT(Module_LibnxNvidia, LibnxNvidiaError_InsufficientMemory); int event_id = _nvGetEventSlot(); @@ -99,22 +113,37 @@ Result nvFenceWait(NvFence* f, s32 timeout_us) Event* event = _nvGetEvent(event_id); if (event) { rc = nvioctlNvhostCtrl_EventWaitAsync(g_ctrl_fd, f->id, f->value, timeout_us, event_id); - if (rc == MAKERESULT(Module_LibnxNvidia, LibnxNvidiaError_Timeout)) { - u64 timeout_ns = U64_MAX; - if (timeout_us >= 0) - timeout_ns = (u64)1000*timeout_us; - rc = eventWait(event, timeout_ns); - if ((rc & 0x3FFFFF) == 0xEA01) { // timeout - nvioctlNvhostCtrl_EventSignal(g_ctrl_fd, 0x10000000 | event_id); - rc = MAKERESULT(Module_LibnxNvidia, LibnxNvidiaError_Timeout); - } - } + if (rc == MAKERESULT(Module_LibnxNvidia, LibnxNvidiaError_Timeout)) + rc = _nvFenceEventWaitCommon(event, 0x10000000 | event_id, timeout_us); } _nvFreeEventSlot(event_id); } return rc; } +static Result _nvFenceWait_100(NvFence* f, s32 timeout_us) +{ + u32 event_id; + Result rc = nvioctlNvhostCtrl_EventWait(g_ctrl_fd, f->id, f->value, timeout_us, 0, &event_id); + if (rc == MAKERESULT(Module_LibnxNvidia, LibnxNvidiaError_Timeout) && timeout_us) { + Event event; + rc = nvQueryEvent(g_ctrl_fd, event_id, &event); + if (R_SUCCEEDED(rc)) { + rc = _nvFenceEventWaitCommon(&event, event_id, timeout_us); + eventClose(&event); + } + } + return rc; +} + +Result nvFenceWait(NvFence* f, s32 timeout_us) +{ + if (kernelAbove200()) + return _nvFenceWait_200(f, timeout_us); + else + return _nvFenceWait_100(f, timeout_us); +} + Result nvMultiFenceWait(NvMultiFence* mf, s32 timeout_us) { // TODO: properly respect timeout diff --git a/nx/source/nvidia/ioctl/nvhost-ctrl.c b/nx/source/nvidia/ioctl/nvhost-ctrl.c index f5ec2f58..78d1b1de 100644 --- a/nx/source/nvidia/ioctl/nvhost-ctrl.c +++ b/nx/source/nvidia/ioctl/nvhost-ctrl.c @@ -84,9 +84,7 @@ Result nvioctlNvhostCtrl_EventWait(u32 fd, u32 syncpt_id, u32 threshold, s32 tim data.value = event_id; rc = nvIoctl(fd, _NV_IOWR(0x00, 0x1D, data), &data); - - if (R_SUCCEEDED(rc)) - *out = data.value; + *out = data.value; return rc; }