From ff7d0cc87cd3da5bdeb6acc49a0098f9e773cef9 Mon Sep 17 00:00:00 2001 From: Ashish Mhetre Date: Mon, 9 Jan 2023 08:46:35 +0000 Subject: [PATCH] platform: tegra: rtcpu: Fix cache sync APIs For dma mappings done with dma_map_sg() calls, dma_sync_sg* calls are required in order to make sure that caches for all the scattered addresses are synced. Using dma_sync_single* call for syncing caches can access address which is not mapped by dma_sync_sg() and cause kernel exceptions. Fix this by using correct cache sync calls for appropriate dma mapping APIs. Bug 3879036 Change-Id: I30afcf17806c505d94ff4eb7faefab5fbbf9e7b9 Signed-off-by: Ashish Mhetre Signed-off-by: Matti Ryttylainen Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2839838 Reviewed-by: svcacv Reviewed-by: Pekka Pessi Reviewed-by: Sachin Nikam GVS: Gerrit_Virtual_Submit --- drivers/platform/tegra/rtcpu/debug.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/platform/tegra/rtcpu/debug.c b/drivers/platform/tegra/rtcpu/debug.c index 830ac02f..a44d8765 100644 --- a/drivers/platform/tegra/rtcpu/debug.c +++ b/drivers/platform/tegra/rtcpu/debug.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 -// Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include "soc/tegra/camrtc-dbg-messages.h" @@ -840,6 +840,8 @@ static void camrtc_run_rmem_unmap_all(struct camrtc_debug *crd, } } +#define INT_MAX ((int)(~0U >> 1)) + static int camrtc_run_mem_map(struct tegra_ivc_channel *ch, struct device *mem_dev, struct device *dev, @@ -861,6 +863,8 @@ static int camrtc_run_mem_map(struct tegra_ivc_channel *ch, if (mem_dev == dev) { *return_iova = mem->iova; + dma_sync_single_for_device(dev, mem->iova, mem->size, + DMA_BIDIRECTIONAL); goto done; } @@ -872,6 +876,8 @@ static int camrtc_run_mem_map(struct tegra_ivc_channel *ch, *return_iova = 0ULL; return -ENOMEM; } + dma_sync_single_for_device(dev, mem->iova, mem->size, + DMA_BIDIRECTIONAL); } else { ret = dma_get_sgtable(dev, sgt, mem->ptr, mem->iova, mem->size); if (ret < 0) { @@ -889,6 +895,10 @@ static int camrtc_run_mem_map(struct tegra_ivc_channel *ch, } *return_iova = sgt->sgl->dma_address; + if (sgt->nents <= INT_MAX) + dma_sync_sg_for_device(dev, sgt->sgl, (int)sgt->nents, DMA_BIDIRECTIONAL); + else + ret = -EINVAL; } done: @@ -1056,8 +1066,6 @@ static int camrtc_run_mem_test(struct seq_file *file, if (ret < 0) goto unmap; - dma_sync_single_for_device(mem_dev, mem->iova, mem->used, - DMA_BIDIRECTIONAL); } BUILD_BUG_ON_MISMATCH( @@ -1080,8 +1088,12 @@ static int camrtc_run_mem_test(struct seq_file *file, if (!WARN_ON(testmem->size > mem->size)) mem->used = testmem->size; - dma_sync_single_for_cpu(mem_dev, mem->iova, mem->used, - DMA_BIDIRECTIONAL); + if (_camdbg_rmem.enabled) + dma_sync_single_for_cpu(mem_dev, mem->iova, mem->used, + DMA_BIDIRECTIONAL); + else + dma_sync_sg_for_cpu(mem_dev, vi_sgt[i].sgl, + vi_sgt[i].nents, DMA_BIDIRECTIONAL); } unmap: