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 |
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 --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;
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(-)