mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-03 21:45:08 -04:00
drm/xe/oa: Override GuC RC with OA on PVC
On PVC, a w/a resets RCS/CCS before it goes into RC6. This breaks OA since OA does not expect engine resets during its use. Fix it by disabling RC6. v2: Convert to gt oriented error/warn messages (Michal) Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com> Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240618014609.3233427-16-ashutosh.dixit@intel.com
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
#include "xe_map.h"
|
||||
#include "xe_mmio.h"
|
||||
#include "xe_pcode.h"
|
||||
#include "xe_pm.h"
|
||||
|
||||
#define MCHBAR_MIRROR_BASE_SNB 0x140000
|
||||
|
||||
@@ -190,6 +191,27 @@ static int pc_action_set_param(struct xe_guc_pc *pc, u8 id, u32 value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pc_action_unset_param(struct xe_guc_pc *pc, u8 id)
|
||||
{
|
||||
u32 action[] = {
|
||||
GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
|
||||
SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 1),
|
||||
id,
|
||||
};
|
||||
struct xe_guc_ct *ct = &pc_to_guc(pc)->ct;
|
||||
int ret;
|
||||
|
||||
if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING))
|
||||
return -EAGAIN;
|
||||
|
||||
ret = xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0);
|
||||
if (ret)
|
||||
xe_gt_err(pc_to_gt(pc), "GuC PC unset param failed: %pe",
|
||||
ERR_PTR(ret));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pc_action_setup_gucrc(struct xe_guc_pc *pc, u32 mode)
|
||||
{
|
||||
struct xe_guc_ct *ct = pc_to_ct(pc);
|
||||
@@ -772,6 +794,41 @@ int xe_guc_pc_gucrc_disable(struct xe_guc_pc *pc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_guc_pc_override_gucrc_mode - override GUCRC mode
|
||||
* @pc: Xe_GuC_PC instance
|
||||
* @mode: new value of the mode.
|
||||
*
|
||||
* Return: 0 on success, negative error code on error
|
||||
*/
|
||||
int xe_guc_pc_override_gucrc_mode(struct xe_guc_pc *pc, enum slpc_gucrc_mode mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
xe_pm_runtime_get(pc_to_xe(pc));
|
||||
ret = pc_action_set_param(pc, SLPC_PARAM_PWRGATE_RC_MODE, mode);
|
||||
xe_pm_runtime_put(pc_to_xe(pc));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* xe_guc_pc_unset_gucrc_mode - unset GUCRC mode override
|
||||
* @pc: Xe_GuC_PC instance
|
||||
*
|
||||
* Return: 0 on success, negative error code on error
|
||||
*/
|
||||
int xe_guc_pc_unset_gucrc_mode(struct xe_guc_pc *pc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
xe_pm_runtime_get(pc_to_xe(pc));
|
||||
ret = pc_action_unset_param(pc, SLPC_PARAM_PWRGATE_RC_MODE);
|
||||
xe_pm_runtime_put(pc_to_xe(pc));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pc_init_pcode_freq(struct xe_guc_pc *pc)
|
||||
{
|
||||
u32 min = DIV_ROUND_CLOSEST(pc->rpn_freq, GT_FREQUENCY_MULTIPLIER);
|
||||
|
||||
@@ -9,11 +9,14 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
struct xe_guc_pc;
|
||||
enum slpc_gucrc_mode;
|
||||
|
||||
int xe_guc_pc_init(struct xe_guc_pc *pc);
|
||||
int xe_guc_pc_start(struct xe_guc_pc *pc);
|
||||
int xe_guc_pc_stop(struct xe_guc_pc *pc);
|
||||
int xe_guc_pc_gucrc_disable(struct xe_guc_pc *pc);
|
||||
int xe_guc_pc_override_gucrc_mode(struct xe_guc_pc *pc, enum slpc_gucrc_mode mode);
|
||||
int xe_guc_pc_unset_gucrc_mode(struct xe_guc_pc *pc);
|
||||
|
||||
u32 xe_guc_pc_get_act_freq(struct xe_guc_pc *pc);
|
||||
int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq);
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/xe_drm.h>
|
||||
|
||||
#include "abi/guc_actions_slpc_abi.h"
|
||||
#include "instructions/xe_mi_commands.h"
|
||||
#include "regs/xe_engine_regs.h"
|
||||
#include "regs/xe_gt_regs.h"
|
||||
@@ -26,6 +27,7 @@
|
||||
#include "xe_gt.h"
|
||||
#include "xe_gt_mcr.h"
|
||||
#include "xe_gt_printk.h"
|
||||
#include "xe_guc_pc.h"
|
||||
#include "xe_lrc.h"
|
||||
#include "xe_macros.h"
|
||||
#include "xe_mmio.h"
|
||||
@@ -817,6 +819,10 @@ static void xe_oa_stream_destroy(struct xe_oa_stream *stream)
|
||||
XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
|
||||
xe_pm_runtime_put(stream->oa->xe);
|
||||
|
||||
/* Wa_1509372804:pvc: Unset the override of GUCRC mode to enable rc6 */
|
||||
if (stream->override_gucrc)
|
||||
xe_gt_WARN_ON(gt, xe_guc_pc_unset_gucrc_mode(>->uc.guc.pc));
|
||||
|
||||
xe_oa_free_configs(stream);
|
||||
}
|
||||
|
||||
@@ -1308,6 +1314,21 @@ static int xe_oa_stream_init(struct xe_oa_stream *stream,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wa_1509372804:pvc
|
||||
*
|
||||
* GuC reset of engines causes OA to lose configuration
|
||||
* state. Prevent this by overriding GUCRC mode.
|
||||
*/
|
||||
if (stream->oa->xe->info.platform == XE_PVC) {
|
||||
ret = xe_guc_pc_override_gucrc_mode(>->uc.guc.pc,
|
||||
SLPC_GUCRC_MODE_GUCRC_NO_RC6);
|
||||
if (ret)
|
||||
goto err_free_configs;
|
||||
|
||||
stream->override_gucrc = true;
|
||||
}
|
||||
|
||||
/* Take runtime pm ref and forcewake to disable RC6 */
|
||||
xe_pm_runtime_get(stream->oa->xe);
|
||||
XE_WARN_ON(xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL));
|
||||
@@ -1354,6 +1375,9 @@ static int xe_oa_stream_init(struct xe_oa_stream *stream,
|
||||
err_fw_put:
|
||||
XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
|
||||
xe_pm_runtime_put(stream->oa->xe);
|
||||
if (stream->override_gucrc)
|
||||
xe_gt_WARN_ON(gt, xe_guc_pc_unset_gucrc_mode(>->uc.guc.pc));
|
||||
err_free_configs:
|
||||
xe_oa_free_configs(stream);
|
||||
exit:
|
||||
return ret;
|
||||
|
||||
@@ -227,6 +227,9 @@ struct xe_oa_stream {
|
||||
/** @poll_period_ns: hrtimer period for checking OA buffer for available data */
|
||||
u64 poll_period_ns;
|
||||
|
||||
/** @override_gucrc: GuC RC has been overridden for the OA stream */
|
||||
bool override_gucrc;
|
||||
|
||||
/** @oa_status: temporary storage for oa_status register value */
|
||||
u32 oa_status;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user