xref: /linux/drivers/gpu/drm/xe/xe_mert.c (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
11fc30960SLukasz Laguna // SPDX-License-Identifier: MIT
21fc30960SLukasz Laguna /*
31fc30960SLukasz Laguna  * Copyright(c) 2025, Intel Corporation. All rights reserved.
41fc30960SLukasz Laguna  */
51fc30960SLukasz Laguna 
61fc30960SLukasz Laguna #include "regs/xe_irq_regs.h"
71fc30960SLukasz Laguna #include "regs/xe_mert_regs.h"
81fc30960SLukasz Laguna 
91fc30960SLukasz Laguna #include "xe_device.h"
101fc30960SLukasz Laguna #include "xe_mert.h"
111fc30960SLukasz Laguna #include "xe_mmio.h"
12*def675cfSMichal Wajdeczko #include "xe_sriov_printk.h"
131fc30960SLukasz Laguna #include "xe_tile.h"
141fc30960SLukasz Laguna 
151fc30960SLukasz Laguna /**
167970e04dSMichal Wajdeczko  * xe_mert_init_early() - Initialize MERT data
177970e04dSMichal Wajdeczko  * @xe: the &xe_device with MERT to init
187970e04dSMichal Wajdeczko  */
197970e04dSMichal Wajdeczko void xe_mert_init_early(struct xe_device *xe)
207970e04dSMichal Wajdeczko {
217970e04dSMichal Wajdeczko 	struct xe_tile *tile = xe_device_get_root_tile(xe);
227970e04dSMichal Wajdeczko 	struct xe_mert *mert = &tile->mert;
237970e04dSMichal Wajdeczko 
247970e04dSMichal Wajdeczko 	spin_lock_init(&mert->lock);
257970e04dSMichal Wajdeczko 	init_completion(&mert->tlb_inv_done);
267970e04dSMichal Wajdeczko }
277970e04dSMichal Wajdeczko 
287970e04dSMichal Wajdeczko /**
29ff4eca1fSMichal Wajdeczko  * xe_mert_invalidate_lmtt() - Invalidate MERT LMTT
30ff4eca1fSMichal Wajdeczko  * @xe: the &xe_device with MERT
311fc30960SLukasz Laguna  *
321fc30960SLukasz Laguna  * Trigger invalidation of the MERT LMTT and wait for completion.
331fc30960SLukasz Laguna  *
341fc30960SLukasz Laguna  * Return: 0 on success or -ETIMEDOUT in case of a timeout.
351fc30960SLukasz Laguna  */
36ff4eca1fSMichal Wajdeczko int xe_mert_invalidate_lmtt(struct xe_device *xe)
371fc30960SLukasz Laguna {
38ff4eca1fSMichal Wajdeczko 	struct xe_tile *tile = xe_device_get_root_tile(xe);
391fc30960SLukasz Laguna 	struct xe_mert *mert = &tile->mert;
401fc30960SLukasz Laguna 	const long timeout = HZ / 4;
411fc30960SLukasz Laguna 	unsigned long flags;
421fc30960SLukasz Laguna 
431fc30960SLukasz Laguna 	xe_assert(xe, xe_device_has_mert(xe));
441fc30960SLukasz Laguna 
451fc30960SLukasz Laguna 	spin_lock_irqsave(&mert->lock, flags);
461fc30960SLukasz Laguna 	if (!mert->tlb_inv_triggered) {
471fc30960SLukasz Laguna 		mert->tlb_inv_triggered = true;
481fc30960SLukasz Laguna 		reinit_completion(&mert->tlb_inv_done);
491fc30960SLukasz Laguna 		xe_mmio_write32(&tile->mmio, MERT_TLB_INV_DESC_A, MERT_TLB_INV_DESC_A_VALID);
501fc30960SLukasz Laguna 	}
511fc30960SLukasz Laguna 	spin_unlock_irqrestore(&mert->lock, flags);
521fc30960SLukasz Laguna 
531fc30960SLukasz Laguna 	if (!wait_for_completion_timeout(&mert->tlb_inv_done, timeout))
541fc30960SLukasz Laguna 		return -ETIMEDOUT;
551fc30960SLukasz Laguna 
561fc30960SLukasz Laguna 	return 0;
571fc30960SLukasz Laguna }
581fc30960SLukasz Laguna 
59*def675cfSMichal Wajdeczko static void mert_handle_cat_error(struct xe_device *xe)
60*def675cfSMichal Wajdeczko {
61*def675cfSMichal Wajdeczko 	struct xe_tile *tile = xe_device_get_root_tile(xe);
62*def675cfSMichal Wajdeczko 	u32 reg_val, vfid, code;
63*def675cfSMichal Wajdeczko 
64*def675cfSMichal Wajdeczko 	reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT);
65*def675cfSMichal Wajdeczko 	if (!reg_val)
66*def675cfSMichal Wajdeczko 		return;
67*def675cfSMichal Wajdeczko 	xe_mmio_write32(&tile->mmio, MERT_TLB_CT_INTR_ERR_ID_PORT, 0);
68*def675cfSMichal Wajdeczko 
69*def675cfSMichal Wajdeczko 	vfid = FIELD_GET(CATERR_VFID, reg_val);
70*def675cfSMichal Wajdeczko 	code = FIELD_GET(CATERR_CODES, reg_val);
71*def675cfSMichal Wajdeczko 
72*def675cfSMichal Wajdeczko 	switch (code) {
73*def675cfSMichal Wajdeczko 	case CATERR_NO_ERROR:
74*def675cfSMichal Wajdeczko 		break;
75*def675cfSMichal Wajdeczko 	case CATERR_UNMAPPED_GGTT:
76*def675cfSMichal Wajdeczko 		xe_sriov_err(xe, "MERT: CAT_ERR: Access to an unmapped GGTT!\n");
77*def675cfSMichal Wajdeczko 		xe_device_declare_wedged(xe);
78*def675cfSMichal Wajdeczko 		break;
79*def675cfSMichal Wajdeczko 	case CATERR_LMTT_FAULT:
80*def675cfSMichal Wajdeczko 		xe_sriov_dbg(xe, "MERT: CAT_ERR: VF%u LMTT fault!\n", vfid);
81*def675cfSMichal Wajdeczko 		/* XXX: track/report malicious VF activity */
82*def675cfSMichal Wajdeczko 		break;
83*def675cfSMichal Wajdeczko 	default:
84*def675cfSMichal Wajdeczko 		xe_sriov_err(xe, "MERT: Unexpected CAT_ERR code=%#x!\n", code);
85*def675cfSMichal Wajdeczko 		xe_device_declare_wedged(xe);
86*def675cfSMichal Wajdeczko 		break;
87*def675cfSMichal Wajdeczko 	}
88*def675cfSMichal Wajdeczko }
89*def675cfSMichal Wajdeczko 
901fc30960SLukasz Laguna /**
911fc30960SLukasz Laguna  * xe_mert_irq_handler - Handler for MERT interrupts
921fc30960SLukasz Laguna  * @xe: the &xe_device
931fc30960SLukasz Laguna  * @master_ctl: interrupt register
941fc30960SLukasz Laguna  *
951fc30960SLukasz Laguna  * Handle interrupts generated by MERT.
961fc30960SLukasz Laguna  */
971fc30960SLukasz Laguna void xe_mert_irq_handler(struct xe_device *xe, u32 master_ctl)
981fc30960SLukasz Laguna {
991fc30960SLukasz Laguna 	struct xe_tile *tile = xe_device_get_root_tile(xe);
100401fabd6SMichal Wajdeczko 	struct xe_mert *mert = &tile->mert;
1011fc30960SLukasz Laguna 	unsigned long flags;
1021fc30960SLukasz Laguna 	u32 reg_val;
1031fc30960SLukasz Laguna 
1041fc30960SLukasz Laguna 	if (!(master_ctl & SOC_H2DMEMINT_IRQ))
1051fc30960SLukasz Laguna 		return;
1061fc30960SLukasz Laguna 
107*def675cfSMichal Wajdeczko 	mert_handle_cat_error(xe);
1082e02254eSLukasz Laguna 
109401fabd6SMichal Wajdeczko 	spin_lock_irqsave(&mert->lock, flags);
110401fabd6SMichal Wajdeczko 	if (mert->tlb_inv_triggered) {
1111fc30960SLukasz Laguna 		reg_val = xe_mmio_read32(&tile->mmio, MERT_TLB_INV_DESC_A);
1121fc30960SLukasz Laguna 		if (!(reg_val & MERT_TLB_INV_DESC_A_VALID)) {
113401fabd6SMichal Wajdeczko 			mert->tlb_inv_triggered = false;
114401fabd6SMichal Wajdeczko 			complete_all(&mert->tlb_inv_done);
1151fc30960SLukasz Laguna 		}
1161fc30960SLukasz Laguna 	}
117401fabd6SMichal Wajdeczko 	spin_unlock_irqrestore(&mert->lock, flags);
1181fc30960SLukasz Laguna }
119