Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2014 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  */
0022 
0023 #include "kfd_priv.h"
0024 #include "kfd_events.h"
0025 #include "cik_int.h"
0026 #include "amdgpu_amdkfd.h"
0027 #include "kfd_smi_events.h"
0028 
0029 static bool cik_event_interrupt_isr(struct kfd_dev *dev,
0030                     const uint32_t *ih_ring_entry,
0031                     uint32_t *patched_ihre,
0032                     bool *patched_flag)
0033 {
0034     const struct cik_ih_ring_entry *ihre =
0035             (const struct cik_ih_ring_entry *)ih_ring_entry;
0036     const struct kfd2kgd_calls *f2g = dev->kfd2kgd;
0037     unsigned int vmid;
0038     uint16_t pasid;
0039     bool ret;
0040 
0041     /* This workaround is due to HW/FW limitation on Hawaii that
0042      * VMID and PASID are not written into ih_ring_entry
0043      */
0044     if ((ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT ||
0045         ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT) &&
0046         dev->adev->asic_type == CHIP_HAWAII) {
0047         struct cik_ih_ring_entry *tmp_ihre =
0048             (struct cik_ih_ring_entry *)patched_ihre;
0049 
0050         *patched_flag = true;
0051         *tmp_ihre = *ihre;
0052 
0053         vmid = f2g->read_vmid_from_vmfault_reg(dev->adev);
0054         ret = f2g->get_atc_vmid_pasid_mapping_info(dev->adev, vmid, &pasid);
0055 
0056         tmp_ihre->ring_id &= 0x000000ff;
0057         tmp_ihre->ring_id |= vmid << 8;
0058         tmp_ihre->ring_id |= pasid << 16;
0059 
0060         return ret && (pasid != 0) &&
0061             vmid >= dev->vm_info.first_vmid_kfd &&
0062             vmid <= dev->vm_info.last_vmid_kfd;
0063     }
0064 
0065     /* Only handle interrupts from KFD VMIDs */
0066     vmid  = (ihre->ring_id & 0x0000ff00) >> 8;
0067     if (vmid < dev->vm_info.first_vmid_kfd ||
0068         vmid > dev->vm_info.last_vmid_kfd)
0069         return false;
0070 
0071     /* If there is no valid PASID, it's likely a firmware bug */
0072     pasid = (ihre->ring_id & 0xffff0000) >> 16;
0073     if (WARN_ONCE(pasid == 0, "FW bug: No PASID in KFD interrupt"))
0074         return false;
0075 
0076     /* Interrupt types we care about: various signals and faults.
0077      * They will be forwarded to a work queue (see below).
0078      */
0079     return ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE ||
0080         ihre->source_id == CIK_INTSRC_SDMA_TRAP ||
0081         ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG ||
0082         ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE ||
0083         ((ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT ||
0084         ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT) &&
0085         !amdgpu_no_queue_eviction_on_vm_fault);
0086 }
0087 
0088 static void cik_event_interrupt_wq(struct kfd_dev *dev,
0089                     const uint32_t *ih_ring_entry)
0090 {
0091     const struct cik_ih_ring_entry *ihre =
0092             (const struct cik_ih_ring_entry *)ih_ring_entry;
0093     uint32_t context_id = ihre->data & 0xfffffff;
0094     unsigned int vmid  = (ihre->ring_id & 0x0000ff00) >> 8;
0095     u32 pasid = (ihre->ring_id & 0xffff0000) >> 16;
0096 
0097     if (pasid == 0)
0098         return;
0099 
0100     if (ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE)
0101         kfd_signal_event_interrupt(pasid, context_id, 28);
0102     else if (ihre->source_id == CIK_INTSRC_SDMA_TRAP)
0103         kfd_signal_event_interrupt(pasid, context_id, 28);
0104     else if (ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG)
0105         kfd_signal_event_interrupt(pasid, context_id & 0xff, 8);
0106     else if (ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE)
0107         kfd_signal_hw_exception_event(pasid);
0108     else if (ihre->source_id == CIK_INTSRC_GFX_PAGE_INV_FAULT ||
0109         ihre->source_id == CIK_INTSRC_GFX_MEM_PROT_FAULT) {
0110         struct kfd_vm_fault_info info;
0111 
0112         kfd_smi_event_update_vmfault(dev, pasid);
0113         kfd_dqm_evict_pasid(dev->dqm, pasid);
0114 
0115         memset(&info, 0, sizeof(info));
0116         amdgpu_amdkfd_gpuvm_get_vm_fault_info(dev->adev, &info);
0117         if (!info.page_addr && !info.status)
0118             return;
0119 
0120         if (info.vmid == vmid)
0121             kfd_signal_vm_fault_event(dev, pasid, &info);
0122         else
0123             kfd_signal_vm_fault_event(dev, pasid, NULL);
0124     }
0125 }
0126 
0127 const struct kfd_event_interrupt_class event_interrupt_class_cik = {
0128     .interrupt_isr = cik_event_interrupt_isr,
0129     .interrupt_wq = cik_event_interrupt_wq,
0130 };