Commit 485442c6 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-xe-fixes-2025-04-10' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-fixes



Driver Changes:
- Add another BMG PCI ID
- Fix UAFs on migration paths
- Fix shift-out-of-bounds access on TLB invalidation
- Ensure ccs_mode is correctly set on gt reset
- Extend some HW workarounds to Xe3
- Fix PM runtime get/put on sysfs files
- Fix u64 division on 32b
- Fix flickering due to missing L3 invalidations
- Fix missing error code return

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

From: Lucas De Marchi <lucas.demarchi@intel.com>
Link: https://lore.kernel.org/r/unq5j26aejbrjz5nuvmdtcgupyix5bacpoahod4bdohlvwrney@kekimsi5ossx
parents 927cec6c 88ecb66b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@

#define GFX_OP_PIPE_CONTROL(len)	((0x3<<29)|(0x3<<27)|(0x2<<24)|((len)-2))

#define	  PIPE_CONTROL0_L3_READ_ONLY_CACHE_INVALIDATE	BIT(10)	/* gen12 */
#define	  PIPE_CONTROL0_HDC_PIPELINE_FLUSH		BIT(9)	/* gen12 */

#define   PIPE_CONTROL_COMMAND_CACHE_INVALIDATE		(1<<29)
+10 −2
Original line number Diff line number Diff line
@@ -322,6 +322,13 @@ int xe_gt_tlb_invalidation_ggtt(struct xe_gt *gt)
	return 0;
}

/*
 * Ensure that roundup_pow_of_two(length) doesn't overflow.
 * Note that roundup_pow_of_two() operates on unsigned long,
 * not on u64.
 */
#define MAX_RANGE_TLB_INVALIDATION_LENGTH (rounddown_pow_of_two(ULONG_MAX))

/**
 * xe_gt_tlb_invalidation_range - Issue a TLB invalidation on this GT for an
 * address range
@@ -346,6 +353,7 @@ int xe_gt_tlb_invalidation_range(struct xe_gt *gt,
	struct xe_device *xe = gt_to_xe(gt);
#define MAX_TLB_INVALIDATION_LEN	7
	u32 action[MAX_TLB_INVALIDATION_LEN];
	u64 length = end - start;
	int len = 0;

	xe_gt_assert(gt, fence);
@@ -358,11 +366,11 @@ int xe_gt_tlb_invalidation_range(struct xe_gt *gt,

	action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
	action[len++] = 0; /* seqno, replaced in send_tlb_invalidation */
	if (!xe->info.has_range_tlb_invalidation) {
	if (!xe->info.has_range_tlb_invalidation ||
	    length > MAX_RANGE_TLB_INVALIDATION_LENGTH) {
		action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL);
	} else {
		u64 orig_start = start;
		u64 length = end - start;
		u64 align;

		if (length < SZ_4K)
+1 −0
Original line number Diff line number Diff line
@@ -1070,6 +1070,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc)
		if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING,
				      SLPC_RESET_EXTENDED_TIMEOUT_MS)) {
			xe_gt_err(gt, "GuC PC Start failed: Dynamic GT frequency control and GT sleep states are now disabled.\n");
			ret = -EIO;
			goto out;
		}

+6 −6
Original line number Diff line number Diff line
@@ -389,12 +389,6 @@ xe_hw_engine_setup_default_lrc_state(struct xe_hw_engine *hwe)
				 blit_cctl_val,
				 XE_RTP_ACTION_FLAG(ENGINE_BASE)))
		},
		/* Use Fixed slice CCS mode */
		{ XE_RTP_NAME("RCU_MODE_FIXED_SLICE_CCS_MODE"),
		  XE_RTP_RULES(FUNC(xe_hw_engine_match_fixed_cslice_mode)),
		  XE_RTP_ACTIONS(FIELD_SET(RCU_MODE, RCU_MODE_FIXED_SLICE_CCS_MODE,
					   RCU_MODE_FIXED_SLICE_CCS_MODE))
		},
		/* Disable WMTP if HW doesn't support it */
		{ XE_RTP_NAME("DISABLE_WMTP_ON_UNSUPPORTED_HW"),
		  XE_RTP_RULES(FUNC(xe_rtp_cfeg_wmtp_disabled)),
@@ -461,6 +455,12 @@ hw_engine_setup_default_state(struct xe_hw_engine *hwe)
		  XE_RTP_ACTIONS(SET(CSFE_CHICKEN1(0), CS_PRIORITY_MEM_READ,
				     XE_RTP_ACTION_FLAG(ENGINE_BASE)))
		},
		/* Use Fixed slice CCS mode */
		{ XE_RTP_NAME("RCU_MODE_FIXED_SLICE_CCS_MODE"),
		  XE_RTP_RULES(FUNC(xe_hw_engine_match_fixed_cslice_mode)),
		  XE_RTP_ACTIONS(FIELD_SET(RCU_MODE, RCU_MODE_FIXED_SLICE_CCS_MODE,
					   RCU_MODE_FIXED_SLICE_CCS_MODE))
		},
	};

	xe_rtp_process_to_sr(&ctx, engine_entries, ARRAY_SIZE(engine_entries), &hwe->reg_sr);
+52 −56
Original line number Diff line number Diff line
@@ -32,14 +32,61 @@ bool xe_hw_engine_timeout_in_range(u64 timeout, u64 min, u64 max)
	return timeout >= min && timeout <= max;
}

static void kobj_xe_hw_engine_release(struct kobject *kobj)
static void xe_hw_engine_sysfs_kobj_release(struct kobject *kobj)
{
	kfree(kobj);
}

static ssize_t xe_hw_engine_class_sysfs_attr_show(struct kobject *kobj,
						  struct attribute *attr,
						  char *buf)
{
	struct xe_device *xe = kobj_to_xe(kobj);
	struct kobj_attribute *kattr;
	ssize_t ret = -EIO;

	kattr = container_of(attr, struct kobj_attribute, attr);
	if (kattr->show) {
		xe_pm_runtime_get(xe);
		ret = kattr->show(kobj, kattr, buf);
		xe_pm_runtime_put(xe);
	}

	return ret;
}

static ssize_t xe_hw_engine_class_sysfs_attr_store(struct kobject *kobj,
						   struct attribute *attr,
						   const char *buf,
						   size_t count)
{
	struct xe_device *xe = kobj_to_xe(kobj);
	struct kobj_attribute *kattr;
	ssize_t ret = -EIO;

	kattr = container_of(attr, struct kobj_attribute, attr);
	if (kattr->store) {
		xe_pm_runtime_get(xe);
		ret = kattr->store(kobj, kattr, buf, count);
		xe_pm_runtime_put(xe);
	}

	return ret;
}

static const struct sysfs_ops xe_hw_engine_class_sysfs_ops = {
	.show = xe_hw_engine_class_sysfs_attr_show,
	.store = xe_hw_engine_class_sysfs_attr_store,
};

static const struct kobj_type kobj_xe_hw_engine_type = {
	.release = kobj_xe_hw_engine_release,
	.sysfs_ops = &kobj_sysfs_ops
	.release = xe_hw_engine_sysfs_kobj_release,
	.sysfs_ops = &xe_hw_engine_class_sysfs_ops,
};

static const struct kobj_type kobj_xe_hw_engine_type_def = {
	.release = xe_hw_engine_sysfs_kobj_release,
	.sysfs_ops = &kobj_sysfs_ops,
};

static ssize_t job_timeout_max_store(struct kobject *kobj,
@@ -543,7 +590,7 @@ static int xe_add_hw_engine_class_defaults(struct xe_device *xe,
	if (!kobj)
		return -ENOMEM;

	kobject_init(kobj, &kobj_xe_hw_engine_type);
	kobject_init(kobj, &kobj_xe_hw_engine_type_def);
	err = kobject_add(kobj, parent, "%s", ".defaults");
	if (err)
		goto err_object;
@@ -559,57 +606,6 @@ static int xe_add_hw_engine_class_defaults(struct xe_device *xe,
	return err;
}

static void xe_hw_engine_sysfs_kobj_release(struct kobject *kobj)
{
	kfree(kobj);
}

static ssize_t xe_hw_engine_class_sysfs_attr_show(struct kobject *kobj,
						  struct attribute *attr,
						  char *buf)
{
	struct xe_device *xe = kobj_to_xe(kobj);
	struct kobj_attribute *kattr;
	ssize_t ret = -EIO;

	kattr = container_of(attr, struct kobj_attribute, attr);
	if (kattr->show) {
		xe_pm_runtime_get(xe);
		ret = kattr->show(kobj, kattr, buf);
		xe_pm_runtime_put(xe);
	}

	return ret;
}

static ssize_t xe_hw_engine_class_sysfs_attr_store(struct kobject *kobj,
						   struct attribute *attr,
						   const char *buf,
						   size_t count)
{
	struct xe_device *xe = kobj_to_xe(kobj);
	struct kobj_attribute *kattr;
	ssize_t ret = -EIO;

	kattr = container_of(attr, struct kobj_attribute, attr);
	if (kattr->store) {
		xe_pm_runtime_get(xe);
		ret = kattr->store(kobj, kattr, buf, count);
		xe_pm_runtime_put(xe);
	}

	return ret;
}

static const struct sysfs_ops xe_hw_engine_class_sysfs_ops = {
	.show = xe_hw_engine_class_sysfs_attr_show,
	.store = xe_hw_engine_class_sysfs_attr_store,
};

static const struct kobj_type xe_hw_engine_sysfs_kobj_type = {
	.release = xe_hw_engine_sysfs_kobj_release,
	.sysfs_ops = &xe_hw_engine_class_sysfs_ops,
};

static void hw_engine_class_sysfs_fini(void *arg)
{
@@ -640,7 +636,7 @@ int xe_hw_engine_class_sysfs_init(struct xe_gt *gt)
	if (!kobj)
		return -ENOMEM;

	kobject_init(kobj, &xe_hw_engine_sysfs_kobj_type);
	kobject_init(kobj, &kobj_xe_hw_engine_type);

	err = kobject_add(kobj, gt->sysfs, "engines");
	if (err)
Loading