mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
drm/xe/reg_sr: Add debugfs to verify status of reg_sr programming
When applying save-restore register programming for workarounds, tuning settings, and general device configuration we assume the programming was successful. However there are a number of cases where the desired reg_sr programming can become lost: - workarounds implemented on the wrong RTP table might not get saved/restored at the right time leading to, for example, failure to re-apply the programming after engine resets - some hardware registers become "locked" and can no longer be updated after firmware or the driver finishes initializing them - sometimes the hardware teams just made a mistake when documenting the register and/or bits that needed to be programmed Add a debugfs entry that will read back the registers referenced on a GT's save-restore lists and print any cases where the desired programming is no longer in effect. Such cases might indicate the presence of a driver/firmware bug, might indicate that the documentation we were following has a mistake, or might be benign (occasionally registers have broken read-back capability preventing verification, but previous writes were still successful and effective). For now we only verify the GT and engine reg_sr lists. Verifying the LRC list will require checking the expected programming against the default_lrc contents, not the live registers (which may not reflect the reg_sr programming if no context is actively running). Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com> Link: https://patch.msgid.link/20260218-sr_verify-v4-2-35d6deeb3421@intel.com Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
This commit is contained in:
parent
a41ee215b5
commit
d389489225
|
|
@ -155,6 +155,30 @@ static int register_save_restore(struct xe_gt *gt, struct drm_printer *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the registers referenced on a save-restore list and report any
|
||||
* save-restore entries that did not get applied.
|
||||
*/
|
||||
static int register_save_restore_check(struct xe_gt *gt, struct drm_printer *p)
|
||||
{
|
||||
struct xe_hw_engine *hwe;
|
||||
enum xe_hw_engine_id id;
|
||||
|
||||
CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
|
||||
if (!xe_force_wake_ref_has_domain(fw_ref.domains, XE_FORCEWAKE_ALL)) {
|
||||
drm_printf(p, "ERROR: Could not acquire forcewake\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
xe_reg_sr_readback_check(>->reg_sr, gt, p);
|
||||
for_each_hw_engine(hwe, gt, id)
|
||||
xe_reg_sr_readback_check(&hwe->reg_sr, gt, p);
|
||||
|
||||
/* TODO: Check hwe->reg_lrc against contents of default_lrc. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rcs_default_lrc(struct xe_gt *gt, struct drm_printer *p)
|
||||
{
|
||||
xe_lrc_dump_default(p, gt, XE_ENGINE_CLASS_RENDER);
|
||||
|
|
@ -209,6 +233,8 @@ static const struct drm_info_list vf_safe_debugfs_list[] = {
|
|||
{ "default_lrc_vecs", .show = xe_gt_debugfs_show_with_rpm, .data = vecs_default_lrc },
|
||||
{ "hwconfig", .show = xe_gt_debugfs_show_with_rpm, .data = hwconfig },
|
||||
{ "pat_sw_config", .show = xe_gt_debugfs_simple_show, .data = xe_pat_dump_sw_config },
|
||||
{ "register-save-restore-check",
|
||||
.show = xe_gt_debugfs_show_with_rpm, .data = register_save_restore_check },
|
||||
};
|
||||
|
||||
/* everything else should be added here */
|
||||
|
|
|
|||
|
|
@ -208,3 +208,37 @@ void xe_reg_sr_dump(struct xe_reg_sr *sr, struct drm_printer *p)
|
|||
str_yes_no(entry->reg.masked),
|
||||
str_yes_no(entry->reg.mcr));
|
||||
}
|
||||
|
||||
static u32 readback_reg(struct xe_gt *gt, struct xe_reg reg)
|
||||
{
|
||||
struct xe_reg_mcr mcr_reg = to_xe_reg_mcr(reg);
|
||||
|
||||
if (reg.mcr)
|
||||
return xe_gt_mcr_unicast_read_any(gt, mcr_reg);
|
||||
else
|
||||
return xe_mmio_read32(>->mmio, reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_reg_sr_readback_check() - Readback registers referenced in save/restore
|
||||
* entries and check whether the programming is in place.
|
||||
* @sr: Save/restore entries
|
||||
* @gt: GT to read register from
|
||||
* @p: DRM printer to report discrepancies on
|
||||
*/
|
||||
void xe_reg_sr_readback_check(struct xe_reg_sr *sr,
|
||||
struct xe_gt *gt,
|
||||
struct drm_printer *p)
|
||||
{
|
||||
struct xe_reg_sr_entry *entry;
|
||||
unsigned long offset;
|
||||
|
||||
xa_for_each(&sr->xa, offset, entry) {
|
||||
u32 val = readback_reg(gt, entry->reg);
|
||||
u32 mask = entry->clr_bits | entry->set_bits;
|
||||
|
||||
if ((val & mask) != entry->set_bits)
|
||||
drm_printf(p, "%#8lx & %#10x :: expected %#10x got %#10x\n",
|
||||
offset, mask, entry->set_bits, val & mask);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ struct drm_printer;
|
|||
|
||||
int xe_reg_sr_init(struct xe_reg_sr *sr, const char *name, struct xe_device *xe);
|
||||
void xe_reg_sr_dump(struct xe_reg_sr *sr, struct drm_printer *p);
|
||||
void xe_reg_sr_readback_check(struct xe_reg_sr *sr,
|
||||
struct xe_gt *gt,
|
||||
struct drm_printer *p);
|
||||
|
||||
int xe_reg_sr_add(struct xe_reg_sr *sr, const struct xe_reg_sr_entry *e,
|
||||
struct xe_gt *gt);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user