Driver Changes:

- Fix NULL pointer dereference on error path
 - Add missing HW workaround for BMG
 - Fix survivability mode not triggering
 - Fix build warning when DRM_FBDEV_EMULATION is not set
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE6rM8lpABPHM5FqyDm6KlpjDL6lMFAmflamoZHGx1Y2FzLmRl
 bWFyY2hpQGludGVsLmNvbQAKCRCboqWmMMvqUzFcD/9uZkIvrmhZ7Yy0fyDlXu4K
 jIPN/IIzrk0Cn2+KBNC7oZOtVqwDblX8qk+n59u+wJHTKxmqrBfJZ1nEPRMfIRoY
 1dEdOmbl5E1fu4vWlKqFOmj69wTz80+NhHewMOV6vaNNPUo2Ub6MjrIYG+8Y+e7v
 WeoqTxxY7OEUKrygDjLxflG8yMr/faxoY2VhudtW88omENI7bOoH/fdJE6XUvoZI
 ACXvYBDImbe31KqSFTfJKKMrSN43hVzhaeoMi9bpt0Vyz5JNBvb4KfccD0vvzY9y
 2nErIyGaN4vc65kYibHhhEa76dlbMz0vTYAgXKTLz1TC/mVWsjHEh3ExOYSWFAbN
 ziN9wA8MN0zFnhqKDzatK4hjgR29hDxDG3rLdweGqvtNZqWc3f3AcJ5vvH6OacFb
 LGG7khi732msq6+cNAdJ+T9YK4OXWVMOX/woZ4iAMaexGv2i4pXYFqBlWpoTUrbd
 s7A9IHsZXNQ7gcUrJvzuGN9llJ0b5b2hRaL2bmeze0C+GeT5DEcSKo3wMBEnxqOc
 zSelYnBs5y5fUwU1vM4Ak5L2a1ZAIXFyeIcWahPRuIGOgANn7h7mWXEc8aBJefsM
 JALCI/yAZE0mTzfuOGq169p4ifUCJJmj9aL86SA/xjJTFqMZHLUXwpEP06LtZigV
 jra7pFnsQ2hRtkJHFZETfw==
 =uIRa
 -----END PGP SIGNATURE-----

Merge tag 'drm-xe-next-fixes-2025-03-27' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next

Driver Changes:
- Fix NULL pointer dereference on error path
- Add missing HW workaround for BMG
- Fix survivability mode not triggering
- Fix build warning when DRM_FBDEV_EMULATION is not set

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://lore.kernel.org/r/vxy5kwdkzgp2u2umnyxv4ygslmdlvzjl22xotzxaw55dv7plpz@34miqxkbvggu
This commit is contained in:
Dave Airlie 2025-04-03 15:52:34 +10:00
commit 227bcf2c55
12 changed files with 131 additions and 45 deletions

View File

@ -53,7 +53,7 @@ config DRM_XE
config DRM_XE_DISPLAY
bool "Enable display support"
depends on DRM_XE && DRM_XE=m && HAS_IOPORT
select FB_IOMEM_HELPERS
select FB_IOMEM_HELPERS if DRM_FBDEV_EMULATION
select I2C
select I2C_ALGOBIT
default y

View File

@ -130,6 +130,10 @@
#define RING_EXECLIST_STATUS_LO(base) XE_REG((base) + 0x234)
#define RING_EXECLIST_STATUS_HI(base) XE_REG((base) + 0x234 + 4)
#define RING_IDLEDLY(base) XE_REG((base) + 0x23c)
#define INHIBIT_SWITCH_UNTIL_PREEMPTED REG_BIT(31)
#define IDLE_DELAY REG_GENMASK(20, 0)
#define RING_CONTEXT_CONTROL(base) XE_REG((base) + 0x244, XE_REG_OPTION_MASKED)
#define CTX_CTRL_PXP_ENABLE REG_BIT(10)
#define CTX_CTRL_OAC_CONTEXT_ENABLE REG_BIT(8)

View File

@ -53,6 +53,7 @@
#include "xe_pxp.h"
#include "xe_query.h"
#include "xe_shrinker.h"
#include "xe_survivability_mode.h"
#include "xe_sriov.h"
#include "xe_tile.h"
#include "xe_ttm_stolen_mgr.h"
@ -705,8 +706,20 @@ int xe_device_probe_early(struct xe_device *xe)
sriov_update_device_info(xe);
err = xe_pcode_probe_early(xe);
if (err)
return err;
if (err) {
int save_err = err;
/*
* Try to leave device in survivability mode if device is
* possible, but still return the previous error for error
* propagation
*/
err = xe_survivability_mode_enable(xe);
if (err)
return err;
return save_err;
}
err = wait_for_lmem_ready(xe);
if (err)

View File

@ -222,13 +222,7 @@ int xe_eu_stall_init(struct xe_gt *gt)
goto exit_free;
}
ret = devm_add_action_or_reset(xe->drm.dev, xe_eu_stall_fini, gt);
if (ret)
goto exit_destroy;
return 0;
exit_destroy:
destroy_workqueue(gt->eu_stall->buf_ptr_poll_wq);
return devm_add_action_or_reset(xe->drm.dev, xe_eu_stall_fini, gt);
exit_free:
mutex_destroy(&gt->eu_stall->stream_lock);
kfree(gt->eu_stall);

View File

@ -16,35 +16,47 @@
#include "xe_macros.h"
#include "xe_mmio.h"
static u32 get_crystal_clock_freq(u32 rpm_config_reg)
#define f19_2_mhz 19200000
#define f24_mhz 24000000
#define f25_mhz 25000000
#define f38_4_mhz 38400000
#define ts_base_83 83333
#define ts_base_52 52083
#define ts_base_80 80000
static void read_crystal_clock(struct xe_gt *gt, u32 rpm_config_reg, u32 *freq,
u32 *timestamp_base)
{
const u32 f19_2_mhz = 19200000;
const u32 f24_mhz = 24000000;
const u32 f25_mhz = 25000000;
const u32 f38_4_mhz = 38400000;
u32 crystal_clock = REG_FIELD_GET(RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK,
rpm_config_reg);
switch (crystal_clock) {
case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_24_MHZ:
return f24_mhz;
*freq = f24_mhz;
*timestamp_base = ts_base_83;
return;
case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_19_2_MHZ:
return f19_2_mhz;
*freq = f19_2_mhz;
*timestamp_base = ts_base_52;
return;
case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_38_4_MHZ:
return f38_4_mhz;
*freq = f38_4_mhz;
*timestamp_base = ts_base_52;
return;
case RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_25_MHZ:
return f25_mhz;
*freq = f25_mhz;
*timestamp_base = ts_base_80;
return;
default:
XE_WARN_ON("NOT_POSSIBLE");
return 0;
xe_gt_warn(gt, "Invalid crystal clock frequency: %u", crystal_clock);
*freq = 0;
*timestamp_base = 0;
return;
}
}
int xe_gt_clock_init(struct xe_gt *gt)
static void check_ctc_mode(struct xe_gt *gt)
{
u32 c0 = xe_mmio_read32(&gt->mmio, RPM_CONFIG0);
u32 freq = 0;
/*
* CTC_MODE[0] = 1 is definitely not supported for Xe2 and later
* platforms. In theory it could be a valid setting for pre-Xe2
@ -57,8 +69,18 @@ int xe_gt_clock_init(struct xe_gt *gt)
*/
if (xe_mmio_read32(&gt->mmio, CTC_MODE) & CTC_SOURCE_DIVIDE_LOGIC)
xe_gt_warn(gt, "CTC_MODE[0] is set; this is unexpected and undocumented\n");
}
freq = get_crystal_clock_freq(c0);
int xe_gt_clock_init(struct xe_gt *gt)
{
u32 freq;
u32 c0;
if (!IS_SRIOV_VF(gt_to_xe(gt)))
check_ctc_mode(gt);
c0 = xe_mmio_read32(&gt->mmio, RPM_CONFIG0);
read_crystal_clock(gt, c0, &freq, &gt->info.timestamp_base);
/*
* Now figure out how the command stream's timestamp

View File

@ -121,6 +121,8 @@ struct xe_gt {
enum xe_gt_type type;
/** @info.reference_clock: clock frequency */
u32 reference_clock;
/** @info.timestamp_base: GT timestamp base */
u32 timestamp_base;
/**
* @info.engine_mask: mask of engines present on GT. Some of
* them may be reserved in runtime and not available for user.

View File

@ -8,7 +8,9 @@
#include <linux/nospec.h>
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
#include <uapi/drm/xe_drm.h>
#include <generated/xe_wa_oob.h>
#include "regs/xe_engine_regs.h"
#include "regs/xe_gt_regs.h"
@ -21,6 +23,7 @@
#include "xe_gsc.h"
#include "xe_gt.h"
#include "xe_gt_ccs_mode.h"
#include "xe_gt_clock.h"
#include "xe_gt_printk.h"
#include "xe_gt_mcr.h"
#include "xe_gt_topology.h"
@ -564,6 +567,33 @@ static void hw_engine_init_early(struct xe_gt *gt, struct xe_hw_engine *hwe,
xe_reg_whitelist_process_engine(hwe);
}
static void adjust_idledly(struct xe_hw_engine *hwe)
{
struct xe_gt *gt = hwe->gt;
u32 idledly, maxcnt;
u32 idledly_units_ps = 8 * gt->info.timestamp_base;
u32 maxcnt_units_ns = 640;
bool inhibit_switch = 0;
if (!IS_SRIOV_VF(gt_to_xe(hwe->gt)) && XE_WA(gt, 16023105232)) {
idledly = xe_mmio_read32(&gt->mmio, RING_IDLEDLY(hwe->mmio_base));
maxcnt = xe_mmio_read32(&gt->mmio, RING_PWRCTX_MAXCNT(hwe->mmio_base));
inhibit_switch = idledly & INHIBIT_SWITCH_UNTIL_PREEMPTED;
idledly = REG_FIELD_GET(IDLE_DELAY, idledly);
idledly = DIV_ROUND_CLOSEST(idledly * idledly_units_ps, 1000);
maxcnt = REG_FIELD_GET(IDLE_WAIT_TIME, maxcnt);
maxcnt *= maxcnt_units_ns;
if (xe_gt_WARN_ON(gt, idledly >= maxcnt || inhibit_switch)) {
idledly = DIV_ROUND_CLOSEST(((maxcnt - 1) * maxcnt_units_ns),
idledly_units_ps);
idledly = DIV_ROUND_CLOSEST(idledly, 1000);
xe_mmio_write32(&gt->mmio, RING_IDLEDLY(hwe->mmio_base), idledly);
}
}
}
static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe,
enum xe_hw_engine_id id)
{
@ -604,6 +634,9 @@ static int hw_engine_init(struct xe_gt *gt, struct xe_hw_engine *hwe,
if (xe->info.has_usm && hwe->class == XE_ENGINE_CLASS_COPY)
gt->usm.reserved_bcs_instance = hwe->instance;
/* Ensure IDLEDLY is lower than MAXCNT */
adjust_idledly(hwe);
return devm_add_action_or_reset(xe->drm.dev, hw_engine_fini, hwe);
err_hwsp:

View File

@ -803,16 +803,14 @@ static int xe_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return err;
err = xe_device_probe_early(xe);
/*
* In Boot Survivability mode, no drm card is exposed and driver is
* loaded with bare minimum to allow for firmware to be flashed through
* mei. If early probe fails, check if survivability mode is flagged by
* HW to be enabled. In that case enable it and return success.
*/
if (err) {
if (xe_survivability_mode_required(xe) &&
xe_survivability_mode_enable(xe))
/*
* In Boot Survivability mode, no drm card is exposed and driver
* is loaded with bare minimum to allow for firmware to be
* flashed through mei. If early probe failed, but it managed to
* enable survivability mode, return success.
*/
if (xe_survivability_mode_is_enabled(xe))
return 0;
return err;

View File

@ -155,13 +155,21 @@ static int enable_survivability_mode(struct pci_dev *pdev)
if (ret)
return ret;
/* Make sure xe_heci_gsc_init() knows about survivability mode */
survivability->mode = true;
ret = xe_heci_gsc_init(xe);
if (ret)
if (ret) {
/*
* But if it fails, device can't enter survivability
* so move it back for correct error handling
*/
survivability->mode = false;
return ret;
}
xe_vsec_init(xe);
survivability->mode = true;
dev_err(dev, "In Survivability Mode\n");
return 0;
@ -178,15 +186,16 @@ bool xe_survivability_mode_is_enabled(struct xe_device *xe)
return xe->survivability.mode;
}
/**
* xe_survivability_mode_required - checks if survivability mode is required
* @xe: xe device instance
/*
* survivability_mode_requested - check if it's possible to enable
* survivability mode and that was requested by firmware
*
* This function reads the boot status from Pcode
* This function reads the boot status from Pcode.
*
* Return: true if boot status indicates failure, false otherwise
* Return: true if platform support is available and boot status indicates
* failure, false otherwise.
*/
bool xe_survivability_mode_required(struct xe_device *xe)
static bool survivability_mode_requested(struct xe_device *xe)
{
struct xe_survivability *survivability = &xe->survivability;
struct xe_mmio *mmio = xe_root_tile_mmio(xe);
@ -208,7 +217,8 @@ bool xe_survivability_mode_required(struct xe_device *xe)
*
* Initialize survivability information and enable survivability mode
*
* Return: 0 for success, negative error code otherwise.
* Return: 0 if survivability mode is enabled or not requested; negative error
* code otherwise.
*/
int xe_survivability_mode_enable(struct xe_device *xe)
{
@ -216,6 +226,9 @@ int xe_survivability_mode_enable(struct xe_device *xe)
struct xe_survivability_info *info;
struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
if (!survivability_mode_requested(xe))
return 0;
survivability->size = MAX_SCRATCH_MMIO;
info = devm_kcalloc(xe->drm.dev, survivability->size, sizeof(*info),

View File

@ -12,6 +12,5 @@ struct xe_device;
int xe_survivability_mode_enable(struct xe_device *xe);
bool xe_survivability_mode_is_enabled(struct xe_device *xe);
bool xe_survivability_mode_required(struct xe_device *xe);
#endif /* _XE_SURVIVABILITY_MODE_H_ */

View File

@ -622,6 +622,12 @@ static const struct xe_rtp_entry_sr engine_was[] = {
FUNC(xe_rtp_match_first_render_or_compute)),
XE_RTP_ACTIONS(SET(TDL_TSL_CHICKEN, RES_CHK_SPR_DIS))
},
{ XE_RTP_NAME("16023105232"),
XE_RTP_RULES(MEDIA_VERSION_RANGE(1301, 3000), OR,
GRAPHICS_VERSION_RANGE(2001, 3001)),
XE_RTP_ACTIONS(SET(RING_PSMI_CTL(0), RC_SEMA_IDLE_MSG_DISABLE,
XE_RTP_ACTION_FLAG(ENGINE_BASE)))
},
};
static const struct xe_rtp_entry_sr lrc_was[] = {

View File

@ -53,3 +53,5 @@ no_media_l3 MEDIA_VERSION(3000)
GRAPHICS_VERSION_RANGE(1270, 1274)
1508761755 GRAPHICS_VERSION(1255)
GRAPHICS_VERSION(1260), GRAPHICS_STEP(A0, B0)
16023105232 GRAPHICS_VERSION_RANGE(2001, 3001)
MEDIA_VERSION_RANGE(1301, 3000)