drm/xe: Introduce SR-IOV logging macros
[linux-block.git] / drivers / gpu / drm / xe / xe_gt.c
CommitLineData
dd08ebf6
MB
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2022 Intel Corporation
4 */
5
ea9f879d
LDM
6#include "xe_gt.h"
7
dd08ebf6
MB
8#include <linux/minmax.h>
9
10#include <drm/drm_managed.h>
4f027e30 11#include <drm/xe_drm.h>
dd08ebf6 12
72ac3047 13#include "instructions/xe_gfxpipe_commands.h"
0134f130 14#include "instructions/xe_mi_commands.h"
226bfec8 15#include "regs/xe_gt_regs.h"
c73acc1e 16#include "xe_assert.h"
dd08ebf6
MB
17#include "xe_bb.h"
18#include "xe_bo.h"
19#include "xe_device.h"
c22a4ed0 20#include "xe_exec_queue.h"
dd08ebf6
MB
21#include "xe_execlist.h"
22#include "xe_force_wake.h"
23#include "xe_ggtt.h"
aae84bf1 24#include "xe_gsc.h"
0d97ecce 25#include "xe_gt_ccs_mode.h"
dd08ebf6 26#include "xe_gt_clock.h"
c550f64f 27#include "xe_gt_idle.h"
dd08ebf6
MB
28#include "xe_gt_mcr.h"
29#include "xe_gt_pagefault.h"
3e535bd5 30#include "xe_gt_printk.h"
dd08ebf6 31#include "xe_gt_sysfs.h"
a9351846 32#include "xe_gt_tlb_invalidation.h"
dd08ebf6 33#include "xe_gt_topology.h"
9b9529ce 34#include "xe_guc_exec_queue_types.h"
43efd3ba 35#include "xe_guc_pc.h"
dd08ebf6 36#include "xe_hw_fence.h"
038ff941 37#include "xe_hw_engine_class_sysfs.h"
dd08ebf6
MB
38#include "xe_irq.h"
39#include "xe_lrc.h"
40#include "xe_map.h"
41#include "xe_migrate.h"
42#include "xe_mmio.h"
576c6380 43#include "xe_pat.h"
dd08ebf6
MB
44#include "xe_mocs.h"
45#include "xe_reg_sr.h"
46#include "xe_ring_ops.h"
47#include "xe_sa.h"
48#include "xe_sched_job.h"
dd08ebf6
MB
49#include "xe_tuning.h"
50#include "xe_uc.h"
51#include "xe_vm.h"
52#include "xe_wa.h"
53#include "xe_wopcm.h"
54
f6929e80 55struct xe_gt *xe_gt_alloc(struct xe_tile *tile)
dd08ebf6 56{
f6929e80 57 struct xe_gt *gt;
dd08ebf6 58
f6929e80
MR
59 gt = drmm_kzalloc(&tile_to_xe(tile)->drm, sizeof(*gt), GFP_KERNEL);
60 if (!gt)
61 return ERR_PTR(-ENOMEM);
62
63 gt->tile = tile;
dd08ebf6
MB
64 gt->ordered_wq = alloc_ordered_workqueue("gt-ordered-wq", 0);
65
f6929e80 66 return gt;
dd08ebf6
MB
67}
68
da3799c9
MB
69void xe_gt_sanitize(struct xe_gt *gt)
70{
71 /*
72 * FIXME: if xe_uc_sanitize is called here, on TGL driver will not
73 * reload
74 */
75 gt->uc.guc.submission_state.enabled = false;
76}
77
dd08ebf6
MB
78static void gt_fini(struct drm_device *drm, void *arg)
79{
80 struct xe_gt *gt = arg;
81 int i;
82
83 destroy_workqueue(gt->ordered_wq);
84
85 for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i)
86 xe_hw_fence_irq_finish(&gt->fence_irq[i]);
87}
88
89static void gt_reset_worker(struct work_struct *w);
90
9b9529ce 91static int emit_nop_job(struct xe_gt *gt, struct xe_exec_queue *q)
dd08ebf6
MB
92{
93 struct xe_sched_job *job;
94 struct xe_bb *bb;
95 struct dma_fence *fence;
dd08ebf6
MB
96 long timeout;
97
98 bb = xe_bb_new(gt, 4, false);
99 if (IS_ERR(bb))
100 return PTR_ERR(bb);
101
9e952635 102 job = xe_bb_create_job(q, bb);
dd08ebf6
MB
103 if (IS_ERR(job)) {
104 xe_bb_free(bb, NULL);
99c5952f 105 return PTR_ERR(job);
dd08ebf6
MB
106 }
107
108 xe_sched_job_arm(job);
109 fence = dma_fence_get(&job->drm.s_fence->finished);
110 xe_sched_job_push(job);
111
112 timeout = dma_fence_wait_timeout(fence, false, HZ);
113 dma_fence_put(fence);
114 xe_bb_free(bb, NULL);
115 if (timeout < 0)
116 return timeout;
117 else if (!timeout)
118 return -ETIME;
119
120 return 0;
121}
122
278c3582
LDM
123/*
124 * Convert back from encoded value to type-safe, only to be used when reg.mcr
125 * is true
126 */
127static struct xe_reg_mcr to_xe_reg_mcr(const struct xe_reg reg)
128{
129 return (const struct xe_reg_mcr){.__reg.raw = reg.raw };
130}
131
9b9529ce 132static int emit_wa_job(struct xe_gt *gt, struct xe_exec_queue *q)
dd08ebf6 133{
9b9529ce 134 struct xe_reg_sr *sr = &q->hwe->reg_lrc;
dd08ebf6 135 struct xe_reg_sr_entry *entry;
278c3582 136 unsigned long idx;
dd08ebf6
MB
137 struct xe_sched_job *job;
138 struct xe_bb *bb;
139 struct dma_fence *fence;
dd08ebf6
MB
140 long timeout;
141 int count = 0;
142
b1543a49
MR
143 if (q->hwe->class == XE_ENGINE_CLASS_RENDER)
144 /* Big enough to emit all of the context's 3DSTATE */
145 bb = xe_bb_new(gt, xe_lrc_size(gt_to_xe(gt), q->hwe->class), false);
146 else
147 /* Just pick a large BB size */
148 bb = xe_bb_new(gt, SZ_4K, false);
149
dd08ebf6
MB
150 if (IS_ERR(bb))
151 return PTR_ERR(bb);
152
278c3582 153 xa_for_each(&sr->xa, idx, entry)
dd08ebf6
MB
154 ++count;
155
156 if (count) {
12a66a47
LDM
157 xe_gt_dbg(gt, "LRC WA %s save-restore batch\n", sr->name);
158
e12a6488 159 bb->cs[bb->len++] = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(count);
278c3582
LDM
160
161 xa_for_each(&sr->xa, idx, entry) {
162 struct xe_reg reg = entry->reg;
163 struct xe_reg_mcr reg_mcr = to_xe_reg_mcr(reg);
164 u32 val;
165
166 /*
167 * Skip reading the register if it's not really needed
168 */
169 if (reg.masked)
170 val = entry->clr_bits << 16;
171 else if (entry->clr_bits + 1)
172 val = (reg.mcr ?
173 xe_gt_mcr_unicast_read_any(gt, reg_mcr) :
174 xe_mmio_read32(gt, reg)) & (~entry->clr_bits);
175 else
176 val = 0;
177
178 val |= entry->set_bits;
179
180 bb->cs[bb->len++] = reg.addr;
181 bb->cs[bb->len++] = val;
182 xe_gt_dbg(gt, "REG[0x%x] = 0x%08x", reg.addr, val);
dd08ebf6
MB
183 }
184 }
dd08ebf6 185
b1543a49
MR
186 xe_lrc_emit_hwe_state_instructions(q, bb);
187
9e952635 188 job = xe_bb_create_job(q, bb);
dd08ebf6
MB
189 if (IS_ERR(job)) {
190 xe_bb_free(bb, NULL);
99c5952f 191 return PTR_ERR(job);
dd08ebf6
MB
192 }
193
194 xe_sched_job_arm(job);
195 fence = dma_fence_get(&job->drm.s_fence->finished);
196 xe_sched_job_push(job);
197
198 timeout = dma_fence_wait_timeout(fence, false, HZ);
199 dma_fence_put(fence);
200 xe_bb_free(bb, NULL);
201 if (timeout < 0)
202 return timeout;
203 else if (!timeout)
204 return -ETIME;
205
206 return 0;
207}
208
209int xe_gt_record_default_lrcs(struct xe_gt *gt)
210{
211 struct xe_device *xe = gt_to_xe(gt);
212 struct xe_hw_engine *hwe;
213 enum xe_hw_engine_id id;
214 int err = 0;
215
216 for_each_hw_engine(hwe, gt, id) {
9b9529ce 217 struct xe_exec_queue *q, *nop_q;
dd08ebf6
MB
218 void *default_lrc;
219
220 if (gt->default_lrc[hwe->class])
221 continue;
222
766849c4 223 xe_reg_sr_init(&hwe->reg_lrc, hwe->name, xe);
dd08ebf6 224 xe_wa_process_lrc(hwe);
bb95a4f9 225 xe_hw_engine_setup_default_lrc_state(hwe);
3dbec470 226 xe_tuning_process_lrc(hwe);
dd08ebf6
MB
227
228 default_lrc = drmm_kzalloc(&xe->drm,
229 xe_lrc_size(xe, hwe->class),
230 GFP_KERNEL);
231 if (!default_lrc)
232 return -ENOMEM;
233
9e952635
DCS
234 q = xe_exec_queue_create(xe, NULL, BIT(hwe->logical_instance), 1,
235 hwe, EXEC_QUEUE_FLAG_KERNEL);
9b9529ce
FD
236 if (IS_ERR(q)) {
237 err = PTR_ERR(q);
238 xe_gt_err(gt, "hwe %s: xe_exec_queue_create failed (%pe)\n",
239 hwe->name, q);
9e952635 240 return err;
dd08ebf6
MB
241 }
242
243 /* Prime golden LRC with known good state */
9b9529ce 244 err = emit_wa_job(gt, q);
3d4451d3 245 if (err) {
3e535bd5 246 xe_gt_err(gt, "hwe %s: emit_wa_job failed (%pe) guc_id=%u\n",
9b9529ce
FD
247 hwe->name, ERR_PTR(err), q->guc->id);
248 goto put_exec_queue;
3d4451d3 249 }
dd08ebf6 250
9e952635
DCS
251 nop_q = xe_exec_queue_create(xe, NULL, BIT(hwe->logical_instance),
252 1, hwe, EXEC_QUEUE_FLAG_KERNEL);
9b9529ce
FD
253 if (IS_ERR(nop_q)) {
254 err = PTR_ERR(nop_q);
255 xe_gt_err(gt, "hwe %s: nop xe_exec_queue_create failed (%pe)\n",
256 hwe->name, nop_q);
257 goto put_exec_queue;
dd08ebf6
MB
258 }
259
260 /* Switch to different LRC */
9b9529ce 261 err = emit_nop_job(gt, nop_q);
3d4451d3 262 if (err) {
3e535bd5 263 xe_gt_err(gt, "hwe %s: nop emit_nop_job failed (%pe) guc_id=%u\n",
9b9529ce
FD
264 hwe->name, ERR_PTR(err), nop_q->guc->id);
265 goto put_nop_q;
3d4451d3 266 }
dd08ebf6
MB
267
268 /* Reload golden LRC to record the effect of any indirect W/A */
9b9529ce 269 err = emit_nop_job(gt, q);
3d4451d3 270 if (err) {
3e535bd5 271 xe_gt_err(gt, "hwe %s: emit_nop_job failed (%pe) guc_id=%u\n",
9b9529ce
FD
272 hwe->name, ERR_PTR(err), q->guc->id);
273 goto put_nop_q;
3d4451d3 274 }
dd08ebf6
MB
275
276 xe_map_memcpy_from(xe, default_lrc,
9b9529ce
FD
277 &q->lrc[0].bo->vmap,
278 xe_lrc_pphwsp_offset(&q->lrc[0]),
dd08ebf6
MB
279 xe_lrc_size(xe, hwe->class));
280
281 gt->default_lrc[hwe->class] = default_lrc;
9b9529ce
FD
282put_nop_q:
283 xe_exec_queue_put(nop_q);
284put_exec_queue:
285 xe_exec_queue_put(q);
dd08ebf6
MB
286 if (err)
287 break;
288 }
289
290 return err;
291}
292
293int xe_gt_init_early(struct xe_gt *gt)
294{
295 int err;
296
dd08ebf6
MB
297 err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
298 if (err)
299 return err;
300
301 xe_gt_topology_init(gt);
302 xe_gt_mcr_init(gt);
303
304 err = xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
305 if (err)
306 return err;
307
308 xe_reg_sr_init(&gt->reg_sr, "GT", gt_to_xe(gt));
49d329a0
LDM
309
310 err = xe_wa_init(gt);
311 if (err)
312 return err;
313
dd08ebf6 314 xe_wa_process_gt(gt);
9616e74b 315 xe_wa_process_oob(gt);
dd08ebf6
MB
316 xe_tuning_process_gt(gt);
317
318 return 0;
319}
320
d2300987
LDM
321static void dump_pat_on_error(struct xe_gt *gt)
322{
323 struct drm_printer p;
324 char prefix[32];
325
326 snprintf(prefix, sizeof(prefix), "[GT%u Error]", gt->info.id);
327 p = drm_debug_printer(prefix);
328
329 xe_pat_dump(gt, &p);
330}
331
dd08ebf6
MB
332static int gt_fw_domain_init(struct xe_gt *gt)
333{
334 int err, i;
335
336 xe_device_mem_access_get(gt_to_xe(gt));
337 err = xe_force_wake_get(gt_to_fw(gt), XE_FW_GT);
338 if (err)
339 goto err_hw_fence_irq;
340
576c6380 341 xe_pat_init(gt);
6c8c1e74 342
dd08ebf6 343 if (!xe_gt_is_media_type(gt)) {
ad703e06 344 err = xe_ggtt_init(gt_to_tile(gt)->mem.ggtt);
dd08ebf6
MB
345 if (err)
346 goto err_force_wake;
347 }
348
dd08ebf6 349 err = xe_uc_init(&gt->uc);
33de290b
CB
350 if (err)
351 goto err_force_wake;
dd08ebf6 352
43efd3ba
VB
353 /* Raise GT freq to speed up HuC/GuC load */
354 xe_guc_pc_init_early(&gt->uc.guc.pc);
355
dd08ebf6
MB
356 err = xe_uc_init_hwconfig(&gt->uc);
357 if (err)
358 goto err_force_wake;
359
1c2097bb
RT
360 xe_gt_idle_sysfs_init(&gt->gtidle);
361
da34c2cf
MB
362 /* XXX: Fake that we pull the engine mask from hwconfig blob */
363 gt->info.engine_mask = gt->info.__engine_mask;
364
3e29c149
MR
365 /* Enable per hw engine IRQs */
366 xe_irq_enable_hwe(gt);
dd08ebf6
MB
367
368 /* Rerun MCR init as we now have hw engine list */
369 xe_gt_mcr_init(gt);
370
371 err = xe_hw_engines_init_early(gt);
372 if (err)
373 goto err_force_wake;
374
038ff941
TU
375 err = xe_hw_engine_class_sysfs_init(gt);
376 if (err)
377 drm_warn(&gt_to_xe(gt)->drm,
378 "failed to register engines sysfs directory, err: %d\n",
379 err);
380
f3bc5bb4
NV
381 /* Initialize CCS mode sysfs after early initialization of HW engines */
382 xe_gt_ccs_mode_sysfs_init(gt);
383
dd08ebf6
MB
384 err = xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
385 XE_WARN_ON(err);
386 xe_device_mem_access_put(gt_to_xe(gt));
387
388 return 0;
389
390err_force_wake:
d2300987 391 dump_pat_on_error(gt);
dd08ebf6
MB
392 xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
393err_hw_fence_irq:
394 for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i)
395 xe_hw_fence_irq_finish(&gt->fence_irq[i]);
396 xe_device_mem_access_put(gt_to_xe(gt));
397
398 return err;
399}
400
401static int all_fw_domain_init(struct xe_gt *gt)
402{
403 int err, i;
404
405 xe_device_mem_access_get(gt_to_xe(gt));
406 err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
407 if (err)
408 goto err_hw_fence_irq;
409
564d64f8 410 xe_gt_mcr_set_implicit_defaults(gt);
dd08ebf6
MB
411 xe_reg_sr_apply_mmio(&gt->reg_sr, gt);
412
413 err = xe_gt_clock_init(gt);
414 if (err)
415 goto err_force_wake;
416
417 xe_mocs_init(gt);
418 err = xe_execlist_init(gt);
419 if (err)
420 goto err_force_wake;
421
422 err = xe_hw_engines_init(gt);
423 if (err)
424 goto err_force_wake;
425
426 err = xe_uc_init_post_hwconfig(&gt->uc);
427 if (err)
428 goto err_force_wake;
429
dd08ebf6 430 if (!xe_gt_is_media_type(gt)) {
dd08ebf6
MB
431 /*
432 * USM has its only SA pool to non-block behind user operations
433 */
434 if (gt_to_xe(gt)->info.supports_usm) {
876611c2 435 gt->usm.bb_pool = xe_sa_bo_manager_init(gt_to_tile(gt), SZ_1M, 16);
0a12a612
MR
436 if (IS_ERR(gt->usm.bb_pool)) {
437 err = PTR_ERR(gt->usm.bb_pool);
dd08ebf6 438 goto err_force_wake;
0a12a612 439 }
dd08ebf6
MB
440 }
441 }
442
443 if (!xe_gt_is_media_type(gt)) {
08dea767
MR
444 struct xe_tile *tile = gt_to_tile(gt);
445
446 tile->migrate = xe_migrate_init(tile);
447 if (IS_ERR(tile->migrate)) {
448 err = PTR_ERR(tile->migrate);
dd08ebf6 449 goto err_force_wake;
99c5952f 450 }
dd08ebf6
MB
451 }
452
453 err = xe_uc_init_hw(&gt->uc);
454 if (err)
455 goto err_force_wake;
456
0d97ecce
NV
457 /* Configure default CCS mode of 1 engine with all resources */
458 if (xe_gt_ccs_mode_enabled(gt)) {
459 gt->ccs_mode = 1;
460 xe_gt_apply_ccs_mode(gt);
461 }
462
dd08ebf6
MB
463 err = xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
464 XE_WARN_ON(err);
465 xe_device_mem_access_put(gt_to_xe(gt));
466
467 return 0;
468
469err_force_wake:
470 xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
471err_hw_fence_irq:
472 for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i)
473 xe_hw_fence_irq_finish(&gt->fence_irq[i]);
474 xe_device_mem_access_put(gt_to_xe(gt));
475
476 return err;
477}
478
479int xe_gt_init(struct xe_gt *gt)
480{
481 int err;
482 int i;
483
484 INIT_WORK(&gt->reset.worker, gt_reset_worker);
485
486 for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i) {
487 gt->ring_ops[i] = xe_ring_ops_get(gt, i);
488 xe_hw_fence_irq_init(&gt->fence_irq[i]);
489 }
490
a9351846
MB
491 err = xe_gt_tlb_invalidation_init(gt);
492 if (err)
493 return err;
494
dd08ebf6
MB
495 err = xe_gt_pagefault_init(gt);
496 if (err)
497 return err;
498
17a6726c
MR
499 xe_mocs_init_early(gt);
500
dd08ebf6
MB
501 xe_gt_sysfs_init(gt);
502
503 err = gt_fw_domain_init(gt);
504 if (err)
505 return err;
506
507 xe_force_wake_init_engines(gt, gt_to_fw(gt));
508
509 err = all_fw_domain_init(gt);
510 if (err)
511 return err;
512
dd08ebf6
MB
513 err = drmm_add_action_or_reset(&gt_to_xe(gt)->drm, gt_fini, gt);
514 if (err)
515 return err;
516
517 return 0;
518}
519
671ca05d 520static int do_gt_reset(struct xe_gt *gt)
dd08ebf6 521{
dd08ebf6
MB
522 int err;
523
aae84bf1
DCS
524 xe_gsc_wa_14015076503(gt, true);
525
ce8bf5bd 526 xe_mmio_write32(gt, GDRST, GRDOM_FULL);
063e09af 527 err = xe_mmio_wait32(gt, GDRST, GRDOM_FULL, 0, 5000, NULL, false);
dd08ebf6 528 if (err)
0bc519d2 529 xe_gt_err(gt, "failed to clear GRDOM_FULL (%pe)\n",
3e535bd5 530 ERR_PTR(err));
dd08ebf6 531
aae84bf1
DCS
532 xe_gsc_wa_14015076503(gt, false);
533
dd08ebf6
MB
534 return err;
535}
536
537static int do_gt_restart(struct xe_gt *gt)
538{
539 struct xe_hw_engine *hwe;
540 enum xe_hw_engine_id id;
541 int err;
542
576c6380 543 xe_pat_init(gt);
dd08ebf6 544
564d64f8 545 xe_gt_mcr_set_implicit_defaults(gt);
dd08ebf6
MB
546 xe_reg_sr_apply_mmio(&gt->reg_sr, gt);
547
548 err = xe_wopcm_init(&gt->uc.wopcm);
549 if (err)
550 return err;
551
552 for_each_hw_engine(hwe, gt, id)
553 xe_hw_engine_enable_ring(hwe);
554
7704f32c
MW
555 err = xe_uc_sanitize_reset(&gt->uc);
556 if (err)
557 return err;
558
dd08ebf6
MB
559 err = xe_uc_init_hw(&gt->uc);
560 if (err)
561 return err;
562
563 xe_mocs_init(gt);
564 err = xe_uc_start(&gt->uc);
565 if (err)
566 return err;
567
568 for_each_hw_engine(hwe, gt, id) {
569 xe_reg_sr_apply_mmio(&hwe->reg_sr, gt);
1011812c 570 xe_reg_sr_apply_whitelist(hwe);
dd08ebf6
MB
571 }
572
0d97ecce
NV
573 /* Get CCS mode in sync between sw/hw */
574 xe_gt_apply_ccs_mode(gt);
575
dd08ebf6
MB
576 return 0;
577}
578
4f027e30
HPG
579static void xe_uevent_gt_reset_failure(struct pci_dev *pdev, u8 tile_id, u8 gt_id)
580{
581 char *reset_event[4];
582
d5dc73db 583 reset_event[0] = DRM_XE_RESET_FAILED_UEVENT "=NEEDS_RESET";
4f027e30
HPG
584 reset_event[1] = kasprintf(GFP_KERNEL, "TILE_ID=%d", tile_id);
585 reset_event[2] = kasprintf(GFP_KERNEL, "GT_ID=%d", gt_id);
586 reset_event[3] = NULL;
587 kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, reset_event);
588
589 kfree(reset_event[1]);
590 kfree(reset_event[2]);
591}
592
dd08ebf6
MB
593static int gt_reset(struct xe_gt *gt)
594{
dd08ebf6
MB
595 int err;
596
597 /* We only support GT resets with GuC submission */
c4991ee0 598 if (!xe_device_uc_enabled(gt_to_xe(gt)))
dd08ebf6
MB
599 return -ENODEV;
600
3e535bd5 601 xe_gt_info(gt, "reset started\n");
dd08ebf6 602
8f3013e0
HPG
603 if (xe_fault_inject_gt_reset()) {
604 err = -ECANCELED;
605 goto err_fail;
606 }
607
da3799c9
MB
608 xe_gt_sanitize(gt);
609
dd08ebf6
MB
610 xe_device_mem_access_get(gt_to_xe(gt));
611 err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
612 if (err)
613 goto err_msg;
614
1737785a 615 xe_uc_gucrc_disable(&gt->uc);
dd08ebf6
MB
616 xe_uc_stop_prepare(&gt->uc);
617 xe_gt_pagefault_reset(gt);
618
619 err = xe_uc_stop(&gt->uc);
620 if (err)
621 goto err_out;
622
623 err = do_gt_reset(gt);
624 if (err)
625 goto err_out;
626
7b24cc3e
MA
627 xe_gt_tlb_invalidation_reset(gt);
628
dd08ebf6
MB
629 err = do_gt_restart(gt);
630 if (err)
631 goto err_out;
632
dd08ebf6 633 err = xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL);
03af26c9 634 xe_device_mem_access_put(gt_to_xe(gt));
dd08ebf6
MB
635 XE_WARN_ON(err);
636
3e535bd5 637 xe_gt_info(gt, "reset done\n");
dd08ebf6
MB
638
639 return 0;
640
641err_out:
642 XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
643err_msg:
644 XE_WARN_ON(xe_uc_start(&gt->uc));
645 xe_device_mem_access_put(gt_to_xe(gt));
8f3013e0 646err_fail:
3e535bd5 647 xe_gt_err(gt, "reset failed (%pe)\n", ERR_PTR(err));
dd08ebf6 648
4f027e30
HPG
649 /* Notify userspace about gt reset failure */
650 xe_uevent_gt_reset_failure(to_pci_dev(gt_to_xe(gt)->drm.dev),
651 gt_to_tile(gt)->id, gt->info.id);
652
57162274
AH
653 gt_to_xe(gt)->needs_flr_on_fini = true;
654
dd08ebf6
MB
655 return err;
656}
657
658static void gt_reset_worker(struct work_struct *w)
659{
660 struct xe_gt *gt = container_of(w, typeof(*gt), reset.worker);
661
662 gt_reset(gt);
663}
664
665void xe_gt_reset_async(struct xe_gt *gt)
666{
3e535bd5 667 xe_gt_info(gt, "trying reset\n");
dd08ebf6
MB
668
669 /* Don't do a reset while one is already in flight */
8f3013e0 670 if (!xe_fault_inject_gt_reset() && xe_uc_reset_prepare(&gt->uc))
dd08ebf6
MB
671 return;
672
3e535bd5 673 xe_gt_info(gt, "reset queued\n");
dd08ebf6
MB
674 queue_work(gt->ordered_wq, &gt->reset.worker);
675}
676
677void xe_gt_suspend_prepare(struct xe_gt *gt)
678{
679 xe_device_mem_access_get(gt_to_xe(gt));
680 XE_WARN_ON(xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL));
681
682 xe_uc_stop_prepare(&gt->uc);
683
dd08ebf6 684 XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
03af26c9 685 xe_device_mem_access_put(gt_to_xe(gt));
dd08ebf6
MB
686}
687
688int xe_gt_suspend(struct xe_gt *gt)
689{
dd08ebf6
MB
690 int err;
691
da3799c9
MB
692 xe_gt_sanitize(gt);
693
dd08ebf6
MB
694 xe_device_mem_access_get(gt_to_xe(gt));
695 err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
696 if (err)
697 goto err_msg;
698
3856b0f7
AI
699 xe_pmu_suspend(gt);
700
dd08ebf6
MB
701 err = xe_uc_suspend(&gt->uc);
702 if (err)
703 goto err_force_wake;
704
dd08ebf6 705 XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
03af26c9 706 xe_device_mem_access_put(gt_to_xe(gt));
3e535bd5 707 xe_gt_info(gt, "suspended\n");
dd08ebf6
MB
708
709 return 0;
710
711err_force_wake:
712 XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
713err_msg:
714 xe_device_mem_access_put(gt_to_xe(gt));
3e535bd5 715 xe_gt_err(gt, "suspend failed (%pe)\n", ERR_PTR(err));
dd08ebf6
MB
716
717 return err;
718}
719
720int xe_gt_resume(struct xe_gt *gt)
721{
dd08ebf6
MB
722 int err;
723
724 xe_device_mem_access_get(gt_to_xe(gt));
725 err = xe_force_wake_get(gt_to_fw(gt), XE_FORCEWAKE_ALL);
726 if (err)
727 goto err_msg;
728
729 err = do_gt_restart(gt);
730 if (err)
731 goto err_force_wake;
732
dd08ebf6 733 XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
03af26c9 734 xe_device_mem_access_put(gt_to_xe(gt));
3e535bd5 735 xe_gt_info(gt, "resumed\n");
dd08ebf6
MB
736
737 return 0;
738
739err_force_wake:
740 XE_WARN_ON(xe_force_wake_put(gt_to_fw(gt), XE_FORCEWAKE_ALL));
741err_msg:
742 xe_device_mem_access_put(gt_to_xe(gt));
3e535bd5 743 xe_gt_err(gt, "resume failed (%pe)\n", ERR_PTR(err));
dd08ebf6
MB
744
745 return err;
746}
747
dd08ebf6
MB
748struct xe_hw_engine *xe_gt_hw_engine(struct xe_gt *gt,
749 enum xe_engine_class class,
750 u16 instance, bool logical)
751{
752 struct xe_hw_engine *hwe;
753 enum xe_hw_engine_id id;
754
755 for_each_hw_engine(hwe, gt, id)
756 if (hwe->class == class &&
757 ((!logical && hwe->instance == instance) ||
758 (logical && hwe->logical_instance == instance)))
759 return hwe;
760
761 return NULL;
762}
763
764struct xe_hw_engine *xe_gt_any_hw_engine_by_reset_domain(struct xe_gt *gt,
765 enum xe_engine_class class)
766{
767 struct xe_hw_engine *hwe;
768 enum xe_hw_engine_id id;
769
770 for_each_hw_engine(hwe, gt, id) {
771 switch (class) {
772 case XE_ENGINE_CLASS_RENDER:
773 case XE_ENGINE_CLASS_COMPUTE:
774 if (hwe->class == XE_ENGINE_CLASS_RENDER ||
775 hwe->class == XE_ENGINE_CLASS_COMPUTE)
776 return hwe;
777 break;
778 default:
779 if (hwe->class == class)
780 return hwe;
781 }
782 }
783
784 return NULL;
785}