diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2011-09-15 15:08:05 +0200 | 
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2011-09-15 15:08:18 +0200 | 
| commit | e060c38434b2caa78efe7cedaff4191040b65a15 (patch) | |
| tree | 407361230bf6733f63d8e788e4b5e6566ee04818 /drivers/gpu/drm/nouveau/nv40_graph.c | |
| parent | 10e4ac572eeffe5317019bd7330b6058a400dfc2 (diff) | |
| parent | cc39c6a9bbdebfcf1a7dee64d83bf302bc38d941 (diff) | |
| download | olio-linux-3.10-e060c38434b2caa78efe7cedaff4191040b65a15.tar.xz olio-linux-3.10-e060c38434b2caa78efe7cedaff4191040b65a15.zip  | |
Merge branch 'master' into for-next
Fast-forward merge with Linus to be able to merge patches
based on more recent version of the tree.
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv40_graph.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv40_graph.c | 112 | 
1 files changed, 20 insertions, 92 deletions
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index 5beb01b8ace..ba14a93d8af 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c @@ -35,89 +35,6 @@ struct nv40_graph_engine {  	u32 grctx_size;  }; -static struct nouveau_channel * -nv40_graph_channel(struct drm_device *dev) -{ -	struct drm_nouveau_private *dev_priv = dev->dev_private; -	struct nouveau_gpuobj *grctx; -	uint32_t inst; -	int i; - -	inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); -	if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) -		return NULL; -	inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; - -	for (i = 0; i < dev_priv->engine.fifo.channels; i++) { -		if (!dev_priv->channels.ptr[i]) -			continue; - -		grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; -		if (grctx && grctx->pinst == inst) -			return dev_priv->channels.ptr[i]; -	} - -	return NULL; -} - -static int -nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) -{ -	uint32_t old_cp, tv = 1000, tmp; -	int i; - -	old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER); -	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); - -	tmp  = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310); -	tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE : -		      NV40_PGRAPH_CTXCTL_0310_XFER_LOAD; -	nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp); - -	tmp  = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304); -	tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX; -	nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp); - -	nouveau_wait_for_idle(dev); - -	for (i = 0; i < tv; i++) { -		if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0) -			break; -	} - -	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp); - -	if (i == tv) { -		uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT); -		NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save); -		NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n", -			 ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT, -			 ucstat  & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK); -		NV_ERROR(dev, "0x40030C = 0x%08x\n", -			 nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C)); -		return -EBUSY; -	} - -	return 0; -} - -static int -nv40_graph_unload_context(struct drm_device *dev) -{ -	uint32_t inst; -	int ret; - -	inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); -	if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) -		return 0; -	inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE; - -	ret = nv40_graph_transfer_context(dev, inst, 1); - -	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); -	return ret; -} -  static int  nv40_graph_context_new(struct nouveau_channel *chan, int engine)  { @@ -163,16 +80,16 @@ nv40_graph_context_del(struct nouveau_channel *chan, int engine)  	struct nouveau_gpuobj *grctx = chan->engctx[engine];  	struct drm_device *dev = chan->dev;  	struct drm_nouveau_private *dev_priv = dev->dev_private; +	u32 inst = 0x01000000 | (grctx->pinst >> 4);  	unsigned long flags;  	spin_lock_irqsave(&dev_priv->context_switch_lock, flags); -	nv04_graph_fifo_access(dev, false); - -	/* Unload the context if it's the currently active one */ -	if (nv40_graph_channel(dev) == chan) -		nv40_graph_unload_context(dev); - -	nv04_graph_fifo_access(dev, true); +	nv_mask(dev, 0x400720, 0x00000000, 0x00000001); +	if (nv_rd32(dev, 0x40032c) == inst) +		nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); +	if (nv_rd32(dev, 0x400330) == inst) +		nv_mask(dev, 0x400330, 0x01000000, 0x00000000); +	nv_mask(dev, 0x400720, 0x00000001, 0x00000001);  	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);  	/* Free the context resources */ @@ -429,9 +346,20 @@ nv40_graph_init(struct drm_device *dev, int engine)  }  static int -nv40_graph_fini(struct drm_device *dev, int engine) +nv40_graph_fini(struct drm_device *dev, int engine, bool suspend)  { -	nv40_graph_unload_context(dev); +	u32 inst = nv_rd32(dev, 0x40032c); +	if (inst & 0x01000000) { +		nv_wr32(dev, 0x400720, 0x00000000); +		nv_wr32(dev, 0x400784, inst); +		nv_mask(dev, 0x400310, 0x00000020, 0x00000020); +		nv_mask(dev, 0x400304, 0x00000001, 0x00000001); +		if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) { +			u32 insn = nv_rd32(dev, 0x400308); +			NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn); +		} +		nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); +	}  	return 0;  }  |