]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe/pf: Add functions to set preempt timeouts for each group
authorDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Thu, 18 Dec 2025 22:38:57 +0000 (14:38 -0800)
committerDaniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Mon, 22 Dec 2025 18:22:16 +0000 (10:22 -0800)
The KLV to set the preemption timeout for each groups works the exact
same way as the one for the exec quantums, so we add similar functions.

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-25-daniele.ceraolospurio@intel.com
drivers/gpu/drm/xe/abi/guc_klvs_abi.h
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_guc_klv_helpers.c

index dc753c317ae0f428c5c93f6a206fb5c512e28e11..e33bd622ab44837dfdde729d9ec7d6c0fdf760dd 100644 (file)
@@ -405,6 +405,16 @@ enum  {
  *      the GuC always sets the EQ for all groups (even the non-enabled ones),
  *      so if we provide fewer values than the max the GuC will use 0 for the
  *      remaining groups. This KLV is available starting from GuC 70.53.0.
+ *
+ * _`GUC_KLV_VF_CFG_ENGINE_GROUP_PREEMPT_TIMEOUT' : 0x8A0F
+ *      This config sets the VFs-preemption-timeout for each scheduling group in
+ *      microseconds. The driver must provide an array of values, with each of
+ *      them matching the respective group index (first value goes to group 0,
+ *      second to group 1, etc). The setting of group values follows the same
+ *      behavior and rules as setting via GUC_KLV_VF_CFG_PREEMPT_TIMEOUT. Note
+ *      that the GuC always sets the EQ for all groups (even the non-enabled
+ *      ones), so if we provide fewer values than the max the GuC will use 0 for
+ *      the remaining groups. This KLV is available starting from GuC 70.53.0.
  */
 
 #define GUC_KLV_VF_CFG_GGTT_START_KEY          0x0001
@@ -470,6 +480,9 @@ enum  {
 #define GUC_KLV_VF_CFG_ENGINE_GROUP_EXEC_QUANTUM_MIN_LEN       1u
 #define GUC_KLV_VF_CFG_ENGINE_GROUP_EXEC_QUANTUM_MAX_LEN       GUC_MAX_SCHED_GROUPS
 
+#define GUC_KLV_VF_CFG_ENGINE_GROUP_PREEMPT_TIMEOUT_KEY                0x8a0f
+#define GUC_KLV_VF_CFG_ENGINE_GROUP_PREEMPT_TIMEOUT_MIN_LEN    1u
+#define GUC_KLV_VF_CFG_ENGINE_GROUP_PREEMPT_TIMEOUT_MAX_LEN    GUC_MAX_SCHED_GROUPS
 /*
  * Workaround keys:
  */
index c663f349b437d212379093872c84f15a5e7b70db..5a870914b102cc618237bc6f57ded28693f2a103 100644 (file)
@@ -295,13 +295,18 @@ static u32 encode_config_sched(struct xe_gt *gt, u32 *cfg, u32 n,
        if (xe_sriov_gt_pf_policy_has_multi_group_modes(gt)) {
                BUILD_BUG_ON(ARRAY_SIZE(config->exec_quantum) >
                             GUC_KLV_VF_CFG_ENGINE_GROUP_EXEC_QUANTUM_MAX_LEN);
+               BUILD_BUG_ON(ARRAY_SIZE(config->preempt_timeout) >
+                            GUC_KLV_VF_CFG_ENGINE_GROUP_PREEMPT_TIMEOUT_MAX_LEN);
 
                cfg[n++] = PREP_GUC_KLV_CONST(GUC_KLV_VF_CFG_ENGINE_GROUP_EXEC_QUANTUM_KEY,
                                              ARRAY_SIZE(config->exec_quantum));
                for (i = 0; i < ARRAY_SIZE(config->exec_quantum); i++)
                        cfg[n++] = config->exec_quantum[i];
 
-               /* TODO: add group preempt timeout setting */
+               cfg[n++] = PREP_GUC_KLV_CONST(GUC_KLV_VF_CFG_ENGINE_GROUP_PREEMPT_TIMEOUT_KEY,
+                                             ARRAY_SIZE(config->preempt_timeout));
+               for (i = 0; i < ARRAY_SIZE(config->preempt_timeout); i++)
+                       cfg[n++] = config->preempt_timeout[i];
        } else {
                cfg[n++] = PREP_GUC_KLV_TAG(VF_CFG_EXEC_QUANTUM);
                cfg[n++] = config->exec_quantum[0];
@@ -2265,6 +2270,89 @@ int xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked(struct xe_gt *gt, u32
                                           preempt_timeout_unit, n, err);
 }
 
+static int pf_provision_groups_preempt_timeouts(struct xe_gt *gt, unsigned int vfid,
+                                               const u32 *preempt_timeouts, u32 count)
+{
+       struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid);
+       int err;
+       int i;
+
+       err = pf_push_vf_grp_cfg_u32(gt, vfid, GUC_KLV_VF_CFG_ENGINE_GROUP_PREEMPT_TIMEOUT_KEY,
+                                    preempt_timeouts, count);
+       if (unlikely(err))
+               return err;
+
+       /*
+        * GuC silently clamps values exceeding the max and zeroes out the
+        * quantum for groups not in the klv payload
+        */
+       for (i = 0; i < ARRAY_SIZE(config->preempt_timeout); i++) {
+               if (i < count)
+                       config->preempt_timeout[i] =
+                               min_t(u32, preempt_timeouts[i],
+                                     GUC_KLV_VF_CFG_PREEMPT_TIMEOUT_MAX_VALUE);
+               else
+                       config->preempt_timeout[i] = 0;
+       }
+
+       return 0;
+}
+
+static void pf_get_groups_preempt_timeouts(struct xe_gt *gt, unsigned int vfid,
+                                          u32 *preempt_timeouts, u32 max_count)
+{
+       struct xe_gt_sriov_config *config = pf_pick_vf_config(gt, vfid);
+       u32 count = min_t(u32, max_count, ARRAY_SIZE(config->preempt_timeout));
+
+       memcpy(preempt_timeouts, config->preempt_timeout, sizeof(u32) * count);
+}
+
+/**
+ * xe_gt_sriov_pf_config_set_groups_preempt_timeouts() - Configure PF/VF PTs for sched groups.
+ * @gt: the &xe_gt
+ * @vfid: the PF or VF identifier
+ * @preempt_timeouts: array of requested PTs in microseconds (0 is infinity)
+ * @count: number of entries in the array
+ *
+ * This function can only be called on PF.
+ * It will log the provisioned value or an error in case of the failure.
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int xe_gt_sriov_pf_config_set_groups_preempt_timeouts(struct xe_gt *gt, unsigned int vfid,
+                                                     u32 *preempt_timeouts, u32 count)
+{
+       int err;
+
+       guard(mutex)(xe_gt_sriov_pf_master_mutex(gt));
+
+       err = pf_provision_groups_preempt_timeouts(gt, vfid, preempt_timeouts, count);
+
+       return pf_groups_cfg_set_u32_done(gt, vfid, preempt_timeouts, count,
+                                         pf_get_groups_preempt_timeouts,
+                                         "preempt_timeout",
+                                         preempt_timeout_unit, err);
+}
+
+/**
+ * xe_gt_sriov_pf_config_get_groups_preempt_timeouts() - Get PF/VF sched groups PTs
+ * @gt: the &xe_gt
+ * @vfid: the PF or VF identifier
+ * @preempt_timeouts: array in which to store the preemption timeouts values
+ * @count: maximum number of entries to store
+ *
+ * This function can only be called on PF.
+ */
+void xe_gt_sriov_pf_config_get_groups_preempt_timeouts(struct xe_gt *gt, unsigned int vfid,
+                                                      u32 *preempt_timeouts, u32 count)
+{
+       guard(mutex)(xe_gt_sriov_pf_master_mutex(gt));
+
+       xe_gt_assert(gt, count <= GUC_MAX_SCHED_GROUPS);
+
+       pf_get_groups_preempt_timeouts(gt, vfid, preempt_timeouts, count);
+}
+
 static const char *sched_priority_unit(u32 priority)
 {
        return priority == GUC_SCHED_PRIORITY_LOW ? "(low)" :
@@ -2712,6 +2800,11 @@ static int pf_restore_vf_config_klv(struct xe_gt *gt, unsigned int vfid,
                        return -EBADMSG;
                return pf_provision_groups_exec_quantums(gt, vfid, value, len);
 
+       case GUC_KLV_VF_CFG_ENGINE_GROUP_PREEMPT_TIMEOUT_KEY:
+               if (len > GUC_KLV_VF_CFG_ENGINE_GROUP_PREEMPT_TIMEOUT_MAX_LEN)
+                       return -EBADMSG;
+               return pf_provision_groups_preempt_timeouts(gt, vfid, value, len);
+
        case GUC_KLV_VF_CFG_PREEMPT_TIMEOUT_KEY:
                if (len != GUC_KLV_VF_CFG_PREEMPT_TIMEOUT_LEN)
                        return -EBADMSG;
index aaed1f490da894db7f575e15ecffcb0bbe2c5b11..3c6c8b6655af7d2c8656f02d4a27bb2fa904b0c9 100644 (file)
@@ -60,6 +60,11 @@ int xe_gt_sriov_pf_config_set_preempt_timeout_locked(struct xe_gt *gt, unsigned
                                                     u32 preempt_timeout);
 int xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked(struct xe_gt *gt, u32 preempt_timeout);
 
+void xe_gt_sriov_pf_config_get_groups_preempt_timeouts(struct xe_gt *gt, unsigned int vfid,
+                                                      u32 *preempt_timeout, u32 max_count);
+int xe_gt_sriov_pf_config_set_groups_preempt_timeouts(struct xe_gt *gt, unsigned int vfid,
+                                                     u32 *preempt_timeout, u32 count);
+
 u32 xe_gt_sriov_pf_config_get_sched_priority(struct xe_gt *gt, unsigned int vfid);
 int xe_gt_sriov_pf_config_set_sched_priority(struct xe_gt *gt, unsigned int vfid, u32 priority);
 
index b696a21f87e8481bf98f417a9d9c15d3cb822123..97600edda837a3315b096c0c56d52110ee3cd242 100644 (file)
@@ -58,6 +58,8 @@ const char *xe_guc_klv_key_to_string(u16 key)
                return "sched_priority";
        case GUC_KLV_VF_CFG_ENGINE_GROUP_EXEC_QUANTUM_KEY:
                return "sched_groups_exec_quantum";
+       case GUC_KLV_VF_CFG_ENGINE_GROUP_PREEMPT_TIMEOUT_KEY:
+               return "sched_groups_preempt_timeout";
 
        /* VF CFG threshold keys */
 #define define_threshold_key_to_string_case(TAG, NAME, ...)    \