17
17
#include "xe_hw_engine.h"
18
18
#include "xe_map.h"
19
19
#include "xe_mmio.h"
20
+ #include "xe_sriov_pf_helpers.h"
20
21
#include "xe_trace_guc.h"
21
22
22
23
#define TOTAL_QUANTA 0x8000
23
24
24
- static struct iosys_map engine_activity_map (struct xe_guc * guc , struct xe_hw_engine * hwe )
25
+ static struct iosys_map engine_activity_map (struct xe_guc * guc , struct xe_hw_engine * hwe ,
26
+ unsigned int index )
25
27
{
26
28
struct xe_guc_engine_activity * engine_activity = & guc -> engine_activity ;
27
- struct engine_activity_buffer * buffer = & engine_activity -> device_buffer ;
29
+ struct engine_activity_buffer * buffer ;
28
30
u16 guc_class = xe_engine_class_to_guc_class (hwe -> class );
29
31
size_t offset ;
30
32
31
- offset = offsetof(struct guc_engine_activity_data ,
33
+ if (engine_activity -> num_functions ) {
34
+ buffer = & engine_activity -> function_buffer ;
35
+ offset = sizeof (struct guc_engine_activity_data ) * index ;
36
+ } else {
37
+ buffer = & engine_activity -> device_buffer ;
38
+ offset = 0 ;
39
+ }
40
+
41
+ offset += offsetof(struct guc_engine_activity_data ,
32
42
engine_activity [guc_class ][hwe -> logical_instance ]);
33
43
34
44
return IOSYS_MAP_INIT_OFFSET (& buffer -> activity_bo -> vmap , offset );
35
45
}
36
46
37
- static struct iosys_map engine_metadata_map (struct xe_guc * guc )
47
+ static struct iosys_map engine_metadata_map (struct xe_guc * guc ,
48
+ unsigned int index )
38
49
{
39
50
struct xe_guc_engine_activity * engine_activity = & guc -> engine_activity ;
40
- struct engine_activity_buffer * buffer = & engine_activity -> device_buffer ;
51
+ struct engine_activity_buffer * buffer ;
52
+ size_t offset ;
41
53
42
- return buffer -> metadata_bo -> vmap ;
54
+ if (engine_activity -> num_functions ) {
55
+ buffer = & engine_activity -> function_buffer ;
56
+ offset = sizeof (struct guc_engine_activity_metadata ) * index ;
57
+ } else {
58
+ buffer = & engine_activity -> device_buffer ;
59
+ offset = 0 ;
60
+ }
61
+
62
+ return IOSYS_MAP_INIT_OFFSET (& buffer -> metadata_bo -> vmap , offset );
43
63
}
44
64
45
65
static int allocate_engine_activity_group (struct xe_guc * guc )
46
66
{
47
67
struct xe_guc_engine_activity * engine_activity = & guc -> engine_activity ;
48
68
struct xe_device * xe = guc_to_xe (guc );
49
- u32 num_activity_group = 1 ; /* Will be modified for VF */
69
+ u32 num_activity_group ;
70
+
71
+ /*
72
+ * An additional activity group is allocated for PF
73
+ */
74
+ num_activity_group = IS_SRIOV_PF (xe ) ? xe_sriov_pf_get_totalvfs (xe ) + 1 : 1 ;
50
75
51
76
engine_activity -> eag = drmm_kcalloc (& xe -> drm , num_activity_group ,
52
77
sizeof (struct engine_activity_group ), GFP_KERNEL );
@@ -60,10 +85,11 @@ static int allocate_engine_activity_group(struct xe_guc *guc)
60
85
}
61
86
62
87
static int allocate_engine_activity_buffers (struct xe_guc * guc ,
63
- struct engine_activity_buffer * buffer )
88
+ struct engine_activity_buffer * buffer ,
89
+ int count )
64
90
{
65
- u32 metadata_size = sizeof (struct guc_engine_activity_metadata );
66
- u32 size = sizeof (struct guc_engine_activity_data );
91
+ u32 metadata_size = sizeof (struct guc_engine_activity_metadata ) * count ;
92
+ u32 size = sizeof (struct guc_engine_activity_data ) * count ;
67
93
struct xe_gt * gt = guc_to_gt (guc );
68
94
struct xe_tile * tile = gt_to_tile (gt );
69
95
struct xe_bo * bo , * metadata_bo ;
@@ -118,10 +144,11 @@ static bool is_engine_activity_supported(struct xe_guc *guc)
118
144
return true;
119
145
}
120
146
121
- static struct engine_activity * hw_engine_to_engine_activity (struct xe_hw_engine * hwe )
147
+ static struct engine_activity * hw_engine_to_engine_activity (struct xe_hw_engine * hwe ,
148
+ unsigned int index )
122
149
{
123
150
struct xe_guc * guc = & hwe -> gt -> uc .guc ;
124
- struct engine_activity_group * eag = & guc -> engine_activity .eag [0 ];
151
+ struct engine_activity_group * eag = & guc -> engine_activity .eag [index ];
125
152
u16 guc_class = xe_engine_class_to_guc_class (hwe -> class );
126
153
127
154
return & eag -> engine [guc_class ][hwe -> logical_instance ];
@@ -138,9 +165,10 @@ static u64 cpu_ns_to_guc_tsc_tick(ktime_t ns, u32 freq)
138
165
#define read_metadata_record (xe_ , map_ , field_ ) \
139
166
xe_map_rd_field(xe_, map_, 0, struct guc_engine_activity_metadata, field_)
140
167
141
- static u64 get_engine_active_ticks (struct xe_guc * guc , struct xe_hw_engine * hwe )
168
+ static u64 get_engine_active_ticks (struct xe_guc * guc , struct xe_hw_engine * hwe ,
169
+ unsigned int index )
142
170
{
143
- struct engine_activity * ea = hw_engine_to_engine_activity (hwe );
171
+ struct engine_activity * ea = hw_engine_to_engine_activity (hwe , index );
144
172
struct guc_engine_activity * cached_activity = & ea -> activity ;
145
173
struct guc_engine_activity_metadata * cached_metadata = & ea -> metadata ;
146
174
struct xe_guc_engine_activity * engine_activity = & guc -> engine_activity ;
@@ -151,8 +179,8 @@ static u64 get_engine_active_ticks(struct xe_guc *guc, struct xe_hw_engine *hwe)
151
179
u64 active_ticks , gpm_ts ;
152
180
u16 change_num ;
153
181
154
- activity_map = engine_activity_map (guc , hwe );
155
- metadata_map = engine_metadata_map (guc );
182
+ activity_map = engine_activity_map (guc , hwe , index );
183
+ metadata_map = engine_metadata_map (guc , index );
156
184
global_change_num = read_metadata_record (xe , & metadata_map , global_change_num );
157
185
158
186
/* GuC has not initialized activity data yet, return 0 */
@@ -194,9 +222,9 @@ static u64 get_engine_active_ticks(struct xe_guc *guc, struct xe_hw_engine *hwe)
194
222
return ea -> total + ea -> active ;
195
223
}
196
224
197
- static u64 get_engine_total_ticks (struct xe_guc * guc , struct xe_hw_engine * hwe )
225
+ static u64 get_engine_total_ticks (struct xe_guc * guc , struct xe_hw_engine * hwe , unsigned int index )
198
226
{
199
- struct engine_activity * ea = hw_engine_to_engine_activity (hwe );
227
+ struct engine_activity * ea = hw_engine_to_engine_activity (hwe , index );
200
228
struct guc_engine_activity_metadata * cached_metadata = & ea -> metadata ;
201
229
struct guc_engine_activity * cached_activity = & ea -> activity ;
202
230
struct iosys_map activity_map , metadata_map ;
@@ -205,8 +233,8 @@ static u64 get_engine_total_ticks(struct xe_guc *guc, struct xe_hw_engine *hwe)
205
233
u64 numerator ;
206
234
u16 quanta_ratio ;
207
235
208
- activity_map = engine_activity_map (guc , hwe );
209
- metadata_map = engine_metadata_map (guc );
236
+ activity_map = engine_activity_map (guc , hwe , index );
237
+ metadata_map = engine_metadata_map (guc , index );
210
238
211
239
if (!cached_metadata -> guc_tsc_frequency_hz )
212
240
cached_metadata -> guc_tsc_frequency_hz = read_metadata_record (xe , & metadata_map ,
@@ -245,10 +273,35 @@ static int enable_engine_activity_stats(struct xe_guc *guc)
245
273
return xe_guc_ct_send_block (& guc -> ct , action , ARRAY_SIZE (action ));
246
274
}
247
275
248
- static void engine_activity_set_cpu_ts (struct xe_guc * guc )
276
+ static int enable_function_engine_activity_stats (struct xe_guc * guc , bool enable )
249
277
{
250
278
struct xe_guc_engine_activity * engine_activity = & guc -> engine_activity ;
251
- struct engine_activity_group * eag = & engine_activity -> eag [0 ];
279
+ u32 metadata_ggtt_addr = 0 , ggtt_addr = 0 , num_functions = 0 ;
280
+ struct engine_activity_buffer * buffer = & engine_activity -> function_buffer ;
281
+ u32 action [6 ];
282
+ int len = 0 ;
283
+
284
+ if (enable ) {
285
+ metadata_ggtt_addr = xe_bo_ggtt_addr (buffer -> metadata_bo );
286
+ ggtt_addr = xe_bo_ggtt_addr (buffer -> activity_bo );
287
+ num_functions = engine_activity -> num_functions ;
288
+ }
289
+
290
+ action [len ++ ] = XE_GUC_ACTION_SET_FUNCTION_ENGINE_ACTIVITY_BUFFER ;
291
+ action [len ++ ] = num_functions ;
292
+ action [len ++ ] = metadata_ggtt_addr ;
293
+ action [len ++ ] = 0 ;
294
+ action [len ++ ] = ggtt_addr ;
295
+ action [len ++ ] = 0 ;
296
+
297
+ /* Blocking here to ensure the buffers are ready before reading them */
298
+ return xe_guc_ct_send_block (& guc -> ct , action , ARRAY_SIZE (action ));
299
+ }
300
+
301
+ static void engine_activity_set_cpu_ts (struct xe_guc * guc , unsigned int index )
302
+ {
303
+ struct xe_guc_engine_activity * engine_activity = & guc -> engine_activity ;
304
+ struct engine_activity_group * eag = & engine_activity -> eag [index ];
252
305
int i , j ;
253
306
254
307
for (i = 0 ; i < GUC_MAX_ENGINE_CLASSES ; i ++ )
@@ -265,34 +318,106 @@ static u32 gpm_timestamp_shift(struct xe_gt *gt)
265
318
return 3 - REG_FIELD_GET (RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK , reg );
266
319
}
267
320
321
+ static bool is_function_valid (struct xe_guc * guc , unsigned int fn_id )
322
+ {
323
+ struct xe_device * xe = guc_to_xe (guc );
324
+ struct xe_guc_engine_activity * engine_activity = & guc -> engine_activity ;
325
+
326
+ if (!IS_SRIOV_PF (xe ) && fn_id )
327
+ return false;
328
+
329
+ if (engine_activity -> num_functions && fn_id >= engine_activity -> num_functions )
330
+ return false;
331
+
332
+ return true;
333
+ }
334
+
335
+ static int engine_activity_disable_function_stats (struct xe_guc * guc )
336
+ {
337
+ struct xe_guc_engine_activity * engine_activity = & guc -> engine_activity ;
338
+ struct engine_activity_buffer * buffer = & engine_activity -> function_buffer ;
339
+ int ret ;
340
+
341
+ if (!engine_activity -> num_functions )
342
+ return 0 ;
343
+
344
+ ret = enable_function_engine_activity_stats (guc , false);
345
+ if (ret )
346
+ return ret ;
347
+
348
+ free_engine_activity_buffers (buffer );
349
+ engine_activity -> num_functions = 0 ;
350
+
351
+ return 0 ;
352
+ }
353
+
354
+ static int engine_activity_enable_function_stats (struct xe_guc * guc , int num_vfs )
355
+ {
356
+ struct xe_guc_engine_activity * engine_activity = & guc -> engine_activity ;
357
+ struct engine_activity_buffer * buffer = & engine_activity -> function_buffer ;
358
+ int ret , i ;
359
+
360
+ if (!num_vfs )
361
+ return 0 ;
362
+
363
+ /* This includes 1 PF and num_vfs */
364
+ engine_activity -> num_functions = num_vfs + 1 ;
365
+
366
+ ret = allocate_engine_activity_buffers (guc , buffer , engine_activity -> num_functions );
367
+ if (ret )
368
+ return ret ;
369
+
370
+ ret = enable_function_engine_activity_stats (guc , true);
371
+ if (ret ) {
372
+ free_engine_activity_buffers (buffer );
373
+ engine_activity -> num_functions = 0 ;
374
+ return ret ;
375
+ }
376
+
377
+ for (i = 0 ; i < engine_activity -> num_functions ; i ++ )
378
+ engine_activity_set_cpu_ts (guc , i + 1 );
379
+
380
+ return 0 ;
381
+ }
382
+
268
383
/**
269
384
* xe_guc_engine_activity_active_ticks - Get engine active ticks
270
385
* @guc: The GuC object
271
386
* @hwe: The hw_engine object
387
+ * @fn_id: function id to report on
272
388
*
273
389
* Return: accumulated ticks @hwe was active since engine activity stats were enabled.
274
390
*/
275
- u64 xe_guc_engine_activity_active_ticks (struct xe_guc * guc , struct xe_hw_engine * hwe )
391
+ u64 xe_guc_engine_activity_active_ticks (struct xe_guc * guc , struct xe_hw_engine * hwe ,
392
+ unsigned int fn_id )
276
393
{
277
394
if (!xe_guc_engine_activity_supported (guc ))
278
395
return 0 ;
279
396
280
- return get_engine_active_ticks (guc , hwe );
397
+ if (!is_function_valid (guc , fn_id ))
398
+ return 0 ;
399
+
400
+ return get_engine_active_ticks (guc , hwe , fn_id );
281
401
}
282
402
283
403
/**
284
404
* xe_guc_engine_activity_total_ticks - Get engine total ticks
285
405
* @guc: The GuC object
286
406
* @hwe: The hw_engine object
407
+ * @fn_id: function id to report on
287
408
*
288
409
* Return: accumulated quanta of ticks allocated for the engine
289
410
*/
290
- u64 xe_guc_engine_activity_total_ticks (struct xe_guc * guc , struct xe_hw_engine * hwe )
411
+ u64 xe_guc_engine_activity_total_ticks (struct xe_guc * guc , struct xe_hw_engine * hwe ,
412
+ unsigned int fn_id )
291
413
{
292
414
if (!xe_guc_engine_activity_supported (guc ))
293
415
return 0 ;
294
416
295
- return get_engine_total_ticks (guc , hwe );
417
+ if (!is_function_valid (guc , fn_id ))
418
+ return 0 ;
419
+
420
+ return get_engine_total_ticks (guc , hwe , fn_id );
296
421
}
297
422
298
423
/**
@@ -310,6 +435,25 @@ bool xe_guc_engine_activity_supported(struct xe_guc *guc)
310
435
return engine_activity -> supported ;
311
436
}
312
437
438
+ /**
439
+ * xe_guc_engine_activity_function_stats - Enable/Disable per-function engine activity stats
440
+ * @guc: The GuC object
441
+ * @num_vfs: number of vfs
442
+ * @enable: true to enable, false otherwise
443
+ *
444
+ * Return: 0 on success, negative error code otherwise
445
+ */
446
+ int xe_guc_engine_activity_function_stats (struct xe_guc * guc , int num_vfs , bool enable )
447
+ {
448
+ if (!xe_guc_engine_activity_supported (guc ))
449
+ return 0 ;
450
+
451
+ if (enable )
452
+ return engine_activity_enable_function_stats (guc , num_vfs );
453
+
454
+ return engine_activity_disable_function_stats (guc );
455
+ }
456
+
313
457
/**
314
458
* xe_guc_engine_activity_enable_stats - Enable engine activity stats
315
459
* @guc: The GuC object
@@ -327,7 +471,7 @@ void xe_guc_engine_activity_enable_stats(struct xe_guc *guc)
327
471
if (ret )
328
472
xe_gt_err (guc_to_gt (guc ), "failed to enable activity stats%d\n" , ret );
329
473
else
330
- engine_activity_set_cpu_ts (guc );
474
+ engine_activity_set_cpu_ts (guc , 0 );
331
475
}
332
476
333
477
static void engine_activity_fini (void * arg )
@@ -360,7 +504,7 @@ int xe_guc_engine_activity_init(struct xe_guc *guc)
360
504
return ret ;
361
505
}
362
506
363
- ret = allocate_engine_activity_buffers (guc , & engine_activity -> device_buffer );
507
+ ret = allocate_engine_activity_buffers (guc , & engine_activity -> device_buffer , 1 );
364
508
if (ret ) {
365
509
xe_gt_err (gt , "failed to allocate engine activity buffers (%pe)\n" , ERR_PTR (ret ));
366
510
return ret ;
0 commit comments