mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 19:43:40 +02:00
- Release kobject for the failure path (Shuicheng)
- SRIOV PF: Drop rounddown_pow_of_two fair (Michal) - Remove type casting on hwmon (Mallesh) - Defer free of NVM auxiliary container to device release (Nitin) - Fix a NULL vs IS_ERR (Dan) - Add cleanup action in xe_device_sysfs_init (Zongyao) - Fix error handling if PXP fails to start (Daniele) - Set GuC RCS/CCS yield policy (Daniele) -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEbSBwaO7dZQkcLOKj+mJfZA7rE8oFAmjMC1kACgkQ+mJfZA7r E8rpPQf/YkotrWDTSbbH7Lq3EJfpksC4mAOzVKQCbAwUsllhnSYhrJJuL9mg21yf kEj767DcQUP+J4EXvu2nCsBTA2prSQQfaPbwHiDOU2+tZjuH0ii7ww8BRSdClejv KIy9iKzwOAlmuw4bv1LTfTdO1+wNOM3BF6XNrxfDeVDH5+qvB50CZbNsuitduB1B vbVdh6d4xYoKB7VEAD6fKJDpdg4YxA7EtfrI+qAkFTka9VttwcepVPVLhtJM0xzO 09n/ZysiOMIoBKKmC9SAAeHguhuk8vlQDBsosnK0jHB/icBbTeu4UcHmBH5ODb+D dV6v3XPhxnT5AVsud7ebosiojQZLjg== =YlAg -----END PGP SIGNATURE----- Merge tag 'drm-xe-fixes-2025-09-18' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-fixes - Release kobject for the failure path (Shuicheng) - SRIOV PF: Drop rounddown_pow_of_two fair (Michal) - Remove type casting on hwmon (Mallesh) - Defer free of NVM auxiliary container to device release (Nitin) - Fix a NULL vs IS_ERR (Dan) - Add cleanup action in xe_device_sysfs_init (Zongyao) - Fix error handling if PXP fails to start (Daniele) - Set GuC RCS/CCS yield policy (Daniele) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://lore.kernel.org/r/aMwL7vxFP1L94IML@intel.com
This commit is contained in:
commit
b55caa69c5
|
|
@ -117,6 +117,7 @@ enum xe_guc_action {
|
|||
XE_GUC_ACTION_ENTER_S_STATE = 0x501,
|
||||
XE_GUC_ACTION_EXIT_S_STATE = 0x502,
|
||||
XE_GUC_ACTION_GLOBAL_SCHED_POLICY_CHANGE = 0x506,
|
||||
XE_GUC_ACTION_UPDATE_SCHEDULING_POLICIES_KLV = 0x509,
|
||||
XE_GUC_ACTION_SCHED_CONTEXT = 0x1000,
|
||||
XE_GUC_ACTION_SCHED_CONTEXT_MODE_SET = 0x1001,
|
||||
XE_GUC_ACTION_SCHED_CONTEXT_MODE_DONE = 0x1002,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
* | 0 | 31:16 | **KEY** - KLV key identifier |
|
||||
* | | | - `GuC Self Config KLVs`_ |
|
||||
* | | | - `GuC Opt In Feature KLVs`_ |
|
||||
* | | | - `GuC Scheduling Policies KLVs`_ |
|
||||
* | | | - `GuC VGT Policy KLVs`_ |
|
||||
* | | | - `GuC VF Configuration KLVs`_ |
|
||||
* | | | |
|
||||
|
|
@ -152,6 +153,30 @@ enum {
|
|||
#define GUC_KLV_OPT_IN_FEATURE_DYNAMIC_INHIBIT_CONTEXT_SWITCH_KEY 0x4003
|
||||
#define GUC_KLV_OPT_IN_FEATURE_DYNAMIC_INHIBIT_CONTEXT_SWITCH_LEN 0u
|
||||
|
||||
/**
|
||||
* DOC: GuC Scheduling Policies KLVs
|
||||
*
|
||||
* `GuC KLV`_ keys available for use with UPDATE_SCHEDULING_POLICIES_KLV.
|
||||
*
|
||||
* _`GUC_KLV_SCHEDULING_POLICIES_RENDER_COMPUTE_YIELD` : 0x1001
|
||||
* Some platforms do not allow concurrent execution of RCS and CCS
|
||||
* workloads from different address spaces. By default, the GuC prioritizes
|
||||
* RCS submissions over CCS ones, which can lead to CCS workloads being
|
||||
* significantly (or completely) starved of execution time. This KLV allows
|
||||
* the driver to specify a quantum (in ms) and a ratio (percentage value
|
||||
* between 0 and 100), and the GuC will prioritize the CCS for that
|
||||
* percentage of each quantum. For example, specifying 100ms and 30% will
|
||||
* make the GuC prioritize the CCS for 30ms of every 100ms.
|
||||
* Note that this does not necessarly mean that RCS and CCS engines will
|
||||
* only be active for their percentage of the quantum, as the restriction
|
||||
* only kicks in if both classes are fully busy with non-compatible address
|
||||
* spaces; i.e., if one engine is idle or running the same address space,
|
||||
* a pending job on the other engine will still be submitted to the HW no
|
||||
* matter what the ratio is
|
||||
*/
|
||||
#define GUC_KLV_SCHEDULING_POLICIES_RENDER_COMPUTE_YIELD_KEY 0x1001
|
||||
#define GUC_KLV_SCHEDULING_POLICIES_RENDER_COMPUTE_YIELD_LEN 2u
|
||||
|
||||
/**
|
||||
* DOC: GuC VGT Policy KLVs
|
||||
*
|
||||
|
|
|
|||
|
|
@ -311,12 +311,16 @@ int xe_device_sysfs_init(struct xe_device *xe)
|
|||
if (xe->info.platform == XE_BATTLEMAGE) {
|
||||
ret = sysfs_create_files(&dev->kobj, auto_link_downgrade_attrs);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
ret = late_bind_create_files(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return devm_add_action_or_reset(dev, xe_device_sysfs_fini, xe);
|
||||
|
||||
cleanup:
|
||||
xe_device_sysfs_fini(xe);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,6 +151,16 @@ static int __xe_exec_queue_init(struct xe_exec_queue *q)
|
|||
return err;
|
||||
}
|
||||
|
||||
static void __xe_exec_queue_fini(struct xe_exec_queue *q)
|
||||
{
|
||||
int i;
|
||||
|
||||
q->ops->fini(q);
|
||||
|
||||
for (i = 0; i < q->width; ++i)
|
||||
xe_lrc_put(q->lrc[i]);
|
||||
}
|
||||
|
||||
struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *vm,
|
||||
u32 logical_mask, u16 width,
|
||||
struct xe_hw_engine *hwe, u32 flags,
|
||||
|
|
@ -181,11 +191,13 @@ struct xe_exec_queue *xe_exec_queue_create(struct xe_device *xe, struct xe_vm *v
|
|||
if (xe_exec_queue_uses_pxp(q)) {
|
||||
err = xe_pxp_exec_queue_add(xe->pxp, q);
|
||||
if (err)
|
||||
goto err_post_alloc;
|
||||
goto err_post_init;
|
||||
}
|
||||
|
||||
return q;
|
||||
|
||||
err_post_init:
|
||||
__xe_exec_queue_fini(q);
|
||||
err_post_alloc:
|
||||
__xe_exec_queue_free(q);
|
||||
return ERR_PTR(err);
|
||||
|
|
@ -283,13 +295,11 @@ void xe_exec_queue_destroy(struct kref *ref)
|
|||
xe_exec_queue_put(eq);
|
||||
}
|
||||
|
||||
q->ops->fini(q);
|
||||
q->ops->destroy(q);
|
||||
}
|
||||
|
||||
void xe_exec_queue_fini(struct xe_exec_queue *q)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Before releasing our ref to lrc and xef, accumulate our run ticks
|
||||
* and wakeup any waiters.
|
||||
|
|
@ -298,9 +308,7 @@ void xe_exec_queue_fini(struct xe_exec_queue *q)
|
|||
if (q->xef && atomic_dec_and_test(&q->xef->exec_queue.pending_removal))
|
||||
wake_up_var(&q->xef->exec_queue.pending_removal);
|
||||
|
||||
for (i = 0; i < q->width; ++i)
|
||||
xe_lrc_put(q->lrc[i]);
|
||||
|
||||
__xe_exec_queue_fini(q);
|
||||
__xe_exec_queue_free(q);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -166,8 +166,14 @@ struct xe_exec_queue_ops {
|
|||
int (*init)(struct xe_exec_queue *q);
|
||||
/** @kill: Kill inflight submissions for backend */
|
||||
void (*kill)(struct xe_exec_queue *q);
|
||||
/** @fini: Fini exec queue for submission backend */
|
||||
/** @fini: Undoes the init() for submission backend */
|
||||
void (*fini)(struct xe_exec_queue *q);
|
||||
/**
|
||||
* @destroy: Destroy exec queue for submission backend. The backend
|
||||
* function must call xe_exec_queue_fini() (which will in turn call the
|
||||
* fini() backend function) to ensure the queue is properly cleaned up.
|
||||
*/
|
||||
void (*destroy)(struct xe_exec_queue *q);
|
||||
/** @set_priority: Set priority for exec queue */
|
||||
int (*set_priority)(struct xe_exec_queue *q,
|
||||
enum xe_exec_queue_priority priority);
|
||||
|
|
|
|||
|
|
@ -385,10 +385,20 @@ static int execlist_exec_queue_init(struct xe_exec_queue *q)
|
|||
return err;
|
||||
}
|
||||
|
||||
static void execlist_exec_queue_fini_async(struct work_struct *w)
|
||||
static void execlist_exec_queue_fini(struct xe_exec_queue *q)
|
||||
{
|
||||
struct xe_execlist_exec_queue *exl = q->execlist;
|
||||
|
||||
drm_sched_entity_fini(&exl->entity);
|
||||
drm_sched_fini(&exl->sched);
|
||||
|
||||
kfree(exl);
|
||||
}
|
||||
|
||||
static void execlist_exec_queue_destroy_async(struct work_struct *w)
|
||||
{
|
||||
struct xe_execlist_exec_queue *ee =
|
||||
container_of(w, struct xe_execlist_exec_queue, fini_async);
|
||||
container_of(w, struct xe_execlist_exec_queue, destroy_async);
|
||||
struct xe_exec_queue *q = ee->q;
|
||||
struct xe_execlist_exec_queue *exl = q->execlist;
|
||||
struct xe_device *xe = gt_to_xe(q->gt);
|
||||
|
|
@ -401,10 +411,6 @@ static void execlist_exec_queue_fini_async(struct work_struct *w)
|
|||
list_del(&exl->active_link);
|
||||
spin_unlock_irqrestore(&exl->port->lock, flags);
|
||||
|
||||
drm_sched_entity_fini(&exl->entity);
|
||||
drm_sched_fini(&exl->sched);
|
||||
kfree(exl);
|
||||
|
||||
xe_exec_queue_fini(q);
|
||||
}
|
||||
|
||||
|
|
@ -413,10 +419,10 @@ static void execlist_exec_queue_kill(struct xe_exec_queue *q)
|
|||
/* NIY */
|
||||
}
|
||||
|
||||
static void execlist_exec_queue_fini(struct xe_exec_queue *q)
|
||||
static void execlist_exec_queue_destroy(struct xe_exec_queue *q)
|
||||
{
|
||||
INIT_WORK(&q->execlist->fini_async, execlist_exec_queue_fini_async);
|
||||
queue_work(system_unbound_wq, &q->execlist->fini_async);
|
||||
INIT_WORK(&q->execlist->destroy_async, execlist_exec_queue_destroy_async);
|
||||
queue_work(system_unbound_wq, &q->execlist->destroy_async);
|
||||
}
|
||||
|
||||
static int execlist_exec_queue_set_priority(struct xe_exec_queue *q,
|
||||
|
|
@ -467,6 +473,7 @@ static const struct xe_exec_queue_ops execlist_exec_queue_ops = {
|
|||
.init = execlist_exec_queue_init,
|
||||
.kill = execlist_exec_queue_kill,
|
||||
.fini = execlist_exec_queue_fini,
|
||||
.destroy = execlist_exec_queue_destroy,
|
||||
.set_priority = execlist_exec_queue_set_priority,
|
||||
.set_timeslice = execlist_exec_queue_set_timeslice,
|
||||
.set_preempt_timeout = execlist_exec_queue_set_preempt_timeout,
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ struct xe_execlist_exec_queue {
|
|||
|
||||
bool has_run;
|
||||
|
||||
struct work_struct fini_async;
|
||||
struct work_struct destroy_async;
|
||||
|
||||
enum xe_exec_queue_priority active_priority;
|
||||
struct list_head active_link;
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "xe_gt_topology.h"
|
||||
#include "xe_guc_exec_queue_types.h"
|
||||
#include "xe_guc_pc.h"
|
||||
#include "xe_guc_submit.h"
|
||||
#include "xe_hw_fence.h"
|
||||
#include "xe_hw_engine_class_sysfs.h"
|
||||
#include "xe_irq.h"
|
||||
|
|
@ -97,7 +98,7 @@ void xe_gt_sanitize(struct xe_gt *gt)
|
|||
* FIXME: if xe_uc_sanitize is called here, on TGL driver will not
|
||||
* reload
|
||||
*/
|
||||
gt->uc.guc.submission_state.enabled = false;
|
||||
xe_guc_submit_disable(>->uc.guc);
|
||||
}
|
||||
|
||||
static void xe_gt_enable_host_l2_vram(struct xe_gt *gt)
|
||||
|
|
|
|||
|
|
@ -1632,7 +1632,6 @@ static u64 pf_estimate_fair_lmem(struct xe_gt *gt, unsigned int num_vfs)
|
|||
u64 fair;
|
||||
|
||||
fair = div_u64(available, num_vfs);
|
||||
fair = rounddown_pow_of_two(fair); /* XXX: ttm_vram_mgr & drm_buddy limitation */
|
||||
fair = ALIGN_DOWN(fair, alignment);
|
||||
#ifdef MAX_FAIR_LMEM
|
||||
fair = min_t(u64, MAX_FAIR_LMEM, fair);
|
||||
|
|
|
|||
|
|
@ -880,9 +880,7 @@ int xe_guc_post_load_init(struct xe_guc *guc)
|
|||
return ret;
|
||||
}
|
||||
|
||||
guc->submission_state.enabled = true;
|
||||
|
||||
return 0;
|
||||
return xe_guc_submit_enable(guc);
|
||||
}
|
||||
|
||||
int xe_guc_reset(struct xe_guc *guc)
|
||||
|
|
@ -1579,7 +1577,7 @@ void xe_guc_sanitize(struct xe_guc *guc)
|
|||
{
|
||||
xe_uc_fw_sanitize(&guc->fw);
|
||||
xe_guc_ct_disable(&guc->ct);
|
||||
guc->submission_state.enabled = false;
|
||||
xe_guc_submit_disable(guc);
|
||||
}
|
||||
|
||||
int xe_guc_reset_prepare(struct xe_guc *guc)
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ struct xe_guc_exec_queue {
|
|||
struct xe_sched_msg static_msgs[MAX_STATIC_MSG_TYPE];
|
||||
/** @lr_tdr: long running TDR worker */
|
||||
struct work_struct lr_tdr;
|
||||
/** @fini_async: do final fini async from this worker */
|
||||
struct work_struct fini_async;
|
||||
/** @destroy_async: do final destroy async from this worker */
|
||||
struct work_struct destroy_async;
|
||||
/** @resume_time: time of last resume */
|
||||
u64 resume_time;
|
||||
/** @state: GuC specific state for this xe_exec_queue */
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "xe_guc_ct.h"
|
||||
#include "xe_guc_exec_queue_types.h"
|
||||
#include "xe_guc_id_mgr.h"
|
||||
#include "xe_guc_klv_helpers.h"
|
||||
#include "xe_guc_submit_types.h"
|
||||
#include "xe_hw_engine.h"
|
||||
#include "xe_hw_fence.h"
|
||||
|
|
@ -316,6 +317,71 @@ int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids)
|
|||
return drmm_add_action_or_reset(&xe->drm, guc_submit_fini, guc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given that we want to guarantee enough RCS throughput to avoid missing
|
||||
* frames, we set the yield policy to 20% of each 80ms interval.
|
||||
*/
|
||||
#define RC_YIELD_DURATION 80 /* in ms */
|
||||
#define RC_YIELD_RATIO 20 /* in percent */
|
||||
static u32 *emit_render_compute_yield_klv(u32 *emit)
|
||||
{
|
||||
*emit++ = PREP_GUC_KLV_TAG(SCHEDULING_POLICIES_RENDER_COMPUTE_YIELD);
|
||||
*emit++ = RC_YIELD_DURATION;
|
||||
*emit++ = RC_YIELD_RATIO;
|
||||
|
||||
return emit;
|
||||
}
|
||||
|
||||
#define SCHEDULING_POLICY_MAX_DWORDS 16
|
||||
static int guc_init_global_schedule_policy(struct xe_guc *guc)
|
||||
{
|
||||
u32 data[SCHEDULING_POLICY_MAX_DWORDS];
|
||||
u32 *emit = data;
|
||||
u32 count = 0;
|
||||
int ret;
|
||||
|
||||
if (GUC_SUBMIT_VER(guc) < MAKE_GUC_VER(1, 1, 0))
|
||||
return 0;
|
||||
|
||||
*emit++ = XE_GUC_ACTION_UPDATE_SCHEDULING_POLICIES_KLV;
|
||||
|
||||
if (CCS_MASK(guc_to_gt(guc)))
|
||||
emit = emit_render_compute_yield_klv(emit);
|
||||
|
||||
count = emit - data;
|
||||
if (count > 1) {
|
||||
xe_assert(guc_to_xe(guc), count <= SCHEDULING_POLICY_MAX_DWORDS);
|
||||
|
||||
ret = xe_guc_ct_send_block(&guc->ct, data, count);
|
||||
if (ret < 0) {
|
||||
xe_gt_err(guc_to_gt(guc),
|
||||
"failed to enable GuC sheduling policies: %pe\n",
|
||||
ERR_PTR(ret));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xe_guc_submit_enable(struct xe_guc *guc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = guc_init_global_schedule_policy(guc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
guc->submission_state.enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xe_guc_submit_disable(struct xe_guc *guc)
|
||||
{
|
||||
guc->submission_state.enabled = false;
|
||||
}
|
||||
|
||||
static void __release_guc_id(struct xe_guc *guc, struct xe_exec_queue *q, u32 xa_count)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -1277,21 +1343,12 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
|
|||
return DRM_GPU_SCHED_STAT_NO_HANG;
|
||||
}
|
||||
|
||||
static void __guc_exec_queue_fini_async(struct work_struct *w)
|
||||
static void guc_exec_queue_fini(struct xe_exec_queue *q)
|
||||
{
|
||||
struct xe_guc_exec_queue *ge =
|
||||
container_of(w, struct xe_guc_exec_queue, fini_async);
|
||||
struct xe_exec_queue *q = ge->q;
|
||||
struct xe_guc_exec_queue *ge = q->guc;
|
||||
struct xe_guc *guc = exec_queue_to_guc(q);
|
||||
|
||||
xe_pm_runtime_get(guc_to_xe(guc));
|
||||
trace_xe_exec_queue_destroy(q);
|
||||
|
||||
release_guc_id(guc, q);
|
||||
if (xe_exec_queue_is_lr(q))
|
||||
cancel_work_sync(&ge->lr_tdr);
|
||||
/* Confirm no work left behind accessing device structures */
|
||||
cancel_delayed_work_sync(&ge->sched.base.work_tdr);
|
||||
xe_sched_entity_fini(&ge->entity);
|
||||
xe_sched_fini(&ge->sched);
|
||||
|
||||
|
|
@ -1300,25 +1357,43 @@ static void __guc_exec_queue_fini_async(struct work_struct *w)
|
|||
* (timeline name).
|
||||
*/
|
||||
kfree_rcu(ge, rcu);
|
||||
}
|
||||
|
||||
static void __guc_exec_queue_destroy_async(struct work_struct *w)
|
||||
{
|
||||
struct xe_guc_exec_queue *ge =
|
||||
container_of(w, struct xe_guc_exec_queue, destroy_async);
|
||||
struct xe_exec_queue *q = ge->q;
|
||||
struct xe_guc *guc = exec_queue_to_guc(q);
|
||||
|
||||
xe_pm_runtime_get(guc_to_xe(guc));
|
||||
trace_xe_exec_queue_destroy(q);
|
||||
|
||||
if (xe_exec_queue_is_lr(q))
|
||||
cancel_work_sync(&ge->lr_tdr);
|
||||
/* Confirm no work left behind accessing device structures */
|
||||
cancel_delayed_work_sync(&ge->sched.base.work_tdr);
|
||||
|
||||
xe_exec_queue_fini(q);
|
||||
|
||||
xe_pm_runtime_put(guc_to_xe(guc));
|
||||
}
|
||||
|
||||
static void guc_exec_queue_fini_async(struct xe_exec_queue *q)
|
||||
static void guc_exec_queue_destroy_async(struct xe_exec_queue *q)
|
||||
{
|
||||
struct xe_guc *guc = exec_queue_to_guc(q);
|
||||
struct xe_device *xe = guc_to_xe(guc);
|
||||
|
||||
INIT_WORK(&q->guc->fini_async, __guc_exec_queue_fini_async);
|
||||
INIT_WORK(&q->guc->destroy_async, __guc_exec_queue_destroy_async);
|
||||
|
||||
/* We must block on kernel engines so slabs are empty on driver unload */
|
||||
if (q->flags & EXEC_QUEUE_FLAG_PERMANENT || exec_queue_wedged(q))
|
||||
__guc_exec_queue_fini_async(&q->guc->fini_async);
|
||||
__guc_exec_queue_destroy_async(&q->guc->destroy_async);
|
||||
else
|
||||
queue_work(xe->destroy_wq, &q->guc->fini_async);
|
||||
queue_work(xe->destroy_wq, &q->guc->destroy_async);
|
||||
}
|
||||
|
||||
static void __guc_exec_queue_fini(struct xe_guc *guc, struct xe_exec_queue *q)
|
||||
static void __guc_exec_queue_destroy(struct xe_guc *guc, struct xe_exec_queue *q)
|
||||
{
|
||||
/*
|
||||
* Might be done from within the GPU scheduler, need to do async as we
|
||||
|
|
@ -1327,7 +1402,7 @@ static void __guc_exec_queue_fini(struct xe_guc *guc, struct xe_exec_queue *q)
|
|||
* this we and don't really care when everything is fini'd, just that it
|
||||
* is.
|
||||
*/
|
||||
guc_exec_queue_fini_async(q);
|
||||
guc_exec_queue_destroy_async(q);
|
||||
}
|
||||
|
||||
static void __guc_exec_queue_process_msg_cleanup(struct xe_sched_msg *msg)
|
||||
|
|
@ -1341,7 +1416,7 @@ static void __guc_exec_queue_process_msg_cleanup(struct xe_sched_msg *msg)
|
|||
if (exec_queue_registered(q))
|
||||
disable_scheduling_deregister(guc, q);
|
||||
else
|
||||
__guc_exec_queue_fini(guc, q);
|
||||
__guc_exec_queue_destroy(guc, q);
|
||||
}
|
||||
|
||||
static bool guc_exec_queue_allowed_to_change_state(struct xe_exec_queue *q)
|
||||
|
|
@ -1574,14 +1649,14 @@ static bool guc_exec_queue_try_add_msg(struct xe_exec_queue *q,
|
|||
#define STATIC_MSG_CLEANUP 0
|
||||
#define STATIC_MSG_SUSPEND 1
|
||||
#define STATIC_MSG_RESUME 2
|
||||
static void guc_exec_queue_fini(struct xe_exec_queue *q)
|
||||
static void guc_exec_queue_destroy(struct xe_exec_queue *q)
|
||||
{
|
||||
struct xe_sched_msg *msg = q->guc->static_msgs + STATIC_MSG_CLEANUP;
|
||||
|
||||
if (!(q->flags & EXEC_QUEUE_FLAG_PERMANENT) && !exec_queue_wedged(q))
|
||||
guc_exec_queue_add_msg(q, msg, CLEANUP);
|
||||
else
|
||||
__guc_exec_queue_fini(exec_queue_to_guc(q), q);
|
||||
__guc_exec_queue_destroy(exec_queue_to_guc(q), q);
|
||||
}
|
||||
|
||||
static int guc_exec_queue_set_priority(struct xe_exec_queue *q,
|
||||
|
|
@ -1711,6 +1786,7 @@ static const struct xe_exec_queue_ops guc_exec_queue_ops = {
|
|||
.init = guc_exec_queue_init,
|
||||
.kill = guc_exec_queue_kill,
|
||||
.fini = guc_exec_queue_fini,
|
||||
.destroy = guc_exec_queue_destroy,
|
||||
.set_priority = guc_exec_queue_set_priority,
|
||||
.set_timeslice = guc_exec_queue_set_timeslice,
|
||||
.set_preempt_timeout = guc_exec_queue_set_preempt_timeout,
|
||||
|
|
@ -1732,7 +1808,7 @@ static void guc_exec_queue_stop(struct xe_guc *guc, struct xe_exec_queue *q)
|
|||
if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q))
|
||||
xe_exec_queue_put(q);
|
||||
else if (exec_queue_destroyed(q))
|
||||
__guc_exec_queue_fini(guc, q);
|
||||
__guc_exec_queue_destroy(guc, q);
|
||||
}
|
||||
if (q->guc->suspend_pending) {
|
||||
set_exec_queue_suspended(q);
|
||||
|
|
@ -1989,7 +2065,7 @@ static void handle_deregister_done(struct xe_guc *guc, struct xe_exec_queue *q)
|
|||
if (exec_queue_extra_ref(q) || xe_exec_queue_is_lr(q))
|
||||
xe_exec_queue_put(q);
|
||||
else
|
||||
__guc_exec_queue_fini(guc, q);
|
||||
__guc_exec_queue_destroy(guc, q);
|
||||
}
|
||||
|
||||
int xe_guc_deregister_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ struct xe_exec_queue;
|
|||
struct xe_guc;
|
||||
|
||||
int xe_guc_submit_init(struct xe_guc *guc, unsigned int num_ids);
|
||||
int xe_guc_submit_enable(struct xe_guc *guc);
|
||||
void xe_guc_submit_disable(struct xe_guc *guc);
|
||||
|
||||
int xe_guc_submit_reset_prepare(struct xe_guc *guc);
|
||||
void xe_guc_submit_reset_wait(struct xe_guc *guc);
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ static struct xe_reg xe_hwmon_get_reg(struct xe_hwmon *hwmon, enum xe_hwmon_reg
|
|||
*/
|
||||
static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, u32 attr, int channel, long *value)
|
||||
{
|
||||
u64 reg_val = 0, min, max;
|
||||
u32 reg_val = 0;
|
||||
struct xe_device *xe = hwmon->xe;
|
||||
struct xe_reg rapl_limit, pkg_power_sku;
|
||||
struct xe_mmio *mmio = xe_root_tile_mmio(xe);
|
||||
|
|
@ -294,7 +294,7 @@ static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, u32 attr, int channe
|
|||
mutex_lock(&hwmon->hwmon_lock);
|
||||
|
||||
if (hwmon->xe->info.has_mbx_power_limits) {
|
||||
xe_hwmon_pcode_read_power_limit(hwmon, attr, channel, (u32 *)®_val);
|
||||
xe_hwmon_pcode_read_power_limit(hwmon, attr, channel, ®_val);
|
||||
} else {
|
||||
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);
|
||||
|
|
@ -304,19 +304,21 @@ static void xe_hwmon_power_max_read(struct xe_hwmon *hwmon, u32 attr, int channe
|
|||
/* Check if PL limits are disabled. */
|
||||
if (!(reg_val & PWR_LIM_EN)) {
|
||||
*value = PL_DISABLE;
|
||||
drm_info(&hwmon->xe->drm, "%s disabled for channel %d, val 0x%016llx\n",
|
||||
drm_info(&hwmon->xe->drm, "%s disabled for channel %d, val 0x%08x\n",
|
||||
PWR_ATTR_TO_STR(attr), channel, reg_val);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
reg_val = REG_FIELD_GET(PWR_LIM_VAL, reg_val);
|
||||
*value = mul_u64_u32_shr(reg_val, SF_POWER, hwmon->scl_shift_power);
|
||||
*value = mul_u32_u32(reg_val, SF_POWER) >> hwmon->scl_shift_power;
|
||||
|
||||
/* For platforms with mailbox power limit support clamping would be done by pcode. */
|
||||
if (!hwmon->xe->info.has_mbx_power_limits) {
|
||||
reg_val = xe_mmio_read64_2x32(mmio, pkg_power_sku);
|
||||
min = REG_FIELD_GET(PKG_MIN_PWR, reg_val);
|
||||
max = REG_FIELD_GET(PKG_MAX_PWR, reg_val);
|
||||
u64 pkg_pwr, min, max;
|
||||
|
||||
pkg_pwr = xe_mmio_read64_2x32(mmio, pkg_power_sku);
|
||||
min = REG_FIELD_GET(PKG_MIN_PWR, pkg_pwr);
|
||||
max = REG_FIELD_GET(PKG_MAX_PWR, pkg_pwr);
|
||||
min = mul_u64_u32_shr(min, SF_POWER, hwmon->scl_shift_power);
|
||||
max = mul_u64_u32_shr(max, SF_POWER, hwmon->scl_shift_power);
|
||||
if (min && max)
|
||||
|
|
@ -493,8 +495,8 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at
|
|||
{
|
||||
struct xe_hwmon *hwmon = dev_get_drvdata(dev);
|
||||
struct xe_mmio *mmio = xe_root_tile_mmio(hwmon->xe);
|
||||
u32 x, y, x_w = 2; /* 2 bits */
|
||||
u64 r, tau4, out;
|
||||
u32 reg_val, x, y, x_w = 2; /* 2 bits */
|
||||
u64 tau4, out;
|
||||
int channel = (to_sensor_dev_attr(attr)->index % 2) ? CHANNEL_PKG : CHANNEL_CARD;
|
||||
u32 power_attr = (to_sensor_dev_attr(attr)->index > 1) ? PL2_HWMON_ATTR : PL1_HWMON_ATTR;
|
||||
|
||||
|
|
@ -505,23 +507,24 @@ xe_hwmon_power_max_interval_show(struct device *dev, struct device_attribute *at
|
|||
mutex_lock(&hwmon->hwmon_lock);
|
||||
|
||||
if (hwmon->xe->info.has_mbx_power_limits) {
|
||||
ret = xe_hwmon_pcode_read_power_limit(hwmon, power_attr, channel, (u32 *)&r);
|
||||
ret = xe_hwmon_pcode_read_power_limit(hwmon, power_attr, channel, ®_val);
|
||||
if (ret) {
|
||||
drm_err(&hwmon->xe->drm,
|
||||
"power interval read fail, ch %d, attr %d, r 0%llx, ret %d\n",
|
||||
channel, power_attr, r, ret);
|
||||
r = 0;
|
||||
"power interval read fail, ch %d, attr %d, val 0x%08x, ret %d\n",
|
||||
channel, power_attr, reg_val, ret);
|
||||
reg_val = 0;
|
||||
}
|
||||
} else {
|
||||
r = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT, channel));
|
||||
reg_val = xe_mmio_read32(mmio, xe_hwmon_get_reg(hwmon, REG_PKG_RAPL_LIMIT,
|
||||
channel));
|
||||
}
|
||||
|
||||
mutex_unlock(&hwmon->hwmon_lock);
|
||||
|
||||
xe_pm_runtime_put(hwmon->xe);
|
||||
|
||||
x = REG_FIELD_GET(PWR_LIM_TIME_X, r);
|
||||
y = REG_FIELD_GET(PWR_LIM_TIME_Y, r);
|
||||
x = REG_FIELD_GET(PWR_LIM_TIME_X, reg_val);
|
||||
y = REG_FIELD_GET(PWR_LIM_TIME_Y, reg_val);
|
||||
|
||||
/*
|
||||
* tau = (1 + (x / 4)) * power(2,y), x = bits(23:22), y = bits(21:17)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,10 @@ static const struct intel_dg_nvm_region regions[INTEL_DG_NVM_REGIONS] = {
|
|||
|
||||
static void xe_nvm_release_dev(struct device *dev)
|
||||
{
|
||||
struct auxiliary_device *aux = container_of(dev, struct auxiliary_device, dev);
|
||||
struct intel_dg_nvm_dev *nvm = container_of(aux, struct intel_dg_nvm_dev, aux_dev);
|
||||
|
||||
kfree(nvm);
|
||||
}
|
||||
|
||||
static bool xe_nvm_non_posted_erase(struct xe_device *xe)
|
||||
|
|
@ -162,6 +166,5 @@ void xe_nvm_fini(struct xe_device *xe)
|
|||
|
||||
auxiliary_device_delete(&nvm->aux_dev);
|
||||
auxiliary_device_uninit(&nvm->aux_dev);
|
||||
kfree(nvm);
|
||||
xe->nvm = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,16 +44,18 @@ int xe_tile_sysfs_init(struct xe_tile *tile)
|
|||
kt->tile = tile;
|
||||
|
||||
err = kobject_add(&kt->base, &dev->kobj, "tile%d", tile->id);
|
||||
if (err) {
|
||||
kobject_put(&kt->base);
|
||||
return err;
|
||||
}
|
||||
if (err)
|
||||
goto err_object;
|
||||
|
||||
tile->sysfs = &kt->base;
|
||||
|
||||
err = xe_vram_freq_sysfs_init(tile);
|
||||
if (err)
|
||||
return err;
|
||||
goto err_object;
|
||||
|
||||
return devm_add_action_or_reset(xe->drm.dev, tile_sysfs_fini, tile);
|
||||
|
||||
err_object:
|
||||
kobject_put(&kt->base);
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,8 +240,8 @@ int xe_vm_add_compute_exec_queue(struct xe_vm *vm, struct xe_exec_queue *q)
|
|||
|
||||
pfence = xe_preempt_fence_create(q, q->lr.context,
|
||||
++q->lr.seqno);
|
||||
if (!pfence) {
|
||||
err = -ENOMEM;
|
||||
if (IS_ERR(pfence)) {
|
||||
err = PTR_ERR(pfence);
|
||||
goto out_fini;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user