]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/xe/guc: Limit sleep while waiting for H2G credits
authorMichal Wajdeczko <michal.wajdeczko@intel.com>
Tue, 27 Jan 2026 19:37:23 +0000 (20:37 +0100)
committerMichal Wajdeczko <michal.wajdeczko@intel.com>
Mon, 2 Feb 2026 21:35:43 +0000 (22:35 +0100)
Instead of endlessly increasing the sleep timeout while waiting
for the H2G credits, use exponential increase only up to the given
limit, like it was initially done in the GuC submission code.

While here, fix the actual timeout to the 1s as it was documented.

Suggested-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Link: https://patch.msgid.link/20260127193727.601-4-michal.wajdeczko@intel.com
drivers/gpu/drm/xe/xe_guc_ct.c

index dfbf76037b042b0fe04f8f122258b14ec3c8c886..d4111124cd5f40a8cf6f7821fc2930fe932674ee 100644 (file)
@@ -32,6 +32,7 @@
 #include "xe_guc_tlb_inval.h"
 #include "xe_map.h"
 #include "xe_pm.h"
+#include "xe_sleep.h"
 #include "xe_sriov_vf.h"
 #include "xe_trace_guc.h"
 
@@ -1101,7 +1102,8 @@ static int dequeue_one_g2h(struct xe_guc_ct *ct);
  */
 static bool guc_ct_send_wait_for_retry(struct xe_guc_ct *ct, u32 len,
                                       u32 g2h_len, struct g2h_fence *g2h_fence,
-                                      unsigned int *sleep_period_ms)
+                                      unsigned int *sleep_period_ms,
+                                      unsigned int *sleep_total_ms)
 {
        struct xe_device *xe = ct_to_xe(ct);
 
@@ -1115,15 +1117,14 @@ static bool guc_ct_send_wait_for_retry(struct xe_guc_ct *ct, u32 len,
        if (!h2g_has_room(ct, len + GUC_CTB_HDR_LEN)) {
                struct guc_ctb *h2g = &ct->ctbs.h2g;
 
-               if (*sleep_period_ms == 1024)
+               if (*sleep_total_ms > 1000)
                        return false;
 
                trace_xe_guc_ct_h2g_flow_control(xe, h2g->info.head, h2g->info.tail,
                                                 h2g->info.size,
                                                 h2g->info.space,
                                                 len + GUC_CTB_HDR_LEN);
-               msleep(*sleep_period_ms);
-               *sleep_period_ms <<= 1;
+               xe_sleep_exponential_ms(sleep_period_ms, 64);
        } else {
                struct xe_device *xe = ct_to_xe(ct);
                struct guc_ctb *g2h = &ct->ctbs.g2h;
@@ -1161,6 +1162,7 @@ static int guc_ct_send_locked(struct xe_guc_ct *ct, const u32 *action, u32 len,
 {
        struct xe_gt *gt = ct_to_gt(ct);
        unsigned int sleep_period_ms = 1;
+       unsigned int sleep_total_ms = 0;
        int ret;
 
        xe_gt_assert(gt, !g2h_len || !g2h_fence);
@@ -1173,7 +1175,7 @@ try_again:
 
        if (unlikely(ret == -EBUSY)) {
                if (!guc_ct_send_wait_for_retry(ct, len, g2h_len, g2h_fence,
-                                               &sleep_period_ms))
+                                               &sleep_period_ms, &sleep_total_ms))
                        goto broken;
                goto try_again;
        }