| .. | .. |
|---|
| 28 | 28 | #include <core/enum.h> |
|---|
| 29 | 29 | #include <core/gpuobj.h> |
|---|
| 30 | 30 | #include <subdev/bar.h> |
|---|
| 31 | +#include <subdev/fault.h> |
|---|
| 31 | 32 | #include <engine/sw.h> |
|---|
| 32 | 33 | |
|---|
| 33 | 34 | #include <nvif/class.h> |
|---|
| .. | .. |
|---|
| 194 | 195 | } |
|---|
| 195 | 196 | |
|---|
| 196 | 197 | static const struct nvkm_enum |
|---|
| 198 | +gf100_fifo_fault_engine[] = { |
|---|
| 199 | + { 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR }, |
|---|
| 200 | + { 0x03, "PEEPHOLE", NULL, NVKM_ENGINE_IFB }, |
|---|
| 201 | + { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, |
|---|
| 202 | + { 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM }, |
|---|
| 203 | + { 0x07, "PFIFO", NULL, NVKM_ENGINE_FIFO }, |
|---|
| 204 | + { 0x10, "PMSVLD", NULL, NVKM_ENGINE_MSVLD }, |
|---|
| 205 | + { 0x11, "PMSPPP", NULL, NVKM_ENGINE_MSPPP }, |
|---|
| 206 | + { 0x13, "PCOUNTER" }, |
|---|
| 207 | + { 0x14, "PMSPDEC", NULL, NVKM_ENGINE_MSPDEC }, |
|---|
| 208 | + { 0x15, "PCE0", NULL, NVKM_ENGINE_CE0 }, |
|---|
| 209 | + { 0x16, "PCE1", NULL, NVKM_ENGINE_CE1 }, |
|---|
| 210 | + { 0x17, "PMU" }, |
|---|
| 211 | + {} |
|---|
| 212 | +}; |
|---|
| 213 | + |
|---|
| 214 | +static const struct nvkm_enum |
|---|
| 215 | +gf100_fifo_fault_reason[] = { |
|---|
| 216 | + { 0x00, "PT_NOT_PRESENT" }, |
|---|
| 217 | + { 0x01, "PT_TOO_SHORT" }, |
|---|
| 218 | + { 0x02, "PAGE_NOT_PRESENT" }, |
|---|
| 219 | + { 0x03, "VM_LIMIT_EXCEEDED" }, |
|---|
| 220 | + { 0x04, "NO_CHANNEL" }, |
|---|
| 221 | + { 0x05, "PAGE_SYSTEM_ONLY" }, |
|---|
| 222 | + { 0x06, "PAGE_READ_ONLY" }, |
|---|
| 223 | + { 0x0a, "COMPRESSED_SYSRAM" }, |
|---|
| 224 | + { 0x0c, "INVALID_STORAGE_TYPE" }, |
|---|
| 225 | + {} |
|---|
| 226 | +}; |
|---|
| 227 | + |
|---|
| 228 | +static const struct nvkm_enum |
|---|
| 229 | +gf100_fifo_fault_hubclient[] = { |
|---|
| 230 | + { 0x01, "PCOPY0" }, |
|---|
| 231 | + { 0x02, "PCOPY1" }, |
|---|
| 232 | + { 0x04, "DISPATCH" }, |
|---|
| 233 | + { 0x05, "CTXCTL" }, |
|---|
| 234 | + { 0x06, "PFIFO" }, |
|---|
| 235 | + { 0x07, "BAR_READ" }, |
|---|
| 236 | + { 0x08, "BAR_WRITE" }, |
|---|
| 237 | + { 0x0b, "PVP" }, |
|---|
| 238 | + { 0x0c, "PMSPPP" }, |
|---|
| 239 | + { 0x0d, "PMSVLD" }, |
|---|
| 240 | + { 0x11, "PCOUNTER" }, |
|---|
| 241 | + { 0x12, "PMU" }, |
|---|
| 242 | + { 0x14, "CCACHE" }, |
|---|
| 243 | + { 0x15, "CCACHE_POST" }, |
|---|
| 244 | + {} |
|---|
| 245 | +}; |
|---|
| 246 | + |
|---|
| 247 | +static const struct nvkm_enum |
|---|
| 248 | +gf100_fifo_fault_gpcclient[] = { |
|---|
| 249 | + { 0x01, "TEX" }, |
|---|
| 250 | + { 0x0c, "ESETUP" }, |
|---|
| 251 | + { 0x0e, "CTXCTL" }, |
|---|
| 252 | + { 0x0f, "PROP" }, |
|---|
| 253 | + {} |
|---|
| 254 | +}; |
|---|
| 255 | + |
|---|
| 256 | +static void |
|---|
| 257 | +gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info) |
|---|
| 258 | +{ |
|---|
| 259 | + struct gf100_fifo *fifo = gf100_fifo(base); |
|---|
| 260 | + struct nvkm_subdev *subdev = &fifo->base.engine.subdev; |
|---|
| 261 | + struct nvkm_device *device = subdev->device; |
|---|
| 262 | + const struct nvkm_enum *er, *eu, *ec; |
|---|
| 263 | + struct nvkm_engine *engine = NULL; |
|---|
| 264 | + struct nvkm_fifo_chan *chan; |
|---|
| 265 | + unsigned long flags; |
|---|
| 266 | + char gpcid[8] = ""; |
|---|
| 267 | + |
|---|
| 268 | + er = nvkm_enum_find(gf100_fifo_fault_reason, info->reason); |
|---|
| 269 | + eu = nvkm_enum_find(gf100_fifo_fault_engine, info->engine); |
|---|
| 270 | + if (info->hub) { |
|---|
| 271 | + ec = nvkm_enum_find(gf100_fifo_fault_hubclient, info->client); |
|---|
| 272 | + } else { |
|---|
| 273 | + ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, info->client); |
|---|
| 274 | + snprintf(gpcid, sizeof(gpcid), "GPC%d/", info->gpc); |
|---|
| 275 | + } |
|---|
| 276 | + |
|---|
| 277 | + if (eu && eu->data2) { |
|---|
| 278 | + switch (eu->data2) { |
|---|
| 279 | + case NVKM_SUBDEV_BAR: |
|---|
| 280 | + nvkm_bar_bar1_reset(device); |
|---|
| 281 | + break; |
|---|
| 282 | + case NVKM_SUBDEV_INSTMEM: |
|---|
| 283 | + nvkm_bar_bar2_reset(device); |
|---|
| 284 | + break; |
|---|
| 285 | + case NVKM_ENGINE_IFB: |
|---|
| 286 | + nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); |
|---|
| 287 | + break; |
|---|
| 288 | + default: |
|---|
| 289 | + engine = nvkm_device_engine(device, eu->data2); |
|---|
| 290 | + break; |
|---|
| 291 | + } |
|---|
| 292 | + } |
|---|
| 293 | + |
|---|
| 294 | + chan = nvkm_fifo_chan_inst(&fifo->base, info->inst, &flags); |
|---|
| 295 | + |
|---|
| 296 | + nvkm_error(subdev, |
|---|
| 297 | + "%s fault at %010llx engine %02x [%s] client %02x [%s%s] " |
|---|
| 298 | + "reason %02x [%s] on channel %d [%010llx %s]\n", |
|---|
| 299 | + info->access ? "write" : "read", info->addr, |
|---|
| 300 | + info->engine, eu ? eu->name : "", |
|---|
| 301 | + info->client, gpcid, ec ? ec->name : "", |
|---|
| 302 | + info->reason, er ? er->name : "", chan ? chan->chid : -1, |
|---|
| 303 | + info->inst, chan ? chan->object.client->name : "unknown"); |
|---|
| 304 | + |
|---|
| 305 | + if (engine && chan) |
|---|
| 306 | + gf100_fifo_recover(fifo, engine, (void *)chan); |
|---|
| 307 | + nvkm_fifo_chan_put(&fifo->base, flags, &chan); |
|---|
| 308 | +} |
|---|
| 309 | + |
|---|
| 310 | +static const struct nvkm_enum |
|---|
| 197 | 311 | gf100_fifo_sched_reason[] = { |
|---|
| 198 | 312 | { 0x0a, "CTXSW_TIMEOUT" }, |
|---|
| 199 | 313 | {} |
|---|
| .. | .. |
|---|
| 255 | 369 | } |
|---|
| 256 | 370 | } |
|---|
| 257 | 371 | |
|---|
| 258 | | -static const struct nvkm_enum |
|---|
| 259 | | -gf100_fifo_fault_engine[] = { |
|---|
| 260 | | - { 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR }, |
|---|
| 261 | | - { 0x03, "PEEPHOLE", NULL, NVKM_ENGINE_IFB }, |
|---|
| 262 | | - { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR }, |
|---|
| 263 | | - { 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM }, |
|---|
| 264 | | - { 0x07, "PFIFO", NULL, NVKM_ENGINE_FIFO }, |
|---|
| 265 | | - { 0x10, "PMSVLD", NULL, NVKM_ENGINE_MSVLD }, |
|---|
| 266 | | - { 0x11, "PMSPPP", NULL, NVKM_ENGINE_MSPPP }, |
|---|
| 267 | | - { 0x13, "PCOUNTER" }, |
|---|
| 268 | | - { 0x14, "PMSPDEC", NULL, NVKM_ENGINE_MSPDEC }, |
|---|
| 269 | | - { 0x15, "PCE0", NULL, NVKM_ENGINE_CE0 }, |
|---|
| 270 | | - { 0x16, "PCE1", NULL, NVKM_ENGINE_CE1 }, |
|---|
| 271 | | - { 0x17, "PMU" }, |
|---|
| 272 | | - {} |
|---|
| 273 | | -}; |
|---|
| 274 | | - |
|---|
| 275 | | -static const struct nvkm_enum |
|---|
| 276 | | -gf100_fifo_fault_reason[] = { |
|---|
| 277 | | - { 0x00, "PT_NOT_PRESENT" }, |
|---|
| 278 | | - { 0x01, "PT_TOO_SHORT" }, |
|---|
| 279 | | - { 0x02, "PAGE_NOT_PRESENT" }, |
|---|
| 280 | | - { 0x03, "VM_LIMIT_EXCEEDED" }, |
|---|
| 281 | | - { 0x04, "NO_CHANNEL" }, |
|---|
| 282 | | - { 0x05, "PAGE_SYSTEM_ONLY" }, |
|---|
| 283 | | - { 0x06, "PAGE_READ_ONLY" }, |
|---|
| 284 | | - { 0x0a, "COMPRESSED_SYSRAM" }, |
|---|
| 285 | | - { 0x0c, "INVALID_STORAGE_TYPE" }, |
|---|
| 286 | | - {} |
|---|
| 287 | | -}; |
|---|
| 288 | | - |
|---|
| 289 | | -static const struct nvkm_enum |
|---|
| 290 | | -gf100_fifo_fault_hubclient[] = { |
|---|
| 291 | | - { 0x01, "PCOPY0" }, |
|---|
| 292 | | - { 0x02, "PCOPY1" }, |
|---|
| 293 | | - { 0x04, "DISPATCH" }, |
|---|
| 294 | | - { 0x05, "CTXCTL" }, |
|---|
| 295 | | - { 0x06, "PFIFO" }, |
|---|
| 296 | | - { 0x07, "BAR_READ" }, |
|---|
| 297 | | - { 0x08, "BAR_WRITE" }, |
|---|
| 298 | | - { 0x0b, "PVP" }, |
|---|
| 299 | | - { 0x0c, "PMSPPP" }, |
|---|
| 300 | | - { 0x0d, "PMSVLD" }, |
|---|
| 301 | | - { 0x11, "PCOUNTER" }, |
|---|
| 302 | | - { 0x12, "PMU" }, |
|---|
| 303 | | - { 0x14, "CCACHE" }, |
|---|
| 304 | | - { 0x15, "CCACHE_POST" }, |
|---|
| 305 | | - {} |
|---|
| 306 | | -}; |
|---|
| 307 | | - |
|---|
| 308 | | -static const struct nvkm_enum |
|---|
| 309 | | -gf100_fifo_fault_gpcclient[] = { |
|---|
| 310 | | - { 0x01, "TEX" }, |
|---|
| 311 | | - { 0x0c, "ESETUP" }, |
|---|
| 312 | | - { 0x0e, "CTXCTL" }, |
|---|
| 313 | | - { 0x0f, "PROP" }, |
|---|
| 314 | | - {} |
|---|
| 315 | | -}; |
|---|
| 316 | | - |
|---|
| 317 | | -static void |
|---|
| 318 | | -gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit) |
|---|
| 372 | +void |
|---|
| 373 | +gf100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit) |
|---|
| 319 | 374 | { |
|---|
| 320 | | - struct nvkm_subdev *subdev = &fifo->base.engine.subdev; |
|---|
| 321 | | - struct nvkm_device *device = subdev->device; |
|---|
| 375 | + struct nvkm_device *device = fifo->engine.subdev.device; |
|---|
| 322 | 376 | u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10)); |
|---|
| 323 | 377 | u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10)); |
|---|
| 324 | 378 | u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10)); |
|---|
| 325 | | - u32 stat = nvkm_rd32(device, 0x00280c + (unit * 0x10)); |
|---|
| 326 | | - u32 gpc = (stat & 0x1f000000) >> 24; |
|---|
| 327 | | - u32 client = (stat & 0x00001f00) >> 8; |
|---|
| 328 | | - u32 write = (stat & 0x00000080); |
|---|
| 329 | | - u32 hub = (stat & 0x00000040); |
|---|
| 330 | | - u32 reason = (stat & 0x0000000f); |
|---|
| 331 | | - const struct nvkm_enum *er, *eu, *ec; |
|---|
| 332 | | - struct nvkm_engine *engine = NULL; |
|---|
| 333 | | - struct nvkm_fifo_chan *chan; |
|---|
| 334 | | - unsigned long flags; |
|---|
| 335 | | - char gpcid[8] = ""; |
|---|
| 379 | + u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10)); |
|---|
| 380 | + struct nvkm_fault_data info; |
|---|
| 336 | 381 | |
|---|
| 337 | | - er = nvkm_enum_find(gf100_fifo_fault_reason, reason); |
|---|
| 338 | | - eu = nvkm_enum_find(gf100_fifo_fault_engine, unit); |
|---|
| 339 | | - if (hub) { |
|---|
| 340 | | - ec = nvkm_enum_find(gf100_fifo_fault_hubclient, client); |
|---|
| 341 | | - } else { |
|---|
| 342 | | - ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, client); |
|---|
| 343 | | - snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc); |
|---|
| 344 | | - } |
|---|
| 382 | + info.inst = (u64)inst << 12; |
|---|
| 383 | + info.addr = ((u64)vahi << 32) | valo; |
|---|
| 384 | + info.time = 0; |
|---|
| 385 | + info.engine = unit; |
|---|
| 386 | + info.valid = 1; |
|---|
| 387 | + info.gpc = (type & 0x1f000000) >> 24; |
|---|
| 388 | + info.client = (type & 0x00001f00) >> 8; |
|---|
| 389 | + info.access = (type & 0x00000080) >> 7; |
|---|
| 390 | + info.hub = (type & 0x00000040) >> 6; |
|---|
| 391 | + info.reason = (type & 0x0000000f); |
|---|
| 345 | 392 | |
|---|
| 346 | | - if (eu && eu->data2) { |
|---|
| 347 | | - switch (eu->data2) { |
|---|
| 348 | | - case NVKM_SUBDEV_BAR: |
|---|
| 349 | | - nvkm_mask(device, 0x001704, 0x00000000, 0x00000000); |
|---|
| 350 | | - break; |
|---|
| 351 | | - case NVKM_SUBDEV_INSTMEM: |
|---|
| 352 | | - nvkm_mask(device, 0x001714, 0x00000000, 0x00000000); |
|---|
| 353 | | - break; |
|---|
| 354 | | - case NVKM_ENGINE_IFB: |
|---|
| 355 | | - nvkm_mask(device, 0x001718, 0x00000000, 0x00000000); |
|---|
| 356 | | - break; |
|---|
| 357 | | - default: |
|---|
| 358 | | - engine = nvkm_device_engine(device, eu->data2); |
|---|
| 359 | | - break; |
|---|
| 360 | | - } |
|---|
| 361 | | - } |
|---|
| 362 | | - |
|---|
| 363 | | - chan = nvkm_fifo_chan_inst(&fifo->base, (u64)inst << 12, &flags); |
|---|
| 364 | | - |
|---|
| 365 | | - nvkm_error(subdev, |
|---|
| 366 | | - "%s fault at %010llx engine %02x [%s] client %02x [%s%s] " |
|---|
| 367 | | - "reason %02x [%s] on channel %d [%010llx %s]\n", |
|---|
| 368 | | - write ? "write" : "read", (u64)vahi << 32 | valo, |
|---|
| 369 | | - unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "", |
|---|
| 370 | | - reason, er ? er->name : "", chan ? chan->chid : -1, |
|---|
| 371 | | - (u64)inst << 12, |
|---|
| 372 | | - chan ? chan->object.client->name : "unknown"); |
|---|
| 373 | | - |
|---|
| 374 | | - if (engine && chan) |
|---|
| 375 | | - gf100_fifo_recover(fifo, engine, (void *)chan); |
|---|
| 376 | | - nvkm_fifo_chan_put(&fifo->base, flags, &chan); |
|---|
| 393 | + nvkm_fifo_fault(fifo, &info); |
|---|
| 377 | 394 | } |
|---|
| 378 | 395 | |
|---|
| 379 | 396 | static const struct nvkm_bitfield |
|---|
| .. | .. |
|---|
| 518 | 535 | u32 mask = nvkm_rd32(device, 0x00259c); |
|---|
| 519 | 536 | while (mask) { |
|---|
| 520 | 537 | u32 unit = __ffs(mask); |
|---|
| 521 | | - gf100_fifo_intr_fault(fifo, unit); |
|---|
| 538 | + gf100_fifo_intr_fault(&fifo->base, unit); |
|---|
| 522 | 539 | nvkm_wr32(device, 0x00259c, (1 << unit)); |
|---|
| 523 | 540 | mask &= ~(1 << unit); |
|---|
| 524 | 541 | } |
|---|
| .. | .. |
|---|
| 655 | 672 | .init = gf100_fifo_init, |
|---|
| 656 | 673 | .fini = gf100_fifo_fini, |
|---|
| 657 | 674 | .intr = gf100_fifo_intr, |
|---|
| 675 | + .fault = gf100_fifo_fault, |
|---|
| 658 | 676 | .uevent_init = gf100_fifo_uevent_init, |
|---|
| 659 | 677 | .uevent_fini = gf100_fifo_uevent_fini, |
|---|
| 660 | 678 | .chan = { |
|---|