xref: /openbmc/linux/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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  */
2406db7fdeSBen Skeggs #include "priv.h"
2562742b5eSBen 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>
32358ce601SBen Skeggs #include <subdev/bar.h>
33cf9518b5SBen Skeggs #include <subdev/fault.h>
342fc71a05SBen Skeggs #include <subdev/mc.h>
3506db7fdeSBen Skeggs #include <subdev/mmu.h>
3661570911SBen Skeggs #include <engine/sw.h>
3705c7145dSBen Skeggs 
3805c7145dSBen Skeggs #include <nvif/class.h>
3905c7145dSBen Skeggs 
40acff9415SBen Skeggs void
gf100_chan_preempt(struct nvkm_chan * chan)41acff9415SBen Skeggs gf100_chan_preempt(struct nvkm_chan *chan)
42acff9415SBen Skeggs {
43acff9415SBen Skeggs 	nvkm_wr32(chan->cgrp->runl->fifo->engine.subdev.device, 0x002634, chan->id);
44acff9415SBen Skeggs }
45acff9415SBen Skeggs 
4667059b9fSBen Skeggs static void
gf100_chan_stop(struct nvkm_chan * chan)4767059b9fSBen Skeggs gf100_chan_stop(struct nvkm_chan *chan)
4867059b9fSBen Skeggs {
4967059b9fSBen Skeggs 	struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
5067059b9fSBen Skeggs 
5167059b9fSBen Skeggs 	nvkm_mask(device, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000);
5267059b9fSBen Skeggs }
5367059b9fSBen Skeggs 
5467059b9fSBen Skeggs static void
gf100_chan_start(struct nvkm_chan * chan)5567059b9fSBen Skeggs gf100_chan_start(struct nvkm_chan *chan)
5667059b9fSBen Skeggs {
5767059b9fSBen Skeggs 	struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
5867059b9fSBen Skeggs 
5967059b9fSBen Skeggs 	nvkm_wr32(device, 0x003004 + (chan->id * 8), 0x001f0001);
6067059b9fSBen Skeggs }
6167059b9fSBen Skeggs 
6262742b5eSBen Skeggs static void gf100_fifo_intr_engine(struct nvkm_fifo *);
6362742b5eSBen Skeggs 
6462742b5eSBen Skeggs static void
gf100_chan_unbind(struct nvkm_chan * chan)6562742b5eSBen Skeggs gf100_chan_unbind(struct nvkm_chan *chan)
6662742b5eSBen Skeggs {
6762742b5eSBen Skeggs 	struct nvkm_fifo *fifo = chan->cgrp->runl->fifo;
6862742b5eSBen Skeggs 	struct nvkm_device *device = fifo->engine.subdev.device;
6962742b5eSBen Skeggs 
7062742b5eSBen Skeggs 	/*TODO: Is this cargo-culted, or necessary? RM does *something* here... Why? */
7162742b5eSBen Skeggs 	gf100_fifo_intr_engine(fifo);
7262742b5eSBen Skeggs 
7362742b5eSBen Skeggs 	nvkm_wr32(device, 0x003000 + (chan->id * 8), 0x00000000);
7462742b5eSBen Skeggs }
7562742b5eSBen Skeggs 
7662742b5eSBen Skeggs static void
gf100_chan_bind(struct nvkm_chan * chan)7762742b5eSBen Skeggs gf100_chan_bind(struct nvkm_chan *chan)
7862742b5eSBen Skeggs {
7962742b5eSBen Skeggs 	struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
8062742b5eSBen Skeggs 
8162742b5eSBen Skeggs 	nvkm_wr32(device, 0x003000 + (chan->id * 8), 0xc0000000 | chan->inst->addr >> 12);
8262742b5eSBen Skeggs }
8362742b5eSBen Skeggs 
843647c53bSBen Skeggs static int
gf100_chan_ramfc_write(struct nvkm_chan * chan,u64 offset,u64 length,u32 devm,bool priv)853647c53bSBen Skeggs gf100_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
863647c53bSBen Skeggs {
873647c53bSBen Skeggs 	const u64 userd = nvkm_memory_addr(chan->userd.mem) + chan->userd.base;
883647c53bSBen Skeggs 	const u32 limit2 = ilog2(length / 8);
893647c53bSBen Skeggs 
903647c53bSBen Skeggs 	nvkm_kmap(chan->inst);
913647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0x08, lower_32_bits(userd));
923647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0x0c, upper_32_bits(userd));
933647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0x10, 0x0000face);
943647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0x30, 0xfffff902);
953647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0x48, lower_32_bits(offset));
963647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0x4c, upper_32_bits(offset) | (limit2 << 16));
973647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0x54, 0x00000002);
983647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0x84, 0x20400000);
993647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0x94, 0x30000000 | devm);
1003647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0x9c, 0x00000100);
1013647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0xa4, 0x1f1f1f1f);
1023647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0xa8, 0x1f1f1f1f);
1033647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0xac, 0x0000001f);
1043647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0xb8, 0xf8000000);
1053647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0xf8, 0x10003080); /* 0x002310 */
1063647c53bSBen Skeggs 	nvkm_wo32(chan->inst, 0xfc, 0x10000010); /* 0x002350 */
1073647c53bSBen Skeggs 	nvkm_done(chan->inst);
1083647c53bSBen Skeggs 	return 0;
1093647c53bSBen Skeggs }
1103647c53bSBen Skeggs 
1113647c53bSBen Skeggs static const struct nvkm_chan_func_ramfc
1123647c53bSBen Skeggs gf100_chan_ramfc = {
1133647c53bSBen Skeggs 	.write = gf100_chan_ramfc_write,
1143647c53bSBen Skeggs 	.devm = 0xfff,
1153647c53bSBen Skeggs };
1163647c53bSBen Skeggs 
117fbe9f433SBen Skeggs void
gf100_chan_userd_clear(struct nvkm_chan * chan)118fbe9f433SBen Skeggs gf100_chan_userd_clear(struct nvkm_chan *chan)
119fbe9f433SBen Skeggs {
120fbe9f433SBen Skeggs 	nvkm_kmap(chan->userd.mem);
121fbe9f433SBen Skeggs 	nvkm_wo32(chan->userd.mem, chan->userd.base + 0x040, 0x00000000);
122fbe9f433SBen Skeggs 	nvkm_wo32(chan->userd.mem, chan->userd.base + 0x044, 0x00000000);
123fbe9f433SBen Skeggs 	nvkm_wo32(chan->userd.mem, chan->userd.base + 0x048, 0x00000000);
124fbe9f433SBen Skeggs 	nvkm_wo32(chan->userd.mem, chan->userd.base + 0x04c, 0x00000000);
125fbe9f433SBen Skeggs 	nvkm_wo32(chan->userd.mem, chan->userd.base + 0x050, 0x00000000);
126fbe9f433SBen Skeggs 	nvkm_wo32(chan->userd.mem, chan->userd.base + 0x058, 0x00000000);
127fbe9f433SBen Skeggs 	nvkm_wo32(chan->userd.mem, chan->userd.base + 0x05c, 0x00000000);
128fbe9f433SBen Skeggs 	nvkm_wo32(chan->userd.mem, chan->userd.base + 0x060, 0x00000000);
129fbe9f433SBen Skeggs 	nvkm_wo32(chan->userd.mem, chan->userd.base + 0x088, 0x00000000);
130fbe9f433SBen Skeggs 	nvkm_wo32(chan->userd.mem, chan->userd.base + 0x08c, 0x00000000);
131fbe9f433SBen Skeggs 	nvkm_done(chan->userd.mem);
132fbe9f433SBen Skeggs }
133fbe9f433SBen Skeggs 
134fbe9f433SBen Skeggs static const struct nvkm_chan_func_userd
135fbe9f433SBen Skeggs gf100_chan_userd = {
136fbe9f433SBen Skeggs 	.bar = 1,
137fbe9f433SBen Skeggs 	.size = 0x1000,
138fbe9f433SBen Skeggs 	.clear = gf100_chan_userd_clear,
139fbe9f433SBen Skeggs };
140fbe9f433SBen Skeggs 
141d3e7a439SBen Skeggs const struct nvkm_chan_func_inst
142d3e7a439SBen Skeggs gf100_chan_inst = {
143d3e7a439SBen Skeggs 	.size = 0x1000,
144d3e7a439SBen Skeggs 	.zero = true,
145d3e7a439SBen Skeggs 	.vmm = true,
146d3e7a439SBen Skeggs };
147d3e7a439SBen Skeggs 
148f5e45689SBen Skeggs static const struct nvkm_chan_func
149f5e45689SBen Skeggs gf100_chan = {
150d3e7a439SBen Skeggs 	.inst = &gf100_chan_inst,
151fbe9f433SBen Skeggs 	.userd = &gf100_chan_userd,
1523647c53bSBen Skeggs 	.ramfc = &gf100_chan_ramfc,
15362742b5eSBen Skeggs 	.bind = gf100_chan_bind,
15462742b5eSBen Skeggs 	.unbind = gf100_chan_unbind,
15567059b9fSBen Skeggs 	.start = gf100_chan_start,
15667059b9fSBen Skeggs 	.stop = gf100_chan_stop,
157acff9415SBen Skeggs 	.preempt = gf100_chan_preempt,
158f5e45689SBen Skeggs };
159f5e45689SBen Skeggs 
1608ab849d6SBen Skeggs static void
gf100_ectx_bind(struct nvkm_engn * engn,struct nvkm_cctx * cctx,struct nvkm_chan * chan)1618ab849d6SBen Skeggs gf100_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan)
1628ab849d6SBen Skeggs {
1638ab849d6SBen Skeggs 	u64 addr = 0ULL;
1648ab849d6SBen Skeggs 	u32 ptr0;
1658ab849d6SBen Skeggs 
1668ab849d6SBen Skeggs 	switch (engn->engine->subdev.type) {
1678ab849d6SBen Skeggs 	case NVKM_ENGINE_SW    : return;
1688ab849d6SBen Skeggs 	case NVKM_ENGINE_GR    : ptr0 = 0x0210; break;
1698ab849d6SBen Skeggs 	case NVKM_ENGINE_CE    : ptr0 = 0x0230 + (engn->engine->subdev.inst * 0x10); break;
1708ab849d6SBen Skeggs 	case NVKM_ENGINE_MSPDEC: ptr0 = 0x0250; break;
1718ab849d6SBen Skeggs 	case NVKM_ENGINE_MSPPP : ptr0 = 0x0260; break;
1728ab849d6SBen Skeggs 	case NVKM_ENGINE_MSVLD : ptr0 = 0x0270; break;
1738ab849d6SBen Skeggs 	default:
1748ab849d6SBen Skeggs 		WARN_ON(1);
1758ab849d6SBen Skeggs 		return;
1768ab849d6SBen Skeggs 	}
1778ab849d6SBen Skeggs 
1788ab849d6SBen Skeggs 	if (cctx) {
1798ab849d6SBen Skeggs 		addr  = cctx->vctx->vma->addr;
1808ab849d6SBen Skeggs 		addr |= 4ULL;
1818ab849d6SBen Skeggs 	}
1828ab849d6SBen Skeggs 
1838ab849d6SBen Skeggs 	nvkm_kmap(chan->inst);
1848ab849d6SBen Skeggs 	nvkm_wo32(chan->inst, ptr0 + 0, lower_32_bits(addr));
1858ab849d6SBen Skeggs 	nvkm_wo32(chan->inst, ptr0 + 4, upper_32_bits(addr));
1868ab849d6SBen Skeggs 	nvkm_done(chan->inst);
1878ab849d6SBen Skeggs }
1888ab849d6SBen Skeggs 
1898ab849d6SBen Skeggs static int
gf100_ectx_ctor(struct nvkm_engn * engn,struct nvkm_vctx * vctx)1908ab849d6SBen Skeggs gf100_ectx_ctor(struct nvkm_engn *engn, struct nvkm_vctx *vctx)
1918ab849d6SBen Skeggs {
1928ab849d6SBen Skeggs 	int ret;
1938ab849d6SBen Skeggs 
1948ab849d6SBen Skeggs 	ret = nvkm_vmm_get(vctx->vmm, 12, vctx->inst->size, &vctx->vma);
1958ab849d6SBen Skeggs 	if (ret)
1968ab849d6SBen Skeggs 		return ret;
1978ab849d6SBen Skeggs 
1988ab849d6SBen Skeggs 	return nvkm_memory_map(vctx->inst, 0, vctx->vmm, vctx->vma, NULL, 0);
1998ab849d6SBen Skeggs }
2008ab849d6SBen Skeggs 
2014d60100aSBen Skeggs bool
gf100_engn_mmu_fault_triggered(struct nvkm_engn * engn)2024d60100aSBen Skeggs gf100_engn_mmu_fault_triggered(struct nvkm_engn *engn)
2034d60100aSBen Skeggs {
2044d60100aSBen Skeggs 	struct nvkm_runl *runl = engn->runl;
2054d60100aSBen Skeggs 	struct nvkm_fifo *fifo = runl->fifo;
2064d60100aSBen Skeggs 	struct nvkm_device *device = fifo->engine.subdev.device;
2074d60100aSBen Skeggs 	u32 data = nvkm_rd32(device, 0x002a30 + (engn->id * 4));
2084d60100aSBen Skeggs 
2094d60100aSBen Skeggs 	ENGN_DEBUG(engn, "%08x: mmu fault triggered", data);
2104d60100aSBen Skeggs 	if (!(data & 0x00000100))
2114d60100aSBen Skeggs 		return false;
2124d60100aSBen Skeggs 
2134d60100aSBen Skeggs 	spin_lock(&fifo->lock);
2144d60100aSBen Skeggs 	nvkm_mask(device, 0x002a30 + (engn->id * 4), 0x00000100, 0x00000000);
2154d60100aSBen Skeggs 	if (atomic_dec_and_test(&runl->rc_triggered))
2164d60100aSBen Skeggs 		nvkm_mask(device, 0x002140, 0x00000100, 0x00000100);
2174d60100aSBen Skeggs 	spin_unlock(&fifo->lock);
2184d60100aSBen Skeggs 	return true;
2194d60100aSBen Skeggs }
2204d60100aSBen Skeggs 
2214d60100aSBen Skeggs void
gf100_engn_mmu_fault_trigger(struct nvkm_engn * engn)2224d60100aSBen Skeggs gf100_engn_mmu_fault_trigger(struct nvkm_engn *engn)
2234d60100aSBen Skeggs {
2244d60100aSBen Skeggs 	struct nvkm_runl *runl = engn->runl;
2254d60100aSBen Skeggs 	struct nvkm_fifo *fifo = runl->fifo;
2264d60100aSBen Skeggs 	struct nvkm_device *device = fifo->engine.subdev.device;
2274d60100aSBen Skeggs 
2284d60100aSBen Skeggs 	ENGN_DEBUG(engn, "triggering mmu fault on 0x%02x", engn->fault);
2294d60100aSBen Skeggs 	spin_lock(&fifo->lock);
2304d60100aSBen Skeggs 	if (atomic_inc_return(&runl->rc_triggered) == 1)
2314d60100aSBen Skeggs 		nvkm_mask(device, 0x002140, 0x00000100, 0x00000000);
2324d60100aSBen Skeggs 	nvkm_wr32(device, 0x002100, 0x00000100);
2334d60100aSBen Skeggs 	nvkm_wr32(device, 0x002a30 + (engn->id * 4), 0x00000100 | engn->fault);
2344d60100aSBen Skeggs 	spin_unlock(&fifo->lock);
2354d60100aSBen Skeggs }
2364d60100aSBen Skeggs 
2374d60100aSBen Skeggs /*TODO: clean all this up. */
2384d60100aSBen Skeggs struct gf100_engn_status {
2394d60100aSBen Skeggs 	bool busy;
2404d60100aSBen Skeggs 	bool save;
2414d60100aSBen Skeggs 	bool unk0;
2424d60100aSBen Skeggs 	bool unk1;
2434d60100aSBen Skeggs 	u8   chid;
2444d60100aSBen Skeggs };
2454d60100aSBen Skeggs 
2464d60100aSBen Skeggs static void
gf100_engn_status(struct nvkm_engn * engn,struct gf100_engn_status * status)2474d60100aSBen Skeggs gf100_engn_status(struct nvkm_engn *engn, struct gf100_engn_status *status)
2484d60100aSBen Skeggs {
2494d60100aSBen Skeggs 	u32 stat = nvkm_rd32(engn->engine->subdev.device, 0x002640 + (engn->id * 4));
2504d60100aSBen Skeggs 
2514d60100aSBen Skeggs 	status->busy = (stat & 0x10000000);
2524d60100aSBen Skeggs 	status->save = (stat & 0x00100000);
2534d60100aSBen Skeggs 	status->unk0 = (stat & 0x00004000);
2544d60100aSBen Skeggs 	status->unk1 = (stat & 0x00001000);
2554d60100aSBen Skeggs 	status->chid = (stat & 0x0000007f);
2564d60100aSBen Skeggs 
2574d60100aSBen Skeggs 	ENGN_DEBUG(engn, "%08x: busy %d save %d unk0 %d unk1 %d chid %d",
2584d60100aSBen Skeggs 		   stat, status->busy, status->save, status->unk0, status->unk1, status->chid);
2594d60100aSBen Skeggs }
2604d60100aSBen Skeggs 
2614d60100aSBen Skeggs static int
gf100_engn_cxid(struct nvkm_engn * engn,bool * cgid)2624d60100aSBen Skeggs gf100_engn_cxid(struct nvkm_engn *engn, bool *cgid)
2634d60100aSBen Skeggs {
2644d60100aSBen Skeggs 	struct gf100_engn_status status;
2654d60100aSBen Skeggs 
2664d60100aSBen Skeggs 	gf100_engn_status(engn, &status);
2674d60100aSBen Skeggs 	if (status.busy) {
2684d60100aSBen Skeggs 		*cgid = false;
2694d60100aSBen Skeggs 		return status.chid;
2704d60100aSBen Skeggs 	}
2714d60100aSBen Skeggs 
2724d60100aSBen Skeggs 	return -ENODEV;
2734d60100aSBen Skeggs }
2744d60100aSBen Skeggs 
2754d60100aSBen Skeggs static bool
gf100_engn_chsw(struct nvkm_engn * engn)2764d60100aSBen Skeggs gf100_engn_chsw(struct nvkm_engn *engn)
2774d60100aSBen Skeggs {
2784d60100aSBen Skeggs 	struct gf100_engn_status status;
2794d60100aSBen Skeggs 
2804d60100aSBen Skeggs 	gf100_engn_status(engn, &status);
2814d60100aSBen Skeggs 	if (status.busy && (status.unk0 || status.unk1))
2824d60100aSBen Skeggs 		return true;
2834d60100aSBen Skeggs 
2844d60100aSBen Skeggs 	return false;
2854d60100aSBen Skeggs }
2864d60100aSBen Skeggs 
287d94470e9SBen Skeggs static const struct nvkm_engn_func
288d94470e9SBen Skeggs gf100_engn = {
2894d60100aSBen Skeggs 	.chsw = gf100_engn_chsw,
2904d60100aSBen Skeggs 	.cxid = gf100_engn_cxid,
2914d60100aSBen Skeggs 	.mmu_fault_trigger = gf100_engn_mmu_fault_trigger,
2924d60100aSBen Skeggs 	.mmu_fault_triggered = gf100_engn_mmu_fault_triggered,
2938ab849d6SBen Skeggs 	.ctor = gf100_ectx_ctor,
2948ab849d6SBen Skeggs 	.bind = gf100_ectx_bind,
295d94470e9SBen Skeggs };
296d94470e9SBen Skeggs 
297d94470e9SBen Skeggs const struct nvkm_engn_func
298d94470e9SBen Skeggs gf100_engn_sw = {
299d94470e9SBen Skeggs };
300d94470e9SBen Skeggs 
301fd67738aSBen Skeggs static const struct nvkm_bitfield
302923f1ff5SBen Skeggs gf100_runq_intr_0_names[] = {
303fd67738aSBen Skeggs /*	{ 0x00008000, "" }	seen with null ib push */
304fd67738aSBen Skeggs 	{ 0x00200000, "ILLEGAL_MTHD" },
305fd67738aSBen Skeggs 	{ 0x00800000, "EMPTY_SUBC" },
306fd67738aSBen Skeggs 	{}
307fd67738aSBen Skeggs };
308fd67738aSBen Skeggs 
309923f1ff5SBen Skeggs bool
gf100_runq_intr(struct nvkm_runq * runq,struct nvkm_runl * null)310923f1ff5SBen Skeggs gf100_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null)
311fd67738aSBen Skeggs {
312923f1ff5SBen Skeggs 	struct nvkm_subdev *subdev = &runq->fifo->engine.subdev;
313fd67738aSBen Skeggs 	struct nvkm_device *device = subdev->device;
314923f1ff5SBen Skeggs 	u32 mask = nvkm_rd32(device, 0x04010c + (runq->id * 0x2000));
315923f1ff5SBen Skeggs 	u32 stat = nvkm_rd32(device, 0x040108 + (runq->id * 0x2000)) & mask;
316923f1ff5SBen Skeggs 	u32 addr = nvkm_rd32(device, 0x0400c0 + (runq->id * 0x2000));
317923f1ff5SBen Skeggs 	u32 data = nvkm_rd32(device, 0x0400c4 + (runq->id * 0x2000));
318923f1ff5SBen Skeggs 	u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x2000)) & runq->fifo->chid->mask;
319fd67738aSBen Skeggs 	u32 subc = (addr & 0x00070000) >> 16;
320fd67738aSBen Skeggs 	u32 mthd = (addr & 0x00003ffc);
321fd67738aSBen Skeggs 	u32 show = stat;
322923f1ff5SBen Skeggs 	struct nvkm_chan *chan;
323923f1ff5SBen Skeggs 	unsigned long flags;
324fd67738aSBen Skeggs 	char msg[128];
325fd67738aSBen Skeggs 
326fd67738aSBen Skeggs 	if (stat & 0x00800000) {
327fd67738aSBen Skeggs 		if (device->sw) {
328fd67738aSBen Skeggs 			if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data))
329fd67738aSBen Skeggs 				show &= ~0x00800000;
330fd67738aSBen Skeggs 		}
331fd67738aSBen Skeggs 	}
332fd67738aSBen Skeggs 
333fd67738aSBen Skeggs 	if (show) {
334923f1ff5SBen Skeggs 		nvkm_snprintbf(msg, sizeof(msg), runq->func->intr_0_names, show);
335c358f538SBen Skeggs 		chan = nvkm_chan_get_chid(&runq->fifo->engine, chid, &flags);
336fd67738aSBen Skeggs 		nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
337fd67738aSBen Skeggs 				   "subc %d mthd %04x data %08x\n",
338923f1ff5SBen Skeggs 			   runq->id, show, msg, chid, chan ? chan->inst->addr : 0,
339520db040SBen Skeggs 			   chan ? chan->name : "unknown", subc, mthd, data);
3404d60100aSBen Skeggs 
3414d60100aSBen Skeggs 		/*TODO: use proper procedure for clearing each exception / debug output */
342520db040SBen Skeggs 		if ((stat & 0xc67fe000) && chan)
343520db040SBen Skeggs 			nvkm_chan_error(chan, true);
344c358f538SBen Skeggs 		nvkm_chan_put(&chan, flags);
345fd67738aSBen Skeggs 	}
346fd67738aSBen Skeggs 
347923f1ff5SBen Skeggs 	nvkm_wr32(device, 0x0400c0 + (runq->id * 0x2000), 0x80600008);
348923f1ff5SBen Skeggs 	nvkm_wr32(device, 0x040108 + (runq->id * 0x2000), stat);
349923f1ff5SBen Skeggs 	return true;
350fd67738aSBen Skeggs }
351fd67738aSBen Skeggs 
35287c86024SBen Skeggs void
gf100_runq_init(struct nvkm_runq * runq)35387c86024SBen Skeggs gf100_runq_init(struct nvkm_runq *runq)
35487c86024SBen Skeggs {
35587c86024SBen Skeggs 	struct nvkm_device *device = runq->fifo->engine.subdev.device;
35687c86024SBen Skeggs 
35787c86024SBen Skeggs 	nvkm_mask(device, 0x04013c + (runq->id * 0x2000), 0x10000100, 0x00000000);
35887c86024SBen Skeggs 	nvkm_wr32(device, 0x040108 + (runq->id * 0x2000), 0xffffffff); /* INTR */
35987c86024SBen Skeggs 	nvkm_wr32(device, 0x04010c + (runq->id * 0x2000), 0xfffffeff); /* INTREN */
36087c86024SBen Skeggs }
36187c86024SBen Skeggs 
3621c488ba9SBen Skeggs static const struct nvkm_runq_func
3631c488ba9SBen Skeggs gf100_runq = {
36487c86024SBen Skeggs 	.init = gf100_runq_init,
365923f1ff5SBen Skeggs 	.intr = gf100_runq_intr,
366923f1ff5SBen Skeggs 	.intr_0_names = gf100_runq_intr_0_names,
3671c488ba9SBen Skeggs };
3681c488ba9SBen Skeggs 
369acff9415SBen Skeggs bool
gf100_runl_preempt_pending(struct nvkm_runl * runl)370acff9415SBen Skeggs gf100_runl_preempt_pending(struct nvkm_runl *runl)
371acff9415SBen Skeggs {
372acff9415SBen Skeggs 	return nvkm_rd32(runl->fifo->engine.subdev.device, 0x002634) & 0x00100000;
373acff9415SBen Skeggs }
374acff9415SBen Skeggs 
3753a6bc9c2SBen Skeggs static void
gf100_runl_fault_clear(struct nvkm_runl * runl)3764d60100aSBen Skeggs gf100_runl_fault_clear(struct nvkm_runl *runl)
3774d60100aSBen Skeggs {
3784d60100aSBen Skeggs 	nvkm_mask(runl->fifo->engine.subdev.device, 0x00262c, 0x00000000, 0x00000000);
3794d60100aSBen Skeggs }
3804d60100aSBen Skeggs 
3814d60100aSBen Skeggs static void
gf100_runl_allow(struct nvkm_runl * runl,u32 engm)3823a6bc9c2SBen Skeggs gf100_runl_allow(struct nvkm_runl *runl, u32 engm)
3833a6bc9c2SBen Skeggs {
3843a6bc9c2SBen Skeggs 	nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, engm, 0x00000000);
3853a6bc9c2SBen Skeggs }
3863a6bc9c2SBen Skeggs 
3873a6bc9c2SBen Skeggs static void
gf100_runl_block(struct nvkm_runl * runl,u32 engm)3883a6bc9c2SBen Skeggs gf100_runl_block(struct nvkm_runl *runl, u32 engm)
3893a6bc9c2SBen Skeggs {
3903a6bc9c2SBen Skeggs 	nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, engm, engm);
3913a6bc9c2SBen Skeggs }
3923a6bc9c2SBen Skeggs 
3934a492fd5SBen Skeggs static bool
gf100_runl_pending(struct nvkm_runl * runl)3944a492fd5SBen Skeggs gf100_runl_pending(struct nvkm_runl *runl)
3954a492fd5SBen Skeggs {
3964a492fd5SBen Skeggs 	return nvkm_rd32(runl->fifo->engine.subdev.device, 0x00227c) & 0x00100000;
3974a492fd5SBen Skeggs }
3984a492fd5SBen Skeggs 
399b084fff2SBen Skeggs static void
gf100_runl_commit(struct nvkm_runl * runl,struct nvkm_memory * memory,u32 start,int count)400b084fff2SBen Skeggs gf100_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count)
40105c7145dSBen Skeggs {
402b084fff2SBen Skeggs 	struct nvkm_device *device = runl->fifo->engine.subdev.device;
403b084fff2SBen Skeggs 	u64 addr = nvkm_memory_addr(memory) + start;
404c694ecadSAlexandre Courbot 	int target;
40505c7145dSBen Skeggs 
406b084fff2SBen Skeggs 	switch (nvkm_memory_target(memory)) {
407d2ee3605SBen Skeggs 	case NVKM_MEM_TARGET_VRAM: target = 0; break;
408d2ee3605SBen Skeggs 	case NVKM_MEM_TARGET_NCOH: target = 3; break;
409d2ee3605SBen Skeggs 	default:
410d2ee3605SBen Skeggs 		WARN_ON(1);
411d2ee3605SBen Skeggs 		return;
412d2ee3605SBen Skeggs 	}
413c694ecadSAlexandre Courbot 
414b084fff2SBen Skeggs 	nvkm_wr32(device, 0x002270, (target << 28) | (addr >> 12));
415b084fff2SBen Skeggs 	nvkm_wr32(device, 0x002274, 0x01f00000 | count);
41605c7145dSBen Skeggs }
41705c7145dSBen Skeggs 
418b084fff2SBen Skeggs static void
gf100_runl_insert_chan(struct nvkm_chan * chan,struct nvkm_memory * memory,u64 offset)419b084fff2SBen Skeggs gf100_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset)
420d40d0fd4SBen Skeggs {
421b084fff2SBen Skeggs 	nvkm_wo32(memory, offset + 0, chan->id);
422b084fff2SBen Skeggs 	nvkm_wo32(memory, offset + 4, 0x00000004);
423d40d0fd4SBen Skeggs }
424d40d0fd4SBen Skeggs 
425d94470e9SBen Skeggs static const struct nvkm_runl_func
426d94470e9SBen Skeggs gf100_runl = {
427b084fff2SBen Skeggs 	.size = 8,
428b084fff2SBen Skeggs 	.update = nv50_runl_update,
429b084fff2SBen Skeggs 	.insert_chan = gf100_runl_insert_chan,
430b084fff2SBen Skeggs 	.commit = gf100_runl_commit,
4314a492fd5SBen Skeggs 	.wait = nv50_runl_wait,
4324a492fd5SBen Skeggs 	.pending = gf100_runl_pending,
4333a6bc9c2SBen Skeggs 	.block = gf100_runl_block,
4343a6bc9c2SBen Skeggs 	.allow = gf100_runl_allow,
4354d60100aSBen Skeggs 	.fault_clear = gf100_runl_fault_clear,
436acff9415SBen Skeggs 	.preempt_pending = gf100_runl_preempt_pending,
437d94470e9SBen Skeggs };
438d94470e9SBen Skeggs 
439d67f3b96SBen Skeggs static void
gf100_fifo_nonstall_allow(struct nvkm_event * event,int type,int index)440d67f3b96SBen Skeggs gf100_fifo_nonstall_allow(struct nvkm_event *event, int type, int index)
441d67f3b96SBen Skeggs {
442d67f3b96SBen Skeggs 	struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event);
443d67f3b96SBen Skeggs 	unsigned long flags;
444d67f3b96SBen Skeggs 
445d67f3b96SBen Skeggs 	spin_lock_irqsave(&fifo->lock, flags);
446d67f3b96SBen Skeggs 	nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x80000000, 0x80000000);
447d67f3b96SBen Skeggs 	spin_unlock_irqrestore(&fifo->lock, flags);
448d67f3b96SBen Skeggs }
449d67f3b96SBen Skeggs 
450*abe3c66fSTom Rix static void
gf100_fifo_nonstall_block(struct nvkm_event * event,int type,int index)451d67f3b96SBen Skeggs gf100_fifo_nonstall_block(struct nvkm_event *event, int type, int index)
452d67f3b96SBen Skeggs {
453d67f3b96SBen Skeggs 	struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event);
454d67f3b96SBen Skeggs 	unsigned long flags;
455d67f3b96SBen Skeggs 
456d67f3b96SBen Skeggs 	spin_lock_irqsave(&fifo->lock, flags);
457d67f3b96SBen Skeggs 	nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x80000000, 0x00000000);
458d67f3b96SBen Skeggs 	spin_unlock_irqrestore(&fifo->lock, flags);
459d67f3b96SBen Skeggs }
460d67f3b96SBen Skeggs 
461d67f3b96SBen Skeggs const struct nvkm_event_func
462d67f3b96SBen Skeggs gf100_fifo_nonstall = {
463d67f3b96SBen Skeggs 	.init = gf100_fifo_nonstall_allow,
464d67f3b96SBen Skeggs 	.fini = gf100_fifo_nonstall_block,
465d67f3b96SBen Skeggs };
466d67f3b96SBen Skeggs 
46705c7145dSBen Skeggs static const struct nvkm_enum
468e43c872cSBen Skeggs gf100_fifo_mmu_fault_engine[] = {
469cf9518b5SBen Skeggs 	{ 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR },
470cf9518b5SBen Skeggs 	{ 0x03, "PEEPHOLE", NULL, NVKM_ENGINE_IFB },
471cf9518b5SBen Skeggs 	{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
472cf9518b5SBen Skeggs 	{ 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM },
4734d60100aSBen Skeggs 	{ 0x07, "PFIFO" },
474cf9518b5SBen Skeggs 	{ 0x10, "PMSVLD", NULL, NVKM_ENGINE_MSVLD },
475cf9518b5SBen Skeggs 	{ 0x11, "PMSPPP", NULL, NVKM_ENGINE_MSPPP },
476cf9518b5SBen Skeggs 	{ 0x13, "PCOUNTER" },
477cf9518b5SBen Skeggs 	{ 0x14, "PMSPDEC", NULL, NVKM_ENGINE_MSPDEC },
478088bfe43SBen Skeggs 	{ 0x15, "PCE0", NULL, NVKM_ENGINE_CE, 0 },
479088bfe43SBen Skeggs 	{ 0x16, "PCE1", NULL, NVKM_ENGINE_CE, 1 },
480cf9518b5SBen Skeggs 	{ 0x17, "PMU" },
481cf9518b5SBen Skeggs 	{}
482cf9518b5SBen Skeggs };
483cf9518b5SBen Skeggs 
484cf9518b5SBen Skeggs static const struct nvkm_enum
485e43c872cSBen Skeggs gf100_fifo_mmu_fault_reason[] = {
486cf9518b5SBen Skeggs 	{ 0x00, "PT_NOT_PRESENT" },
487cf9518b5SBen Skeggs 	{ 0x01, "PT_TOO_SHORT" },
488cf9518b5SBen Skeggs 	{ 0x02, "PAGE_NOT_PRESENT" },
489cf9518b5SBen Skeggs 	{ 0x03, "VM_LIMIT_EXCEEDED" },
490cf9518b5SBen Skeggs 	{ 0x04, "NO_CHANNEL" },
491cf9518b5SBen Skeggs 	{ 0x05, "PAGE_SYSTEM_ONLY" },
492cf9518b5SBen Skeggs 	{ 0x06, "PAGE_READ_ONLY" },
493cf9518b5SBen Skeggs 	{ 0x0a, "COMPRESSED_SYSRAM" },
494cf9518b5SBen Skeggs 	{ 0x0c, "INVALID_STORAGE_TYPE" },
495cf9518b5SBen Skeggs 	{}
496cf9518b5SBen Skeggs };
497cf9518b5SBen Skeggs 
498cf9518b5SBen Skeggs static const struct nvkm_enum
499e43c872cSBen Skeggs gf100_fifo_mmu_fault_hubclient[] = {
500cf9518b5SBen Skeggs 	{ 0x01, "PCOPY0" },
501cf9518b5SBen Skeggs 	{ 0x02, "PCOPY1" },
502cf9518b5SBen Skeggs 	{ 0x04, "DISPATCH" },
503cf9518b5SBen Skeggs 	{ 0x05, "CTXCTL" },
504cf9518b5SBen Skeggs 	{ 0x06, "PFIFO" },
505cf9518b5SBen Skeggs 	{ 0x07, "BAR_READ" },
506cf9518b5SBen Skeggs 	{ 0x08, "BAR_WRITE" },
507cf9518b5SBen Skeggs 	{ 0x0b, "PVP" },
508cf9518b5SBen Skeggs 	{ 0x0c, "PMSPPP" },
509cf9518b5SBen Skeggs 	{ 0x0d, "PMSVLD" },
510cf9518b5SBen Skeggs 	{ 0x11, "PCOUNTER" },
511cf9518b5SBen Skeggs 	{ 0x12, "PMU" },
512cf9518b5SBen Skeggs 	{ 0x14, "CCACHE" },
513cf9518b5SBen Skeggs 	{ 0x15, "CCACHE_POST" },
514cf9518b5SBen Skeggs 	{}
515cf9518b5SBen Skeggs };
516cf9518b5SBen Skeggs 
517cf9518b5SBen Skeggs static const struct nvkm_enum
518e43c872cSBen Skeggs gf100_fifo_mmu_fault_gpcclient[] = {
519cf9518b5SBen Skeggs 	{ 0x01, "TEX" },
520cf9518b5SBen Skeggs 	{ 0x0c, "ESETUP" },
521cf9518b5SBen Skeggs 	{ 0x0e, "CTXCTL" },
522cf9518b5SBen Skeggs 	{ 0x0f, "PROP" },
523cf9518b5SBen Skeggs 	{}
524cf9518b5SBen Skeggs };
525cf9518b5SBen Skeggs 
526e43c872cSBen Skeggs const struct nvkm_enum
527e43c872cSBen Skeggs gf100_fifo_mmu_fault_access[] = {
528e43c872cSBen Skeggs 	{ 0x00, "READ" },
529e43c872cSBen Skeggs 	{ 0x01, "WRITE" },
530e43c872cSBen Skeggs 	{}
531e43c872cSBen Skeggs };
532e43c872cSBen Skeggs 
533e43c872cSBen Skeggs void
gf100_fifo_mmu_fault_recover(struct nvkm_fifo * fifo,struct nvkm_fault_data * info)534e43c872cSBen Skeggs gf100_fifo_mmu_fault_recover(struct nvkm_fifo *fifo, struct nvkm_fault_data *info)
535cf9518b5SBen Skeggs {
536e43c872cSBen Skeggs 	struct nvkm_subdev *subdev = &fifo->engine.subdev;
537cf9518b5SBen Skeggs 	struct nvkm_device *device = subdev->device;
538e43c872cSBen Skeggs 	const struct nvkm_enum *er, *ee, *ec, *ea;
539cf9518b5SBen Skeggs 	struct nvkm_engine *engine = NULL;
540e43c872cSBen Skeggs 	struct nvkm_runl *runl;
541e43c872cSBen Skeggs 	struct nvkm_engn *engn;
542c358f538SBen Skeggs 	struct nvkm_chan *chan;
543cf9518b5SBen Skeggs 	unsigned long flags;
544e43c872cSBen Skeggs 	char ct[8] = "HUB/";
545cf9518b5SBen Skeggs 
546e43c872cSBen Skeggs 	/* Lookup engine by MMU fault ID. */
547e43c872cSBen Skeggs 	nvkm_runl_foreach(runl, fifo) {
548e43c872cSBen Skeggs 		engn = nvkm_runl_find_engn(engn, runl, engn->fault == info->engine);
549e43c872cSBen Skeggs 		if (engn) {
5504d60100aSBen Skeggs 			/* Fault triggered by CTXSW_TIMEOUT recovery procedure. */
5514d60100aSBen Skeggs 			if (engn->func->mmu_fault_triggered &&
5524d60100aSBen Skeggs 			    engn->func->mmu_fault_triggered(engn)) {
5534d60100aSBen Skeggs 				nvkm_runl_rc_engn(runl, engn);
5544d60100aSBen Skeggs 				return;
5554d60100aSBen Skeggs 			}
5564d60100aSBen Skeggs 
557e43c872cSBen Skeggs 			engine = engn->engine;
558e43c872cSBen Skeggs 			break;
559e43c872cSBen Skeggs 		}
560cf9518b5SBen Skeggs 	}
561cf9518b5SBen Skeggs 
562e43c872cSBen Skeggs 	er = nvkm_enum_find(fifo->func->mmu_fault->reason, info->reason);
563e43c872cSBen Skeggs 	ee = nvkm_enum_find(fifo->func->mmu_fault->engine, info->engine);
564e43c872cSBen Skeggs 	if (info->hub) {
565e43c872cSBen Skeggs 		ec = nvkm_enum_find(fifo->func->mmu_fault->hubclient, info->client);
566e43c872cSBen Skeggs 	} else {
567e43c872cSBen Skeggs 		ec = nvkm_enum_find(fifo->func->mmu_fault->gpcclient, info->client);
568e43c872cSBen Skeggs 		snprintf(ct, sizeof(ct), "GPC%d/", info->gpc);
569e43c872cSBen Skeggs 	}
570e43c872cSBen Skeggs 	ea = nvkm_enum_find(fifo->func->mmu_fault->access, info->access);
571e43c872cSBen Skeggs 
572e43c872cSBen Skeggs 	/* Handle BAR faults. */
573e43c872cSBen Skeggs 	if (ee && ee->data2) {
574e43c872cSBen Skeggs 		switch (ee->data2) {
575cf9518b5SBen Skeggs 		case NVKM_SUBDEV_BAR:
576cf9518b5SBen Skeggs 			nvkm_bar_bar1_reset(device);
577cf9518b5SBen Skeggs 			break;
578cf9518b5SBen Skeggs 		case NVKM_SUBDEV_INSTMEM:
579cf9518b5SBen Skeggs 			nvkm_bar_bar2_reset(device);
580cf9518b5SBen Skeggs 			break;
581cf9518b5SBen Skeggs 		case NVKM_ENGINE_IFB:
582cf9518b5SBen Skeggs 			nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
583cf9518b5SBen Skeggs 			break;
584cf9518b5SBen Skeggs 		default:
585cf9518b5SBen Skeggs 			break;
586cf9518b5SBen Skeggs 		}
587cf9518b5SBen Skeggs 	}
588cf9518b5SBen Skeggs 
589c358f538SBen Skeggs 	chan = nvkm_chan_get_inst(&fifo->engine, info->inst, &flags);
590cf9518b5SBen Skeggs 
591cf9518b5SBen Skeggs 	nvkm_error(subdev,
592e43c872cSBen Skeggs 		   "fault %02x [%s] at %016llx engine %02x [%s] client %02x "
593e43c872cSBen Skeggs 		   "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n",
594e43c872cSBen Skeggs 		   info->access, ea ? ea->name : "", info->addr,
595e43c872cSBen Skeggs 		   info->engine, ee ? ee->name : engine ? engine->subdev.name : "",
596e43c872cSBen Skeggs 		   info->client, ct, ec ? ec->name : "",
597e43c872cSBen Skeggs 		   info->reason, er ? er->name : "",
598e43c872cSBen Skeggs 		   chan ? chan->id : -1, info->inst, chan ? chan->name : "unknown");
599cf9518b5SBen Skeggs 
600e43c872cSBen Skeggs 	/* Handle host/engine faults. */
6014d60100aSBen Skeggs 	if (chan)
6024d60100aSBen Skeggs 		nvkm_runl_rc_cgrp(chan->cgrp);
603e43c872cSBen Skeggs 
604c358f538SBen Skeggs 	nvkm_chan_put(&chan, flags);
605cf9518b5SBen Skeggs }
606cf9518b5SBen Skeggs 
6079be9c606SBen Skeggs static const struct nvkm_fifo_func_mmu_fault
6089be9c606SBen Skeggs gf100_fifo_mmu_fault = {
609e43c872cSBen Skeggs 	.recover = gf100_fifo_mmu_fault_recover,
610e43c872cSBen Skeggs 	.access = gf100_fifo_mmu_fault_access,
611e43c872cSBen Skeggs 	.engine = gf100_fifo_mmu_fault_engine,
612e43c872cSBen Skeggs 	.reason = gf100_fifo_mmu_fault_reason,
613e43c872cSBen Skeggs 	.hubclient = gf100_fifo_mmu_fault_hubclient,
614e43c872cSBen Skeggs 	.gpcclient = gf100_fifo_mmu_fault_gpcclient,
6159be9c606SBen Skeggs };
6169be9c606SBen Skeggs 
6174d60100aSBen Skeggs void
gf100_fifo_intr_ctxsw_timeout(struct nvkm_fifo * fifo,u32 engm)6184d60100aSBen Skeggs gf100_fifo_intr_ctxsw_timeout(struct nvkm_fifo *fifo, u32 engm)
6194d60100aSBen Skeggs {
6204d60100aSBen Skeggs 	struct nvkm_runl *runl;
6214d60100aSBen Skeggs 	struct nvkm_engn *engn, *engn2;
6224d60100aSBen Skeggs 	bool cgid, cgid2;
6234d60100aSBen Skeggs 	int id, id2;
6244d60100aSBen Skeggs 
6254d60100aSBen Skeggs 	nvkm_runl_foreach(runl, fifo) {
6264d60100aSBen Skeggs 		/* Stop the runlist, and go through all engines serving it. */
6274d60100aSBen Skeggs 		nvkm_runl_block(runl);
6284d60100aSBen Skeggs 		nvkm_runl_foreach_engn_cond(engn, runl, engm & BIT(engn->id)) {
6294d60100aSBen Skeggs 			/* Determine what channel (group) the engine is on. */
6304d60100aSBen Skeggs 			id = engn->func->cxid(engn, &cgid);
6314d60100aSBen Skeggs 			if (id >= 0) {
6324d60100aSBen Skeggs 				/* Trigger MMU fault on any engine(s) on that channel (group). */
6334d60100aSBen Skeggs 				nvkm_runl_foreach_engn_cond(engn2, runl, engn2->func->cxid) {
6344d60100aSBen Skeggs 					id2 = engn2->func->cxid(engn2, &cgid2);
6354d60100aSBen Skeggs 					if (cgid2 == cgid && id2 == id)
6364d60100aSBen Skeggs 						engn2->func->mmu_fault_trigger(engn2);
6374d60100aSBen Skeggs 				}
6384d60100aSBen Skeggs 			}
6394d60100aSBen Skeggs 		}
6404d60100aSBen Skeggs 		nvkm_runl_allow(runl); /* HW will keep runlist blocked via ERROR_SCHED_DISABLE. */
6414d60100aSBen Skeggs 	}
6424d60100aSBen Skeggs }
6434d60100aSBen Skeggs 
6444d60100aSBen Skeggs static void
gf100_fifo_intr_sched_ctxsw(struct nvkm_fifo * fifo)6454d60100aSBen Skeggs gf100_fifo_intr_sched_ctxsw(struct nvkm_fifo *fifo)
6464d60100aSBen Skeggs {
6474d60100aSBen Skeggs 	struct nvkm_runl *runl;
6484d60100aSBen Skeggs 	struct nvkm_engn *engn;
6494d60100aSBen Skeggs 	u32 engm = 0;
6504d60100aSBen Skeggs 
6514d60100aSBen Skeggs 	/* Look for any engines that are busy, and awaiting chsw ack. */
6524d60100aSBen Skeggs 	nvkm_runl_foreach(runl, fifo) {
6534d60100aSBen Skeggs 		nvkm_runl_foreach_engn_cond(engn, runl, engn->func->chsw) {
6544d60100aSBen Skeggs 			if (WARN_ON(engn->fault < 0) || !engn->func->chsw(engn))
6554d60100aSBen Skeggs 				continue;
6564d60100aSBen Skeggs 
6574d60100aSBen Skeggs 			engm |= BIT(engn->id);
6584d60100aSBen Skeggs 		}
6594d60100aSBen Skeggs 	}
6604d60100aSBen Skeggs 
6614d60100aSBen Skeggs 	if (!engm)
6624d60100aSBen Skeggs 		return;
6634d60100aSBen Skeggs 
6644d60100aSBen Skeggs 	fifo->func->intr_ctxsw_timeout(fifo, engm);
6654d60100aSBen Skeggs }
6664d60100aSBen Skeggs 
667cf9518b5SBen Skeggs static const struct nvkm_enum
6684d60100aSBen Skeggs gf100_fifo_intr_sched_names[] = {
66905c7145dSBen Skeggs 	{ 0x0a, "CTXSW_TIMEOUT" },
67005c7145dSBen Skeggs 	{}
67105c7145dSBen Skeggs };
67205c7145dSBen Skeggs 
6734d60100aSBen Skeggs void
gf100_fifo_intr_sched(struct nvkm_fifo * fifo)6744d60100aSBen Skeggs gf100_fifo_intr_sched(struct nvkm_fifo *fifo)
67505c7145dSBen Skeggs {
6764d60100aSBen Skeggs 	struct nvkm_subdev *subdev = &fifo->engine.subdev;
677e5c5e4f5SBen Skeggs 	struct nvkm_device *device = subdev->device;
67887744403SBen Skeggs 	u32 intr = nvkm_rd32(device, 0x00254c);
67905c7145dSBen Skeggs 	u32 code = intr & 0x000000ff;
68005c7145dSBen Skeggs 	const struct nvkm_enum *en;
68105c7145dSBen Skeggs 
6824d60100aSBen Skeggs 	en = nvkm_enum_find(gf100_fifo_intr_sched_names, code);
68305c7145dSBen Skeggs 
684e5c5e4f5SBen Skeggs 	nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : "");
68505c7145dSBen Skeggs 
68605c7145dSBen Skeggs 	switch (code) {
68705c7145dSBen Skeggs 	case 0x0a:
6886189f1b0SBen Skeggs 		gf100_fifo_intr_sched_ctxsw(fifo);
68905c7145dSBen Skeggs 		break;
69005c7145dSBen Skeggs 	default:
69105c7145dSBen Skeggs 		break;
69205c7145dSBen Skeggs 	}
69305c7145dSBen Skeggs }
69405c7145dSBen Skeggs 
695cf9518b5SBen Skeggs void
gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo * fifo,int unit)6969be9c606SBen Skeggs gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit)
69705c7145dSBen Skeggs {
698cf9518b5SBen Skeggs 	struct nvkm_device *device = fifo->engine.subdev.device;
69987744403SBen Skeggs 	u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
70087744403SBen Skeggs 	u32 valo = nvkm_rd32(device, 0x002804 + (unit * 0x10));
70187744403SBen Skeggs 	u32 vahi = nvkm_rd32(device, 0x002808 + (unit * 0x10));
702cf9518b5SBen Skeggs 	u32 type = nvkm_rd32(device, 0x00280c + (unit * 0x10));
703cf9518b5SBen Skeggs 	struct nvkm_fault_data info;
70405c7145dSBen Skeggs 
705cf9518b5SBen Skeggs 	info.inst   =  (u64)inst << 12;
706cf9518b5SBen Skeggs 	info.addr   = ((u64)vahi << 32) | valo;
707cf9518b5SBen Skeggs 	info.time   = 0;
708cf9518b5SBen Skeggs 	info.engine = unit;
709cf9518b5SBen Skeggs 	info.valid  = 1;
710cf9518b5SBen Skeggs 	info.gpc    = (type & 0x1f000000) >> 24;
711cf9518b5SBen Skeggs 	info.client = (type & 0x00001f00) >> 8;
712cf9518b5SBen Skeggs 	info.access = (type & 0x00000080) >> 7;
713cf9518b5SBen Skeggs 	info.hub    = (type & 0x00000040) >> 6;
714cf9518b5SBen Skeggs 	info.reason = (type & 0x0000000f);
715e5c5e4f5SBen Skeggs 
716cf9518b5SBen Skeggs 	nvkm_fifo_fault(fifo, &info);
71705c7145dSBen Skeggs }
71805c7145dSBen Skeggs 
719e43c872cSBen Skeggs void
gf100_fifo_intr_mmu_fault(struct nvkm_fifo * fifo)720e43c872cSBen Skeggs gf100_fifo_intr_mmu_fault(struct nvkm_fifo *fifo)
721e43c872cSBen Skeggs {
722e43c872cSBen Skeggs 	struct nvkm_device *device = fifo->engine.subdev.device;
723e43c872cSBen Skeggs 	unsigned long mask = nvkm_rd32(device, 0x00259c);
724e43c872cSBen Skeggs 	int unit;
725e43c872cSBen Skeggs 
726e43c872cSBen Skeggs 	for_each_set_bit(unit, &mask, 32) {
727e43c872cSBen Skeggs 		fifo->func->intr_mmu_fault_unit(fifo, unit);
728e43c872cSBen Skeggs 		nvkm_wr32(device, 0x00259c, BIT(unit));
729e43c872cSBen Skeggs 	}
730e43c872cSBen Skeggs }
731e43c872cSBen Skeggs 
732923f1ff5SBen Skeggs bool
gf100_fifo_intr_pbdma(struct nvkm_fifo * fifo)733923f1ff5SBen Skeggs gf100_fifo_intr_pbdma(struct nvkm_fifo *fifo)
734923f1ff5SBen Skeggs {
735923f1ff5SBen Skeggs 	struct nvkm_device *device = fifo->engine.subdev.device;
736923f1ff5SBen Skeggs 	struct nvkm_runq *runq;
737923f1ff5SBen Skeggs 	u32 mask = nvkm_rd32(device, 0x0025a0);
738923f1ff5SBen Skeggs 	bool handled = false;
739923f1ff5SBen Skeggs 
740923f1ff5SBen Skeggs 	nvkm_runq_foreach_cond(runq, fifo, mask & BIT(runq->id)) {
741923f1ff5SBen Skeggs 		if (runq->func->intr(runq, NULL))
742923f1ff5SBen Skeggs 			handled = true;
743923f1ff5SBen Skeggs 
744923f1ff5SBen Skeggs 		nvkm_wr32(device, 0x0025a0, BIT(runq->id));
745923f1ff5SBen Skeggs 	}
746923f1ff5SBen Skeggs 
747923f1ff5SBen Skeggs 	return handled;
748923f1ff5SBen Skeggs }
749923f1ff5SBen Skeggs 
75005c7145dSBen Skeggs static void
gf100_fifo_intr_runlist(struct nvkm_fifo * fifo)7514a492fd5SBen Skeggs gf100_fifo_intr_runlist(struct nvkm_fifo *fifo)
75205c7145dSBen Skeggs {
7534a492fd5SBen Skeggs 	struct nvkm_subdev *subdev = &fifo->engine.subdev;
754e5c5e4f5SBen Skeggs 	struct nvkm_device *device = subdev->device;
75587744403SBen Skeggs 	u32 intr = nvkm_rd32(device, 0x002a00);
75605c7145dSBen Skeggs 
75705c7145dSBen Skeggs 	if (intr & 0x10000000) {
75887744403SBen Skeggs 		nvkm_wr32(device, 0x002a00, 0x10000000);
75905c7145dSBen Skeggs 		intr &= ~0x10000000;
76005c7145dSBen Skeggs 	}
76105c7145dSBen Skeggs 
76205c7145dSBen Skeggs 	if (intr) {
763e5c5e4f5SBen Skeggs 		nvkm_error(subdev, "RUNLIST %08x\n", intr);
76487744403SBen Skeggs 		nvkm_wr32(device, 0x002a00, intr);
76505c7145dSBen Skeggs 	}
76605c7145dSBen Skeggs }
76705c7145dSBen Skeggs 
76805c7145dSBen Skeggs static void
gf100_fifo_intr_engine_unit(struct nvkm_fifo * fifo,int engn)769d67f3b96SBen Skeggs gf100_fifo_intr_engine_unit(struct nvkm_fifo *fifo, int engn)
77005c7145dSBen Skeggs {
771d67f3b96SBen Skeggs 	struct nvkm_subdev *subdev = &fifo->engine.subdev;
772e5c5e4f5SBen Skeggs 	struct nvkm_device *device = subdev->device;
77387744403SBen Skeggs 	u32 intr = nvkm_rd32(device, 0x0025a8 + (engn * 0x04));
77487744403SBen Skeggs 	u32 inte = nvkm_rd32(device, 0x002628);
77505c7145dSBen Skeggs 	u32 unkn;
77605c7145dSBen Skeggs 
77787744403SBen Skeggs 	nvkm_wr32(device, 0x0025a8 + (engn * 0x04), intr);
77805c7145dSBen Skeggs 
77905c7145dSBen Skeggs 	for (unkn = 0; unkn < 8; unkn++) {
78005c7145dSBen Skeggs 		u32 ints = (intr >> (unkn * 0x04)) & inte;
78105c7145dSBen Skeggs 		if (ints & 0x1) {
782d67f3b96SBen Skeggs 			nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT);
78305c7145dSBen Skeggs 			ints &= ~1;
78405c7145dSBen Skeggs 		}
78505c7145dSBen Skeggs 		if (ints) {
786d67f3b96SBen Skeggs 			nvkm_error(subdev, "ENGINE %d %d %01x", engn, unkn, ints);
78787744403SBen Skeggs 			nvkm_mask(device, 0x002628, ints, 0);
78805c7145dSBen Skeggs 		}
78905c7145dSBen Skeggs 	}
79005c7145dSBen Skeggs }
79105c7145dSBen Skeggs 
79262742b5eSBen Skeggs static void
gf100_fifo_intr_engine(struct nvkm_fifo * fifo)79362742b5eSBen Skeggs gf100_fifo_intr_engine(struct nvkm_fifo *fifo)
79405c7145dSBen Skeggs {
79562742b5eSBen Skeggs 	struct nvkm_device *device = fifo->engine.subdev.device;
79687744403SBen Skeggs 	u32 mask = nvkm_rd32(device, 0x0025a4);
797d67f3b96SBen Skeggs 
79805c7145dSBen Skeggs 	while (mask) {
79905c7145dSBen Skeggs 		u32 unit = __ffs(mask);
80062742b5eSBen Skeggs 		gf100_fifo_intr_engine_unit(fifo, unit);
80105c7145dSBen Skeggs 		mask &= ~(1 << unit);
80205c7145dSBen Skeggs 	}
80305c7145dSBen Skeggs }
80405c7145dSBen Skeggs 
8052fc71a05SBen Skeggs static irqreturn_t
gf100_fifo_intr(struct nvkm_inth * inth)8062fc71a05SBen Skeggs gf100_fifo_intr(struct nvkm_inth *inth)
80705c7145dSBen Skeggs {
8082fc71a05SBen Skeggs 	struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), engine.subdev.inth);
8092fc71a05SBen Skeggs 	struct nvkm_subdev *subdev = &fifo->engine.subdev;
81013de7f46SBen Skeggs 	struct nvkm_device *device = subdev->device;
81187744403SBen Skeggs 	u32 mask = nvkm_rd32(device, 0x002140);
81287744403SBen Skeggs 	u32 stat = nvkm_rd32(device, 0x002100) & mask;
81305c7145dSBen Skeggs 
81405c7145dSBen Skeggs 	if (stat & 0x00000001) {
81587744403SBen Skeggs 		u32 intr = nvkm_rd32(device, 0x00252c);
816e5c5e4f5SBen Skeggs 		nvkm_warn(subdev, "INTR 00000001: %08x\n", intr);
81787744403SBen Skeggs 		nvkm_wr32(device, 0x002100, 0x00000001);
81805c7145dSBen Skeggs 		stat &= ~0x00000001;
81905c7145dSBen Skeggs 	}
82005c7145dSBen Skeggs 
82105c7145dSBen Skeggs 	if (stat & 0x00000100) {
8224d60100aSBen Skeggs 		gf100_fifo_intr_sched(fifo);
82387744403SBen Skeggs 		nvkm_wr32(device, 0x002100, 0x00000100);
82405c7145dSBen Skeggs 		stat &= ~0x00000100;
82505c7145dSBen Skeggs 	}
82605c7145dSBen Skeggs 
82705c7145dSBen Skeggs 	if (stat & 0x00010000) {
82887744403SBen Skeggs 		u32 intr = nvkm_rd32(device, 0x00256c);
829e5c5e4f5SBen Skeggs 		nvkm_warn(subdev, "INTR 00010000: %08x\n", intr);
83087744403SBen Skeggs 		nvkm_wr32(device, 0x002100, 0x00010000);
83105c7145dSBen Skeggs 		stat &= ~0x00010000;
83205c7145dSBen Skeggs 	}
83305c7145dSBen Skeggs 
83405c7145dSBen Skeggs 	if (stat & 0x01000000) {
83587744403SBen Skeggs 		u32 intr = nvkm_rd32(device, 0x00258c);
836e5c5e4f5SBen Skeggs 		nvkm_warn(subdev, "INTR 01000000: %08x\n", intr);
83787744403SBen Skeggs 		nvkm_wr32(device, 0x002100, 0x01000000);
83805c7145dSBen Skeggs 		stat &= ~0x01000000;
83905c7145dSBen Skeggs 	}
84005c7145dSBen Skeggs 
84105c7145dSBen Skeggs 	if (stat & 0x10000000) {
842e43c872cSBen Skeggs 		gf100_fifo_intr_mmu_fault(fifo);
84305c7145dSBen Skeggs 		stat &= ~0x10000000;
84405c7145dSBen Skeggs 	}
84505c7145dSBen Skeggs 
84605c7145dSBen Skeggs 	if (stat & 0x20000000) {
847923f1ff5SBen Skeggs 		if (gf100_fifo_intr_pbdma(fifo))
84805c7145dSBen Skeggs 			stat &= ~0x20000000;
84905c7145dSBen Skeggs 	}
85005c7145dSBen Skeggs 
85105c7145dSBen Skeggs 	if (stat & 0x40000000) {
8524a492fd5SBen Skeggs 		gf100_fifo_intr_runlist(fifo);
85305c7145dSBen Skeggs 		stat &= ~0x40000000;
85405c7145dSBen Skeggs 	}
85505c7145dSBen Skeggs 
85605c7145dSBen Skeggs 	if (stat & 0x80000000) {
85762742b5eSBen Skeggs 		gf100_fifo_intr_engine(fifo);
85805c7145dSBen Skeggs 		stat &= ~0x80000000;
85905c7145dSBen Skeggs 	}
86005c7145dSBen Skeggs 
86105c7145dSBen Skeggs 	if (stat) {
862e5c5e4f5SBen Skeggs 		nvkm_error(subdev, "INTR %08x\n", stat);
863d67f3b96SBen Skeggs 		spin_lock(&fifo->lock);
86487744403SBen Skeggs 		nvkm_mask(device, 0x002140, stat, 0x00000000);
865d67f3b96SBen Skeggs 		spin_unlock(&fifo->lock);
86687744403SBen Skeggs 		nvkm_wr32(device, 0x002100, stat);
86705c7145dSBen Skeggs 	}
8682fc71a05SBen Skeggs 
8692fc71a05SBen Skeggs 	return IRQ_HANDLED;
87005c7145dSBen Skeggs }
87105c7145dSBen Skeggs 
87213de7f46SBen Skeggs static void
gf100_fifo_init_pbdmas(struct nvkm_fifo * fifo,u32 mask)873965c41d9SBen Skeggs gf100_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask)
87413de7f46SBen Skeggs {
875965c41d9SBen Skeggs 	struct nvkm_device *device = fifo->engine.subdev.device;
87613de7f46SBen Skeggs 
877adbe24a2SBen Skeggs 	/* Enable PBDMAs. */
878965c41d9SBen Skeggs 	nvkm_wr32(device, 0x000204, mask);
879965c41d9SBen Skeggs 	nvkm_wr32(device, 0x002204, mask);
8809a65a38cSBen Skeggs 
881adbe24a2SBen Skeggs 	/* Assign engines to PBDMAs. */
882965c41d9SBen Skeggs 	if ((mask & 7) == 7) {
8839a65a38cSBen Skeggs 		nvkm_wr32(device, 0x002208, ~(1 << 0)); /* PGRAPH */
8849a65a38cSBen Skeggs 		nvkm_wr32(device, 0x00220c, ~(1 << 1)); /* PVP */
8859a65a38cSBen Skeggs 		nvkm_wr32(device, 0x002210, ~(1 << 1)); /* PMSPP */
8869a65a38cSBen Skeggs 		nvkm_wr32(device, 0x002214, ~(1 << 1)); /* PMSVLD */
8879a65a38cSBen Skeggs 		nvkm_wr32(device, 0x002218, ~(1 << 2)); /* PCE0 */
8889a65a38cSBen Skeggs 		nvkm_wr32(device, 0x00221c, ~(1 << 1)); /* PCE1 */
8899a65a38cSBen Skeggs 	}
8909a65a38cSBen Skeggs 
891324176e7SBen Skeggs 	nvkm_mask(device, 0x002a04, 0xbfffffff, 0xbfffffff);
892965c41d9SBen Skeggs }
893965c41d9SBen Skeggs 
894965c41d9SBen Skeggs static void
gf100_fifo_init(struct nvkm_fifo * fifo)895fbe9f433SBen Skeggs gf100_fifo_init(struct nvkm_fifo *fifo)
896965c41d9SBen Skeggs {
897fbe9f433SBen Skeggs 	struct nvkm_device *device = fifo->engine.subdev.device;
8989a65a38cSBen Skeggs 
8999a65a38cSBen Skeggs 	nvkm_mask(device, 0x002200, 0x00000001, 0x00000001);
900fbe9f433SBen Skeggs 	nvkm_wr32(device, 0x002254, 0x10000000 | fifo->userd.bar1->addr >> 12);
9019a65a38cSBen Skeggs 
9029a65a38cSBen Skeggs 	nvkm_wr32(device, 0x002100, 0xffffffff);
9039a65a38cSBen Skeggs 	nvkm_wr32(device, 0x002140, 0x7fffffff);
9049a65a38cSBen Skeggs 	nvkm_wr32(device, 0x002628, 0x00000001); /* ENGINE_INTR_EN */
90505c7145dSBen Skeggs }
90605c7145dSBen Skeggs 
907d94470e9SBen Skeggs static int
gf100_fifo_runl_ctor(struct nvkm_fifo * fifo)908d94470e9SBen Skeggs gf100_fifo_runl_ctor(struct nvkm_fifo *fifo)
909d94470e9SBen Skeggs {
910d94470e9SBen Skeggs 	struct nvkm_runl *runl;
911d94470e9SBen Skeggs 
912d94470e9SBen Skeggs 	runl = nvkm_runl_new(fifo, 0, 0, 0);
913d94470e9SBen Skeggs 	if (IS_ERR(runl))
914d94470e9SBen Skeggs 		return PTR_ERR(runl);
915d94470e9SBen Skeggs 
916d94470e9SBen Skeggs 	nvkm_runl_add(runl,  0, fifo->func->engn, NVKM_ENGINE_GR, 0);
917d94470e9SBen Skeggs 	nvkm_runl_add(runl,  1, fifo->func->engn, NVKM_ENGINE_MSPDEC, 0);
918d94470e9SBen Skeggs 	nvkm_runl_add(runl,  2, fifo->func->engn, NVKM_ENGINE_MSPPP, 0);
919d94470e9SBen Skeggs 	nvkm_runl_add(runl,  3, fifo->func->engn, NVKM_ENGINE_MSVLD, 0);
920d94470e9SBen Skeggs 	nvkm_runl_add(runl,  4, fifo->func->engn, NVKM_ENGINE_CE, 0);
921d94470e9SBen Skeggs 	nvkm_runl_add(runl,  5, fifo->func->engn, NVKM_ENGINE_CE, 1);
922d94470e9SBen Skeggs 	nvkm_runl_add(runl, 15,   &gf100_engn_sw, NVKM_ENGINE_SW, 0);
923d94470e9SBen Skeggs 	return 0;
924d94470e9SBen Skeggs }
925d94470e9SBen Skeggs 
926800ac1f8SBen Skeggs int
gf100_fifo_runq_nr(struct nvkm_fifo * fifo)9271c488ba9SBen Skeggs gf100_fifo_runq_nr(struct nvkm_fifo *fifo)
9281c488ba9SBen Skeggs {
9291c488ba9SBen Skeggs 	struct nvkm_device *device = fifo->engine.subdev.device;
9301c488ba9SBen Skeggs 	u32 save;
9311c488ba9SBen Skeggs 
9321c488ba9SBen Skeggs 	/* Determine number of PBDMAs by checking valid enable bits. */
9331c488ba9SBen Skeggs 	save = nvkm_mask(device, 0x000204, 0xffffffff, 0xffffffff);
9341c488ba9SBen Skeggs 	save = nvkm_mask(device, 0x000204, 0xffffffff, save);
9351c488ba9SBen Skeggs 	return hweight32(save);
9361c488ba9SBen Skeggs }
9371c488ba9SBen Skeggs 
9381c488ba9SBen Skeggs int
gf100_fifo_chid_ctor(struct nvkm_fifo * fifo,int nr)939800ac1f8SBen Skeggs gf100_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr)
940800ac1f8SBen Skeggs {
941800ac1f8SBen Skeggs 	return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 0, nr, &fifo->chid);
942800ac1f8SBen Skeggs }
943800ac1f8SBen Skeggs 
9448f0649b5SBen Skeggs static const struct nvkm_fifo_func
94513de7f46SBen Skeggs gf100_fifo = {
9468c18138cSBen Skeggs 	.chid_nr = nv50_fifo_chid_nr,
947800ac1f8SBen Skeggs 	.chid_ctor = gf100_fifo_chid_ctor,
9481c488ba9SBen Skeggs 	.runq_nr = gf100_fifo_runq_nr,
949d94470e9SBen Skeggs 	.runl_ctor = gf100_fifo_runl_ctor,
95013de7f46SBen Skeggs 	.init = gf100_fifo_init,
951965c41d9SBen Skeggs 	.init_pbdmas = gf100_fifo_init_pbdmas,
95213de7f46SBen Skeggs 	.intr = gf100_fifo_intr,
953e43c872cSBen Skeggs 	.intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit,
9544d60100aSBen Skeggs 	.intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout,
9559be9c606SBen Skeggs 	.mmu_fault = &gf100_fifo_mmu_fault,
956d67f3b96SBen Skeggs 	.nonstall = &gf100_fifo_nonstall,
957d94470e9SBen Skeggs 	.runl = &gf100_runl,
9581c488ba9SBen Skeggs 	.runq = &gf100_runq,
959d94470e9SBen Skeggs 	.engn = &gf100_engn,
960f5e45689SBen Skeggs 	.cgrp = {{                            }, &nv04_cgrp },
96106db7fdeSBen Skeggs 	.chan = {{ 0, 0, FERMI_CHANNEL_GPFIFO }, &gf100_chan },
9628f0649b5SBen Skeggs };
9638f0649b5SBen Skeggs 
96413de7f46SBen Skeggs int
gf100_fifo_new(struct nvkm_device * device,enum nvkm_subdev_type type,int inst,struct nvkm_fifo ** pfifo)965ab0db2bdSBen Skeggs gf100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
966ab0db2bdSBen Skeggs 	       struct nvkm_fifo **pfifo)
96705c7145dSBen Skeggs {
96806db7fdeSBen Skeggs 	return nvkm_fifo_new_(&gf100_fifo, device, type, inst, pfifo);
96905c7145dSBen Skeggs }
970