diff mbox series

drm/mediatek: dp: Support flexible length of DP calibration data

Message ID 20241204053634.1365491-1-fshao@chromium.org (mailing list archive)
State New
Headers show
Series drm/mediatek: dp: Support flexible length of DP calibration data | expand

Commit Message

Fei Shao Dec. 4, 2024, 5:32 a.m. UTC
The DP calibration data is stored in nvmem cells, and the data layout is
described in the `mtk_dp_efuse_fmt` arrays for each platform.

There is no guarantee that the data is always a 4-length u32 buffer.
For example, MT8188 has a data length of 3, preventing it from passing
the preliminary check and undergoing calibration.

Update the logic to support flexible data lengths. Specifically, we
validate the length returned from `nvmem_cell_read()` against the
platform-specific efuse format. If out-of-bound access is detected, fall
back to the default calibration values. This likely indicates an error
in either the efuse data length described in DT or the efuse format
within the driver.

Signed-off-by: Fei Shao <fshao@chromium.org>
---

 drivers/gpu/drm/mediatek/mtk_dp.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

Comments

kernel test robot Dec. 4, 2024, 1:10 p.m. UTC | #1
Hi Fei,

kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.13-rc1 next-20241203]
[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/Fei-Shao/drm-mediatek-dp-Support-flexible-length-of-DP-calibration-data/20241204-133854
base:   linus/master
patch link:    https://lore.kernel.org/r/20241204053634.1365491-1-fshao%40chromium.org
patch subject: [PATCH] drm/mediatek: dp: Support flexible length of DP calibration data
config: mips-allyesconfig (https://download.01.org/0day-ci/archive/20241204/202412042020.FZmfgvza-lkp@intel.com/config)
compiler: mips-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241204/202412042020.FZmfgvza-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/202412042020.FZmfgvza-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from include/linux/device.h:15,
                    from include/drm/display/drm_dp_aux_bus.h:13,
                    from drivers/gpu/drm/mediatek/mtk_dp.c:7:
   drivers/gpu/drm/mediatek/mtk_dp.c: In function 'mtk_dp_get_calibration_data':
>> drivers/gpu/drm/mediatek/mtk_dp.c:1181:34: warning: format '%lu' expects argument of type 'long unsigned int', but argument 4 has type 'size_t' {aka 'unsigned int'} [-Wformat=]
    1181 |                                  "Out-of-bound efuse data access, fmt idx = %d, buf len = %lu\n",
         |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/dev_printk.h:110:30: note: in definition of macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ^~~
   include/linux/dev_printk.h:156:61: note: in expansion of macro 'dev_fmt'
     156 |         dev_printk_index_wrap(_dev_warn, KERN_WARNING, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                             ^~~~~~~
   drivers/gpu/drm/mediatek/mtk_dp.c:1180:25: note: in expansion of macro 'dev_warn'
    1180 |                         dev_warn(mtk_dp->dev,
         |                         ^~~~~~~~
   drivers/gpu/drm/mediatek/mtk_dp.c:1181:93: note: format string is defined here
    1181 |                                  "Out-of-bound efuse data access, fmt idx = %d, buf len = %lu\n",
         |                                                                                           ~~^
         |                                                                                             |
         |                                                                                             long unsigned int
         |                                                                                           %u


vim +1181 drivers/gpu/drm/mediatek/mtk_dp.c

  1148	
  1149	static void mtk_dp_get_calibration_data(struct mtk_dp *mtk_dp)
  1150	{
  1151		const struct mtk_dp_efuse_fmt *fmt;
  1152		struct device *dev = mtk_dp->dev;
  1153		struct nvmem_cell *cell;
  1154		u32 *cal_data = mtk_dp->cal_data;
  1155		u32 *buf;
  1156		int i;
  1157		size_t len;
  1158	
  1159		cell = nvmem_cell_get(dev, "dp_calibration_data");
  1160		if (IS_ERR(cell)) {
  1161			dev_warn(dev, "Failed to get nvmem cell dp_calibration_data\n");
  1162			goto use_default_val;
  1163		}
  1164	
  1165		buf = (u32 *)nvmem_cell_read(cell, &len);
  1166		nvmem_cell_put(cell);
  1167	
  1168		if (IS_ERR(buf)) {
  1169			dev_warn(dev, "Failed to read nvmem_cell_read\n");
  1170			goto use_default_val;
  1171		}
  1172	
  1173		/* The cell length is in bytes. Convert it to be compatible with u32 buffer. */
  1174		len /= sizeof(u32);
  1175	
  1176		for (i = 0; i < MTK_DP_CAL_MAX; i++) {
  1177			fmt = &mtk_dp->data->efuse_fmt[i];
  1178	
  1179			if (fmt->idx >= len) {
  1180				dev_warn(mtk_dp->dev,
> 1181					 "Out-of-bound efuse data access, fmt idx = %d, buf len = %lu\n",
  1182					 fmt->idx, len);
  1183				kfree(buf);
  1184				goto use_default_val;
  1185			}
  1186	
  1187			cal_data[i] = (buf[fmt->idx] >> fmt->shift) & fmt->mask;
  1188	
  1189			if (cal_data[i] < fmt->min_val || cal_data[i] > fmt->max_val) {
  1190				dev_warn(mtk_dp->dev, "Invalid efuse data, idx = %d\n", i);
  1191				kfree(buf);
  1192				goto use_default_val;
  1193			}
  1194		}
  1195		kfree(buf);
  1196	
  1197		return;
  1198	
  1199	use_default_val:
  1200		dev_warn(mtk_dp->dev, "Use default calibration data\n");
  1201		for (i = 0; i < MTK_DP_CAL_MAX; i++)
  1202			cal_data[i] = mtk_dp->data->efuse_fmt[i].default_val;
  1203	}
  1204
diff mbox series

Patch

diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
index 1cc916b16471..e9ff6fdfd6ee 100644
--- a/drivers/gpu/drm/mediatek/mtk_dp.c
+++ b/drivers/gpu/drm/mediatek/mtk_dp.c
@@ -1165,17 +1165,25 @@  static void mtk_dp_get_calibration_data(struct mtk_dp *mtk_dp)
 	buf = (u32 *)nvmem_cell_read(cell, &len);
 	nvmem_cell_put(cell);
 
-	if (IS_ERR(buf) || ((len / sizeof(u32)) != 4)) {
+	if (IS_ERR(buf)) {
 		dev_warn(dev, "Failed to read nvmem_cell_read\n");
-
-		if (!IS_ERR(buf))
-			kfree(buf);
-
 		goto use_default_val;
 	}
 
+	/* The cell length is in bytes. Convert it to be compatible with u32 buffer. */
+	len /= sizeof(u32);
+
 	for (i = 0; i < MTK_DP_CAL_MAX; i++) {
 		fmt = &mtk_dp->data->efuse_fmt[i];
+
+		if (fmt->idx >= len) {
+			dev_warn(mtk_dp->dev,
+				 "Out-of-bound efuse data access, fmt idx = %d, buf len = %lu\n",
+				 fmt->idx, len);
+			kfree(buf);
+			goto use_default_val;
+		}
+
 		cal_data[i] = (buf[fmt->idx] >> fmt->shift) & fmt->mask;
 
 		if (cal_data[i] < fmt->min_val || cal_data[i] > fmt->max_val) {