* [PATCH v7 20/36] drm: tegra: fix common struct sg_table related issues [not found] ` <20200619103636.11974-1-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> @ 2020-06-19 10:36 ` Marek Szyprowski 2020-06-19 10:36 ` [PATCH v7 26/36] drm: host1x: " Marek Szyprowski 2020-06-19 10:36 ` [PATCH v7 31/36] staging: tegra-vde: " Marek Szyprowski 2 siblings, 0 replies; 7+ messages in thread From: Marek Szyprowski @ 2020-06-19 10:36 UTC (permalink / raw) To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, linaro-mm-sig-cunTk1MwBs8s++Sfvej+rw, linux-kernel-u79uwXL29TY76Z2rM5mHXA Cc: Bartlomiej Zolnierkiewicz, David Airlie, Jonathan Hunter, Thierry Reding, Daniel Vetter, linux-tegra-u79uwXL29TY76Z2rM5mHXA, Robin Murphy, Christoph Hellwig, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> --- drivers/gpu/drm/tegra/gem.c | 27 ++++++++++----------------- drivers/gpu/drm/tegra/plane.c | 15 +++++---------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 723df142a981..01d94befab11 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -98,8 +98,8 @@ static struct sg_table *tegra_bo_pin(struct device *dev, struct host1x_bo *bo, * the SG table needs to be copied to avoid overwriting any * other potential users of the original SG table. */ - err = sg_alloc_table_from_sg(sgt, obj->sgt->sgl, obj->sgt->nents, - GFP_KERNEL); + err = sg_alloc_table_from_sg(sgt, obj->sgt->sgl, + obj->sgt->orig_nents, GFP_KERNEL); if (err < 0) goto free; } else { @@ -196,8 +196,7 @@ static int tegra_bo_iommu_map(struct tegra_drm *tegra, struct tegra_bo *bo) bo->iova = bo->mm->start; - bo->size = iommu_map_sg(tegra->domain, bo->iova, bo->sgt->sgl, - bo->sgt->nents, prot); + bo->size = iommu_map_sgtable(tegra->domain, bo->iova, bo->sgt, prot); if (!bo->size) { dev_err(tegra->drm->dev, "failed to map buffer\n"); err = -ENOMEM; @@ -264,8 +263,7 @@ static struct tegra_bo *tegra_bo_alloc_object(struct drm_device *drm, static void tegra_bo_free(struct drm_device *drm, struct tegra_bo *bo) { if (bo->pages) { - dma_unmap_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents, - DMA_FROM_DEVICE); + dma_unmap_sgtable(drm->dev, bo->sgt, DMA_FROM_DEVICE, 0); drm_gem_put_pages(&bo->gem, bo->pages, true, true); sg_free_table(bo->sgt); kfree(bo->sgt); @@ -290,12 +288,9 @@ static int tegra_bo_get_pages(struct drm_device *drm, struct tegra_bo *bo) goto put_pages; } - err = dma_map_sg(drm->dev, bo->sgt->sgl, bo->sgt->nents, - DMA_FROM_DEVICE); - if (err == 0) { - err = -EFAULT; + err = dma_map_sgtable(drm->dev, bo->sgt, DMA_FROM_DEVICE, 0); + if (err) goto free_sgt; - } return 0; @@ -571,7 +566,7 @@ tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, goto free; } - if (dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir) == 0) + if (dma_map_sgtable(attach->dev, sgt, dir, 0)) goto free; return sgt; @@ -590,7 +585,7 @@ static void tegra_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach, struct tegra_bo *bo = to_tegra_bo(gem); if (bo->pages) - dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir); + dma_unmap_sgtable(attach->dev, sgt, dir, 0); sg_free_table(sgt); kfree(sgt); @@ -609,8 +604,7 @@ static int tegra_gem_prime_begin_cpu_access(struct dma_buf *buf, struct drm_device *drm = gem->dev; if (bo->pages) - dma_sync_sg_for_cpu(drm->dev, bo->sgt->sgl, bo->sgt->nents, - DMA_FROM_DEVICE); + dma_sync_sgtable_for_cpu(drm->dev, bo->sgt, DMA_FROM_DEVICE); return 0; } @@ -623,8 +617,7 @@ static int tegra_gem_prime_end_cpu_access(struct dma_buf *buf, struct drm_device *drm = gem->dev; if (bo->pages) - dma_sync_sg_for_device(drm->dev, bo->sgt->sgl, bo->sgt->nents, - DMA_TO_DEVICE); + dma_sync_sgtable_for_device(drm->dev, bo->sgt, DMA_TO_DEVICE); return 0; } diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index 9ccfb56e9b01..0d2ef1662a39 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c @@ -130,12 +130,9 @@ static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state) } if (sgt) { - err = dma_map_sg(dc->dev, sgt->sgl, sgt->nents, - DMA_TO_DEVICE); - if (err == 0) { - err = -ENOMEM; + err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0); + if (err) goto unpin; - } /* * The display controller needs contiguous memory, so @@ -143,7 +140,7 @@ static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state) * map its SG table to a single contiguous chunk of * I/O virtual memory. */ - if (err > 1) { + if (sgt->nents > 1) { err = -EINVAL; goto unpin; } @@ -165,8 +162,7 @@ static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state) struct sg_table *sgt = state->sgt[i]; if (sgt) - dma_unmap_sg(dc->dev, sgt->sgl, sgt->nents, - DMA_TO_DEVICE); + dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0); host1x_bo_unpin(dc->dev, &bo->base, sgt); state->iova[i] = DMA_MAPPING_ERROR; @@ -185,8 +181,7 @@ static void tegra_dc_unpin(struct tegra_dc *dc, struct tegra_plane_state *state) struct sg_table *sgt = state->sgt[i]; if (sgt) - dma_unmap_sg(dc->dev, sgt->sgl, sgt->nents, - DMA_TO_DEVICE); + dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0); host1x_bo_unpin(dc->dev, &bo->base, sgt); state->iova[i] = DMA_MAPPING_ERROR; -- 2.17.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v7 26/36] drm: host1x: fix common struct sg_table related issues [not found] ` <20200619103636.11974-1-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> 2020-06-19 10:36 ` [PATCH v7 20/36] drm: tegra: fix common struct sg_table related issues Marek Szyprowski @ 2020-06-19 10:36 ` Marek Szyprowski [not found] ` <20200619103636.11974-27-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> 2020-06-19 10:36 ` [PATCH v7 31/36] staging: tegra-vde: " Marek Szyprowski 2 siblings, 1 reply; 7+ messages in thread From: Marek Szyprowski @ 2020-06-19 10:36 UTC (permalink / raw) To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, linaro-mm-sig-cunTk1MwBs8s++Sfvej+rw, linux-kernel-u79uwXL29TY76Z2rM5mHXA Cc: Bartlomiej Zolnierkiewicz, David Airlie, Thierry Reding, Daniel Vetter, linux-tegra-u79uwXL29TY76Z2rM5mHXA, Robin Murphy, Christoph Hellwig, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> --- drivers/gpu/host1x/job.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index a10643aa89aa..4832b57f10c4 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -166,11 +166,9 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) goto unpin; } - err = dma_map_sg(dev, sgt->sgl, sgt->nents, dir); - if (!err) { - err = -ENOMEM; + err = dma_map_sgtable(dev, sgt, dir, 0); + if (err) goto unpin; - } job->unpins[job->num_unpins].dev = dev; job->unpins[job->num_unpins].dir = dir; @@ -217,7 +215,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) } if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) { - for_each_sg(sgt->sgl, sg, sgt->nents, j) + for_each_sgtable_sg(sgt, sg, j) gather_size += sg->length; gather_size = iova_align(&host->iova, gather_size); @@ -229,9 +227,9 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) goto unpin; } - err = iommu_map_sg(host->domain, + err = iommu_map_sgtable(host->domain, iova_dma_addr(&host->iova, alloc), - sgt->sgl, sgt->nents, IOMMU_READ); + sgt, IOMMU_READ); if (err == 0) { __free_iova(&host->iova, alloc); err = -EINVAL; @@ -241,12 +239,9 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) job->unpins[job->num_unpins].size = gather_size; phys_addr = iova_dma_addr(&host->iova, alloc); } else if (sgt) { - err = dma_map_sg(host->dev, sgt->sgl, sgt->nents, - DMA_TO_DEVICE); - if (!err) { - err = -ENOMEM; + err = dma_map_sgtable(host->dev, sgt, DMA_TO_DEVICE, 0); + if (err) goto unpin; - } job->unpins[job->num_unpins].dir = DMA_TO_DEVICE; job->unpins[job->num_unpins].dev = host->dev; @@ -647,8 +642,7 @@ void host1x_job_unpin(struct host1x_job *job) } if (unpin->dev && sgt) - dma_unmap_sg(unpin->dev, sgt->sgl, sgt->nents, - unpin->dir); + dma_unmap_sgtable(unpin->dev, sgt, unpin->dir, 0); host1x_bo_unpin(dev, unpin->bo, sgt); host1x_bo_put(unpin->bo); -- 2.17.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
[parent not found: <20200619103636.11974-27-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>]
* Re: [PATCH v7 26/36] drm: host1x: fix common struct sg_table related issues [not found] ` <20200619103636.11974-27-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> @ 2020-06-21 14:47 ` kernel test robot 0 siblings, 0 replies; 7+ messages in thread From: kernel test robot @ 2020-06-21 14:47 UTC (permalink / raw) To: Marek Szyprowski, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, linaro-mm-sig-cunTk1MwBs8s++Sfvej+rw, linux-kernel-u79uwXL29TY76Z2rM5mHXA Cc: kbuild-all-hn68Rpc1hR1g9hUCZPvPmw, Bartlomiej Zolnierkiewicz, David Airlie, clang-built-linux-/JYPxA39Uh5TLH3MbocFFw, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA, Robin Murphy, Christoph Hellwig [-- Attachment #1: Type: text/plain, Size: 7211 bytes --] Hi Marek, I love your patch! Yet something to improve: [auto build test ERROR on next-20200618] [also build test ERROR on v5.8-rc1] [cannot apply to linuxtv-media/master staging/staging-testing drm-exynos/exynos-drm-next drm-intel/for-linux-next linus/master v5.8-rc1 v5.7 v5.7-rc7] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Marek-Szyprowski/DRM-fix-struct-sg_table-nents-vs-orig_nents-misuse/20200619-184302 base: ce2cc8efd7a40cbd17841add878cb691d0ce0bba config: arm64-randconfig-r036-20200621 (attached as .config) compiler: clang version 11.0.0 (https://github.com/llvm/llvm-project ef455a55bcf2cfea04a99c361b182ad18b7f03f1) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install arm64 cross compiling tool for clang build # apt-get install binutils-aarch64-linux-gnu # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=arm64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org> All errors (new ones prefixed by >>): >> drivers/gpu/host1x/job.c:230:10: error: implicit declaration of function 'iommu_map_sgtable' [-Werror,-Wimplicit-function-declaration] err = iommu_map_sgtable(host->domain, ^ drivers/gpu/host1x/job.c:230:10: note: did you mean 'dma_map_sgtable'? include/linux/dma-mapping.h:628:19: note: 'dma_map_sgtable' declared here static inline int dma_map_sgtable(struct device *dev, struct sg_table *sgt, ^ 1 error generated. vim +/iommu_map_sgtable +230 drivers/gpu/host1x/job.c 100 101 static unsigned int pin_job(struct host1x *host, struct host1x_job *job) 102 { 103 struct host1x_client *client = job->client; 104 struct device *dev = client->dev; 105 struct iommu_domain *domain; 106 unsigned int i; 107 int err; 108 109 domain = iommu_get_domain_for_dev(dev); 110 job->num_unpins = 0; 111 112 for (i = 0; i < job->num_relocs; i++) { 113 struct host1x_reloc *reloc = &job->relocs[i]; 114 dma_addr_t phys_addr, *phys; 115 struct sg_table *sgt; 116 117 reloc->target.bo = host1x_bo_get(reloc->target.bo); 118 if (!reloc->target.bo) { 119 err = -EINVAL; 120 goto unpin; 121 } 122 123 /* 124 * If the client device is not attached to an IOMMU, the 125 * physical address of the buffer object can be used. 126 * 127 * Similarly, when an IOMMU domain is shared between all 128 * host1x clients, the IOVA is already available, so no 129 * need to map the buffer object again. 130 * 131 * XXX Note that this isn't always safe to do because it 132 * relies on an assumption that no cache maintenance is 133 * needed on the buffer objects. 134 */ 135 if (!domain || client->group) 136 phys = &phys_addr; 137 else 138 phys = NULL; 139 140 sgt = host1x_bo_pin(dev, reloc->target.bo, phys); 141 if (IS_ERR(sgt)) { 142 err = PTR_ERR(sgt); 143 goto unpin; 144 } 145 146 if (sgt) { 147 unsigned long mask = HOST1X_RELOC_READ | 148 HOST1X_RELOC_WRITE; 149 enum dma_data_direction dir; 150 151 switch (reloc->flags & mask) { 152 case HOST1X_RELOC_READ: 153 dir = DMA_TO_DEVICE; 154 break; 155 156 case HOST1X_RELOC_WRITE: 157 dir = DMA_FROM_DEVICE; 158 break; 159 160 case HOST1X_RELOC_READ | HOST1X_RELOC_WRITE: 161 dir = DMA_BIDIRECTIONAL; 162 break; 163 164 default: 165 err = -EINVAL; 166 goto unpin; 167 } 168 169 err = dma_map_sgtable(dev, sgt, dir, 0); 170 if (err) 171 goto unpin; 172 173 job->unpins[job->num_unpins].dev = dev; 174 job->unpins[job->num_unpins].dir = dir; 175 phys_addr = sg_dma_address(sgt->sgl); 176 } 177 178 job->addr_phys[job->num_unpins] = phys_addr; 179 job->unpins[job->num_unpins].bo = reloc->target.bo; 180 job->unpins[job->num_unpins].sgt = sgt; 181 job->num_unpins++; 182 } 183 184 for (i = 0; i < job->num_gathers; i++) { 185 struct host1x_job_gather *g = &job->gathers[i]; 186 size_t gather_size = 0; 187 struct scatterlist *sg; 188 struct sg_table *sgt; 189 dma_addr_t phys_addr; 190 unsigned long shift; 191 struct iova *alloc; 192 dma_addr_t *phys; 193 unsigned int j; 194 195 g->bo = host1x_bo_get(g->bo); 196 if (!g->bo) { 197 err = -EINVAL; 198 goto unpin; 199 } 200 201 /** 202 * If the host1x is not attached to an IOMMU, there is no need 203 * to map the buffer object for the host1x, since the physical 204 * address can simply be used. 205 */ 206 if (!iommu_get_domain_for_dev(host->dev)) 207 phys = &phys_addr; 208 else 209 phys = NULL; 210 211 sgt = host1x_bo_pin(host->dev, g->bo, phys); 212 if (IS_ERR(sgt)) { 213 err = PTR_ERR(sgt); 214 goto unpin; 215 } 216 217 if (!IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL) && host->domain) { 218 for_each_sgtable_sg(sgt, sg, j) 219 gather_size += sg->length; 220 gather_size = iova_align(&host->iova, gather_size); 221 222 shift = iova_shift(&host->iova); 223 alloc = alloc_iova(&host->iova, gather_size >> shift, 224 host->iova_end >> shift, true); 225 if (!alloc) { 226 err = -ENOMEM; 227 goto unpin; 228 } 229 > 230 err = iommu_map_sgtable(host->domain, 231 iova_dma_addr(&host->iova, alloc), 232 sgt, IOMMU_READ); 233 if (err == 0) { 234 __free_iova(&host->iova, alloc); 235 err = -EINVAL; 236 goto unpin; 237 } 238 239 job->unpins[job->num_unpins].size = gather_size; 240 phys_addr = iova_dma_addr(&host->iova, alloc); 241 } else if (sgt) { 242 err = dma_map_sgtable(host->dev, sgt, DMA_TO_DEVICE, 0); 243 if (err) 244 goto unpin; 245 246 job->unpins[job->num_unpins].dir = DMA_TO_DEVICE; 247 job->unpins[job->num_unpins].dev = host->dev; 248 phys_addr = sg_dma_address(sgt->sgl); 249 } 250 251 job->addr_phys[job->num_unpins] = phys_addr; 252 job->gather_addr_phys[i] = phys_addr; 253 254 job->unpins[job->num_unpins].bo = g->bo; 255 job->unpins[job->num_unpins].sgt = sgt; 256 job->num_unpins++; 257 } 258 259 return 0; 260 261 unpin: 262 host1x_job_unpin(job); 263 return err; 264 } 265 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org [-- Attachment #2: .config.gz --] [-- Type: application/gzip, Size: 35472 bytes --] [-- Attachment #3: Type: text/plain, Size: 0 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v7 31/36] staging: tegra-vde: fix common struct sg_table related issues [not found] ` <20200619103636.11974-1-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> 2020-06-19 10:36 ` [PATCH v7 20/36] drm: tegra: fix common struct sg_table related issues Marek Szyprowski 2020-06-19 10:36 ` [PATCH v7 26/36] drm: host1x: " Marek Szyprowski @ 2020-06-19 10:36 ` Marek Szyprowski [not found] ` <20200619103636.11974-32-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> 2 siblings, 1 reply; 7+ messages in thread From: Marek Szyprowski @ 2020-06-19 10:36 UTC (permalink / raw) To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, linaro-mm-sig-cunTk1MwBs8s++Sfvej+rw, linux-kernel-u79uwXL29TY76Z2rM5mHXA Cc: devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b, Bartlomiej Zolnierkiewicz, David Airlie, Greg Kroah-Hartman, linux-media-u79uwXL29TY76Z2rM5mHXA, Jonathan Hunter, Thierry Reding, Daniel Vetter, linux-tegra-u79uwXL29TY76Z2rM5mHXA, Dmitry Osipenko, Mauro Carvalho Chehab, Robin Murphy, Christoph Hellwig, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() function returns the number of the created entries in the DMA address space. However the subsequent calls to the dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with the original number of the entries passed to the dma_map_sg(). struct sg_table is a common structure used for describing a non-contiguous memory buffer, used commonly in the DRM and graphics subsystems. It consists of a scatterlist with memory pages and DMA addresses (sgl entry), as well as the number of scatterlist entries: CPU pages (orig_nents entry) and DMA mapped pages (nents entry). It turned out that it was a common mistake to misuse nents and orig_nents entries, calling DMA-mapping functions with a wrong number of entries or ignoring the number of mapped entries returned by the dma_map_sg() function. To avoid such issues, lets use a common dma-mapping wrappers operating directly on the struct sg_table objects and use scatterlist page iterators where possible. This, almost always, hides references to the nents and orig_nents entries, making the code robust, easier to follow and copy/paste safe. Signed-off-by: Marek Szyprowski <m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> Reviewed-by: Dmitry Osipenko <digetx-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> --- drivers/staging/media/tegra-vde/iommu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/media/tegra-vde/iommu.c b/drivers/staging/media/tegra-vde/iommu.c index 6af863d92123..adf8dc7ee25c 100644 --- a/drivers/staging/media/tegra-vde/iommu.c +++ b/drivers/staging/media/tegra-vde/iommu.c @@ -36,8 +36,8 @@ int tegra_vde_iommu_map(struct tegra_vde *vde, addr = iova_dma_addr(&vde->iova, iova); - size = iommu_map_sg(vde->domain, addr, sgt->sgl, sgt->nents, - IOMMU_READ | IOMMU_WRITE); + size = iommu_map_sgtable(vde->domain, addr, sgt, + IOMMU_READ | IOMMU_WRITE); if (!size) { __free_iova(&vde->iova, iova); return -ENXIO; -- 2.17.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
[parent not found: <20200619103636.11974-32-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>]
* Re: [PATCH v7 31/36] staging: tegra-vde: fix common struct sg_table related issues [not found] ` <20200619103636.11974-32-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> @ 2020-06-21 4:00 ` Dmitry Osipenko 2020-06-30 10:07 ` Marek Szyprowski 0 siblings, 1 reply; 7+ messages in thread From: Dmitry Osipenko @ 2020-06-21 4:00 UTC (permalink / raw) To: Marek Szyprowski Cc: devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b, Bartlomiej Zolnierkiewicz, David Airlie, Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Jonathan Hunter, linaro-mm-sig-cunTk1MwBs8s++Sfvej+rw, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Thierry Reding, Daniel Vetter, linux-tegra-u79uwXL29TY76Z2rM5mHXA, Mauro Carvalho Chehab, Robin Murphy, Christoph Hellwig, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, linux-media-u79uwXL29TY76Z2rM5mHXA В Fri, 19 Jun 2020 12:36:31 +0200 Marek Szyprowski <m.szyprowski@samsung.com> пишет: > The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() > function returns the number of the created entries in the DMA address > space. However the subsequent calls to the > dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with > the original number of the entries passed to the dma_map_sg(). > > struct sg_table is a common structure used for describing a > non-contiguous memory buffer, used commonly in the DRM and graphics > subsystems. It consists of a scatterlist with memory pages and DMA > addresses (sgl entry), as well as the number of scatterlist entries: > CPU pages (orig_nents entry) and DMA mapped pages (nents entry). > > It turned out that it was a common mistake to misuse nents and > orig_nents entries, calling DMA-mapping functions with a wrong number > of entries or ignoring the number of mapped entries returned by the > dma_map_sg() function. > > To avoid such issues, lets use a common dma-mapping wrappers operating > directly on the struct sg_table objects and use scatterlist page > iterators where possible. This, almost always, hides references to the > nents and orig_nents entries, making the code robust, easier to follow > and copy/paste safe. > > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> > Reviewed-by: Dmitry Osipenko <digetx@gmail.com> > --- > drivers/staging/media/tegra-vde/iommu.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/staging/media/tegra-vde/iommu.c > b/drivers/staging/media/tegra-vde/iommu.c index > 6af863d92123..adf8dc7ee25c 100644 --- > a/drivers/staging/media/tegra-vde/iommu.c +++ > b/drivers/staging/media/tegra-vde/iommu.c @@ -36,8 +36,8 @@ int > tegra_vde_iommu_map(struct tegra_vde *vde, > addr = iova_dma_addr(&vde->iova, iova); > > - size = iommu_map_sg(vde->domain, addr, sgt->sgl, sgt->nents, > - IOMMU_READ | IOMMU_WRITE); > + size = iommu_map_sgtable(vde->domain, addr, sgt, > + IOMMU_READ | IOMMU_WRITE); > if (!size) { > __free_iova(&vde->iova, iova); > return -ENXIO; Ahh, I saw the build failure report. You're changing the DMA API in this series, while DMA API isn't used by this driver, it uses IOMMU API. Hence there is no need to touch this code. Similar problem in the host1x driver patch. _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v7 31/36] staging: tegra-vde: fix common struct sg_table related issues 2020-06-21 4:00 ` Dmitry Osipenko @ 2020-06-30 10:07 ` Marek Szyprowski [not found] ` <559970b6-e80f-90ec-7fb0-1fab742d99de-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> 0 siblings, 1 reply; 7+ messages in thread From: Marek Szyprowski @ 2020-06-30 10:07 UTC (permalink / raw) To: Dmitry Osipenko Cc: dri-devel, iommu, linaro-mm-sig, linux-kernel, Christoph Hellwig, Robin Murphy, Bartlomiej Zolnierkiewicz, linux-arm-kernel, David Airlie, Daniel Vetter, Mauro Carvalho Chehab, Greg Kroah-Hartman, Thierry Reding, Jonathan Hunter, linux-media, linux-tegra, devel On 21.06.2020 06:00, Dmitry Osipenko wrote: > В Fri, 19 Jun 2020 12:36:31 +0200 > Marek Szyprowski <m.szyprowski@samsung.com> пишет: > >> The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() >> function returns the number of the created entries in the DMA address >> space. However the subsequent calls to the >> dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with >> the original number of the entries passed to the dma_map_sg(). >> >> struct sg_table is a common structure used for describing a >> non-contiguous memory buffer, used commonly in the DRM and graphics >> subsystems. It consists of a scatterlist with memory pages and DMA >> addresses (sgl entry), as well as the number of scatterlist entries: >> CPU pages (orig_nents entry) and DMA mapped pages (nents entry). >> >> It turned out that it was a common mistake to misuse nents and >> orig_nents entries, calling DMA-mapping functions with a wrong number >> of entries or ignoring the number of mapped entries returned by the >> dma_map_sg() function. >> >> To avoid such issues, lets use a common dma-mapping wrappers operating >> directly on the struct sg_table objects and use scatterlist page >> iterators where possible. This, almost always, hides references to the >> nents and orig_nents entries, making the code robust, easier to follow >> and copy/paste safe. >> >> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> >> Reviewed-by: Dmitry Osipenko <digetx@gmail.com> >> --- >> drivers/staging/media/tegra-vde/iommu.c | 4 ++-- >> 1 file changed, 2 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/staging/media/tegra-vde/iommu.c >> b/drivers/staging/media/tegra-vde/iommu.c index >> 6af863d92123..adf8dc7ee25c 100644 --- >> a/drivers/staging/media/tegra-vde/iommu.c +++ >> b/drivers/staging/media/tegra-vde/iommu.c @@ -36,8 +36,8 @@ int >> tegra_vde_iommu_map(struct tegra_vde *vde, >> addr = iova_dma_addr(&vde->iova, iova); >> >> - size = iommu_map_sg(vde->domain, addr, sgt->sgl, sgt->nents, >> - IOMMU_READ | IOMMU_WRITE); >> + size = iommu_map_sgtable(vde->domain, addr, sgt, >> + IOMMU_READ | IOMMU_WRITE); >> if (!size) { >> __free_iova(&vde->iova, iova); >> return -ENXIO; > Ahh, I saw the build failure report. You're changing the DMA API in > this series, while DMA API isn't used by this driver, it uses IOMMU > API. Hence there is no need to touch this code. Similar problem in the > host1x driver patch. The issue is caused by the lack of iommu_map_sgtable() stub when no IOMMU support is configured. I've posted a patch for this: https://lore.kernel.org/lkml/20200630081756.18526-1-m.szyprowski@samsung.com/ The patch for this driver is fine, we have to wait until the above fix gets merged and then it can be applied during the next release cycle. Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <559970b6-e80f-90ec-7fb0-1fab742d99de-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>]
* Re: [PATCH v7 31/36] staging: tegra-vde: fix common struct sg_table related issues [not found] ` <559970b6-e80f-90ec-7fb0-1fab742d99de-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> @ 2020-07-01 1:45 ` Dmitry Osipenko 0 siblings, 0 replies; 7+ messages in thread From: Dmitry Osipenko @ 2020-07-01 1:45 UTC (permalink / raw) To: Marek Szyprowski Cc: devel-gWbeCf7V1WCQmaza687I9mD2FQJk+8+b, Bartlomiej Zolnierkiewicz, David Airlie, Greg Kroah-Hartman, linux-kernel-u79uwXL29TY76Z2rM5mHXA, dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, Jonathan Hunter, linaro-mm-sig-cunTk1MwBs8s++Sfvej+rw, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA, Thierry Reding, Daniel Vetter, linux-tegra-u79uwXL29TY76Z2rM5mHXA, Mauro Carvalho Chehab, Robin Murphy, Christoph Hellwig, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, linux-media-u79uwXL29TY76Z2rM5mHXA 30.06.2020 13:07, Marek Szyprowski пишет: > On 21.06.2020 06:00, Dmitry Osipenko wrote: >> В Fri, 19 Jun 2020 12:36:31 +0200 >> Marek Szyprowski <m.szyprowski@samsung.com> пишет: >> >>> The Documentation/DMA-API-HOWTO.txt states that the dma_map_sg() >>> function returns the number of the created entries in the DMA address >>> space. However the subsequent calls to the >>> dma_sync_sg_for_{device,cpu}() and dma_unmap_sg must be called with >>> the original number of the entries passed to the dma_map_sg(). >>> >>> struct sg_table is a common structure used for describing a >>> non-contiguous memory buffer, used commonly in the DRM and graphics >>> subsystems. It consists of a scatterlist with memory pages and DMA >>> addresses (sgl entry), as well as the number of scatterlist entries: >>> CPU pages (orig_nents entry) and DMA mapped pages (nents entry). >>> >>> It turned out that it was a common mistake to misuse nents and >>> orig_nents entries, calling DMA-mapping functions with a wrong number >>> of entries or ignoring the number of mapped entries returned by the >>> dma_map_sg() function. >>> >>> To avoid such issues, lets use a common dma-mapping wrappers operating >>> directly on the struct sg_table objects and use scatterlist page >>> iterators where possible. This, almost always, hides references to the >>> nents and orig_nents entries, making the code robust, easier to follow >>> and copy/paste safe. >>> >>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> >>> Reviewed-by: Dmitry Osipenko <digetx@gmail.com> >>> --- >>> drivers/staging/media/tegra-vde/iommu.c | 4 ++-- >>> 1 file changed, 2 insertions(+), 2 deletions(-) >>> >>> diff --git a/drivers/staging/media/tegra-vde/iommu.c >>> b/drivers/staging/media/tegra-vde/iommu.c index >>> 6af863d92123..adf8dc7ee25c 100644 --- >>> a/drivers/staging/media/tegra-vde/iommu.c +++ >>> b/drivers/staging/media/tegra-vde/iommu.c @@ -36,8 +36,8 @@ int >>> tegra_vde_iommu_map(struct tegra_vde *vde, >>> addr = iova_dma_addr(&vde->iova, iova); >>> >>> - size = iommu_map_sg(vde->domain, addr, sgt->sgl, sgt->nents, >>> - IOMMU_READ | IOMMU_WRITE); >>> + size = iommu_map_sgtable(vde->domain, addr, sgt, >>> + IOMMU_READ | IOMMU_WRITE); >>> if (!size) { >>> __free_iova(&vde->iova, iova); >>> return -ENXIO; >> Ahh, I saw the build failure report. You're changing the DMA API in >> this series, while DMA API isn't used by this driver, it uses IOMMU >> API. Hence there is no need to touch this code. Similar problem in the >> host1x driver patch. > > The issue is caused by the lack of iommu_map_sgtable() stub when no > IOMMU support is configured. I've posted a patch for this: > > https://lore.kernel.org/lkml/20200630081756.18526-1-m.szyprowski@samsung.com/ > > The patch for this driver is fine, we have to wait until the above fix > gets merged and then it can be applied during the next release cycle. Thank you for the clarification! _______________________________________________ iommu mailing list iommu@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/iommu ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-07-01 1:45 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20200619103636.11974-1-m.szyprowski@samsung.com>
[not found] ` <CGME20200619103706eucas1p2b9a9926941e812db1111ec46a97695cd@eucas1p2.samsung.com>
[not found] ` <20200619103636.11974-1-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2020-06-19 10:36 ` [PATCH v7 20/36] drm: tegra: fix common struct sg_table related issues Marek Szyprowski
2020-06-19 10:36 ` [PATCH v7 26/36] drm: host1x: " Marek Szyprowski
[not found] ` <20200619103636.11974-27-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2020-06-21 14:47 ` kernel test robot
2020-06-19 10:36 ` [PATCH v7 31/36] staging: tegra-vde: " Marek Szyprowski
[not found] ` <20200619103636.11974-32-m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2020-06-21 4:00 ` Dmitry Osipenko
2020-06-30 10:07 ` Marek Szyprowski
[not found] ` <559970b6-e80f-90ec-7fb0-1fab742d99de-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2020-07-01 1:45 ` Dmitry Osipenko
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox