]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/gpu/drm/nouveau/nouveau_irq.c
drm/nouveau: move PFIFO ISR into nv04_fifo.c
[mv-sheeva.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 "nouveau_ramht.h"
39 #include "nouveau_util.h"
40
41 void
42 nouveau_irq_preinstall(struct drm_device *dev)
43 {
44         struct drm_nouveau_private *dev_priv = dev->dev_private;
45
46         /* Master disable */
47         nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
48
49         INIT_LIST_HEAD(&dev_priv->vbl_waiting);
50 }
51
52 int
53 nouveau_irq_postinstall(struct drm_device *dev)
54 {
55         struct drm_nouveau_private *dev_priv = dev->dev_private;
56
57         /* Master enable */
58         nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE);
59         if (dev_priv->msi_enabled)
60                 nv_wr08(dev, 0x00088068, 0xff);
61
62         return 0;
63 }
64
65 void
66 nouveau_irq_uninstall(struct drm_device *dev)
67 {
68         /* Master disable */
69         nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
70 }
71
72 static struct nouveau_bitfield nstatus_names[] =
73 {
74         { NV04_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
75         { NV04_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
76         { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
77         { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" },
78         {}
79 };
80
81 static struct nouveau_bitfield nstatus_names_nv10[] =
82 {
83         { NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
84         { NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
85         { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
86         { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" },
87         {}
88 };
89
90 static struct nouveau_bitfield nsource_names[] =
91 {
92         { NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
93         { NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
94         { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
95         { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
96         { NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
97         { NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
98         { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
99         { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
100         { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
101         { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
102         { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
103         { NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
104         { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
105         { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
106         { NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
107         { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
108         { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
109         { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
110         { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
111         {}
112 };
113
114 static int
115 nouveau_graph_chid_from_grctx(struct drm_device *dev)
116 {
117         struct drm_nouveau_private *dev_priv = dev->dev_private;
118         struct nouveau_channel *chan;
119         unsigned long flags;
120         uint32_t inst;
121         int i;
122
123         if (dev_priv->card_type < NV_40)
124                 return dev_priv->engine.fifo.channels;
125         else
126         if (dev_priv->card_type < NV_50) {
127                 inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 4;
128
129                 spin_lock_irqsave(&dev_priv->channels.lock, flags);
130                 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
131                         chan = dev_priv->channels.ptr[i];
132                         if (!chan || !chan->ramin_grctx)
133                                 continue;
134
135                         if (inst == chan->ramin_grctx->pinst)
136                                 break;
137                 }
138                 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
139         } else {
140                 inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 12;
141
142                 spin_lock_irqsave(&dev_priv->channels.lock, flags);
143                 for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
144                         chan = dev_priv->channels.ptr[i];
145                         if (!chan || !chan->ramin)
146                                 continue;
147
148                         if (inst == chan->ramin->vinst)
149                                 break;
150                 }
151                 spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
152         }
153
154
155         return i;
156 }
157
158 static int
159 nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret)
160 {
161         struct drm_nouveau_private *dev_priv = dev->dev_private;
162         struct nouveau_engine *engine = &dev_priv->engine;
163         int channel;
164
165         if (dev_priv->card_type < NV_10)
166                 channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf;
167         else
168         if (dev_priv->card_type < NV_40)
169                 channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
170         else
171                 channel = nouveau_graph_chid_from_grctx(dev);
172
173         if (channel >= engine->fifo.channels ||
174             !dev_priv->channels.ptr[channel]) {
175                 NV_ERROR(dev, "AIII, invalid/inactive channel id %d\n", channel);
176                 return -EINVAL;
177         }
178
179         *channel_ret = channel;
180         return 0;
181 }
182
183 struct nouveau_pgraph_trap {
184         int channel;
185         int class;
186         int subc, mthd, size;
187         uint32_t data, data2;
188         uint32_t nsource, nstatus;
189 };
190
191 static void
192 nouveau_graph_trap_info(struct drm_device *dev,
193                         struct nouveau_pgraph_trap *trap)
194 {
195         struct drm_nouveau_private *dev_priv = dev->dev_private;
196         uint32_t address;
197
198         trap->nsource = trap->nstatus = 0;
199         if (dev_priv->card_type < NV_50) {
200                 trap->nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
201                 trap->nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
202         }
203
204         if (nouveau_graph_trapped_channel(dev, &trap->channel))
205                 trap->channel = -1;
206         address = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
207
208         trap->mthd = address & 0x1FFC;
209         trap->data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
210         if (dev_priv->card_type < NV_10) {
211                 trap->subc  = (address >> 13) & 0x7;
212         } else {
213                 trap->subc  = (address >> 16) & 0x7;
214                 trap->data2 = nv_rd32(dev, NV10_PGRAPH_TRAPPED_DATA_HIGH);
215         }
216
217         if (dev_priv->card_type < NV_10)
218                 trap->class = nv_rd32(dev, 0x400180 + trap->subc*4) & 0xFF;
219         else if (dev_priv->card_type < NV_40)
220                 trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFF;
221         else if (dev_priv->card_type < NV_50)
222                 trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFFF;
223         else
224                 trap->class = nv_rd32(dev, 0x400814);
225 }
226
227 static void
228 nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id,
229                              struct nouveau_pgraph_trap *trap)
230 {
231         struct drm_nouveau_private *dev_priv = dev->dev_private;
232         uint32_t nsource = trap->nsource, nstatus = trap->nstatus;
233
234         if (dev_priv->card_type < NV_50) {
235                 NV_INFO(dev, "%s - nSource:", id);
236                 nouveau_bitfield_print(nsource_names, nsource);
237                 printk(", nStatus:");
238                 if (dev_priv->card_type < NV_10)
239                         nouveau_bitfield_print(nstatus_names, nstatus);
240                 else
241                         nouveau_bitfield_print(nstatus_names_nv10, nstatus);
242                 printk("\n");
243         }
244
245         NV_INFO(dev, "%s - Ch %d/%d Class 0x%04x Mthd 0x%04x "
246                                         "Data 0x%08x:0x%08x\n",
247                                         id, trap->channel, trap->subc,
248                                         trap->class, trap->mthd,
249                                         trap->data2, trap->data);
250 }
251
252 static int
253 nouveau_pgraph_intr_swmthd(struct drm_device *dev,
254                            struct nouveau_pgraph_trap *trap)
255 {
256         struct drm_nouveau_private *dev_priv = dev->dev_private;
257         struct nouveau_channel *chan;
258         unsigned long flags;
259         int ret = -EINVAL;
260
261         spin_lock_irqsave(&dev_priv->channels.lock, flags);
262         if (trap->channel > 0 &&
263             trap->channel < dev_priv->engine.fifo.channels &&
264             dev_priv->channels.ptr[trap->channel]) {
265                 chan = dev_priv->channels.ptr[trap->channel];
266                 ret = nouveau_gpuobj_mthd_call(chan, trap->class, trap->mthd, trap->data);
267         }
268         spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
269
270         return ret;
271 }
272
273 static inline void
274 nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource)
275 {
276         struct nouveau_pgraph_trap trap;
277         int unhandled = 0;
278
279         nouveau_graph_trap_info(dev, &trap);
280
281         if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
282                 if (nouveau_pgraph_intr_swmthd(dev, &trap))
283                         unhandled = 1;
284         } else {
285                 unhandled = 1;
286         }
287
288         if (unhandled)
289                 nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap);
290 }
291
292
293 static inline void
294 nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource)
295 {
296         struct nouveau_pgraph_trap trap;
297         int unhandled = 0;
298
299         nouveau_graph_trap_info(dev, &trap);
300         trap.nsource = nsource;
301
302         if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
303                 if (nouveau_pgraph_intr_swmthd(dev, &trap))
304                         unhandled = 1;
305         } else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
306                 uint32_t v = nv_rd32(dev, 0x402000);
307                 nv_wr32(dev, 0x402000, v);
308
309                 /* dump the error anyway for now: it's useful for
310                    Gallium development */
311                 unhandled = 1;
312         } else {
313                 unhandled = 1;
314         }
315
316         if (unhandled && nouveau_ratelimit())
317                 nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap);
318 }
319
320 static inline void
321 nouveau_pgraph_intr_context_switch(struct drm_device *dev)
322 {
323         struct drm_nouveau_private *dev_priv = dev->dev_private;
324         struct nouveau_engine *engine = &dev_priv->engine;
325         uint32_t chid;
326
327         chid = engine->fifo.channel_id(dev);
328         NV_DEBUG(dev, "PGRAPH context switch interrupt channel %x\n", chid);
329
330         switch (dev_priv->card_type) {
331         case NV_04:
332                 nv04_graph_context_switch(dev);
333                 break;
334         case NV_10:
335                 nv10_graph_context_switch(dev);
336                 break;
337         default:
338                 NV_ERROR(dev, "Context switch not implemented\n");
339                 break;
340         }
341 }
342
343 static void
344 nouveau_pgraph_irq_handler(struct drm_device *dev)
345 {
346         uint32_t status;
347
348         while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
349                 uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
350
351                 if (status & NV_PGRAPH_INTR_NOTIFY) {
352                         nouveau_pgraph_intr_notify(dev, nsource);
353
354                         status &= ~NV_PGRAPH_INTR_NOTIFY;
355                         nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY);
356                 }
357
358                 if (status & NV_PGRAPH_INTR_ERROR) {
359                         nouveau_pgraph_intr_error(dev, nsource);
360
361                         status &= ~NV_PGRAPH_INTR_ERROR;
362                         nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR);
363                 }
364
365                 if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
366                         status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
367                         nv_wr32(dev, NV03_PGRAPH_INTR,
368                                  NV_PGRAPH_INTR_CONTEXT_SWITCH);
369
370                         nouveau_pgraph_intr_context_switch(dev);
371                 }
372
373                 if (status) {
374                         NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status);
375                         nv_wr32(dev, NV03_PGRAPH_INTR, status);
376                 }
377
378                 if ((nv_rd32(dev, NV04_PGRAPH_FIFO) & (1 << 0)) == 0)
379                         nv_wr32(dev, NV04_PGRAPH_FIFO, 1);
380         }
381
382         nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
383 }
384
385 static struct nouveau_enum nv50_mp_exec_error_names[] =
386 {
387         { 3, "STACK_UNDERFLOW" },
388         { 4, "QUADON_ACTIVE" },
389         { 8, "TIMEOUT" },
390         { 0x10, "INVALID_OPCODE" },
391         { 0x40, "BREAKPOINT" },
392         {}
393 };
394
395 static void
396 nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display)
397 {
398         struct drm_nouveau_private *dev_priv = dev->dev_private;
399         uint32_t units = nv_rd32(dev, 0x1540);
400         uint32_t addr, mp10, status, pc, oplow, ophigh;
401         int i;
402         int mps = 0;
403         for (i = 0; i < 4; i++) {
404                 if (!(units & 1 << (i+24)))
405                         continue;
406                 if (dev_priv->chipset < 0xa0)
407                         addr = 0x408200 + (tpid << 12) + (i << 7);
408                 else
409                         addr = 0x408100 + (tpid << 11) + (i << 7);
410                 mp10 = nv_rd32(dev, addr + 0x10);
411                 status = nv_rd32(dev, addr + 0x14);
412                 if (!status)
413                         continue;
414                 if (display) {
415                         nv_rd32(dev, addr + 0x20);
416                         pc = nv_rd32(dev, addr + 0x24);
417                         oplow = nv_rd32(dev, addr + 0x70);
418                         ophigh= nv_rd32(dev, addr + 0x74);
419                         NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - "
420                                         "TP %d MP %d: ", tpid, i);
421                         nouveau_enum_print(nv50_mp_exec_error_names, status);
422                         printk(" at %06x warp %d, opcode %08x %08x\n",
423                                         pc&0xffffff, pc >> 24,
424                                         oplow, ophigh);
425                 }
426                 nv_wr32(dev, addr + 0x10, mp10);
427                 nv_wr32(dev, addr + 0x14, 0);
428                 mps++;
429         }
430         if (!mps && display)
431                 NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: "
432                                 "No MPs claiming errors?\n", tpid);
433 }
434
435 static void
436 nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
437                 uint32_t ustatus_new, int display, const char *name)
438 {
439         struct drm_nouveau_private *dev_priv = dev->dev_private;
440         int tps = 0;
441         uint32_t units = nv_rd32(dev, 0x1540);
442         int i, r;
443         uint32_t ustatus_addr, ustatus;
444         for (i = 0; i < 16; i++) {
445                 if (!(units & (1 << i)))
446                         continue;
447                 if (dev_priv->chipset < 0xa0)
448                         ustatus_addr = ustatus_old + (i << 12);
449                 else
450                         ustatus_addr = ustatus_new + (i << 11);
451                 ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff;
452                 if (!ustatus)
453                         continue;
454                 tps++;
455                 switch (type) {
456                 case 6: /* texture error... unknown for now */
457                         nv50_fb_vm_trap(dev, display, name);
458                         if (display) {
459                                 NV_ERROR(dev, "magic set %d:\n", i);
460                                 for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
461                                         NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
462                                                 nv_rd32(dev, r));
463                         }
464                         break;
465                 case 7: /* MP error */
466                         if (ustatus & 0x00010000) {
467                                 nv50_pgraph_mp_trap(dev, i, display);
468                                 ustatus &= ~0x00010000;
469                         }
470                         break;
471                 case 8: /* TPDMA error */
472                         {
473                         uint32_t e0c = nv_rd32(dev, ustatus_addr + 4);
474                         uint32_t e10 = nv_rd32(dev, ustatus_addr + 8);
475                         uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc);
476                         uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10);
477                         uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14);
478                         uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18);
479                         uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c);
480                         nv50_fb_vm_trap(dev, display, name);
481                         /* 2d engine destination */
482                         if (ustatus & 0x00000010) {
483                                 if (display) {
484                                         NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n",
485                                                         i, e14, e10);
486                                         NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
487                                                         i, e0c, e18, e1c, e20, e24);
488                                 }
489                                 ustatus &= ~0x00000010;
490                         }
491                         /* Render target */
492                         if (ustatus & 0x00000040) {
493                                 if (display) {
494                                         NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n",
495                                                         i, e14, e10);
496                                         NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
497                                                         i, e0c, e18, e1c, e20, e24);
498                                 }
499                                 ustatus &= ~0x00000040;
500                         }
501                         /* CUDA memory: l[], g[] or stack. */
502                         if (ustatus & 0x00000080) {
503                                 if (display) {
504                                         if (e18 & 0x80000000) {
505                                                 /* g[] read fault? */
506                                                 NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n",
507                                                                 i, e14, e10 | ((e18 >> 24) & 0x1f));
508                                                 e18 &= ~0x1f000000;
509                                         } else if (e18 & 0xc) {
510                                                 /* g[] write fault? */
511                                                 NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n",
512                                                                 i, e14, e10 | ((e18 >> 7) & 0x1f));
513                                                 e18 &= ~0x00000f80;
514                                         } else {
515                                                 NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n",
516                                                                 i, e14, e10);
517                                         }
518                                         NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
519                                                         i, e0c, e18, e1c, e20, e24);
520                                 }
521                                 ustatus &= ~0x00000080;
522                         }
523                         }
524                         break;
525                 }
526                 if (ustatus) {
527                         if (display)
528                                 NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus);
529                 }
530                 nv_wr32(dev, ustatus_addr, 0xc0000000);
531         }
532
533         if (!tps && display)
534                 NV_INFO(dev, "%s - No TPs claiming errors?\n", name);
535 }
536
537 static void
538 nv50_pgraph_trap_handler(struct drm_device *dev)
539 {
540         struct nouveau_pgraph_trap trap;
541         uint32_t status = nv_rd32(dev, 0x400108);
542         uint32_t ustatus;
543         int display = nouveau_ratelimit();
544
545
546         if (!status && display) {
547                 nouveau_graph_trap_info(dev, &trap);
548                 nouveau_graph_dump_trap_info(dev, "PGRAPH_TRAP", &trap);
549                 NV_INFO(dev, "PGRAPH_TRAP - no units reporting traps?\n");
550         }
551
552         /* DISPATCH: Relays commands to other units and handles NOTIFY,
553          * COND, QUERY. If you get a trap from it, the command is still stuck
554          * in DISPATCH and you need to do something about it. */
555         if (status & 0x001) {
556                 ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff;
557                 if (!ustatus && display) {
558                         NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n");
559                 }
560
561                 /* Known to be triggered by screwed up NOTIFY and COND... */
562                 if (ustatus & 0x00000001) {
563                         nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT");
564                         nv_wr32(dev, 0x400500, 0);
565                         if (nv_rd32(dev, 0x400808) & 0x80000000) {
566                                 if (display) {
567                                         if (nouveau_graph_trapped_channel(dev, &trap.channel))
568                                                 trap.channel = -1;
569                                         trap.class = nv_rd32(dev, 0x400814);
570                                         trap.mthd = nv_rd32(dev, 0x400808) & 0x1ffc;
571                                         trap.subc = (nv_rd32(dev, 0x400808) >> 16) & 0x7;
572                                         trap.data = nv_rd32(dev, 0x40080c);
573                                         trap.data2 = nv_rd32(dev, 0x400810);
574                                         nouveau_graph_dump_trap_info(dev,
575                                                         "PGRAPH_TRAP_DISPATCH_FAULT", &trap);
576                                         NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400808: %08x\n", nv_rd32(dev, 0x400808));
577                                         NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400848: %08x\n", nv_rd32(dev, 0x400848));
578                                 }
579                                 nv_wr32(dev, 0x400808, 0);
580                         } else if (display) {
581                                 NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - No stuck command?\n");
582                         }
583                         nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3);
584                         nv_wr32(dev, 0x400848, 0);
585                         ustatus &= ~0x00000001;
586                 }
587                 if (ustatus & 0x00000002) {
588                         nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY");
589                         nv_wr32(dev, 0x400500, 0);
590                         if (nv_rd32(dev, 0x40084c) & 0x80000000) {
591                                 if (display) {
592                                         if (nouveau_graph_trapped_channel(dev, &trap.channel))
593                                                 trap.channel = -1;
594                                         trap.class = nv_rd32(dev, 0x400814);
595                                         trap.mthd = nv_rd32(dev, 0x40084c) & 0x1ffc;
596                                         trap.subc = (nv_rd32(dev, 0x40084c) >> 16) & 0x7;
597                                         trap.data = nv_rd32(dev, 0x40085c);
598                                         trap.data2 = 0;
599                                         nouveau_graph_dump_trap_info(dev,
600                                                         "PGRAPH_TRAP_DISPATCH_QUERY", &trap);
601                                         NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - 40084c: %08x\n", nv_rd32(dev, 0x40084c));
602                                 }
603                                 nv_wr32(dev, 0x40084c, 0);
604                         } else if (display) {
605                                 NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - No stuck command?\n");
606                         }
607                         ustatus &= ~0x00000002;
608                 }
609                 if (ustatus && display)
610                         NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - Unhandled ustatus 0x%08x\n", ustatus);
611                 nv_wr32(dev, 0x400804, 0xc0000000);
612                 nv_wr32(dev, 0x400108, 0x001);
613                 status &= ~0x001;
614         }
615
616         /* TRAPs other than dispatch use the "normal" trap regs. */
617         if (status && display) {
618                 nouveau_graph_trap_info(dev, &trap);
619                 nouveau_graph_dump_trap_info(dev,
620                                 "PGRAPH_TRAP", &trap);
621         }
622
623         /* M2MF: Memory to memory copy engine. */
624         if (status & 0x002) {
625                 ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff;
626                 if (!ustatus && display) {
627                         NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n");
628                 }
629                 if (ustatus & 0x00000001) {
630                         nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY");
631                         ustatus &= ~0x00000001;
632                 }
633                 if (ustatus & 0x00000002) {
634                         nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN");
635                         ustatus &= ~0x00000002;
636                 }
637                 if (ustatus & 0x00000004) {
638                         nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT");
639                         ustatus &= ~0x00000004;
640                 }
641                 NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n",
642                                 nv_rd32(dev, 0x406804),
643                                 nv_rd32(dev, 0x406808),
644                                 nv_rd32(dev, 0x40680c),
645                                 nv_rd32(dev, 0x406810));
646                 if (ustatus && display)
647                         NV_INFO(dev, "PGRAPH_TRAP_M2MF - Unhandled ustatus 0x%08x\n", ustatus);
648                 /* No sane way found yet -- just reset the bugger. */
649                 nv_wr32(dev, 0x400040, 2);
650                 nv_wr32(dev, 0x400040, 0);
651                 nv_wr32(dev, 0x406800, 0xc0000000);
652                 nv_wr32(dev, 0x400108, 0x002);
653                 status &= ~0x002;
654         }
655
656         /* VFETCH: Fetches data from vertex buffers. */
657         if (status & 0x004) {
658                 ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff;
659                 if (!ustatus && display) {
660                         NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n");
661                 }
662                 if (ustatus & 0x00000001) {
663                         nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT");
664                         NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n",
665                                         nv_rd32(dev, 0x400c00),
666                                         nv_rd32(dev, 0x400c08),
667                                         nv_rd32(dev, 0x400c0c),
668                                         nv_rd32(dev, 0x400c10));
669                         ustatus &= ~0x00000001;
670                 }
671                 if (ustatus && display)
672                         NV_INFO(dev, "PGRAPH_TRAP_VFETCH - Unhandled ustatus 0x%08x\n", ustatus);
673                 nv_wr32(dev, 0x400c04, 0xc0000000);
674                 nv_wr32(dev, 0x400108, 0x004);
675                 status &= ~0x004;
676         }
677
678         /* STRMOUT: DirectX streamout / OpenGL transform feedback. */
679         if (status & 0x008) {
680                 ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff;
681                 if (!ustatus && display) {
682                         NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n");
683                 }
684                 if (ustatus & 0x00000001) {
685                         nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT");
686                         NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n",
687                                         nv_rd32(dev, 0x401804),
688                                         nv_rd32(dev, 0x401808),
689                                         nv_rd32(dev, 0x40180c),
690                                         nv_rd32(dev, 0x401810));
691                         ustatus &= ~0x00000001;
692                 }
693                 if (ustatus && display)
694                         NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - Unhandled ustatus 0x%08x\n", ustatus);
695                 /* No sane way found yet -- just reset the bugger. */
696                 nv_wr32(dev, 0x400040, 0x80);
697                 nv_wr32(dev, 0x400040, 0);
698                 nv_wr32(dev, 0x401800, 0xc0000000);
699                 nv_wr32(dev, 0x400108, 0x008);
700                 status &= ~0x008;
701         }
702
703         /* CCACHE: Handles code and c[] caches and fills them. */
704         if (status & 0x010) {
705                 ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff;
706                 if (!ustatus && display) {
707                         NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n");
708                 }
709                 if (ustatus & 0x00000001) {
710                         nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT");
711                         NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n",
712                                         nv_rd32(dev, 0x405800),
713                                         nv_rd32(dev, 0x405804),
714                                         nv_rd32(dev, 0x405808),
715                                         nv_rd32(dev, 0x40580c),
716                                         nv_rd32(dev, 0x405810),
717                                         nv_rd32(dev, 0x405814),
718                                         nv_rd32(dev, 0x40581c));
719                         ustatus &= ~0x00000001;
720                 }
721                 if (ustatus && display)
722                         NV_INFO(dev, "PGRAPH_TRAP_CCACHE - Unhandled ustatus 0x%08x\n", ustatus);
723                 nv_wr32(dev, 0x405018, 0xc0000000);
724                 nv_wr32(dev, 0x400108, 0x010);
725                 status &= ~0x010;
726         }
727
728         /* Unknown, not seen yet... 0x402000 is the only trap status reg
729          * remaining, so try to handle it anyway. Perhaps related to that
730          * unknown DMA slot on tesla? */
731         if (status & 0x20) {
732                 nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04");
733                 ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff;
734                 if (display)
735                         NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus);
736                 nv_wr32(dev, 0x402000, 0xc0000000);
737                 /* no status modifiction on purpose */
738         }
739
740         /* TEXTURE: CUDA texturing units */
741         if (status & 0x040) {
742                 nv50_pgraph_tp_trap (dev, 6, 0x408900, 0x408600, display,
743                                 "PGRAPH_TRAP_TEXTURE");
744                 nv_wr32(dev, 0x400108, 0x040);
745                 status &= ~0x040;
746         }
747
748         /* MP: CUDA execution engines. */
749         if (status & 0x080) {
750                 nv50_pgraph_tp_trap (dev, 7, 0x408314, 0x40831c, display,
751                                 "PGRAPH_TRAP_MP");
752                 nv_wr32(dev, 0x400108, 0x080);
753                 status &= ~0x080;
754         }
755
756         /* TPDMA:  Handles TP-initiated uncached memory accesses:
757          * l[], g[], stack, 2d surfaces, render targets. */
758         if (status & 0x100) {
759                 nv50_pgraph_tp_trap (dev, 8, 0x408e08, 0x408708, display,
760                                 "PGRAPH_TRAP_TPDMA");
761                 nv_wr32(dev, 0x400108, 0x100);
762                 status &= ~0x100;
763         }
764
765         if (status) {
766                 if (display)
767                         NV_INFO(dev, "PGRAPH_TRAP - Unknown trap 0x%08x\n",
768                                 status);
769                 nv_wr32(dev, 0x400108, status);
770         }
771 }
772
773 /* There must be a *lot* of these. Will take some time to gather them up. */
774 static struct nouveau_enum nv50_data_error_names[] =
775 {
776         { 4,    "INVALID_VALUE" },
777         { 5,    "INVALID_ENUM" },
778         { 8,    "INVALID_OBJECT" },
779         { 0xc,  "INVALID_BITFIELD" },
780         { 0x28, "MP_NO_REG_SPACE" },
781         { 0x2b, "MP_BLOCK_SIZE_MISMATCH" },
782         {}
783 };
784
785 static void
786 nv50_pgraph_irq_handler(struct drm_device *dev)
787 {
788         struct nouveau_pgraph_trap trap;
789         int unhandled = 0;
790         uint32_t status;
791
792         while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
793                 /* NOTIFY: You've set a NOTIFY an a command and it's done. */
794                 if (status & 0x00000001) {
795                         nouveau_graph_trap_info(dev, &trap);
796                         if (nouveau_ratelimit())
797                                 nouveau_graph_dump_trap_info(dev,
798                                                 "PGRAPH_NOTIFY", &trap);
799                         status &= ~0x00000001;
800                         nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001);
801                 }
802
803                 /* COMPUTE_QUERY: Purpose and exact cause unknown, happens
804                  * when you write 0x200 to 0x50c0 method 0x31c. */
805                 if (status & 0x00000002) {
806                         nouveau_graph_trap_info(dev, &trap);
807                         if (nouveau_ratelimit())
808                                 nouveau_graph_dump_trap_info(dev,
809                                                 "PGRAPH_COMPUTE_QUERY", &trap);
810                         status &= ~0x00000002;
811                         nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000002);
812                 }
813
814                 /* Unknown, never seen: 0x4 */
815
816                 /* ILLEGAL_MTHD: You used a wrong method for this class. */
817                 if (status & 0x00000010) {
818                         nouveau_graph_trap_info(dev, &trap);
819                         if (nouveau_pgraph_intr_swmthd(dev, &trap))
820                                 unhandled = 1;
821                         if (unhandled && nouveau_ratelimit())
822                                 nouveau_graph_dump_trap_info(dev,
823                                                 "PGRAPH_ILLEGAL_MTHD", &trap);
824                         status &= ~0x00000010;
825                         nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010);
826                 }
827
828                 /* ILLEGAL_CLASS: You used a wrong class. */
829                 if (status & 0x00000020) {
830                         nouveau_graph_trap_info(dev, &trap);
831                         if (nouveau_ratelimit())
832                                 nouveau_graph_dump_trap_info(dev,
833                                                 "PGRAPH_ILLEGAL_CLASS", &trap);
834                         status &= ~0x00000020;
835                         nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000020);
836                 }
837
838                 /* DOUBLE_NOTIFY: You tried to set a NOTIFY on another NOTIFY. */
839                 if (status & 0x00000040) {
840                         nouveau_graph_trap_info(dev, &trap);
841                         if (nouveau_ratelimit())
842                                 nouveau_graph_dump_trap_info(dev,
843                                                 "PGRAPH_DOUBLE_NOTIFY", &trap);
844                         status &= ~0x00000040;
845                         nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000040);
846                 }
847
848                 /* CONTEXT_SWITCH: PGRAPH needs us to load a new context */
849                 if (status & 0x00001000) {
850                         nv_wr32(dev, 0x400500, 0x00000000);
851                         nv_wr32(dev, NV03_PGRAPH_INTR,
852                                 NV_PGRAPH_INTR_CONTEXT_SWITCH);
853                         nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev,
854                                 NV40_PGRAPH_INTR_EN) &
855                                 ~NV_PGRAPH_INTR_CONTEXT_SWITCH);
856                         nv_wr32(dev, 0x400500, 0x00010001);
857
858                         nv50_graph_context_switch(dev);
859
860                         status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
861                 }
862
863                 /* BUFFER_NOTIFY: Your m2mf transfer finished */
864                 if (status & 0x00010000) {
865                         nouveau_graph_trap_info(dev, &trap);
866                         if (nouveau_ratelimit())
867                                 nouveau_graph_dump_trap_info(dev,
868                                                 "PGRAPH_BUFFER_NOTIFY", &trap);
869                         status &= ~0x00010000;
870                         nv_wr32(dev, NV03_PGRAPH_INTR, 0x00010000);
871                 }
872
873                 /* DATA_ERROR: Invalid value for this method, or invalid
874                  * state in current PGRAPH context for this operation */
875                 if (status & 0x00100000) {
876                         nouveau_graph_trap_info(dev, &trap);
877                         if (nouveau_ratelimit()) {
878                                 nouveau_graph_dump_trap_info(dev,
879                                                 "PGRAPH_DATA_ERROR", &trap);
880                                 NV_INFO (dev, "PGRAPH_DATA_ERROR - ");
881                                 nouveau_enum_print(nv50_data_error_names,
882                                                    nv_rd32(dev, 0x400110));
883                                 printk("\n");
884                         }
885                         status &= ~0x00100000;
886                         nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000);
887                 }
888
889                 /* TRAP: Something bad happened in the middle of command
890                  * execution.  Has a billion types, subtypes, and even
891                  * subsubtypes. */
892                 if (status & 0x00200000) {
893                         nv50_pgraph_trap_handler(dev);
894                         status &= ~0x00200000;
895                         nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000);
896                 }
897
898                 /* Unknown, never seen: 0x00400000 */
899
900                 /* SINGLE_STEP: Happens on every method if you turned on
901                  * single stepping in 40008c */
902                 if (status & 0x01000000) {
903                         nouveau_graph_trap_info(dev, &trap);
904                         if (nouveau_ratelimit())
905                                 nouveau_graph_dump_trap_info(dev,
906                                                 "PGRAPH_SINGLE_STEP", &trap);
907                         status &= ~0x01000000;
908                         nv_wr32(dev, NV03_PGRAPH_INTR, 0x01000000);
909                 }
910
911                 /* 0x02000000 happens when you pause a ctxprog...
912                  * but the only way this can happen that I know is by
913                  * poking the relevant MMIO register, and we don't
914                  * do that. */
915
916                 if (status) {
917                         NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n",
918                                 status);
919                         nv_wr32(dev, NV03_PGRAPH_INTR, status);
920                 }
921
922                 {
923                         const int isb = (1 << 16) | (1 << 0);
924
925                         if ((nv_rd32(dev, 0x400500) & isb) != isb)
926                                 nv_wr32(dev, 0x400500,
927                                         nv_rd32(dev, 0x400500) | isb);
928                 }
929         }
930
931         nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
932         if (nv_rd32(dev, 0x400824) & (1 << 31))
933                 nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
934 }
935
936 irqreturn_t
937 nouveau_irq_handler(DRM_IRQ_ARGS)
938 {
939         struct drm_device *dev = (struct drm_device *)arg;
940         struct drm_nouveau_private *dev_priv = dev->dev_private;
941         unsigned long flags;
942         u32 status;
943         int i;
944
945         status = nv_rd32(dev, NV03_PMC_INTR_0);
946         if (!status)
947                 return IRQ_NONE;
948
949         spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
950
951         if (status & NV_PMC_INTR_0_PGRAPH_PENDING) {
952                 if (dev_priv->card_type >= NV_50)
953                         nv50_pgraph_irq_handler(dev);
954                 else
955                         nouveau_pgraph_irq_handler(dev);
956
957                 status &= ~NV_PMC_INTR_0_PGRAPH_PENDING;
958         }
959
960         for (i = 0; i < 32 && status; i++) {
961                 if (!(status & (1 << i)) || !dev_priv->irq_handler[i])
962                         continue;
963
964                 dev_priv->irq_handler[i](dev);
965                 status &= ~(1 << i);
966         }
967
968         if (status)
969                 NV_ERROR(dev, "Unhandled PMC INTR status bits 0x%08x\n", status);
970
971         spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
972
973         if (dev_priv->msi_enabled)
974                 nv_wr08(dev, 0x00088068, 0xff);
975
976         return IRQ_HANDLED;
977 }
978
979 int
980 nouveau_irq_init(struct drm_device *dev)
981 {
982         struct drm_nouveau_private *dev_priv = dev->dev_private;
983         int ret;
984
985         if (nouveau_msi != 0 && dev_priv->card_type >= NV_50) {
986                 ret = pci_enable_msi(dev->pdev);
987                 if (ret == 0) {
988                         NV_INFO(dev, "enabled MSI\n");
989                         dev_priv->msi_enabled = true;
990                 }
991         }
992
993         return drm_irq_install(dev);
994 }
995
996 void
997 nouveau_irq_fini(struct drm_device *dev)
998 {
999         struct drm_nouveau_private *dev_priv = dev->dev_private;
1000
1001         drm_irq_uninstall(dev);
1002         if (dev_priv->msi_enabled)
1003                 pci_disable_msi(dev->pdev);
1004 }
1005
1006 void
1007 nouveau_irq_register(struct drm_device *dev, int status_bit,
1008                      void (*handler)(struct drm_device *))
1009 {
1010         struct drm_nouveau_private *dev_priv = dev->dev_private;
1011         unsigned long flags;
1012
1013         spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
1014         dev_priv->irq_handler[status_bit] = handler;
1015         spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
1016 }
1017
1018 void
1019 nouveau_irq_unregister(struct drm_device *dev, int status_bit)
1020 {
1021         struct drm_nouveau_private *dev_priv = dev->dev_private;
1022         unsigned long flags;
1023
1024         spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
1025         dev_priv->irq_handler[status_bit] = NULL;
1026         spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
1027 }