drm/nouveau/fifo/nv04: remove the loop from the interrupt handler

Complete bong hit (and not the last...), the hardware will reassert the
interrupt to PMC if it's necessary.

Also potentially harmful in the face of interrupts such as the non-stall
interrupt, which remain active in NV_PFIFO_INTR even when we don't care
about servicing it.

It appears (hopefully, fdo#87244), that under certain loads, the methods
may pass quickly enough to hit the "100 spins and kill PFIFO" thing that
we had going on.  Not ideal ;)

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Ben Skeggs 2015-01-27 15:09:39 +10:00
parent 046d669c62
commit adc346b133
1 changed files with 43 additions and 58 deletions

View File

@ -502,34 +502,29 @@ nv04_fifo_intr(struct nvkm_subdev *subdev)
{
struct nvkm_device *device = nv_device(subdev);
struct nv04_fifo_priv *priv = (void *)subdev;
uint32_t status, reassign;
int cnt = 0;
u32 mask = nv_rd32(priv, NV03_PFIFO_INTR_EN_0);
u32 stat = nv_rd32(priv, NV03_PFIFO_INTR_0) & mask;
u32 reassign, chid, get, sem;
reassign = nv_rd32(priv, NV03_PFIFO_CACHES) & 1;
while ((status = nv_rd32(priv, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) {
uint32_t chid, get;
nv_wr32(priv, NV03_PFIFO_CACHES, 0);
chid = nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH1) & priv->base.max;
get = nv_rd32(priv, NV03_PFIFO_CACHE1_GET);
if (status & NV_PFIFO_INTR_CACHE_ERROR) {
if (stat & NV_PFIFO_INTR_CACHE_ERROR) {
nv04_fifo_cache_error(device, priv, chid, get);
status &= ~NV_PFIFO_INTR_CACHE_ERROR;
stat &= ~NV_PFIFO_INTR_CACHE_ERROR;
}
if (status & NV_PFIFO_INTR_DMA_PUSHER) {
if (stat & NV_PFIFO_INTR_DMA_PUSHER) {
nv04_fifo_dma_pusher(device, priv, chid);
status &= ~NV_PFIFO_INTR_DMA_PUSHER;
stat &= ~NV_PFIFO_INTR_DMA_PUSHER;
}
if (status & NV_PFIFO_INTR_SEMAPHORE) {
uint32_t sem;
status &= ~NV_PFIFO_INTR_SEMAPHORE;
nv_wr32(priv, NV03_PFIFO_INTR_0,
NV_PFIFO_INTR_SEMAPHORE);
if (stat & NV_PFIFO_INTR_SEMAPHORE) {
stat &= ~NV_PFIFO_INTR_SEMAPHORE;
nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_SEMAPHORE);
sem = nv_rd32(priv, NV10_PFIFO_CACHE1_SEMAPHORE);
nv_wr32(priv, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
@ -539,37 +534,27 @@ nv04_fifo_intr(struct nvkm_subdev *subdev)
}
if (device->card_type == NV_50) {
if (status & 0x00000010) {
status &= ~0x00000010;
if (stat & 0x00000010) {
stat &= ~0x00000010;
nv_wr32(priv, 0x002100, 0x00000010);
}
if (status & 0x40000000) {
if (stat & 0x40000000) {
nv_wr32(priv, 0x002100, 0x40000000);
nvkm_fifo_uevent(&priv->base);
status &= ~0x40000000;
stat &= ~0x40000000;
}
}
if (status) {
nv_warn(priv, "unknown intr 0x%08x, ch %d\n",
status, chid);
nv_wr32(priv, NV03_PFIFO_INTR_0, status);
status = 0;
if (stat) {
nv_warn(priv, "unknown intr 0x%08x\n", stat);
nv_mask(priv, NV03_PFIFO_INTR_EN_0, stat, 0x00000000);
nv_wr32(priv, NV03_PFIFO_INTR_0, stat);
}
nv_wr32(priv, NV03_PFIFO_CACHES, reassign);
}
if (status) {
nv_error(priv, "still angry after %d spins, halt\n", cnt);
nv_wr32(priv, 0x002140, 0);
nv_wr32(priv, 0x000140, 0);
}
nv_wr32(priv, 0x000100, 0x00000100);
}
static int
nv04_fifo_ctor(struct nvkm_object *parent, struct nvkm_object *engine,
struct nvkm_oclass *oclass, void *data, u32 size,