diff mbox series

[v8,6/7] drm/i915/mtl: find the best QGV point for the SAGV configuration

Message ID 20230526125055.39886-7-vinod.govindapillai@intel.com (mailing list archive)
State New, archived
Headers show
Series mtl: add support for pmdemand | expand

Commit Message

Vinod Govindapillai May 26, 2023, 12:50 p.m. UTC
From MTL onwards, we need to find the best QGV point based on
the required data rate and pass the peak BW of that point to
the punit to lock the corresponding QGV point.

Bspec: 64636

Signed-off-by: Vinod Govindapillai <vinod.govindapillai@intel.com>
Reviewed-by: Stanislav Lisovskiy <stanislav.lisovskiy@intel.com>
---
 drivers/gpu/drm/i915/display/intel_bw.c | 87 ++++++++++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_bw.h |  6 ++
 2 files changed, 91 insertions(+), 2 deletions(-)

Comments

Dan Carpenter May 29, 2023, 9:23 a.m. UTC | #1
Hi Vinod,

kernel test robot noticed the following build warnings:

url:    https://github.com/intel-lab-lkp/linux/commits/Vinod-Govindapillai/drm-i915-fix-the-derating-percentage-for-MTL/20230526-205305
base:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
patch link:    https://lore.kernel.org/r/20230526125055.39886-7-vinod.govindapillai%40intel.com
patch subject: [Intel-gfx] [PATCH v8 6/7] drm/i915/mtl: find the best QGV point for the SAGV configuration
config: i386-randconfig-m021-20230526 (https://download.01.org/0day-ci/archive/20230528/202305280253.Ab8bRV2w-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-12) 11.3.0

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>
| Closes: https://lore.kernel.org/r/202305280253.Ab8bRV2w-lkp@intel.com/

New smatch warnings:
drivers/gpu/drm/i915/display/intel_bw.c:845 mtl_find_qgv_points() error: buffer overflow 'i915->display.bw.max' 6 <= 6

Old smatch warnings:
drivers/gpu/drm/i915/display/intel_bw.c:852 mtl_find_qgv_points() error: buffer overflow 'i915->display.bw.max' 6 <= 6

vim +845 drivers/gpu/drm/i915/display/intel_bw.c

a10fe26325bd3a Vinod Govindapillai 2023-05-26  806  static int mtl_find_qgv_points(struct drm_i915_private *i915,
a10fe26325bd3a Vinod Govindapillai 2023-05-26  807  			       unsigned int data_rate,
a10fe26325bd3a Vinod Govindapillai 2023-05-26  808  			       unsigned int num_active_planes,
a10fe26325bd3a Vinod Govindapillai 2023-05-26  809  			       const struct intel_bw_state *old_bw_state,
a10fe26325bd3a Vinod Govindapillai 2023-05-26  810  			       struct intel_bw_state *new_bw_state)
a10fe26325bd3a Vinod Govindapillai 2023-05-26  811  {
a10fe26325bd3a Vinod Govindapillai 2023-05-26  812  	unsigned int best_rate = UINT_MAX;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  813  	unsigned int num_qgv_points = i915->display.bw.max[0].num_qgv_points;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  814  	unsigned int qgv_peak_bw  = 0;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  815  	int i;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  816  	int ret;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  817  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  818  	ret = intel_atomic_lock_global_state(&new_bw_state->base);
a10fe26325bd3a Vinod Govindapillai 2023-05-26  819  	if (ret)
a10fe26325bd3a Vinod Govindapillai 2023-05-26  820  		return ret;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  821  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  822  	/*
a10fe26325bd3a Vinod Govindapillai 2023-05-26  823  	 * If SAGV cannot be enabled, disable the pcode SAGV by passing all 1's
a10fe26325bd3a Vinod Govindapillai 2023-05-26  824  	 * for qgv peak bw in PM Demand request. So assign UINT_MAX if SAGV is
a10fe26325bd3a Vinod Govindapillai 2023-05-26  825  	 * not enabled. PM Demand code will clamp the value for the register
a10fe26325bd3a Vinod Govindapillai 2023-05-26  826  	 */
a10fe26325bd3a Vinod Govindapillai 2023-05-26  827  	if (!intel_can_enable_sagv(i915, new_bw_state)) {
a10fe26325bd3a Vinod Govindapillai 2023-05-26  828  		new_bw_state->qgv_point_peakbw = UINT_MAX;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  829  		drm_dbg_kms(&i915->drm, "No SAGV, use UINT_MAX as peak bw.");
a10fe26325bd3a Vinod Govindapillai 2023-05-26  830  		goto out;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  831  	}
a10fe26325bd3a Vinod Govindapillai 2023-05-26  832  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  833  	/*
a10fe26325bd3a Vinod Govindapillai 2023-05-26  834  	 * Find the best QGV point by comparing the data_rate with max data rate
a10fe26325bd3a Vinod Govindapillai 2023-05-26  835  	 * offered per plane group
a10fe26325bd3a Vinod Govindapillai 2023-05-26  836  	 */
a10fe26325bd3a Vinod Govindapillai 2023-05-26  837  	for (i = 0; i < num_qgv_points; i++) {
a10fe26325bd3a Vinod Govindapillai 2023-05-26  838  		unsigned int bw_index =
a10fe26325bd3a Vinod Govindapillai 2023-05-26  839  			tgl_max_bw_index(i915, num_active_planes, i);
a10fe26325bd3a Vinod Govindapillai 2023-05-26  840  		unsigned int max_data_rate;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  841  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  842  		if (bw_index > ARRAY_SIZE(i915->display.bw.max))

Should be >= ARRAY_SIZE()

a10fe26325bd3a Vinod Govindapillai 2023-05-26  843  			continue;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  844  
a10fe26325bd3a Vinod Govindapillai 2023-05-26 @845  		max_data_rate = i915->display.bw.max[bw_index].deratedbw[i];
a10fe26325bd3a Vinod Govindapillai 2023-05-26  846  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  847  		if (max_data_rate < data_rate)
a10fe26325bd3a Vinod Govindapillai 2023-05-26  848  			continue;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  849  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  850  		if (max_data_rate - data_rate < best_rate) {
a10fe26325bd3a Vinod Govindapillai 2023-05-26  851  			best_rate = max_data_rate - data_rate;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  852  			qgv_peak_bw = i915->display.bw.max[bw_index].peakbw[i];
a10fe26325bd3a Vinod Govindapillai 2023-05-26  853  		}
a10fe26325bd3a Vinod Govindapillai 2023-05-26  854  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  855  		drm_dbg_kms(&i915->drm, "QGV point %d: max bw %d required %d qgv_peak_bw: %d\n",
a10fe26325bd3a Vinod Govindapillai 2023-05-26  856  			    i, max_data_rate, data_rate, qgv_peak_bw);
a10fe26325bd3a Vinod Govindapillai 2023-05-26  857  	}
a10fe26325bd3a Vinod Govindapillai 2023-05-26  858  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  859  	drm_dbg_kms(&i915->drm, "Matching peaks QGV bw: %d for required data rate: %d\n",
a10fe26325bd3a Vinod Govindapillai 2023-05-26  860  		    qgv_peak_bw, data_rate);
a10fe26325bd3a Vinod Govindapillai 2023-05-26  861  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  862  	/*
a10fe26325bd3a Vinod Govindapillai 2023-05-26  863  	 * The display configuration cannot be supported if no QGV point
a10fe26325bd3a Vinod Govindapillai 2023-05-26  864  	 * satisfying the required data rate is found
a10fe26325bd3a Vinod Govindapillai 2023-05-26  865  	 */
a10fe26325bd3a Vinod Govindapillai 2023-05-26  866  	if (qgv_peak_bw == 0) {
a10fe26325bd3a Vinod Govindapillai 2023-05-26  867  		drm_dbg_kms(&i915->drm, "No QGV points for bw %d for display configuration(%d active planes).\n",
a10fe26325bd3a Vinod Govindapillai 2023-05-26  868  			    data_rate, num_active_planes);
a10fe26325bd3a Vinod Govindapillai 2023-05-26  869  		return -EINVAL;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  870  	}
a10fe26325bd3a Vinod Govindapillai 2023-05-26  871  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  872  	/* MTL PM DEMAND expects QGV BW parameter in multiples of 100 mbps */
a10fe26325bd3a Vinod Govindapillai 2023-05-26  873  	new_bw_state->qgv_point_peakbw = DIV_ROUND_CLOSEST(qgv_peak_bw, 100);
a10fe26325bd3a Vinod Govindapillai 2023-05-26  874  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  875  out:
a10fe26325bd3a Vinod Govindapillai 2023-05-26  876  	if (new_bw_state->qgv_point_peakbw != old_bw_state->qgv_point_peakbw)  {
a10fe26325bd3a Vinod Govindapillai 2023-05-26  877  		ret = intel_atomic_serialize_global_state(&new_bw_state->base);
a10fe26325bd3a Vinod Govindapillai 2023-05-26  878  		if (ret)
a10fe26325bd3a Vinod Govindapillai 2023-05-26  879  			return ret;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  880  	}
a10fe26325bd3a Vinod Govindapillai 2023-05-26  881  
a10fe26325bd3a Vinod Govindapillai 2023-05-26  882  	return 0;
a10fe26325bd3a Vinod Govindapillai 2023-05-26  883  }
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c
index c810c9f3f7d1..9a7489371c0c 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -803,6 +803,85 @@  intel_atomic_get_bw_state(struct intel_atomic_state *state)
 	return to_intel_bw_state(bw_state);
 }
 
+static int mtl_find_qgv_points(struct drm_i915_private *i915,
+			       unsigned int data_rate,
+			       unsigned int num_active_planes,
+			       const struct intel_bw_state *old_bw_state,
+			       struct intel_bw_state *new_bw_state)
+{
+	unsigned int best_rate = UINT_MAX;
+	unsigned int num_qgv_points = i915->display.bw.max[0].num_qgv_points;
+	unsigned int qgv_peak_bw  = 0;
+	int i;
+	int ret;
+
+	ret = intel_atomic_lock_global_state(&new_bw_state->base);
+	if (ret)
+		return ret;
+
+	/*
+	 * If SAGV cannot be enabled, disable the pcode SAGV by passing all 1's
+	 * for qgv peak bw in PM Demand request. So assign UINT_MAX if SAGV is
+	 * not enabled. PM Demand code will clamp the value for the register
+	 */
+	if (!intel_can_enable_sagv(i915, new_bw_state)) {
+		new_bw_state->qgv_point_peakbw = UINT_MAX;
+		drm_dbg_kms(&i915->drm, "No SAGV, use UINT_MAX as peak bw.");
+		goto out;
+	}
+
+	/*
+	 * Find the best QGV point by comparing the data_rate with max data rate
+	 * offered per plane group
+	 */
+	for (i = 0; i < num_qgv_points; i++) {
+		unsigned int bw_index =
+			tgl_max_bw_index(i915, num_active_planes, i);
+		unsigned int max_data_rate;
+
+		if (bw_index > ARRAY_SIZE(i915->display.bw.max))
+			continue;
+
+		max_data_rate = i915->display.bw.max[bw_index].deratedbw[i];
+
+		if (max_data_rate < data_rate)
+			continue;
+
+		if (max_data_rate - data_rate < best_rate) {
+			best_rate = max_data_rate - data_rate;
+			qgv_peak_bw = i915->display.bw.max[bw_index].peakbw[i];
+		}
+
+		drm_dbg_kms(&i915->drm, "QGV point %d: max bw %d required %d qgv_peak_bw: %d\n",
+			    i, max_data_rate, data_rate, qgv_peak_bw);
+	}
+
+	drm_dbg_kms(&i915->drm, "Matching peaks QGV bw: %d for required data rate: %d\n",
+		    qgv_peak_bw, data_rate);
+
+	/*
+	 * The display configuration cannot be supported if no QGV point
+	 * satisfying the required data rate is found
+	 */
+	if (qgv_peak_bw == 0) {
+		drm_dbg_kms(&i915->drm, "No QGV points for bw %d for display configuration(%d active planes).\n",
+			    data_rate, num_active_planes);
+		return -EINVAL;
+	}
+
+	/* MTL PM DEMAND expects QGV BW parameter in multiples of 100 mbps */
+	new_bw_state->qgv_point_peakbw = DIV_ROUND_CLOSEST(qgv_peak_bw, 100);
+
+out:
+	if (new_bw_state->qgv_point_peakbw != old_bw_state->qgv_point_peakbw)  {
+		ret = intel_atomic_serialize_global_state(&new_bw_state->base);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int icl_find_qgv_points(struct drm_i915_private *i915,
 			       unsigned int data_rate,
 			       unsigned int num_active_planes,
@@ -928,8 +1007,12 @@  static int intel_bw_check_qgv_points(struct drm_i915_private *i915,
 
 	data_rate = DIV_ROUND_UP(data_rate, 1000);
 
-	return icl_find_qgv_points(i915, data_rate, num_active_planes,
-				   old_bw_state, new_bw_state);
+	if (DISPLAY_VER(i915) >= 14)
+		return mtl_find_qgv_points(i915, data_rate, num_active_planes,
+					   old_bw_state, new_bw_state);
+	else
+		return icl_find_qgv_points(i915, data_rate, num_active_planes,
+					   old_bw_state, new_bw_state);
 }
 
 static bool intel_bw_state_changed(struct drm_i915_private *i915,
diff --git a/drivers/gpu/drm/i915/display/intel_bw.h b/drivers/gpu/drm/i915/display/intel_bw.h
index f20292143745..67ae66a3fcdd 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.h
+++ b/drivers/gpu/drm/i915/display/intel_bw.h
@@ -34,6 +34,12 @@  struct intel_bw_state {
 	/* bitmask of active pipes */
 	u8 active_pipes;
 
+	/*
+	 * From MTL onwards, to lock a QGV point, punit expects the peak BW of
+	 * the selected QGV point as the parameter in multiples of 100MB/s
+	 */
+	unsigned int qgv_point_peakbw;
+
 	/*
 	 * Current QGV points mask, which restricts
 	 * some particular SAGV states, not to confuse