#include "xe_guc_pc.h"
 
 #include <linux/delay.h>
+#include <linux/ktime.h>
 
 #include <drm/drm_managed.h>
 #include <drm/drm_print.h>
 #include "xe_gt.h"
 #include "xe_gt_idle.h"
 #include "xe_gt_printk.h"
+#include "xe_gt_throttle.h"
 #include "xe_gt_types.h"
 #include "xe_guc.h"
 #include "xe_guc_ct.h"
 #define LNL_MERT_FREQ_CAP      800
 #define BMG_MERT_FREQ_CAP      2133
 
+#define SLPC_RESET_TIMEOUT_MS 5 /* roughly 5ms, but no need for precision */
+#define SLPC_RESET_EXTENDED_TIMEOUT_MS 1000 /* To be used only at pc_start */
+
 /**
  * DOC: GuC Power Conservation (PC)
  *
         FIELD_PREP(HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC, count))
 
 static int wait_for_pc_state(struct xe_guc_pc *pc,
-                            enum slpc_global_state state)
+                            enum slpc_global_state state,
+                            int timeout_ms)
 {
-       int timeout_us = 5000; /* rought 5ms, but no need for precision */
+       int timeout_us = 1000 * timeout_ms;
        int slept, wait = 10;
 
        xe_device_assert_mem_access(pc_to_xe(pc));
        };
        int ret;
 
-       if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING))
+       if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING,
+                             SLPC_RESET_TIMEOUT_MS))
                return -EAGAIN;
 
        /* Blocking here to ensure the results are ready before reading them */
        };
        int ret;
 
-       if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING))
+       if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING,
+                             SLPC_RESET_TIMEOUT_MS))
                return -EAGAIN;
 
        ret = xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0);
        struct xe_guc_ct *ct = &pc_to_guc(pc)->ct;
        int ret;
 
-       if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING))
+       if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING,
+                             SLPC_RESET_TIMEOUT_MS))
                return -EAGAIN;
 
        ret = xe_guc_ct_send(ct, action, ARRAY_SIZE(action), 0, 0);
        return freq;
 }
 
+static u32 get_cur_freq(struct xe_gt *gt)
+{
+       u32 freq;
+
+       freq = xe_mmio_read32(>->mmio, RPNSWREQ);
+       freq = REG_FIELD_GET(REQ_RATIO_MASK, freq);
+       return decode_freq(freq);
+}
+
 /**
  * xe_guc_pc_get_cur_freq - Get Current requested frequency
  * @pc: The GuC PC
                return -ETIMEDOUT;
        }
 
-       *freq = xe_mmio_read32(>->mmio, RPNSWREQ);
-
-       *freq = REG_FIELD_GET(REQ_RATIO_MASK, *freq);
-       *freq = decode_freq(*freq);
+       *freq = get_cur_freq(gt);
 
        xe_force_wake_put(gt_to_fw(gt), fw_ref);
        return 0;
        struct xe_gt *gt = pc_to_gt(pc);
        u32 size = PAGE_ALIGN(sizeof(struct slpc_shared_data));
        unsigned int fw_ref;
+       ktime_t earlier;
        int ret;
 
        xe_gt_assert(gt, xe_device_uc_enabled(xe));
        memset(pc->bo->vmap.vaddr, 0, size);
        slpc_shared_data_write(pc, header.size, size);
 
+       earlier = ktime_get();
        ret = pc_action_reset(pc);
        if (ret)
                goto out;
 
-       if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING)) {
-               xe_gt_err(gt, "GuC PC Start failed\n");
-               ret = -EIO;
-               goto out;
+       if (wait_for_pc_state(pc, SLPC_GLOBAL_STATE_RUNNING,
+                             SLPC_RESET_TIMEOUT_MS)) {
+               xe_gt_warn(gt, "GuC PC start taking longer than normal [freq = %dMHz (req = %dMHz), perf_limit_reasons = 0x%08X]\n",
+                          xe_guc_pc_get_act_freq(pc), get_cur_freq(gt),
+                          xe_gt_throttle_get_limit_reasons(gt));
+
+               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");
+                       goto out;
+               }
+
+               xe_gt_warn(gt, "GuC PC excessive start time: %lldms",
+                          ktime_ms_delta(ktime_get(), earlier));
        }
 
        ret = pc_init_freqs(pc);