diff mbox series

[v6,32/36] rapidio: fix common struct sg_table related issues

Message ID 20200618153956.29558-33-m.szyprowski@samsung.com (mailing list archive)
State New, archived
Headers show
Series DRM: fix struct sg_table nents vs. orig_nents misuse | expand

Commit Message

Marek Szyprowski June 18, 2020, 3:39 p.m. UTC
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>
---
 drivers/rapidio/devices/rio_mport_cdev.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

Comments

kernel test robot June 18, 2020, 11:39 p.m. UTC | #1
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-000417
base:    ce2cc8efd7a40cbd17841add878cb691d0ce0bba
config: alpha-allyesconfig (attached as .config)
compiler: alpha-linux-gcc (GCC) 9.3.0
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
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=alpha 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   In file included from include/linux/dma-mapping.h:11,
                    from drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:25:
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c: In function 'amdgpu_vram_mgr_alloc_sgt':
>> include/linux/scatterlist.h:158:17: error: '*sgt' is a pointer; did you mean to use '->'?
     158 |  for_each_sg(sgt->sgl, sg, sgt->orig_nents, i)
         |                 ^~
   include/linux/scatterlist.h:152:22: note: in definition of macro 'for_each_sg'
     152 |  for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
         |                      ^~~~~~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:480:2: note: in expansion of macro 'for_each_sgtable_sg'
     480 |  for_each_sgtable_sg(*sgt, sg, i)
         |  ^~~~~~~~~~~~~~~~~~~
   include/linux/scatterlist.h:158:31: error: '*sgt' is a pointer; did you mean to use '->'?
     158 |  for_each_sg(sgt->sgl, sg, sgt->orig_nents, i)
         |                               ^~
   include/linux/scatterlist.h:152:38: note: in definition of macro 'for_each_sg'
     152 |  for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
         |                                      ^~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:480:2: note: in expansion of macro 'for_each_sgtable_sg'
     480 |  for_each_sgtable_sg(*sgt, sg, i)
         |  ^~~~~~~~~~~~~~~~~~~
>> include/linux/scatterlist.h:158:17: error: '*sgt' is a pointer; did you mean to use '->'?
     158 |  for_each_sg(sgt->sgl, sg, sgt->orig_nents, i)
         |                 ^~
   include/linux/scatterlist.h:152:22: note: in definition of macro 'for_each_sg'
     152 |  for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
         |                      ^~~~~~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:484:2: note: in expansion of macro 'for_each_sgtable_sg'
     484 |  for_each_sgtable_sg(*sgt, sg, i) {
         |  ^~~~~~~~~~~~~~~~~~~
   include/linux/scatterlist.h:158:31: error: '*sgt' is a pointer; did you mean to use '->'?
     158 |  for_each_sg(sgt->sgl, sg, sgt->orig_nents, i)
         |                               ^~
   include/linux/scatterlist.h:152:38: note: in definition of macro 'for_each_sg'
     152 |  for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
         |                                      ^~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:484:2: note: in expansion of macro 'for_each_sgtable_sg'
     484 |  for_each_sgtable_sg(*sgt, sg, i) {
         |  ^~~~~~~~~~~~~~~~~~~
>> include/linux/scatterlist.h:158:17: error: '*sgt' is a pointer; did you mean to use '->'?
     158 |  for_each_sg(sgt->sgl, sg, sgt->orig_nents, i)
         |                 ^~
   include/linux/scatterlist.h:152:22: note: in definition of macro 'for_each_sg'
     152 |  for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
         |                      ^~~~~~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:504:2: note: in expansion of macro 'for_each_sgtable_sg'
     504 |  for_each_sgtable_sg(*sgt, sg, i) {
         |  ^~~~~~~~~~~~~~~~~~~
   include/linux/scatterlist.h:158:31: error: '*sgt' is a pointer; did you mean to use '->'?
     158 |  for_each_sg(sgt->sgl, sg, sgt->orig_nents, i)
         |                               ^~
   include/linux/scatterlist.h:152:38: note: in definition of macro 'for_each_sg'
     152 |  for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg))
         |                                      ^~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:504:2: note: in expansion of macro 'for_each_sgtable_sg'
     504 |  for_each_sgtable_sg(*sgt, sg, i) {
         |  ^~~~~~~~~~~~~~~~~~~
   In file included from drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:26:
   At top level:
   drivers/gpu/drm/amd/amdgpu/amdgpu.h:190:18: warning: 'sched_policy' defined but not used [-Wunused-const-variable=]
     190 | static const int sched_policy = KFD_SCHED_POLICY_HWS;
         |                  ^~~~~~~~~~~~
   In file included from drivers/gpu/drm/amd/amdgpu/../display/dc/dc_types.h:33,
                    from drivers/gpu/drm/amd/amdgpu/../display/dc/dm_services_types.h:30,
                    from drivers/gpu/drm/amd/amdgpu/../include/dm_pp_interface.h:26,
                    from drivers/gpu/drm/amd/amdgpu/amdgpu.h:65,
                    from drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:26:
   drivers/gpu/drm/amd/amdgpu/../display/include/fixed31_32.h:76:32: warning: 'dc_fixpt_ln2_div_2' defined but not used [-Wunused-const-variable=]
      76 | static const struct fixed31_32 dc_fixpt_ln2_div_2 = { 1488522236LL };
         |                                ^~~~~~~~~~~~~~~~~~
   drivers/gpu/drm/amd/amdgpu/../display/include/fixed31_32.h:75:32: warning: 'dc_fixpt_ln2' defined but not used [-Wunused-const-variable=]
      75 | static const struct fixed31_32 dc_fixpt_ln2 = { 2977044471LL };
         |                                ^~~~~~~~~~~~
   drivers/gpu/drm/amd/amdgpu/../display/include/fixed31_32.h:74:32: warning: 'dc_fixpt_e' defined but not used [-Wunused-const-variable=]
      74 | static const struct fixed31_32 dc_fixpt_e = { 11674931555LL };
         |                                ^~~~~~~~~~
   drivers/gpu/drm/amd/amdgpu/../display/include/fixed31_32.h:73:32: warning: 'dc_fixpt_two_pi' defined but not used [-Wunused-const-variable=]
      73 | static const struct fixed31_32 dc_fixpt_two_pi = { 26986075409LL };
         |                                ^~~~~~~~~~~~~~~
   drivers/gpu/drm/amd/amdgpu/../display/include/fixed31_32.h:72:32: warning: 'dc_fixpt_pi' defined but not used [-Wunused-const-variable=]
      72 | static const struct fixed31_32 dc_fixpt_pi = { 13493037705LL };
         |                                ^~~~~~~~~~~
   drivers/gpu/drm/amd/amdgpu/../display/include/fixed31_32.h:67:32: warning: 'dc_fixpt_zero' defined but not used [-Wunused-const-variable=]
      67 | static const struct fixed31_32 dc_fixpt_zero = { 0 };
         |                                ^~~~~~~~~~~~~
--
   In file included from include/linux/kernel.h:11,
                    from include/linux/delay.h:22,
                    from drivers/gpu/drm/v3d/v3d_drv.h:4,
                    from drivers/gpu/drm/v3d/v3d_mmu.c:21:
   drivers/gpu/drm/v3d/v3d_mmu.c: In function 'v3d_mmu_insert_ptes':
>> include/linux/compiler.h:339:38: error: call to '__compiletime_assert_254' declared with attribute error: BUILD_BUG_ON failed: V3D_MMU_PAGE_SHIFT != PAGE_SIZE
     339 |  _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
         |                                      ^
   include/linux/compiler.h:320:4: note: in definition of macro '__compiletime_assert'
     320 |    prefix ## suffix();    \
         |    ^~~~~~
   include/linux/compiler.h:339:2: note: in expansion of macro '_compiletime_assert'
     339 |  _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
         |  ^~~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
      39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
         |                                     ^~~~~~~~~~~~~~~~~~
   include/linux/build_bug.h:50:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
      50 |  BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
         |  ^~~~~~~~~~~~~~~~
   drivers/gpu/drm/v3d/v3d_mmu.c:100:3: note: in expansion of macro 'BUILD_BUG_ON'
     100 |   BUILD_BUG_ON(V3D_MMU_PAGE_SHIFT != PAGE_SIZE);
         |   ^~~~~~~~~~~~
--
   drivers/rapidio/devices/rio_mport_cdev.c: In function 'dma_req_free':
>> drivers/rapidio/devices/rio_mport_cdev.c:576:48: error: incompatible type for argument 2 of 'dma_unmap_sgtable'
     576 |  dma_unmap_sgtable(req->dmach->device->dev, req->sgt, req->dir, 0);
         |                                             ~~~^~~~~
         |                                                |
         |                                                struct sg_table
   In file included from drivers/rapidio/devices/rio_mport_cdev.c:32:
   include/linux/dma-mapping.h:651:75: note: expected 'struct sg_table *' but argument is of type 'struct sg_table'
     651 | static inline void dma_unmap_sgtable(struct device *dev, struct sg_table *sgt,
         |                                                          ~~~~~~~~~~~~~~~~~^~~
   drivers/rapidio/devices/rio_mport_cdev.c: In function 'rio_dma_transfer':
>> drivers/rapidio/devices/rio_mport_cdev.c:932:46: error: incompatible type for argument 2 of 'dma_map_sgtable'
     932 |  ret = dma_map_sgtable(chan->device->dev, req->sgt, dir, 0);
         |                                           ~~~^~~~~
         |                                              |
         |                                              struct sg_table
   In file included from drivers/rapidio/devices/rio_mport_cdev.c:32:
   include/linux/dma-mapping.h:628:72: note: expected 'struct sg_table *' but argument is of type 'struct sg_table'
     628 | static inline int dma_map_sgtable(struct device *dev, struct sg_table *sgt,
         |                                                       ~~~~~~~~~~~~~~~~~^~~

vim +/dma_unmap_sgtable +576 drivers/rapidio/devices/rio_mport_cdev.c

   569	
   570	static void dma_req_free(struct kref *ref)
   571	{
   572		struct mport_dma_req *req = container_of(ref, struct mport_dma_req,
   573				refcount);
   574		struct mport_cdev_priv *priv = req->priv;
   575	
 > 576		dma_unmap_sgtable(req->dmach->device->dev, req->sgt, req->dir, 0);
   577		sg_free_table(&req->sgt);
   578		if (req->page_list) {
   579			unpin_user_pages(req->page_list, req->nr_pages);
   580			kfree(req->page_list);
   581		}
   582	
   583		if (req->map) {
   584			mutex_lock(&req->map->md->buf_mutex);
   585			kref_put(&req->map->ref, mport_release_mapping);
   586			mutex_unlock(&req->map->md->buf_mutex);
   587		}
   588	
   589		kref_put(&priv->dma_ref, mport_release_dma);
   590	
   591		kfree(req);
   592	}
   593	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c
index 451608e960a1..a33cc1b6beb2 100644
--- a/drivers/rapidio/devices/rio_mport_cdev.c
+++ b/drivers/rapidio/devices/rio_mport_cdev.c
@@ -573,8 +573,7 @@  static void dma_req_free(struct kref *ref)
 			refcount);
 	struct mport_cdev_priv *priv = req->priv;
 
-	dma_unmap_sg(req->dmach->device->dev,
-		     req->sgt.sgl, req->sgt.nents, req->dir);
+	dma_unmap_sgtable(req->dmach->device->dev, req->sgt, req->dir, 0);
 	sg_free_table(&req->sgt);
 	if (req->page_list) {
 		unpin_user_pages(req->page_list, req->nr_pages);
@@ -930,9 +929,8 @@  rio_dma_transfer(struct file *filp, u32 transfer_mode,
 				xfer->offset, xfer->length);
 	}
 
-	nents = dma_map_sg(chan->device->dev,
-			   req->sgt.sgl, req->sgt.nents, dir);
-	if (nents == 0) {
+	ret = dma_map_sgtable(chan->device->dev, req->sgt, dir, 0);
+	if (ret) {
 		rmcd_error("Failed to map SG list");
 		ret = -EFAULT;
 		goto err_pg;