xref: /linux/drivers/gpu/drm/xe/xe_mert.c (revision 9ec3c8ee16a07dff8be82aba595dd77c134c03c2)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright(c) 2025, Intel Corporation. All rights reserved.
4  */
5 
6 #include "regs/xe_irq_regs.h"
7 #include "regs/xe_mert_regs.h"
8 
9 #include "xe_device.h"
10 #include "xe_mert.h"
11 #include "xe_mmio.h"
12 #include "xe_tile.h"
13 
14 /**
15  * xe_mert_invalidate_lmtt - Invalidate MERT LMTT
16  * @tile: the &xe_tile
17  *
18  * Trigger invalidation of the MERT LMTT and wait for completion.
19  *
20  * Return: 0 on success or -ETIMEDOUT in case of a timeout.
21  */
22 int xe_mert_invalidate_lmtt(struct xe_tile *tile)
23 {
24 	struct xe_device *xe = tile_to_xe(tile);
25 	struct xe_mert *mert = &tile->mert;
26 	const long timeout = HZ / 4;
27 	unsigned long flags;
28 
29 	xe_assert(xe, xe_device_has_mert(xe));
30 	xe_assert(xe, xe_tile_is_root(tile));
31 
32 	spin_lock_irqsave(&mert->lock, flags);
33 	if (!mert->tlb_inv_triggered) {
34 		mert->tlb_inv_triggered = true;
35 		reinit_completion(&mert->tlb_inv_done);
36 		xe_mmio_write32(&tile->mmio, MERT_TLB_INV_DESC_A, MERT_TLB_INV_DESC_A_VALID);
37 	}
38 	spin_unlock_irqrestore(&mert->lock, flags);
39 
40 	if (!wait_for_completion_timeout(&mert->tlb_inv_done, timeout))
41 		return -ETIMEDOUT;
42 
43 	return 0;
44 }
45 
46 /**
47  * xe_mert_irq_handler - Handler for MERT interrupts
48  * @xe: the &xe_device
49  * @master_ctl: interrupt register
50  *
51  * Handle interrupts generated by MERT.
52  */
53 void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl)
54 {
55 	struct xe_tile *tile = xe_device_get_root_tile(xe);
56 	unsigned long flags;
57 	u32 reg_val;
58 	u8 err;
59 
60 	if (!(master_ctl & SOC_H2DMEMINT_IRQ))
61 		return;
62 
63 	reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT);
64 	xe_mmio_write32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT, 0);
65 
66 	err = FIELD_GET(MERT_TLB_CT_ERROR_MASK, reg_val);
67 	if (err == MERT_TLB_CT_LMTT_FAULT)
68 		drm_dbg(&xe->drm, "MERT catastrophic error: LMTT fault (VF%u)\n",
69 			FIELD_GET(MERT_TLB_CT_VFID_MASK, reg_val));
70 	else if (err)
71 		drm_dbg(&xe->drm, "MERT catastrophic error: Unexpected fault (0x%x)\n", err);
72 
73 	spin_lock_irqsave(&tile->mert.lock, flags);
74 	if (tile->mert.tlb_inv_triggered) {
75 		reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_INV_DESC_A);
76 		if (!(reg_val & MERT_TLB_INV_DESC_A_VALID)) {
77 			tile->mert.tlb_inv_triggered = false;
78 			complete_all(&tile->mert.tlb_inv_done);
79 		}
80 	}
81 	spin_unlock_irqrestore(&tile->mert.lock, flags);
82 }
83