Merge branch 'gemini_fix' of git://git.berlios.de/gemini-board into devel-stable
[sfrench/cifs-2.6.git] / drivers / gpu / drm / nouveau / nouveau_irq.c
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
44 void
45 nouveau_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
59 int
60 nouveau_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
67 void
68 nouveau_irq_uninstall(struct drm_device *dev)
69 {
70         /* Master disable */
71         nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
72 }
73
74 static int
75 nouveau_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
101 static bool
102 nouveau_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
133 static void
134 nouveau_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
248 struct nouveau_bitfield_names {
249         uint32_t mask;
250         const char *name;
251 };
252
253 static 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
261 static 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
269 static 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
292 static void
293 nouveau_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
315 struct nouveau_enum_names {
316         uint32_t value;
317         const char *name;
318 };
319
320 static void
321 nouveau_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
341 static int
342 nouveau_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
381 static int
382 nouveau_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
405 struct 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
413 static void
414 nouveau_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
449 static void
450 nouveau_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
474 static int
475 nouveau_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
489 static inline void
490 nouveau_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
508 static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20);
509
510 static int nouveau_ratelimit(void)
511 {
512         return __ratelimit(&nouveau_ratelimit_state);
513 }
514
515
516 static inline void
517 nouveau_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
543 static inline void
544 nouveau_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
566 static void
567 nouveau_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
608 static void
609 nv50_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
642 static 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
651 static void
652 nv50_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
692 static void
693 nv50_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
794 static void
795 nv50_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. */
1031 static 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
1041 static void
1042 nv50_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
1192 static void
1193 nouveau_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
1202 irqreturn_t
1203 nouveau_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, fbdev_flags = 0;
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 (dev_priv->fbdev_info) {
1217                 fbdev_flags = dev_priv->fbdev_info->flags;
1218                 dev_priv->fbdev_info->flags |= FBINFO_HWACCEL_DISABLED;
1219         }
1220
1221         if (status & NV_PMC_INTR_0_PFIFO_PENDING) {
1222                 nouveau_fifo_irq_handler(dev);
1223                 status &= ~NV_PMC_INTR_0_PFIFO_PENDING;
1224         }
1225
1226         if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
1227                 if (dev_priv->card_type >= NV_50)
1228                         nv50_pgraph_irq_handler(dev);
1229                 else
1230                         nouveau_pgraph_irq_handler(dev);
1231
1232                 status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
1233         }
1234
1235         if (status & NV_PMC_INTR_0_CRTCn_PENDING) {
1236                 nouveau_crtc_irq_handler(dev, (status>>24)&3);
1237                 status &= ~NV_PMC_INTR_0_CRTCn_PENDING;
1238         }
1239
1240         if (status & (NV_PMC_INTR_0_NV50_DISPLAY_PENDING |
1241                       NV_PMC_INTR_0_NV50_I2C_PENDING)) {
1242                 nv50_display_irq_handler(dev);
1243                 status &= ~(NV_PMC_INTR_0_NV50_DISPLAY_PENDING |
1244                             NV_PMC_INTR_0_NV50_I2C_PENDING);
1245         }
1246
1247         if (status)
1248                 NV_ERROR(dev, "Unhandled PMC INTR status bits 0x%08x\n", status);
1249
1250         if (dev_priv->fbdev_info)
1251                 dev_priv->fbdev_info->flags = fbdev_flags;
1252
1253         spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
1254
1255         return IRQ_HANDLED;
1256 }