diff mbox series

[v3,13/21] drm/i915/xe2hpd: Add max memory bandwidth algorithm

Message ID 20240415081423.495834-14-balasubramani.vivekanandan@intel.com (mailing list archive)
State New, archived
Headers show
Series Enable display support for Battlemage | expand

Commit Message

Vivekanandan, Balasubramani April 15, 2024, 8:14 a.m. UTC
From: Matt Roper <matthew.d.roper@intel.com>

Unlike DG2, Xe2_HPD does support multiple GV points with different
maximum memory bandwidths, but uses a much simpler algorithm than igpu
platforms use.

Bspec: 64631
CC: Jani Nikula <jani.nikula@linux.intel.com>
Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
Signed-off-by: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
---
 drivers/gpu/drm/i915/display/intel_bw.c | 65 ++++++++++++++++++++++++-
 drivers/gpu/drm/i915/i915_drv.h         |  1 +
 drivers/gpu/drm/i915/soc/intel_dram.c   |  4 ++
 drivers/gpu/drm/xe/xe_device_types.h    |  1 +
 4 files changed, 69 insertions(+), 2 deletions(-)

Comments

Sripada, Radhakrishna April 15, 2024, 7:52 p.m. UTC | #1
LGTM,
Reviewed-by: Radhakrishna Sripada <radhakrishna.sripada@intel.com>

> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of
> Balasubramani Vivekanandan
> Sent: Monday, April 15, 2024 1:14 AM
> To: intel-xe@lists.freedesktop.org; intel-gfx@lists.freedesktop.org
> Cc: De Marchi, Lucas <lucas.demarchi@intel.com>; Roper, Matthew D
> <matthew.d.roper@intel.com>; Jani Nikula <jani.nikula@linux.intel.com>;
> Vivekanandan, Balasubramani <balasubramani.vivekanandan@intel.com>
> Subject: [PATCH v3 13/21] drm/i915/xe2hpd: Add max memory bandwidth
> algorithm
> 
> From: Matt Roper <matthew.d.roper@intel.com>
> 
> Unlike DG2, Xe2_HPD does support multiple GV points with different
> maximum memory bandwidths, but uses a much simpler algorithm than igpu
> platforms use.
> 
> Bspec: 64631
> CC: Jani Nikula <jani.nikula@linux.intel.com>
> Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
> Signed-off-by: Balasubramani Vivekanandan
> <balasubramani.vivekanandan@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_bw.c | 65 ++++++++++++++++++++++++-
>  drivers/gpu/drm/i915/i915_drv.h         |  1 +
>  drivers/gpu/drm/i915/soc/intel_dram.c   |  4 ++
>  drivers/gpu/drm/xe/xe_device_types.h    |  1 +
>  4 files changed, 69 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_bw.c
> b/drivers/gpu/drm/i915/display/intel_bw.c
> index 7f2a50b4f494..dc9ac4831065 100644
> --- a/drivers/gpu/drm/i915/display/intel_bw.c
> +++ b/drivers/gpu/drm/i915/display/intel_bw.c
> @@ -22,6 +22,8 @@ struct intel_qgv_point {
>  	u16 dclk, t_rp, t_rdpre, t_rc, t_ras, t_rcd;
>  };
> 
> +#define DEPROGBWPCLIMIT		60
> +
>  struct intel_psf_gv_point {
>  	u8 clk; /* clock in multiples of 16.6666 MHz */
>  };
> @@ -239,6 +241,9 @@ static int icl_get_qgv_points(struct drm_i915_private
> *dev_priv,
>  			qi->channel_width = 16;
>  			qi->deinterleave = 4;
>  			break;
> +		case INTEL_DRAM_GDDR:
> +			qi->channel_width = 32;
> +			break;
>  		default:
>  			MISSING_CASE(dram_info->type);
>  			return -EINVAL;
> @@ -383,6 +388,12 @@ static const struct intel_sa_info mtl_sa_info = {
>  	.derating = 10,
>  };
> 
> +static const struct intel_sa_info xe2_hpd_sa_info = {
> +	.derating = 30,
> +	.deprogbwlimit = 53,
> +	/* Other values not used by simplified algorithm */
> +};
> +
>  static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct
> intel_sa_info *sa)
>  {
>  	struct intel_qgv_info qi = {};
> @@ -489,7 +500,7 @@ static int tgl_get_bw_info(struct drm_i915_private
> *dev_priv, const struct intel
>  	dclk_max = icl_sagv_max_dclk(&qi);
> 
>  	peakbw = num_channels * DIV_ROUND_UP(qi.channel_width, 8) *
> dclk_max;
> -	maxdebw = min(sa->deprogbwlimit * 1000, peakbw * 6 / 10); /* 60% */
> +	maxdebw = min(sa->deprogbwlimit * 1000, peakbw *
> DEPROGBWPCLIMIT / 100);
> 
>  	ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels);
>  	/*
> @@ -594,6 +605,54 @@ static void dg2_get_bw_info(struct drm_i915_private
> *i915)
>  	i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED;
>  }
> 
> +static int xe2_hpd_get_bw_info(struct drm_i915_private *i915,
> +			       const struct intel_sa_info *sa)
> +{
> +	struct intel_qgv_info qi = {};
> +	int num_channels = i915->dram_info.num_channels;
> +	int peakbw, maxdebw;
> +	int ret, i;
> +
> +	ret = icl_get_qgv_points(i915, &qi, true);
> +	if (ret) {
> +		drm_dbg_kms(&i915->drm,
> +			    "Failed to get memory subsystem information, ignoring
> bandwidth limits");
> +		return ret;
> +	}
> +
> +	peakbw = num_channels * qi.channel_width / 8 *
> icl_sagv_max_dclk(&qi);
> +	maxdebw = min(sa->deprogbwlimit * 1000, peakbw *
> DEPROGBWPCLIMIT / 10);
> +
> +	for (i = 0; i < qi.num_points; i++) {
> +		const struct intel_qgv_point *point = &qi.points[i];
> +		int bw = num_channels * (qi.channel_width / 8) * point->dclk;
> +
> +		i915->display.bw.max[0].deratedbw[i] =
> +			min(maxdebw, (100 - sa->derating) * bw / 100);
> +		i915->display.bw.max[0].peakbw[i] = bw;
> +
> +		drm_dbg_kms(&i915->drm, "QGV %d: deratedbw=%u peakbw:
> %u\n",
> +			    i, i915->display.bw.max[0].deratedbw[i],
> +			    i915->display.bw.max[0].peakbw[i]);
> +	}
> +
> +	/* Bandwidth does not depend on # of planes; set all groups the same */
> +	i915->display.bw.max[0].num_planes = 1;
> +	i915->display.bw.max[0].num_qgv_points = qi.num_points;
> +	for (i = 1; i < ARRAY_SIZE(i915->display.bw.max); i++)
> +		memcpy(&i915->display.bw.max[i], &i915->display.bw.max[0],
> +		       sizeof(i915->display.bw.max[0]));
> +
> +	/*
> +	 * Xe2_HPD should always have exactly two QGV points representing
> +	 * battery and plugged-in operation.
> +	 */
> +	drm_WARN_ON(&i915->drm, qi.num_points != 2);
> +	i915->display.sagv.status = I915_SAGV_ENABLED;
> +
> +	return 0;
> +}
> +
>  static unsigned int icl_max_bw_index(struct drm_i915_private *dev_priv,
>  				     int num_planes, int qgv_point)
>  {
> @@ -664,7 +723,9 @@ void intel_bw_init_hw(struct drm_i915_private
> *dev_priv)
>  	if (!HAS_DISPLAY(dev_priv))
>  		return;
> 
> -	if (DISPLAY_VER(dev_priv) >= 14)
> +	if (DISPLAY_VER_FULL(dev_priv) >= IP_VER(14, 1) && IS_DGFX(dev_priv))
> +		xe2_hpd_get_bw_info(dev_priv, &xe2_hpd_sa_info);
> +	else if (DISPLAY_VER(dev_priv) >= 14)
>  		tgl_get_bw_info(dev_priv, &mtl_sa_info);
>  	else if (IS_DG2(dev_priv))
>  		dg2_get_bw_info(dev_priv);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 481ddce038b2..d1d21d433766 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -305,6 +305,7 @@ struct drm_i915_private {
>  			INTEL_DRAM_LPDDR4,
>  			INTEL_DRAM_DDR5,
>  			INTEL_DRAM_LPDDR5,
> +			INTEL_DRAM_GDDR,
>  		} type;
>  		u8 num_qgv_points;
>  		u8 num_psf_gv_points;
> diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c
> b/drivers/gpu/drm/i915/soc/intel_dram.c
> index 15492b69f698..99b541babb31 100644
> --- a/drivers/gpu/drm/i915/soc/intel_dram.c
> +++ b/drivers/gpu/drm/i915/soc/intel_dram.c
> @@ -640,6 +640,10 @@ static int xelpdp_get_dram_info(struct
> drm_i915_private *i915)
>  	case 5:
>  		dram_info->type = INTEL_DRAM_LPDDR3;
>  		break;
> +	case 8:
> +		drm_WARN_ON(&i915->drm, !IS_DGFX(i915));
> +		dram_info->type = INTEL_DRAM_GDDR;
> +		break;
>  	default:
>  		MISSING_CASE(val);
>  		return -EINVAL;
> diff --git a/drivers/gpu/drm/xe/xe_device_types.h
> b/drivers/gpu/drm/xe/xe_device_types.h
> index 60ced5f90c2b..d1aef541d1c7 100644
> --- a/drivers/gpu/drm/xe/xe_device_types.h
> +++ b/drivers/gpu/drm/xe/xe_device_types.h
> @@ -487,6 +487,7 @@ struct xe_device {
>  			INTEL_DRAM_LPDDR4,
>  			INTEL_DRAM_DDR5,
>  			INTEL_DRAM_LPDDR5,
> +			INTEL_DRAM_GDDR,
>  		} type;
>  		u8 num_qgv_points;
>  		u8 num_psf_gv_points;
> --
> 2.25.1
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 7f2a50b4f494..dc9ac4831065 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -22,6 +22,8 @@  struct intel_qgv_point {
 	u16 dclk, t_rp, t_rdpre, t_rc, t_ras, t_rcd;
 };
 
+#define DEPROGBWPCLIMIT		60
+
 struct intel_psf_gv_point {
 	u8 clk; /* clock in multiples of 16.6666 MHz */
 };
@@ -239,6 +241,9 @@  static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
 			qi->channel_width = 16;
 			qi->deinterleave = 4;
 			break;
+		case INTEL_DRAM_GDDR:
+			qi->channel_width = 32;
+			break;
 		default:
 			MISSING_CASE(dram_info->type);
 			return -EINVAL;
@@ -383,6 +388,12 @@  static const struct intel_sa_info mtl_sa_info = {
 	.derating = 10,
 };
 
+static const struct intel_sa_info xe2_hpd_sa_info = {
+	.derating = 30,
+	.deprogbwlimit = 53,
+	/* Other values not used by simplified algorithm */
+};
+
 static int icl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel_sa_info *sa)
 {
 	struct intel_qgv_info qi = {};
@@ -489,7 +500,7 @@  static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
 	dclk_max = icl_sagv_max_dclk(&qi);
 
 	peakbw = num_channels * DIV_ROUND_UP(qi.channel_width, 8) * dclk_max;
-	maxdebw = min(sa->deprogbwlimit * 1000, peakbw * 6 / 10); /* 60% */
+	maxdebw = min(sa->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 100);
 
 	ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels);
 	/*
@@ -594,6 +605,54 @@  static void dg2_get_bw_info(struct drm_i915_private *i915)
 	i915->display.sagv.status = I915_SAGV_NOT_CONTROLLED;
 }
 
+static int xe2_hpd_get_bw_info(struct drm_i915_private *i915,
+			       const struct intel_sa_info *sa)
+{
+	struct intel_qgv_info qi = {};
+	int num_channels = i915->dram_info.num_channels;
+	int peakbw, maxdebw;
+	int ret, i;
+
+	ret = icl_get_qgv_points(i915, &qi, true);
+	if (ret) {
+		drm_dbg_kms(&i915->drm,
+			    "Failed to get memory subsystem information, ignoring bandwidth limits");
+		return ret;
+	}
+
+	peakbw = num_channels * qi.channel_width / 8 * icl_sagv_max_dclk(&qi);
+	maxdebw = min(sa->deprogbwlimit * 1000, peakbw * DEPROGBWPCLIMIT / 10);
+
+	for (i = 0; i < qi.num_points; i++) {
+		const struct intel_qgv_point *point = &qi.points[i];
+		int bw = num_channels * (qi.channel_width / 8) * point->dclk;
+
+		i915->display.bw.max[0].deratedbw[i] =
+			min(maxdebw, (100 - sa->derating) * bw / 100);
+		i915->display.bw.max[0].peakbw[i] = bw;
+
+		drm_dbg_kms(&i915->drm, "QGV %d: deratedbw=%u peakbw: %u\n",
+			    i, i915->display.bw.max[0].deratedbw[i],
+			    i915->display.bw.max[0].peakbw[i]);
+	}
+
+	/* Bandwidth does not depend on # of planes; set all groups the same */
+	i915->display.bw.max[0].num_planes = 1;
+	i915->display.bw.max[0].num_qgv_points = qi.num_points;
+	for (i = 1; i < ARRAY_SIZE(i915->display.bw.max); i++)
+		memcpy(&i915->display.bw.max[i], &i915->display.bw.max[0],
+		       sizeof(i915->display.bw.max[0]));
+
+	/*
+	 * Xe2_HPD should always have exactly two QGV points representing
+	 * battery and plugged-in operation.
+	 */
+	drm_WARN_ON(&i915->drm, qi.num_points != 2);
+	i915->display.sagv.status = I915_SAGV_ENABLED;
+
+	return 0;
+}
+
 static unsigned int icl_max_bw_index(struct drm_i915_private *dev_priv,
 				     int num_planes, int qgv_point)
 {
@@ -664,7 +723,9 @@  void intel_bw_init_hw(struct drm_i915_private *dev_priv)
 	if (!HAS_DISPLAY(dev_priv))
 		return;
 
-	if (DISPLAY_VER(dev_priv) >= 14)
+	if (DISPLAY_VER_FULL(dev_priv) >= IP_VER(14, 1) && IS_DGFX(dev_priv))
+		xe2_hpd_get_bw_info(dev_priv, &xe2_hpd_sa_info);
+	else if (DISPLAY_VER(dev_priv) >= 14)
 		tgl_get_bw_info(dev_priv, &mtl_sa_info);
 	else if (IS_DG2(dev_priv))
 		dg2_get_bw_info(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 481ddce038b2..d1d21d433766 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -305,6 +305,7 @@  struct drm_i915_private {
 			INTEL_DRAM_LPDDR4,
 			INTEL_DRAM_DDR5,
 			INTEL_DRAM_LPDDR5,
+			INTEL_DRAM_GDDR,
 		} type;
 		u8 num_qgv_points;
 		u8 num_psf_gv_points;
diff --git a/drivers/gpu/drm/i915/soc/intel_dram.c b/drivers/gpu/drm/i915/soc/intel_dram.c
index 15492b69f698..99b541babb31 100644
--- a/drivers/gpu/drm/i915/soc/intel_dram.c
+++ b/drivers/gpu/drm/i915/soc/intel_dram.c
@@ -640,6 +640,10 @@  static int xelpdp_get_dram_info(struct drm_i915_private *i915)
 	case 5:
 		dram_info->type = INTEL_DRAM_LPDDR3;
 		break;
+	case 8:
+		drm_WARN_ON(&i915->drm, !IS_DGFX(i915));
+		dram_info->type = INTEL_DRAM_GDDR;
+		break;
 	default:
 		MISSING_CASE(val);
 		return -EINVAL;
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 60ced5f90c2b..d1aef541d1c7 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -487,6 +487,7 @@  struct xe_device {
 			INTEL_DRAM_LPDDR4,
 			INTEL_DRAM_DDR5,
 			INTEL_DRAM_LPDDR5,
+			INTEL_DRAM_GDDR,
 		} type;
 		u8 num_qgv_points;
 		u8 num_psf_gv_points;