.. | .. |
---|
25 | 25 | #include <subdev/mmu.h> |
---|
26 | 26 | #include <engine/fifo.h> |
---|
27 | 27 | |
---|
| 28 | +#include <nvif/class.h> |
---|
| 29 | + |
---|
28 | 30 | static void |
---|
29 | 31 | gv100_fault_buffer_process(struct nvkm_fault_buffer *buffer) |
---|
30 | 32 | { |
---|
31 | 33 | struct nvkm_device *device = buffer->fault->subdev.device; |
---|
32 | 34 | struct nvkm_memory *mem = buffer->mem; |
---|
33 | | - const u32 foff = buffer->id * 0x14; |
---|
34 | | - u32 get = nvkm_rd32(device, 0x100e2c + foff); |
---|
35 | | - u32 put = nvkm_rd32(device, 0x100e30 + foff); |
---|
| 35 | + u32 get = nvkm_rd32(device, buffer->get); |
---|
| 36 | + u32 put = nvkm_rd32(device, buffer->put); |
---|
36 | 37 | if (put == get) |
---|
37 | 38 | return; |
---|
38 | 39 | |
---|
.. | .. |
---|
51 | 52 | |
---|
52 | 53 | if (++get == buffer->entries) |
---|
53 | 54 | get = 0; |
---|
54 | | - nvkm_wr32(device, 0x100e2c + foff, get); |
---|
| 55 | + nvkm_wr32(device, buffer->get, get); |
---|
55 | 56 | |
---|
56 | 57 | info.addr = ((u64)addrhi << 32) | addrlo; |
---|
57 | 58 | info.inst = ((u64)insthi << 32) | instlo; |
---|
.. | .. |
---|
70 | 71 | } |
---|
71 | 72 | |
---|
72 | 73 | static void |
---|
73 | | -gv100_fault_buffer_fini(struct nvkm_fault_buffer *buffer) |
---|
| 74 | +gv100_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable) |
---|
74 | 75 | { |
---|
75 | 76 | struct nvkm_device *device = buffer->fault->subdev.device; |
---|
76 | 77 | const u32 intr = buffer->id ? 0x08000000 : 0x20000000; |
---|
77 | | - const u32 foff = buffer->id * 0x14; |
---|
| 78 | + if (enable) |
---|
| 79 | + nvkm_mask(device, 0x100a2c, intr, intr); |
---|
| 80 | + else |
---|
| 81 | + nvkm_mask(device, 0x100a34, intr, intr); |
---|
| 82 | +} |
---|
78 | 83 | |
---|
79 | | - nvkm_mask(device, 0x100a34, intr, intr); |
---|
| 84 | +static void |
---|
| 85 | +gv100_fault_buffer_fini(struct nvkm_fault_buffer *buffer) |
---|
| 86 | +{ |
---|
| 87 | + struct nvkm_device *device = buffer->fault->subdev.device; |
---|
| 88 | + const u32 foff = buffer->id * 0x14; |
---|
80 | 89 | nvkm_mask(device, 0x100e34 + foff, 0x80000000, 0x00000000); |
---|
81 | 90 | } |
---|
82 | 91 | |
---|
.. | .. |
---|
84 | 93 | gv100_fault_buffer_init(struct nvkm_fault_buffer *buffer) |
---|
85 | 94 | { |
---|
86 | 95 | struct nvkm_device *device = buffer->fault->subdev.device; |
---|
87 | | - const u32 intr = buffer->id ? 0x08000000 : 0x20000000; |
---|
88 | 96 | const u32 foff = buffer->id * 0x14; |
---|
89 | 97 | |
---|
90 | 98 | nvkm_mask(device, 0x100e34 + foff, 0xc0000000, 0x40000000); |
---|
91 | | - nvkm_wr32(device, 0x100e28 + foff, upper_32_bits(buffer->vma->addr)); |
---|
92 | | - nvkm_wr32(device, 0x100e24 + foff, lower_32_bits(buffer->vma->addr)); |
---|
| 99 | + nvkm_wr32(device, 0x100e28 + foff, upper_32_bits(buffer->addr)); |
---|
| 100 | + nvkm_wr32(device, 0x100e24 + foff, lower_32_bits(buffer->addr)); |
---|
93 | 101 | nvkm_mask(device, 0x100e34 + foff, 0x80000000, 0x80000000); |
---|
94 | | - nvkm_mask(device, 0x100a2c, intr, intr); |
---|
95 | 102 | } |
---|
96 | 103 | |
---|
97 | | -static u32 |
---|
98 | | -gv100_fault_buffer_entries(struct nvkm_fault_buffer *buffer) |
---|
| 104 | +static void |
---|
| 105 | +gv100_fault_buffer_info(struct nvkm_fault_buffer *buffer) |
---|
99 | 106 | { |
---|
100 | 107 | struct nvkm_device *device = buffer->fault->subdev.device; |
---|
101 | 108 | const u32 foff = buffer->id * 0x14; |
---|
| 109 | + |
---|
102 | 110 | nvkm_mask(device, 0x100e34 + foff, 0x40000000, 0x40000000); |
---|
103 | | - return nvkm_rd32(device, 0x100e34 + foff) & 0x000fffff; |
---|
| 111 | + |
---|
| 112 | + buffer->entries = nvkm_rd32(device, 0x100e34 + foff) & 0x000fffff; |
---|
| 113 | + buffer->get = 0x100e2c + foff; |
---|
| 114 | + buffer->put = 0x100e30 + foff; |
---|
104 | 115 | } |
---|
105 | 116 | |
---|
106 | 117 | static int |
---|
.. | .. |
---|
157 | 168 | } |
---|
158 | 169 | } |
---|
159 | 170 | |
---|
| 171 | + if (stat & 0x08000000) { |
---|
| 172 | + if (fault->buffer[1]) { |
---|
| 173 | + nvkm_event_send(&fault->event, 1, 1, NULL, 0); |
---|
| 174 | + stat &= ~0x08000000; |
---|
| 175 | + } |
---|
| 176 | + } |
---|
| 177 | + |
---|
160 | 178 | if (stat) { |
---|
161 | 179 | nvkm_debug(subdev, "intr %08x\n", stat); |
---|
162 | 180 | } |
---|
.. | .. |
---|
166 | 184 | gv100_fault_fini(struct nvkm_fault *fault) |
---|
167 | 185 | { |
---|
168 | 186 | nvkm_notify_put(&fault->nrpfb); |
---|
| 187 | + if (fault->buffer[0]) |
---|
| 188 | + fault->func->buffer.fini(fault->buffer[0]); |
---|
169 | 189 | nvkm_mask(fault->subdev.device, 0x100a34, 0x80000000, 0x80000000); |
---|
170 | 190 | } |
---|
171 | 191 | |
---|
.. | .. |
---|
173 | 193 | gv100_fault_init(struct nvkm_fault *fault) |
---|
174 | 194 | { |
---|
175 | 195 | nvkm_mask(fault->subdev.device, 0x100a2c, 0x80000000, 0x80000000); |
---|
| 196 | + fault->func->buffer.init(fault->buffer[0]); |
---|
176 | 197 | nvkm_notify_get(&fault->nrpfb); |
---|
177 | 198 | } |
---|
178 | 199 | |
---|
179 | | -static int |
---|
| 200 | +int |
---|
180 | 201 | gv100_fault_oneinit(struct nvkm_fault *fault) |
---|
181 | 202 | { |
---|
182 | 203 | return nvkm_notify_init(&fault->buffer[0]->object, &fault->event, |
---|
183 | | - gv100_fault_ntfy_nrpfb, false, NULL, 0, 0, |
---|
| 204 | + gv100_fault_ntfy_nrpfb, true, NULL, 0, 0, |
---|
184 | 205 | &fault->nrpfb); |
---|
185 | 206 | } |
---|
186 | 207 | |
---|
.. | .. |
---|
192 | 213 | .intr = gv100_fault_intr, |
---|
193 | 214 | .buffer.nr = 2, |
---|
194 | 215 | .buffer.entry_size = 32, |
---|
195 | | - .buffer.entries = gv100_fault_buffer_entries, |
---|
| 216 | + .buffer.info = gv100_fault_buffer_info, |
---|
| 217 | + .buffer.pin = gp100_fault_buffer_pin, |
---|
196 | 218 | .buffer.init = gv100_fault_buffer_init, |
---|
197 | 219 | .buffer.fini = gv100_fault_buffer_fini, |
---|
| 220 | + .buffer.intr = gv100_fault_buffer_intr, |
---|
| 221 | + /*TODO: Figure out how to expose non-replayable fault buffer, which, |
---|
| 222 | + * for some reason, is where recoverable CE faults appear... |
---|
| 223 | + * |
---|
| 224 | + * It's a bit tricky, as both NVKM and SVM will need access to |
---|
| 225 | + * the non-replayable fault buffer. |
---|
| 226 | + */ |
---|
| 227 | + .user = { { 0, 0, VOLTA_FAULT_BUFFER_A }, 1 }, |
---|
198 | 228 | }; |
---|
199 | 229 | |
---|
200 | 230 | int |
---|