UAPI Changes:

- Expose PCIe link downgrade attributes (Raag)
 
 Cross-subsystem Changes:
 
 Core Changes:
 - gpusvm has_dma_mapping fix (Dafna)
 
 Driver Changes:
 - Forcewake hold fix (Tejas)
 - Fix guc_info debugfs for VFs (Daniele)
 - Fix devcoredump chunk alignment calculation (Arnd)
 - Don't print timedout job message on killed exec queues (Matt Brost)
 - Don't flush the GSC worker from the reset path (Daniele)
 - Use copy_from_user() instead of __copy_from_user() (Harish)
 - Only flush SVM garbage collector if CONFIG_DRM_XE_GPUSVM (Shuicheng)
 - Fix forcewake vs runtime pm ref release ordering (Shuicheng)
 - Move xe_device_sysfs_init() to xe_device_probe() (Raag)
 - Append PCIe Gen5 limitations to xe_firmware document (Raag)
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRskUM7w1oG5rx2IZO4FpNVCsYGvwUCaBzURgAKCRC4FpNVCsYG
 v/SOAQDrXSwMhiU8NFDI5+W2cGKqZa0Z9Jl69J/by97Cr38eMgEArl0wY5+aaSOs
 DYg6OADl6ZHlRdU4kpisHtOzG9V5OA8=
 =680Y
 -----END PGP SIGNATURE-----

Merge tag 'drm-xe-next-2025-05-08' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next

UAPI Changes:
- Expose PCIe link downgrade attributes (Raag)

Cross-subsystem Changes:

Core Changes:
- gpusvm has_dma_mapping fix (Dafna)

Driver Changes:
- Forcewake hold fix (Tejas)
- Fix guc_info debugfs for VFs (Daniele)
- Fix devcoredump chunk alignment calculation (Arnd)
- Don't print timedout job message on killed exec queues (Matt Brost)
- Don't flush the GSC worker from the reset path (Daniele)
- Use copy_from_user() instead of __copy_from_user() (Harish)
- Only flush SVM garbage collector if CONFIG_DRM_XE_GPUSVM (Shuicheng)
- Fix forcewake vs runtime pm ref release ordering (Shuicheng)
- Move xe_device_sysfs_init() to xe_device_probe() (Raag)
- Append PCIe Gen5 limitations to xe_firmware document (Raag)

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

From: Thomas Hellstrom <thomas.hellstrom@linux.intel.com>
Link: https://lore.kernel.org/r/aBzUwbzCzz7Qo7fA@fedora
This commit is contained in:
Dave Airlie 2025-05-10 05:24:39 +10:00
commit 67322d35c3
25 changed files with 240 additions and 67 deletions

View File

@ -31,6 +31,12 @@ GuC Power Conservation (PC)
.. kernel-doc:: drivers/gpu/drm/xe/xe_guc_pc.c
:doc: GuC Power Conservation (PC)
PCIe Gen5 Limitations
=====================
.. kernel-doc:: drivers/gpu/drm/xe/xe_device_sysfs.c
:doc: PCIe Gen5 Limitations
Internal API
============

View File

@ -46,8 +46,11 @@ static void read_l3cc_table(struct xe_gt *gt,
unsigned int fw_ref, i;
u32 reg_val;
fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
KUNIT_ASSERT_NE_MSG(test, fw_ref, 0, "Forcewake Failed.\n");
fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) {
xe_force_wake_put(gt_to_fw(gt), fw_ref);
KUNIT_ASSERT_TRUE_MSG(test, true, "Forcewake Failed.\n");
}
for (i = 0; i < info->num_mocs_regs; i++) {
if (!(i & 1)) {

View File

@ -2569,7 +2569,7 @@ static int gem_create_user_ext_set_property(struct xe_device *xe,
int err;
u32 idx;
err = __copy_from_user(&ext, address, sizeof(ext));
err = copy_from_user(&ext, address, sizeof(ext));
if (XE_IOCTL_DBG(xe, err))
return -EFAULT;
@ -2606,7 +2606,7 @@ static int gem_create_user_extensions(struct xe_device *xe, struct xe_bo *bo,
if (XE_IOCTL_DBG(xe, ext_number >= MAX_USER_EXTENSIONS))
return -E2BIG;
err = __copy_from_user(&ext, address, sizeof(ext));
err = copy_from_user(&ext, address, sizeof(ext));
if (XE_IOCTL_DBG(xe, err))
return -EFAULT;

View File

@ -177,6 +177,8 @@ static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
struct xe_devcoredump *coredump = data;
struct xe_devcoredump_snapshot *ss;
ssize_t byte_copied;
u32 chunk_offset;
ssize_t new_chunk_position;
if (!coredump)
return -ENODEV;
@ -201,10 +203,14 @@ static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
return 0;
}
new_chunk_position = div_u64_rem(offset,
XE_DEVCOREDUMP_CHUNK_MAX,
&chunk_offset);
if (offset >= ss->read.chunk_position + XE_DEVCOREDUMP_CHUNK_MAX ||
offset < ss->read.chunk_position) {
ss->read.chunk_position =
ALIGN_DOWN(offset, XE_DEVCOREDUMP_CHUNK_MAX);
ss->read.chunk_position = new_chunk_position *
XE_DEVCOREDUMP_CHUNK_MAX;
__xe_devcoredump_read(ss->read.buffer,
XE_DEVCOREDUMP_CHUNK_MAX,
@ -213,8 +219,7 @@ static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
byte_copied = count < ss->read.size - offset ? count :
ss->read.size - offset;
memcpy(buffer, ss->read.buffer +
(offset % XE_DEVCOREDUMP_CHUNK_MAX), byte_copied);
memcpy(buffer, ss->read.buffer + chunk_offset, byte_copied);
mutex_unlock(&coredump->lock);

View File

@ -26,6 +26,7 @@
#include "xe_bo_evict.h"
#include "xe_debugfs.h"
#include "xe_devcoredump.h"
#include "xe_device_sysfs.h"
#include "xe_dma_buf.h"
#include "xe_drm_client.h"
#include "xe_drv.h"
@ -915,6 +916,10 @@ int xe_device_probe(struct xe_device *xe)
if (err)
goto err_unregister_display;
err = xe_device_sysfs_init(xe);
if (err)
goto err_unregister_display;
xe_debugfs_register(xe);
err = xe_hwmon_register(xe);

View File

@ -3,14 +3,16 @@
* Copyright © 2023 Intel Corporation
*/
#include <linux/device.h>
#include <linux/kobject.h>
#include <linux/pci.h>
#include <linux/sysfs.h>
#include <drm/drm_managed.h>
#include "xe_device.h"
#include "xe_device_sysfs.h"
#include "xe_mmio.h"
#include "xe_pcode_api.h"
#include "xe_pcode.h"
#include "xe_pm.h"
/**
@ -63,11 +65,93 @@ vram_d3cold_threshold_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RW(vram_d3cold_threshold);
/**
* DOC: PCIe Gen5 Limitations
*
* Default link speed of discrete GPUs is determined by configuration parameters
* stored in their flash memory, which are subject to override through user
* initiated firmware updates. It has been observed that devices configured with
* PCIe Gen5 as their default link speed can come across link quality issues due
* to host or motherboard limitations and may have to auto-downgrade their link
* to PCIe Gen4 speed when faced with unstable link at Gen5, which makes
* firmware updates rather risky on such setups. It is required to ensure that
* the device is capable of auto-downgrading its link to PCIe Gen4 speed before
* pushing the firmware image with PCIe Gen5 as default configuration. This can
* be done by reading ``auto_link_downgrade_capable`` sysfs entry, which will
* denote if the device is capable of auto-downgrading its link to PCIe Gen4
* speed with boolean output value of ``0`` or ``1``, meaning `incapable` or
* `capable` respectively.
*
* .. code-block:: shell
*
* $ cat /sys/bus/pci/devices/<bdf>/auto_link_downgrade_capable
*
* Pushing the firmware image with PCIe Gen5 as default configuration on a auto
* link downgrade incapable device and facing link instability due to host or
* motherboard limitations can result in driver failing to bind to the device,
* making further firmware updates impossible with RMA being the only last
* resort.
*
* Link downgrade status of auto link downgrade capable devices is available
* through ``auto_link_downgrade_status`` sysfs entry with boolean output value
* of ``0`` or ``1``, where ``0`` means no auto-downgrading was required during
* link training (which is the optimal scenario) and ``1`` means the device has
* auto-downgraded its link to PCIe Gen4 speed due to unstable Gen5 link.
*
* .. code-block:: shell
*
* $ cat /sys/bus/pci/devices/<bdf>/auto_link_downgrade_status
*/
static ssize_t
auto_link_downgrade_capable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct xe_device *xe = pdev_to_xe_device(pdev);
u32 cap, val;
xe_pm_runtime_get(xe);
val = xe_mmio_read32(xe_root_tile_mmio(xe), BMG_PCIE_CAP);
xe_pm_runtime_put(xe);
cap = REG_FIELD_GET(LINK_DOWNGRADE, val);
return sysfs_emit(buf, "%u\n", cap == DOWNGRADE_CAPABLE ? true : false);
}
static DEVICE_ATTR_ADMIN_RO(auto_link_downgrade_capable);
static ssize_t
auto_link_downgrade_status_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct xe_device *xe = pdev_to_xe_device(pdev);
u32 val;
int ret;
xe_pm_runtime_get(xe);
ret = xe_pcode_read(xe_device_get_root_tile(xe),
PCODE_MBOX(DGFX_PCODE_STATUS, DGFX_GET_INIT_STATUS, 0),
&val, NULL);
xe_pm_runtime_put(xe);
return ret ?: sysfs_emit(buf, "%u\n", REG_FIELD_GET(DGFX_LINK_DOWNGRADE_STATUS, val));
}
static DEVICE_ATTR_ADMIN_RO(auto_link_downgrade_status);
static const struct attribute *auto_link_downgrade_attrs[] = {
&dev_attr_auto_link_downgrade_capable.attr,
&dev_attr_auto_link_downgrade_status.attr,
NULL
};
static void xe_device_sysfs_fini(void *arg)
{
struct xe_device *xe = arg;
sysfs_remove_file(&xe->drm.dev->kobj, &dev_attr_vram_d3cold_threshold.attr);
if (xe->d3cold.capable)
sysfs_remove_file(&xe->drm.dev->kobj, &dev_attr_vram_d3cold_threshold.attr);
if (xe->info.platform == XE_BATTLEMAGE)
sysfs_remove_files(&xe->drm.dev->kobj, auto_link_downgrade_attrs);
}
int xe_device_sysfs_init(struct xe_device *xe)
@ -75,9 +159,17 @@ int xe_device_sysfs_init(struct xe_device *xe)
struct device *dev = xe->drm.dev;
int ret;
ret = sysfs_create_file(&dev->kobj, &dev_attr_vram_d3cold_threshold.attr);
if (ret)
return ret;
if (xe->d3cold.capable) {
ret = sysfs_create_file(&dev->kobj, &dev_attr_vram_d3cold_threshold.attr);
if (ret)
return ret;
}
if (xe->info.platform == XE_BATTLEMAGE) {
ret = sysfs_create_files(&dev->kobj, auto_link_downgrade_attrs);
if (ret)
return ret;
}
return devm_add_action_or_reset(dev, xe_device_sysfs_fini, xe);
}

View File

@ -283,7 +283,7 @@ static int xe_eu_stall_user_ext_set_property(struct xe_device *xe, u64 extension
int err;
u32 idx;
err = __copy_from_user(&ext, address, sizeof(ext));
err = copy_from_user(&ext, address, sizeof(ext));
if (XE_IOCTL_DBG(xe, err))
return -EFAULT;
@ -313,7 +313,7 @@ static int xe_eu_stall_user_extensions(struct xe_device *xe, u64 extension,
if (XE_IOCTL_DBG(xe, ext_number >= MAX_USER_EXTENSIONS))
return -E2BIG;
err = __copy_from_user(&ext, address, sizeof(ext));
err = copy_from_user(&ext, address, sizeof(ext));
if (XE_IOCTL_DBG(xe, err))
return -EFAULT;

View File

@ -176,8 +176,8 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
}
if (xe_exec_queue_is_parallel(q)) {
err = __copy_from_user(addresses, addresses_user, sizeof(u64) *
q->width);
err = copy_from_user(addresses, addresses_user, sizeof(u64) *
q->width);
if (err) {
err = -EFAULT;
goto err_syncs;

View File

@ -479,7 +479,7 @@ static int exec_queue_user_ext_set_property(struct xe_device *xe,
int err;
u32 idx;
err = __copy_from_user(&ext, address, sizeof(ext));
err = copy_from_user(&ext, address, sizeof(ext));
if (XE_IOCTL_DBG(xe, err))
return -EFAULT;
@ -518,7 +518,7 @@ static int exec_queue_user_extensions(struct xe_device *xe, struct xe_exec_queue
if (XE_IOCTL_DBG(xe, ext_number >= MAX_USER_EXTENSIONS))
return -E2BIG;
err = __copy_from_user(&ext, address, sizeof(ext));
err = copy_from_user(&ext, address, sizeof(ext));
if (XE_IOCTL_DBG(xe, err))
return -EFAULT;
@ -618,9 +618,8 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
if (XE_IOCTL_DBG(xe, !len || len > XE_HW_ENGINE_MAX_INSTANCE))
return -EINVAL;
err = __copy_from_user(eci, user_eci,
sizeof(struct drm_xe_engine_class_instance) *
len);
err = copy_from_user(eci, user_eci,
sizeof(struct drm_xe_engine_class_instance) * len);
if (XE_IOCTL_DBG(xe, err))
return -EFAULT;

View File

@ -555,6 +555,28 @@ void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc)
flush_work(&gsc->work);
}
void xe_gsc_stop_prepare(struct xe_gsc *gsc)
{
struct xe_gt *gt = gsc_to_gt(gsc);
int ret;
if (!xe_uc_fw_is_loadable(&gsc->fw) || xe_uc_fw_is_in_error_state(&gsc->fw))
return;
xe_force_wake_assert_held(gt_to_fw(gt), XE_FW_GSC);
/*
* If the GSC FW load or the proxy init are interrupted, the only way
* to recover it is to do an FLR and reload the GSC from scratch.
* Therefore, let's wait for the init to complete before stopping
* operations. The proxy init is the last step, so we can just wait on
* that
*/
ret = xe_gsc_wait_for_proxy_init_done(gsc);
if (ret)
xe_gt_err(gt, "failed to wait for GSC init completion before uc stop\n");
}
/*
* wa_14015076503: if the GSC FW is loaded, we need to alert it before doing a
* GSC engine reset by writing a notification bit in the GS1 register and then

View File

@ -16,6 +16,7 @@ struct xe_hw_engine;
int xe_gsc_init(struct xe_gsc *gsc);
int xe_gsc_init_post_hwconfig(struct xe_gsc *gsc);
void xe_gsc_wait_for_worker_completion(struct xe_gsc *gsc);
void xe_gsc_stop_prepare(struct xe_gsc *gsc);
void xe_gsc_load_start(struct xe_gsc *gsc);
void xe_gsc_hwe_irq_handler(struct xe_hw_engine *hwe, u16 intr_vec);

View File

@ -71,6 +71,17 @@ bool xe_gsc_proxy_init_done(struct xe_gsc *gsc)
HECI1_FWSTS1_PROXY_STATE_NORMAL;
}
int xe_gsc_wait_for_proxy_init_done(struct xe_gsc *gsc)
{
struct xe_gt *gt = gsc_to_gt(gsc);
/* Proxy init can take up to 500ms, so wait double that for safety */
return xe_mmio_wait32(&gt->mmio, HECI_FWSTS1(MTL_GSC_HECI1_BASE),
HECI1_FWSTS1_CURRENT_STATE,
HECI1_FWSTS1_PROXY_STATE_NORMAL,
USEC_PER_SEC, NULL, false);
}
static void __gsc_proxy_irq_rmw(struct xe_gsc *gsc, u32 clr, u32 set)
{
struct xe_gt *gt = gsc_to_gt(gsc);

View File

@ -12,6 +12,7 @@ struct xe_gsc;
int xe_gsc_proxy_init(struct xe_gsc *gsc);
bool xe_gsc_proxy_init_done(struct xe_gsc *gsc);
int xe_gsc_wait_for_proxy_init_done(struct xe_gsc *gsc);
int xe_gsc_proxy_start(struct xe_gsc *gsc);
int xe_gsc_proxy_request_handler(struct xe_gsc *gsc);

View File

@ -899,7 +899,7 @@ void xe_gt_suspend_prepare(struct xe_gt *gt)
fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
xe_uc_stop_prepare(&gt->uc);
xe_uc_suspend_prepare(&gt->uc);
xe_force_wake_put(gt_to_fw(gt), fw_ref);
}

View File

@ -92,22 +92,23 @@ static int hw_engines(struct xe_gt *gt, struct drm_printer *p)
struct xe_hw_engine *hwe;
enum xe_hw_engine_id id;
unsigned int fw_ref;
int ret = 0;
xe_pm_runtime_get(xe);
fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL)) {
xe_pm_runtime_put(xe);
xe_force_wake_put(gt_to_fw(gt), fw_ref);
return -ETIMEDOUT;
ret = -ETIMEDOUT;
goto fw_put;
}
for_each_hw_engine(hwe, gt, id)
xe_hw_engine_print(hwe, p);
fw_put:
xe_force_wake_put(gt_to_fw(gt), fw_ref);
xe_pm_runtime_put(xe);
return 0;
return ret;
}
static int powergate_info(struct xe_gt *gt, struct drm_printer *p)

View File

@ -1510,30 +1510,32 @@ void xe_guc_print_info(struct xe_guc *guc, struct drm_printer *p)
xe_uc_fw_print(&guc->fw, p);
fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
if (!fw_ref)
return;
if (!IS_SRIOV_VF(gt_to_xe(gt))) {
fw_ref = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
if (!fw_ref)
return;
status = xe_mmio_read32(&gt->mmio, GUC_STATUS);
status = xe_mmio_read32(&gt->mmio, GUC_STATUS);
drm_printf(p, "\nGuC status 0x%08x:\n", status);
drm_printf(p, "\tBootrom status = 0x%x\n",
REG_FIELD_GET(GS_BOOTROM_MASK, status));
drm_printf(p, "\tuKernel status = 0x%x\n",
REG_FIELD_GET(GS_UKERNEL_MASK, status));
drm_printf(p, "\tMIA Core status = 0x%x\n",
REG_FIELD_GET(GS_MIA_MASK, status));
drm_printf(p, "\tLog level = %d\n",
xe_guc_log_get_level(&guc->log));
drm_printf(p, "\nGuC status 0x%08x:\n", status);
drm_printf(p, "\tBootrom status = 0x%x\n",
REG_FIELD_GET(GS_BOOTROM_MASK, status));
drm_printf(p, "\tuKernel status = 0x%x\n",
REG_FIELD_GET(GS_UKERNEL_MASK, status));
drm_printf(p, "\tMIA Core status = 0x%x\n",
REG_FIELD_GET(GS_MIA_MASK, status));
drm_printf(p, "\tLog level = %d\n",
xe_guc_log_get_level(&guc->log));
drm_puts(p, "\nScratch registers:\n");
for (i = 0; i < SOFT_SCRATCH_COUNT; i++) {
drm_printf(p, "\t%2d: \t0x%x\n",
i, xe_mmio_read32(&gt->mmio, SOFT_SCRATCH(i)));
drm_puts(p, "\nScratch registers:\n");
for (i = 0; i < SOFT_SCRATCH_COUNT; i++) {
drm_printf(p, "\t%2d: \t0x%x\n",
i, xe_mmio_read32(&gt->mmio, SOFT_SCRATCH(i)));
}
xe_force_wake_put(gt_to_fw(gt), fw_ref);
}
xe_force_wake_put(gt_to_fw(gt), fw_ref);
drm_puts(p, "\n");
xe_guc_ct_print(&guc->ct, p, false);

View File

@ -1179,9 +1179,12 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
process_name = q->vm->xef->process_name;
pid = q->vm->xef->pid;
}
xe_gt_notice(guc_to_gt(guc), "Timedout job: seqno=%u, lrc_seqno=%u, guc_id=%d, flags=0x%lx in %s [%d]",
xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job),
q->guc->id, q->flags, process_name, pid);
if (!exec_queue_killed(q))
xe_gt_notice(guc_to_gt(guc),
"Timedout job: seqno=%u, lrc_seqno=%u, guc_id=%d, flags=0x%lx in %s [%d]",
xe_sched_job_seqno(job), xe_sched_job_lrc_seqno(job),
q->guc->id, q->flags, process_name, pid);
trace_xe_sched_job_timedout(job);

View File

@ -1301,7 +1301,7 @@ static int xe_oa_user_ext_set_property(struct xe_oa *oa, enum xe_oa_user_extn_fr
int err;
u32 idx;
err = __copy_from_user(&ext, address, sizeof(ext));
err = copy_from_user(&ext, address, sizeof(ext));
if (XE_IOCTL_DBG(oa->xe, err))
return -EFAULT;
@ -1338,7 +1338,7 @@ static int xe_oa_user_extensions(struct xe_oa *oa, enum xe_oa_user_extn_from fro
if (XE_IOCTL_DBG(oa->xe, ext_number >= MAX_USER_EXTENSIONS))
return -E2BIG;
err = __copy_from_user(&ext, address, sizeof(ext));
err = copy_from_user(&ext, address, sizeof(ext));
if (XE_IOCTL_DBG(oa->xe, err))
return -EFAULT;
@ -2281,7 +2281,7 @@ int xe_oa_add_config_ioctl(struct drm_device *dev, u64 data, struct drm_file *fi
return -EACCES;
}
err = __copy_from_user(&param, u64_to_user_ptr(data), sizeof(param));
err = copy_from_user(&param, u64_to_user_ptr(data), sizeof(param));
if (XE_IOCTL_DBG(oa->xe, err))
return -EFAULT;

View File

@ -34,6 +34,7 @@
#define DGFX_PCODE_STATUS 0x7E
#define DGFX_GET_INIT_STATUS 0x0
#define DGFX_INIT_STATUS_COMPLETE 0x1
#define DGFX_LINK_DOWNGRADE_STATUS REG_BIT(31)
#define PCODE_POWER_SETUP 0x7C
#define POWER_SETUP_SUBCOMMAND_READ_I1 0x4
@ -66,6 +67,10 @@
/* Auxiliary info bits */
#define AUXINFO_HISTORY_OFFSET REG_GENMASK(31, 29)
#define BMG_PCIE_CAP XE_REG(0x138340)
#define LINK_DOWNGRADE REG_GENMASK(1, 0)
#define DOWNGRADE_CAPABLE 2
struct pcode_err_decode {
int errno;
const char *str;

View File

@ -16,7 +16,6 @@
#include "xe_bo.h"
#include "xe_bo_evict.h"
#include "xe_device.h"
#include "xe_device_sysfs.h"
#include "xe_ggtt.h"
#include "xe_gt.h"
#include "xe_guc.h"
@ -273,6 +272,7 @@ int xe_pm_init_early(struct xe_device *xe)
if (err)
return err;
xe->d3cold.capable = xe_pm_pci_d3cold_capable(xe);
return 0;
}
ALLOW_ERROR_INJECTION(xe_pm_init_early, ERRNO); /* See xe_pci_probe() */
@ -344,13 +344,7 @@ int xe_pm_init(struct xe_device *xe)
if (!xe_device_uc_enabled(xe))
return 0;
xe->d3cold.capable = xe_pm_pci_d3cold_capable(xe);
if (xe->d3cold.capable) {
err = xe_device_sysfs_init(xe);
if (err)
goto err_unregister;
vram_threshold = vram_threshold_value(xe);
err = xe_pm_set_vram_threshold(xe, vram_threshold);
if (err)

View File

@ -726,7 +726,6 @@ static int xe_svm_alloc_vram(struct xe_vm *vm, struct xe_tile *tile,
}
#endif
/**
* xe_svm_handle_pagefault() - SVM handle page fault
* @vm: The VM.
@ -966,3 +965,15 @@ int xe_devm_add(struct xe_tile *tile, struct xe_vram_region *vr)
return 0;
}
#endif
/**
* xe_svm_flush() - SVM flush
* @vm: The VM.
*
* Flush all SVM actions.
*/
void xe_svm_flush(struct xe_vm *vm)
{
if (xe_vm_in_fault_mode(vm))
flush_work(&vm->svm.garbage_collector.work);
}

View File

@ -96,6 +96,8 @@ static inline bool xe_svm_range_has_dma_mapping(struct xe_svm_range *range)
#define xe_svm_notifier_unlock(vm__) \
drm_gpusvm_notifier_unlock(&(vm__)->svm.gpusvm)
void xe_svm_flush(struct xe_vm *vm);
#else
#include <linux/interval_tree.h>
@ -180,5 +182,9 @@ static inline void xe_svm_notifier_lock(struct xe_vm *vm)
static inline void xe_svm_notifier_unlock(struct xe_vm *vm)
{
}
static inline void xe_svm_flush(struct xe_vm *vm)
{
}
#endif
#endif

View File

@ -244,7 +244,7 @@ void xe_uc_gucrc_disable(struct xe_uc *uc)
void xe_uc_stop_prepare(struct xe_uc *uc)
{
xe_gsc_wait_for_worker_completion(&uc->gsc);
xe_gsc_stop_prepare(&uc->gsc);
xe_guc_stop_prepare(&uc->guc);
}
@ -278,6 +278,12 @@ static void uc_reset_wait(struct xe_uc *uc)
goto again;
}
void xe_uc_suspend_prepare(struct xe_uc *uc)
{
xe_gsc_wait_for_worker_completion(&uc->gsc);
xe_guc_stop_prepare(&uc->guc);
}
int xe_uc_suspend(struct xe_uc *uc)
{
/* GuC submission not enabled, nothing to do */

View File

@ -18,6 +18,7 @@ int xe_uc_reset_prepare(struct xe_uc *uc);
void xe_uc_stop_prepare(struct xe_uc *uc);
void xe_uc_stop(struct xe_uc *uc);
int xe_uc_start(struct xe_uc *uc);
void xe_uc_suspend_prepare(struct xe_uc *uc);
int xe_uc_suspend(struct xe_uc *uc);
int xe_uc_sanitize_reset(struct xe_uc *uc);
void xe_uc_declare_wedged(struct xe_uc *uc);

View File

@ -3101,9 +3101,9 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe, struct xe_vm *vm,
if (!*bind_ops)
return args->num_binds > 1 ? -ENOBUFS : -ENOMEM;
err = __copy_from_user(*bind_ops, bind_user,
sizeof(struct drm_xe_vm_bind_op) *
args->num_binds);
err = copy_from_user(*bind_ops, bind_user,
sizeof(struct drm_xe_vm_bind_op) *
args->num_binds);
if (XE_IOCTL_DBG(xe, err)) {
err = -EFAULT;
goto free_bind_ops;
@ -3331,8 +3331,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
}
/* Ensure all UNMAPs visible */
if (xe_vm_in_fault_mode(vm))
flush_work(&vm->svm.garbage_collector.work);
xe_svm_flush(vm);
err = down_write_killable(&vm->lock);
if (err)