linux/drivers/gpu/drm/nouveau/nouveau_irq.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2006 Ben Skeggs.
   3 *
   4 * All Rights Reserved.
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining
   7 * a copy of this software and associated documentation files (the
   8 * "Software"), to deal in the Software without restriction, including
   9 * without limitation the rights to use, copy, modify, merge, publish,
  10 * distribute, sublicense, and/or sell copies of the Software, and to
  11 * permit persons to whom the Software is furnished to do so, subject to
  12 * the following conditions:
  13 *
  14 * The above copyright notice and this permission notice (including the
  15 * next paragraph) shall be included in all copies or substantial
  16 * portions of the Software.
  17 *
  18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25 *
  26 */
  27
  28/*
  29 * Authors:
  30 *   Ben Skeggs <darktama@iinet.net.au>
  31 */
  32
  33#include "drmP.h"
  34#include "drm.h"
  35#include "nouveau_drm.h"
  36#include "nouveau_drv.h"
  37#include "nouveau_reg.h"
  38#include <linux/ratelimit.h>
  39
  40/* needed for hotplug irq */
  41#include "nouveau_connector.h"
  42#include "nv50_display.h"
  43
  44void
  45nouveau_irq_preinstall(struct drm_device *dev)
  46{
  47        struct drm_nouveau_private *dev_priv = dev->dev_private;
  48
  49        /* Master disable */
  50        nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
  51
  52        if (dev_priv->card_type == NV_50) {
  53                INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
  54                INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh);
  55                INIT_LIST_HEAD(&dev_priv->vbl_waiting);
  56        }
  57}
  58
  59int
  60nouveau_irq_postinstall(struct drm_device *dev)
  61{
  62        /* Master enable */
  63        nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
  64        return 0;
  65}
  66
  67void
  68nouveau_irq_uninstall(struct drm_device *dev)
  69{
  70        /* Master disable */
  71        nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
  72}
  73
  74static int
  75nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data)
  76{
  77        struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
  78        struct nouveau_pgraph_object_method *grm;
  79        struct nouveau_pgraph_object_class *grc;
  80
  81        grc = dev_priv->engine.graph.grclass;
  82        while (grc->id) {
  83                if (grc->id == class)
  84                        break;
  85                grc++;
  86        }
  87
  88        if (grc->id != class || !grc->methods)
  89                return -ENOENT;
  90
  91        grm = grc->methods;
  92        while (grm->id) {
  93                if (grm->id == mthd)
  94                        return grm->exec(chan, class, mthd, data);
  95                grm++;
  96        }
  97
  98        return -ENOENT;
  99}
 100
 101static bool
 102nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data)
 103{
 104        struct drm_device *dev = chan->dev;
 105        const int subc = (addr >> 13) & 0x7;
 106        const int mthd = addr & 0x1ffc;
 107
 108        if (mthd == 0x0000) {
 109                struct nouveau_gpuobj_ref *ref = NULL;
 110
 111                if (nouveau_gpuobj_ref_find(chan, data, &ref))
 112                        return false;
 113
 114                if (ref->gpuobj->engine != NVOBJ_ENGINE_SW)
 115                        return false;
 116
 117                chan->sw_subchannel[subc] = ref->gpuobj->class;
 118                nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev,
 119                        NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4));
 120                return true;
 121        }
 122
 123        /* hw object */
 124        if (nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE) & (1 << (subc*4)))
 125                return false;
 126
 127        if (nouveau_call_method(chan, chan->sw_subchannel[subc], mthd, data))
 128                return false;
 129
 130        return true;
 131}
 132
 133static void
 134nouveau_fifo_irq_handler(struct drm_device *dev)
 135{
 136        struct drm_nouveau_private *dev_priv = dev->dev_private;
 137        struct nouveau_engine *engine = &dev_priv->engine;
 138        uint32_t status, reassign;
 139        int cnt = 0;
 140
 141        reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1;
 142        while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) {
 143                struct nouveau_channel *chan = NULL;
 144                uint32_t chid, get;
 145
 146                nv_wr32(dev, NV03_PFIFO_CACHES, 0);
 147
 148                chid = engine->fifo.channel_id(dev);
 149                if (chid >= 0 && chid < engine->fifo.channels)
 150                        chan = dev_priv->fifos[chid];
 151                get  = nv_rd32(dev, NV03_PFIFO_CACHE1_GET);
 152
 153                if (status & NV_PFIFO_INTR_CACHE_ERROR) {
 154                        uint32_t mthd, data;
 155                        int ptr;
 156
 157                        /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before
 158                         * wrapping on my G80 chips, but CACHE1 isn't big
 159                         * enough for this much data.. Tests show that it
 160                         * wraps around to the start at GET=0x800.. No clue
 161                         * as to why..
 162                         */
 163                        ptr = (get & 0x7ff) >> 2;
 164
 165                        if (dev_priv->card_type < NV_40) {
 166                                mthd = nv_rd32(dev,
 167                                        NV04_PFIFO_CACHE1_METHOD(ptr));
 168                                data = nv_rd32(dev,
 169                                        NV04_PFIFO_CACHE1_DATA(ptr));
 170                        } else {
 171                                mthd = nv_rd32(dev,
 172                                        NV40_PFIFO_CACHE1_METHOD(ptr));
 173                                data = nv_rd32(dev,
 174                                        NV40_PFIFO_CACHE1_DATA(ptr));
 175                        }
 176
 177                        if (!chan || !nouveau_fifo_swmthd(chan, mthd, data)) {
 178                                NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d "
 179                                             "Mthd 0x%04x Data 0x%08x\n",
 180                                        chid, (mthd >> 13) & 7, mthd & 0x1ffc,
 181                                        data);
 182                        }
 183
 184                        nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
 185                        nv_wr32(dev, NV03_PFIFO_INTR_0,
 186                                                NV_PFIFO_INTR_CACHE_ERROR);
 187
 188                        nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
 189                                nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1);
 190                        nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
 191                        nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0,
 192                                nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1);
 193                        nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0);
 194
 195                        nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH,
 196                                nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
 197                        nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
 198
 199                        status &= ~NV_PFIFO_INTR_CACHE_ERROR;
 200                }
 201
 202                if (status & NV_PFIFO_INTR_DMA_PUSHER) {
 203                        NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d\n", chid);
 204
 205                        status &= ~NV_PFIFO_INTR_DMA_PUSHER;
 206                        nv_wr32(dev, NV03_PFIFO_INTR_0,
 207                                                NV_PFIFO_INTR_DMA_PUSHER);
 208
 209                        nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_STATE, 0x00000000);
 210                        if (nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT) != get)
 211                                nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET,
 212                                                                get + 4);
 213                }
 214
 215                if (status & NV_PFIFO_INTR_SEMAPHORE) {
 216                        uint32_t sem;
 217
 218                        status &= ~NV_PFIFO_INTR_SEMAPHORE;
 219                        nv_wr32(dev, NV03_PFIFO_INTR_0,
 220                                NV_PFIFO_INTR_SEMAPHORE);
 221
 222                        sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE);
 223                        nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
 224
 225                        nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
 226                        nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
 227                }
 228
 229                if (status) {
 230                        NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
 231                                status, chid);
 232                        nv_wr32(dev, NV03_PFIFO_INTR_0, status);
 233                        status = 0;
 234                }
 235
 236                nv_wr32(dev, NV03_PFIFO_CACHES, reassign);
 237        }
 238
 239        if (status) {
 240                NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt);
 241                nv_wr32(dev, 0x2140, 0);
 242                nv_wr32(dev, 0x140, 0);
 243        }
 244
 245        nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING);
 246}
 247
 248struct nouveau_bitfield_names {
 249        uint32_t mask;
 250        const char *name;
 251};
 252
 253static struct nouveau_bitfield_names nstatus_names[] =
 254{
 255        { NV04_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
 256        { NV04_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
 257        { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
 258        { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
 259};
 260
 261static struct nouveau_bitfield_names nstatus_names_nv10[] =
 262{
 263        { NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
 264        { NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
 265        { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
 266        { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" }
 267};
 268
 269static struct nouveau_bitfield_names nsource_names[] =
 270{
 271        { NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
 272        { NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
 273        { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
 274        { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
 275        { NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
 276        { NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
 277        { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
 278        { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
 279        { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
 280        { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
 281        { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
 282        { NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
 283        { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
 284        { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
 285        { NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
 286        { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
 287        { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
 288        { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
 289        { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
 290};
 291
 292static void
 293nouveau_print_bitfield_names_(uint32_t value,
 294                                const struct nouveau_bitfield_names *namelist,
 295                                const int namelist_len)
 296{
 297        /*
 298         * Caller must have already printed the KERN_* log level for us.
 299         * Also the caller is responsible for adding the newline.
 300         */
 301        int i;
 302        for (i = 0; i < namelist_len; ++i) {
 303                uint32_t mask = namelist[i].mask;
 304                if (value & mask) {
 305                        printk(" %s", namelist[i].name);
 306                        value &= ~mask;
 307                }
 308        }
 309        if (value)
 310                printk(" (unknown bits 0x%08x)", value);
 311}
 312#define nouveau_print_bitfield_names(val, namelist) \
 313        nouveau_print_bitfield_names_((val), (namelist), ARRAY_SIZE(namelist))
 314
 315struct nouveau_enum_names {
 316        uint32_t value;
 317        const char *name;
 318};
 319
 320static void
 321nouveau_print_enum_names_(uint32_t value,
 322                                const struct nouveau_enum_names *namelist,
 323                                const int namelist_len)
 324{
 325        /*
 326         * Caller must have already printed the KERN_* log level for us.
 327         * Also the caller is responsible for adding the newline.
 328         */
 329        int i;
 330        for (i = 0; i < namelist_len; ++i) {
 331                if (value == namelist[i].value) {
 332                        printk("%s", namelist[i].name);
 333                        return;
 334                }
 335        }
 336        printk("unknown value 0x%08x", value);
 337}
 338#define nouveau_print_enum_names(val, namelist) \
 339        nouveau_print_enum_names_((val), (namelist), ARRAY_SIZE(namelist))
 340
 341static int
 342nouveau_graph_chid_from_grctx(struct drm_device *dev)
 343{
 344        struct drm_nouveau_private *dev_priv = dev->dev_private;
 345        uint32_t inst;
 346        int i;
 347
 348        if (dev_priv->card_type < NV_40)
 349                return dev_priv->engine.fifo.channels;
 350        else
 351        if (dev_priv->card_type < NV_50) {
 352                inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 4;
 353
 354                for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
 355                        struct nouveau_channel *chan = dev_priv->fifos[i];
 356
 357                        if (!chan || !chan->ramin_grctx)
 358                                continue;
 359
 360                        if (inst == chan->ramin_grctx->instance)
 361                                break;
 362                }
 363        } else {
 364                inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 12;
 365
 366                for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
 367                        struct nouveau_channel *chan = dev_priv->fifos[i];
 368
 369                        if (!chan || !chan->ramin)
 370                                continue;
 371
 372                        if (inst == chan->ramin->instance)
 373                                break;
 374                }
 375        }
 376
 377
 378        return i;
 379}
 380
 381static int
 382nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
 383{
 384        struct drm_nouveau_private *dev_priv = dev->dev_private;
 385        struct nouveau_engine *engine = &dev_priv->engine;
 386        int channel;
 387
 388        if (dev_priv->card_type < NV_10)
 389                channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf;
 390        else
 391        if (dev_priv->card_type < NV_40)
 392                channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
 393        else
 394                channel = nouveau_graph_chid_from_grctx(dev);
 395
 396        if (channel >= engine->fifo.channels || !dev_priv->fifos[channel]) {
 397                NV_ERROR(dev, "AIII, invalid/inactive channel id %d\n", channel);
 398                return -EINVAL;
 399        }
 400
 401        *channel_ret = channel;
 402        return 0;
 403}
 404
 405struct nouveau_pgraph_trap {
 406        int channel;
 407        int class;
 408        int subc, mthd, size;
 409        uint32_t data, data2;
 410        uint32_t nsource, nstatus;
 411};
 412
 413static void
 414nouveau_graph_trap_info(struct drm_device *dev,
 415                        struct nouveau_pgraph_trap *trap)
 416{
 417        struct drm_nouveau_private *dev_priv = dev->dev_private;
 418        uint32_t address;
 419
 420        trap->nsource = trap->nstatus = 0;
 421        if (dev_priv->card_type < NV_50) {
 422                trap->nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
 423                trap->nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
 424        }
 425
 426        if (nouveau_graph_trapped_channel(dev, &trap->channel))
 427                trap->channel = -1;
 428        address = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
 429
 430        trap->mthd = address & 0x1FFC;
 431        trap->data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
 432        if (dev_priv->card_type < NV_10) {
 433                trap->subc  = (address >> 13) & 0x7;
 434        } else {
 435                trap->subc  = (address >> 16) & 0x7;
 436                trap->data2 = nv_rd32(dev, NV10_PGRAPH_TRAPPED_DATA_HIGH);
 437        }
 438
 439        if (dev_priv->card_type < NV_10)
 440                trap->class = nv_rd32(dev, 0x400180 + trap->subc*4) & 0xFF;
 441        else if (dev_priv->card_type < NV_40)
 442                trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFF;
 443        else if (dev_priv->card_type < NV_50)
 444                trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFFF;
 445        else
 446                trap->class = nv_rd32(dev, 0x400814);
 447}
 448
 449static void
 450nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id,
 451                             struct nouveau_pgraph_trap *trap)
 452{
 453        struct drm_nouveau_private *dev_priv = dev->dev_private;
 454        uint32_t nsource = trap->nsource, nstatus = trap->nstatus;
 455
 456        if (dev_priv->card_type < NV_50) {
 457                NV_INFO(dev, "%s - nSource:", id);
 458                nouveau_print_bitfield_names(nsource, nsource_names);
 459                printk(", nStatus:");
 460                if (dev_priv->card_type < NV_10)
 461                        nouveau_print_bitfield_names(nstatus, nstatus_names);
 462                else
 463                        nouveau_print_bitfield_names(nstatus, nstatus_names_nv10);
 464                printk("\n");
 465        }
 466
 467        NV_INFO(dev, "%s - Ch %d/%d Class 0x%04x Mthd 0x%04x "
 468                                        "Data 0x%08x:0x%08x\n",
 469                                        id, trap->channel, trap->subc,
 470                                        trap->class, trap->mthd,
 471                                        trap->data2, trap->data);
 472}
 473
 474static int
 475nouveau_pgraph_intr_swmthd(struct drm_device *dev,
 476                           struct nouveau_pgraph_trap *trap)
 477{
 478        struct drm_nouveau_private *dev_priv = dev->dev_private;
 479
 480        if (trap->channel < 0 ||
 481            trap->channel >= dev_priv->engine.fifo.channels ||
 482            !dev_priv->fifos[trap->channel])
 483                return -ENODEV;
 484
 485        return nouveau_call_method(dev_priv->fifos[trap->channel],
 486                                   trap->class, trap->mthd, trap->data);
 487}
 488
 489static inline void
 490nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
 491{
 492        struct nouveau_pgraph_trap trap;
 493        int unhandled = 0;
 494
 495        nouveau_graph_trap_info(dev, &trap);
 496
 497        if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
 498                if (nouveau_pgraph_intr_swmthd(dev, &trap))
 499                        unhandled = 1;
 500        } else {
 501                unhandled = 1;
 502        }
 503
 504        if (unhandled)
 505                nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap);
 506}
 507
 508static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20);
 509
 510static int nouveau_ratelimit(void)
 511{
 512        return __ratelimit(&nouveau_ratelimit_state);
 513}
 514
 515
 516static inline void
 517nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
 518{
 519        struct nouveau_pgraph_trap trap;
 520        int unhandled = 0;
 521
 522        nouveau_graph_trap_info(dev, &trap);
 523        trap.nsource = nsource;
 524
 525        if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
 526                if (nouveau_pgraph_intr_swmthd(dev, &trap))
 527                        unhandled = 1;
 528        } else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
 529                uint32_t v = nv_rd32(dev, 0x402000);
 530                nv_wr32(dev, 0x402000, v);
 531
 532                /* dump the error anyway for now: it's useful for
 533                   Gallium development */
 534                unhandled = 1;
 535        } else {
 536                unhandled = 1;
 537        }
 538
 539        if (unhandled && nouveau_ratelimit())
 540                nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap);
 541}
 542
 543static inline void
 544nouveau_pgraph_intr_context_switch(struct drm_device *dev)
 545{
 546        struct drm_nouveau_private *dev_priv = dev->dev_private;
 547        struct nouveau_engine *engine = &dev_priv->engine;
 548        uint32_t chid;
 549
 550        chid = engine->fifo.channel_id(dev);
 551        NV_DEBUG(dev, "PGRAPH context switch interrupt channel %x\n", chid);
 552
 553        switch (dev_priv->card_type) {
 554        case NV_04:
 555                nv04_graph_context_switch(dev);
 556                break;
 557        case NV_10:
 558                nv10_graph_context_switch(dev);
 559                break;
 560        default:
 561                NV_ERROR(dev, "Context switch not implemented\n");
 562                break;
 563        }
 564}
 565
 566static void
 567nouveau_pgraph_irq_handler(struct drm_device *dev)
 568{
 569        uint32_t status;
 570
 571        while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
 572                uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
 573
 574                if (status & NV_PGRAPH_INTR_NOTIFY) {
 575                        nouveau_pgraph_intr_notify(dev, nsource);
 576
 577                        status &= ~NV_PGRAPH_INTR_NOTIFY;
 578                        nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
 579                }
 580
 581                if (status & NV_PGRAPH_INTR_ERROR) {
 582                        nouveau_pgraph_intr_error(dev, nsource);
 583
 584                        status &= ~NV_PGRAPH_INTR_ERROR;
 585                        nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR);
 586                }
 587
 588                if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
 589                        nouveau_pgraph_intr_context_switch(dev);
 590
 591                        status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
 592                        nv_wr32(dev, NV03_PGRAPH_INTR,
 593                                 NV_PGRAPH_INTR_CONTEXT_SWITCH);
 594                }
 595
 596                if (status) {
 597                        NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status);
 598                        nv_wr32(dev, NV03_PGRAPH_INTR, status);
 599                }
 600
 601                if ((nv_rd32(dev, NV04_PGRAPH_FIFO) & (1 << 0)) == 0)
 602                        nv_wr32(dev, NV04_PGRAPH_FIFO, 1);
 603        }
 604
 605        nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
 606}
 607
 608static void
 609nv50_pfb_vm_trap(struct drm_device *dev, int display, const char *name)
 610{
 611        struct drm_nouveau_private *dev_priv = dev->dev_private;
 612        uint32_t trap[6];
 613        int i, ch;
 614        uint32_t idx = nv_rd32(dev, 0x100c90);
 615        if (idx & 0x80000000) {
 616                idx &= 0xffffff;
 617                if (display) {
 618                        for (i = 0; i < 6; i++) {
 619                                nv_wr32(dev, 0x100c90, idx | i << 24);
 620                                trap[i] = nv_rd32(dev, 0x100c94);
 621                        }
 622                        for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) {
 623                                struct nouveau_channel *chan = dev_priv->fifos[ch];
 624
 625                                if (!chan || !chan->ramin)
 626                                        continue;
 627
 628                                if (trap[1] == chan->ramin->instance >> 12)
 629                                        break;
 630                        }
 631                        NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x %08x channel %d\n",
 632                                        name, (trap[5]&0x100?"read":"write"),
 633                                        trap[5]&0xff, trap[4]&0xffff,
 634                                        trap[3]&0xffff, trap[0], trap[2], ch);
 635                }
 636                nv_wr32(dev, 0x100c90, idx | 0x80000000);
 637        } else if (display) {
 638                NV_INFO(dev, "%s - no VM fault?\n", name);
 639        }
 640}
 641
 642static struct nouveau_enum_names nv50_mp_exec_error_names[] =
 643{
 644        { 3, "STACK_UNDERFLOW" },
 645        { 4, "QUADON_ACTIVE" },
 646        { 8, "TIMEOUT" },
 647        { 0x10, "INVALID_OPCODE" },
 648        { 0x40, "BREAKPOINT" },
 649};
 650
 651static void
 652nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display)
 653{
 654        struct drm_nouveau_private *dev_priv = dev->dev_private;
 655        uint32_t units = nv_rd32(dev, 0x1540);
 656        uint32_t addr, mp10, status, pc, oplow, ophigh;
 657        int i;
 658        int mps = 0;
 659        for (i = 0; i < 4; i++) {
 660                if (!(units & 1 << (i+24)))
 661                        continue;
 662                if (dev_priv->chipset < 0xa0)
 663                        addr = 0x408200 + (tpid << 12) + (i << 7);
 664                else
 665                        addr = 0x408100 + (tpid << 11) + (i << 7);
 666                mp10 = nv_rd32(dev, addr + 0x10);
 667                status = nv_rd32(dev, addr + 0x14);
 668                if (!status)
 669                        continue;
 670                if (display) {
 671                        nv_rd32(dev, addr + 0x20);
 672                        pc = nv_rd32(dev, addr + 0x24);
 673                        oplow = nv_rd32(dev, addr + 0x70);
 674                        ophigh= nv_rd32(dev, addr + 0x74);
 675                        NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - "
 676                                        "TP %d MP %d: ", tpid, i);
 677                        nouveau_print_enum_names(status,
 678                                        nv50_mp_exec_error_names);
 679                        printk(" at %06x warp %d, opcode %08x %08x\n",
 680                                        pc&0xffffff, pc >> 24,
 681                                        oplow, ophigh);
 682                }
 683                nv_wr32(dev, addr + 0x10, mp10);
 684                nv_wr32(dev, addr + 0x14, 0);
 685                mps++;
 686        }
 687        if (!mps && display)
 688                NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: "
 689                                "No MPs claiming errors?\n", tpid);
 690}
 691
 692static void
 693nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
 694                uint32_t ustatus_new, int display, const char *name)
 695{
 696        struct drm_nouveau_private *dev_priv = dev->dev_private;
 697        int tps = 0;
 698        uint32_t units = nv_rd32(dev, 0x1540);
 699        int i, r;
 700        uint32_t ustatus_addr, ustatus;
 701        for (i = 0; i < 16; i++) {
 702                if (!(units & (1 << i)))
 703                        continue;
 704                if (dev_priv->chipset < 0xa0)
 705                        ustatus_addr = ustatus_old + (i << 12);
 706                else
 707                        ustatus_addr = ustatus_new + (i << 11);
 708                ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff;
 709                if (!ustatus)
 710                        continue;
 711                tps++;
 712                switch (type) {
 713                case 6: /* texture error... unknown for now */
 714                        nv50_pfb_vm_trap(dev, display, name);
 715                        if (display) {
 716                                NV_ERROR(dev, "magic set %d:\n", i);
 717                                for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
 718                                        NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
 719                                                nv_rd32(dev, r));
 720                        }
 721                        break;
 722                case 7: /* MP error */
 723                        if (ustatus & 0x00010000) {
 724                                nv50_pgraph_mp_trap(dev, i, display);
 725                                ustatus &= ~0x00010000;
 726                        }
 727                        break;
 728                case 8: /* TPDMA error */
 729                        {
 730                        uint32_t e0c = nv_rd32(dev, ustatus_addr + 4);
 731                        uint32_t e10 = nv_rd32(dev, ustatus_addr + 8);
 732                        uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc);
 733                        uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10);
 734                        uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14);
 735                        uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18);
 736                        uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c);
 737                        nv50_pfb_vm_trap(dev, display, name);
 738                        /* 2d engine destination */
 739                        if (ustatus & 0x00000010) {
 740                                if (display) {
 741                                        NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n",
 742                                                        i, e14, e10);
 743                                        NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
 744                                                        i, e0c, e18, e1c, e20, e24);
 745                                }
 746                                ustatus &= ~0x00000010;
 747                        }
 748                        /* Render target */
 749                        if (ustatus & 0x00000040) {
 750                                if (display) {
 751                                        NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n",
 752                                                        i, e14, e10);
 753                                        NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
 754                                                        i, e0c, e18, e1c, e20, e24);
 755                                }
 756                                ustatus &= ~0x00000040;
 757                        }
 758                        /* CUDA memory: l[], g[] or stack. */
 759                        if (ustatus & 0x00000080) {
 760                                if (display) {
 761                                        if (e18 & 0x80000000) {
 762                                                /* g[] read fault? */
 763                                                NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n",
 764                                                                i, e14, e10 | ((e18 >> 24) & 0x1f));
 765                                                e18 &= ~0x1f000000;
 766                                        } else if (e18 & 0xc) {
 767                                                /* g[] write fault? */
 768                                                NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n",
 769                                                                i, e14, e10 | ((e18 >> 7) & 0x1f));
 770                                                e18 &= ~0x00000f80;
 771                                        } else {
 772                                                NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n",
 773                                                                i, e14, e10);
 774                                        }
 775                                        NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
 776                                                        i, e0c, e18, e1c, e20, e24);
 777                                }
 778                                ustatus &= ~0x00000080;
 779                        }
 780                        }
 781                        break;
 782                }
 783                if (ustatus) {
 784                        if (display)
 785                                NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus);
 786                }
 787                nv_wr32(dev, ustatus_addr, 0xc0000000);
 788        }
 789
 790        if (!tps && display)
 791                NV_INFO(dev, "%s - No TPs claiming errors?\n", name);
 792}
 793
 794static void
 795nv50_pgraph_trap_handler(struct drm_device *dev)
 796{
 797        struct nouveau_pgraph_trap trap;
 798        uint32_t status = nv_rd32(dev, 0x400108);
 799        uint32_t ustatus;
 800        int display = nouveau_ratelimit();
 801
 802
 803        if (!status && display) {
 804                nouveau_graph_trap_info(dev, &trap);
 805                nouveau_graph_dump_trap_info(dev, "PGRAPH_TRAP", &trap);
 806                NV_INFO(dev, "PGRAPH_TRAP - no units reporting traps?\n");
 807        }
 808
 809        /* DISPATCH: Relays commands to other units and handles NOTIFY,
 810         * COND, QUERY. If you get a trap from it, the command is still stuck
 811         * in DISPATCH and you need to do something about it. */
 812        if (status & 0x001) {
 813                ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff;
 814                if (!ustatus && display) {
 815                        NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n");
 816                }
 817
 818                /* Known to be triggered by screwed up NOTIFY and COND... */
 819                if (ustatus & 0x00000001) {
 820                        nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT");
 821                        nv_wr32(dev, 0x400500, 0);
 822                        if (nv_rd32(dev, 0x400808) & 0x80000000) {
 823                                if (display) {
 824                                        if (nouveau_graph_trapped_channel(dev, &trap.channel))
 825                                                trap.channel = -1;
 826                                        trap.class = nv_rd32(dev, 0x400814);
 827                                        trap.mthd = nv_rd32(dev, 0x400808) & 0x1ffc;
 828                                        trap.subc = (nv_rd32(dev, 0x400808) >> 16) & 0x7;
 829                                        trap.data = nv_rd32(dev, 0x40080c);
 830                                        trap.data2 = nv_rd32(dev, 0x400810);
 831                                        nouveau_graph_dump_trap_info(dev,
 832                                                        "PGRAPH_TRAP_DISPATCH_FAULT", &trap);
 833                                        NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400808: %08x\n", nv_rd32(dev, 0x400808));
 834                                        NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400848: %08x\n", nv_rd32(dev, 0x400848));
 835                                }
 836                                nv_wr32(dev, 0x400808, 0);
 837                        } else if (display) {
 838                                NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - No stuck command?\n");
 839                        }
 840                        nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3);
 841                        nv_wr32(dev, 0x400848, 0);
 842                        ustatus &= ~0x00000001;
 843                }
 844                if (ustatus & 0x00000002) {
 845                        nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY");
 846                        nv_wr32(dev, 0x400500, 0);
 847                        if (nv_rd32(dev, 0x40084c) & 0x80000000) {
 848                                if (display) {
 849                                        if (nouveau_graph_trapped_channel(dev, &trap.channel))
 850                                                trap.channel = -1;
 851                                        trap.class = nv_rd32(dev, 0x400814);
 852                                        trap.mthd = nv_rd32(dev, 0x40084c) & 0x1ffc;
 853                                        trap.subc = (nv_rd32(dev, 0x40084c) >> 16) & 0x7;
 854                                        trap.data = nv_rd32(dev, 0x40085c);
 855                                        trap.data2 = 0;
 856                                        nouveau_graph_dump_trap_info(dev,
 857                                                        "PGRAPH_TRAP_DISPATCH_QUERY", &trap);
 858                                        NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - 40084c: %08x\n", nv_rd32(dev, 0x40084c));
 859                                }
 860                                nv_wr32(dev, 0x40084c, 0);
 861                        } else if (display) {
 862                                NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - No stuck command?\n");
 863                        }
 864                        ustatus &= ~0x00000002;
 865                }
 866                if (ustatus && display)
 867                        NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - Unhandled ustatus 0x%08x\n", ustatus);
 868                nv_wr32(dev, 0x400804, 0xc0000000);
 869                nv_wr32(dev, 0x400108, 0x001);
 870                status &= ~0x001;
 871        }
 872
 873        /* TRAPs other than dispatch use the "normal" trap regs. */
 874        if (status && display) {
 875                nouveau_graph_trap_info(dev, &trap);
 876                nouveau_graph_dump_trap_info(dev,
 877                                "PGRAPH_TRAP", &trap);
 878        }
 879
 880        /* M2MF: Memory to memory copy engine. */
 881        if (status & 0x002) {
 882                ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff;
 883                if (!ustatus && display) {
 884                        NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n");
 885                }
 886                if (ustatus & 0x00000001) {
 887                        nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY");
 888                        ustatus &= ~0x00000001;
 889                }
 890                if (ustatus & 0x00000002) {
 891                        nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN");
 892                        ustatus &= ~0x00000002;
 893                }
 894                if (ustatus & 0x00000004) {
 895                        nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT");
 896                        ustatus &= ~0x00000004;
 897                }
 898                NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n",
 899                                nv_rd32(dev, 0x406804),
 900                                nv_rd32(dev, 0x406808),
 901                                nv_rd32(dev, 0x40680c),
 902                                nv_rd32(dev, 0x406810));
 903                if (ustatus && display)
 904                        NV_INFO(dev, "PGRAPH_TRAP_M2MF - Unhandled ustatus 0x%08x\n", ustatus);
 905                /* No sane way found yet -- just reset the bugger. */
 906                nv_wr32(dev, 0x400040, 2);
 907                nv_wr32(dev, 0x400040, 0);
 908                nv_wr32(dev, 0x406800, 0xc0000000);
 909                nv_wr32(dev, 0x400108, 0x002);
 910                status &= ~0x002;
 911        }
 912
 913        /* VFETCH: Fetches data from vertex buffers. */
 914        if (status & 0x004) {
 915                ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff;
 916                if (!ustatus && display) {
 917                        NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n");
 918                }
 919                if (ustatus & 0x00000001) {
 920                        nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT");
 921                        NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n",
 922                                        nv_rd32(dev, 0x400c00),
 923                                        nv_rd32(dev, 0x400c08),
 924                                        nv_rd32(dev, 0x400c0c),
 925                                        nv_rd32(dev, 0x400c10));
 926                        ustatus &= ~0x00000001;
 927                }
 928                if (ustatus && display)
 929                        NV_INFO(dev, "PGRAPH_TRAP_VFETCH - Unhandled ustatus 0x%08x\n", ustatus);
 930                nv_wr32(dev, 0x400c04, 0xc0000000);
 931                nv_wr32(dev, 0x400108, 0x004);
 932                status &= ~0x004;
 933        }
 934
 935        /* STRMOUT: DirectX streamout / OpenGL transform feedback. */
 936        if (status & 0x008) {
 937                ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff;
 938                if (!ustatus && display) {
 939                        NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n");
 940                }
 941                if (ustatus & 0x00000001) {
 942                        nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT");
 943                        NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n",
 944                                        nv_rd32(dev, 0x401804),
 945                                        nv_rd32(dev, 0x401808),
 946                                        nv_rd32(dev, 0x40180c),
 947                                        nv_rd32(dev, 0x401810));
 948                        ustatus &= ~0x00000001;
 949                }
 950                if (ustatus && display)
 951                        NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - Unhandled ustatus 0x%08x\n", ustatus);
 952                /* No sane way found yet -- just reset the bugger. */
 953                nv_wr32(dev, 0x400040, 0x80);
 954                nv_wr32(dev, 0x400040, 0);
 955                nv_wr32(dev, 0x401800, 0xc0000000);
 956                nv_wr32(dev, 0x400108, 0x008);
 957                status &= ~0x008;
 958        }
 959
 960        /* CCACHE: Handles code and c[] caches and fills them. */
 961        if (status & 0x010) {
 962                ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff;
 963                if (!ustatus && display) {
 964                        NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n");
 965                }
 966                if (ustatus & 0x00000001) {
 967                        nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT");
 968                        NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n",
 969                                        nv_rd32(dev, 0x405800),
 970                                        nv_rd32(dev, 0x405804),
 971                                        nv_rd32(dev, 0x405808),
 972                                        nv_rd32(dev, 0x40580c),
 973                                        nv_rd32(dev, 0x405810),
 974                                        nv_rd32(dev, 0x405814),
 975                                        nv_rd32(dev, 0x40581c));
 976                        ustatus &= ~0x00000001;
 977                }
 978                if (ustatus && display)
 979                        NV_INFO(dev, "PGRAPH_TRAP_CCACHE - Unhandled ustatus 0x%08x\n", ustatus);
 980                nv_wr32(dev, 0x405018, 0xc0000000);
 981                nv_wr32(dev, 0x400108, 0x010);
 982                status &= ~0x010;
 983        }
 984
 985        /* Unknown, not seen yet... 0x402000 is the only trap status reg
 986         * remaining, so try to handle it anyway. Perhaps related to that
 987         * unknown DMA slot on tesla? */
 988        if (status & 0x20) {
 989                nv50_pfb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04");
 990                ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff;
 991                if (display)
 992                        NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus);
 993                nv_wr32(dev, 0x402000, 0xc0000000);
 994                /* no status modifiction on purpose */
 995        }
 996
 997        /* TEXTURE: CUDA texturing units */
 998        if (status & 0x040) {
 999                nv50_pgraph_tp_trap (dev, 6, 0x408900, 0x408600, display,
1000                                "PGRAPH_TRAP_TEXTURE");
1001                nv_wr32(dev, 0x400108, 0x040);
1002                status &= ~0x040;
1003        }
1004
1005        /* MP: CUDA execution engines. */
1006        if (status & 0x080) {
1007                nv50_pgraph_tp_trap (dev, 7, 0x408314, 0x40831c, display,
1008                                "PGRAPH_TRAP_MP");
1009                nv_wr32(dev, 0x400108, 0x080);
1010                status &= ~0x080;
1011        }
1012
1013        /* TPDMA:  Handles TP-initiated uncached memory accesses:
1014         * l[], g[], stack, 2d surfaces, render targets. */
1015        if (status & 0x100) {
1016                nv50_pgraph_tp_trap (dev, 8, 0x408e08, 0x408708, display,
1017                                "PGRAPH_TRAP_TPDMA");
1018                nv_wr32(dev, 0x400108, 0x100);
1019                status &= ~0x100;
1020        }
1021
1022        if (status) {
1023                if (display)
1024                        NV_INFO(dev, "PGRAPH_TRAP - Unknown trap 0x%08x\n",
1025                                status);
1026                nv_wr32(dev, 0x400108, status);
1027        }
1028}
1029
1030/* There must be a *lot* of these. Will take some time to gather them up. */
1031static struct nouveau_enum_names nv50_data_error_names[] =
1032{
1033        { 4,    "INVALID_VALUE" },
1034        { 5,    "INVALID_ENUM" },
1035        { 8,    "INVALID_OBJECT" },
1036        { 0xc,  "INVALID_BITFIELD" },
1037        { 0x28, "MP_NO_REG_SPACE" },
1038        { 0x2b, "MP_BLOCK_SIZE_MISMATCH" },
1039};
1040
1041static void
1042nv50_pgraph_irq_handler(struct drm_device *dev)
1043{
1044        struct nouveau_pgraph_trap trap;
1045        int unhandled = 0;
1046        uint32_t status;
1047
1048        while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
1049                /* NOTIFY: You've set a NOTIFY an a command and it's done. */
1050                if (status & 0x00000001) {
1051                        nouveau_graph_trap_info(dev, &trap);
1052                        if (nouveau_ratelimit())
1053                                nouveau_graph_dump_trap_info(dev,
1054                                                "PGRAPH_NOTIFY", &trap);
1055                        status &= ~0x00000001;
1056                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001);
1057                }
1058
1059                /* COMPUTE_QUERY: Purpose and exact cause unknown, happens
1060                 * when you write 0x200 to 0x50c0 method 0x31c. */
1061                if (status & 0x00000002) {
1062                        nouveau_graph_trap_info(dev, &trap);
1063                        if (nouveau_ratelimit())
1064                                nouveau_graph_dump_trap_info(dev,
1065                                                "PGRAPH_COMPUTE_QUERY", &trap);
1066                        status &= ~0x00000002;
1067                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000002);
1068                }
1069
1070                /* Unknown, never seen: 0x4 */
1071
1072                /* ILLEGAL_MTHD: You used a wrong method for this class. */
1073                if (status & 0x00000010) {
1074                        nouveau_graph_trap_info(dev, &trap);
1075                        if (nouveau_pgraph_intr_swmthd(dev, &trap))
1076                                unhandled = 1;
1077                        if (unhandled && nouveau_ratelimit())
1078                                nouveau_graph_dump_trap_info(dev,
1079                                                "PGRAPH_ILLEGAL_MTHD", &trap);
1080                        status &= ~0x00000010;
1081                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010);
1082                }
1083
1084                /* ILLEGAL_CLASS: You used a wrong class. */
1085                if (status & 0x00000020) {
1086                        nouveau_graph_trap_info(dev, &trap);
1087                        if (nouveau_ratelimit())
1088                                nouveau_graph_dump_trap_info(dev,
1089                                                "PGRAPH_ILLEGAL_CLASS", &trap);
1090                        status &= ~0x00000020;
1091                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000020);
1092                }
1093
1094                /* DOUBLE_NOTIFY: You tried to set a NOTIFY on another NOTIFY. */
1095                if (status & 0x00000040) {
1096                        nouveau_graph_trap_info(dev, &trap);
1097                        if (nouveau_ratelimit())
1098                                nouveau_graph_dump_trap_info(dev,
1099                                                "PGRAPH_DOUBLE_NOTIFY", &trap);
1100                        status &= ~0x00000040;
1101                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000040);
1102                }
1103
1104                /* CONTEXT_SWITCH: PGRAPH needs us to load a new context */
1105                if (status & 0x00001000) {
1106                        nv_wr32(dev, 0x400500, 0x00000000);
1107                        nv_wr32(dev, NV03_PGRAPH_INTR,
1108                                NV_PGRAPH_INTR_CONTEXT_SWITCH);
1109                        nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev,
1110                                NV40_PGRAPH_INTR_EN) &
1111                                ~NV_PGRAPH_INTR_CONTEXT_SWITCH);
1112                        nv_wr32(dev, 0x400500, 0x00010001);
1113
1114                        nv50_graph_context_switch(dev);
1115
1116                        status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1117                }
1118
1119                /* BUFFER_NOTIFY: Your m2mf transfer finished */
1120                if (status & 0x00010000) {
1121                        nouveau_graph_trap_info(dev, &trap);
1122                        if (nouveau_ratelimit())
1123                                nouveau_graph_dump_trap_info(dev,
1124                                                "PGRAPH_BUFFER_NOTIFY", &trap);
1125                        status &= ~0x00010000;
1126                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00010000);
1127                }
1128
1129                /* DATA_ERROR: Invalid value for this method, or invalid
1130                 * state in current PGRAPH context for this operation */
1131                if (status & 0x00100000) {
1132                        nouveau_graph_trap_info(dev, &trap);
1133                        if (nouveau_ratelimit()) {
1134                                nouveau_graph_dump_trap_info(dev,
1135                                                "PGRAPH_DATA_ERROR", &trap);
1136                                NV_INFO (dev, "PGRAPH_DATA_ERROR - ");
1137                                nouveau_print_enum_names(nv_rd32(dev, 0x400110),
1138                                                nv50_data_error_names);
1139                                printk("\n");
1140                        }
1141                        status &= ~0x00100000;
1142                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000);
1143                }
1144
1145                /* TRAP: Something bad happened in the middle of command
1146                 * execution.  Has a billion types, subtypes, and even
1147                 * subsubtypes. */
1148                if (status & 0x00200000) {
1149                        nv50_pgraph_trap_handler(dev);
1150                        status &= ~0x00200000;
1151                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000);
1152                }
1153
1154                /* Unknown, never seen: 0x00400000 */
1155
1156                /* SINGLE_STEP: Happens on every method if you turned on
1157                 * single stepping in 40008c */
1158                if (status & 0x01000000) {
1159                        nouveau_graph_trap_info(dev, &trap);
1160                        if (nouveau_ratelimit())
1161                                nouveau_graph_dump_trap_info(dev,
1162                                                "PGRAPH_SINGLE_STEP", &trap);
1163                        status &= ~0x01000000;
1164                        nv_wr32(dev, NV03_PGRAPH_INTR, 0x01000000);
1165                }
1166
1167                /* 0x02000000 happens when you pause a ctxprog...
1168                 * but the only way this can happen that I know is by
1169                 * poking the relevant MMIO register, and we don't
1170                 * do that. */
1171
1172                if (status) {
1173                        NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n",
1174                                status);
1175                        nv_wr32(dev, NV03_PGRAPH_INTR, status);
1176                }
1177
1178                {
1179                        const int isb = (1 << 16) | (1 << 0);
1180
1181                        if ((nv_rd32(dev, 0x400500) & isb) != isb)
1182                                nv_wr32(dev, 0x400500,
1183                                        nv_rd32(dev, 0x400500) | isb);
1184                }
1185        }
1186
1187        nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
1188        if (nv_rd32(dev, 0x400824) & (1 << 31))
1189                nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
1190}
1191
1192static void
1193nouveau_crtc_irq_handler(struct drm_device *dev, int crtc)
1194{
1195        if (crtc & 1)
1196                nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
1197
1198        if (crtc & 2)
1199                nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
1200}
1201
1202irqreturn_t
1203nouveau_irq_handler(DRM_IRQ_ARGS)
1204{
1205        struct drm_device *dev = (struct drm_device *)arg;
1206        struct drm_nouveau_private *dev_priv = dev->dev_private;
1207        uint32_t status;
1208        unsigned long flags;
1209
1210        status = nv_rd32(dev, NV03_PMC_INTR_0);
1211        if (!status)
1212                return IRQ_NONE;
1213
1214        spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
1215
1216        if (status & NV_PMC_INTR_0_PFIFO_PENDING) {
1217                nouveau_fifo_irq_handler(dev);
1218                status &= ~NV_PMC_INTR_0_PFIFO_PENDING;
1219        }
1220
1221        if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
1222                if (dev_priv->card_type >= NV_50)
1223                        nv50_pgraph_irq_handler(dev);
1224                else
1225                        nouveau_pgraph_irq_handler(dev);
1226
1227                status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
1228        }
1229
1230        if (status & NV_PMC_INTR_0_CRTCn_PENDING) {
1231                nouveau_crtc_irq_handler(dev, (status>>24)&3);
1232                status &= ~NV_PMC_INTR_0_CRTCn_PENDING;
1233        }
1234
1235        if (status & (NV_PMC_INTR_0_NV50_DISPLAY_PENDING |
1236                      NV_PMC_INTR_0_NV50_I2C_PENDING)) {
1237                nv50_display_irq_handler(dev);
1238                status &= ~(NV_PMC_INTR_0_NV50_DISPLAY_PENDING |
1239                            NV_PMC_INTR_0_NV50_I2C_PENDING);
1240        }
1241
1242        if (status)
1243                NV_ERROR(dev, "Unhandled PMC INTR status bits 0x%08x\n", status);
1244
1245        spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
1246
1247        return IRQ_HANDLED;
1248}
1249
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.