* [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
* [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
* 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 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
* 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
* 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