mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 02:36:02 +00:00
Driver Changes:
- Missing init value and 64-bit write-order check (Zhanjung) - Fix a memory allocation issue causing lockdep violation (John) -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQRskUM7w1oG5rx2IZO4FpNVCsYGvwUCZ1BhxgAKCRC4FpNVCsYG v2uQAQCIk8ZDX14Yga2GDj2IQ2cpzGfjWMOAYzo4F5mpefUC6AD+JMFMhcws6O+Q QlYk/bE/vT0BKD1nHmqqWyEFh8hZMgU= =j5CV -----END PGP SIGNATURE----- Merge tag 'drm-xe-fixes-2024-12-04' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-fixes Driver Changes: - Missing init value and 64-bit write-order check (Zhanjung) - Fix a memory allocation issue causing lockdep violation (John) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Hellstrom <thomas.hellstrom@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/Z1BidZBFQOLjz__J@fedora
This commit is contained in:
commit
915bac607f
@ -155,36 +155,6 @@ static void xe_devcoredump_snapshot_free(struct xe_devcoredump_snapshot *ss)
|
|||||||
ss->vm = NULL;
|
ss->vm = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xe_devcoredump_deferred_snap_work(struct work_struct *work)
|
|
||||||
{
|
|
||||||
struct xe_devcoredump_snapshot *ss = container_of(work, typeof(*ss), work);
|
|
||||||
struct xe_devcoredump *coredump = container_of(ss, typeof(*coredump), snapshot);
|
|
||||||
struct xe_device *xe = coredump_to_xe(coredump);
|
|
||||||
unsigned int fw_ref;
|
|
||||||
|
|
||||||
xe_pm_runtime_get(xe);
|
|
||||||
|
|
||||||
/* keep going if fw fails as we still want to save the memory and SW data */
|
|
||||||
fw_ref = xe_force_wake_get(gt_to_fw(ss->gt), XE_FORCEWAKE_ALL);
|
|
||||||
if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
|
|
||||||
xe_gt_info(ss->gt, "failed to get forcewake for coredump capture\n");
|
|
||||||
xe_vm_snapshot_capture_delayed(ss->vm);
|
|
||||||
xe_guc_exec_queue_snapshot_capture_delayed(ss->ge);
|
|
||||||
xe_force_wake_put(gt_to_fw(ss->gt), fw_ref);
|
|
||||||
|
|
||||||
xe_pm_runtime_put(xe);
|
|
||||||
|
|
||||||
/* Calculate devcoredump size */
|
|
||||||
ss->read.size = __xe_devcoredump_read(NULL, INT_MAX, coredump);
|
|
||||||
|
|
||||||
ss->read.buffer = kvmalloc(ss->read.size, GFP_USER);
|
|
||||||
if (!ss->read.buffer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
__xe_devcoredump_read(ss->read.buffer, ss->read.size, coredump);
|
|
||||||
xe_devcoredump_snapshot_free(ss);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
|
static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
|
||||||
size_t count, void *data, size_t datalen)
|
size_t count, void *data, size_t datalen)
|
||||||
{
|
{
|
||||||
@ -234,6 +204,45 @@ static void xe_devcoredump_free(void *data)
|
|||||||
"Xe device coredump has been deleted.\n");
|
"Xe device coredump has been deleted.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xe_devcoredump_deferred_snap_work(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct xe_devcoredump_snapshot *ss = container_of(work, typeof(*ss), work);
|
||||||
|
struct xe_devcoredump *coredump = container_of(ss, typeof(*coredump), snapshot);
|
||||||
|
struct xe_device *xe = coredump_to_xe(coredump);
|
||||||
|
unsigned int fw_ref;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NB: Despite passing a GFP_ flags parameter here, more allocations are done
|
||||||
|
* internally using GFP_KERNEL expliictly. Hence this call must be in the worker
|
||||||
|
* thread and not in the initial capture call.
|
||||||
|
*/
|
||||||
|
dev_coredumpm_timeout(gt_to_xe(ss->gt)->drm.dev, THIS_MODULE, coredump, 0, GFP_KERNEL,
|
||||||
|
xe_devcoredump_read, xe_devcoredump_free,
|
||||||
|
XE_COREDUMP_TIMEOUT_JIFFIES);
|
||||||
|
|
||||||
|
xe_pm_runtime_get(xe);
|
||||||
|
|
||||||
|
/* keep going if fw fails as we still want to save the memory and SW data */
|
||||||
|
fw_ref = xe_force_wake_get(gt_to_fw(ss->gt), XE_FORCEWAKE_ALL);
|
||||||
|
if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
|
||||||
|
xe_gt_info(ss->gt, "failed to get forcewake for coredump capture\n");
|
||||||
|
xe_vm_snapshot_capture_delayed(ss->vm);
|
||||||
|
xe_guc_exec_queue_snapshot_capture_delayed(ss->ge);
|
||||||
|
xe_force_wake_put(gt_to_fw(ss->gt), fw_ref);
|
||||||
|
|
||||||
|
xe_pm_runtime_put(xe);
|
||||||
|
|
||||||
|
/* Calculate devcoredump size */
|
||||||
|
ss->read.size = __xe_devcoredump_read(NULL, INT_MAX, coredump);
|
||||||
|
|
||||||
|
ss->read.buffer = kvmalloc(ss->read.size, GFP_USER);
|
||||||
|
if (!ss->read.buffer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
__xe_devcoredump_read(ss->read.buffer, ss->read.size, coredump);
|
||||||
|
xe_devcoredump_snapshot_free(ss);
|
||||||
|
}
|
||||||
|
|
||||||
static void devcoredump_snapshot(struct xe_devcoredump *coredump,
|
static void devcoredump_snapshot(struct xe_devcoredump *coredump,
|
||||||
struct xe_sched_job *job)
|
struct xe_sched_job *job)
|
||||||
{
|
{
|
||||||
@ -310,10 +319,6 @@ void xe_devcoredump(struct xe_sched_job *job)
|
|||||||
drm_info(&xe->drm, "Xe device coredump has been created\n");
|
drm_info(&xe->drm, "Xe device coredump has been created\n");
|
||||||
drm_info(&xe->drm, "Check your /sys/class/drm/card%d/device/devcoredump/data\n",
|
drm_info(&xe->drm, "Check your /sys/class/drm/card%d/device/devcoredump/data\n",
|
||||||
xe->drm.primary->index);
|
xe->drm.primary->index);
|
||||||
|
|
||||||
dev_coredumpm_timeout(xe->drm.dev, THIS_MODULE, coredump, 0, GFP_KERNEL,
|
|
||||||
xe_devcoredump_read, xe_devcoredump_free,
|
|
||||||
XE_COREDUMP_TIMEOUT_JIFFIES);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xe_driver_devcoredump_fini(void *arg)
|
static void xe_driver_devcoredump_fini(void *arg)
|
||||||
|
@ -102,6 +102,7 @@ struct __guc_capture_parsed_output {
|
|||||||
* A 64 bit register define requires 2 consecutive entries,
|
* A 64 bit register define requires 2 consecutive entries,
|
||||||
* with low dword first and hi dword the second.
|
* with low dword first and hi dword the second.
|
||||||
* 2. Register name: null for incompleted define
|
* 2. Register name: null for incompleted define
|
||||||
|
* 3. Incorrect order will trigger XE_WARN.
|
||||||
*/
|
*/
|
||||||
#define COMMON_XELP_BASE_GLOBAL \
|
#define COMMON_XELP_BASE_GLOBAL \
|
||||||
{ FORCEWAKE_GT, REG_32BIT, 0, 0, "FORCEWAKE_GT"}
|
{ FORCEWAKE_GT, REG_32BIT, 0, 0, "FORCEWAKE_GT"}
|
||||||
@ -1675,10 +1676,10 @@ snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_
|
|||||||
struct xe_devcoredump *devcoredump = &xe->devcoredump;
|
struct xe_devcoredump *devcoredump = &xe->devcoredump;
|
||||||
struct xe_devcoredump_snapshot *devcore_snapshot = &devcoredump->snapshot;
|
struct xe_devcoredump_snapshot *devcore_snapshot = &devcoredump->snapshot;
|
||||||
struct gcap_reg_list_info *reginfo = NULL;
|
struct gcap_reg_list_info *reginfo = NULL;
|
||||||
u32 last_value, i;
|
u32 i, last_value = 0;
|
||||||
bool is_ext;
|
bool is_ext, low32_ready = false;
|
||||||
|
|
||||||
if (!list || list->num_regs == 0)
|
if (!list || !list->list || list->num_regs == 0)
|
||||||
return;
|
return;
|
||||||
XE_WARN_ON(!devcore_snapshot->matched_node);
|
XE_WARN_ON(!devcore_snapshot->matched_node);
|
||||||
|
|
||||||
@ -1701,17 +1702,53 @@ snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
value = reg->value;
|
value = reg->value;
|
||||||
if (reg_desc->data_type == REG_64BIT_LOW_DW) {
|
switch (reg_desc->data_type) {
|
||||||
|
case REG_64BIT_LOW_DW:
|
||||||
last_value = value;
|
last_value = value;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A 64 bit register define requires 2 consecutive
|
||||||
|
* entries in register list, with low dword first
|
||||||
|
* and hi dword the second, like:
|
||||||
|
* { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
|
||||||
|
* { XXX_REG_HI(0), REG_64BIT_HI_DW, 0, 0, "XXX_REG"},
|
||||||
|
*
|
||||||
|
* Incorrect order will trigger XE_WARN.
|
||||||
|
*
|
||||||
|
* Possible double low here, for example:
|
||||||
|
* { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
|
||||||
|
* { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
|
||||||
|
*/
|
||||||
|
XE_WARN_ON(low32_ready);
|
||||||
|
low32_ready = true;
|
||||||
/* Low 32 bit dword saved, continue for high 32 bit */
|
/* Low 32 bit dword saved, continue for high 32 bit */
|
||||||
continue;
|
break;
|
||||||
} else if (reg_desc->data_type == REG_64BIT_HI_DW) {
|
|
||||||
|
case REG_64BIT_HI_DW: {
|
||||||
u64 value_qw = ((u64)value << 32) | last_value;
|
u64 value_qw = ((u64)value << 32) | last_value;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Incorrect 64bit register order. Possible missing low.
|
||||||
|
* for example:
|
||||||
|
* { XXX_REG(0), REG_32BIT, 0, 0, NULL},
|
||||||
|
* { XXX_REG_HI(0), REG_64BIT_HI_DW, 0, 0, NULL},
|
||||||
|
*/
|
||||||
|
XE_WARN_ON(!low32_ready);
|
||||||
|
low32_ready = false;
|
||||||
|
|
||||||
drm_printf(p, "\t%s: 0x%016llx\n", reg_desc->regname, value_qw);
|
drm_printf(p, "\t%s: 0x%016llx\n", reg_desc->regname, value_qw);
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case REG_32BIT:
|
||||||
|
/*
|
||||||
|
* Incorrect 64bit register order. Possible missing high.
|
||||||
|
* for example:
|
||||||
|
* { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
|
||||||
|
* { XXX_REG(0), REG_32BIT, 0, 0, "XXX_REG"},
|
||||||
|
*/
|
||||||
|
XE_WARN_ON(low32_ready);
|
||||||
|
|
||||||
if (is_ext) {
|
if (is_ext) {
|
||||||
int dss, group, instance;
|
int dss, group, instance;
|
||||||
|
|
||||||
@ -1723,9 +1760,19 @@ snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_
|
|||||||
} else {
|
} else {
|
||||||
drm_printf(p, "\t%s: 0x%08x\n", reg_desc->regname, value);
|
drm_printf(p, "\t%s: 0x%08x\n", reg_desc->regname, value);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Incorrect 64bit register order. Possible missing high.
|
||||||
|
* for example:
|
||||||
|
* { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
|
||||||
|
* } // <- Register list end
|
||||||
|
*/
|
||||||
|
XE_WARN_ON(low32_ready);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xe_engine_snapshot_print - Print out a given Xe HW Engine snapshot.
|
* xe_engine_snapshot_print - Print out a given Xe HW Engine snapshot.
|
||||||
* @snapshot: Xe HW Engine snapshot object.
|
* @snapshot: Xe HW Engine snapshot object.
|
||||||
|
Loading…
Reference in New Issue
Block a user