sparc: Convert naked unsigned uses to unsigned int
[linux-2.6-block.git] / drivers / gpu / drm / nouveau / nvkm / engine / fifo / gf100.c
1 /*
2  * Copyright 2012 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Ben Skeggs
23  */
24 #include "gf100.h"
25 #include "changf100.h"
26
27 #include <core/client.h>
28 #include <core/enum.h>
29 #include <core/gpuobj.h>
30 #include <subdev/bar.h>
31 #include <engine/sw.h>
32
33 #include <nvif/class.h>
34
35 static void
36 gf100_fifo_uevent_init(struct nvkm_fifo *fifo)
37 {
38         struct nvkm_device *device = fifo->engine.subdev.device;
39         nvkm_mask(device, 0x002140, 0x80000000, 0x80000000);
40 }
41
42 static void
43 gf100_fifo_uevent_fini(struct nvkm_fifo *fifo)
44 {
45         struct nvkm_device *device = fifo->engine.subdev.device;
46         nvkm_mask(device, 0x002140, 0x80000000, 0x00000000);
47 }
48
49 void
50 gf100_fifo_runlist_commit(struct gf100_fifo *fifo)
51 {
52         struct gf100_fifo_chan *chan;
53         struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
54         struct nvkm_device *device = subdev->device;
55         struct nvkm_memory *cur;
56         int nr = 0;
57
58         mutex_lock(&subdev->mutex);
59         cur = fifo->runlist.mem[fifo->runlist.active];
60         fifo->runlist.active = !fifo->runlist.active;
61
62         nvkm_kmap(cur);
63         list_for_each_entry(chan, &fifo->chan, head) {
64                 nvkm_wo32(cur, (nr * 8) + 0, chan->base.chid);
65                 nvkm_wo32(cur, (nr * 8) + 4, 0x00000004);
66                 nr++;
67         }
68         nvkm_done(cur);
69
70         nvkm_wr32(device, 0x002270, nvkm_memory_addr(cur) >> 12);
71         nvkm_wr32(device, 0x002274, 0x01f00000 | nr);
72
73         if (wait_event_timeout(fifo->runlist.wait,
74                                !(nvkm_rd32(device, 0x00227c) & 0x00100000),
75                                msecs_to_jiffies(2000)) == 0)
76                 nvkm_error(subdev, "runlist update timeout\n");
77         mutex_unlock(&subdev->mutex);
78 }
79
80 void
81 gf100_fifo_runlist_remove(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan)
82 {
83         mutex_lock(&fifo->base.engine.subdev.mutex);
84         list_del_init(&chan->head);
85         mutex_unlock(&fifo->base.engine.subdev.mutex);
86 }
87
88 void
89 gf100_fifo_runlist_insert(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan)
90 {
91         mutex_lock(&fifo->base.engine.subdev.mutex);
92         list_add_tail(&chan->head, &fifo->chan);
93         mutex_unlock(&fifo->base.engine.subdev.mutex);
94 }
95
96 static inline int
97 gf100_fifo_engidx(struct gf100_fifo *fifo, u32 engn)
98 {
99         switch (engn) {
100         case NVKM_ENGINE_GR    : engn = 0; break;
101         case NVKM_ENGINE_MSVLD : engn = 1; break;
102         case NVKM_ENGINE_MSPPP : engn = 2; break;
103         case NVKM_ENGINE_MSPDEC: engn = 3; break;
104         case NVKM_ENGINE_CE0   : engn = 4; break;
105         case NVKM_ENGINE_CE1   : engn = 5; break;
106         default:
107                 return -1;
108         }
109
110         return engn;
111 }
112
113 static inline struct nvkm_engine *
114 gf100_fifo_engine(struct gf100_fifo *fifo, u32 engn)
115 {
116         struct nvkm_device *device = fifo->base.engine.subdev.device;
117
118         switch (engn) {
119         case 0: engn = NVKM_ENGINE_GR; break;
120         case 1: engn = NVKM_ENGINE_MSVLD; break;
121         case 2: engn = NVKM_ENGINE_MSPPP; break;
122         case 3: engn = NVKM_ENGINE_MSPDEC; break;
123         case 4: engn = NVKM_ENGINE_CE0; break;
124         case 5: engn = NVKM_ENGINE_CE1; break;
125         default:
126                 return NULL;
127         }
128
129         return nvkm_device_engine(device, engn);
130 }
131
132 static void
133 gf100_fifo_recover_work(struct work_struct *work)
134 {
135         struct gf100_fifo *fifo = container_of(work, typeof(*fifo), fault);
136         struct nvkm_device *device = fifo->base.engine.subdev.device;
137         struct nvkm_engine *engine;
138         unsigned long flags;
139         u32 engn, engm = 0;
140         u64 mask, todo;
141
142         spin_lock_irqsave(&fifo->base.lock, flags);
143         mask = fifo->mask;
144         fifo->mask = 0ULL;
145         spin_unlock_irqrestore(&fifo->base.lock, flags);
146
147         for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn))
148                 engm |= 1 << gf100_fifo_engidx(fifo, engn);
149         nvkm_mask(device, 0x002630, engm, engm);
150
151         for (todo = mask; engn = __ffs64(todo), todo; todo &= ~(1 << engn)) {
152                 if ((engine = nvkm_device_engine(device, engn))) {
153                         nvkm_subdev_fini(&engine->subdev, false);
154                         WARN_ON(nvkm_subdev_init(&engine->subdev));
155                 }
156         }
157
158         gf100_fifo_runlist_commit(fifo);
159         nvkm_wr32(device, 0x00262c, engm);
160         nvkm_mask(device, 0x002630, engm, 0x00000000);
161 }
162
163 static void
164 gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine,
165                    struct gf100_fifo_chan *chan)
166 {
167         struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
168         struct nvkm_device *device = subdev->device;
169         u32 chid = chan->base.chid;
170
171         nvkm_error(subdev, "%s engine fault on channel %d, recovering...\n",
172                    nvkm_subdev_name[engine->subdev.index], chid);
173         assert_spin_locked(&fifo->base.lock);
174
175         nvkm_mask(device, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000);
176         list_del_init(&chan->head);
177         chan->killed = true;
178
179         fifo->mask |= 1ULL << engine->subdev.index;
180         schedule_work(&fifo->fault);
181 }
182
183 static const struct nvkm_enum
184 gf100_fifo_sched_reason[] = {
185         { 0x0a, "CTXSW_TIMEOUT" },
186         {}
187 };
188
189 static void
190 gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo)
191 {
192         struct nvkm_device *device = fifo->base.engine.subdev.device;
193         struct nvkm_engine *engine;
194         struct gf100_fifo_chan *chan;
195         unsigned long flags;
196         u32 engn;
197
198         spin_lock_irqsave(&fifo->base.lock, flags);
199         for (engn = 0; engn < 6; engn++) {
200                 u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04));
201                 u32 busy = (stat & 0x80000000);
202                 u32 save = (stat & 0x00100000); /* maybe? */
203                 u32 unk0 = (stat & 0x00040000);
204                 u32 unk1 = (stat & 0x00001000);
205                 u32 chid = (stat & 0x0000007f);
206                 (void)save;
207
208                 if (busy && unk0 && unk1) {
209                         list_for_each_entry(chan, &fifo->chan, head) {
210                                 if (chan->base.chid == chid) {
211                                         engine = gf100_fifo_engine(fifo, engn);
212                                         if (!engine)
213                                                 break;
214                                         gf100_fifo_recover(fifo, engine, chan);
215                                         break;
216                                 }
217                         }
218                 }
219         }
220         spin_unlock_irqrestore(&fifo->base.lock, flags);
221 }
222
223 static void
224 gf100_fifo_intr_sched(struct gf100_fifo *fifo)
225 {
226         struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
227         struct nvkm_device *device = subdev->device;
228         u32 intr = nvkm_rd32(device, 0x00254c);
229         u32 code = intr & 0x000000ff;
230         const struct nvkm_enum *en;
231
232         en = nvkm_enum_find(gf100_fifo_sched_reason, code);
233
234         nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : "");
235
236         switch (code) {
237         case 0x0a:
238                 gf100_fifo_intr_sched_ctxsw(fifo);
239                 break;
240         default:
241                 break;
242         }
243 }
244
245 static const struct nvkm_enum
246 gf100_fifo_fault_engine[] = {
247         { 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR },
248         { 0x03, "PEEPHOLE", NULL, NVKM_ENGINE_IFB },
249         { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
250         { 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM },
251         { 0x07, "PFIFO", NULL, NVKM_ENGINE_FIFO },
252         { 0x10, "PMSVLD", NULL, NVKM_ENGINE_MSVLD },
253         { 0x11, "PMSPPP", NULL, NVKM_ENGINE_MSPPP },
254         { 0x13, "PCOUNTER" },
255         { 0x14, "PMSPDEC", NULL, NVKM_ENGINE_MSPDEC },
256         { 0x15, "PCE0", NULL, NVKM_ENGINE_CE0 },
257         { 0x16, "PCE1", NULL, NVKM_ENGINE_CE1 },
258         { 0x17, "PMU" },
259         {}
260 };
261
262 static const struct nvkm_enum
263 gf100_fifo_fault_reason[] = {
264         { 0x00, "PT_NOT_PRESENT" },
265         { 0x01, "PT_TOO_SHORT" },
266         { 0x02, "PAGE_NOT_PRESENT" },
267         { 0x03, "VM_LIMIT_EXCEEDED" },
268         { 0x04, "NO_CHANNEL" },
269         { 0x05, "PAGE_SYSTEM_ONLY" },
270         { 0x06, "PAGE_READ_ONLY" },
271         { 0x0a, "COMPRESSED_SYSRAM" },
272         { 0x0c, "INVALID_STORAGE_TYPE" },
273         {}
274 };
275
276 static const struct nvkm_enum
277 gf100_fifo_fault_hubclient[] = {
278         { 0x01, "PCOPY0" },
279         { 0x02, "PCOPY1" },
280         { 0x04, "DISPATCH" },
281         { 0x05, "CTXCTL" },
282         { 0x06, "PFIFO" },
283         { 0x07, "BAR_READ" },
284         { 0x08, "BAR_WRITE" },
285         { 0x0b, "PVP" },
286         { 0x0c, "PMSPPP" },
287         { 0x0d, "PMSVLD" },
288         { 0x11, "PCOUNTER" },
289         { 0x12, "PMU" },
290         { 0x14, "CCACHE" },
291         { 0x15, "CCACHE_POST" },
292         {}
293 };
294
295 static const struct nvkm_enum
296 gf100_fifo_fault_gpcclient[] = {
297         { 0x01, "TEX" },
298         { 0x0c, "ESETUP" },
299         { 0x0e, "CTXCTL" },
300         { 0x0f, "PROP" },
301         {}
302 };
303
304 static void
305 gf100_fifo_intr_fault(struct gf100_fifo *fifo, int unit)
306 {
307         struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
308         struct nvkm_device *device = subdev->device;
309         u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
310         u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10));
311         u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10));
312         u32 stat = nvkm_rd32(device, 0x00280c + (unit * 0x10));
313         u32 gpc    = (stat & 0x1f000000) >> 24;
314         u32 client = (stat & 0x00001f00) >> 8;
315         u32 write  = (stat & 0x00000080);
316         u32 hub    = (stat & 0x00000040);
317         u32 reason = (stat & 0x0000000f);
318         const struct nvkm_enum *er, *eu, *ec;
319         struct nvkm_engine *engine = NULL;
320         struct nvkm_fifo_chan *chan;
321         unsigned long flags;
322         char gpcid[8] = "";
323
324         er = nvkm_enum_find(gf100_fifo_fault_reason, reason);
325         eu = nvkm_enum_find(gf100_fifo_fault_engine, unit);
326         if (hub) {
327                 ec = nvkm_enum_find(gf100_fifo_fault_hubclient, client);
328         } else {
329                 ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, client);
330                 snprintf(gpcid, sizeof(gpcid), "GPC%d/", gpc);
331         }
332
333         if (eu) {
334                 switch (eu->data2) {
335                 case NVKM_SUBDEV_BAR:
336                         nvkm_mask(device, 0x001704, 0x00000000, 0x00000000);
337                         break;
338                 case NVKM_SUBDEV_INSTMEM:
339                         nvkm_mask(device, 0x001714, 0x00000000, 0x00000000);
340                         break;
341                 case NVKM_ENGINE_IFB:
342                         nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
343                         break;
344                 default:
345                         engine = nvkm_device_engine(device, eu->data2);
346                         break;
347                 }
348         }
349
350         chan = nvkm_fifo_chan_inst(&fifo->base, (u64)inst << 12, &flags);
351
352         nvkm_error(subdev,
353                    "%s fault at %010llx engine %02x [%s] client %02x [%s%s] "
354                    "reason %02x [%s] on channel %d [%010llx %s]\n",
355                    write ? "write" : "read", (u64)vahi << 32 | valo,
356                    unit, eu ? eu->name : "", client, gpcid, ec ? ec->name : "",
357                    reason, er ? er->name : "", chan ? chan->chid : -1,
358                    (u64)inst << 12,
359                    chan ? chan->object.client->name : "unknown");
360
361         if (engine && chan)
362                 gf100_fifo_recover(fifo, engine, (void *)chan);
363         nvkm_fifo_chan_put(&fifo->base, flags, &chan);
364 }
365
366 static const struct nvkm_bitfield
367 gf100_fifo_pbdma_intr[] = {
368 /*      { 0x00008000, "" }      seen with null ib push */
369         { 0x00200000, "ILLEGAL_MTHD" },
370         { 0x00800000, "EMPTY_SUBC" },
371         {}
372 };
373
374 static void
375 gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit)
376 {
377         struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
378         struct nvkm_device *device = subdev->device;
379         u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000));
380         u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000));
381         u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000));
382         u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0x7f;
383         u32 subc = (addr & 0x00070000) >> 16;
384         u32 mthd = (addr & 0x00003ffc);
385         struct nvkm_fifo_chan *chan;
386         unsigned long flags;
387         u32 show= stat;
388         char msg[128];
389
390         if (stat & 0x00800000) {
391                 if (device->sw) {
392                         if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data))
393                                 show &= ~0x00800000;
394                 }
395         }
396
397         if (show) {
398                 nvkm_snprintbf(msg, sizeof(msg), gf100_fifo_pbdma_intr, show);
399                 chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
400                 nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
401                                    "subc %d mthd %04x data %08x\n",
402                            unit, show, msg, chid, chan ? chan->inst->addr : 0,
403                            chan ? chan->object.client->name : "unknown",
404                            subc, mthd, data);
405                 nvkm_fifo_chan_put(&fifo->base, flags, &chan);
406         }
407
408         nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008);
409         nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat);
410 }
411
412 static void
413 gf100_fifo_intr_runlist(struct gf100_fifo *fifo)
414 {
415         struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
416         struct nvkm_device *device = subdev->device;
417         u32 intr = nvkm_rd32(device, 0x002a00);
418
419         if (intr & 0x10000000) {
420                 wake_up(&fifo->runlist.wait);
421                 nvkm_wr32(device, 0x002a00, 0x10000000);
422                 intr &= ~0x10000000;
423         }
424
425         if (intr) {
426                 nvkm_error(subdev, "RUNLIST %08x\n", intr);
427                 nvkm_wr32(device, 0x002a00, intr);
428         }
429 }
430
431 static void
432 gf100_fifo_intr_engine_unit(struct gf100_fifo *fifo, int engn)
433 {
434         struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
435         struct nvkm_device *device = subdev->device;
436         u32 intr = nvkm_rd32(device, 0x0025a8 + (engn * 0x04));
437         u32 inte = nvkm_rd32(device, 0x002628);
438         u32 unkn;
439
440         nvkm_wr32(device, 0x0025a8 + (engn * 0x04), intr);
441
442         for (unkn = 0; unkn < 8; unkn++) {
443                 u32 ints = (intr >> (unkn * 0x04)) & inte;
444                 if (ints & 0x1) {
445                         nvkm_fifo_uevent(&fifo->base);
446                         ints &= ~1;
447                 }
448                 if (ints) {
449                         nvkm_error(subdev, "ENGINE %d %d %01x",
450                                    engn, unkn, ints);
451                         nvkm_mask(device, 0x002628, ints, 0);
452                 }
453         }
454 }
455
456 void
457 gf100_fifo_intr_engine(struct gf100_fifo *fifo)
458 {
459         struct nvkm_device *device = fifo->base.engine.subdev.device;
460         u32 mask = nvkm_rd32(device, 0x0025a4);
461         while (mask) {
462                 u32 unit = __ffs(mask);
463                 gf100_fifo_intr_engine_unit(fifo, unit);
464                 mask &= ~(1 << unit);
465         }
466 }
467
468 static void
469 gf100_fifo_intr(struct nvkm_fifo *base)
470 {
471         struct gf100_fifo *fifo = gf100_fifo(base);
472         struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
473         struct nvkm_device *device = subdev->device;
474         u32 mask = nvkm_rd32(device, 0x002140);
475         u32 stat = nvkm_rd32(device, 0x002100) & mask;
476
477         if (stat & 0x00000001) {
478                 u32 intr = nvkm_rd32(device, 0x00252c);
479                 nvkm_warn(subdev, "INTR 00000001: %08x\n", intr);
480                 nvkm_wr32(device, 0x002100, 0x00000001);
481                 stat &= ~0x00000001;
482         }
483
484         if (stat & 0x00000100) {
485                 gf100_fifo_intr_sched(fifo);
486                 nvkm_wr32(device, 0x002100, 0x00000100);
487                 stat &= ~0x00000100;
488         }
489
490         if (stat & 0x00010000) {
491                 u32 intr = nvkm_rd32(device, 0x00256c);
492                 nvkm_warn(subdev, "INTR 00010000: %08x\n", intr);
493                 nvkm_wr32(device, 0x002100, 0x00010000);
494                 stat &= ~0x00010000;
495         }
496
497         if (stat & 0x01000000) {
498                 u32 intr = nvkm_rd32(device, 0x00258c);
499                 nvkm_warn(subdev, "INTR 01000000: %08x\n", intr);
500                 nvkm_wr32(device, 0x002100, 0x01000000);
501                 stat &= ~0x01000000;
502         }
503
504         if (stat & 0x10000000) {
505                 u32 mask = nvkm_rd32(device, 0x00259c);
506                 while (mask) {
507                         u32 unit = __ffs(mask);
508                         gf100_fifo_intr_fault(fifo, unit);
509                         nvkm_wr32(device, 0x00259c, (1 << unit));
510                         mask &= ~(1 << unit);
511                 }
512                 stat &= ~0x10000000;
513         }
514
515         if (stat & 0x20000000) {
516                 u32 mask = nvkm_rd32(device, 0x0025a0);
517                 while (mask) {
518                         u32 unit = __ffs(mask);
519                         gf100_fifo_intr_pbdma(fifo, unit);
520                         nvkm_wr32(device, 0x0025a0, (1 << unit));
521                         mask &= ~(1 << unit);
522                 }
523                 stat &= ~0x20000000;
524         }
525
526         if (stat & 0x40000000) {
527                 gf100_fifo_intr_runlist(fifo);
528                 stat &= ~0x40000000;
529         }
530
531         if (stat & 0x80000000) {
532                 gf100_fifo_intr_engine(fifo);
533                 stat &= ~0x80000000;
534         }
535
536         if (stat) {
537                 nvkm_error(subdev, "INTR %08x\n", stat);
538                 nvkm_mask(device, 0x002140, stat, 0x00000000);
539                 nvkm_wr32(device, 0x002100, stat);
540         }
541 }
542
543 static int
544 gf100_fifo_oneinit(struct nvkm_fifo *base)
545 {
546         struct gf100_fifo *fifo = gf100_fifo(base);
547         struct nvkm_device *device = fifo->base.engine.subdev.device;
548         int ret;
549
550         ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000,
551                               false, &fifo->runlist.mem[0]);
552         if (ret)
553                 return ret;
554
555         ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000,
556                               false, &fifo->runlist.mem[1]);
557         if (ret)
558                 return ret;
559
560         init_waitqueue_head(&fifo->runlist.wait);
561
562         ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000,
563                               0x1000, false, &fifo->user.mem);
564         if (ret)
565                 return ret;
566
567         ret = nvkm_bar_umap(device->bar, 128 * 0x1000, 12, &fifo->user.bar);
568         if (ret)
569                 return ret;
570
571         nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0);
572         return 0;
573 }
574
575 static void
576 gf100_fifo_fini(struct nvkm_fifo *base)
577 {
578         struct gf100_fifo *fifo = gf100_fifo(base);
579         flush_work(&fifo->fault);
580 }
581
582 static void
583 gf100_fifo_init(struct nvkm_fifo *base)
584 {
585         struct gf100_fifo *fifo = gf100_fifo(base);
586         struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
587         struct nvkm_device *device = subdev->device;
588         int i;
589
590         nvkm_wr32(device, 0x000204, 0xffffffff);
591         nvkm_wr32(device, 0x002204, 0xffffffff);
592
593         fifo->spoon_nr = hweight32(nvkm_rd32(device, 0x002204));
594         nvkm_debug(subdev, "%d PBDMA unit(s)\n", fifo->spoon_nr);
595
596         /* assign engines to PBDMAs */
597         if (fifo->spoon_nr >= 3) {
598                 nvkm_wr32(device, 0x002208, ~(1 << 0)); /* PGRAPH */
599                 nvkm_wr32(device, 0x00220c, ~(1 << 1)); /* PVP */
600                 nvkm_wr32(device, 0x002210, ~(1 << 1)); /* PMSPP */
601                 nvkm_wr32(device, 0x002214, ~(1 << 1)); /* PMSVLD */
602                 nvkm_wr32(device, 0x002218, ~(1 << 2)); /* PCE0 */
603                 nvkm_wr32(device, 0x00221c, ~(1 << 1)); /* PCE1 */
604         }
605
606         /* PBDMA[n] */
607         for (i = 0; i < fifo->spoon_nr; i++) {
608                 nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
609                 nvkm_wr32(device, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
610                 nvkm_wr32(device, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */
611         }
612
613         nvkm_mask(device, 0x002200, 0x00000001, 0x00000001);
614         nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar.offset >> 12);
615
616         nvkm_wr32(device, 0x002100, 0xffffffff);
617         nvkm_wr32(device, 0x002140, 0x7fffffff);
618         nvkm_wr32(device, 0x002628, 0x00000001); /* ENGINE_INTR_EN */
619 }
620
621 static void *
622 gf100_fifo_dtor(struct nvkm_fifo *base)
623 {
624         struct gf100_fifo *fifo = gf100_fifo(base);
625         nvkm_vm_put(&fifo->user.bar);
626         nvkm_memory_del(&fifo->user.mem);
627         nvkm_memory_del(&fifo->runlist.mem[0]);
628         nvkm_memory_del(&fifo->runlist.mem[1]);
629         return fifo;
630 }
631
632 static const struct nvkm_fifo_func
633 gf100_fifo = {
634         .dtor = gf100_fifo_dtor,
635         .oneinit = gf100_fifo_oneinit,
636         .init = gf100_fifo_init,
637         .fini = gf100_fifo_fini,
638         .intr = gf100_fifo_intr,
639         .uevent_init = gf100_fifo_uevent_init,
640         .uevent_fini = gf100_fifo_uevent_fini,
641         .chan = {
642                 &gf100_fifo_gpfifo_oclass,
643                 NULL
644         },
645 };
646
647 int
648 gf100_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
649 {
650         struct gf100_fifo *fifo;
651
652         if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
653                 return -ENOMEM;
654         INIT_LIST_HEAD(&fifo->chan);
655         INIT_WORK(&fifo->fault, gf100_fifo_recover_work);
656         *pfifo = &fifo->base;
657
658         return nvkm_fifo_ctor(&gf100_fifo, device, index, 128, &fifo->base);
659 }