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