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

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
......@@ -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,14 +620,8 @@ 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);
}
stat &= ~0x20000000;
if (gf100_fifo_intr_pbdma(fifo))
stat &= ~0x20000000;
}
if (stat & 0x40000000) {
......
......@@ -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,15 +895,8 @@ 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);
}
stat &= ~0x20000000;
if (gf100_fifo_intr_pbdma(fifo))
stat &= ~0x20000000;
}
if (stat & 0x40000000) {
......
......@@ -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 *);
......
......@@ -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
......
......@@ -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
......
......@@ -3,8 +3,10 @@
#define __NVKM_FIFO_PRIV_H__
#define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine)
#include <engine/fifo.h>
#include <core/enum.h>
struct nvkm_cgrp;
struct nvkm_memory;
struct nvkm_runl;
struct nvkm_runq;
struct gk104_fifo;
struct gk104_fifo_chan;
......@@ -113,9 +115,11 @@ extern const struct nvkm_chan_func g84_chan;
int gf100_fifo_chid_ctor(struct nvkm_fifo *, int);
int gf100_fifo_runq_nr(struct nvkm_fifo *);
bool gf100_fifo_intr_pbdma(struct nvkm_fifo *);
void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int);
extern const struct nvkm_event_func gf100_fifo_nonstall;
void gf100_runq_init(struct nvkm_runq *);
bool gf100_runq_intr(struct nvkm_runq *, struct nvkm_runl *);
extern const struct nvkm_engn_func gf100_engn_sw;
int gk104_fifo_chid_nr(struct nvkm_fifo *);
......@@ -130,6 +134,8 @@ void gk104_fifo_recover_chan(struct nvkm_fifo *, int);
int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *);
extern const struct nvkm_runq_func gk104_runq;
void gk104_runq_init(struct nvkm_runq *);
bool gk104_runq_intr(struct nvkm_runq *, struct nvkm_runl *);
extern const struct nvkm_bitfield gk104_runq_intr_0_names[];
extern const struct nvkm_engn_func gk104_engn;
extern const struct nvkm_engn_func gk104_engn_ce;
......
......@@ -2,10 +2,13 @@
#ifndef __NVKM_RUNQ_H__
#define __NVKM_RUNQ_H__
#include <core/os.h>
struct nvkm_runl;
struct nvkm_runq {
const struct nvkm_runq_func {
void (*init)(struct nvkm_runq *);
bool (*intr)(struct nvkm_runq *, struct nvkm_runl *);
const struct nvkm_bitfield *intr_0_names;
} *func;
struct nvkm_fifo *fifo;
int id;
......
......@@ -395,17 +395,8 @@ tu102_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);
}
stat &= ~0x20000000;
if (gf100_fifo_intr_pbdma(fifo))
stat &= ~0x20000000;
}
if (stat & 0x40000000) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment