소스 검색

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>
Ben Skeggs 10 년 전
부모
커밋
adc346b133
1개의 변경된 파일35개의 추가작업 그리고 50개의 파일을 삭제
  1. 35 50
      drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c

+ 35 - 50
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c

@@ -502,72 +502,57 @@ 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);
+	nv_wr32(priv, NV03_PFIFO_CACHES, 0);
 
-		if (status & NV_PFIFO_INTR_CACHE_ERROR) {
-			nv04_fifo_cache_error(device, priv, chid, get);
-			status &= ~NV_PFIFO_INTR_CACHE_ERROR;
-		}
+	chid = nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH1) & priv->base.max;
+	get  = nv_rd32(priv, NV03_PFIFO_CACHE1_GET);
 
-		if (status & NV_PFIFO_INTR_DMA_PUSHER) {
-			nv04_fifo_dma_pusher(device, priv, chid);
-			status &= ~NV_PFIFO_INTR_DMA_PUSHER;
-		}
+	if (stat & NV_PFIFO_INTR_CACHE_ERROR) {
+		nv04_fifo_cache_error(device, priv, chid, get);
+		stat &= ~NV_PFIFO_INTR_CACHE_ERROR;
+	}
 
-		if (status & NV_PFIFO_INTR_SEMAPHORE) {
-			uint32_t sem;
+	if (stat & NV_PFIFO_INTR_DMA_PUSHER) {
+		nv04_fifo_dma_pusher(device, priv, chid);
+		stat &= ~NV_PFIFO_INTR_DMA_PUSHER;
+	}
 
-			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);
+		sem = nv_rd32(priv, NV10_PFIFO_CACHE1_SEMAPHORE);
+		nv_wr32(priv, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
 
-			nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4);
-			nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1);
-		}
+		nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4);
+		nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1);
+	}
 
-		if (device->card_type == NV_50) {
-			if (status & 0x00000010) {
-				status &= ~0x00000010;
-				nv_wr32(priv, 0x002100, 0x00000010);
-			}
-
-			if (status & 0x40000000) {
-				nv_wr32(priv, 0x002100, 0x40000000);
-				nvkm_fifo_uevent(&priv->base);
-				status &= ~0x40000000;
-			}
+	if (device->card_type == NV_50) {
+		if (stat & 0x00000010) {
+			stat &= ~0x00000010;
+			nv_wr32(priv, 0x002100, 0x00000010);
 		}
 
-		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 & 0x40000000) {
+			nv_wr32(priv, 0x002100, 0x40000000);
+			nvkm_fifo_uevent(&priv->base);
+			stat &= ~0x40000000;
 		}
-
-		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);
+	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, 0x000100, 0x00000100);
+	nv_wr32(priv, NV03_PFIFO_CACHES, reassign);
 }
 
 static int