105c7145dSBen Skeggs /*
205c7145dSBen Skeggs * Copyright 2012 Red Hat Inc.
305c7145dSBen Skeggs *
405c7145dSBen Skeggs * Permission is hereby granted, free of charge, to any person obtaining a
505c7145dSBen Skeggs * copy of this software and associated documentation files (the "Software"),
605c7145dSBen Skeggs * to deal in the Software without restriction, including without limitation
705c7145dSBen Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense,
805c7145dSBen Skeggs * and/or sell copies of the Software, and to permit persons to whom the
905c7145dSBen Skeggs * Software is furnished to do so, subject to the following conditions:
1005c7145dSBen Skeggs *
1105c7145dSBen Skeggs * The above copyright notice and this permission notice shall be included in
1205c7145dSBen Skeggs * all copies or substantial portions of the Software.
1305c7145dSBen Skeggs *
1405c7145dSBen Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505c7145dSBen Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605c7145dSBen Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1705c7145dSBen Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1805c7145dSBen Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1905c7145dSBen Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2005c7145dSBen Skeggs * OTHER DEALINGS IN THE SOFTWARE.
2105c7145dSBen Skeggs *
2205c7145dSBen Skeggs * Authors: Ben Skeggs
2305c7145dSBen Skeggs */
24*06db7fdeSBen Skeggs #include "priv.h"
25*06db7fdeSBen Skeggs #include "cgrp.h"
26f5e45689SBen Skeggs #include "chan.h"
27800ac1f8SBen Skeggs #include "chid.h"
28d94470e9SBen Skeggs #include "runl.h"
291c488ba9SBen Skeggs #include "runq.h"
30f5e45689SBen Skeggs
3113de7f46SBen Skeggs #include <core/gpuobj.h>
322fc71a05SBen Skeggs #include <subdev/mc.h>
33*06db7fdeSBen Skeggs #include <subdev/mmu.h>
34e93e198dSBen Skeggs #include <subdev/top.h>
3505c7145dSBen Skeggs
3605c7145dSBen Skeggs #include <nvif/class.h>
378ab849d6SBen Skeggs #include <nvif/if900d.h>
3805c7145dSBen Skeggs
3962742b5eSBen Skeggs void
gk104_chan_stop(struct nvkm_chan * chan)4067059b9fSBen Skeggs gk104_chan_stop(struct nvkm_chan *chan)
4167059b9fSBen Skeggs {
4267059b9fSBen Skeggs struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
4367059b9fSBen Skeggs
4467059b9fSBen Skeggs nvkm_mask(device, 0x800004 + (chan->id * 8), 0x00000800, 0x00000800);
4567059b9fSBen Skeggs }
4667059b9fSBen Skeggs
4767059b9fSBen Skeggs void
gk104_chan_start(struct nvkm_chan * chan)4867059b9fSBen Skeggs gk104_chan_start(struct nvkm_chan *chan)
4967059b9fSBen Skeggs {
5067059b9fSBen Skeggs struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
5167059b9fSBen Skeggs
5267059b9fSBen Skeggs nvkm_mask(device, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400);
5367059b9fSBen Skeggs }
5467059b9fSBen Skeggs
5567059b9fSBen Skeggs void
gk104_chan_unbind(struct nvkm_chan * chan)5662742b5eSBen Skeggs gk104_chan_unbind(struct nvkm_chan *chan)
5762742b5eSBen Skeggs {
5862742b5eSBen Skeggs struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
5962742b5eSBen Skeggs
6062742b5eSBen Skeggs nvkm_wr32(device, 0x800000 + (chan->id * 8), 0x00000000);
6162742b5eSBen Skeggs }
6262742b5eSBen Skeggs
6362742b5eSBen Skeggs void
gk104_chan_bind_inst(struct nvkm_chan * chan)6462742b5eSBen Skeggs gk104_chan_bind_inst(struct nvkm_chan *chan)
6562742b5eSBen Skeggs {
6662742b5eSBen Skeggs struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
6762742b5eSBen Skeggs
6862742b5eSBen Skeggs nvkm_wr32(device, 0x800000 + (chan->id * 8), 0x80000000 | chan->inst->addr >> 12);
6962742b5eSBen Skeggs }
7062742b5eSBen Skeggs
7162742b5eSBen Skeggs void
gk104_chan_bind(struct nvkm_chan * chan)7262742b5eSBen Skeggs gk104_chan_bind(struct nvkm_chan *chan)
7362742b5eSBen Skeggs {
7462742b5eSBen Skeggs struct nvkm_runl *runl = chan->cgrp->runl;
7562742b5eSBen Skeggs struct nvkm_device *device = runl->fifo->engine.subdev.device;
7662742b5eSBen Skeggs
7762742b5eSBen Skeggs nvkm_mask(device, 0x800004 + (chan->id * 8), 0x000f0000, runl->id << 16);
7862742b5eSBen Skeggs gk104_chan_bind_inst(chan);
7962742b5eSBen Skeggs }
8062742b5eSBen Skeggs
813647c53bSBen Skeggs static int
gk104_chan_ramfc_write(struct nvkm_chan * chan,u64 offset,u64 length,u32 devm,bool priv)823647c53bSBen Skeggs gk104_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
833647c53bSBen Skeggs {
843647c53bSBen Skeggs const u64 userd = nvkm_memory_addr(chan->userd.mem) + chan->userd.base;
853647c53bSBen Skeggs const u32 limit2 = ilog2(length / 8);
863647c53bSBen Skeggs
873647c53bSBen Skeggs nvkm_kmap(chan->inst);
883647c53bSBen Skeggs nvkm_wo32(chan->inst, 0x08, lower_32_bits(userd));
893647c53bSBen Skeggs nvkm_wo32(chan->inst, 0x0c, upper_32_bits(userd));
903647c53bSBen Skeggs nvkm_wo32(chan->inst, 0x10, 0x0000face);
913647c53bSBen Skeggs nvkm_wo32(chan->inst, 0x30, 0xfffff902);
923647c53bSBen Skeggs nvkm_wo32(chan->inst, 0x48, lower_32_bits(offset));
933647c53bSBen Skeggs nvkm_wo32(chan->inst, 0x4c, upper_32_bits(offset) | (limit2 << 16));
943647c53bSBen Skeggs nvkm_wo32(chan->inst, 0x84, 0x20400000);
953647c53bSBen Skeggs nvkm_wo32(chan->inst, 0x94, 0x30000000 | devm);
963647c53bSBen Skeggs nvkm_wo32(chan->inst, 0x9c, 0x00000100);
973647c53bSBen Skeggs nvkm_wo32(chan->inst, 0xac, 0x0000001f);
983647c53bSBen Skeggs nvkm_wo32(chan->inst, 0xe4, priv ? 0x00000020 : 0x00000000);
993647c53bSBen Skeggs nvkm_wo32(chan->inst, 0xe8, chan->id);
1003647c53bSBen Skeggs nvkm_wo32(chan->inst, 0xb8, 0xf8000000);
1013647c53bSBen Skeggs nvkm_wo32(chan->inst, 0xf8, 0x10003080); /* 0x002310 */
1023647c53bSBen Skeggs nvkm_wo32(chan->inst, 0xfc, 0x10000010); /* 0x002350 */
1033647c53bSBen Skeggs nvkm_done(chan->inst);
1043647c53bSBen Skeggs return 0;
1053647c53bSBen Skeggs }
1063647c53bSBen Skeggs
1073647c53bSBen Skeggs const struct nvkm_chan_func_ramfc
1083647c53bSBen Skeggs gk104_chan_ramfc = {
1093647c53bSBen Skeggs .write = gk104_chan_ramfc_write,
1103647c53bSBen Skeggs .devm = 0xfff,
1113647c53bSBen Skeggs .priv = true,
1123647c53bSBen Skeggs };
1133647c53bSBen Skeggs
114fbe9f433SBen Skeggs const struct nvkm_chan_func_userd
115fbe9f433SBen Skeggs gk104_chan_userd = {
116fbe9f433SBen Skeggs .bar = 1,
117fbe9f433SBen Skeggs .size = 0x200,
118fbe9f433SBen Skeggs .clear = gf100_chan_userd_clear,
119fbe9f433SBen Skeggs };
120fbe9f433SBen Skeggs
121f5e45689SBen Skeggs static const struct nvkm_chan_func
122f5e45689SBen Skeggs gk104_chan = {
123d3e7a439SBen Skeggs .inst = &gf100_chan_inst,
124fbe9f433SBen Skeggs .userd = &gk104_chan_userd,
1253647c53bSBen Skeggs .ramfc = &gk104_chan_ramfc,
12662742b5eSBen Skeggs .bind = gk104_chan_bind,
12762742b5eSBen Skeggs .unbind = gk104_chan_unbind,
12867059b9fSBen Skeggs .start = gk104_chan_start,
12967059b9fSBen Skeggs .stop = gk104_chan_stop,
130acff9415SBen Skeggs .preempt = gf100_chan_preempt,
131f5e45689SBen Skeggs };
132f5e45689SBen Skeggs
1338ab849d6SBen Skeggs static void
gk104_ectx_bind(struct nvkm_engn * engn,struct nvkm_cctx * cctx,struct nvkm_chan * chan)1348ab849d6SBen Skeggs gk104_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan)
1358ab849d6SBen Skeggs {
1368ab849d6SBen Skeggs u32 ptr0, ptr1 = 0;
1378ab849d6SBen Skeggs u64 addr = 0ULL;
1388ab849d6SBen Skeggs
1398ab849d6SBen Skeggs switch (engn->engine->subdev.type) {
1408ab849d6SBen Skeggs case NVKM_ENGINE_SW : return;
1418ab849d6SBen Skeggs case NVKM_ENGINE_GR : ptr0 = 0x0210; break;
1428ab849d6SBen Skeggs case NVKM_ENGINE_SEC : ptr0 = 0x0220; break;
1438ab849d6SBen Skeggs case NVKM_ENGINE_MSPDEC: ptr0 = 0x0250; break;
1448ab849d6SBen Skeggs case NVKM_ENGINE_MSPPP : ptr0 = 0x0260; break;
1458ab849d6SBen Skeggs case NVKM_ENGINE_MSVLD : ptr0 = 0x0270; break;
1468ab849d6SBen Skeggs case NVKM_ENGINE_VIC : ptr0 = 0x0280; break;
1478ab849d6SBen Skeggs case NVKM_ENGINE_MSENC : ptr0 = 0x0290; break;
1488ab849d6SBen Skeggs case NVKM_ENGINE_NVDEC :
1498ab849d6SBen Skeggs ptr1 = 0x0270;
1508ab849d6SBen Skeggs ptr0 = 0x0210;
1518ab849d6SBen Skeggs break;
1528ab849d6SBen Skeggs case NVKM_ENGINE_NVENC :
1538ab849d6SBen Skeggs if (!engn->engine->subdev.inst)
1548ab849d6SBen Skeggs ptr1 = 0x0290;
1558ab849d6SBen Skeggs ptr0 = 0x0210;
1568ab849d6SBen Skeggs break;
1578ab849d6SBen Skeggs default:
1588ab849d6SBen Skeggs WARN_ON(1);
1598ab849d6SBen Skeggs return;
1608ab849d6SBen Skeggs }
1618ab849d6SBen Skeggs
1628ab849d6SBen Skeggs if (cctx) {
1638ab849d6SBen Skeggs addr = cctx->vctx->vma->addr;
1648ab849d6SBen Skeggs addr |= 4ULL;
1658ab849d6SBen Skeggs }
1668ab849d6SBen Skeggs
1678ab849d6SBen Skeggs nvkm_kmap(chan->inst);
1688ab849d6SBen Skeggs nvkm_wo32(chan->inst, ptr0 + 0, lower_32_bits(addr));
1698ab849d6SBen Skeggs nvkm_wo32(chan->inst, ptr0 + 4, upper_32_bits(addr));
1708ab849d6SBen Skeggs if (ptr1) {
1718ab849d6SBen Skeggs nvkm_wo32(chan->inst, ptr1 + 0, lower_32_bits(addr));
1728ab849d6SBen Skeggs nvkm_wo32(chan->inst, ptr1 + 4, upper_32_bits(addr));
1738ab849d6SBen Skeggs }
1748ab849d6SBen Skeggs nvkm_done(chan->inst);
1758ab849d6SBen Skeggs }
1768ab849d6SBen Skeggs
1778ab849d6SBen Skeggs int
gk104_ectx_ctor(struct nvkm_engn * engn,struct nvkm_vctx * vctx)1788ab849d6SBen Skeggs gk104_ectx_ctor(struct nvkm_engn *engn, struct nvkm_vctx *vctx)
1798ab849d6SBen Skeggs {
1808ab849d6SBen Skeggs struct gf100_vmm_map_v0 args = { .priv = 1 };
1818ab849d6SBen Skeggs int ret;
1828ab849d6SBen Skeggs
1838ab849d6SBen Skeggs ret = nvkm_vmm_get(vctx->vmm, 12, vctx->inst->size, &vctx->vma);
1848ab849d6SBen Skeggs if (ret)
1858ab849d6SBen Skeggs return ret;
1868ab849d6SBen Skeggs
1878ab849d6SBen Skeggs return nvkm_memory_map(vctx->inst, 0, vctx->vmm, vctx->vma, &args, sizeof(args));
1888ab849d6SBen Skeggs }
1898ab849d6SBen Skeggs
1904d60100aSBen Skeggs /*TODO: clean this up */
1914d60100aSBen Skeggs struct gk104_engn_status {
1924d60100aSBen Skeggs bool busy;
1934d60100aSBen Skeggs bool faulted;
1944d60100aSBen Skeggs bool chsw;
1954d60100aSBen Skeggs bool save;
1964d60100aSBen Skeggs bool load;
1974d60100aSBen Skeggs struct {
1984d60100aSBen Skeggs bool tsg;
1994d60100aSBen Skeggs u32 id;
2004d60100aSBen Skeggs } prev, next, *chan;
2014d60100aSBen Skeggs };
2024d60100aSBen Skeggs
2034d60100aSBen Skeggs static void
gk104_engn_status(struct nvkm_engn * engn,struct gk104_engn_status * status)2044d60100aSBen Skeggs gk104_engn_status(struct nvkm_engn *engn, struct gk104_engn_status *status)
205b88917feSBen Skeggs {
2064d60100aSBen Skeggs u32 stat = nvkm_rd32(engn->runl->fifo->engine.subdev.device, 0x002640 + (engn->id * 0x08));
207b88917feSBen Skeggs
208b88917feSBen Skeggs status->busy = !!(stat & 0x80000000);
209b88917feSBen Skeggs status->faulted = !!(stat & 0x40000000);
210b88917feSBen Skeggs status->next.tsg = !!(stat & 0x10000000);
211b88917feSBen Skeggs status->next.id = (stat & 0x0fff0000) >> 16;
212b88917feSBen Skeggs status->chsw = !!(stat & 0x00008000);
213b88917feSBen Skeggs status->save = !!(stat & 0x00004000);
214b88917feSBen Skeggs status->load = !!(stat & 0x00002000);
215b88917feSBen Skeggs status->prev.tsg = !!(stat & 0x00001000);
216b88917feSBen Skeggs status->prev.id = (stat & 0x00000fff);
217ec5c6bdaSBen Skeggs status->chan = NULL;
218ec5c6bdaSBen Skeggs
219ec5c6bdaSBen Skeggs if (status->busy && status->chsw) {
220ec5c6bdaSBen Skeggs if (status->load && status->save) {
2214d60100aSBen Skeggs if (nvkm_engine_chsw_load(engn->engine))
222ec5c6bdaSBen Skeggs status->chan = &status->next;
223ec5c6bdaSBen Skeggs else
224ec5c6bdaSBen Skeggs status->chan = &status->prev;
225ec5c6bdaSBen Skeggs } else
226ec5c6bdaSBen Skeggs if (status->load) {
227ec5c6bdaSBen Skeggs status->chan = &status->next;
228ec5c6bdaSBen Skeggs } else {
229ec5c6bdaSBen Skeggs status->chan = &status->prev;
230ec5c6bdaSBen Skeggs }
231ec5c6bdaSBen Skeggs } else
232ec5c6bdaSBen Skeggs if (status->load) {
233ec5c6bdaSBen Skeggs status->chan = &status->prev;
234ec5c6bdaSBen Skeggs }
235b88917feSBen Skeggs
2364d60100aSBen Skeggs ENGN_DEBUG(engn, "%08x: busy %d faulted %d chsw %d save %d load %d %sid %d%s-> %sid %d%s",
2374d60100aSBen Skeggs stat, status->busy, status->faulted, status->chsw, status->save, status->load,
238b88917feSBen Skeggs status->prev.tsg ? "tsg" : "ch", status->prev.id,
239b88917feSBen Skeggs status->chan == &status->prev ? "*" : " ",
240b88917feSBen Skeggs status->next.tsg ? "tsg" : "ch", status->next.id,
241b88917feSBen Skeggs status->chan == &status->next ? "*" : " ");
242b88917feSBen Skeggs }
243b88917feSBen Skeggs
2444d60100aSBen Skeggs int
gk104_engn_cxid(struct nvkm_engn * engn,bool * cgid)2454d60100aSBen Skeggs gk104_engn_cxid(struct nvkm_engn *engn, bool *cgid)
2464d60100aSBen Skeggs {
2474d60100aSBen Skeggs struct gk104_engn_status status;
2484d60100aSBen Skeggs
2494d60100aSBen Skeggs gk104_engn_status(engn, &status);
2504d60100aSBen Skeggs if (status.chan) {
2514d60100aSBen Skeggs *cgid = status.chan->tsg;
2524d60100aSBen Skeggs return status.chan->id;
2534d60100aSBen Skeggs }
2544d60100aSBen Skeggs
2554d60100aSBen Skeggs return -ENODEV;
2564d60100aSBen Skeggs }
2574d60100aSBen Skeggs
2584d60100aSBen Skeggs bool
gk104_engn_chsw(struct nvkm_engn * engn)2594d60100aSBen Skeggs gk104_engn_chsw(struct nvkm_engn *engn)
2604d60100aSBen Skeggs {
2614d60100aSBen Skeggs struct gk104_engn_status status;
2624d60100aSBen Skeggs
2634d60100aSBen Skeggs gk104_engn_status(engn, &status);
2644d60100aSBen Skeggs if (status.busy && status.chsw)
2654d60100aSBen Skeggs return true;
2664d60100aSBen Skeggs
2674d60100aSBen Skeggs return false;
2684d60100aSBen Skeggs }
2694d60100aSBen Skeggs
270d94470e9SBen Skeggs const struct nvkm_engn_func
271d94470e9SBen Skeggs gk104_engn = {
2724d60100aSBen Skeggs .chsw = gk104_engn_chsw,
2734d60100aSBen Skeggs .cxid = gk104_engn_cxid,
2744d60100aSBen Skeggs .mmu_fault_trigger = gf100_engn_mmu_fault_trigger,
2754d60100aSBen Skeggs .mmu_fault_triggered = gf100_engn_mmu_fault_triggered,
2768ab849d6SBen Skeggs .ctor = gk104_ectx_ctor,
2778ab849d6SBen Skeggs .bind = gk104_ectx_bind,
278d94470e9SBen Skeggs };
279d94470e9SBen Skeggs
280d94470e9SBen Skeggs const struct nvkm_engn_func
281d94470e9SBen Skeggs gk104_engn_ce = {
2824d60100aSBen Skeggs .chsw = gk104_engn_chsw,
2834d60100aSBen Skeggs .cxid = gk104_engn_cxid,
2844d60100aSBen Skeggs .mmu_fault_trigger = gf100_engn_mmu_fault_trigger,
2854d60100aSBen Skeggs .mmu_fault_triggered = gf100_engn_mmu_fault_triggered,
286d94470e9SBen Skeggs };
287d94470e9SBen Skeggs
2884d60100aSBen Skeggs bool
gk104_runq_idle(struct nvkm_runq * runq)2894d60100aSBen Skeggs gk104_runq_idle(struct nvkm_runq *runq)
2904d60100aSBen Skeggs {
2914d60100aSBen Skeggs struct nvkm_device *device = runq->fifo->engine.subdev.device;
2924d60100aSBen Skeggs
2934d60100aSBen Skeggs return !(nvkm_rd32(device, 0x003080 + (runq->id * 4)) & 0x0000e000);
2944d60100aSBen Skeggs }
2954d60100aSBen Skeggs
296923f1ff5SBen Skeggs static const struct nvkm_bitfield
297923f1ff5SBen Skeggs gk104_runq_intr_1_names[] = {
298fd67738aSBen Skeggs { 0x00000001, "HCE_RE_ILLEGAL_OP" },
299fd67738aSBen Skeggs { 0x00000002, "HCE_RE_ALIGNB" },
300fd67738aSBen Skeggs { 0x00000004, "HCE_PRIV" },
301fd67738aSBen Skeggs { 0x00000008, "HCE_ILLEGAL_MTHD" },
302fd67738aSBen Skeggs { 0x00000010, "HCE_ILLEGAL_CLASS" },
303fd67738aSBen Skeggs {}
304fd67738aSBen Skeggs };
305fd67738aSBen Skeggs
306923f1ff5SBen Skeggs static bool
gk104_runq_intr_1(struct nvkm_runq * runq)307923f1ff5SBen Skeggs gk104_runq_intr_1(struct nvkm_runq *runq)
308fd67738aSBen Skeggs {
309923f1ff5SBen Skeggs struct nvkm_subdev *subdev = &runq->fifo->engine.subdev;
310fd67738aSBen Skeggs struct nvkm_device *device = subdev->device;
311923f1ff5SBen Skeggs u32 mask = nvkm_rd32(device, 0x04014c + (runq->id * 0x2000));
312923f1ff5SBen Skeggs u32 stat = nvkm_rd32(device, 0x040148 + (runq->id * 0x2000)) & mask;
313923f1ff5SBen Skeggs u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x2000)) & 0xfff;
314fd67738aSBen Skeggs char msg[128];
315fd67738aSBen Skeggs
3160b1bb129SBen Skeggs if (stat & 0x80000000) {
3170b1bb129SBen Skeggs if (runq->func->intr_1_ctxnotvalid &&
3180b1bb129SBen Skeggs runq->func->intr_1_ctxnotvalid(runq, chid))
3190b1bb129SBen Skeggs stat &= ~0x80000000;
3200b1bb129SBen Skeggs }
3210b1bb129SBen Skeggs
322fd67738aSBen Skeggs if (stat) {
323923f1ff5SBen Skeggs nvkm_snprintbf(msg, sizeof(msg), gk104_runq_intr_1_names, stat);
324fd67738aSBen Skeggs nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d %08x %08x\n",
325923f1ff5SBen Skeggs runq->id, stat, msg, chid,
326923f1ff5SBen Skeggs nvkm_rd32(device, 0x040150 + (runq->id * 0x2000)),
327923f1ff5SBen Skeggs nvkm_rd32(device, 0x040154 + (runq->id * 0x2000)));
328fd67738aSBen Skeggs }
329fd67738aSBen Skeggs
330923f1ff5SBen Skeggs nvkm_wr32(device, 0x040148 + (runq->id * 0x2000), stat);
331923f1ff5SBen Skeggs return true;
332fd67738aSBen Skeggs }
333fd67738aSBen Skeggs
334923f1ff5SBen Skeggs const struct nvkm_bitfield
335923f1ff5SBen Skeggs gk104_runq_intr_0_names[] = {
336fd67738aSBen Skeggs { 0x00000001, "MEMREQ" },
337fd67738aSBen Skeggs { 0x00000002, "MEMACK_TIMEOUT" },
338fd67738aSBen Skeggs { 0x00000004, "MEMACK_EXTRA" },
339fd67738aSBen Skeggs { 0x00000008, "MEMDAT_TIMEOUT" },
340fd67738aSBen Skeggs { 0x00000010, "MEMDAT_EXTRA" },
341fd67738aSBen Skeggs { 0x00000020, "MEMFLUSH" },
342fd67738aSBen Skeggs { 0x00000040, "MEMOP" },
343fd67738aSBen Skeggs { 0x00000080, "LBCONNECT" },
344fd67738aSBen Skeggs { 0x00000100, "LBREQ" },
345fd67738aSBen Skeggs { 0x00000200, "LBACK_TIMEOUT" },
346fd67738aSBen Skeggs { 0x00000400, "LBACK_EXTRA" },
347fd67738aSBen Skeggs { 0x00000800, "LBDAT_TIMEOUT" },
348fd67738aSBen Skeggs { 0x00001000, "LBDAT_EXTRA" },
349fd67738aSBen Skeggs { 0x00002000, "GPFIFO" },
350fd67738aSBen Skeggs { 0x00004000, "GPPTR" },
351fd67738aSBen Skeggs { 0x00008000, "GPENTRY" },
352fd67738aSBen Skeggs { 0x00010000, "GPCRC" },
353fd67738aSBen Skeggs { 0x00020000, "PBPTR" },
354fd67738aSBen Skeggs { 0x00040000, "PBENTRY" },
355fd67738aSBen Skeggs { 0x00080000, "PBCRC" },
356fd67738aSBen Skeggs { 0x00100000, "XBARCONNECT" },
357fd67738aSBen Skeggs { 0x00200000, "METHOD" },
358fd67738aSBen Skeggs { 0x00400000, "METHODCRC" },
359fd67738aSBen Skeggs { 0x00800000, "DEVICE" },
360fd67738aSBen Skeggs { 0x02000000, "SEMAPHORE" },
361fd67738aSBen Skeggs { 0x04000000, "ACQUIRE" },
362fd67738aSBen Skeggs { 0x08000000, "PRI" },
363fd67738aSBen Skeggs { 0x20000000, "NO_CTXSW_SEG" },
364fd67738aSBen Skeggs { 0x40000000, "PBSEG" },
365fd67738aSBen Skeggs { 0x80000000, "SIGNATURE" },
366fd67738aSBen Skeggs {}
367fd67738aSBen Skeggs };
368fd67738aSBen Skeggs
369923f1ff5SBen Skeggs bool
gk104_runq_intr(struct nvkm_runq * runq,struct nvkm_runl * null)370923f1ff5SBen Skeggs gk104_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null)
371923f1ff5SBen Skeggs {
372923f1ff5SBen Skeggs bool intr0 = gf100_runq_intr(runq, NULL);
373923f1ff5SBen Skeggs bool intr1 = gk104_runq_intr_1(runq);
374923f1ff5SBen Skeggs
375923f1ff5SBen Skeggs return intr0 || intr1;
376923f1ff5SBen Skeggs }
377923f1ff5SBen Skeggs
37887c86024SBen Skeggs void
gk104_runq_init(struct nvkm_runq * runq)37987c86024SBen Skeggs gk104_runq_init(struct nvkm_runq *runq)
38087c86024SBen Skeggs {
38187c86024SBen Skeggs struct nvkm_device *device = runq->fifo->engine.subdev.device;
38287c86024SBen Skeggs
38387c86024SBen Skeggs gf100_runq_init(runq);
38487c86024SBen Skeggs
38587c86024SBen Skeggs nvkm_wr32(device, 0x040148 + (runq->id * 0x2000), 0xffffffff); /* HCE.INTR */
38687c86024SBen Skeggs nvkm_wr32(device, 0x04014c + (runq->id * 0x2000), 0xffffffff); /* HCE.INTREN */
38787c86024SBen Skeggs }
38887c86024SBen Skeggs
389d94470e9SBen Skeggs static u32
gk104_runq_runm(struct nvkm_runq * runq)390d94470e9SBen Skeggs gk104_runq_runm(struct nvkm_runq *runq)
391d94470e9SBen Skeggs {
392d94470e9SBen Skeggs return nvkm_rd32(runq->fifo->engine.subdev.device, 0x002390 + (runq->id * 0x04));
393d94470e9SBen Skeggs }
394d94470e9SBen Skeggs
3951c488ba9SBen Skeggs const struct nvkm_runq_func
3961c488ba9SBen Skeggs gk104_runq = {
39787c86024SBen Skeggs .init = gk104_runq_init,
398923f1ff5SBen Skeggs .intr = gk104_runq_intr,
399923f1ff5SBen Skeggs .intr_0_names = gk104_runq_intr_0_names,
4004d60100aSBen Skeggs .idle = gk104_runq_idle,
4011c488ba9SBen Skeggs };
4021c488ba9SBen Skeggs
4033a6bc9c2SBen Skeggs void
gk104_runl_fault_clear(struct nvkm_runl * runl)4044d60100aSBen Skeggs gk104_runl_fault_clear(struct nvkm_runl *runl)
4054d60100aSBen Skeggs {
4064d60100aSBen Skeggs nvkm_wr32(runl->fifo->engine.subdev.device, 0x00262c, BIT(runl->id));
4074d60100aSBen Skeggs }
4084d60100aSBen Skeggs
4094d60100aSBen Skeggs void
gk104_runl_allow(struct nvkm_runl * runl,u32 engm)4103a6bc9c2SBen Skeggs gk104_runl_allow(struct nvkm_runl *runl, u32 engm)
4113a6bc9c2SBen Skeggs {
4123a6bc9c2SBen Skeggs nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, BIT(runl->id), 0x00000000);
4133a6bc9c2SBen Skeggs }
4143a6bc9c2SBen Skeggs
4153a6bc9c2SBen Skeggs void
gk104_runl_block(struct nvkm_runl * runl,u32 engm)4163a6bc9c2SBen Skeggs gk104_runl_block(struct nvkm_runl *runl, u32 engm)
4173a6bc9c2SBen Skeggs {
4183a6bc9c2SBen Skeggs nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, BIT(runl->id), BIT(runl->id));
4193a6bc9c2SBen Skeggs }
4203a6bc9c2SBen Skeggs
4214a492fd5SBen Skeggs bool
gk104_runl_pending(struct nvkm_runl * runl)4224a492fd5SBen Skeggs gk104_runl_pending(struct nvkm_runl *runl)
4234a492fd5SBen Skeggs {
4244a492fd5SBen Skeggs struct nvkm_device *device = runl->fifo->engine.subdev.device;
4254a492fd5SBen Skeggs
4264a492fd5SBen Skeggs return nvkm_rd32(device, 0x002284 + (runl->id * 0x08)) & 0x00100000;
4274a492fd5SBen Skeggs }
4284a492fd5SBen Skeggs
4299a65a38cSBen Skeggs void
gk104_runl_commit(struct nvkm_runl * runl,struct nvkm_memory * memory,u32 start,int count)430b084fff2SBen Skeggs gk104_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count)
431efa44c66SBen Skeggs {
432b084fff2SBen Skeggs struct nvkm_fifo *fifo = runl->fifo;
433b084fff2SBen Skeggs struct nvkm_device *device = fifo->engine.subdev.device;
434b084fff2SBen Skeggs u64 addr = nvkm_memory_addr(memory) + start;
435efa44c66SBen Skeggs int target;
436efa44c66SBen Skeggs
437b084fff2SBen Skeggs switch (nvkm_memory_target(memory)) {
438efa44c66SBen Skeggs case NVKM_MEM_TARGET_VRAM: target = 0; break;
439efa44c66SBen Skeggs case NVKM_MEM_TARGET_NCOH: target = 3; break;
440efa44c66SBen Skeggs default:
441efa44c66SBen Skeggs WARN_ON(1);
442efa44c66SBen Skeggs return;
443efa44c66SBen Skeggs }
444efa44c66SBen Skeggs
445b084fff2SBen Skeggs spin_lock_irq(&fifo->lock);
446b084fff2SBen Skeggs nvkm_wr32(device, 0x002270, (target << 28) | (addr >> 12));
447b084fff2SBen Skeggs nvkm_wr32(device, 0x002274, (runl->id << 20) | count);
448b084fff2SBen Skeggs spin_unlock_irq(&fifo->lock);
449efa44c66SBen Skeggs }
450efa44c66SBen Skeggs
451efa44c66SBen Skeggs void
gk104_runl_insert_chan(struct nvkm_chan * chan,struct nvkm_memory * memory,u64 offset)452b084fff2SBen Skeggs gk104_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset)
45305c7145dSBen Skeggs {
454b084fff2SBen Skeggs nvkm_wo32(memory, offset + 0, chan->id);
45566587083SBen Skeggs nvkm_wo32(memory, offset + 4, 0x00000000);
45666587083SBen Skeggs }
45766587083SBen Skeggs
458d94470e9SBen Skeggs static const struct nvkm_runl_func
459d94470e9SBen Skeggs gk104_runl = {
460b084fff2SBen Skeggs .size = 8,
461b084fff2SBen Skeggs .update = nv50_runl_update,
462b084fff2SBen Skeggs .insert_chan = gk104_runl_insert_chan,
463b084fff2SBen Skeggs .commit = gk104_runl_commit,
4644a492fd5SBen Skeggs .wait = nv50_runl_wait,
4654a492fd5SBen Skeggs .pending = gk104_runl_pending,
4663a6bc9c2SBen Skeggs .block = gk104_runl_block,
4673a6bc9c2SBen Skeggs .allow = gk104_runl_allow,
4684d60100aSBen Skeggs .fault_clear = gk104_runl_fault_clear,
469acff9415SBen Skeggs .preempt_pending = gf100_runl_preempt_pending,
470d94470e9SBen Skeggs };
471d94470e9SBen Skeggs
472e43c872cSBen Skeggs static const struct nvkm_enum
473e43c872cSBen Skeggs gk104_fifo_mmu_fault_engine[] = {
474fd67738aSBen Skeggs { 0x00, "GR", NULL, NVKM_ENGINE_GR },
475fd67738aSBen Skeggs { 0x01, "DISPLAY" },
476fd67738aSBen Skeggs { 0x02, "CAPTURE" },
477fd67738aSBen Skeggs { 0x03, "IFB", NULL, NVKM_ENGINE_IFB },
478fd67738aSBen Skeggs { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
479fd67738aSBen Skeggs { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
480fd67738aSBen Skeggs { 0x06, "SCHED" },
481e43c872cSBen Skeggs { 0x07, "HOST0" },
482e43c872cSBen Skeggs { 0x08, "HOST1" },
483e43c872cSBen Skeggs { 0x09, "HOST2" },
484e43c872cSBen Skeggs { 0x0a, "HOST3" },
485e43c872cSBen Skeggs { 0x0b, "HOST4" },
486e43c872cSBen Skeggs { 0x0c, "HOST5" },
487e43c872cSBen Skeggs { 0x0d, "HOST6" },
488e43c872cSBen Skeggs { 0x0e, "HOST7" },
489fd67738aSBen Skeggs { 0x0f, "HOSTSR" },
490fd67738aSBen Skeggs { 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD },
491fd67738aSBen Skeggs { 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP },
492fd67738aSBen Skeggs { 0x13, "PERF" },
493fd67738aSBen Skeggs { 0x14, "MSPDEC", NULL, NVKM_ENGINE_MSPDEC },
494fd67738aSBen Skeggs { 0x15, "CE0", NULL, NVKM_ENGINE_CE, 0 },
495fd67738aSBen Skeggs { 0x16, "CE1", NULL, NVKM_ENGINE_CE, 1 },
496fd67738aSBen Skeggs { 0x17, "PMU" },
497fd67738aSBen Skeggs { 0x18, "PTP" },
498fd67738aSBen Skeggs { 0x19, "MSENC", NULL, NVKM_ENGINE_MSENC },
499fd67738aSBen Skeggs { 0x1b, "CE2", NULL, NVKM_ENGINE_CE, 2 },
500fd67738aSBen Skeggs {}
501fd67738aSBen Skeggs };
502fd67738aSBen Skeggs
503fd67738aSBen Skeggs const struct nvkm_enum
504e43c872cSBen Skeggs gk104_fifo_mmu_fault_reason[] = {
505fd67738aSBen Skeggs { 0x00, "PDE" },
506fd67738aSBen Skeggs { 0x01, "PDE_SIZE" },
507fd67738aSBen Skeggs { 0x02, "PTE" },
508fd67738aSBen Skeggs { 0x03, "VA_LIMIT_VIOLATION" },
509fd67738aSBen Skeggs { 0x04, "UNBOUND_INST_BLOCK" },
510fd67738aSBen Skeggs { 0x05, "PRIV_VIOLATION" },
511fd67738aSBen Skeggs { 0x06, "RO_VIOLATION" },
512fd67738aSBen Skeggs { 0x07, "WO_VIOLATION" },
513fd67738aSBen Skeggs { 0x08, "PITCH_MASK_VIOLATION" },
514fd67738aSBen Skeggs { 0x09, "WORK_CREATION" },
515fd67738aSBen Skeggs { 0x0a, "UNSUPPORTED_APERTURE" },
516fd67738aSBen Skeggs { 0x0b, "COMPRESSION_FAILURE" },
517fd67738aSBen Skeggs { 0x0c, "UNSUPPORTED_KIND" },
518fd67738aSBen Skeggs { 0x0d, "REGION_VIOLATION" },
519fd67738aSBen Skeggs { 0x0e, "BOTH_PTES_VALID" },
520fd67738aSBen Skeggs { 0x0f, "INFO_TYPE_POISONED" },
521fd67738aSBen Skeggs {}
522fd67738aSBen Skeggs };
523fd67738aSBen Skeggs
524fd67738aSBen Skeggs const struct nvkm_enum
525e43c872cSBen Skeggs gk104_fifo_mmu_fault_hubclient[] = {
526fd67738aSBen Skeggs { 0x00, "VIP" },
527fd67738aSBen Skeggs { 0x01, "CE0" },
528fd67738aSBen Skeggs { 0x02, "CE1" },
529fd67738aSBen Skeggs { 0x03, "DNISO" },
530fd67738aSBen Skeggs { 0x04, "FE" },
531fd67738aSBen Skeggs { 0x05, "FECS" },
532fd67738aSBen Skeggs { 0x06, "HOST" },
533fd67738aSBen Skeggs { 0x07, "HOST_CPU" },
534fd67738aSBen Skeggs { 0x08, "HOST_CPU_NB" },
535fd67738aSBen Skeggs { 0x09, "ISO" },
536fd67738aSBen Skeggs { 0x0a, "MMU" },
537fd67738aSBen Skeggs { 0x0b, "MSPDEC" },
538fd67738aSBen Skeggs { 0x0c, "MSPPP" },
539fd67738aSBen Skeggs { 0x0d, "MSVLD" },
540fd67738aSBen Skeggs { 0x0e, "NISO" },
541fd67738aSBen Skeggs { 0x0f, "P2P" },
542fd67738aSBen Skeggs { 0x10, "PD" },
543fd67738aSBen Skeggs { 0x11, "PERF" },
544fd67738aSBen Skeggs { 0x12, "PMU" },
545fd67738aSBen Skeggs { 0x13, "RASTERTWOD" },
546fd67738aSBen Skeggs { 0x14, "SCC" },
547fd67738aSBen Skeggs { 0x15, "SCC_NB" },
548fd67738aSBen Skeggs { 0x16, "SEC" },
549fd67738aSBen Skeggs { 0x17, "SSYNC" },
550fd67738aSBen Skeggs { 0x18, "GR_CE" },
551fd67738aSBen Skeggs { 0x19, "CE2" },
552fd67738aSBen Skeggs { 0x1a, "XV" },
553fd67738aSBen Skeggs { 0x1b, "MMU_NB" },
554fd67738aSBen Skeggs { 0x1c, "MSENC" },
555fd67738aSBen Skeggs { 0x1d, "DFALCON" },
556fd67738aSBen Skeggs { 0x1e, "SKED" },
557fd67738aSBen Skeggs { 0x1f, "AFALCON" },
558fd67738aSBen Skeggs {}
559fd67738aSBen Skeggs };
560fd67738aSBen Skeggs
561fd67738aSBen Skeggs const struct nvkm_enum
562e43c872cSBen Skeggs gk104_fifo_mmu_fault_gpcclient[] = {
563fd67738aSBen Skeggs { 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
564fd67738aSBen Skeggs { 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
565fd67738aSBen Skeggs { 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
566fd67738aSBen Skeggs { 0x09, "L1_3" }, { 0x0a, "T1_3" }, { 0x0b, "PE_3" },
567fd67738aSBen Skeggs { 0x0c, "RAST" },
568fd67738aSBen Skeggs { 0x0d, "GCC" },
569fd67738aSBen Skeggs { 0x0e, "GPCCS" },
570fd67738aSBen Skeggs { 0x0f, "PROP_0" },
571fd67738aSBen Skeggs { 0x10, "PROP_1" },
572fd67738aSBen Skeggs { 0x11, "PROP_2" },
573fd67738aSBen Skeggs { 0x12, "PROP_3" },
574fd67738aSBen Skeggs { 0x13, "L1_4" }, { 0x14, "T1_4" }, { 0x15, "PE_4" },
575fd67738aSBen Skeggs { 0x16, "L1_5" }, { 0x17, "T1_5" }, { 0x18, "PE_5" },
576fd67738aSBen Skeggs { 0x19, "L1_6" }, { 0x1a, "T1_6" }, { 0x1b, "PE_6" },
577fd67738aSBen Skeggs { 0x1c, "L1_7" }, { 0x1d, "T1_7" }, { 0x1e, "PE_7" },
578fd67738aSBen Skeggs { 0x1f, "GPM" },
579fd67738aSBen Skeggs { 0x20, "LTP_UTLB_0" },
580fd67738aSBen Skeggs { 0x21, "LTP_UTLB_1" },
581fd67738aSBen Skeggs { 0x22, "LTP_UTLB_2" },
582fd67738aSBen Skeggs { 0x23, "LTP_UTLB_3" },
583fd67738aSBen Skeggs { 0x24, "GPC_RGG_UTLB" },
584fd67738aSBen Skeggs {}
585fd67738aSBen Skeggs };
586fd67738aSBen Skeggs
5879be9c606SBen Skeggs const struct nvkm_fifo_func_mmu_fault
5889be9c606SBen Skeggs gk104_fifo_mmu_fault = {
589e43c872cSBen Skeggs .recover = gf100_fifo_mmu_fault_recover,
590e43c872cSBen Skeggs .access = gf100_fifo_mmu_fault_access,
591e43c872cSBen Skeggs .engine = gk104_fifo_mmu_fault_engine,
592e43c872cSBen Skeggs .reason = gk104_fifo_mmu_fault_reason,
593e43c872cSBen Skeggs .hubclient = gk104_fifo_mmu_fault_hubclient,
594e43c872cSBen Skeggs .gpcclient = gk104_fifo_mmu_fault_gpcclient,
5959be9c606SBen Skeggs };
5969be9c606SBen Skeggs
59705c7145dSBen Skeggs static const struct nvkm_enum
5982fc71a05SBen Skeggs gk104_fifo_intr_bind_reason[] = {
59905c7145dSBen Skeggs { 0x01, "BIND_NOT_UNBOUND" },
60005c7145dSBen Skeggs { 0x02, "SNOOP_WITHOUT_BAR1" },
60105c7145dSBen Skeggs { 0x03, "UNBIND_WHILE_RUNNING" },
60205c7145dSBen Skeggs { 0x05, "INVALID_RUNLIST" },
60305c7145dSBen Skeggs { 0x06, "INVALID_CTX_TGT" },
60405c7145dSBen Skeggs { 0x0b, "UNBIND_WHILE_PARKED" },
60505c7145dSBen Skeggs {}
60605c7145dSBen Skeggs };
60705c7145dSBen Skeggs
608b8ab4b45SAlistair Popple void
gk104_fifo_intr_bind(struct nvkm_fifo * fifo)6092fc71a05SBen Skeggs gk104_fifo_intr_bind(struct nvkm_fifo *fifo)
61005c7145dSBen Skeggs {
6112fc71a05SBen Skeggs struct nvkm_subdev *subdev = &fifo->engine.subdev;
6122fc71a05SBen Skeggs u32 intr = nvkm_rd32(subdev->device, 0x00252c);
61305c7145dSBen Skeggs u32 code = intr & 0x000000ff;
6142fc71a05SBen Skeggs const struct nvkm_enum *en = nvkm_enum_find(gk104_fifo_intr_bind_reason, code);
61505c7145dSBen Skeggs
616e5c5e4f5SBen Skeggs nvkm_error(subdev, "BIND_ERROR %02x [%s]\n", code, en ? en->name : "");
61705c7145dSBen Skeggs }
61805c7145dSBen Skeggs
619b8ab4b45SAlistair Popple void
gk104_fifo_intr_chsw(struct nvkm_fifo * fifo)6202fc71a05SBen Skeggs gk104_fifo_intr_chsw(struct nvkm_fifo *fifo)
62105c7145dSBen Skeggs {
6222fc71a05SBen Skeggs struct nvkm_subdev *subdev = &fifo->engine.subdev;
623e5c5e4f5SBen Skeggs struct nvkm_device *device = subdev->device;
62487744403SBen Skeggs u32 stat = nvkm_rd32(device, 0x00256c);
6252fc71a05SBen Skeggs
626e5c5e4f5SBen Skeggs nvkm_error(subdev, "CHSW_ERROR %08x\n", stat);
62787744403SBen Skeggs nvkm_wr32(device, 0x00256c, stat);
62805c7145dSBen Skeggs }
62905c7145dSBen Skeggs
6302fc71a05SBen Skeggs static void
gk104_fifo_intr_dropped_fault(struct nvkm_fifo * fifo)6312fc71a05SBen Skeggs gk104_fifo_intr_dropped_fault(struct nvkm_fifo *fifo)
63205c7145dSBen Skeggs {
6332fc71a05SBen Skeggs struct nvkm_subdev *subdev = &fifo->engine.subdev;
6342fc71a05SBen Skeggs u32 stat = nvkm_rd32(subdev->device, 0x00259c);
6352fc71a05SBen Skeggs
636e5c5e4f5SBen Skeggs nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat);
63705c7145dSBen Skeggs }
63805c7145dSBen Skeggs
639b8ab4b45SAlistair Popple void
gk104_fifo_intr_runlist(struct nvkm_fifo * fifo)6404a492fd5SBen Skeggs gk104_fifo_intr_runlist(struct nvkm_fifo *fifo)
64105c7145dSBen Skeggs {
6424a492fd5SBen Skeggs struct nvkm_device *device = fifo->engine.subdev.device;
6434a492fd5SBen Skeggs struct nvkm_runl *runl;
64487744403SBen Skeggs u32 mask = nvkm_rd32(device, 0x002a00);
6454a492fd5SBen Skeggs
6464a492fd5SBen Skeggs nvkm_runl_foreach_cond(runl, fifo, mask & BIT(runl->id)) {
6474a492fd5SBen Skeggs nvkm_wr32(device, 0x002a00, BIT(runl->id));
64805c7145dSBen Skeggs }
64905c7145dSBen Skeggs }
65005c7145dSBen Skeggs
6512fc71a05SBen Skeggs irqreturn_t
gk104_fifo_intr(struct nvkm_inth * inth)6522fc71a05SBen Skeggs gk104_fifo_intr(struct nvkm_inth *inth)
65305c7145dSBen Skeggs {
6542fc71a05SBen Skeggs struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), engine.subdev.inth);
6552fc71a05SBen Skeggs struct nvkm_subdev *subdev = &fifo->engine.subdev;
65613de7f46SBen Skeggs struct nvkm_device *device = subdev->device;
65787744403SBen Skeggs u32 mask = nvkm_rd32(device, 0x002140);
65887744403SBen Skeggs u32 stat = nvkm_rd32(device, 0x002100) & mask;
65905c7145dSBen Skeggs
66005c7145dSBen Skeggs if (stat & 0x00000001) {
6616189f1b0SBen Skeggs gk104_fifo_intr_bind(fifo);
66287744403SBen Skeggs nvkm_wr32(device, 0x002100, 0x00000001);
66305c7145dSBen Skeggs stat &= ~0x00000001;
66405c7145dSBen Skeggs }
66505c7145dSBen Skeggs
66605c7145dSBen Skeggs if (stat & 0x00000010) {
667e5c5e4f5SBen Skeggs nvkm_error(subdev, "PIO_ERROR\n");
66887744403SBen Skeggs nvkm_wr32(device, 0x002100, 0x00000010);
66905c7145dSBen Skeggs stat &= ~0x00000010;
67005c7145dSBen Skeggs }
67105c7145dSBen Skeggs
67205c7145dSBen Skeggs if (stat & 0x00000100) {
6734d60100aSBen Skeggs gf100_fifo_intr_sched(fifo);
67487744403SBen Skeggs nvkm_wr32(device, 0x002100, 0x00000100);
67505c7145dSBen Skeggs stat &= ~0x00000100;
67605c7145dSBen Skeggs }
67705c7145dSBen Skeggs
67805c7145dSBen Skeggs if (stat & 0x00010000) {
6796189f1b0SBen Skeggs gk104_fifo_intr_chsw(fifo);
68087744403SBen Skeggs nvkm_wr32(device, 0x002100, 0x00010000);
68105c7145dSBen Skeggs stat &= ~0x00010000;
68205c7145dSBen Skeggs }
68305c7145dSBen Skeggs
68405c7145dSBen Skeggs if (stat & 0x00800000) {
685e5c5e4f5SBen Skeggs nvkm_error(subdev, "FB_FLUSH_TIMEOUT\n");
68687744403SBen Skeggs nvkm_wr32(device, 0x002100, 0x00800000);
68705c7145dSBen Skeggs stat &= ~0x00800000;
68805c7145dSBen Skeggs }
68905c7145dSBen Skeggs
69005c7145dSBen Skeggs if (stat & 0x01000000) {
691e5c5e4f5SBen Skeggs nvkm_error(subdev, "LB_ERROR\n");
69287744403SBen Skeggs nvkm_wr32(device, 0x002100, 0x01000000);
69305c7145dSBen Skeggs stat &= ~0x01000000;
69405c7145dSBen Skeggs }
69505c7145dSBen Skeggs
69605c7145dSBen Skeggs if (stat & 0x08000000) {
6976189f1b0SBen Skeggs gk104_fifo_intr_dropped_fault(fifo);
69887744403SBen Skeggs nvkm_wr32(device, 0x002100, 0x08000000);
69905c7145dSBen Skeggs stat &= ~0x08000000;
70005c7145dSBen Skeggs }
70105c7145dSBen Skeggs
70205c7145dSBen Skeggs if (stat & 0x10000000) {
703e43c872cSBen Skeggs gf100_fifo_intr_mmu_fault(fifo);
70405c7145dSBen Skeggs stat &= ~0x10000000;
70505c7145dSBen Skeggs }
70605c7145dSBen Skeggs
70705c7145dSBen Skeggs if (stat & 0x20000000) {
708923f1ff5SBen Skeggs if (gf100_fifo_intr_pbdma(fifo))
70905c7145dSBen Skeggs stat &= ~0x20000000;
71005c7145dSBen Skeggs }
71105c7145dSBen Skeggs
71205c7145dSBen Skeggs if (stat & 0x40000000) {
7134a492fd5SBen Skeggs gk104_fifo_intr_runlist(fifo);
71405c7145dSBen Skeggs stat &= ~0x40000000;
71505c7145dSBen Skeggs }
71605c7145dSBen Skeggs
71705c7145dSBen Skeggs if (stat & 0x80000000) {
71887744403SBen Skeggs nvkm_wr32(device, 0x002100, 0x80000000);
719d67f3b96SBen Skeggs nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT);
72005c7145dSBen Skeggs stat &= ~0x80000000;
72105c7145dSBen Skeggs }
72205c7145dSBen Skeggs
72305c7145dSBen Skeggs if (stat) {
724e5c5e4f5SBen Skeggs nvkm_error(subdev, "INTR %08x\n", stat);
725d67f3b96SBen Skeggs spin_lock(&fifo->lock);
72687744403SBen Skeggs nvkm_mask(device, 0x002140, stat, 0x00000000);
727d67f3b96SBen Skeggs spin_unlock(&fifo->lock);
72887744403SBen Skeggs nvkm_wr32(device, 0x002100, stat);
72905c7145dSBen Skeggs }
7302fc71a05SBen Skeggs
7312fc71a05SBen Skeggs return IRQ_HANDLED;
73205c7145dSBen Skeggs }
73305c7145dSBen Skeggs
734b8ab4b45SAlistair Popple void
gk104_fifo_init_pbdmas(struct nvkm_fifo * fifo,u32 mask)735965c41d9SBen Skeggs gk104_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask)
736965c41d9SBen Skeggs {
737965c41d9SBen Skeggs struct nvkm_device *device = fifo->engine.subdev.device;
738965c41d9SBen Skeggs
739965c41d9SBen Skeggs nvkm_wr32(device, 0x000204, mask);
740324176e7SBen Skeggs nvkm_mask(device, 0x002a04, 0xbfffffff, 0xbfffffff);
741965c41d9SBen Skeggs }
742965c41d9SBen Skeggs
743965c41d9SBen Skeggs void
gk104_fifo_init(struct nvkm_fifo * fifo)744fbe9f433SBen Skeggs gk104_fifo_init(struct nvkm_fifo *fifo)
745fd67738aSBen Skeggs {
746fbe9f433SBen Skeggs struct nvkm_device *device = fifo->engine.subdev.device;
747fd67738aSBen Skeggs
748fbe9f433SBen Skeggs if (fifo->func->chan.func->userd->bar == 1)
749fbe9f433SBen Skeggs nvkm_wr32(device, 0x002254, 0x10000000 | fifo->userd.bar1->addr >> 12);
750fd67738aSBen Skeggs
751fd67738aSBen Skeggs nvkm_wr32(device, 0x002100, 0xffffffff);
752fd67738aSBen Skeggs nvkm_wr32(device, 0x002140, 0x7fffffff);
753fd67738aSBen Skeggs }
754fd67738aSBen Skeggs
755fd67738aSBen Skeggs int
gk104_fifo_runl_ctor(struct nvkm_fifo * fifo)756d94470e9SBen Skeggs gk104_fifo_runl_ctor(struct nvkm_fifo *fifo)
757d94470e9SBen Skeggs {
758d94470e9SBen Skeggs struct nvkm_device *device = fifo->engine.subdev.device;
759d94470e9SBen Skeggs struct nvkm_top_device *tdev;
760d94470e9SBen Skeggs struct nvkm_runl *runl;
761d94470e9SBen Skeggs struct nvkm_runq *runq;
762d94470e9SBen Skeggs const struct nvkm_engn_func *func;
763d94470e9SBen Skeggs
764d94470e9SBen Skeggs nvkm_list_foreach(tdev, &device->top->device, head, tdev->runlist >= 0) {
765d94470e9SBen Skeggs runl = nvkm_runl_get(fifo, tdev->runlist, tdev->runlist);
766d94470e9SBen Skeggs if (!runl) {
767d94470e9SBen Skeggs runl = nvkm_runl_new(fifo, tdev->runlist, tdev->runlist, 0);
768d94470e9SBen Skeggs if (IS_ERR(runl))
769d94470e9SBen Skeggs return PTR_ERR(runl);
770d94470e9SBen Skeggs
771d94470e9SBen Skeggs nvkm_runq_foreach_cond(runq, fifo, gk104_runq_runm(runq) & BIT(runl->id)) {
772d94470e9SBen Skeggs if (WARN_ON(runl->runq_nr == ARRAY_SIZE(runl->runq)))
773d94470e9SBen Skeggs return -ENOMEM;
774d94470e9SBen Skeggs
775d94470e9SBen Skeggs runl->runq[runl->runq_nr++] = runq;
776d94470e9SBen Skeggs }
777d94470e9SBen Skeggs
778d94470e9SBen Skeggs }
779d94470e9SBen Skeggs
780d94470e9SBen Skeggs if (tdev->engine < 0)
781d94470e9SBen Skeggs continue;
782d94470e9SBen Skeggs
783d94470e9SBen Skeggs switch (tdev->type) {
784d94470e9SBen Skeggs case NVKM_ENGINE_CE:
785d94470e9SBen Skeggs func = fifo->func->engn_ce;
786d94470e9SBen Skeggs break;
787d94470e9SBen Skeggs case NVKM_ENGINE_GR:
788d94470e9SBen Skeggs nvkm_runl_add(runl, 15, &gf100_engn_sw, NVKM_ENGINE_SW, 0);
789d94470e9SBen Skeggs fallthrough;
790d94470e9SBen Skeggs default:
791d94470e9SBen Skeggs func = fifo->func->engn;
792d94470e9SBen Skeggs break;
793d94470e9SBen Skeggs }
794d94470e9SBen Skeggs
795d94470e9SBen Skeggs nvkm_runl_add(runl, tdev->engine, func, tdev->type, tdev->inst);
796d94470e9SBen Skeggs }
797d94470e9SBen Skeggs
798d94470e9SBen Skeggs return 0;
799d94470e9SBen Skeggs }
800d94470e9SBen Skeggs
801d94470e9SBen Skeggs int
gk104_fifo_chid_nr(struct nvkm_fifo * fifo)802fd67738aSBen Skeggs gk104_fifo_chid_nr(struct nvkm_fifo *fifo)
803fd67738aSBen Skeggs {
804fd67738aSBen Skeggs return 4096;
805fd67738aSBen Skeggs }
806fd67738aSBen Skeggs
8079be9c606SBen Skeggs static const struct nvkm_fifo_func
80898ac3f06SBen Skeggs gk104_fifo = {
8098c18138cSBen Skeggs .chid_nr = gk104_fifo_chid_nr,
810800ac1f8SBen Skeggs .chid_ctor = gf100_fifo_chid_ctor,
8111c488ba9SBen Skeggs .runq_nr = gf100_fifo_runq_nr,
812d94470e9SBen Skeggs .runl_ctor = gk104_fifo_runl_ctor,
8139be9c606SBen Skeggs .init = gk104_fifo_init,
814965c41d9SBen Skeggs .init_pbdmas = gk104_fifo_init_pbdmas,
8159be9c606SBen Skeggs .intr = gk104_fifo_intr,
8169be9c606SBen Skeggs .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit,
8174d60100aSBen Skeggs .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout,
8189be9c606SBen Skeggs .mmu_fault = &gk104_fifo_mmu_fault,
819d67f3b96SBen Skeggs .nonstall = &gf100_fifo_nonstall,
820d94470e9SBen Skeggs .runl = &gk104_runl,
8211c488ba9SBen Skeggs .runq = &gk104_runq,
822d94470e9SBen Skeggs .engn = &gk104_engn,
823d94470e9SBen Skeggs .engn_ce = &gk104_engn_ce,
824f5e45689SBen Skeggs .cgrp = {{ }, &nv04_cgrp },
825*06db7fdeSBen Skeggs .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk104_chan },
8268f0649b5SBen Skeggs };
8278f0649b5SBen Skeggs
82805c7145dSBen Skeggs int
gk104_fifo_new(struct nvkm_device * device,enum nvkm_subdev_type type,int inst,struct nvkm_fifo ** pfifo)829ab0db2bdSBen Skeggs gk104_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
830ab0db2bdSBen Skeggs struct nvkm_fifo **pfifo)
83105c7145dSBen Skeggs {
832*06db7fdeSBen Skeggs return nvkm_fifo_new_(&gk104_fifo, device, type, inst, pfifo);
83305c7145dSBen Skeggs }
834