Commit 27aec396 authored by Daniel Vetter's avatar Daniel Vetter

Merge tag 'drm-xe-next-2024-07-02' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next

Driver Changes:
- Fix in migration code (Auld)
- Simplification in HWMon related code (Karthik)
- Fix in forcewake logic (Nirmoy)
- Fix engine utilization information (umesh)
- Clean up on MOCS related code (Roper)
- Fix on multicast register (Roper)
- Fix TLB invalidation timeout (Nirmoy)
- More SRIOV preparation (Michal)
- Fix out-of-bounds array access (Lucas)
- Fixes around some mutex utilization (Ashutosh, Vinay)
- Expand LNL workaround to BMG (Vinay)
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/ZoROvquFrTFhk3Pb@intel.com
parents fb625bf6 aaa08078
...@@ -31,9 +31,9 @@ static int live_mocs_init(struct live_mocs *arg, struct xe_gt *gt) ...@@ -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 %d", gt->info.id);
kunit_info(test, "gt type %d", gt->info.type); 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 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; return flags;
} }
...@@ -50,7 +50,7 @@ static void read_l3cc_table(struct xe_gt *gt, ...@@ -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); ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
KUNIT_ASSERT_EQ_MSG(test, ret, 0, "Forcewake Failed.\n"); 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 (!(i & 1)) {
if (regs_are_mcr(gt)) if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i >> 1)); 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, ...@@ -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); ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
KUNIT_ASSERT_EQ_MSG(test, ret, 0, "Forcewake Failed.\n"); 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)) if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i)); reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
else else
......
...@@ -260,13 +260,20 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file) ...@@ -260,13 +260,20 @@ static void show_run_ticks(struct drm_printer *p, struct drm_file *file)
/* Get the total GPU cycles */ /* Get the total GPU cycles */
for_each_gt(gt, xe, gt_id) { for_each_gt(gt, xe, gt_id) {
enum xe_force_wake_domains fw;
hwe = xe_gt_any_hw_engine(gt); hwe = xe_gt_any_hw_engine(gt);
if (!hwe) if (!hwe)
continue; 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); 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; break;
} }
......
...@@ -74,6 +74,9 @@ static unsigned int probe_gsm_size(struct pci_dev *pdev) ...@@ -74,6 +74,9 @@ static unsigned int probe_gsm_size(struct pci_dev *pdev)
static void ggtt_update_access_counter(struct xe_ggtt *ggtt) 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 * 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. * 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) ...@@ -81,8 +84,8 @@ static void ggtt_update_access_counter(struct xe_ggtt *ggtt)
*/ */
lockdep_assert_held(&ggtt->lock); lockdep_assert_held(&ggtt->lock);
if ((++ggtt->access_count % 63) == 0) { if ((++ggtt->access_count % max_gtt_writes) == 0) {
xe_mmio_write32(ggtt->tile->media_gt, GMD_ID, 0x0); xe_mmio_write32(gt, GMD_ID, 0x0);
ggtt->access_count = 0; ggtt->access_count = 0;
} }
} }
...@@ -218,7 +221,9 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt) ...@@ -218,7 +221,9 @@ int xe_ggtt_init_early(struct xe_ggtt *ggtt)
ggtt->size = GUC_GGTT_TOP; ggtt->size = GUC_GGTT_TOP;
if (GRAPHICS_VERx100(xe) >= 1270) 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; &xelpg_pt_wa_ops : &xelpg_pt_ops;
else else
ggtt->pt_ops = &xelp_pt_ops; ggtt->pt_ops = &xelp_pt_ops;
......
...@@ -683,6 +683,9 @@ static int do_gt_restart(struct xe_gt *gt) ...@@ -683,6 +683,9 @@ static int do_gt_restart(struct xe_gt *gt)
/* Restore GT freq to expected values */ /* Restore GT freq to expected values */
xe_gt_sanitize_freq(gt); xe_gt_sanitize_freq(gt);
if (IS_SRIOV_PF(gt_to_xe(gt)))
xe_gt_sriov_pf_restart(gt);
return 0; return 0;
} }
...@@ -818,8 +821,7 @@ int xe_gt_sanitize_freq(struct xe_gt *gt) ...@@ -818,8 +821,7 @@ int xe_gt_sanitize_freq(struct xe_gt *gt)
int ret = 0; int ret = 0;
if ((!xe_uc_fw_is_available(&gt->uc.gsc.fw) || if ((!xe_uc_fw_is_available(&gt->uc.gsc.fw) ||
xe_uc_fw_is_loaded(&gt->uc.gsc.fw)) && xe_uc_fw_is_loaded(&gt->uc.gsc.fw)) && XE_WA(gt, 22019338487))
XE_WA(gt, 22019338487))
ret = xe_guc_pc_restore_stashed_freq(&gt->uc.guc.pc); ret = xe_guc_pc_restore_stashed_freq(&gt->uc.guc.pc);
return ret; return ret;
......
...@@ -342,7 +342,7 @@ static void init_steering_oaddrm(struct xe_gt *gt) ...@@ -342,7 +342,7 @@ static void init_steering_oaddrm(struct xe_gt *gt)
else else
gt->steering[OADDRM].group_target = 1; 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) static void init_steering_sqidi_psmi(struct xe_gt *gt)
...@@ -357,8 +357,8 @@ 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) static void init_steering_inst0(struct xe_gt *gt)
{ {
gt->steering[DSS].group_target = 0; /* unused */ gt->steering[INSTANCE0].group_target = 0; /* unused */
gt->steering[DSS].instance_target = 0; /* unused */ gt->steering[INSTANCE0].instance_target = 0; /* unused */
} }
static const struct { static const struct {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "regs/xe_sriov_regs.h" #include "regs/xe_sriov_regs.h"
#include "xe_gt_sriov_pf.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_helpers.h"
#include "xe_gt_sriov_pf_service.h" #include "xe_gt_sriov_pf_service.h"
#include "xe_mmio.h" #include "xe_mmio.h"
...@@ -82,3 +83,14 @@ void xe_gt_sriov_pf_init_hw(struct xe_gt *gt) ...@@ -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_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);
}
...@@ -11,6 +11,7 @@ struct xe_gt; ...@@ -11,6 +11,7 @@ struct xe_gt;
#ifdef CONFIG_PCI_IOV #ifdef CONFIG_PCI_IOV
int xe_gt_sriov_pf_init_early(struct xe_gt *gt); 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_init_hw(struct xe_gt *gt);
void xe_gt_sriov_pf_restart(struct xe_gt *gt);
#else #else
static inline int xe_gt_sriov_pf_init_early(struct xe_gt *gt) 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) ...@@ -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_init_hw(struct xe_gt *gt)
{ {
} }
static inline void xe_gt_sriov_pf_restart(struct xe_gt *gt)
{
}
#endif #endif
#endif #endif
...@@ -1922,6 +1922,84 @@ int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsigned int vfid, bool refresh ...@@ -1922,6 +1922,84 @@ int xe_gt_sriov_pf_config_push(struct xe_gt *gt, unsigned int vfid, bool refresh
return err; 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. * xe_gt_sriov_pf_config_print_ggtt - Print GGTT configurations.
* @gt: the &xe_gt * @gt: the &xe_gt
......
...@@ -53,6 +53,10 @@ int xe_gt_sriov_pf_config_set_fair(struct xe_gt *gt, unsigned int vfid, unsigned ...@@ -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_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); 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_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_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); int xe_gt_sriov_pf_config_print_dbs(struct xe_gt *gt, struct drm_printer *p);
......
...@@ -17,7 +17,22 @@ ...@@ -17,7 +17,22 @@
#include "xe_trace.h" #include "xe_trace.h"
#include "regs/xe_guc_regs.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(&gt->uc.guc.ct);
return hw_tlb_timeout + 2 * delay;
}
static void xe_gt_tlb_fence_timeout(struct work_struct *work) 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) ...@@ -32,7 +47,7 @@ static void xe_gt_tlb_fence_timeout(struct work_struct *work)
s64 since_inval_ms = ktime_ms_delta(ktime_get(), s64 since_inval_ms = ktime_ms_delta(ktime_get(),
fence->invalidation_time); fence->invalidation_time);
if (msecs_to_jiffies(since_inval_ms) < TLB_TIMEOUT) if (msecs_to_jiffies(since_inval_ms) < tlb_timeout_jiffies(gt))
break; break;
trace_xe_gt_tlb_invalidation_fence_timeout(xe, fence); trace_xe_gt_tlb_invalidation_fence_timeout(xe, fence);
...@@ -47,7 +62,7 @@ static void xe_gt_tlb_fence_timeout(struct work_struct *work) ...@@ -47,7 +62,7 @@ static void xe_gt_tlb_fence_timeout(struct work_struct *work)
if (!list_empty(&gt->tlb_invalidation.pending_fences)) if (!list_empty(&gt->tlb_invalidation.pending_fences))
queue_delayed_work(system_wq, queue_delayed_work(system_wq,
&gt->tlb_invalidation.fence_tdr, &gt->tlb_invalidation.fence_tdr,
TLB_TIMEOUT); tlb_timeout_jiffies(gt));
spin_unlock_irq(&gt->tlb_invalidation.pending_lock); spin_unlock_irq(&gt->tlb_invalidation.pending_lock);
} }
...@@ -183,7 +198,7 @@ static int send_tlb_invalidation(struct xe_guc *guc, ...@@ -183,7 +198,7 @@ static int send_tlb_invalidation(struct xe_guc *guc,
if (list_is_singular(&gt->tlb_invalidation.pending_fences)) if (list_is_singular(&gt->tlb_invalidation.pending_fences))
queue_delayed_work(system_wq, queue_delayed_work(system_wq,
&gt->tlb_invalidation.fence_tdr, &gt->tlb_invalidation.fence_tdr,
TLB_TIMEOUT); tlb_timeout_jiffies(gt));
} }
spin_unlock_irq(&gt->tlb_invalidation.pending_lock); spin_unlock_irq(&gt->tlb_invalidation.pending_lock);
} else if (ret < 0 && fence) { } else if (ret < 0 && fence) {
...@@ -390,8 +405,7 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt, ...@@ -390,8 +405,7 @@ int xe_gt_tlb_invalidation_vma(struct xe_gt *gt,
* @gt: graphics tile * @gt: graphics tile
* @seqno: seqno to wait which was returned from xe_gt_tlb_invalidation * @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 * Wait for tlb_timeout_jiffies() for a TLB invalidation to complete.
* should receive the TLB invalidation within 200ms.
* *
* Return: 0 on success, -ETIME on TLB invalidation timeout * 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) ...@@ -410,7 +424,7 @@ int xe_gt_tlb_invalidation_wait(struct xe_gt *gt, int seqno)
*/ */
ret = wait_event_timeout(guc->ct.wq, ret = wait_event_timeout(guc->ct.wq,
tlb_invalidation_seqno_past(gt, seqno), tlb_invalidation_seqno_past(gt, seqno),
TLB_TIMEOUT); tlb_timeout_jiffies(gt));
if (!ret) { if (!ret) {
struct drm_printer p = xe_gt_err_printer(gt); 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) ...@@ -486,7 +500,7 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
if (!list_empty(&gt->tlb_invalidation.pending_fences)) if (!list_empty(&gt->tlb_invalidation.pending_fences))
mod_delayed_work(system_wq, mod_delayed_work(system_wq,
&gt->tlb_invalidation.fence_tdr, &gt->tlb_invalidation.fence_tdr,
TLB_TIMEOUT); tlb_timeout_jiffies(gt));
else else
cancel_delayed_work(&gt->tlb_invalidation.fence_tdr); cancel_delayed_work(&gt->tlb_invalidation.fence_tdr);
......
...@@ -112,6 +112,23 @@ ct_to_xe(struct xe_guc_ct *ct) ...@@ -112,6 +112,23 @@ ct_to_xe(struct xe_guc_ct *ct)
#define CTB_G2H_BUFFER_SIZE (4 * CTB_H2G_BUFFER_SIZE) #define CTB_G2H_BUFFER_SIZE (4 * CTB_H2G_BUFFER_SIZE)
#define G2H_ROOM_BUFFER_SIZE (CTB_G2H_BUFFER_SIZE / 4) #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) static size_t guc_ct_size(void)
{ {
return 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE + return 2 * CTB_DESC_SIZE + CTB_H2G_BUFFER_SIZE +
......
...@@ -64,4 +64,6 @@ xe_guc_ct_send_block_no_fail(struct xe_guc_ct *ct, const u32 *action, u32 len) ...@@ -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); 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 #endif
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "xe_mmio.h" #include "xe_mmio.h"
#include "xe_pcode.h" #include "xe_pcode.h"
#include "xe_pm.h" #include "xe_pm.h"
#include "xe_sriov.h"
#include "xe_wa.h" #include "xe_wa.h"
#define MCHBAR_MIRROR_BASE_SNB 0x140000 #define MCHBAR_MIRROR_BASE_SNB 0x140000
...@@ -45,6 +46,7 @@ ...@@ -45,6 +46,7 @@
#define GT_FREQUENCY_SCALER 3 #define GT_FREQUENCY_SCALER 3
#define LNL_MERT_FREQ_CAP 800 #define LNL_MERT_FREQ_CAP 800
#define BMG_MERT_FREQ_CAP 2133
/** /**
* DOC: GuC Power Conservation (PC) * DOC: GuC Power Conservation (PC)
...@@ -703,10 +705,14 @@ static u32 pc_max_freq_cap(struct xe_guc_pc *pc) ...@@ -703,10 +705,14 @@ static u32 pc_max_freq_cap(struct xe_guc_pc *pc)
{ {
struct xe_gt *gt = pc_to_gt(pc); struct xe_gt *gt = pc_to_gt(pc);
if (XE_WA(gt, 22019338487)) if (XE_WA(gt, 22019338487)) {
return min(LNL_MERT_FREQ_CAP, pc->rp0_freq); if (xe_gt_is_media_type(gt))
else return min(LNL_MERT_FREQ_CAP, pc->rp0_freq);
else
return min(BMG_MERT_FREQ_CAP, pc->rp0_freq);
} else {
return pc->rp0_freq; return pc->rp0_freq;
}
} }
/** /**
...@@ -825,6 +831,9 @@ int xe_guc_pc_restore_stashed_freq(struct xe_guc_pc *pc) ...@@ -825,6 +831,9 @@ int xe_guc_pc_restore_stashed_freq(struct xe_guc_pc *pc)
{ {
int ret = 0; 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); mutex_lock(&pc->freq_lock);
ret = pc_set_max_freq(pc, pc->stashed_max_freq); ret = pc_set_max_freq(pc, pc->stashed_max_freq);
if (!ret) if (!ret)
......
...@@ -1130,3 +1130,8 @@ u64 xe_hw_engine_read_timestamp(struct xe_hw_engine *hwe) ...@@ -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)); 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;
}
...@@ -69,5 +69,6 @@ static inline bool xe_hw_engine_is_valid(struct xe_hw_engine *hwe) ...@@ -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); const char *xe_hw_engine_class_to_str(enum xe_engine_class class);
u64 xe_hw_engine_read_timestamp(struct xe_hw_engine *hwe); 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 #endif
...@@ -137,34 +137,6 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg ...@@ -137,34 +137,6 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg
return XE_REG(0); 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(&gt_to_xe(hwmon->gt)->drm, "Invalid xe hwmon reg operation: %d\n",
operation);
break;
}
}
#define PL1_DISABLE 0 #define PL1_DISABLE 0
/* /*
...@@ -176,10 +148,25 @@ static void xe_hwmon_process_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg hwmon ...@@ -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) static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, int channel, long *value)
{ {
u64 reg_val, min, max; 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); mutex_lock(&hwmon->hwmon_lock);
xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_READ32, &reg_val, 0, 0, channel); reg_val = xe_mmio_read32(hwmon->gt, rapl_limit);
/* Check if PL1 limit is disabled */ /* Check if PL1 limit is disabled */
if (!(reg_val & PKG_PWR_LIM_1_EN)) { if (!(reg_val & PKG_PWR_LIM_1_EN)) {
*value = PL1_DISABLE; *value = PL1_DISABLE;
...@@ -189,7 +176,7 @@ static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, int channel, long *v ...@@ -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); reg_val = REG_FIELD_GET(PKG_PWR_LIM_1, reg_val);
*value = mul_u64_u32_shr(reg_val, SF_POWER, hwmon->scl_shift_power); *value = mul_u64_u32_shr(reg_val, SF_POWER, hwmon->scl_shift_power);
xe_hwmon_process_reg(hwmon, REG_PKG_POWER_SKU, REG_READ64, &reg_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 = REG_FIELD_GET(PKG_MIN_PWR, reg_val);
min = mul_u64_u32_shr(min, SF_POWER, hwmon->scl_shift_power); min = mul_u64_u32_shr(min, SF_POWER, hwmon->scl_shift_power);
max = REG_FIELD_GET(PKG_MAX_PWR, reg_val); 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 ...@@ -205,16 +192,16 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long va
{ {
int ret = 0; int ret = 0;
u64 reg_val; 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); mutex_lock(&hwmon->hwmon_lock);
/* Disable PL1 limit and verify, as limit cannot be disabled on all platforms */ /* Disable PL1 limit and verify, as limit cannot be disabled on all platforms */
if (value == PL1_DISABLE) { if (value == PL1_DISABLE) {
xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_RMW32, &reg_val, reg_val = xe_mmio_rmw32(hwmon->gt, rapl_limit, PKG_PWR_LIM_1_EN, 0);
PKG_PWR_LIM_1_EN, 0, channel); reg_val = xe_mmio_read32(hwmon->gt, rapl_limit);
xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_READ32, &reg_val,
PKG_PWR_LIM_1_EN, 0, channel);
if (reg_val & PKG_PWR_LIM_1_EN) { if (reg_val & PKG_PWR_LIM_1_EN) {
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
goto unlock; goto unlock;
...@@ -224,9 +211,8 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long va ...@@ -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. */ /* 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 = 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 = 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, &reg_val,
PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, reg_val, channel);
unlock: unlock:
mutex_unlock(&hwmon->hwmon_lock); mutex_unlock(&hwmon->hwmon_lock);
return ret; return ret;
...@@ -234,9 +220,15 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long va ...@@ -234,9 +220,15 @@ static int xe_hwmon_power_max_write(struct xe_hwmon *hwmon, int channel, long va
static void xe_hwmon_power_rated_max_read(struct xe_hwmon *hwmon, int channel, long *value) 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; u64 reg_val;
xe_hwmon_process_reg(hwmon, REG_PKG_POWER_SKU, REG_READ32, &reg_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); reg_val = REG_FIELD_GET(PKG_TDP, reg_val);
*value = mul_u64_u32_shr(reg_val, SF_POWER, hwmon->scl_shift_power); *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) ...@@ -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]; struct xe_hwmon_energy_info *ei = &hwmon->ei[channel];
u64 reg_val; u64 reg_val;
xe_hwmon_process_reg(hwmon, REG_PKG_ENERGY_STATUS, REG_READ32, reg_val = xe_mmio_read32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_PKG_ENERGY_STATUS,
&reg_val, 0, 0, channel); channel));
if (reg_val >= ei->reg_val_prev) if (reg_val >= ei->reg_val_prev)
ei->accum_energy += 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 ...@@ -294,8 +286,7 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at
mutex_lock(&hwmon->hwmon_lock); mutex_lock(&hwmon->hwmon_lock);
xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, r = xe_mmio_read32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, sensor_index));
REG_READ32, &r, 0, 0, sensor_index);
mutex_unlock(&hwmon->hwmon_lock); mutex_unlock(&hwmon->hwmon_lock);
...@@ -383,8 +374,8 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a ...@@ -383,8 +374,8 @@ xe_hwmon_power_max_interval_store(struct device *dev, struct device_attribute *a
mutex_lock(&hwmon->hwmon_lock); mutex_lock(&hwmon->hwmon_lock);
xe_hwmon_process_reg(hwmon, REG_PKG_RAPL_LIMIT, REG_RMW32, (u64 *)&r, r = xe_mmio_rmw32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, sensor_index),
PKG_PWR_LIM_1_TIME, rxy, sensor_index); PKG_PWR_LIM_1_TIME, rxy);
mutex_unlock(&hwmon->hwmon_lock); mutex_unlock(&hwmon->hwmon_lock);
...@@ -499,8 +490,7 @@ static void xe_hwmon_get_voltage(struct xe_hwmon *hwmon, int channel, long *valu ...@@ -499,8 +490,7 @@ static void xe_hwmon_get_voltage(struct xe_hwmon *hwmon, int channel, long *valu
{ {
u64 reg_val; u64 reg_val;
xe_hwmon_process_reg(hwmon, REG_GT_PERF_STATUS, reg_val = xe_mmio_read32(hwmon->gt, xe_hwmon_get_reg(hwmon, REG_GT_PERF_STATUS, channel));
REG_READ32, &reg_val, 0, 0, channel);
/* HW register value in units of 2.5 millivolt */ /* HW register value in units of 2.5 millivolt */
*value = DIV_ROUND_CLOSEST(REG_FIELD_GET(VOLTAGE_MASK, reg_val) * 2500, SF_VOLTAGE); *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) ...@@ -784,14 +774,15 @@ xe_hwmon_get_preregistration_info(struct xe_device *xe)
long energy; long energy;
u64 val_sku_unit = 0; u64 val_sku_unit = 0;
int channel; int channel;
struct xe_reg pkg_power_sku_unit;
/* /*
* The contents of register PKG_POWER_SKU_UNIT do not change, * The contents of register PKG_POWER_SKU_UNIT do not change,
* so read it once and store the shift values. * 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))) { pkg_power_sku_unit = xe_hwmon_get_reg(hwmon, REG_PKG_POWER_SKU_UNIT, 0);
xe_hwmon_process_reg(hwmon, REG_PKG_POWER_SKU_UNIT, if (xe_reg_is_valid(pkg_power_sku_unit)) {
REG_READ32, &val_sku_unit, 0, 0, 0); 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_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_energy = REG_FIELD_GET(PKG_ENERGY_UNIT, val_sku_unit);
hwmon->scl_shift_time = REG_FIELD_GET(PKG_TIME_UNIT, val_sku_unit); hwmon->scl_shift_time = REG_FIELD_GET(PKG_TIME_UNIT, val_sku_unit);
......
...@@ -1358,7 +1358,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m, ...@@ -1358,7 +1358,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
GFP_KERNEL, true, 0); GFP_KERNEL, true, 0);
if (IS_ERR(sa_bo)) { if (IS_ERR(sa_bo)) {
err = PTR_ERR(sa_bo); err = PTR_ERR(sa_bo);
goto err; goto err_bb;
} }
ppgtt_ofs = NUM_KERNEL_PDE + ppgtt_ofs = NUM_KERNEL_PDE +
...@@ -1406,7 +1406,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m, ...@@ -1406,7 +1406,7 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
update_idx); update_idx);
if (IS_ERR(job)) { if (IS_ERR(job)) {
err = PTR_ERR(job); err = PTR_ERR(job);
goto err_bb; goto err_sa;
} }
/* Wait on BO move */ /* Wait on BO move */
...@@ -1458,10 +1458,10 @@ xe_migrate_update_pgtables(struct xe_migrate *m, ...@@ -1458,10 +1458,10 @@ xe_migrate_update_pgtables(struct xe_migrate *m,
err_job: err_job:
xe_sched_job_put(job); xe_sched_job_put(job);
err_sa:
drm_suballoc_free(sa_bo, NULL);
err_bb: err_bb:
xe_bb_free(bb, NULL); xe_bb_free(bb, NULL);
err:
drm_suballoc_free(sa_bo, NULL);
return ERR_PTR(err); return ERR_PTR(err);
} }
......
...@@ -47,8 +47,16 @@ struct xe_mocs_ops { ...@@ -47,8 +47,16 @@ struct xe_mocs_ops {
}; };
struct xe_mocs_info { 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_entry *table;
const struct xe_mocs_ops *ops; const struct xe_mocs_ops *ops;
u8 uc_index; u8 uc_index;
...@@ -266,7 +274,7 @@ static void xelp_lncf_dump(struct xe_mocs_info *info, struct xe_gt *gt, struct d ...@@ -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"); 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)) if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i)); reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
else else
...@@ -298,7 +306,7 @@ static void xelp_mocs_dump(struct xe_mocs_info *info, unsigned int flags, ...@@ -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, "Global mocs table configuration:\n");
drm_printf(p, "GLOB_MOCS[idx] = [LeCC, TC, LRUM, AOM, RSC, SCC, PFM, SCF, CoS, SSE] (value)\n\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)) if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i)); reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
else else
...@@ -371,7 +379,7 @@ static void xehp_lncf_dump(struct xe_mocs_info *info, unsigned int flags, ...@@ -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"); 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)) if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i)); reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
else else
...@@ -416,7 +424,7 @@ static void pvc_mocs_dump(struct xe_mocs_info *info, unsigned int flags, struct ...@@ -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"); 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)) if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i)); reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_LNCFCMOCS(i));
else else
...@@ -498,7 +506,7 @@ static void mtl_mocs_dump(struct xe_mocs_info *info, unsigned int flags, ...@@ -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, "Global mocs table configuration:\n");
drm_printf(p, "GLOB_MOCS[idx] = [IG_PAT, L4_CACHE_POLICY] (value)\n\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)) if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i)); reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
else else
...@@ -541,7 +549,7 @@ static void xe2_mocs_dump(struct xe_mocs_info *info, unsigned int flags, ...@@ -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, "Global mocs table configuration:\n");
drm_printf(p, "GLOB_MOCS[idx] = [IG_PAT, L3_CLOS, L3_CACHE_POLICY, L4_CACHE_POLICY] (value)\n\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)) if (regs_are_mcr(gt))
reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i)); reg_val = xe_gt_mcr_unicast_read_any(gt, XEHP_GLOBAL_MOCS(i));
else else
...@@ -571,48 +579,48 @@ static unsigned int get_mocs_settings(struct xe_device *xe, ...@@ -571,48 +579,48 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
case XE_LUNARLAKE: case XE_LUNARLAKE:
case XE_BATTLEMAGE: case XE_BATTLEMAGE:
info->ops = &xe2_mocs_ops; 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->table = xe2_mocs_table;
info->n_entries = XE2_NUM_MOCS_ENTRIES; info->num_mocs_regs = XE2_NUM_MOCS_ENTRIES;
info->uc_index = 3; info->uc_index = 3;
info->wb_index = 4; info->wb_index = 4;
info->unused_entries_index = 4; info->unused_entries_index = 4;
break; break;
case XE_PVC: case XE_PVC:
info->ops = &pvc_mocs_ops; 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->table = pvc_mocs_desc;
info->n_entries = PVC_NUM_MOCS_ENTRIES; info->num_mocs_regs = PVC_NUM_MOCS_ENTRIES;
info->uc_index = 1; info->uc_index = 1;
info->wb_index = 2; info->wb_index = 2;
info->unused_entries_index = 2; info->unused_entries_index = 2;
break; break;
case XE_METEORLAKE: case XE_METEORLAKE:
info->ops = &mtl_mocs_ops; 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->table = mtl_mocs_desc;
info->n_entries = MTL_NUM_MOCS_ENTRIES; info->num_mocs_regs = MTL_NUM_MOCS_ENTRIES;
info->uc_index = 9; info->uc_index = 9;
info->unused_entries_index = 1; info->unused_entries_index = 1;
break; break;
case XE_DG2: case XE_DG2:
info->ops = &xehp_mocs_ops; 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->table = dg2_mocs_desc;
info->uc_index = 1; info->uc_index = 1;
/* /*
* Last entry is RO on hardware, don't bother with what was * Last entry is RO on hardware, don't bother with what was
* written when checking later * 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; info->unused_entries_index = 3;
break; break;
case XE_DG1: case XE_DG1:
info->ops = &xelp_mocs_ops; 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->table = dg1_mocs_desc;
info->uc_index = 1; info->uc_index = 1;
info->n_entries = XELP_NUM_MOCS_ENTRIES; info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES;
info->unused_entries_index = 5; info->unused_entries_index = 5;
break; break;
case XE_TIGERLAKE: case XE_TIGERLAKE:
...@@ -621,9 +629,9 @@ static unsigned int get_mocs_settings(struct xe_device *xe, ...@@ -621,9 +629,9 @@ static unsigned int get_mocs_settings(struct xe_device *xe,
case XE_ALDERLAKE_P: case XE_ALDERLAKE_P:
case XE_ALDERLAKE_N: case XE_ALDERLAKE_N:
info->ops = &xelp_mocs_ops; 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->table = gen12_mocs_desc;
info->n_entries = XELP_NUM_MOCS_ENTRIES; info->num_mocs_regs = XELP_NUM_MOCS_ENTRIES;
info->uc_index = 3; info->uc_index = 3;
info->unused_entries_index = 2; info->unused_entries_index = 2;
break; break;
...@@ -642,12 +650,8 @@ static unsigned int get_mocs_settings(struct xe_device *xe, ...@@ -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->unused_entries_index != 0);
xe_assert(xe, !info->ops || info->ops->dump); xe_assert(xe, info->ops && info->ops->dump);
xe_assert(xe, info->table_size <= info->num_mocs_regs);
if (XE_WARN_ON(info->size > info->n_entries)) {
info->table = NULL;
return 0;
}
if (!IS_DGFX(xe) || GRAPHICS_VER(xe) >= 20) if (!IS_DGFX(xe) || GRAPHICS_VER(xe) >= 20)
flags |= HAS_GLOBAL_MOCS; flags |= HAS_GLOBAL_MOCS;
...@@ -664,7 +668,7 @@ static unsigned int get_mocs_settings(struct xe_device *xe, ...@@ -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, static u32 get_entry_control(const struct xe_mocs_info *info,
unsigned int index) 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[index].control_value;
return info->table[info->unused_entries_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, ...@@ -675,12 +679,9 @@ static void __init_mocs_table(struct xe_gt *gt,
unsigned int i; unsigned int i;
u32 mocs; u32 mocs;
xe_gt_WARN_ONCE(gt, !info->unused_entries_index, mocs_dbg(gt, "mocs entries: %d\n", info->num_mocs_regs);
"Unused entries index should have been defined\n");
mocs_dbg(gt, "mocs entries: %d\n", info->n_entries);
for (i = 0; i < info->n_entries; i++) { for (i = 0; i < info->num_mocs_regs; i++) {
mocs = get_entry_control(info, i); mocs = get_entry_control(info, i);
mocs_dbg(gt, "GLOB_MOCS[%d] 0x%x 0x%x\n", 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, ...@@ -701,7 +702,7 @@ static void __init_mocs_table(struct xe_gt *gt,
static u16 get_entry_l3cc(const struct xe_mocs_info *info, static u16 get_entry_l3cc(const struct xe_mocs_info *info,
unsigned int index) 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[index].l3cc_value;
return info->table[info->unused_entries_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, ...@@ -717,9 +718,9 @@ static void init_l3cc_table(struct xe_gt *gt,
unsigned int i; unsigned int i;
u32 l3cc; 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), l3cc = l3cc_combine(get_entry_l3cc(info, 2 * i),
get_entry_l3cc(info, 2 * i + 1)); get_entry_l3cc(info, 2 * i + 1));
...@@ -779,9 +780,6 @@ void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p) ...@@ -779,9 +780,6 @@ void xe_mocs_dump(struct xe_gt *gt, struct drm_printer *p)
flags = get_mocs_settings(xe, &table); flags = get_mocs_settings(xe, &table);
if (!table.ops->dump)
return;
xe_pm_runtime_get_noresume(xe); xe_pm_runtime_get_noresume(xe);
ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT); ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
......
...@@ -824,6 +824,8 @@ static void xe_oa_stream_destroy(struct xe_oa_stream *stream) ...@@ -824,6 +824,8 @@ static void xe_oa_stream_destroy(struct xe_oa_stream *stream)
WRITE_ONCE(u->exclusive_stream, NULL); WRITE_ONCE(u->exclusive_stream, NULL);
mutex_destroy(&stream->stream_lock);
xe_oa_disable_metric_set(stream); xe_oa_disable_metric_set(stream);
xe_exec_queue_put(stream->k_exec_q); xe_exec_queue_put(stream->k_exec_q);
......
...@@ -748,10 +748,8 @@ static void xe_pci_remove(struct pci_dev *pdev) ...@@ -748,10 +748,8 @@ static void xe_pci_remove(struct pci_dev *pdev)
if (!xe) /* driver load aborted, nothing to cleanup */ if (!xe) /* driver load aborted, nothing to cleanup */
return; return;
#ifdef CONFIG_PCI_IOV
if (IS_SRIOV_PF(xe)) if (IS_SRIOV_PF(xe))
xe_pci_sriov_configure(pdev, 0); xe_pci_sriov_configure(pdev, 0);
#endif
xe_device_remove(xe); xe_device_remove(xe);
xe_pm_runtime_fini(xe); xe_pm_runtime_fini(xe);
...@@ -1009,9 +1007,7 @@ static struct pci_driver xe_pci_driver = { ...@@ -1009,9 +1007,7 @@ static struct pci_driver xe_pci_driver = {
.probe = xe_pci_probe, .probe = xe_pci_probe,
.remove = xe_pci_remove, .remove = xe_pci_remove,
.shutdown = xe_pci_shutdown, .shutdown = xe_pci_shutdown,
#ifdef CONFIG_PCI_IOV
.sriov_configure = xe_pci_sriov_configure, .sriov_configure = xe_pci_sriov_configure,
#endif
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
.driver.pm = &xe_pm_ops, .driver.pm = &xe_pm_ops,
#endif #endif
......
...@@ -13,6 +13,17 @@ ...@@ -13,6 +13,17 @@
#include "xe_sriov_pf_helpers.h" #include "xe_sriov_pf_helpers.h"
#include "xe_sriov_printk.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) static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)
{ {
struct xe_gt *gt; struct xe_gt *gt;
...@@ -20,6 +31,8 @@ static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) ...@@ -20,6 +31,8 @@ static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)
int result = 0, err; int result = 0, err;
for_each_gt(gt, xe, id) { 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); err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs);
result = result ?: err; result = result ?: err;
} }
......
...@@ -8,6 +8,13 @@ ...@@ -8,6 +8,13 @@
struct pci_dev; struct pci_dev;
#ifdef CONFIG_PCI_IOV
int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs); 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 #endif
...@@ -121,7 +121,7 @@ static bool rule_matches(const struct xe_device *xe, ...@@ -121,7 +121,7 @@ static bool rule_matches(const struct xe_device *xe,
* Advance rules until we find XE_RTP_MATCH_OR to check * Advance rules until we find XE_RTP_MATCH_OR to check
* if there's another set of conditions 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) if (i >= n_rules)
......
...@@ -28,3 +28,4 @@ ...@@ -28,3 +28,4 @@
GRAPHICS_VERSION(2004) GRAPHICS_VERSION(2004)
13011645652 GRAPHICS_VERSION(2004) 13011645652 GRAPHICS_VERSION(2004)
22019338487 MEDIA_VERSION(2000) 22019338487 MEDIA_VERSION(2000)
GRAPHICS_VERSION(2001)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment