]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe/pf: Scheduler groups are incompatible with multi-lrc
authorDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Thu, 18 Dec 2025 22:38:51 +0000 (14:38 -0800)
committerDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Mon, 22 Dec 2025 18:22:05 +0000 (10:22 -0800)
Since engines in the same class can be divided across multiple groups,
the GuC does not allow scheduler groups to be active if there are
multi-lrc contexts. This means that:

1) if a MLRC context is registered when we enable scheduler groups, the
   GuC will silently ignore the configuration
2) if a MLRC context is registered after scheduler groups are enabled,
   the GuC will disable the groups and generate an adverse event.

The expectation is that the admin will ensure that all apps that use
MLRC on PF have been terminated before scheduler groups are created. A
check is added anyway to make sure we don't still have contexts waiting
to be cleaned up laying around. A check is also added at queue creation
time to block MLRC queue creation if scheduler groups have been enabled.

Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Link: https://patch.msgid.link/20251218223846.1146344-19-daniele.ceraolospurio@intel.com
drivers/gpu/drm/xe/xe_exec_queue.c
drivers/gpu/drm/xe/xe_gt_sriov_pf.c
drivers/gpu/drm/xe/xe_gt_sriov_pf.h
drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.c
drivers/gpu/drm/xe/xe_gt_sriov_pf_policy.h
drivers/gpu/drm/xe/xe_guc_submit.c
drivers/gpu/drm/xe/xe_guc_submit.h

index 41023a4644807d16854c25977091a938165e7ab5..c336dcd19020b8f50ebae7f905e18746766b78bf 100644 (file)
@@ -17,6 +17,7 @@
 #include "xe_dep_scheduler.h"
 #include "xe_device.h"
 #include "xe_gt.h"
+#include "xe_gt_sriov_pf.h"
 #include "xe_gt_sriov_vf.h"
 #include "xe_hw_engine_class_sysfs.h"
 #include "xe_hw_engine_group.h"
@@ -1108,6 +1109,14 @@ static u32 calc_validate_logical_mask(struct xe_device *xe,
        return return_mask;
 }
 
+static bool has_sched_groups(struct xe_gt *gt)
+{
+       if (IS_SRIOV_PF(gt_to_xe(gt)) && xe_gt_sriov_pf_sched_groups_enabled(gt))
+               return true;
+
+       return false;
+}
+
 int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
                               struct drm_file *file)
 {
@@ -1200,6 +1209,13 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
                        return -ENOENT;
                }
 
+               /* SRIOV sched groups are not compatible with multi-lrc */
+               if (XE_IOCTL_DBG(xe, args->width > 1 && has_sched_groups(hwe->gt))) {
+                       up_read(&vm->lock);
+                       xe_vm_put(vm);
+                       return -EINVAL;
+               }
+
                q = xe_exec_queue_create(xe, vm, logical_mask,
                                         args->width, hwe, flags,
                                         args->extensions);
index 0d97a823e702184bf0c2dc200c8c7725bb0cf22a..fb5c9101e2756a2957dd5d5a236450542034f489 100644 (file)
@@ -284,3 +284,20 @@ int xe_gt_sriov_pf_wait_ready(struct xe_gt *gt)
        pf_flush_restart(gt);
        return 0;
 }
+
+/**
+ * xe_gt_sriov_pf_sched_groups_enabled - Check if multiple scheduler groups are
+ * enabled
+ * @gt: the &xe_gt
+ *
+ * This function is for PF use only.
+ *
+ * Return: true if shed groups were enabled, false otherwise.
+ */
+bool xe_gt_sriov_pf_sched_groups_enabled(struct xe_gt *gt)
+{
+       xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));
+
+       return xe_gt_sriov_pf_policy_sched_groups_enabled(gt);
+}
+
index e7fde3f9937af282d3aea45e1a53bd282fdfbc79..1ccfc7137b9886cd38004e2b4294b29d9d95cd0d 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef _XE_GT_SRIOV_PF_H_
 #define _XE_GT_SRIOV_PF_H_
 
+#include <linux/types.h>
+
 struct xe_gt;
 
 #ifdef CONFIG_PCI_IOV
@@ -16,6 +18,7 @@ void xe_gt_sriov_pf_init_hw(struct xe_gt *gt);
 void xe_gt_sriov_pf_sanitize_hw(struct xe_gt *gt, unsigned int vfid);
 void xe_gt_sriov_pf_stop_prepare(struct xe_gt *gt);
 void xe_gt_sriov_pf_restart(struct xe_gt *gt);
+bool xe_gt_sriov_pf_sched_groups_enabled(struct xe_gt *gt);
 #else
 static inline int xe_gt_sriov_pf_init_early(struct xe_gt *gt)
 {
@@ -38,6 +41,11 @@ static inline void xe_gt_sriov_pf_stop_prepare(struct xe_gt *gt)
 static inline void xe_gt_sriov_pf_restart(struct xe_gt *gt)
 {
 }
+
+static inline bool xe_gt_sriov_pf_sched_groups_enabled(struct xe_gt *gt)
+{
+       return false;
+}
 #endif
 
 #endif
index cf6ead37bd642f380dffff3979f3c0c11ee9bf82..c28606ca6623cb3c94a5df6e79f488824e09a78c 100644 (file)
@@ -16,6 +16,7 @@
 #include "xe_guc_buf.h"
 #include "xe_guc_ct.h"
 #include "xe_guc_klv_helpers.h"
+#include "xe_guc_submit.h"
 #include "xe_pm.h"
 
 /*
@@ -590,6 +591,19 @@ static int pf_provision_sched_groups(struct xe_gt *gt, enum xe_sriov_sched_group
        if (xe_sriov_pf_num_vfs(gt_to_xe(gt)))
                return -EBUSY;
 
+       /*
+        * The GuC silently ignores the setting if any MLRC contexts are
+        * registered. We expect the admin to make sure that all apps that use
+        * MLRC are terminated before scheduler groups are enabled, so this
+        * check is just to make sure that the exec_queue destruction has been
+        * completed.
+        */
+       if (mode != XE_SRIOV_SCHED_GROUPS_DISABLED &&
+           xe_guc_has_registered_mlrc_queues(&gt->uc.guc)) {
+               xe_gt_sriov_notice(gt, "can't enable sched groups with active MLRC queues\n");
+               return -EPERM;
+       }
+
        err = __pf_provision_sched_groups(gt, mode);
        if (err)
                return err;
@@ -638,6 +652,20 @@ int xe_gt_sriov_pf_policy_set_sched_groups_mode(struct xe_gt *gt,
        return pf_provision_sched_groups(gt, mode);
 }
 
+/**
+ * xe_gt_sriov_pf_policy_sched_groups_enabled() - check whether the GT has
+ * multiple scheduler groups enabled
+ * @gt: the &xe_gt to check
+ *
+ * This function can only be called on PF.
+ *
+ * Return: true if the GT has multiple groups enabled, false otherwise.
+ */
+bool xe_gt_sriov_pf_policy_sched_groups_enabled(struct xe_gt *gt)
+{
+       return gt->sriov.pf.policy.guc.sched_groups.current_mode != XE_SRIOV_SCHED_GROUPS_DISABLED;
+}
+
 static void pf_sanitize_guc_policies(struct xe_gt *gt)
 {
        pf_sanitize_sched_if_idle(gt);
index d6e96302ff68c24c25cb4c5091c718b2bbf47b6c..bd73aa58f9ca7f2869870c8404c0347c218fe14a 100644 (file)
@@ -25,6 +25,7 @@ bool xe_sriov_gt_pf_policy_has_sched_group_mode(struct xe_gt *gt,
                                                enum xe_sriov_sched_group_modes mode);
 int xe_gt_sriov_pf_policy_set_sched_groups_mode(struct xe_gt *gt,
                                                enum xe_sriov_sched_group_modes mode);
+bool xe_gt_sriov_pf_policy_sched_groups_enabled(struct xe_gt *gt);
 
 void xe_gt_sriov_pf_policy_init(struct xe_gt *gt);
 void xe_gt_sriov_pf_policy_sanitize(struct xe_gt *gt);
index 1646535b86a34c523e39193af4cd523e2f1b68b8..7a4218f760241b10eb31ebead63e9c243dba9a17 100644 (file)
@@ -3563,6 +3563,27 @@ void xe_guc_submit_print(struct xe_guc *guc, struct drm_printer *p)
        mutex_unlock(&guc->submission_state.lock);
 }
 
+/**
+ * xe_guc_has_registered_mlrc_queues - check whether there are any MLRC queues
+ * registered with the GuC
+ * @guc: GuC.
+ *
+ * Return: true if any MLRC queue is registered with the GuC, false otherwise.
+ */
+bool xe_guc_has_registered_mlrc_queues(struct xe_guc *guc)
+{
+       struct xe_exec_queue *q;
+       unsigned long index;
+
+       guard(mutex)(&guc->submission_state.lock);
+
+       xa_for_each(&guc->submission_state.exec_queue_lookup, index, q)
+               if (q->width > 1)
+                       return true;
+
+       return false;
+}
+
 /**
  * xe_guc_contexts_hwsp_rebase - Re-compute GGTT references within all
  * exec queues registered to given GuC.
index 4d89b2975fe93680779c1f63297d04c81f1f1fca..b3839a90c142bc9e33fdc10a369a4a8571a9ae5a 100644 (file)
@@ -52,6 +52,8 @@ xe_guc_exec_queue_snapshot_free(struct xe_guc_submit_exec_queue_snapshot *snapsh
 void xe_guc_submit_print(struct xe_guc *guc, struct drm_printer *p);
 void xe_guc_register_vf_exec_queue(struct xe_exec_queue *q, int ctx_type);
 
+bool xe_guc_has_registered_mlrc_queues(struct xe_guc *guc);
+
 int xe_guc_contexts_hwsp_rebase(struct xe_guc *guc, void *scratch);
 
 #endif