]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe/pf: Perform fair scheduling auto-provisioning
authorMichal Wajdeczko <michal.wajdeczko@intel.com>
Thu, 2 Apr 2026 19:17:26 +0000 (21:17 +0200)
committerMichal Wajdeczko <michal.wajdeczko@intel.com>
Sun, 12 Apr 2026 08:32:58 +0000 (10:32 +0200)
Default VF scheduling configuration is the same as for the PF and
includes unlimited execution quantum (EQ) and unlimited preemption
timeout (PT). While this setup gives the most flexibility it does
not protect the PF or VFs from other VF that could constantly submit
workloads without any gaps that would let GuC do a VF-switch.

To avoid that, do some trivial auto-provisioning and configure PF
and all VFs with 16ms EQ and PT. This setup should allow GuC to
perform a full round-robin with up to 63 VFs within 2s, which in
turn should match expectations from most of the VMs using VFs.

Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: Piotr Piórkowski <piotr.piorkowski@intel.com> #v1
Reviewed-by: Michał Winiarski <michal.winiarski@intel.com>
Link: https://patch.msgid.link/20260402191726.4932-14-michal.wajdeczko@intel.com
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
drivers/gpu/drm/xe/xe_gt_sriov_pf_config.h
drivers/gpu/drm/xe/xe_sriov_pf_provision.c

index d02c96d3041a4b4045d8313c950f2a4ab0985f4d..e112aa148dab341bfeac04d0e4aed2ace1864491 100644 (file)
@@ -2662,6 +2662,97 @@ static bool pf_non_default_sched(struct xe_gt *gt, unsigned int vfid)
               custom_sched_priority(gt, pf_get_sched_priority(gt, vfid));
 }
 
+static void __pf_show_provisioned_sched(struct xe_gt *gt, unsigned int first_vf,
+                                       unsigned int num_vfs, bool provisioned)
+{
+       __pf_show_provisioned(gt, first_vf, num_vfs, provisioned,
+                             pf_get_exec_quantum, NULL, "EQ");
+       __pf_show_provisioned(gt, first_vf, num_vfs, provisioned,
+                             pf_get_preempt_timeout, NULL, "PT");
+
+       /* we only care about non-default priorities */
+       if (provisioned)
+               __pf_show_provisioned(gt, first_vf, num_vfs, true,
+                                     pf_get_sched_priority, NULL, "PRIORITY");
+}
+
+static void pf_show_all_provisioned_sched(struct xe_gt *gt)
+{
+       __pf_show_provisioned_sched(gt, PFID, 1 + xe_gt_sriov_pf_get_totalvfs(gt), true);
+}
+
+static void pf_show_unprovisioned_sched(struct xe_gt *gt, unsigned int num_vfs)
+{
+       __pf_show_provisioned_sched(gt, PFID, 1 + num_vfs, false);
+}
+
+static bool pf_needs_provision_sched(struct xe_gt *gt, unsigned int num_vfs)
+{
+       unsigned int vfid;
+
+       for (vfid = PFID; vfid <= PFID + num_vfs; vfid++) {
+               if (pf_non_default_sched(gt, vfid)) {
+                       pf_show_all_provisioned_sched(gt);
+                       pf_show_unprovisioned_sched(gt, num_vfs);
+                       return false;
+               }
+       }
+
+       if (xe_gt_sriov_pf_policy_get_sched_if_idle_locked(gt)) {
+               pf_show_all_provisioned_sched(gt);
+               pf_show_unprovisioned_sched(gt, num_vfs);
+               return false;
+       }
+
+       pf_show_all_provisioned_sched(gt);
+       return true;
+}
+
+/* With 16ms EQ/PT GuC should be able to handle up to 63 VFs within 2s */
+#define XE_FAIR_EXEC_QUANTUM_MS                16
+#define XE_FAIR_PREEMPT_TIMEOUT_US     16000
+#define XE_FAIR_SCHED_PRIORITY         GUC_SCHED_PRIORITY_LOW
+#define XE_ADMIN_PF_SCHED_PRIORITY     GUC_SCHED_PRIORITY_HIGH
+
+/**
+ * xe_gt_sriov_pf_config_set_fair_sched() - Provision PF and VFs with fair scheduling.
+ * @gt: the &xe_gt
+ * @num_vfs: number of VFs to provision (can't be 0)
+ *
+ * This function can only be called on PF.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int xe_gt_sriov_pf_config_set_fair_sched(struct xe_gt *gt, unsigned int num_vfs)
+{
+       int result = 0;
+       int err;
+
+       xe_gt_assert(gt, num_vfs);
+       xe_gt_assert(gt, XE_FAIR_EXEC_QUANTUM_MS);
+       xe_gt_assert(gt, XE_FAIR_PREEMPT_TIMEOUT_US);
+
+       guard(mutex)(xe_gt_sriov_pf_master_mutex(gt));
+
+       if (!pf_needs_provision_sched(gt, num_vfs))
+               return 0;
+
+       err = pf_bulk_set_exec_quantum(gt, XE_FAIR_EXEC_QUANTUM_MS, PFID, 1 + num_vfs);
+       result = result ?: err;
+       err = pf_bulk_set_preempt_timeout(gt, XE_FAIR_PREEMPT_TIMEOUT_US, PFID, 1 + num_vfs);
+       result = result ?: err;
+
+       xe_gt_assert(gt, XE_FAIR_SCHED_PRIORITY == GUC_SCHED_PRIORITY_LOW);
+       xe_gt_assert(gt, !xe_gt_sriov_pf_policy_get_sched_if_idle_locked(gt));
+
+       if (xe_sriov_pf_admin_only(gt_to_xe(gt))) {
+               err = pf_provision_sched_priority(gt, PFID, XE_ADMIN_PF_SCHED_PRIORITY);
+               result = result ?: err;
+       }
+
+       return result;
+}
+
 static int pf_provision_threshold(struct xe_gt *gt, unsigned int vfid,
                                  enum xe_guc_klv_threshold_index index, u32 value)
 {
index e9314f0a9b4ea21590c951efd4b54b29d96a2da0..2ec62c12ad5cf06df962c86ab8a74aa37f93f6bf 100644 (file)
@@ -78,6 +78,7 @@ u32 xe_gt_sriov_pf_config_get_threshold(struct xe_gt *gt, unsigned int vfid,
 int xe_gt_sriov_pf_config_set_threshold(struct xe_gt *gt, unsigned int vfid,
                                        enum xe_guc_klv_threshold_index index, u32 value);
 
+int xe_gt_sriov_pf_config_set_fair_sched(struct xe_gt *gt, unsigned int num_vfs);
 int xe_gt_sriov_pf_config_set_fair(struct xe_gt *gt, unsigned int vfid, unsigned int num_vfs);
 int xe_gt_sriov_pf_config_sanitize(struct xe_gt *gt, unsigned int vfid, long timeout);
 int xe_gt_sriov_pf_config_release(struct xe_gt *gt, unsigned int vfid, bool force);
index e11874d689fa0fa152971914c08861685c5935d8..0ec7ea83f12acff4520c4e53fe3af004dfc2c4d6 100644 (file)
@@ -41,6 +41,8 @@ static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)
        int err;
 
        for_each_gt(gt, xe, id) {
+               err = xe_gt_sriov_pf_config_set_fair_sched(gt, num_vfs);
+               result = result ?: err;
                err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs);
                result = result ?: err;
        }