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