linux/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Red Hat Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: Ben Skeggs
  23 */
  24#include "nv50.h"
  25
  26#include <core/client.h>
  27#include <core/gpuobj.h>
  28#include <engine/fifo.h>
  29
  30#include <nvif/class.h>
  31
  32u64
  33nv50_gr_units(struct nvkm_gr *gr)
  34{
  35        return nvkm_rd32(gr->engine.subdev.device, 0x1540);
  36}
  37
  38/*******************************************************************************
  39 * Graphics object classes
  40 ******************************************************************************/
  41
  42static int
  43nv50_gr_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
  44                    int align, struct nvkm_gpuobj **pgpuobj)
  45{
  46        int ret = nvkm_gpuobj_new(object->engine->subdev.device, 16,
  47                                  align, false, parent, pgpuobj);
  48        if (ret == 0) {
  49                nvkm_kmap(*pgpuobj);
  50                nvkm_wo32(*pgpuobj, 0x00, object->oclass);
  51                nvkm_wo32(*pgpuobj, 0x04, 0x00000000);
  52                nvkm_wo32(*pgpuobj, 0x08, 0x00000000);
  53                nvkm_wo32(*pgpuobj, 0x0c, 0x00000000);
  54                nvkm_done(*pgpuobj);
  55        }
  56        return ret;
  57}
  58
  59const struct nvkm_object_func
  60nv50_gr_object = {
  61        .bind = nv50_gr_object_bind,
  62};
  63
  64/*******************************************************************************
  65 * PGRAPH context
  66 ******************************************************************************/
  67
  68static int
  69nv50_gr_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
  70                  int align, struct nvkm_gpuobj **pgpuobj)
  71{
  72        struct nv50_gr *gr = nv50_gr_chan(object)->gr;
  73        int ret = nvkm_gpuobj_new(gr->base.engine.subdev.device, gr->size,
  74                                  align, true, parent, pgpuobj);
  75        if (ret == 0) {
  76                nvkm_kmap(*pgpuobj);
  77                nv50_grctx_fill(gr->base.engine.subdev.device, *pgpuobj);
  78                nvkm_done(*pgpuobj);
  79        }
  80        return ret;
  81}
  82
  83static const struct nvkm_object_func
  84nv50_gr_chan = {
  85        .bind = nv50_gr_chan_bind,
  86};
  87
  88int
  89nv50_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
  90                 const struct nvkm_oclass *oclass, struct nvkm_object **pobject)
  91{
  92        struct nv50_gr *gr = nv50_gr(base);
  93        struct nv50_gr_chan *chan;
  94
  95        if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
  96                return -ENOMEM;
  97        nvkm_object_ctor(&nv50_gr_chan, oclass, &chan->object);
  98        chan->gr = gr;
  99        *pobject = &chan->object;
 100        return 0;
 101}
 102
 103/*******************************************************************************
 104 * PGRAPH engine/subdev functions
 105 ******************************************************************************/
 106
 107static const struct nvkm_bitfield nv50_mp_exec_errors[] = {
 108        { 0x01, "STACK_UNDERFLOW" },
 109        { 0x02, "STACK_MISMATCH" },
 110        { 0x04, "QUADON_ACTIVE" },
 111        { 0x08, "TIMEOUT" },
 112        { 0x10, "INVALID_OPCODE" },
 113        { 0x20, "PM_OVERFLOW" },
 114        { 0x40, "BREAKPOINT" },
 115        {}
 116};
 117
 118static const struct nvkm_bitfield nv50_mpc_traps[] = {
 119        { 0x0000001, "LOCAL_LIMIT_READ" },
 120        { 0x0000010, "LOCAL_LIMIT_WRITE" },
 121        { 0x0000040, "STACK_LIMIT" },
 122        { 0x0000100, "GLOBAL_LIMIT_READ" },
 123        { 0x0001000, "GLOBAL_LIMIT_WRITE" },
 124        { 0x0010000, "MP0" },
 125        { 0x0020000, "MP1" },
 126        { 0x0040000, "GLOBAL_LIMIT_RED" },
 127        { 0x0400000, "GLOBAL_LIMIT_ATOM" },
 128        { 0x4000000, "MP2" },
 129        {}
 130};
 131
 132static const struct nvkm_bitfield nv50_tex_traps[] = {
 133        { 0x00000001, "" }, /* any bit set? */
 134        { 0x00000002, "FAULT" },
 135        { 0x00000004, "STORAGE_TYPE_MISMATCH" },
 136        { 0x00000008, "LINEAR_MISMATCH" },
 137        { 0x00000020, "WRONG_MEMTYPE" },
 138        {}
 139};
 140
 141static const struct nvkm_bitfield nv50_gr_trap_m2mf[] = {
 142        { 0x00000001, "NOTIFY" },
 143        { 0x00000002, "IN" },
 144        { 0x00000004, "OUT" },
 145        {}
 146};
 147
 148static const struct nvkm_bitfield nv50_gr_trap_vfetch[] = {
 149        { 0x00000001, "FAULT" },
 150        {}
 151};
 152
 153static const struct nvkm_bitfield nv50_gr_trap_strmout[] = {
 154        { 0x00000001, "FAULT" },
 155        {}
 156};
 157
 158static const struct nvkm_bitfield nv50_gr_trap_ccache[] = {
 159        { 0x00000001, "FAULT" },
 160        {}
 161};
 162
 163/* There must be a *lot* of these. Will take some time to gather them up. */
 164const struct nvkm_enum nv50_data_error_names[] = {
 165        { 0x00000003, "INVALID_OPERATION", NULL },
 166        { 0x00000004, "INVALID_VALUE", NULL },
 167        { 0x00000005, "INVALID_ENUM", NULL },
 168        { 0x00000008, "INVALID_OBJECT", NULL },
 169        { 0x00000009, "READ_ONLY_OBJECT", NULL },
 170        { 0x0000000a, "SUPERVISOR_OBJECT", NULL },
 171        { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL },
 172        { 0x0000000c, "INVALID_BITFIELD", NULL },
 173        { 0x0000000d, "BEGIN_END_ACTIVE", NULL },
 174        { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL },
 175        { 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL },
 176        { 0x00000010, "RT_DOUBLE_BIND", NULL },
 177        { 0x00000011, "RT_TYPES_MISMATCH", NULL },
 178        { 0x00000012, "RT_LINEAR_WITH_ZETA", NULL },
 179        { 0x00000015, "FP_TOO_FEW_REGS", NULL },
 180        { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL },
 181        { 0x00000017, "RT_LINEAR_WITH_MSAA", NULL },
 182        { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL },
 183        { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL },
 184        { 0x0000001a, "RT_INVALID_ALIGNMENT", NULL },
 185        { 0x0000001b, "SAMPLER_OVER_LIMIT", NULL },
 186        { 0x0000001c, "TEXTURE_OVER_LIMIT", NULL },
 187        { 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL },
 188        { 0x0000001f, "RT_BPP128_WITH_MS8", NULL },
 189        { 0x00000021, "Z_OUT_OF_BOUNDS", NULL },
 190        { 0x00000023, "XY_OUT_OF_BOUNDS", NULL },
 191        { 0x00000024, "VP_ZERO_INPUTS", NULL },
 192        { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL },
 193        { 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL },
 194        { 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL },
 195        { 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL },
 196        { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL },
 197        { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL },
 198        { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL },
 199        { 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL },
 200        { 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL },
 201        { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL },
 202        { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL },
 203        { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL },
 204        { 0x00000046, "LAYER_ID_NEEDS_GP", NULL },
 205        { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL },
 206        { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL },
 207        {}
 208};
 209
 210static const struct nvkm_bitfield nv50_gr_intr_name[] = {
 211        { 0x00000001, "NOTIFY" },
 212        { 0x00000002, "COMPUTE_QUERY" },
 213        { 0x00000010, "ILLEGAL_MTHD" },
 214        { 0x00000020, "ILLEGAL_CLASS" },
 215        { 0x00000040, "DOUBLE_NOTIFY" },
 216        { 0x00001000, "CONTEXT_SWITCH" },
 217        { 0x00010000, "BUFFER_NOTIFY" },
 218        { 0x00100000, "DATA_ERROR" },
 219        { 0x00200000, "TRAP" },
 220        { 0x01000000, "SINGLE_STEP" },
 221        {}
 222};
 223
 224static const struct nvkm_bitfield nv50_gr_trap_prop[] = {
 225        { 0x00000004, "SURF_WIDTH_OVERRUN" },
 226        { 0x00000008, "SURF_HEIGHT_OVERRUN" },
 227        { 0x00000010, "DST2D_FAULT" },
 228        { 0x00000020, "ZETA_FAULT" },
 229        { 0x00000040, "RT_FAULT" },
 230        { 0x00000080, "CUDA_FAULT" },
 231        { 0x00000100, "DST2D_STORAGE_TYPE_MISMATCH" },
 232        { 0x00000200, "ZETA_STORAGE_TYPE_MISMATCH" },
 233        { 0x00000400, "RT_STORAGE_TYPE_MISMATCH" },
 234        { 0x00000800, "DST2D_LINEAR_MISMATCH" },
 235        { 0x00001000, "RT_LINEAR_MISMATCH" },
 236        {}
 237};
 238
 239static void
 240nv50_gr_prop_trap(struct nv50_gr *gr, u32 ustatus_addr, u32 ustatus, u32 tp)
 241{
 242        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
 243        struct nvkm_device *device = subdev->device;
 244        u32 e0c = nvkm_rd32(device, ustatus_addr + 0x04);
 245        u32 e10 = nvkm_rd32(device, ustatus_addr + 0x08);
 246        u32 e14 = nvkm_rd32(device, ustatus_addr + 0x0c);
 247        u32 e18 = nvkm_rd32(device, ustatus_addr + 0x10);
 248        u32 e1c = nvkm_rd32(device, ustatus_addr + 0x14);
 249        u32 e20 = nvkm_rd32(device, ustatus_addr + 0x18);
 250        u32 e24 = nvkm_rd32(device, ustatus_addr + 0x1c);
 251        char msg[128];
 252
 253        /* CUDA memory: l[], g[] or stack. */
 254        if (ustatus & 0x00000080) {
 255                if (e18 & 0x80000000) {
 256                        /* g[] read fault? */
 257                        nvkm_error(subdev, "TRAP_PROP - TP %d - CUDA_FAULT - Global read fault at address %02x%08x\n",
 258                                         tp, e14, e10 | ((e18 >> 24) & 0x1f));
 259                        e18 &= ~0x1f000000;
 260                } else if (e18 & 0xc) {
 261                        /* g[] write fault? */
 262                        nvkm_error(subdev, "TRAP_PROP - TP %d - CUDA_FAULT - Global write fault at address %02x%08x\n",
 263                                 tp, e14, e10 | ((e18 >> 7) & 0x1f));
 264                        e18 &= ~0x00000f80;
 265                } else {
 266                        nvkm_error(subdev, "TRAP_PROP - TP %d - Unknown CUDA fault at address %02x%08x\n",
 267                                 tp, e14, e10);
 268                }
 269                ustatus &= ~0x00000080;
 270        }
 271        if (ustatus) {
 272                nvkm_snprintbf(msg, sizeof(msg), nv50_gr_trap_prop, ustatus);
 273                nvkm_error(subdev, "TRAP_PROP - TP %d - %08x [%s] - "
 274                                   "Address %02x%08x\n",
 275                           tp, ustatus, msg, e14, e10);
 276        }
 277        nvkm_error(subdev, "TRAP_PROP - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
 278                 tp, e0c, e18, e1c, e20, e24);
 279}
 280
 281static void
 282nv50_gr_mp_trap(struct nv50_gr *gr, int tpid, int display)
 283{
 284        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
 285        struct nvkm_device *device = subdev->device;
 286        u32 units = nvkm_rd32(device, 0x1540);
 287        u32 addr, mp10, status, pc, oplow, ophigh;
 288        char msg[128];
 289        int i;
 290        int mps = 0;
 291        for (i = 0; i < 4; i++) {
 292                if (!(units & 1 << (i+24)))
 293                        continue;
 294                if (device->chipset < 0xa0)
 295                        addr = 0x408200 + (tpid << 12) + (i << 7);
 296                else
 297                        addr = 0x408100 + (tpid << 11) + (i << 7);
 298                mp10 = nvkm_rd32(device, addr + 0x10);
 299                status = nvkm_rd32(device, addr + 0x14);
 300                if (!status)
 301                        continue;
 302                if (display) {
 303                        nvkm_rd32(device, addr + 0x20);
 304                        pc = nvkm_rd32(device, addr + 0x24);
 305                        oplow = nvkm_rd32(device, addr + 0x70);
 306                        ophigh = nvkm_rd32(device, addr + 0x74);
 307                        nvkm_snprintbf(msg, sizeof(msg),
 308                                       nv50_mp_exec_errors, status);
 309                        nvkm_error(subdev, "TRAP_MP_EXEC - TP %d MP %d: "
 310                                           "%08x [%s] at %06x warp %d, "
 311                                           "opcode %08x %08x\n",
 312                                   tpid, i, status, msg, pc & 0xffffff,
 313                                   pc >> 24, oplow, ophigh);
 314                }
 315                nvkm_wr32(device, addr + 0x10, mp10);
 316                nvkm_wr32(device, addr + 0x14, 0);
 317                mps++;
 318        }
 319        if (!mps && display)
 320                nvkm_error(subdev, "TRAP_MP_EXEC - TP %d: "
 321                                "No MPs claiming errors?\n", tpid);
 322}
 323
 324static void
 325nv50_gr_tp_trap(struct nv50_gr *gr, int type, u32 ustatus_old,
 326                  u32 ustatus_new, int display, const char *name)
 327{
 328        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
 329        struct nvkm_device *device = subdev->device;
 330        u32 units = nvkm_rd32(device, 0x1540);
 331        int tps = 0;
 332        int i, r;
 333        char msg[128];
 334        u32 ustatus_addr, ustatus;
 335        for (i = 0; i < 16; i++) {
 336                if (!(units & (1 << i)))
 337                        continue;
 338                if (device->chipset < 0xa0)
 339                        ustatus_addr = ustatus_old + (i << 12);
 340                else
 341                        ustatus_addr = ustatus_new + (i << 11);
 342                ustatus = nvkm_rd32(device, ustatus_addr) & 0x7fffffff;
 343                if (!ustatus)
 344                        continue;
 345                tps++;
 346                switch (type) {
 347                case 6: /* texture error... unknown for now */
 348                        if (display) {
 349                                nvkm_error(subdev, "magic set %d:\n", i);
 350                                for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
 351                                        nvkm_error(subdev, "\t%08x: %08x\n", r,
 352                                                   nvkm_rd32(device, r));
 353                                if (ustatus) {
 354                                        nvkm_snprintbf(msg, sizeof(msg),
 355                                                       nv50_tex_traps, ustatus);
 356                                        nvkm_error(subdev,
 357                                                   "%s - TP%d: %08x [%s]\n",
 358                                                   name, i, ustatus, msg);
 359                                        ustatus = 0;
 360                                }
 361                        }
 362                        break;
 363                case 7: /* MP error */
 364                        if (ustatus & 0x04030000) {
 365                                nv50_gr_mp_trap(gr, i, display);
 366                                ustatus &= ~0x04030000;
 367                        }
 368                        if (ustatus && display) {
 369                                nvkm_snprintbf(msg, sizeof(msg),
 370                                               nv50_mpc_traps, ustatus);
 371                                nvkm_error(subdev, "%s - TP%d: %08x [%s]\n",
 372                                           name, i, ustatus, msg);
 373                                ustatus = 0;
 374                        }
 375                        break;
 376                case 8: /* PROP error */
 377                        if (display)
 378                                nv50_gr_prop_trap(
 379                                                gr, ustatus_addr, ustatus, i);
 380                        ustatus = 0;
 381                        break;
 382                }
 383                if (ustatus) {
 384                        if (display)
 385                                nvkm_error(subdev, "%s - TP%d: Unhandled ustatus %08x\n", name, i, ustatus);
 386                }
 387                nvkm_wr32(device, ustatus_addr, 0xc0000000);
 388        }
 389
 390        if (!tps && display)
 391                nvkm_warn(subdev, "%s - No TPs claiming errors?\n", name);
 392}
 393
 394static int
 395nv50_gr_trap_handler(struct nv50_gr *gr, u32 display,
 396                     int chid, u64 inst, const char *name)
 397{
 398        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
 399        struct nvkm_device *device = subdev->device;
 400        u32 status = nvkm_rd32(device, 0x400108);
 401        u32 ustatus;
 402        char msg[128];
 403
 404        if (!status && display) {
 405                nvkm_error(subdev, "TRAP: no units reporting traps?\n");
 406                return 1;
 407        }
 408
 409        /* DISPATCH: Relays commands to other units and handles NOTIFY,
 410         * COND, QUERY. If you get a trap from it, the command is still stuck
 411         * in DISPATCH and you need to do something about it. */
 412        if (status & 0x001) {
 413                ustatus = nvkm_rd32(device, 0x400804) & 0x7fffffff;
 414                if (!ustatus && display) {
 415                        nvkm_error(subdev, "TRAP_DISPATCH - no ustatus?\n");
 416                }
 417
 418                nvkm_wr32(device, 0x400500, 0x00000000);
 419
 420                /* Known to be triggered by screwed up NOTIFY and COND... */
 421                if (ustatus & 0x00000001) {
 422                        u32 addr = nvkm_rd32(device, 0x400808);
 423                        u32 subc = (addr & 0x00070000) >> 16;
 424                        u32 mthd = (addr & 0x00001ffc);
 425                        u32 datal = nvkm_rd32(device, 0x40080c);
 426                        u32 datah = nvkm_rd32(device, 0x400810);
 427                        u32 class = nvkm_rd32(device, 0x400814);
 428                        u32 r848 = nvkm_rd32(device, 0x400848);
 429
 430                        nvkm_error(subdev, "TRAP DISPATCH_FAULT\n");
 431                        if (display && (addr & 0x80000000)) {
 432                                nvkm_error(subdev,
 433                                           "ch %d [%010llx %s] subc %d "
 434                                           "class %04x mthd %04x data %08x%08x "
 435                                           "400808 %08x 400848 %08x\n",
 436                                           chid, inst, name, subc, class, mthd,
 437                                           datah, datal, addr, r848);
 438                        } else
 439                        if (display) {
 440                                nvkm_error(subdev, "no stuck command?\n");
 441                        }
 442
 443                        nvkm_wr32(device, 0x400808, 0);
 444                        nvkm_wr32(device, 0x4008e8, nvkm_rd32(device, 0x4008e8) & 3);
 445                        nvkm_wr32(device, 0x400848, 0);
 446                        ustatus &= ~0x00000001;
 447                }
 448
 449                if (ustatus & 0x00000002) {
 450                        u32 addr = nvkm_rd32(device, 0x40084c);
 451                        u32 subc = (addr & 0x00070000) >> 16;
 452                        u32 mthd = (addr & 0x00001ffc);
 453                        u32 data = nvkm_rd32(device, 0x40085c);
 454                        u32 class = nvkm_rd32(device, 0x400814);
 455
 456                        nvkm_error(subdev, "TRAP DISPATCH_QUERY\n");
 457                        if (display && (addr & 0x80000000)) {
 458                                nvkm_error(subdev,
 459                                           "ch %d [%010llx %s] subc %d "
 460                                           "class %04x mthd %04x data %08x "
 461                                           "40084c %08x\n", chid, inst, name,
 462                                           subc, class, mthd, data, addr);
 463                        } else
 464                        if (display) {
 465                                nvkm_error(subdev, "no stuck command?\n");
 466                        }
 467
 468                        nvkm_wr32(device, 0x40084c, 0);
 469                        ustatus &= ~0x00000002;
 470                }
 471
 472                if (ustatus && display) {
 473                        nvkm_error(subdev, "TRAP_DISPATCH "
 474                                           "(unknown %08x)\n", ustatus);
 475                }
 476
 477                nvkm_wr32(device, 0x400804, 0xc0000000);
 478                nvkm_wr32(device, 0x400108, 0x001);
 479                status &= ~0x001;
 480                if (!status)
 481                        return 0;
 482        }
 483
 484        /* M2MF: Memory to memory copy engine. */
 485        if (status & 0x002) {
 486                u32 ustatus = nvkm_rd32(device, 0x406800) & 0x7fffffff;
 487                if (display) {
 488                        nvkm_snprintbf(msg, sizeof(msg),
 489                                       nv50_gr_trap_m2mf, ustatus);
 490                        nvkm_error(subdev, "TRAP_M2MF %08x [%s]\n",
 491                                   ustatus, msg);
 492                        nvkm_error(subdev, "TRAP_M2MF %08x %08x %08x %08x\n",
 493                                   nvkm_rd32(device, 0x406804),
 494                                   nvkm_rd32(device, 0x406808),
 495                                   nvkm_rd32(device, 0x40680c),
 496                                   nvkm_rd32(device, 0x406810));
 497                }
 498
 499                /* No sane way found yet -- just reset the bugger. */
 500                nvkm_wr32(device, 0x400040, 2);
 501                nvkm_wr32(device, 0x400040, 0);
 502                nvkm_wr32(device, 0x406800, 0xc0000000);
 503                nvkm_wr32(device, 0x400108, 0x002);
 504                status &= ~0x002;
 505        }
 506
 507        /* VFETCH: Fetches data from vertex buffers. */
 508        if (status & 0x004) {
 509                u32 ustatus = nvkm_rd32(device, 0x400c04) & 0x7fffffff;
 510                if (display) {
 511                        nvkm_snprintbf(msg, sizeof(msg),
 512                                       nv50_gr_trap_vfetch, ustatus);
 513                        nvkm_error(subdev, "TRAP_VFETCH %08x [%s]\n",
 514                                   ustatus, msg);
 515                        nvkm_error(subdev, "TRAP_VFETCH %08x %08x %08x %08x\n",
 516                                   nvkm_rd32(device, 0x400c00),
 517                                   nvkm_rd32(device, 0x400c08),
 518                                   nvkm_rd32(device, 0x400c0c),
 519                                   nvkm_rd32(device, 0x400c10));
 520                }
 521
 522                nvkm_wr32(device, 0x400c04, 0xc0000000);
 523                nvkm_wr32(device, 0x400108, 0x004);
 524                status &= ~0x004;
 525        }
 526
 527        /* STRMOUT: DirectX streamout / OpenGL transform feedback. */
 528        if (status & 0x008) {
 529                ustatus = nvkm_rd32(device, 0x401800) & 0x7fffffff;
 530                if (display) {
 531                        nvkm_snprintbf(msg, sizeof(msg),
 532                                       nv50_gr_trap_strmout, ustatus);
 533                        nvkm_error(subdev, "TRAP_STRMOUT %08x [%s]\n",
 534                                   ustatus, msg);
 535                        nvkm_error(subdev, "TRAP_STRMOUT %08x %08x %08x %08x\n",
 536                                   nvkm_rd32(device, 0x401804),
 537                                   nvkm_rd32(device, 0x401808),
 538                                   nvkm_rd32(device, 0x40180c),
 539                                   nvkm_rd32(device, 0x401810));
 540                }
 541
 542                /* No sane way found yet -- just reset the bugger. */
 543                nvkm_wr32(device, 0x400040, 0x80);
 544                nvkm_wr32(device, 0x400040, 0);
 545                nvkm_wr32(device, 0x401800, 0xc0000000);
 546                nvkm_wr32(device, 0x400108, 0x008);
 547                status &= ~0x008;
 548        }
 549
 550        /* CCACHE: Handles code and c[] caches and fills them. */
 551        if (status & 0x010) {
 552                ustatus = nvkm_rd32(device, 0x405018) & 0x7fffffff;
 553                if (display) {
 554                        nvkm_snprintbf(msg, sizeof(msg),
 555                                       nv50_gr_trap_ccache, ustatus);
 556                        nvkm_error(subdev, "TRAP_CCACHE %08x [%s]\n",
 557                                   ustatus, msg);
 558                        nvkm_error(subdev, "TRAP_CCACHE %08x %08x %08x %08x "
 559                                           "%08x %08x %08x\n",
 560                                   nvkm_rd32(device, 0x405000),
 561                                   nvkm_rd32(device, 0x405004),
 562                                   nvkm_rd32(device, 0x405008),
 563                                   nvkm_rd32(device, 0x40500c),
 564                                   nvkm_rd32(device, 0x405010),
 565                                   nvkm_rd32(device, 0x405014),
 566                                   nvkm_rd32(device, 0x40501c));
 567                }
 568
 569                nvkm_wr32(device, 0x405018, 0xc0000000);
 570                nvkm_wr32(device, 0x400108, 0x010);
 571                status &= ~0x010;
 572        }
 573
 574        /* Unknown, not seen yet... 0x402000 is the only trap status reg
 575         * remaining, so try to handle it anyway. Perhaps related to that
 576         * unknown DMA slot on tesla? */
 577        if (status & 0x20) {
 578                ustatus = nvkm_rd32(device, 0x402000) & 0x7fffffff;
 579                if (display)
 580                        nvkm_error(subdev, "TRAP_UNKC04 %08x\n", ustatus);
 581                nvkm_wr32(device, 0x402000, 0xc0000000);
 582                /* no status modifiction on purpose */
 583        }
 584
 585        /* TEXTURE: CUDA texturing units */
 586        if (status & 0x040) {
 587                nv50_gr_tp_trap(gr, 6, 0x408900, 0x408600, display,
 588                                    "TRAP_TEXTURE");
 589                nvkm_wr32(device, 0x400108, 0x040);
 590                status &= ~0x040;
 591        }
 592
 593        /* MP: CUDA execution engines. */
 594        if (status & 0x080) {
 595                nv50_gr_tp_trap(gr, 7, 0x408314, 0x40831c, display,
 596                                    "TRAP_MP");
 597                nvkm_wr32(device, 0x400108, 0x080);
 598                status &= ~0x080;
 599        }
 600
 601        /* PROP:  Handles TP-initiated uncached memory accesses:
 602         * l[], g[], stack, 2d surfaces, render targets. */
 603        if (status & 0x100) {
 604                nv50_gr_tp_trap(gr, 8, 0x408e08, 0x408708, display,
 605                                    "TRAP_PROP");
 606                nvkm_wr32(device, 0x400108, 0x100);
 607                status &= ~0x100;
 608        }
 609
 610        if (status) {
 611                if (display)
 612                        nvkm_error(subdev, "TRAP: unknown %08x\n", status);
 613                nvkm_wr32(device, 0x400108, status);
 614        }
 615
 616        return 1;
 617}
 618
 619void
 620nv50_gr_intr(struct nvkm_gr *base)
 621{
 622        struct nv50_gr *gr = nv50_gr(base);
 623        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
 624        struct nvkm_device *device = subdev->device;
 625        struct nvkm_fifo_chan *chan;
 626        u32 stat = nvkm_rd32(device, 0x400100);
 627        u32 inst = nvkm_rd32(device, 0x40032c) & 0x0fffffff;
 628        u32 addr = nvkm_rd32(device, 0x400704);
 629        u32 subc = (addr & 0x00070000) >> 16;
 630        u32 mthd = (addr & 0x00001ffc);
 631        u32 data = nvkm_rd32(device, 0x400708);
 632        u32 class = nvkm_rd32(device, 0x400814);
 633        u32 show = stat, show_bitfield = stat;
 634        const struct nvkm_enum *en;
 635        unsigned long flags;
 636        const char *name = "unknown";
 637        char msg[128];
 638        int chid = -1;
 639
 640        chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags);
 641        if (chan)  {
 642                name = chan->object.client->name;
 643                chid = chan->chid;
 644        }
 645
 646        if (show & 0x00100000) {
 647                u32 ecode = nvkm_rd32(device, 0x400110);
 648                en = nvkm_enum_find(nv50_data_error_names, ecode);
 649                nvkm_error(subdev, "DATA_ERROR %08x [%s]\n",
 650                           ecode, en ? en->name : "");
 651                show_bitfield &= ~0x00100000;
 652        }
 653
 654        if (stat & 0x00200000) {
 655                if (!nv50_gr_trap_handler(gr, show, chid, (u64)inst << 12, name))
 656                        show &= ~0x00200000;
 657                show_bitfield &= ~0x00200000;
 658        }
 659
 660        nvkm_wr32(device, 0x400100, stat);
 661        nvkm_wr32(device, 0x400500, 0x00010001);
 662
 663        if (show) {
 664                show &= show_bitfield;
 665                nvkm_snprintbf(msg, sizeof(msg), nv50_gr_intr_name, show);
 666                nvkm_error(subdev, "%08x [%s] ch %d [%010llx %s] subc %d "
 667                                   "class %04x mthd %04x data %08x\n",
 668                           stat, msg, chid, (u64)inst << 12, name,
 669                           subc, class, mthd, data);
 670        }
 671
 672        if (nvkm_rd32(device, 0x400824) & (1 << 31))
 673                nvkm_wr32(device, 0x400824, nvkm_rd32(device, 0x400824) & ~(1 << 31));
 674
 675        nvkm_fifo_chan_put(device->fifo, flags, &chan);
 676}
 677
 678int
 679nv50_gr_init(struct nvkm_gr *base)
 680{
 681        struct nv50_gr *gr = nv50_gr(base);
 682        struct nvkm_device *device = gr->base.engine.subdev.device;
 683        int ret, units, i;
 684
 685        /* NV_PGRAPH_DEBUG_3_HW_CTX_SWITCH_ENABLED */
 686        nvkm_wr32(device, 0x40008c, 0x00000004);
 687
 688        /* reset/enable traps and interrupts */
 689        nvkm_wr32(device, 0x400804, 0xc0000000);
 690        nvkm_wr32(device, 0x406800, 0xc0000000);
 691        nvkm_wr32(device, 0x400c04, 0xc0000000);
 692        nvkm_wr32(device, 0x401800, 0xc0000000);
 693        nvkm_wr32(device, 0x405018, 0xc0000000);
 694        nvkm_wr32(device, 0x402000, 0xc0000000);
 695
 696        units = nvkm_rd32(device, 0x001540);
 697        for (i = 0; i < 16; i++) {
 698                if (!(units & (1 << i)))
 699                        continue;
 700
 701                if (device->chipset < 0xa0) {
 702                        nvkm_wr32(device, 0x408900 + (i << 12), 0xc0000000);
 703                        nvkm_wr32(device, 0x408e08 + (i << 12), 0xc0000000);
 704                        nvkm_wr32(device, 0x408314 + (i << 12), 0xc0000000);
 705                } else {
 706                        nvkm_wr32(device, 0x408600 + (i << 11), 0xc0000000);
 707                        nvkm_wr32(device, 0x408708 + (i << 11), 0xc0000000);
 708                        nvkm_wr32(device, 0x40831c + (i << 11), 0xc0000000);
 709                }
 710        }
 711
 712        nvkm_wr32(device, 0x400108, 0xffffffff);
 713        nvkm_wr32(device, 0x400138, 0xffffffff);
 714        nvkm_wr32(device, 0x400100, 0xffffffff);
 715        nvkm_wr32(device, 0x40013c, 0xffffffff);
 716        nvkm_wr32(device, 0x400500, 0x00010001);
 717
 718        /* upload context program, initialise ctxctl defaults */
 719        ret = nv50_grctx_init(device, &gr->size);
 720        if (ret)
 721                return ret;
 722
 723        nvkm_wr32(device, 0x400824, 0x00000000);
 724        nvkm_wr32(device, 0x400828, 0x00000000);
 725        nvkm_wr32(device, 0x40082c, 0x00000000);
 726        nvkm_wr32(device, 0x400830, 0x00000000);
 727        nvkm_wr32(device, 0x40032c, 0x00000000);
 728        nvkm_wr32(device, 0x400330, 0x00000000);
 729
 730        /* some unknown zcull magic */
 731        switch (device->chipset & 0xf0) {
 732        case 0x50:
 733        case 0x80:
 734        case 0x90:
 735                nvkm_wr32(device, 0x402ca8, 0x00000800);
 736                break;
 737        case 0xa0:
 738        default:
 739                if (device->chipset == 0xa0 ||
 740                    device->chipset == 0xaa ||
 741                    device->chipset == 0xac) {
 742                        nvkm_wr32(device, 0x402ca8, 0x00000802);
 743                } else {
 744                        nvkm_wr32(device, 0x402cc0, 0x00000000);
 745                        nvkm_wr32(device, 0x402ca8, 0x00000002);
 746                }
 747
 748                break;
 749        }
 750
 751        /* zero out zcull regions */
 752        for (i = 0; i < 8; i++) {
 753                nvkm_wr32(device, 0x402c20 + (i * 0x10), 0x00000000);
 754                nvkm_wr32(device, 0x402c24 + (i * 0x10), 0x00000000);
 755                nvkm_wr32(device, 0x402c28 + (i * 0x10), 0x00000000);
 756                nvkm_wr32(device, 0x402c2c + (i * 0x10), 0x00000000);
 757        }
 758
 759        return 0;
 760}
 761
 762int
 763nv50_gr_new_(const struct nvkm_gr_func *func, struct nvkm_device *device,
 764             enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr)
 765{
 766        struct nv50_gr *gr;
 767
 768        if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL)))
 769                return -ENOMEM;
 770        spin_lock_init(&gr->lock);
 771        *pgr = &gr->base;
 772
 773        return nvkm_gr_ctor(func, device, type, inst, true, &gr->base);
 774}
 775
 776static const struct nvkm_gr_func
 777nv50_gr = {
 778        .init = nv50_gr_init,
 779        .intr = nv50_gr_intr,
 780        .chan_new = nv50_gr_chan_new,
 781        .units = nv50_gr_units,
 782        .sclass = {
 783                { -1, -1, NV_NULL_CLASS, &nv50_gr_object },
 784                { -1, -1, NV50_TWOD, &nv50_gr_object },
 785                { -1, -1, NV50_MEMORY_TO_MEMORY_FORMAT, &nv50_gr_object },
 786                { -1, -1, NV50_TESLA, &nv50_gr_object },
 787                { -1, -1, NV50_COMPUTE, &nv50_gr_object },
 788                {}
 789        }
 790};
 791
 792int
 793nv50_gr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr)
 794{
 795        return nv50_gr_new_(&nv50_gr, device, type, inst, pgr);
 796}
 797