Unverified Commit 3b1592fb authored by Vinay Belgaumkar's avatar Vinay Belgaumkar Committed by Rodrigo Vivi
Browse files

drm/xe/lnl: Apply Wa_22019338487



This WA requires us to limit media GT frequency requests to a certain
cap value during driver load. Freq limits are restored after load
completes, so perf will not be affected during normal operations.

During normal driver operation, this WA requires dummy writes to media
offset 0x380D8C after every ~63 GGTT writes. This will ensure completion
of the LMEM writes originating from Gunit.

During driver unload(before FLR), the WA requires that we set requested
frequency to the cap value again.

v3: Do not use WA number in function name. Call WA wrapper from xe_device.
Rename some variables, check for locks in the correct function (Rodrigo).
Ensure reset path is also covered for this WA.

v4: Fix BAT failure

v5: Add a function pointer for ggtt_ops (Michal W)

v6: Fix name collision and use static function (Rodrigo)

Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: default avatarVinay Belgaumkar <vinay.belgaumkar@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240620224928.3986377-2-vinay.belgaumkar@intel.com


Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
parent 8664e763
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -24,9 +24,12 @@ $(obj)/generated/%_wa_oob.c $(obj)/generated/%_wa_oob.h: $(obj)/xe_gen_wa_oob \
	$(call cmd,wa_oob)

uses_generated_oob := \
	$(obj)/xe_ggtt.o \
	$(obj)/xe_gsc.o \
	$(obj)/xe_gt.o \
	$(obj)/xe_guc.o \
	$(obj)/xe_guc_ads.o \
	$(obj)/xe_guc_pc.o \
	$(obj)/xe_migrate.o \
	$(obj)/xe_ring_ops.o \
	$(obj)/xe_vm.o \
+2 −2
Original line number Diff line number Diff line
@@ -171,7 +171,7 @@ write_ggtt_rotated(struct xe_bo *bo, struct xe_ggtt *ggtt, u32 *ggtt_ofs, u32 bo
			u64 pte = ggtt->pt_ops->pte_encode_bo(bo, src_idx * XE_PAGE_SIZE,
							      xe->pat.idx[XE_CACHE_NONE]);

			xe_ggtt_set_pte(ggtt, *ggtt_ofs, pte);
			ggtt->pt_ops->ggtt_set_pte(ggtt, *ggtt_ofs, pte);
			*ggtt_ofs += XE_PAGE_SIZE;
			src_idx -= src_stride;
		}
@@ -217,7 +217,7 @@ static int __xe_pin_fb_vma_ggtt(const struct intel_framebuffer *fb,
			u64 pte = ggtt->pt_ops->pte_encode_bo(bo, x,
							      xe->pat.idx[XE_CACHE_NONE]);

			xe_ggtt_set_pte(ggtt, vma->node.start + x, pte);
			ggtt->pt_ops->ggtt_set_pte(ggtt, vma->node.start + x, pte);
		}
	} else {
		u32 i, ggtt_ofs;
+3 −0
Original line number Diff line number Diff line
@@ -689,6 +689,9 @@ int xe_device_probe(struct xe_device *xe)

	xe_hwmon_register(xe);

	for_each_gt(gt, xe, id)
		xe_gt_sanitize_freq(gt);

	return devm_add_action_or_reset(xe->drm.dev, xe_device_sanitize, xe);

err_fini_display:
+37 −5
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <drm/drm_drv.h>
#include <drm/drm_managed.h>
#include <drm/intel/i915_drm.h>
#include <generated/xe_wa_oob.h>

#include "regs/xe_gt_regs.h"
#include "regs/xe_gtt_defs.h"
@@ -23,8 +24,10 @@
#include "xe_gt_sriov_vf.h"
#include "xe_gt_tlb_invalidation.h"
#include "xe_map.h"
#include "xe_mmio.h"
#include "xe_pm.h"
#include "xe_sriov.h"
#include "xe_wa.h"
#include "xe_wopcm.h"

static u64 xelp_ggtt_pte_encode_bo(struct xe_bo *bo, u64 bo_offset,
@@ -69,7 +72,22 @@ static unsigned int probe_gsm_size(struct pci_dev *pdev)
	return ggms ? SZ_1M << ggms : 0;
}

void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte)
static void ggtt_update_access_counter(struct xe_ggtt *ggtt)
{
	/*
	 * Wa_22019338487: GMD_ID is a RO register, a dummy write forces gunit
	 * to wait for completion of prior GTT writes before letting this through.
	 * This needs to be done for all GGTT writes originating from the CPU.
	 */
	lockdep_assert_held(&ggtt->lock);

	if ((++ggtt->access_count % 63) == 0) {
		xe_mmio_write32(ggtt->tile->media_gt, GMD_ID, 0x0);
		ggtt->access_count = 0;
	}
}

static void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte)
{
	xe_tile_assert(ggtt->tile, !(addr & XE_PTE_MASK));
	xe_tile_assert(ggtt->tile, addr < ggtt->size);
@@ -77,6 +95,12 @@ void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte)
	writeq(pte, &ggtt->gsm[addr >> XE_PTE_SHIFT]);
}

static void xe_ggtt_set_pte_and_flush(struct xe_ggtt *ggtt, u64 addr, u64 pte)
{
	xe_ggtt_set_pte(ggtt, addr, pte);
	ggtt_update_access_counter(ggtt);
}

static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size)
{
	u16 pat_index = tile_to_xe(ggtt->tile)->pat.idx[XE_CACHE_WB];
@@ -92,7 +116,7 @@ static void xe_ggtt_clear(struct xe_ggtt *ggtt, u64 start, u64 size)
		scratch_pte = 0;

	while (start < end) {
		xe_ggtt_set_pte(ggtt, start, scratch_pte);
		ggtt->pt_ops->ggtt_set_pte(ggtt, start, scratch_pte);
		start += XE_PAGE_SIZE;
	}
}
@@ -124,10 +148,17 @@ static void primelockdep(struct xe_ggtt *ggtt)

static const struct xe_ggtt_pt_ops xelp_pt_ops = {
	.pte_encode_bo = xelp_ggtt_pte_encode_bo,
	.ggtt_set_pte = xe_ggtt_set_pte,
};

static const struct xe_ggtt_pt_ops xelpg_pt_ops = {
	.pte_encode_bo = xelpg_ggtt_pte_encode_bo,
	.ggtt_set_pte = xe_ggtt_set_pte,
};

static const struct xe_ggtt_pt_ops xelpg_pt_wa_ops = {
	.pte_encode_bo = xelpg_ggtt_pte_encode_bo,
	.ggtt_set_pte = xe_ggtt_set_pte_and_flush,
};

/*
@@ -187,7 +218,8 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt)
		ggtt->size = GUC_GGTT_TOP;

	if (GRAPHICS_VERx100(xe) >= 1270)
		ggtt->pt_ops = &xelpg_pt_ops;
		ggtt->pt_ops = ggtt->tile->media_gt && XE_WA(ggtt->tile->media_gt, 22019338487) ?
			       &xelpg_pt_wa_ops : &xelpg_pt_ops;
	else
		ggtt->pt_ops = &xelp_pt_ops;

@@ -394,7 +426,7 @@ void xe_ggtt_map_bo(struct xe_ggtt *ggtt, struct xe_bo *bo)

	for (offset = 0; offset < bo->size; offset += XE_PAGE_SIZE) {
		pte = ggtt->pt_ops->pte_encode_bo(bo, offset, pat_index);
		xe_ggtt_set_pte(ggtt, start + offset, pte);
		ggtt->pt_ops->ggtt_set_pte(ggtt, start + offset, pte);
	}
}

@@ -502,7 +534,7 @@ static void xe_ggtt_assign_locked(struct xe_ggtt *ggtt, const struct drm_mm_node
		return;

	while (start < end) {
		xe_ggtt_set_pte(ggtt, start, pte);
		ggtt->pt_ops->ggtt_set_pte(ggtt, start, pte);
		start += XE_PAGE_SIZE;
	}

+0 −1
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@

struct drm_printer;

void xe_ggtt_set_pte(struct xe_ggtt *ggtt, u64 addr, u64 pte);
int xe_ggtt_init_early(struct xe_ggtt *ggtt);
int xe_ggtt_init(struct xe_ggtt *ggtt);
void xe_ggtt_printk(struct xe_ggtt *ggtt, const char *prefix);
Loading