6
6
#include "xe_guc_pc.h"
7
7
8
8
#include <linux/delay.h>
9
+ #include <linux/ktime.h>
9
10
10
11
#include <drm/drm_managed.h>
11
12
#include <generated/xe_wa_oob.h>
19
20
#include "xe_gt.h"
20
21
#include "xe_gt_idle.h"
21
22
#include "xe_gt_printk.h"
23
+ #include "xe_gt_throttle.h"
22
24
#include "xe_gt_types.h"
23
25
#include "xe_guc.h"
24
26
#include "xe_guc_ct.h"
49
51
#define LNL_MERT_FREQ_CAP 800
50
52
#define BMG_MERT_FREQ_CAP 2133
51
53
54
+ #define SLPC_RESET_TIMEOUT_MS 5 /* roughly 5ms, but no need for precision */
55
+ #define SLPC_RESET_EXTENDED_TIMEOUT_MS 1000 /* To be used only at pc_start */
56
+
52
57
/**
53
58
* DOC: GuC Power Conservation (PC)
54
59
*
@@ -113,9 +118,10 @@ static struct iosys_map *pc_to_maps(struct xe_guc_pc *pc)
113
118
FIELD_PREP(HOST2GUC_PC_SLPC_REQUEST_MSG_1_EVENT_ARGC, count))
114
119
115
120
static int wait_for_pc_state (struct xe_guc_pc * pc ,
116
- enum slpc_global_state state )
121
+ enum slpc_global_state state ,
122
+ int timeout_ms )
117
123
{
118
- int timeout_us = 5000 ; /* rought 5ms, but no need for precision */
124
+ int timeout_us = 1000 * timeout_ms ;
119
125
int slept , wait = 10 ;
120
126
121
127
xe_device_assert_mem_access (pc_to_xe (pc ));
@@ -164,7 +170,8 @@ static int pc_action_query_task_state(struct xe_guc_pc *pc)
164
170
};
165
171
int ret ;
166
172
167
- if (wait_for_pc_state (pc , SLPC_GLOBAL_STATE_RUNNING ))
173
+ if (wait_for_pc_state (pc , SLPC_GLOBAL_STATE_RUNNING ,
174
+ SLPC_RESET_TIMEOUT_MS ))
168
175
return - EAGAIN ;
169
176
170
177
/* Blocking here to ensure the results are ready before reading them */
@@ -187,7 +194,8 @@ static int pc_action_set_param(struct xe_guc_pc *pc, u8 id, u32 value)
187
194
};
188
195
int ret ;
189
196
190
- if (wait_for_pc_state (pc , SLPC_GLOBAL_STATE_RUNNING ))
197
+ if (wait_for_pc_state (pc , SLPC_GLOBAL_STATE_RUNNING ,
198
+ SLPC_RESET_TIMEOUT_MS ))
191
199
return - EAGAIN ;
192
200
193
201
ret = xe_guc_ct_send (ct , action , ARRAY_SIZE (action ), 0 , 0 );
@@ -208,7 +216,8 @@ static int pc_action_unset_param(struct xe_guc_pc *pc, u8 id)
208
216
struct xe_guc_ct * ct = & pc_to_guc (pc )-> ct ;
209
217
int ret ;
210
218
211
- if (wait_for_pc_state (pc , SLPC_GLOBAL_STATE_RUNNING ))
219
+ if (wait_for_pc_state (pc , SLPC_GLOBAL_STATE_RUNNING ,
220
+ SLPC_RESET_TIMEOUT_MS ))
212
221
return - EAGAIN ;
213
222
214
223
ret = xe_guc_ct_send (ct , action , ARRAY_SIZE (action ), 0 , 0 );
@@ -440,6 +449,15 @@ u32 xe_guc_pc_get_act_freq(struct xe_guc_pc *pc)
440
449
return freq ;
441
450
}
442
451
452
+ static u32 get_cur_freq (struct xe_gt * gt )
453
+ {
454
+ u32 freq ;
455
+
456
+ freq = xe_mmio_read32 (& gt -> mmio , RPNSWREQ );
457
+ freq = REG_FIELD_GET (REQ_RATIO_MASK , freq );
458
+ return decode_freq (freq );
459
+ }
460
+
443
461
/**
444
462
* xe_guc_pc_get_cur_freq - Get Current requested frequency
445
463
* @pc: The GuC PC
@@ -463,10 +481,7 @@ int xe_guc_pc_get_cur_freq(struct xe_guc_pc *pc, u32 *freq)
463
481
return - ETIMEDOUT ;
464
482
}
465
483
466
- * freq = xe_mmio_read32 (& gt -> mmio , RPNSWREQ );
467
-
468
- * freq = REG_FIELD_GET (REQ_RATIO_MASK , * freq );
469
- * freq = decode_freq (* freq );
484
+ * freq = get_cur_freq (gt );
470
485
471
486
xe_force_wake_put (gt_to_fw (gt ), fw_ref );
472
487
return 0 ;
@@ -1002,6 +1017,7 @@ int xe_guc_pc_start(struct xe_guc_pc *pc)
1002
1017
struct xe_gt * gt = pc_to_gt (pc );
1003
1018
u32 size = PAGE_ALIGN (sizeof (struct slpc_shared_data ));
1004
1019
unsigned int fw_ref ;
1020
+ ktime_t earlier ;
1005
1021
int ret ;
1006
1022
1007
1023
xe_gt_assert (gt , xe_device_uc_enabled (xe ));
@@ -1026,14 +1042,25 @@ int xe_guc_pc_start(struct xe_guc_pc *pc)
1026
1042
memset (pc -> bo -> vmap .vaddr , 0 , size );
1027
1043
slpc_shared_data_write (pc , header .size , size );
1028
1044
1045
+ earlier = ktime_get ();
1029
1046
ret = pc_action_reset (pc );
1030
1047
if (ret )
1031
1048
goto out ;
1032
1049
1033
- if (wait_for_pc_state (pc , SLPC_GLOBAL_STATE_RUNNING )) {
1034
- xe_gt_err (gt , "GuC PC Start failed\n" );
1035
- ret = - EIO ;
1036
- goto out ;
1050
+ if (wait_for_pc_state (pc , SLPC_GLOBAL_STATE_RUNNING ,
1051
+ SLPC_RESET_TIMEOUT_MS )) {
1052
+ xe_gt_warn (gt , "GuC PC start taking longer than normal [freq = %dMHz (req = %dMHz), perf_limit_reasons = 0x%08X]\n" ,
1053
+ xe_guc_pc_get_act_freq (pc ), get_cur_freq (gt ),
1054
+ xe_gt_throttle_get_limit_reasons (gt ));
1055
+
1056
+ if (wait_for_pc_state (pc , SLPC_GLOBAL_STATE_RUNNING ,
1057
+ SLPC_RESET_EXTENDED_TIMEOUT_MS )) {
1058
+ xe_gt_err (gt , "GuC PC Start failed: Dynamic GT frequency control and GT sleep states are now disabled.\n" );
1059
+ goto out ;
1060
+ }
1061
+
1062
+ xe_gt_warn (gt , "GuC PC excessive start time: %lldms" ,
1063
+ ktime_ms_delta (ktime_get (), earlier ));
1037
1064
}
1038
1065
1039
1066
ret = pc_init_freqs (pc );
0 commit comments