mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
gpu: nvgpu: ensure coherency in sema wait ioctl
The semaphore dmabuf supplied in NVGPU_IOCTL_CHANNEL_WAIT is not necessarily always cache coherent with the GPU. Call dma_buf_begin_cpu_access() and dma_buf_end_cpu_access() around the sema read to make sure we see updated values after the interrupt. Jira NVGPU-5387 Bug 3028497 Change-Id: I09d23c8a679621c86bdfe609d454199e05fa2987 Signed-off-by: Konsta Hölttä <kholtta@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2359002 Reviewed-by: automaticguardword <automaticguardword@nvidia.com> Reviewed-by: Alex Waterman <alexw@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Alex Waterman
parent
530381ee86
commit
d660a5d0e8
@@ -629,13 +629,41 @@ static void nvgpu_get_fence_args(
|
|||||||
fence_args_out->value = fence_args_in->value;
|
fence_args_out->value = fence_args_in->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool channel_test_user_semaphore(struct dma_buf *dmabuf, void *data,
|
||||||
|
u32 offset, u32 payload)
|
||||||
|
{
|
||||||
|
u32 *semaphore;
|
||||||
|
bool ret;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||||
|
err = dma_buf_begin_cpu_access(dmabuf, offset, sizeof(u32), DMA_FROM_DEVICE);
|
||||||
|
#else
|
||||||
|
err = dma_buf_begin_cpu_access(dmabuf, DMA_FROM_DEVICE);
|
||||||
|
#endif
|
||||||
|
if (err != 0) {
|
||||||
|
pr_err("nvgpu: sema begin cpu access failed\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
semaphore = (u32 *)((uintptr_t)data + offset);
|
||||||
|
ret = *semaphore == payload;
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0)
|
||||||
|
dma_buf_end_cpu_access(dmabuf, offset, sizeof(u32), DMA_FROM_DEVICE);
|
||||||
|
#else
|
||||||
|
dma_buf_end_cpu_access(dmabuf, DMA_FROM_DEVICE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int gk20a_channel_wait_semaphore(struct nvgpu_channel *ch,
|
static int gk20a_channel_wait_semaphore(struct nvgpu_channel *ch,
|
||||||
ulong id, u32 offset,
|
ulong id, u32 offset,
|
||||||
u32 payload, u32 timeout)
|
u32 payload, u32 timeout)
|
||||||
{
|
{
|
||||||
struct dma_buf *dmabuf;
|
struct dma_buf *dmabuf;
|
||||||
void *data;
|
void *data;
|
||||||
u32 *semaphore;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* do not wait if channel has timed out */
|
/* do not wait if channel has timed out */
|
||||||
@@ -669,11 +697,9 @@ static int gk20a_channel_wait_semaphore(struct nvgpu_channel *ch,
|
|||||||
goto cleanup_put;
|
goto cleanup_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
semaphore = (u32 *)((uintptr_t)data + offset);
|
|
||||||
|
|
||||||
ret = NVGPU_COND_WAIT_INTERRUPTIBLE(
|
ret = NVGPU_COND_WAIT_INTERRUPTIBLE(
|
||||||
&ch->semaphore_wq,
|
&ch->semaphore_wq,
|
||||||
*semaphore == payload ||
|
channel_test_user_semaphore(dmabuf, data, offset, payload) ||
|
||||||
nvgpu_channel_check_unserviceable(ch),
|
nvgpu_channel_check_unserviceable(ch),
|
||||||
timeout);
|
timeout);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user