diff options
24 files changed, 290 insertions, 121 deletions
diff --git a/drivers/gpu/drm/xe/tests/xe_mocs.c b/drivers/gpu/drm/xe/tests/xe_mocs.c index 1b8617075b37..67c65e88c384 100644 --- a/drivers/gpu/drm/xe/tests/xe_mocs.c +++ b/drivers/gpu/drm/xe/tests/xe_mocs.c @@ -31,9 +31,9 @@ static int live_mocs_init(struct live_mocs *arg, struct xe_gt *gt) kunit_info(test, "gt %d", gt->info.id); kunit_info(test, "gt type %d", gt->info.type); - kunit_info(test, "table size %d", arg->table.size); + kunit_info(test, "table size %d", arg->table.table_size); kunit_info(test, "table uc_index %d", arg->table.uc_index); - kunit_info(test, "table n_entries %d", arg->table.n_entries); + kunit_info(test, "table num_mocs_regs %d", arg->table.num_mocs_regs); return flags; } @@ -50,7 +50,7 @@ static void read_l3cc_table(struct xe_gt *gt, ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); KUNIT_ASSERT_EQ_MSG(test, ret, 0, "Forcewake Failed.\n"); - for (i = 0; i < info->n_entries; i++) { + for (i = 0; i < info->num_mocs_regs; i++) { if (!(i & 1)) { if (regs_are_mcr(gt)) reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i >> 1)); @@ -90,7 +90,7 @@ static void read_mocs_table(struct xe_gt *gt, ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); KUNIT_ASSERT_EQ_MSG(test, ret, 0, "Forcewake Failed.\n"); - for (i = 0; i < info->n_entries; i++) { + for (i = 0; i < info->num_mocs_regs; i++) { if (regs_are_mcr(gt)) reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i)); else diff --git a/drivers/gpu/drm/xe/xe_drm_client.c b/drivers/gpu/drm/xe/xe_drm_client.c index 4a19b771e3a0..6a26923fa10e 100644 --- a/drivers/gpu/drm/xe/xe_drm_client.c +++ b/drivers/gpu/drm/xe/xe_drm_client.c @@ -260,13 +260,20 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) /* Get the total GPU cycles */ for_each_gt(gt, xe, gt_id) { + enum xe_force_wake_domains fw; + hwe = xe_gt_any_hw_engine(gt); if (!hwe) continue; - xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); + fw = xe_hw_engine_to_fw_domain(hwe); + if (xe_force_wake_get(gt_to_fw(gt), fw)) { + hwe = NULL; + break; + } + gpu_timestamp = xe_hw_engine_read_timestamp(hwe); - xe_force_wake_put(gt_to_fw(gt), XE_FW_GT); + XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), fw)); break; } diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c index 883cfc7f98a8..0cdbc1296e88 100644 --- a/drivers/gpu/drm/xe/xe_ggtt.c +++ b/drivers/gpu/drm/xe/xe_ggtt.c @@ -74,6 +74,9 @@ static unsigned int probe_gsm_size(struct pci_dev *pdev) static void ggtt_update_access_counter(struct xe_ggtt *ggtt) { + struct xe_gt *gt = XE_WA(ggtt->tile->primary_gt, 22019338487) ? ggtt->tile->primary_gt : + ggtt->tile->media_gt; + u32 max_gtt_writes = XE_WA(ggtt->tile->primary_gt, 22019338487) ? 1100 : 63; /* * 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. @@ -81,8 +84,8 @@ static void ggtt_update_access_counter(struct xe_ggtt *ggtt) */ lockdep_assert_held(&ggtt->lock); - if ((++ggtt->access_count % 63) == 0) { - xe_mmio_write32(ggtt->tile->media_gt, GMD_ID, 0x0); + if ((++ggtt->access_count % max_gtt_writes) == 0) { + xe_mmio_write32(gt, GMD_ID, 0x0); ggtt->access_count = 0; } } @@ -218,7 +221,9 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) ggtt->size = GUC_GGTT_TOP; if (GRAPHICS_VERx100(xe) >= 1270) - ggtt->pt_ops = ggtt->tile->media_gt && XE_WA(ggtt->tile->media_gt, 22019338487) ? + ggtt->pt_ops = (ggtt->tile->media_gt && + XE_WA(ggtt->tile->media_gt, 22019338487)) || + XE_WA(ggtt->tile->primary_gt, 22019338487) ? &xelpg_pt_wa_ops : &xelpg_pt_ops; else ggtt->pt_ops = &xelp_pt_ops; diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c index 759634cff1d8..0ba2e2d0289b 100644 --- a/drivers/gpu/drm/xe/xe_gt.c +++ b/drivers/gpu/drm/xe/xe_gt.c @@ -683,6 +683,9 @@ static int do_gt_restart(struct xe_gt *gt) /* Restore GT freq to expected values */ xe_gt_sanitize_freq(gt); + if (IS_SRIOV_PF(gt_to_xe(gt))) + xe_gt_sriov_pf_restart(gt); + return 0; } @@ -818,8 +821,7 @@ int xe_gt_sanitize_freq(struct xe_gt *gt) int ret = 0; if ((!xe_uc_fw_is_available(>->uc.gsc.fw) || - xe_uc_fw_is_loaded(>->uc.gsc.fw)) && - XE_WA(gt, 22019338487)) + xe_uc_fw_is_loaded(>->uc.gsc.fw)) && XE_WA(gt, 22019338487)) ret = xe_guc_pc_restore_stashed_freq(>->uc.guc.pc); return ret; diff --git a/drivers/gpu/drm/xe/xe_gt_mcr.c b/drivers/gpu/drm/xe/xe_gt_mcr.c index 386ac3269909..6d948a469126 100644 --- a/drivers/gpu/drm/xe/xe_gt_mcr.c +++ b/drivers/gpu/drm/xe/xe_gt_mcr.c @@ -342,7 +342,7 @@ static void init_steering_oaddrm(struct xe_gt *gt) else gt->steering[OADDRM].group_target = 1; - gt->steering[DSS].instance_target = 0; /* unused */ + gt->steering[OADDRM].instance_target = 0; /* unused */ } static void init_steering_sqidi_psmi(struct xe_gt *gt) @@ -357,8 +357,8 @@ static void init_steering_sqidi_psmi(struct xe_gt *gt) static void init_steering_inst0(struct xe_gt *gt) { - gt->steering[DSS].group_target = 0; /* unused */ - gt->steering[DSS].instance_target = 0; /* unused */ + gt->steering[INSTANCE0].group_target = 0; /* unused */ + gt->steering[INSTANCE0].instance_target = 0; /* unused */ } static const struct { diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c index 7decf71c2b7d..9dbba9ab7a9a 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.c @@ -8,6 +8,7 @@ #include "regs/xe_sriov_regs.h" #include "xe_gt_sriov_pf.h" +#include "xe_gt_sriov_pf_config.h" #include "xe_gt_sriov_pf_helpers.h" #include "xe_gt_sriov_pf_service.h" #include "xe_mmio.h" @@ -82,3 +83,14 @@ void xe_gt_sriov_pf_init_hw(struct xe_gt *gt) xe_gt_sriov_pf_service_update(gt); } + +/** + * xe_gt_sriov_pf_restart - Restart SR-IOV support after a GT reset. + * @gt: the &xe_gt + * + * This function can only be called on PF. + */ +void xe_gt_sriov_pf_restart(struct xe_gt *gt) +{ + xe_gt_sriov_pf_config_restart(gt); +} diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf.h index 37d7d6c3df03..f0cb726a6919 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf.h @@ -11,6 +11,7 @@ struct xe_gt; #ifdef CONFIG_PCI_IOV int xe_gt_sriov_pf_init_early(struct xe_gt *gt); void xe_gt_sriov_pf_init_hw(struct xe_gt *gt); +void xe_gt_sriov_pf_restart(struct xe_gt *gt); #else static inline int xe_gt_sriov_pf_init_early(struct xe_gt *gt) { @@ -20,6 +21,10 @@ static inline int xe_gt_sriov_pf_init_early(struct xe_gt *gt) static inline void xe_gt_sriov_pf_init_hw(struct xe_gt *gt) { } + +static inline void xe_gt_sriov_pf_restart(struct xe_gt *gt) +{ +} #endif #endif diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c index 694671497f6e..db6c213da847 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c @@ -1922,6 +1922,84 @@ int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsigned int vfid, bool refresh return err; } +static int pf_validate_vf_config(struct xe_gt *gt, unsigned int vfid) +{ + struct xe_gt *primary_gt = gt_to_tile(gt)->primary_gt; + struct xe_device *xe = gt_to_xe(gt); + bool valid_ggtt, valid_ctxs, valid_dbs; + bool valid_any, valid_all; + + valid_ggtt = pf_get_vf_config_ggtt(primary_gt, vfid); + valid_ctxs = pf_get_vf_config_ctxs(gt, vfid); + valid_dbs = pf_get_vf_config_dbs(gt, vfid); + + /* note that GuC doorbells are optional */ + valid_any = valid_ggtt || valid_ctxs || valid_dbs; + valid_all = valid_ggtt && valid_ctxs; + + if (IS_DGFX(xe)) { + bool valid_lmem = pf_get_vf_config_ggtt(primary_gt, vfid); + + valid_any = valid_any || valid_lmem; + valid_all = valid_all && valid_lmem; + } + + return valid_all ? 1 : valid_any ? -ENOKEY : -ENODATA; +} + +/** + * xe_gt_sriov_pf_config_is_empty - Check VF's configuration. + * @gt: the &xe_gt + * @vfid: the VF identifier (can't be PF) + * + * This function can only be called on PF. + * + * Return: true if VF mandatory configuration (GGTT, LMEM, ...) is empty. + */ +bool xe_gt_sriov_pf_config_is_empty(struct xe_gt *gt, unsigned int vfid) +{ + bool empty; + + xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt))); + xe_gt_assert(gt, vfid); + + mutex_lock(xe_gt_sriov_pf_master_mutex(gt)); + empty = pf_validate_vf_config(gt, vfid) == -ENODATA; + mutex_unlock(xe_gt_sriov_pf_master_mutex(gt)); + + return empty; +} + +/** + * xe_gt_sriov_pf_config_restart - Restart SR-IOV configurations after a GT reset. + * @gt: the &xe_gt + * + * Any prior configurations pushed to GuC are lost when the GT is reset. + * Push again all non-empty VF configurations to the GuC. + * + * This function can only be called on PF. + */ +void xe_gt_sriov_pf_config_restart(struct xe_gt *gt) +{ + unsigned int n, total_vfs = xe_sriov_pf_get_totalvfs(gt_to_xe(gt)); + unsigned int fail = 0, skip = 0; + + for (n = 1; n <= total_vfs; n++) { + if (xe_gt_sriov_pf_config_is_empty(gt, n)) + skip++; + else if (xe_gt_sriov_pf_config_push(gt, n, false)) + fail++; + } + + if (fail) + xe_gt_sriov_notice(gt, "Failed to push %u of %u VF%s configurations\n", + fail, total_vfs - skip, str_plural(total_vfs)); + + if (fail != total_vfs) + xe_gt_sriov_dbg(gt, "pushed %u skip %u of %u VF%s configurations\n", + total_vfs - skip - fail, skip, total_vfs, str_plural(total_vfs)); +} + /** * xe_gt_sriov_pf_config_print_ggtt - Print GGTT configurations. * @gt: the &xe_gt diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h index e8238c1ad06a..c0e6e4743dc2 100644 --- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h +++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h @@ -53,6 +53,10 @@ int xe_gt_sriov_pf_config_set_fair(struct xe_gt *gt, unsigned int vfid, unsigned int xe_gt_sriov_pf_config_release(struct xe_gt *gt, unsigned int vfid, bool force); int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsigned int vfid, bool refresh); +bool xe_gt_sriov_pf_config_is_empty(struct xe_gt *gt, unsigned int vfid); + +void xe_gt_sriov_pf_config_restart(struct xe_gt *gt); + int xe_gt_sriov_pf_config_print_ggtt(struct xe_gt *gt, struct drm_printer *p); int xe_gt_sriov_pf_config_print_ctxs(struct xe_gt *gt, struct drm_printer *p); int xe_gt_sriov_pf_config_print_dbs(struct xe_gt *gt, struct drm_printer *p); diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c index e1f1ccb01143..d9359976ab8b 100644 --- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c +++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c @@ -17,7 +17,22 @@ #include "xe_trace.h" #include "regs/xe_guc_regs.h" -#define TLB_TIMEOUT (HZ / 4) +/* + * TLB inval depends on pending commands in the CT queue and then the real + * invalidation time. Double up the time to process full CT queue + * just to be on the safe side. + */ +static long tlb_timeout_jiffies(struct xe_gt *gt) +{ + /* this reflects what HW/GuC needs to process TLB inv request */ + const long hw_tlb_timeout = HZ / 4; + + /* this estimates actual delay caused by the CTB transport */ + long delay = xe_guc_ct_queue_proc_time_jiffies(>->uc.guc.ct); + + return hw_tlb_timeout + 2 * delay; +} + static void xe_gt_tlb_fence_timeout(struct work_struct *work) { @@ -32,7 +47,7 @@ static void xe_gt_tlb_fence_timeout(struct work_struct *work) s64 since_inval_ms = ktime_ms_delta(ktime_get(), fence->invalidation_time); - if (msecs_to_jiffies(since_inval_ms) < TLB_TIMEOUT) + if (msecs_to_jiffies(since_inval_ms) < tlb_timeout_jiffies(gt)) break; trace_xe_gt_tlb_invalidation_fence_timeout(xe, fence); @@ -47,7 +62,7 @@ static void xe_gt_tlb_fence_timeout(struct work_struct *work) if (!list_empty(>->tlb_invalidation.pending_fences)) queue_delayed_work(system_wq, >->tlb_invalidation.fence_tdr, - TLB_TIMEOUT); + tlb_timeout_jiffies(gt)); spin_unlock_irq(>->tlb_invalidation.pending_lock); } @@ -183,7 +198,7 @@ static int send_tlb_invalidation(struct xe_guc *guc, if (list_is_singular(>->tlb_invalidation.pending_fences)) queue_delayed_work(system_wq, >->tlb_invalidation.fence_tdr, - TLB_TIMEOUT); + tlb_timeout_jiffies(gt)); } spin_unlock_irq(>->tlb_invalidation.pending_lock); } else if (ret < 0 && fence) { @@ -390,8 +405,7 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt, * @gt: graphics tile * @seqno: seqno to wait which was returned from xe_gt_tlb_invalidation * - * Wait for 200ms for a TLB invalidation to complete, in practice we always - * should receive the TLB invalidation within 200ms. + * Wait for tlb_timeout_jiffies() for a TLB invalidation to complete. * * Return: 0 on success, -ETIME on TLB invalidation timeout */ @@ -410,7 +424,7 @@ int xe_gt_tlb_invalidation_wait(struct xe_gt *gt, int seqno) */ ret = wait_event_timeout(guc->ct.wq, tlb_invalidation_seqno_past(gt, seqno), - TLB_TIMEOUT); + tlb_timeout_jiffies(gt)); if (!ret) { struct drm_printer p = xe_gt_err_printer(gt); @@ -486,7 +500,7 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len) if (!list_empty(>->tlb_invalidation.pending_fences)) mod_delayed_work(system_wq, >->tlb_invalidation.fence_tdr, - TLB_TIMEOUT); + tlb_timeout_jiffies(gt)); else cancel_delayed_work(>->tlb_invalidation.fence_tdr); diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c index 873d1bcbedd7..7d2e937da1d8 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.c +++ b/drivers/gpu/drm/xe/xe_guc_ct.c @@ -112,6 +112,23 @@ ct_to_xe(struct xe_guc_ct *ct) #define CTB_G2H_BUFFER_SIZE (4 * CTB_H2G_BUFFER_SIZE) #define G2H_ROOM_BUFFER_SIZE (CTB_G2H_BUFFER_SIZE / 4) +/** + * xe_guc_ct_queue_proc_time_jiffies - Return maximum time to process a full + * CT command queue + * @ct: the &xe_guc_ct. Unused at this moment but will be used in the future. + * + * Observation is that a 4KiB buffer full of commands takes a little over a + * second to process. Use that to calculate maximum time to process a full CT + * command queue. + * + * Return: Maximum time to process a full CT queue in jiffies. + */ +long xe_guc_ct_queue_proc_time_jiffies(struct xe_guc_ct *ct) +{ + BUILD_BUG_ON(!IS_ALIGNED(CTB_H2G_BUFFER_SIZE, SZ_4)); + return (CTB_H2G_BUFFER_SIZE / SZ_4K) * HZ; +} + static size_t guc_ct_size(void) { return 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE + diff --git a/drivers/gpu/drm/xe/xe_guc_ct.h b/drivers/gpu/drm/xe/xe_guc_ct.h index 105bb8e99a8d..190202fce2d0 100644 --- a/drivers/gpu/drm/xe/xe_guc_ct.h +++ b/drivers/gpu/drm/xe/xe_guc_ct.h @@ -64,4 +64,6 @@ xe_guc_ct_send_block_no_fail(struct xe_guc_ct *ct, const u32 *action, u32 len) return xe_guc_ct_send_recv_no_fail(ct, action, len, NULL); } +long xe_guc_ct_queue_proc_time_jiffies(struct xe_guc_ct *ct); + #endif diff --git a/drivers/gpu/drm/xe/xe_guc_pc.c b/drivers/gpu/drm/xe/xe_guc_pc.c index d88f5e960fbd..32e93a8127d4 100644 --- a/drivers/gpu/drm/xe/xe_guc_pc.c +++ b/drivers/gpu/drm/xe/xe_guc_pc.c @@ -26,6 +26,7 @@ #include "xe_mmio.h" #include "xe_pcode.h" #include "xe_pm.h" +#include "xe_sriov.h" #include "xe_wa.h" #define MCHBAR_MIRROR_BASE_SNB 0x140000 @@ -45,6 +46,7 @@ #define GT_FREQUENCY_SCALER 3 #define LNL_MERT_FREQ_CAP 800 +#define BMG_MERT_FREQ_CAP 2133 /** * DOC: GuC Power Conservation (PC) @@ -703,10 +705,14 @@ static u32 pc_max_freq_cap(struct xe_guc_pc *pc) { struct xe_gt *gt = pc_to_gt(pc); - if (XE_WA(gt, 22019338487)) - return min(LNL_MERT_FREQ_CAP, pc->rp0_freq); - else + if (XE_WA(gt, 22019338487)) { + if (xe_gt_is_media_type(gt)) + return min(LNL_MERT_FREQ_CAP, pc->rp0_freq); + else + return min(BMG_MERT_FREQ_CAP, pc->rp0_freq); + } else { return pc->rp0_freq; + } } /** @@ -825,6 +831,9 @@ int xe_guc_pc_restore_stashed_freq(struct xe_guc_pc *pc) { int ret = 0; + if (IS_SRIOV_VF(pc_to_xe(pc)) || pc_to_xe(pc)->info.skip_guc_pc) + return 0; + mutex_lock(&pc->freq_lock); ret = pc_set_max_freq(pc, pc->stashed_max_freq); if (!ret) diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c index 78b50d3a6501..07ed9fd28f19 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.c +++ b/drivers/gpu/drm/xe/xe_hw_engine.c @@ -1130,3 +1130,8 @@ u64 xe_hw_engine_read_timestamp(struct xe_hw_engine *hwe) { return xe_mmio_read64_2x32(hwe->gt, RING_TIMESTAMP(hwe->mmio_base)); } + +enum xe_force_wake_domains xe_hw_engine_to_fw_domain(struct xe_hw_engine *hwe) +{ + return engine_infos[hwe->engine_id].domain; +} diff --git a/drivers/gpu/drm/xe/xe_hw_engine.h b/drivers/gpu/drm/xe/xe_hw_engine.h index 7f2d27c0ba1a..900c8c991430 100644 --- a/drivers/gpu/drm/xe/xe_hw_engine.h +++ b/drivers/gpu/drm/xe/xe_hw_engine.h @@ -69,5 +69,6 @@ static inline bool xe_hw_engine_is_valid(struct xe_hw_engine *hwe) const char *xe_hw_engine_class_to_str(enum xe_engine_class class); u64 xe_hw_engine_read_timestamp(struct xe_hw_engine *hwe); +enum xe_force_wake_domains xe_hw_engine_to_fw_domain(struct xe_hw_engine *hwe); #endif diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index 222c651ee1f8..0c8ce09e5025 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -137,34 +137,6 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg return XE_REG(0); } -static void xe_hwmon_process_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg hwmon_reg, - enum xe_hwmon_reg_operation operation, u64 *value, - u32 clr, u32 set, int channel) -{ - struct xe_reg reg; - - reg = xe_hwmon_get_reg(hwmon, hwmon_reg, channel); - - if (!xe_reg_is_valid(reg)) - return; - - switch (operation) { - case REG_READ32: - *value = xe_mmio_read32(hwmon->gt, reg); - break; - case REG_RMW32: - *value = xe_mmio_rmw32(hwmon->gt, reg, clr, set); - break; - case REG_READ64: - *value = xe_mmio_read64_2x32(hwmon->gt, reg); - break; - default: - drm_warn(>_to_xe(hwmon->gt)->drm, "Invalid xe hwmon reg operation: %d\n", - operation); - break; - } -} - #define PL1_DISABLE 0 /* @@ -176,10 +148,25 @@ static void xe_hwmon_process_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg hwmon static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, int channel, long *value) { u64 reg_val, min, max; + struct xe_device *xe = gt_to_xe(hwmon->gt); + struct xe_reg rapl_limit, pkg_power_sku; + + rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); + pkg_power_sku = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel); + + /* + * Valid check of REG_PKG_RAPL_LIMIT is already done in xe_hwmon_power_is_visible. + * So not checking it again here. + */ + if (!xe_reg_is_valid(pkg_power_sku)) { + drm_warn(&xe->drm, "pkg_power_sku invalid\n"); + *value = 0; + return; + } mutex_lock(&hwmon->hwmon_lock); - xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_READ32, ®_val, 0, 0, channel); + reg_val = xe_mmio_read32(hwmon->gt, rapl_limit); /* Check if PL1 limit is disabled */ if (!(reg_val & PKG_PWR_LIM_1_EN)) { *value = PL1_DISABLE; @@ -189,7 +176,7 @@ static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, int channel, long *v reg_val = REG_FIELD_GET(PKG_PWR_LIM_1, reg_val); *value = mul_u64_u32_shr(reg_val, SF_POWER, hwmon->scl_shift_power); - xe_hwmon_process_reg(hwmon, REG_PKG_POWER_SKU, REG_READ64, ®_val, 0, 0, channel); + reg_val = xe_mmio_read64_2x32(hwmon->gt, pkg_power_sku); min = REG_FIELD_GET(PKG_MIN_PWR, reg_val); min = mul_u64_u32_shr(min, SF_POWER, hwmon->scl_shift_power); max = REG_FIELD_GET(PKG_MAX_PWR, reg_val); @@ -205,16 +192,16 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long va { int ret = 0; u64 reg_val; + struct xe_reg rapl_limit; + + rapl_limit = xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel); mutex_lock(&hwmon->hwmon_lock); /* Disable PL1 limit and verify, as limit cannot be disabled on all platforms */ if (value == PL1_DISABLE) { - xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_RMW32, ®_val, - PKG_PWR_LIM_1_EN, 0, channel); - xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_READ32, ®_val, - PKG_PWR_LIM_1_EN, 0, channel); - + reg_val = xe_mmio_rmw32(hwmon->gt, rapl_limit, PKG_PWR_LIM_1_EN, 0); + reg_val = xe_mmio_read32(hwmon->gt, rapl_limit); if (reg_val & PKG_PWR_LIM_1_EN) { ret = -EOPNOTSUPP; goto unlock; @@ -224,9 +211,8 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long va /* Computation in 64-bits to avoid overflow. Round to nearest. */ reg_val = DIV_ROUND_CLOSEST_ULL((u64)value << hwmon->scl_shift_power, SF_POWER); reg_val = PKG_PWR_LIM_1_EN | REG_FIELD_PREP(PKG_PWR_LIM_1, reg_val); + reg_val = xe_mmio_rmw32(hwmon->gt, rapl_limit, PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, reg_val); - xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_RMW32, ®_val, - PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, reg_val, channel); unlock: mutex_unlock(&hwmon->hwmon_lock); return ret; @@ -234,9 +220,15 @@ unlock: static void xe_hwmon_power_rated_max_read(struct xe_hwmon *hwmon, int channel, long *value) { + struct xe_reg reg = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU, channel); u64 reg_val; - xe_hwmon_process_reg(hwmon, REG_PKG_POWER_SKU, REG_READ32, ®_val, 0, 0, channel); + /* + * This sysfs file won't be visible if REG_PKG_POWER_SKU is invalid, so valid check + * for this register can be skipped. + * See xe_hwmon_power_is_visible. + */ + reg_val = xe_mmio_read32(hwmon->gt, reg); reg_val = REG_FIELD_GET(PKG_TDP, reg_val); *value = mul_u64_u32_shr(reg_val, SF_POWER, hwmon->scl_shift_power); } @@ -267,8 +259,8 @@ xe_hwmon_energy_get(struct xe_hwmon *hwmon, int channel, long *energy) struct xe_hwmon_energy_info *ei = &hwmon->ei[channel]; u64 reg_val; - xe_hwmon_process_reg(hwmon, REG_PKG_ENERGY_STATUS, REG_READ32, - ®_val, 0, 0, channel); + reg_val = xe_mmio_read32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS, + channel)); if (reg_val >= ei->reg_val_prev) ei->accum_energy += reg_val - ei->reg_val_prev; @@ -294,8 +286,7 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at mutex_lock(&hwmon->hwmon_lock); - xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, - REG_READ32, &r, 0, 0, sensor_index); + r = xe_mmio_read32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, sensor_index)); mutex_unlock(&hwmon->hwmon_lock); @@ -383,8 +374,8 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a mutex_lock(&hwmon->hwmon_lock); - xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_RMW32, (u64 *)&r, - PKG_PWR_LIM_1_TIME, rxy, sensor_index); + r = xe_mmio_rmw32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, sensor_index), + PKG_PWR_LIM_1_TIME, rxy); mutex_unlock(&hwmon->hwmon_lock); @@ -499,8 +490,7 @@ static void xe_hwmon_get_voltage(struct xe_hwmon *hwmon, int channel, long *valu { u64 reg_val; - xe_hwmon_process_reg(hwmon, REG_GT_PERF_STATUS, - REG_READ32, ®_val, 0, 0, channel); + reg_val = xe_mmio_read32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_GT_PERF_STATUS, channel)); /* HW register value in units of 2.5 millivolt */ *value = DIV_ROUND_CLOSEST(REG_FIELD_GET(VOLTAGE_MASK, reg_val) * 2500, SF_VOLTAGE); } @@ -784,14 +774,15 @@ xe_hwmon_get_preregistration_info(struct xe_device *xe) long energy; u64 val_sku_unit = 0; int channel; + struct xe_reg pkg_power_sku_unit; /* * The contents of register PKG_POWER_SKU_UNIT do not change, * so read it once and store the shift values. */ - if (xe_reg_is_valid(xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU_UNIT, 0))) { - xe_hwmon_process_reg(hwmon, REG_PKG_POWER_SKU_UNIT, - REG_READ32, &val_sku_unit, 0, 0, 0); + pkg_power_sku_unit = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU_UNIT, 0); + if (xe_reg_is_valid(pkg_power_sku_unit)) { + val_sku_unit = xe_mmio_read32(hwmon->gt, pkg_power_sku_unit); hwmon->scl_shift_power = REG_FIELD_GET(PKG_PWR_UNIT, val_sku_unit); hwmon->scl_shift_energy = REG_FIELD_GET(PKG_ENERGY_UNIT, val_sku_unit); hwmon->scl_shift_time = REG_FIELD_GET(PKG_TIME_UNIT, val_sku_unit); diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index 05f933787860..c9f5673353ee 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -1358,7 +1358,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m, GFP_KERNEL, true, 0); if (IS_ERR(sa_bo)) { err = PTR_ERR(sa_bo); - goto err; + goto err_bb; } ppgtt_ofs = NUM_KERNEL_PDE + @@ -1406,7 +1406,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m, update_idx); if (IS_ERR(job)) { err = PTR_ERR(job); - goto err_bb; + goto err_sa; } /* Wait on BO move */ @@ -1458,10 +1458,10 @@ xe_migrate_update_pgtables(struct xe_migrate *m, err_job: xe_sched_job_put(job); +err_sa: + drm_suballoc_free(sa_bo, NULL); err_bb: xe_bb_free(bb, NULL); -err: - drm_suballoc_free(sa_bo, NULL); return ERR_PTR(err); } diff --git a/drivers/gpu/drm/xe/xe_mocs.c b/drivers/gpu/drm/xe/xe_mocs.c index de3f2d3f1b04..7ff0ac5b799a 100644 --- a/drivers/gpu/drm/xe/xe_mocs.c +++ b/drivers/gpu/drm/xe/xe_mocs.c @@ -47,8 +47,16 @@ struct xe_mocs_ops { }; struct xe_mocs_info { - unsigned int size; - unsigned int n_entries; + /* + * Size of the spec's suggested MOCS programming table. The list of + * table entries from the spec can potentially be smaller than the + * number of hardware registers used to program the MOCS table; in such + * cases the registers for the remaining indices will be programmed to + * match unused_entries_index. + */ + unsigned int table_size; + /* Number of MOCS entries supported by the hardware */ + unsigned int num_mocs_regs; const struct xe_mocs_entry *table; const struct xe_mocs_ops *ops; u8 uc_index; @@ -266,7 +274,7 @@ static void xelp_lncf_dump(struct xe_mocs_info *info, struct xe_gt *gt, struct d drm_printf(p, "LNCFCMOCS[idx] = [ESC, SCC, L3CC] (value)\n\n"); - for (i = 0, j = 0; i < (info->n_entries + 1) / 2; i++, j++) { + for (i = 0, j = 0; i < (info->num_mocs_regs + 1) / 2; i++, j++) { if (regs_are_mcr(gt)) reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i)); else @@ -298,7 +306,7 @@ static void xelp_mocs_dump(struct xe_mocs_info *info, unsigned int flags, drm_printf(p, "Global mocs table configuration:\n"); drm_printf(p, "GLOB_MOCS[idx] = [LeCC, TC, LRUM, AOM, RSC, SCC, PFM, SCF, CoS, SSE] (value)\n\n"); - for (i = 0; i < info->n_entries; i++) { + for (i = 0; i < info->num_mocs_regs; i++) { if (regs_are_mcr(gt)) reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i)); else @@ -371,7 +379,7 @@ static void xehp_lncf_dump(struct xe_mocs_info *info, unsigned int flags, drm_printf(p, "LNCFCMOCS[idx] = [UCL3LOOKUP, GLBGO, L3CC] (value)\n\n"); - for (i = 0, j = 0; i < (info->n_entries + 1) / 2; i++, j++) { + for (i = 0, j = 0; i < (info->num_mocs_regs + 1) / 2; i++, j++) { if (regs_are_mcr(gt)) reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i)); else @@ -416,7 +424,7 @@ static void pvc_mocs_dump(struct xe_mocs_info *info, unsigned int flags, struct drm_printf(p, "LNCFCMOCS[idx] = [ L3CC ] (value)\n\n"); - for (i = 0, j = 0; i < (info->n_entries + 1) / 2; i++, j++) { + for (i = 0, j = 0; i < (info->num_mocs_regs + 1) / 2; i++, j++) { if (regs_are_mcr(gt)) reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i)); else @@ -498,7 +506,7 @@ static void mtl_mocs_dump(struct xe_mocs_info *info, unsigned int flags, drm_printf(p, "Global mocs table configuration:\n"); drm_printf(p, "GLOB_MOCS[idx] = [IG_PAT, L4_CACHE_POLICY] (value)\n\n"); - for (i = 0; i < info->n_entries; i++) { + for (i = 0; i < info->num_mocs_regs; i++) { if (regs_are_mcr(gt)) reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i)); else @@ -541,7 +549,7 @@ static void xe2_mocs_dump(struct xe_mocs_info *info, unsigned int flags, drm_printf(p, "Global mocs table configuration:\n"); drm_printf(p, "GLOB_MOCS[idx] = [IG_PAT, L3_CLOS, L3_CACHE_POLICY, L4_CACHE_POLICY] (value)\n\n"); - for (i = 0; i < info->n_entries; i++) { + for (i = 0; i < info->num_mocs_regs; i++) { if (regs_are_mcr(gt)) reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i)); else @@ -571,48 +579,48 @@ static unsigned int get_mocs_settings(struct xe_device *xe, case XE_LUNARLAKE: case XE_BATTLEMAGE: info->ops = &xe2_mocs_ops; - info->size = ARRAY_SIZE(xe2_mocs_table); + info->table_size = ARRAY_SIZE(xe2_mocs_table); info->table = xe2_mocs_table; - info->n_entries = XE2_NUM_MOCS_ENTRIES; + info->num_mocs_regs = XE2_NUM_MOCS_ENTRIES; info->uc_index = 3; info->wb_index = 4; info->unused_entries_index = 4; break; case XE_PVC: info->ops = &pvc_mocs_ops; - info->size = ARRAY_SIZE(pvc_mocs_desc); + info->table_size = ARRAY_SIZE(pvc_mocs_desc); info->table = pvc_mocs_desc; - info->n_entries = PVC_NUM_MOCS_ENTRIES; + info->num_mocs_regs = PVC_NUM_MOCS_ENTRIES; info->uc_index = 1; info->wb_index = 2; info->unused_entries_index = 2; break; case XE_METEORLAKE: info->ops = &mtl_mocs_ops; - info->size = ARRAY_SIZE(mtl_mocs_desc); + info->table_size = ARRAY_SIZE(mtl_mocs_desc); info->table = mtl_mocs_desc; - info->n_entries = MTL_NUM_MOCS_ENTRIES; + info->num_mocs_regs = MTL_NUM_MOCS_ENTRIES; info->uc_index = 9; info->unused_entries_index = 1; break; case XE_DG2: info->ops = &xehp_mocs_ops; - info->size = ARRAY_SIZE(dg2_mocs_desc); + info->table_size = ARRAY_SIZE(dg2_mocs_desc); info->table = dg2_mocs_desc; info->uc_index = 1; /* * Last entry is RO on hardware, don't bother with what was * written when checking later */ - info->n_entries = XELP_NUM_MOCS_ENTRIES - 1; + info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES - 1; info->unused_entries_index = 3; break; case XE_DG1: info->ops = &xelp_mocs_ops; - info->size = ARRAY_SIZE(dg1_mocs_desc); + info->table_size = ARRAY_SIZE(dg1_mocs_desc); info->table = dg1_mocs_desc; info->uc_index = 1; - info->n_entries = XELP_NUM_MOCS_ENTRIES; + info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES; info->unused_entries_index = 5; break; case XE_TIGERLAKE: @@ -621,9 +629,9 @@ static unsigned int get_mocs_settings(struct xe_device *xe, case XE_ALDERLAKE_P: case XE_ALDERLAKE_N: info->ops = &xelp_mocs_ops; - info->size = ARRAY_SIZE(gen12_mocs_desc); + info->table_size = ARRAY_SIZE(gen12_mocs_desc); info->table = gen12_mocs_desc; - info->n_entries = XELP_NUM_MOCS_ENTRIES; + info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES; info->uc_index = 3; info->unused_entries_index = 2; break; @@ -642,12 +650,8 @@ static unsigned int get_mocs_settings(struct xe_device *xe, */ xe_assert(xe, info->unused_entries_index != 0); - xe_assert(xe, !info->ops || info->ops->dump); - - if (XE_WARN_ON(info->size > info->n_entries)) { - info->table = NULL; - return 0; - } + xe_assert(xe, info->ops && info->ops->dump); + xe_assert(xe, info->table_size <= info->num_mocs_regs); if (!IS_DGFX(xe) || GRAPHICS_VER(xe) >= 20) flags |= HAS_GLOBAL_MOCS; @@ -664,7 +668,7 @@ static unsigned int get_mocs_settings(struct xe_device *xe, static u32 get_entry_control(const struct xe_mocs_info *info, unsigned int index) { - if (index < info->size && info->table[index].used) + if (index < info->table_size && info->table[index].used) return info->table[index].control_value; return info->table[info->unused_entries_index].control_value; } @@ -675,12 +679,9 @@ static void __init_mocs_table(struct xe_gt *gt, unsigned int i; u32 mocs; - xe_gt_WARN_ONCE(gt, !info->unused_entries_index, - "Unused entries index should have been defined\n"); - - mocs_dbg(gt, "mocs entries: %d\n", info->n_entries); + mocs_dbg(gt, "mocs entries: %d\n", info->num_mocs_regs); - for (i = 0; i < info->n_entries; i++) { + for (i = 0; i < info->num_mocs_regs; i++) { mocs = get_entry_control(info, i); mocs_dbg(gt, "GLOB_MOCS[%d] 0x%x 0x%x\n", i, @@ -701,7 +702,7 @@ static void __init_mocs_table(struct xe_gt *gt, static u16 get_entry_l3cc(const struct xe_mocs_info *info, unsigned int index) { - if (index < info->size && info->table[index].used) + if (index < info->table_size && info->table[index].used) return info->table[index].l3cc_value; return info->table[info->unused_entries_index].l3cc_value; } @@ -717,9 +718,9 @@ static void init_l3cc_table(struct xe_gt *gt, unsigned int i; u32 l3cc; - mocs_dbg(gt, "l3cc entries: %d\n", info->n_entries); + mocs_dbg(gt, "l3cc entries: %d\n", info->num_mocs_regs); - for (i = 0; i < (info->n_entries + 1) / 2; i++) { + for (i = 0; i < (info->num_mocs_regs + 1) / 2; i++) { l3cc = l3cc_combine(get_entry_l3cc(info, 2 * i), get_entry_l3cc(info, 2 * i + 1)); @@ -779,9 +780,6 @@ void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p) flags = get_mocs_settings(xe, &table); - if (!table.ops->dump) - return; - xe_pm_runtime_get_noresume(xe); ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c index 6cc3f0217341..4188516a7816 100644 --- a/drivers/gpu/drm/xe/xe_oa.c +++ b/drivers/gpu/drm/xe/xe_oa.c @@ -824,6 +824,8 @@ static void xe_oa_stream_destroy(struct xe_oa_stream *stream) WRITE_ONCE(u->exclusive_stream, NULL); + mutex_destroy(&stream->stream_lock); + xe_oa_disable_metric_set(stream); xe_exec_queue_put(stream->k_exec_q); diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c index f5d5a368e595..732ee0d02124 100644 --- a/drivers/gpu/drm/xe/xe_pci.c +++ b/drivers/gpu/drm/xe/xe_pci.c @@ -748,10 +748,8 @@ static void xe_pci_remove(struct pci_dev *pdev) if (!xe) /* driver load aborted, nothing to cleanup */ return; -#ifdef CONFIG_PCI_IOV if (IS_SRIOV_PF(xe)) xe_pci_sriov_configure(pdev, 0); -#endif xe_device_remove(xe); xe_pm_runtime_fini(xe); @@ -1009,9 +1007,7 @@ static struct pci_driver xe_pci_driver = { .probe = xe_pci_probe, .remove = xe_pci_remove, .shutdown = xe_pci_shutdown, -#ifdef CONFIG_PCI_IOV .sriov_configure = xe_pci_sriov_configure, -#endif #ifdef CONFIG_PM_SLEEP .driver.pm = &xe_pm_ops, #endif diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.c b/drivers/gpu/drm/xe/xe_pci_sriov.c index 74c8fadc9365..aaceee748287 100644 --- a/drivers/gpu/drm/xe/xe_pci_sriov.c +++ b/drivers/gpu/drm/xe/xe_pci_sriov.c @@ -13,6 +13,17 @@ #include "xe_sriov_pf_helpers.h" #include "xe_sriov_printk.h" +static int pf_needs_provisioning(struct xe_gt *gt, unsigned int num_vfs) +{ + unsigned int n; + + for (n = 1; n <= num_vfs; n++) + if (!xe_gt_sriov_pf_config_is_empty(gt, n)) + return false; + + return true; +} + static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) { struct xe_gt *gt; @@ -20,6 +31,8 @@ static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) int result = 0, err; for_each_gt(gt, xe, id) { + if (!pf_needs_provisioning(gt, num_vfs)) + continue; err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs); result = result ?: err; } diff --git a/drivers/gpu/drm/xe/xe_pci_sriov.h b/drivers/gpu/drm/xe/xe_pci_sriov.h index 3b8bfbf7e1d9..c76dd0d90495 100644 --- a/drivers/gpu/drm/xe/xe_pci_sriov.h +++ b/drivers/gpu/drm/xe/xe_pci_sriov.h @@ -8,6 +8,13 @@ struct pci_dev; +#ifdef CONFIG_PCI_IOV int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs); +#else +static inline int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) +{ + return 0; +} +#endif #endif diff --git a/drivers/gpu/drm/xe/xe_rtp.c b/drivers/gpu/drm/xe/xe_rtp.c index 5b27f7c45ea3..02e28274282f 100644 --- a/drivers/gpu/drm/xe/xe_rtp.c +++ b/drivers/gpu/drm/xe/xe_rtp.c @@ -121,7 +121,7 @@ static bool rule_matches(const struct xe_device *xe, * Advance rules until we find XE_RTP_MATCH_OR to check * if there's another set of conditions to check */ - while (i < n_rules && rules[++i].match_type != XE_RTP_MATCH_OR) + while (++i < n_rules && rules[i].match_type != XE_RTP_MATCH_OR) ; if (i >= n_rules) diff --git a/drivers/gpu/drm/xe/xe_wa_oob.rules b/drivers/gpu/drm/xe/xe_wa_oob.rules index a6b897030fde..26066beb4f6f 100644 --- a/drivers/gpu/drm/xe/xe_wa_oob.rules +++ b/drivers/gpu/drm/xe/xe_wa_oob.rules @@ -28,3 +28,4 @@ GRAPHICS_VERSION(2004) 13011645652 GRAPHICS_VERSION(2004) 22019338487 MEDIA_VERSION(2000) + GRAPHICS_VERSION(2001) |