Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adc346b1 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

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: default avatarBen Skeggs <bskeggs@redhat.com>
parent 046d669c
Loading
Loading
Loading
Loading
+35 −50
Original line number Diff line number Diff line
@@ -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,