mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-07 08:03:00 -04:00
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: Daniel Vetter <daniel.vetter@ffwll.ch> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/ZoROvquFrTFhk3Pb@intel.com
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 +
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 @@ 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)
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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->num_mocs_regs);
|
||||
|
||||
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_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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -28,3 +28,4 @@
|
||||
GRAPHICS_VERSION(2004)
|
||||
13011645652 GRAPHICS_VERSION(2004)
|
||||
22019338487 MEDIA_VERSION(2000)
|
||||
GRAPHICS_VERSION(2001)
|
||||
|
||||
Reference in New Issue
Block a user