[Intel-xe] [PATCH v2 4/7] drm/xe/xe2: Program PAT tables

Balasubramani Vivekanandan balasubramani.vivekanandan at intel.com
Fri Oct 6 07:35:24 UTC 2023


On 03.10.2023 05:52, Lucas De Marchi wrote:
> From: Matt Roper <matthew.d.roper at intel.com>
> 
> The PAT tables become significantly more complicated on Xe2 platforms.
> They now control L3, L4, and coherency settings, as well as additional
> characteristics such as compression.
> 
> Aside from the main PAT table, there's an additional register that
> also needs to be programmed with PAT settings for PCI Address
> Translation Services.
> 
> Bspec: 71582
> Cc: Balasubramani Vivekanandan <balasubramani.vivekanandan at intel.com>
> Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
> Signed-off-by: Lucas De Marchi <lucas.demarchi at intel.com>

Reviewed-by: Balasubramani Vivekanandan <balasubramani.vivekanandan at intel.com>

Regards,
Bala

> ---
>  drivers/gpu/drm/xe/xe_pat.c | 92 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 91 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c
> index 4668ca3932c5..296763594370 100644
> --- a/drivers/gpu/drm/xe/xe_pat.c
> +++ b/drivers/gpu/drm/xe/xe_pat.c
> @@ -10,10 +10,18 @@
>  #include "xe_gt_mcr.h"
>  #include "xe_mmio.h"
>  
> +#define _PAT_ATS				0x47fc
>  #define _PAT_INDEX(index)			_PICK_EVEN_2RANGES(index, 8, \
>  								   0x4800, 0x4804, \
>  								   0x4848, 0x484c)
>  
> +#define XE2_NO_PROMOTE				REG_BIT(10)
> +#define XE2_COMP_EN				REG_BIT(9)
> +#define XE2_L3_CLOS				REG_GENMASK(7, 6)
> +#define XE2_L3_POLICY				REG_GENMASK(5, 4)
> +#define XE2_L4_POLICY				REG_GENMASK(3, 2)
> +#define XE2_COH_MODE				REG_GENMASK(1, 0)
> +
>  #define XELPG_L4_POLICY_MASK			REG_GENMASK(3, 2)
>  #define XELPG_PAT_3_UC				REG_FIELD_PREP(XELPG_L4_POLICY_MASK, 3)
>  #define XELPG_PAT_1_WT				REG_FIELD_PREP(XELPG_L4_POLICY_MASK, 1)
> @@ -67,6 +75,64 @@ static const u32 xelpg_pat_table[] = {
>  	[4] = XELPG_PAT_0_WB | XELPG_3_COH_2W,
>  };
>  
> +/*
> + * The Xe2 table is getting large/complicated so it's easier to review if
> + * provided in a form that exactly matches the bspec's formatting.  The meaning
> + * of the fields here are:
> + *   - no_promote:  0=promotable, 1=no promote
> + *   - comp_en:     0=disable, 1=enable
> + *   - l3clos:      L3 class of service (0-3)
> + *   - l3_policy:   0=WB, 1=XD ("WB - Transient Display"), 3=UC
> + *   - l4_policy:   0=WB, 1=WT, 3=UC
> + *   - coh_mode:    0=no snoop, 2=1-way coherent, 3=2-way coherent
> + *
> + * Reserved entries should be programmed with the maximum caching, minimum
> + * coherency (which matches an all-0's encoding), so we can just omit them
> + * in the table.
> + */
> +#define XE2_PAT(no_promote, comp_en, l3clos, l3_policy, l4_policy, coh_mode) \
> +	(no_promote ? XE2_NO_PROMOTE : 0) | \
> +	(comp_en ? XE2_COMP_EN : 0) | \
> +	REG_FIELD_PREP(XE2_L3_CLOS, l3clos) | \
> +	REG_FIELD_PREP(XE2_L3_POLICY, l3_policy) | \
> +	REG_FIELD_PREP(XE2_L4_POLICY, l4_policy) | \
> +	REG_FIELD_PREP(XE2_COH_MODE, coh_mode)
> +
> +static const u32 xe2_pat_table[] = {
> +	[ 0] = XE2_PAT( 0, 0, 0, 0, 3, 0 ),
> +	[ 1] = XE2_PAT( 0, 0, 0, 0, 3, 2 ),
> +	[ 2] = XE2_PAT( 0, 0, 0, 0, 3, 3 ),
> +	[ 3] = XE2_PAT( 0, 0, 0, 3, 3, 0 ),
> +	[ 4] = XE2_PAT( 0, 0, 0, 3, 0, 2 ),
> +	[ 5] = XE2_PAT( 0, 0, 0, 3, 3, 2 ),
> +	[ 6] = XE2_PAT( 1, 0, 0, 1, 3, 0 ),
> +	[ 7] = XE2_PAT( 0, 0, 0, 3, 0, 3 ),
> +	[ 8] = XE2_PAT( 0, 0, 0, 3, 0, 0 ),
> +	[ 9] = XE2_PAT( 0, 1, 0, 0, 3, 0 ),
> +	[10] = XE2_PAT( 0, 1, 0, 3, 0, 0 ),
> +	[11] = XE2_PAT( 1, 1, 0, 1, 3, 0 ),
> +	[12] = XE2_PAT( 0, 1, 0, 3, 3, 0 ),
> +	[13] = XE2_PAT( 0, 0, 0, 0, 0, 0 ),
> +	[14] = XE2_PAT( 0, 1, 0, 0, 0, 0 ),
> +	[15] = XE2_PAT( 1, 1, 0, 1, 1, 0 ),
> +	/* 16..19 are reserved; leave set to all 0's */
> +	[20] = XE2_PAT( 0, 0, 1, 0, 3, 0 ),
> +	[21] = XE2_PAT( 0, 1, 1, 0, 3, 0 ),
> +	[22] = XE2_PAT( 0, 0, 1, 0, 3, 2 ),
> +	[23] = XE2_PAT( 0, 0, 1, 0, 3, 3 ),
> +	[24] = XE2_PAT( 0, 0, 2, 0, 3, 0 ),
> +	[25] = XE2_PAT( 0, 1, 2, 0, 3, 0 ),
> +	[26] = XE2_PAT( 0, 0, 2, 0, 3, 2 ),
> +	[27] = XE2_PAT( 0, 0, 2, 0, 3, 3 ),
> +	[28] = XE2_PAT( 0, 0, 3, 0, 3, 0 ),
> +	[29] = XE2_PAT( 0, 1, 3, 0, 3, 0 ),
> +	[30] = XE2_PAT( 0, 0, 3, 0, 3, 2 ),
> +	[31] = XE2_PAT( 0, 0, 3, 0, 3, 3 ),
> +};
> +
> +/* Special PAT values programmed outside the main table */
> +#define XE2_PAT_ATS	XE2_PAT( 0, 0, 0, 0, 3, 3 )
> +
>  static void program_pat(struct xe_gt *gt, const u32 table[], int n_entries)
>  {
>  	for (int i = 0; i < n_entries; i++) {
> @@ -102,9 +168,33 @@ static const struct xe_pat_ops xelpg_pat_ops = {
>  	.program_media = program_pat_mcr,
>  };
>  
> +static void xe2lpg_program_pat(struct xe_gt *gt, const u32 table[], int n_entries)
> +{
> +	program_pat_mcr(gt, table, n_entries);
> +	xe_gt_mcr_multicast_write(gt, XE_REG_MCR(_PAT_ATS), XE2_PAT_ATS);
> +}
> +
> +static void xe2lpm_program_pat(struct xe_gt *gt, const u32 table[], int n_entries)
> +{
> +	program_pat(gt, table, n_entries);
> +	xe_mmio_write32(gt, XE_REG(_PAT_ATS), XE2_PAT_ATS);
> +}
> +
> +static const struct xe_pat_ops xe2_pat_ops = {
> +	.program_graphics = xe2lpg_program_pat,
> +	.program_media = xe2lpm_program_pat,
> +};
> +
>  void xe_pat_init_early(struct xe_device *xe)
>  {
> -	if (xe->info.platform == XE_METEORLAKE) {
> +	if (GRAPHICS_VER(xe) == 20) {
> +		xe->pat.ops = &xe2_pat_ops;
> +		xe->pat.table = xe2_pat_table;
> +		xe->pat.n_entries = ARRAY_SIZE(xe2_pat_table);
> +		xe->pat.idx[XE_CACHE_NONE] = 3;
> +		xe->pat.idx[XE_CACHE_WT] = 15;
> +		xe->pat.idx[XE_CACHE_WB] = 2;
> +	} else if (xe->info.platform == XE_METEORLAKE) {
>  		xe->pat.ops = &xelpg_pat_ops;
>  		xe->pat.table = xelpg_pat_table;
>  		xe->pat.n_entries = ARRAY_SIZE(xelpg_pat_table);
> -- 
> 2.40.1
> 


More information about the Intel-xe mailing list