[kernel/f16] nouveau: fix accel on GF108 and enable on GF108/GF110

Ben Skeggs bskeggs at fedoraproject.org
Thu Dec 8 00:44:28 UTC 2011


commit 5a7d4b130b111cc6da283a680b70883e1e6a4fa9
Author: Ben Skeggs <bskeggs at redhat.com>
Date:   Thu Dec 8 10:42:31 2011 +1000

    nouveau: fix accel on GF108 and enable on GF108/GF110

 drm-nouveau-gf108.patch |  151 +++++++++++++++++++++++++++++++++++++++++++++++
 kernel.spec             |    7 ++-
 2 files changed, 157 insertions(+), 1 deletions(-)
---
diff --git a/drm-nouveau-gf108.patch b/drm-nouveau-gf108.patch
new file mode 100644
index 0000000..80f0d9b
--- /dev/null
+++ b/drm-nouveau-gf108.patch
@@ -0,0 +1,151 @@
+diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
+index 82478e0..d8831ab 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_state.c
++++ b/drivers/gpu/drm/nouveau/nouveau_state.c
+@@ -579,6 +579,14 @@ nouveau_card_init(struct drm_device *dev)
+ 	if (ret)
+ 		goto out_display_early;
+ 
++	/* workaround an odd issue on nvc1 by disabling the device's
++	 * nosnoop capability.  hopefully won't cause issues until a
++	 * better fix is found - assuming there is one...
++	 */
++	if (dev_priv->chipset == 0xc1) {
++		nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
++	}
++
+ 	nouveau_pm_init(dev);
+ 
+ 	ret = engine->vram.init(dev);
+@@ -1102,12 +1110,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
+ 	dev_priv->noaccel = !!nouveau_noaccel;
+ 	if (nouveau_noaccel == -1) {
+ 		switch (dev_priv->chipset) {
+-		case 0xc1: /* known broken */
+-		case 0xc8: /* never tested */
++#if 0
++		case 0xXX: /* known broken */
+ 			NV_INFO(dev, "acceleration disabled by default, pass "
+ 				     "noaccel=0 to force enable\n");
+ 			dev_priv->noaccel = true;
+ 			break;
++#endif
+ 		default:
+ 			dev_priv->noaccel = false;
+ 			break;
+diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c
+index 4b8d0b3..3cc1c60 100644
+--- a/drivers/gpu/drm/nouveau/nvc0_graph.c
++++ b/drivers/gpu/drm/nouveau/nvc0_graph.c
+@@ -156,8 +156,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
+ 	struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
+ 	struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
+ 	struct drm_device *dev = chan->dev;
++	struct drm_nouveau_private *dev_priv = dev->dev_private;
+ 	int i = 0, gpc, tp, ret;
+-	u32 magic;
+ 
+ 	ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
+ 				 &grch->unk408004);
+@@ -206,14 +206,37 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
+ 	nv_wo32(grch->mmio, i++ * 4, 0x0041880c);
+ 	nv_wo32(grch->mmio, i++ * 4, 0x80000018);
+ 
+-	magic = 0x02180000;
+-	nv_wo32(grch->mmio, i++ * 4, 0x00405830);
+-	nv_wo32(grch->mmio, i++ * 4, magic);
+-	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+-		for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) {
+-			u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
+-			nv_wo32(grch->mmio, i++ * 4, reg);
+-			nv_wo32(grch->mmio, i++ * 4, magic);
++	if (dev_priv->chipset != 0xc1) {
++		u32 magic = 0x02180000;
++		nv_wo32(grch->mmio, i++ * 4, 0x00405830);
++		nv_wo32(grch->mmio, i++ * 4, magic);
++		for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
++			for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
++				u32 reg = TP_UNIT(gpc, tp, 0x520);
++				nv_wo32(grch->mmio, i++ * 4, reg);
++				nv_wo32(grch->mmio, i++ * 4, magic);
++				magic += 0x0324;
++			}
++		}
++	} else {
++		u32 magic = 0x02180000;
++		nv_wo32(grch->mmio, i++ * 4, 0x00405830);
++		nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218);
++		nv_wo32(grch->mmio, i++ * 4, 0x004064c4);
++		nv_wo32(grch->mmio, i++ * 4, 0x0086ffff);
++		for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
++			for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
++				u32 reg = TP_UNIT(gpc, tp, 0x520);
++				nv_wo32(grch->mmio, i++ * 4, reg);
++				nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic);
++				magic += 0x0324;
++			}
++			for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
++				u32 reg = TP_UNIT(gpc, tp, 0x544);
++				nv_wo32(grch->mmio, i++ * 4, reg);
++				nv_wo32(grch->mmio, i++ * 4, magic);
++				magic += 0x0324;
++			}
+ 		}
+ 	}
+ 
+diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c
+index dd0e6a7..96b0b93d 100644
+--- a/drivers/gpu/drm/nouveau/nvc0_grctx.c
++++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c
+@@ -1812,6 +1812,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
+ 		/* calculate first set of magics */
+ 		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
+ 
++		gpc = -1;
+ 		for (tp = 0; tp < priv->tp_total; tp++) {
+ 			do {
+ 				gpc = (gpc + 1) % priv->gpc_nr;
+@@ -1861,30 +1862,26 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
+ 
+ 	if (1) {
+ 		u32 tp_mask = 0, tp_set = 0;
+-		u8  tpnr[GPC_MAX];
++		u8  tpnr[GPC_MAX], a, b;
+ 
+ 		memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
+ 		for (gpc = 0; gpc < priv->gpc_nr; gpc++)
+ 			tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8);
+ 
+-		gpc = -1;
+-		for (i = 0, gpc = -1; i < 32; i++) {
+-			int ltp = i * (priv->tp_total - 1) / 32;
+-
+-			do {
+-				gpc = (gpc + 1) % priv->gpc_nr;
+-			} while (!tpnr[gpc]);
+-			tp = priv->tp_nr[gpc] - tpnr[gpc]--;
++		for (i = 0, gpc = -1, b = -1; i < 32; i++) {
++			a = (i * (priv->tp_total - 1)) / 32;
++			if (a != b) {
++				b = a;
++				do {
++					gpc = (gpc + 1) % priv->gpc_nr;
++				} while (!tpnr[gpc]);
++				tp = priv->tp_nr[gpc] - tpnr[gpc]--;
+ 
+-			tp_set |= 1 << ((gpc * 8) + tp);
++				tp_set |= 1 << ((gpc * 8) + tp);
++			}
+ 
+-			do {
+-				nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
+-				tp_set ^= tp_mask;
+-				nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set);
+-				tp_set ^= tp_mask;
+-			} while (ltp == (++i * (priv->tp_total - 1) / 32));
+-			i--;
++			nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
++			nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask);
+ 		}
+ 	}
+ 
diff --git a/kernel.spec b/kernel.spec
index 523bb42..4e5f07b 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -54,7 +54,7 @@ Summary: The Linux kernel
 # For non-released -rc kernels, this will be appended after the rcX and
 # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
 #
-%global baserelease 1
+%global baserelease 2
 %global fedora_build %{baserelease}
 
 # base_sublevel is the kernel version we're starting with and patching
@@ -700,6 +700,7 @@ Patch1500: fix_xen_guest_on_old_EC2.patch
 
 # nouveau + drm fixes
 Patch1810: drm-nouveau-updates.patch
+Patch1811: drm-nouveau-gf108.patch
 # intel drm is all merged upstream
 Patch1824: drm-intel-next.patch
 # hush the i915 fbc noise
@@ -1379,6 +1380,7 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch
 
 # Nouveau DRM
 ApplyOptionalPatch drm-nouveau-updates.patch
+ApplyPatch drm-nouveau-gf108.patch
 
 # Intel DRM
 ApplyOptionalPatch drm-intel-next.patch
@@ -2198,6 +2200,9 @@ fi
 # and build.
 
 %changelog
+* Thu Dec 08 2011 Ben Skeggs <bskeggs at redhat.com> 3.1.5-0.rc1.2
+- nouveau: fix accel on GF108 and enable on GF108/GF110
+
 * Wed Dec 07 2011 Chuck Ebbert <cebbert at redhat.com> 3.1.5-0.rc1.1
 - Linux 3.1.5-rc1
 - Comment out merged patches:


More information about the scm-commits mailing list