media: mediatek: vcodec: fix AV1 decode fail for 36bit iova

Xiaoyong Lu posted 1 patch 1 year, 4 months ago
There is a newer version of this series
.../platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c    | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
media: mediatek: vcodec: fix AV1 decode fail for 36bit iova
Posted by Xiaoyong Lu 1 year, 4 months ago
Decoder hardware will access incorrect iova address when tile buffer is
36bit, leading to iommu fault when hardware access dram data.

Fixes: 2f5d0aef37c6 ("media: mediatek: vcodec: support stateless AV1 decoder")
Signed-off-by: Xiaoyong Lu<xiaoyong.lu@mediatek.com>
---
- Test ok: mt8195 32bit and mt8188 36bit iova.
---
 .../platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c    | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c
index 404a1a23fd40..420222c8a56d 100644
--- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c
@@ -1658,9 +1658,9 @@ static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *ins
 	u32 allow_update_cdf = 0;
 	u32 sb_boundary_x_m1 = 0, sb_boundary_y_m1 = 0;
 	int tile_info_base;
-	u32 tile_buf_pa;
+	u64 tile_buf_pa;
 	u32 *tile_info_buf = instance->tile.va;
-	u32 pa = (u32)bs->dma_addr;
+	u64 pa = (u64)bs->dma_addr;
 
 	if (uh->disable_cdf_update == 0)
 		allow_update_cdf = 1;
@@ -1673,7 +1673,8 @@ static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *ins
 		tile_info_buf[tile_info_base + 0] = (tile_group->tile_size[tile_num] << 3);
 		tile_buf_pa = pa + tile_group->tile_start_offset[tile_num];
 
-		tile_info_buf[tile_info_base + 1] = (tile_buf_pa >> 4) << 4;
+		tile_info_buf[tile_info_base + 1] = (unsigned int)(tile_buf_pa >> 4) << 4 +
+			((unsigned int)(tile_buf_pa >> 32) & 0xf);
 		tile_info_buf[tile_info_base + 2] = (tile_buf_pa % 16) << 3;
 
 		sb_boundary_x_m1 =
-- 
2.25.1
Re: media: mediatek: vcodec: fix AV1 decode fail for 36bit iova
Posted by Nicolas Dufresne 1 year, 4 months ago
Hi,

Le mercredi 28 juin 2023 à 13:41 +0800, Xiaoyong Lu a écrit :
> Decoder hardware will access incorrect iova address when tile buffer is
> 36bit, leading to iommu fault when hardware access dram data.
> 
> Fixes: 2f5d0aef37c6 ("media: mediatek: vcodec: support stateless AV1 decoder")
> Signed-off-by: Xiaoyong Lu<xiaoyong.lu@mediatek.com>
> ---
> - Test ok: mt8195 32bit and mt8188 36bit iova.
> ---
>  .../platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c    | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c
> index 404a1a23fd40..420222c8a56d 100644
> --- a/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c
> +++ b/drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c
> @@ -1658,9 +1658,9 @@ static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *ins
>  	u32 allow_update_cdf = 0;
>  	u32 sb_boundary_x_m1 = 0, sb_boundary_y_m1 = 0;
>  	int tile_info_base;
> -	u32 tile_buf_pa;
> +	u64 tile_buf_pa;
>  	u32 *tile_info_buf = instance->tile.va;
> -	u32 pa = (u32)bs->dma_addr;
> +	u64 pa = (u64)bs->dma_addr;
>  
>  	if (uh->disable_cdf_update == 0)
>  		allow_update_cdf = 1;
> @@ -1673,7 +1673,8 @@ static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *ins
>  		tile_info_buf[tile_info_base + 0] = (tile_group->tile_size[tile_num] << 3);
>  		tile_buf_pa = pa + tile_group->tile_start_offset[tile_num];
>  
> -		tile_info_buf[tile_info_base + 1] = (tile_buf_pa >> 4) << 4;
> +		tile_info_buf[tile_info_base + 1] = (unsigned int)(tile_buf_pa >> 4) << 4 +
> +			((unsigned int)(tile_buf_pa >> 32) & 0xf);

I'm not clear on how this works. In the original code, it was a complicated way
to ignore the 4 least significant bits. Something like this would avoid the cast
and clarify it:

		tile_info_buf[tile_info_base + 1] = tile_buf_pa & 0xFFFFFFFFFFFFFF00ull;

But in the updated code, if you have 36 bit, you store these 2 bits in the lower
part, which was originally cleared. Can you confirm this is exactly what you
wanted ? And if so add a comment ? It could also be written has (but this is
just me considering this more readable, I also prefer | (or) rather then +, and
hates casting):

		tile_info_buf[tile_info_base + 1] = (tile_buf_pa & 0xFFFFFFFFFFFFFF00ull) |
			(tile_buf_pa & 0x0000000F00000000ull) >> 32;

>  		tile_info_buf[tile_info_base + 2] = (tile_buf_pa % 16) << 3;

Is this the same as ?

		tile_info_buf[tile_info_base + 2] = (tile_buf_pa & 0x00FFull) << 3;

> 
>  
>  		sb_boundary_x_m1 =
Re: media: mediatek: vcodec: fix AV1 decode fail for 36bit iova
Posted by kernel test robot 1 year, 4 months ago
Hi Xiaoyong,

kernel test robot noticed the following build warnings:

[auto build test WARNING on next-20230627]
[cannot apply to media-tree/master v6.4 v6.4-rc7 v6.4-rc6 linus/master v6.4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Xiaoyong-Lu/media-mediatek-vcodec-fix-AV1-decode-fail-for-36bit-iova/20230628-134327
base:   next-20230627
patch link:    https://lore.kernel.org/r/20230628054111.8967-1-xiaoyong.lu%40mediatek.com
patch subject: media: mediatek: vcodec: fix AV1 decode fail for 36bit iova
config: arm-allmodconfig (https://download.01.org/0day-ci/archive/20230629/202306291250.o5AmGFiC-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230629/202306291250.o5AmGFiC-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202306291250.o5AmGFiC-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c: In function 'vdec_av1_slice_setup_tile_buffer':
>> drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c:1676:91: warning: suggest parentheses around '+' inside '<<' [-Wparentheses]
    1676 |                 tile_info_buf[tile_info_base + 1] = (unsigned int)(tile_buf_pa >> 4) << 4 +
         |                                                                                         ~~^
    1677 |                         ((unsigned int)(tile_buf_pa >> 32) & 0xf);
         |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                          

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for SM_GCC_8350
   Depends on [n]: COMMON_CLK [=y] && COMMON_CLK_QCOM [=m] && (ARM64 || COMPILE_TEST [=n])
   Selected by [m]:
   - SM_VIDEOCC_8350 [=m] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=m]
   WARNING: unmet direct dependencies detected for SM_GCC_8450
   Depends on [n]: COMMON_CLK [=y] && COMMON_CLK_QCOM [=m] && (ARM64 || COMPILE_TEST [=n])
   Selected by [m]:
   - SM_GPUCC_8450 [=m] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=m]
   - SM_VIDEOCC_8450 [=m] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=m]
   WARNING: unmet direct dependencies detected for SM_GCC_8550
   Depends on [n]: COMMON_CLK [=y] && COMMON_CLK_QCOM [=m] && (ARM64 || COMPILE_TEST [=n])
   Selected by [m]:
   - SM_GPUCC_8550 [=m] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=m]
   - SM_VIDEOCC_8550 [=m] && COMMON_CLK [=y] && COMMON_CLK_QCOM [=m]


vim +1676 drivers/media/platform/mediatek/vcodec/vdec/vdec_av1_req_lat_if.c

  1649	
  1650	static void vdec_av1_slice_setup_tile_buffer(struct vdec_av1_slice_instance *instance,
  1651						     struct vdec_av1_slice_vsi *vsi,
  1652						     struct mtk_vcodec_mem *bs)
  1653	{
  1654		struct vdec_av1_slice_tile_group *tile_group = &instance->tile_group;
  1655		struct vdec_av1_slice_uncompressed_header *uh = &vsi->frame.uh;
  1656		struct vdec_av1_slice_tile *tile = &uh->tile;
  1657		u32 tile_num, tile_row, tile_col;
  1658		u32 allow_update_cdf = 0;
  1659		u32 sb_boundary_x_m1 = 0, sb_boundary_y_m1 = 0;
  1660		int tile_info_base;
  1661		u64 tile_buf_pa;
  1662		u32 *tile_info_buf = instance->tile.va;
  1663		u64 pa = (u64)bs->dma_addr;
  1664	
  1665		if (uh->disable_cdf_update == 0)
  1666			allow_update_cdf = 1;
  1667	
  1668		for (tile_num = 0; tile_num < tile_group->num_tiles; tile_num++) {
  1669			/* each uint32 takes place of 4 bytes */
  1670			tile_info_base = (AV1_TILE_BUF_SIZE * tile_num) >> 2;
  1671			tile_row = tile_num / tile->tile_cols;
  1672			tile_col = tile_num % tile->tile_cols;
  1673			tile_info_buf[tile_info_base + 0] = (tile_group->tile_size[tile_num] << 3);
  1674			tile_buf_pa = pa + tile_group->tile_start_offset[tile_num];
  1675	
> 1676			tile_info_buf[tile_info_base + 1] = (unsigned int)(tile_buf_pa >> 4) << 4 +
  1677				((unsigned int)(tile_buf_pa >> 32) & 0xf);
  1678			tile_info_buf[tile_info_base + 2] = (tile_buf_pa % 16) << 3;
  1679	
  1680			sb_boundary_x_m1 =
  1681				(tile->mi_col_starts[tile_col + 1] - tile->mi_col_starts[tile_col] - 1) &
  1682				0x3f;
  1683			sb_boundary_y_m1 =
  1684				(tile->mi_row_starts[tile_row + 1] - tile->mi_row_starts[tile_row] - 1) &
  1685				0x1ff;
  1686	
  1687			tile_info_buf[tile_info_base + 3] = (sb_boundary_y_m1 << 7) | sb_boundary_x_m1;
  1688			tile_info_buf[tile_info_base + 4] = ((allow_update_cdf << 18) | (1 << 16));
  1689	
  1690			if (tile_num == tile->context_update_tile_id &&
  1691			    uh->disable_frame_end_update_cdf == 0)
  1692				tile_info_buf[tile_info_base + 4] |= (1 << 17);
  1693	
  1694			mtk_vcodec_debug(instance, "// tile buf %d pos(%dx%d) offset 0x%x\n",
  1695					 tile_num, tile_row, tile_col, tile_info_base);
  1696			mtk_vcodec_debug(instance, "// %08x %08x %08x %08x\n",
  1697					 tile_info_buf[tile_info_base + 0],
  1698					 tile_info_buf[tile_info_base + 1],
  1699					 tile_info_buf[tile_info_base + 2],
  1700					 tile_info_buf[tile_info_base + 3]);
  1701			mtk_vcodec_debug(instance, "// %08x %08x %08x %08x\n",
  1702					 tile_info_buf[tile_info_base + 4],
  1703					 tile_info_buf[tile_info_base + 5],
  1704					 tile_info_buf[tile_info_base + 6],
  1705					 tile_info_buf[tile_info_base + 7]);
  1706		}
  1707	}
  1708	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki