Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2018 Red Hat 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 #include "priv.h"
0023 
0024 #include <core/memory.h>
0025 #include <subdev/mc.h>
0026 #include <subdev/mmu.h>
0027 #include <engine/fifo.h>
0028 
0029 #include <nvif/class.h>
0030 
0031 static void
0032 tu102_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable)
0033 {
0034     /*XXX: Earlier versions of RM touched the old regs on Turing,
0035      *     which don't appear to actually work anymore, but newer
0036      *     versions of RM don't appear to touch anything at all..
0037      */
0038     struct nvkm_device *device = buffer->fault->subdev.device;
0039 
0040     nvkm_mc_intr_mask(device, NVKM_SUBDEV_FAULT, 0, enable);
0041 }
0042 
0043 static void
0044 tu102_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
0045 {
0046     struct nvkm_device *device = buffer->fault->subdev.device;
0047     const u32 foff = buffer->id * 0x20;
0048 
0049     /* Disable the fault interrupts */
0050     nvkm_wr32(device, 0xb81408, 0x1);
0051     nvkm_wr32(device, 0xb81410, 0x10);
0052 
0053     nvkm_mask(device, 0xb83010 + foff, 0x80000000, 0x00000000);
0054 }
0055 
0056 static void
0057 tu102_fault_buffer_init(struct nvkm_fault_buffer *buffer)
0058 {
0059     struct nvkm_device *device = buffer->fault->subdev.device;
0060     const u32 foff = buffer->id * 0x20;
0061 
0062     /* Enable the fault interrupts */
0063     nvkm_wr32(device, 0xb81208, 0x1);
0064     nvkm_wr32(device, 0xb81210, 0x10);
0065 
0066     nvkm_mask(device, 0xb83010 + foff, 0xc0000000, 0x40000000);
0067     nvkm_wr32(device, 0xb83004 + foff, upper_32_bits(buffer->addr));
0068     nvkm_wr32(device, 0xb83000 + foff, lower_32_bits(buffer->addr));
0069     nvkm_mask(device, 0xb83010 + foff, 0x80000000, 0x80000000);
0070 }
0071 
0072 static void
0073 tu102_fault_buffer_info(struct nvkm_fault_buffer *buffer)
0074 {
0075     struct nvkm_device *device = buffer->fault->subdev.device;
0076     const u32 foff = buffer->id * 0x20;
0077 
0078     nvkm_mask(device, 0xb83010 + foff, 0x40000000, 0x40000000);
0079 
0080     buffer->entries = nvkm_rd32(device, 0xb83010 + foff) & 0x000fffff;
0081     buffer->get = 0xb83008 + foff;
0082     buffer->put = 0xb8300c + foff;
0083 }
0084 
0085 static void
0086 tu102_fault_intr_fault(struct nvkm_fault *fault)
0087 {
0088     struct nvkm_subdev *subdev = &fault->subdev;
0089     struct nvkm_device *device = subdev->device;
0090     struct nvkm_fault_data info;
0091     const u32 addrlo = nvkm_rd32(device, 0xb83080);
0092     const u32 addrhi = nvkm_rd32(device, 0xb83084);
0093     const u32  info0 = nvkm_rd32(device, 0xb83088);
0094     const u32 insthi = nvkm_rd32(device, 0xb8308c);
0095     const u32  info1 = nvkm_rd32(device, 0xb83090);
0096 
0097     info.addr = ((u64)addrhi << 32) | addrlo;
0098     info.inst = ((u64)insthi << 32) | (info0 & 0xfffff000);
0099     info.time = 0;
0100     info.engine = (info0 & 0x000000ff);
0101     info.valid  = (info1 & 0x80000000) >> 31;
0102     info.gpc    = (info1 & 0x1f000000) >> 24;
0103     info.hub    = (info1 & 0x00100000) >> 20;
0104     info.access = (info1 & 0x000f0000) >> 16;
0105     info.client = (info1 & 0x00007f00) >> 8;
0106     info.reason = (info1 & 0x0000001f);
0107 
0108     nvkm_fifo_fault(device->fifo, &info);
0109 }
0110 
0111 static void
0112 tu102_fault_intr(struct nvkm_fault *fault)
0113 {
0114     struct nvkm_subdev *subdev = &fault->subdev;
0115     struct nvkm_device *device = subdev->device;
0116     u32 stat = nvkm_rd32(device, 0xb83094);
0117 
0118     if (stat & 0x80000000) {
0119         tu102_fault_intr_fault(fault);
0120         nvkm_wr32(device, 0xb83094, 0x80000000);
0121         stat &= ~0x80000000;
0122     }
0123 
0124     if (stat & 0x00000200) {
0125         /* Clear the associated interrupt flag */
0126         nvkm_wr32(device, 0xb81010, 0x10);
0127 
0128         if (fault->buffer[0]) {
0129             nvkm_event_send(&fault->event, 1, 0, NULL, 0);
0130             stat &= ~0x00000200;
0131         }
0132     }
0133 
0134     /* Replayable MMU fault */
0135     if (stat & 0x00000100) {
0136         /* Clear the associated interrupt flag */
0137         nvkm_wr32(device, 0xb81008, 0x1);
0138 
0139         if (fault->buffer[1]) {
0140             nvkm_event_send(&fault->event, 1, 1, NULL, 0);
0141             stat &= ~0x00000100;
0142         }
0143     }
0144 
0145     if (stat) {
0146         nvkm_debug(subdev, "intr %08x\n", stat);
0147     }
0148 }
0149 
0150 static void
0151 tu102_fault_fini(struct nvkm_fault *fault)
0152 {
0153     nvkm_notify_put(&fault->nrpfb);
0154     if (fault->buffer[0])
0155         fault->func->buffer.fini(fault->buffer[0]);
0156     /*XXX: disable priv faults */
0157 }
0158 
0159 static void
0160 tu102_fault_init(struct nvkm_fault *fault)
0161 {
0162     /*XXX: enable priv faults */
0163     fault->func->buffer.init(fault->buffer[0]);
0164     nvkm_notify_get(&fault->nrpfb);
0165 }
0166 
0167 static const struct nvkm_fault_func
0168 tu102_fault = {
0169     .oneinit = gv100_fault_oneinit,
0170     .init = tu102_fault_init,
0171     .fini = tu102_fault_fini,
0172     .intr = tu102_fault_intr,
0173     .buffer.nr = 2,
0174     .buffer.entry_size = 32,
0175     .buffer.info = tu102_fault_buffer_info,
0176     .buffer.pin = gp100_fault_buffer_pin,
0177     .buffer.init = tu102_fault_buffer_init,
0178     .buffer.fini = tu102_fault_buffer_fini,
0179     .buffer.intr = tu102_fault_buffer_intr,
0180     .user = { { 0, 0, VOLTA_FAULT_BUFFER_A }, 1 },
0181 };
0182 
0183 int
0184 tu102_fault_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0185         struct nvkm_fault **pfault)
0186 {
0187     return nvkm_fault_new_(&tu102_fault, device, type, inst, pfault);
0188 }