Commit fc10199e authored by Marcin Slusarz's avatar Marcin Slusarz Committed by Ben Skeggs
Browse files

drm/nouveau: split fifo interrupt handler

parent 3600ad5e
Loading
Loading
Loading
Loading
+88 −86
Original line number Diff line number Diff line
@@ -398,57 +398,36 @@ out:
	return handled;
}

void
nv04_fifo_intr(struct nouveau_subdev *subdev)
static void
nv04_fifo_cache_error(struct nouveau_device *device,
		struct nv04_fifo_priv *priv, u32 chid, u32 get)
{
	struct nouveau_device *device = nv_device(subdev);
	struct nv04_fifo_priv *priv = (void *)subdev;
	uint32_t status, reassign;
	int cnt = 0;

	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) {
			uint32_t mthd, data;
	u32 mthd, data;
	int ptr;

			/* NV_PFIFO_CACHE1_GET actually goes to 0xffc before
			 * wrapping on my G80 chips, but CACHE1 isn't big
			 * enough for this much data.. Tests show that it
			 * wraps around to the start at GET=0x800.. No clue
			 * as to why..
	/* NV_PFIFO_CACHE1_GET actually goes to 0xffc before wrapping on my
	 * G80 chips, but CACHE1 isn't big enough for this much data.. Tests
	 * show that it wraps around to the start at GET=0x800.. No clue as to
	 * why..
	 */
	ptr = (get & 0x7ff) >> 2;

	if (device->card_type < NV_40) {
				mthd = nv_rd32(priv,
					NV04_PFIFO_CACHE1_METHOD(ptr));
				data = nv_rd32(priv,
					NV04_PFIFO_CACHE1_DATA(ptr));
		mthd = nv_rd32(priv, NV04_PFIFO_CACHE1_METHOD(ptr));
		data = nv_rd32(priv, NV04_PFIFO_CACHE1_DATA(ptr));
	} else {
				mthd = nv_rd32(priv,
					NV40_PFIFO_CACHE1_METHOD(ptr));
				data = nv_rd32(priv,
					NV40_PFIFO_CACHE1_DATA(ptr));
		mthd = nv_rd32(priv, NV40_PFIFO_CACHE1_METHOD(ptr));
		data = nv_rd32(priv, NV40_PFIFO_CACHE1_DATA(ptr));
	}

	if (!nv04_fifo_swmthd(priv, chid, mthd, data)) {
				nv_error(priv, "CACHE_ERROR - Ch %d/%d "
					      "Mthd 0x%04x Data 0x%08x\n",
					chid, (mthd >> 13) & 7, mthd & 0x1ffc,
					data);
		nv_error(priv,
			 "CACHE_ERROR - Ch %d/%d Mthd 0x%04x Data 0x%08x\n",
			 chid, (mthd >> 13) & 7, mthd & 0x1ffc, data);
	}

	nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
			nv_wr32(priv, NV03_PFIFO_INTR_0,
						NV_PFIFO_INTR_CACHE_ERROR);
	nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR);

	nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0,
		nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) & ~1);
@@ -460,11 +439,12 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
	nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH,
		nv_rd32(priv, NV04_PFIFO_CACHE1_DMA_PUSH) | 1);
	nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1);

			status &= ~NV_PFIFO_INTR_CACHE_ERROR;
}

		if (status & NV_PFIFO_INTR_DMA_PUSHER) {
static void
nv04_fifo_dma_pusher(struct nouveau_device *device, struct nv04_fifo_priv *priv,
		u32 chid)
{
	u32 dma_get = nv_rd32(priv, 0x003244);
	u32 dma_put = nv_rd32(priv, 0x003240);
	u32 push = nv_rd32(priv, 0x003220);
@@ -476,13 +456,10 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
		u32 ib_get = nv_rd32(priv, 0x003334);
		u32 ib_put = nv_rd32(priv, 0x003330);

				nv_error(priv, "DMA_PUSHER - Ch %d Get 0x%02x%08x "
				     "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x "
				     "State 0x%08x (err: %s) Push 0x%08x\n",
					chid, ho_get, dma_get, ho_put,
					dma_put, ib_get, ib_put, state,
					nv_dma_state_err(state),
					push);
		nv_error(priv,
			 "DMA_PUSHER - Ch %d Get 0x%02x%08x Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x State 0x%08x (err: %s) Push 0x%08x\n",
			 chid, ho_get, dma_get, ho_put, dma_put, ib_get, ib_put,
			 state, nv_dma_state_err(state), push);

		/* METHOD_COUNT, in DMA_STATE on earlier chipsets */
		nv_wr32(priv, 0x003364, 0x00000000);
@@ -490,14 +467,13 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
			nv_wr32(priv, 0x003244, dma_put);
			nv_wr32(priv, 0x003328, ho_put);
		} else
				if (ib_get != ib_put) {
		if (ib_get != ib_put)
			nv_wr32(priv, 0x003334, ib_put);
				}
	} else {
				nv_error(priv, "DMA_PUSHER - Ch %d Get 0x%08x "
					     "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n",
					chid, dma_get, dma_put, state,
					nv_dma_state_err(state), push);
		nv_error(priv,
			 "DMA_PUSHER - Ch %d Get 0x%08x Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n",
			 chid, dma_get, dma_put, state, nv_dma_state_err(state),
			 push);

		if (dma_get != dma_put)
			nv_wr32(priv, 0x003244, dma_put);
@@ -506,6 +482,32 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
	nv_wr32(priv, 0x003228, 0x00000000);
	nv_wr32(priv, 0x003220, 0x00000001);
	nv_wr32(priv, 0x002100, NV_PFIFO_INTR_DMA_PUSHER);
}

void
nv04_fifo_intr(struct nouveau_subdev *subdev)
{
	struct nouveau_device *device = nv_device(subdev);
	struct nv04_fifo_priv *priv = (void *)subdev;
	uint32_t status, reassign;
	int cnt = 0;

	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) {
			nv04_fifo_cache_error(device, priv, chid, get);
			status &= ~NV_PFIFO_INTR_CACHE_ERROR;
		}

		if (status & NV_PFIFO_INTR_DMA_PUSHER) {
			nv04_fifo_dma_pusher(device, priv, chid);
			status &= ~NV_PFIFO_INTR_DMA_PUSHER;
		}