Commit 923f1ff5 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fifo: move PBDMA intr to runq



- merges gf100/gk104- NV_PFIFO_INTR_0_PBDMA and NV_PPBDMA_INTR_0 code

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent 87c86024
Loading
Loading
Loading
Loading
+40 −25
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@
#include "changf100.h"

#include <core/client.h>
#include <core/enum.h>
#include <core/gpuobj.h>
#include <subdev/bar.h>
#include <subdev/fault.h>
@@ -52,27 +51,28 @@ gf100_engn_sw = {
};

static const struct nvkm_bitfield
gf100_fifo_pbdma_intr[] = {
gf100_runq_intr_0_names[] = {
/*	{ 0x00008000, "" }	seen with null ib push */
	{ 0x00200000, "ILLEGAL_MTHD" },
	{ 0x00800000, "EMPTY_SUBC" },
	{}
};

static void
gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit)
bool
gf100_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null)
{
	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
	struct nvkm_subdev *subdev = &runq->fifo->engine.subdev;
	struct nvkm_device *device = subdev->device;
	u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000));
	u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000));
	u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000));
	u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0x7f;
	u32 mask = nvkm_rd32(device, 0x04010c + (runq->id * 0x2000));
	u32 stat = nvkm_rd32(device, 0x040108 + (runq->id * 0x2000)) & mask;
	u32 addr = nvkm_rd32(device, 0x0400c0 + (runq->id * 0x2000));
	u32 data = nvkm_rd32(device, 0x0400c4 + (runq->id * 0x2000));
	u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x2000)) & runq->fifo->chid->mask;
	u32 subc = (addr & 0x00070000) >> 16;
	u32 mthd = (addr & 0x00003ffc);
	struct nvkm_fifo_chan *chan;
	unsigned long flags;
	u32 show = stat;
	struct nvkm_chan *chan;
	unsigned long flags;
	char msg[128];

	if (stat & 0x00800000) {
@@ -83,18 +83,19 @@ gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit)
	}

	if (show) {
		nvkm_snprintbf(msg, sizeof(msg), gf100_fifo_pbdma_intr, show);
		chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
		nvkm_snprintbf(msg, sizeof(msg), runq->func->intr_0_names, show);
		chan = nvkm_fifo_chan_chid(runq->fifo, chid, &flags);
		nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
				   "subc %d mthd %04x data %08x\n",
			   unit, show, msg, chid, chan ? chan->inst->addr : 0,
			   runq->id, show, msg, chid, chan ? chan->inst->addr : 0,
			   chan ? chan->object.client->name : "unknown",
			   subc, mthd, data);
		nvkm_fifo_chan_put(&fifo->base, flags, &chan);
		nvkm_fifo_chan_put(runq->fifo, flags, &chan);
	}

	nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008);
	nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat);
	nvkm_wr32(device, 0x0400c0 + (runq->id * 0x2000), 0x80600008);
	nvkm_wr32(device, 0x040108 + (runq->id * 0x2000), stat);
	return true;
}

void
@@ -110,6 +111,8 @@ gf100_runq_init(struct nvkm_runq *runq)
static const struct nvkm_runq_func
gf100_runq = {
	.init = gf100_runq_init,
	.intr = gf100_runq_intr,
	.intr_0_names = gf100_runq_intr_0_names,
};

void
@@ -495,6 +498,24 @@ gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit)
	nvkm_fifo_fault(fifo, &info);
}

bool
gf100_fifo_intr_pbdma(struct nvkm_fifo *fifo)
{
	struct nvkm_device *device = fifo->engine.subdev.device;
	struct nvkm_runq *runq;
	u32 mask = nvkm_rd32(device, 0x0025a0);
	bool handled = false;

	nvkm_runq_foreach_cond(runq, fifo, mask & BIT(runq->id)) {
		if (runq->func->intr(runq, NULL))
			handled = true;

		nvkm_wr32(device, 0x0025a0, BIT(runq->id));
	}

	return handled;
}

static void
gf100_fifo_intr_runlist(struct gf100_fifo *fifo)
{
@@ -599,13 +620,7 @@ gf100_fifo_intr(struct nvkm_inth *inth)
	}

	if (stat & 0x20000000) {
		u32 mask = nvkm_rd32(device, 0x0025a0);
		while (mask) {
			u32 unit = __ffs(mask);
			gf100_fifo_intr_pbdma(gf100_fifo(fifo), unit);
			nvkm_wr32(device, 0x0025a0, (1 << unit));
			mask &= ~(1 << unit);
		}
		if (gf100_fifo_intr_pbdma(fifo))
			stat &= ~0x20000000;
	}

+29 −63
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@
#include <subdev/mc.h>
#include <subdev/timer.h>
#include <subdev/top.h>
#include <engine/sw.h>

#include <nvif/class.h>

@@ -100,7 +99,8 @@ const struct nvkm_engn_func
gk104_engn_ce = {
};

static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = {
static const struct nvkm_bitfield
gk104_runq_intr_1_names[] = {
	{ 0x00000001, "HCE_RE_ILLEGAL_OP" },
	{ 0x00000002, "HCE_RE_ALIGNB" },
	{ 0x00000004, "HCE_PRIV" },
@@ -109,28 +109,30 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = {
	{}
};

void
gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit)
static bool
gk104_runq_intr_1(struct nvkm_runq *runq)
{
	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
	struct nvkm_subdev *subdev = &runq->fifo->engine.subdev;
	struct nvkm_device *device = subdev->device;
	u32 mask = nvkm_rd32(device, 0x04014c + (unit * 0x2000));
	u32 stat = nvkm_rd32(device, 0x040148 + (unit * 0x2000)) & mask;
	u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0xfff;
	u32 mask = nvkm_rd32(device, 0x04014c + (runq->id * 0x2000));
	u32 stat = nvkm_rd32(device, 0x040148 + (runq->id * 0x2000)) & mask;
	u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x2000)) & 0xfff;
	char msg[128];

	if (stat) {
		nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_1, stat);
		nvkm_snprintbf(msg, sizeof(msg), gk104_runq_intr_1_names, stat);
		nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d %08x %08x\n",
			   unit, stat, msg, chid,
			   nvkm_rd32(device, 0x040150 + (unit * 0x2000)),
			   nvkm_rd32(device, 0x040154 + (unit * 0x2000)));
			   runq->id, stat, msg, chid,
			   nvkm_rd32(device, 0x040150 + (runq->id * 0x2000)),
			   nvkm_rd32(device, 0x040154 + (runq->id * 0x2000)));
	}

	nvkm_wr32(device, 0x040148 + (unit * 0x2000), stat);
	nvkm_wr32(device, 0x040148 + (runq->id * 0x2000), stat);
	return true;
}

static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = {
const struct nvkm_bitfield
gk104_runq_intr_0_names[] = {
	{ 0x00000001, "MEMREQ" },
	{ 0x00000002, "MEMACK_TIMEOUT" },
	{ 0x00000004, "MEMACK_EXTRA" },
@@ -164,6 +166,15 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = {
	{}
};

bool
gk104_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null)
{
	bool intr0 = gf100_runq_intr(runq, NULL);
	bool intr1 = gk104_runq_intr_1(runq);

	return intr0 || intr1;
}

void
gk104_runq_init(struct nvkm_runq *runq)
{
@@ -184,6 +195,8 @@ gk104_runq_runm(struct nvkm_runq *runq)
const struct nvkm_runq_func
gk104_runq = {
	.init = gk104_runq_init,
	.intr = gk104_runq_intr,
	.intr_0_names = gk104_runq_intr_0_names,
};

void
@@ -806,46 +819,6 @@ gk104_fifo_intr_dropped_fault(struct nvkm_fifo *fifo)
	nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat);
}

void
gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit)
{
	struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
	struct nvkm_device *device = subdev->device;
	u32 mask = nvkm_rd32(device, 0x04010c + (unit * 0x2000));
	u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000)) & mask;
	u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000));
	u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000));
	u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0xfff;
	u32 subc = (addr & 0x00070000) >> 16;
	u32 mthd = (addr & 0x00003ffc);
	u32 show = stat;
	struct nvkm_fifo_chan *chan;
	unsigned long flags;
	char msg[128];

	if (stat & 0x00800000) {
		if (device->sw) {
			if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data))
				show &= ~0x00800000;
		}
	}

	nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008);

	if (show) {
		nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_0, show);
		chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
		nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
				   "subc %d mthd %04x data %08x\n",
			   unit, show, msg, chid, chan ? chan->inst->addr : 0,
			   chan ? chan->object.client->name : "unknown",
			   subc, mthd, data);
		nvkm_fifo_chan_put(&fifo->base, flags, &chan);
	}

	nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat);
}

void
gk104_fifo_intr_runlist(struct gk104_fifo *fifo)
{
@@ -922,14 +895,7 @@ gk104_fifo_intr(struct nvkm_inth *inth)
	}

	if (stat & 0x20000000) {
		u32 mask = nvkm_rd32(device, 0x0025a0);
		while (mask) {
			u32 unit = __ffs(mask);
			gk104_fifo_intr_pbdma_0(gk104_fifo(fifo), unit);
			gk104_fifo_intr_pbdma_1(gk104_fifo(fifo), unit);
			nvkm_wr32(device, 0x0025a0, (1 << unit));
			mask &= ~(1 << unit);
		}
		if (gf100_fifo_intr_pbdma(fifo))
			stat &= ~0x20000000;
	}

+0 −3
Original line number Diff line number Diff line
@@ -5,7 +5,6 @@
#include "priv.h"
struct nvkm_fifo_cgrp;

#include <core/enum.h>
#include <subdev/mmu.h>

#define gk104_fifo_func nvkm_fifo_func
@@ -64,8 +63,6 @@ void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *);
void gk104_fifo_runlist_update(struct gk104_fifo *, int runl);
void gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn,
			      struct gk104_fifo_engine_status *status);
void gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit);
void gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit);
void gk104_fifo_intr_runlist(struct gk104_fifo *fifo);
void *gk104_fifo_dtor(struct nvkm_fifo *base);
int gk104_fifo_oneinit(struct nvkm_fifo *);
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ gk208_runq_init(struct nvkm_runq *runq)
const struct nvkm_runq_func
gk208_runq = {
	.init = gk208_runq_init,
	.intr = gk104_runq_intr,
	.intr_0_names = gk104_runq_intr_0_names,
};

static int
+2 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ gv100_engn_ce = {
const struct nvkm_runq_func
gv100_runq = {
	.init = gk208_runq_init,
	.intr = gk104_runq_intr,
	.intr_0_names = gk104_runq_intr_0_names,
};

void
Loading