drm/gf100-/gr: unhardcode attribute cb config

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c
index 11bf8b3..6b903c9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk110b.c
@@ -82,7 +82,7 @@
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nve4_grctx_generate_main,
-	.mods  = nvf0_grctx_generate_mods,
+	.mods  = nve4_grctx_generate_mods,
 	.unkn  = nve4_grctx_generate_unkn,
 	.hub   = nvf0_grctx_pack_hub,
 	.gpc   = nvf0_grctx_pack_gpc,
@@ -97,4 +97,9 @@
 	.bundle_token_limit = 0x600,
 	.pagepool = nve4_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x7ff,
+	.alpha_nr = 0x648,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c
index c560f48..f336fe3 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgk20a.c
@@ -56,4 +56,9 @@
 	.bundle_token_limit = 0x100,
 	.pagepool = nve4_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x240,
+	.attrib_nr = 0x240,
+	.alpha_nr_max = 0x648 + (0x648 / 2),
+	.alpha_nr = 0x648,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
index 5f4d60e..dfd92fa 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxgm107.c
@@ -891,29 +891,47 @@
 }
 
 static void
+gm107_grctx_generate_attrib(struct nvc0_grctx *info)
+{
+	struct nvc0_graph_priv *priv = info->priv;
+	const struct nvc0_grctx_oclass *impl = (void *)nvc0_grctx_impl(priv);
+	const u32  alpha = impl->alpha_nr;
+	const u32 attrib = impl->attrib_nr;
+	const u32   size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+	const u32 access = NV_MEM_ACCESS_RW;
+	const int s = 12;
+	const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
+	const int max_batches = 0xffff;
+	u32 bo = 0;
+	u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
+	int gpc, ppc, n = 0;
+
+	mmio_refn(info, 0x418810, 0x80000000, s, b);
+	mmio_refn(info, 0x419848, 0x10000000, s, b);
+	mmio_refn(info, 0x419c2c, 0x10000000, s, b);
+	mmio_wr32(info, 0x405830, (attrib << 16) | alpha);
+	mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
+
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+		for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++, n++) {
+			const u32 as =  alpha * priv->ppc_tpc_nr[gpc][ppc];
+			const u32 bs = attrib * priv->ppc_tpc_nr[gpc][ppc];
+			const u32 u = 0x418ea0 + (n * 0x04);
+			const u32 o = PPC_UNIT(gpc, ppc, 0);
+			mmio_wr32(info, o + 0xc0, bs);
+			mmio_wr32(info, o + 0xf4, bo);
+			bo += impl->attrib_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+			mmio_wr32(info, o + 0xe4, as);
+			mmio_wr32(info, o + 0xf8, ao);
+			ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+			mmio_wr32(info, u, (0x715 /*XXX*/ << 16) | bs);
+		}
+	}
+}
+
+void
 gm107_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
-	mmio_data(0x200000, 0x1000, NV_MEM_ACCESS_RW);
-
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-	mmio_list(0x419c2c, 0x10000000, 12, 2);
-
-	mmio_list(0x405830, 0x0aa01000,  0, 0);
-	mmio_list(0x4064c4, 0x0400ffff,  0, 0);
-
-	/*XXX*/
-	mmio_list(0x5030c0, 0x00001540,  0, 0);
-	mmio_list(0x5030f4, 0x00000000,  0, 0);
-	mmio_list(0x5030e4, 0x00002000,  0, 0);
-	mmio_list(0x5030f8, 0x00003fc0,  0, 0);
-	mmio_list(0x418ea0, 0x07151540,  0, 0);
-
-	mmio_list(0x5032c0, 0x00001540,  0, 0);
-	mmio_list(0x5032f4, 0x00001fe0,  0, 0);
-	mmio_list(0x5032e4, 0x00002000,  0, 0);
-	mmio_list(0x5032f8, 0x00006fc0,  0, 0);
-	mmio_list(0x418ea4, 0x07151540,  0, 0);
 }
 
 static void
@@ -952,6 +970,7 @@
 
 	oclass->bundle(info);
 	oclass->pagepool(info);
+	oclass->attrib(info);
 	oclass->mods(priv, info);
 	oclass->unkn(priv);
 
@@ -1012,4 +1031,9 @@
 	.bundle_token_limit = 0x2c0,
 	.pagepool = gm107_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = gm107_grctx_generate_attrib,
+	.attrib_nr_max = 0xff0,
+	.attrib_nr = 0xaa0,
+	.alpha_nr_max = 0x1800,
+	.alpha_nr = 0x1000,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
index c3487c4..f322418 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv108.c
@@ -534,31 +534,6 @@
 static void
 nv108_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
-	u32 magic[GPC_MAX][2];
-	u32 offset;
-	int gpc;
-
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-
-	mmio_list(0x405830, 0x02180648,  0, 0);
-	mmio_list(0x4064c4, 0x0192ffff,  0, 0);
-
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
-		u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
-		u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
-		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
-		magic[gpc][1]  = 0x00000000 | (magic1 << 16);
-		offset += 0x0324 * priv->tpc_nr[gpc];
-	}
-
-	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
-		mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
-		offset += 0x07ff * priv->tpc_nr[gpc];
-	}
-
 	mmio_list(0x17e91c, 0x0b040a0b, 0, 0);
 	mmio_list(0x17e920, 0x00090d08, 0, 0);
 }
@@ -590,4 +565,9 @@
 	.bundle_token_limit = 0x200,
 	.pagepool = nve4_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x7ff,
+	.alpha_nr = 0x648,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
index 8dd3a5b..46905a4 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c
@@ -1047,28 +1047,38 @@
 }
 
 void
-nvc0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+nvc0_grctx_generate_attrib(struct nvc0_grctx *info)
 {
+	struct nvc0_graph_priv *priv = info->priv;
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
+	const u32 attrib = impl->attrib_nr;
+	const u32   size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+	const u32 access = NV_MEM_ACCESS_RW;
+	const int s = 12;
+	const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
 	int gpc, tpc;
-	u32 offset;
+	u32 bo = 0;
 
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
+	mmio_refn(info, 0x418810, 0x80000000, s, b);
+	mmio_refn(info, 0x419848, 0x10000000, s, b);
+	mmio_wr32(info, 0x405830, (attrib << 16));
 
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-
-	mmio_list(0x405830, 0x02180000, 0, 0);
-
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
 		for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
-			u32 addr = TPC_UNIT(gpc, tpc, 0x0520);
-			mmio_list(addr, 0x02180000 | offset, 0, 0);
-			offset += 0x0324;
+			const u32 o = TPC_UNIT(gpc, tpc, 0x0520);
+			mmio_skip(info, o, (attrib << 16) | ++bo);
+			mmio_wr32(info, o, (attrib << 16) | --bo);
+			bo += impl->attrib_nr_max;
 		}
 	}
 }
 
 void
+nvc0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+{
+}
+
+void
 nvc0_grctx_generate_unkn(struct nvc0_graph_priv *priv)
 {
 }
@@ -1236,6 +1246,7 @@
 
 	oclass->bundle(info);
 	oclass->pagepool(info);
+	oclass->attrib(info);
 	oclass->mods(priv, info);
 	oclass->unkn(priv);
 
@@ -1376,4 +1387,7 @@
 	.bundle_size = 0x1800,
 	.pagepool = nvc0_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvc0_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h
index 6387a16..fe3fcb9 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.h
@@ -47,6 +47,12 @@
 	/* pagepool */
 	void (*pagepool)(struct nvc0_grctx *);
 	u32 pagepool_size;
+	/* attribute(/alpha) circular buffer */
+	void (*attrib)(struct nvc0_grctx *);
+	u32 attrib_nr_max;
+	u32 attrib_nr;
+	u32 alpha_nr_max;
+	u32 alpha_nr;
 };
 
 static inline const struct nvc0_grctx_oclass *
@@ -60,6 +66,7 @@
 void nvc0_grctx_generate_main(struct nvc0_graph_priv *, struct nvc0_grctx *);
 void nvc0_grctx_generate_bundle(struct nvc0_grctx *);
 void nvc0_grctx_generate_pagepool(struct nvc0_grctx *);
+void nvc0_grctx_generate_attrib(struct nvc0_grctx *);
 void nvc0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
 void nvc0_grctx_generate_unkn(struct nvc0_graph_priv *);
 void nvc0_grctx_generate_tpcid(struct nvc0_graph_priv *);
@@ -69,12 +76,16 @@
 void nvc0_grctx_generate_r406800(struct nvc0_graph_priv *);
 
 extern struct nouveau_oclass *nvc1_grctx_oclass;
+void nvc1_grctx_generate_attrib(struct nvc0_grctx *);
 void nvc1_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
 void nvc1_grctx_generate_unkn(struct nvc0_graph_priv *);
 
 extern struct nouveau_oclass *nvc4_grctx_oclass;
 extern struct nouveau_oclass *nvc8_grctx_oclass;
+
 extern struct nouveau_oclass *nvd7_grctx_oclass;
+void nvd7_grctx_generate_attrib(struct nvc0_grctx *);
+
 extern struct nouveau_oclass *nvd9_grctx_oclass;
 
 extern struct nouveau_oclass *nve4_grctx_oclass;
@@ -86,8 +97,6 @@
 void nve4_grctx_generate_unkn(struct nvc0_graph_priv *);
 void nve4_grctx_generate_r418bb8(struct nvc0_graph_priv *);
 
-void nvf0_grctx_generate_mods(struct nvc0_graph_priv *, struct nvc0_grctx *);
-
 extern struct nouveau_oclass *nvf0_grctx_oclass;
 extern struct nouveau_oclass *gk110b_grctx_oclass;
 extern struct nouveau_oclass *nv108_grctx_oclass;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
index f174204..d9b8f98 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc1.c
@@ -727,33 +727,48 @@
  ******************************************************************************/
 
 void
-nvc1_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+nvc1_grctx_generate_attrib(struct nvc0_grctx *info)
 {
+	struct nvc0_graph_priv *priv = info->priv;
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
+	const u32  alpha = impl->alpha_nr;
+	const u32   beta = impl->attrib_nr;
+	const u32   size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+	const u32 access = NV_MEM_ACCESS_RW;
+	const int s = 12;
+	const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
+	const int timeslice_mode = 1;
+	const int max_batches = 0xffff;
+	u32 bo = 0;
+	u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
 	int gpc, tpc;
-	u32 offset;
 
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
+	mmio_refn(info, 0x418810, 0x80000000, s, b);
+	mmio_refn(info, 0x419848, 0x10000000, s, b);
+	mmio_wr32(info, 0x405830, (beta << 16) | alpha);
+	mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
 
-	mmio_list(0x405830, 0x02180218, 0, 0);
-	mmio_list(0x4064c4, 0x0086ffff, 0, 0);
-
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
 		for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
-			u32 addr = TPC_UNIT(gpc, tpc, 0x0520);
-			mmio_list(addr, 0x12180000 | offset, 0, 0);
-			offset += 0x0324;
-		}
-		for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
-			u32 addr = TPC_UNIT(gpc, tpc, 0x0544);
-			mmio_list(addr, 0x02180000 | offset, 0, 0);
-			offset += 0x0324;
+			const u32 a = alpha;
+			const u32 b =  beta;
+			const u32 t = timeslice_mode;
+			const u32 o = TPC_UNIT(gpc, tpc, 0x500);
+			mmio_skip(info, o + 0x20, (t << 28) | (b << 16) | ++bo);
+			mmio_wr32(info, o + 0x20, (t << 28) | (b << 16) | --bo);
+			bo += impl->attrib_nr_max;
+			mmio_wr32(info, o + 0x44, (a << 16) | ao);
+			ao += impl->alpha_nr_max;
 		}
 	}
 }
 
 void
+nvc1_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
+{
+}
+
+void
 nvc1_grctx_generate_unkn(struct nvc0_graph_priv *priv)
 {
 	nv_mask(priv, 0x418c6c, 0x00000001, 0x00000001);
@@ -788,4 +803,9 @@
 	.bundle_size = 0x1800,
 	.pagepool = nvc0_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvc1_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x324,
+	.alpha_nr = 0x218,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c
index ec7f32a..8d84dff 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc4.c
@@ -104,4 +104,7 @@
 	.bundle_size = 0x1800,
 	.pagepool = nvc0_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvc0_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
index de05868..93f9b60 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc8.c
@@ -355,4 +355,7 @@
 	.bundle_size = 0x1800,
 	.pagepool = nvc0_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvc0_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
index ce016ac..05b7653 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd7.c
@@ -177,33 +177,46 @@
  * PGRAPH context implementation
  ******************************************************************************/
 
+void
+nvd7_grctx_generate_attrib(struct nvc0_grctx *info)
+{
+	struct nvc0_graph_priv *priv = info->priv;
+	const struct nvc0_grctx_oclass *impl = nvc0_grctx_impl(priv);
+	const u32  alpha = impl->alpha_nr;
+	const u32   beta = impl->attrib_nr;
+	const u32   size = 0x20 * (impl->attrib_nr_max + impl->alpha_nr_max);
+	const u32 access = NV_MEM_ACCESS_RW;
+	const int s = 12;
+	const int b = mmio_vram(info, size * priv->tpc_total, (1 << s), access);
+	const int timeslice_mode = 1;
+	const int max_batches = 0xffff;
+	u32 bo = 0;
+	u32 ao = bo + impl->attrib_nr_max * priv->tpc_total;
+	int gpc, ppc;
+
+	mmio_refn(info, 0x418810, 0x80000000, s, b);
+	mmio_refn(info, 0x419848, 0x10000000, s, b);
+	mmio_wr32(info, 0x405830, (beta << 16) | alpha);
+	mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
+
+	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+		for (ppc = 0; ppc < priv->ppc_nr[gpc]; ppc++) {
+			const u32 a = alpha * priv->ppc_tpc_nr[gpc][ppc];
+			const u32 b =  beta * priv->ppc_tpc_nr[gpc][ppc];
+			const u32 t = timeslice_mode;
+			const u32 o = PPC_UNIT(gpc, ppc, 0);
+			mmio_skip(info, o + 0xc0, (t << 28) | (b << 16) | ++bo);
+			mmio_wr32(info, o + 0xc0, (t << 28) | (b << 16) | --bo);
+			bo += impl->attrib_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+			mmio_wr32(info, o + 0xe4, (a << 16) | ao);
+			ao += impl->alpha_nr_max * priv->ppc_tpc_nr[gpc][ppc];
+		}
+	}
+}
+
 static void
 nvd7_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
-	u32 magic[GPC_MAX][2];
-	u32 offset;
-	int gpc;
-
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-
-	mmio_list(0x405830, 0x02180324,  0, 0);
-	mmio_list(0x4064c4, 0x00c9ffff,  0, 0);
-
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
-		u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
-		u16 magic1 = 0x0324 * priv->tpc_nr[gpc];
-		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
-		magic[gpc][1]  = 0x00000000 | (magic1 << 16);
-		offset += 0x0324 * priv->tpc_nr[gpc];
-	}
-
-	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
-		mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
-		offset += 0x07ff * priv->tpc_nr[gpc];
-	}
 	mmio_list(0x17e91c, 0x03060609, 0, 0); /* different from kepler */
 }
 
@@ -225,6 +238,7 @@
 
 	oclass->bundle(info);
 	oclass->pagepool(info);
+	oclass->attrib(info);
 	oclass->mods(priv, info);
 	oclass->unkn(priv);
 
@@ -268,4 +282,9 @@
 	.bundle_size = 0x1800,
 	.pagepool = nvc0_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x7ff,
+	.alpha_nr = 0x324,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
index b2b0f70..e5808a8 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvd9.c
@@ -523,4 +523,9 @@
 	.bundle_size = 0x1800,
 	.pagepool = nvc0_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvc1_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x324,
+	.alpha_nr = 0x218,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
index 9dfb60d..22de56b 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve4.c
@@ -872,31 +872,6 @@
 void
 nve4_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
 {
-	u32 magic[GPC_MAX][2];
-	u32 offset;
-	int gpc;
-
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-
-	mmio_list(0x405830, 0x02180648,  0, 0);
-	mmio_list(0x4064c4, 0x0192ffff,  0, 0);
-
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
-		u16 magic0 = 0x0218 * priv->tpc_nr[gpc];
-		u16 magic1 = 0x0648 * priv->tpc_nr[gpc];
-		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
-		magic[gpc][1]  = 0x00000000 | (magic1 << 16);
-		offset += 0x0324 * priv->tpc_nr[gpc];
-	}
-
-	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
-		mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
-		offset += 0x07ff * priv->tpc_nr[gpc];
-	}
-
 	mmio_list(0x17e91c, 0x06060609, 0, 0);
 	mmio_list(0x17e920, 0x00090a05, 0, 0);
 }
@@ -988,6 +963,7 @@
 
 	oclass->bundle(info);
 	oclass->pagepool(info);
+	oclass->attrib(info);
 	oclass->mods(priv, info);
 	oclass->unkn(priv);
 
@@ -1045,4 +1021,9 @@
 	.bundle_token_limit = 0x600,
 	.pagepool = nve4_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x7ff,
+	.alpha_nr = 0x648,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
index e25ec47..4400b1d 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvf0.c
@@ -809,46 +809,6 @@
  * PGRAPH context implementation
  ******************************************************************************/
 
-void
-nvf0_grctx_generate_mods(struct nvc0_graph_priv *priv, struct nvc0_grctx *info)
-{
-	u32 magic[GPC_MAX][4];
-	u32 offset;
-	int gpc;
-
-	mmio_data(0x060000, 0x1000, NV_MEM_ACCESS_RW);
-	mmio_list(0x418810, 0x80000000, 12, 2);
-	mmio_list(0x419848, 0x10000000, 12, 2);
-
-	mmio_list(0x405830, 0x02180648,  0, 0);
-	mmio_list(0x4064c4, 0x0192ffff,  0, 0);
-
-	for (gpc = 0, offset = 0; gpc < priv->gpc_nr; gpc++) {
-		u16 magic0 = 0x0218 * (priv->tpc_nr[gpc] - 1);
-		u16 magic1 = 0x0648 * (priv->tpc_nr[gpc] - 1);
-		u16 magic2 = 0x0218;
-		u16 magic3 = 0x0648;
-		magic[gpc][0]  = 0x10000000 | (magic0 << 16) | offset;
-		magic[gpc][1]  = 0x00000000 | (magic1 << 16);
-		offset += 0x0324 * (priv->tpc_nr[gpc] - 1);
-		magic[gpc][2]  = 0x10000000 | (magic2 << 16) | offset;
-		magic[gpc][3]  = 0x00000000 | (magic3 << 16);
-		offset += 0x0324;
-	}
-
-	for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-		mmio_list(GPC_UNIT(gpc, 0x30c0), magic[gpc][0], 0, 0);
-		mmio_list(GPC_UNIT(gpc, 0x30e4), magic[gpc][1] | offset, 0, 0);
-		offset += 0x07ff * (priv->tpc_nr[gpc] - 1);
-		mmio_list(GPC_UNIT(gpc, 0x32c0), magic[gpc][2], 0, 0);
-		mmio_list(GPC_UNIT(gpc, 0x32e4), magic[gpc][3] | offset, 0, 0);
-		offset += 0x07ff;
-	}
-
-	mmio_list(0x17e91c, 0x06060609, 0, 0);
-	mmio_list(0x17e920, 0x00090a05, 0, 0);
-}
-
 struct nouveau_oclass *
 nvf0_grctx_oclass = &(struct nvc0_grctx_oclass) {
 	.base.handle = NV_ENGCTX(GR, 0xf0),
@@ -861,7 +821,7 @@
 		.wr32 = _nouveau_graph_context_wr32,
 	},
 	.main  = nve4_grctx_generate_main,
-	.mods  = nvf0_grctx_generate_mods,
+	.mods  = nve4_grctx_generate_mods,
 	.unkn  = nve4_grctx_generate_unkn,
 	.hub   = nvf0_grctx_pack_hub,
 	.gpc   = nvf0_grctx_pack_gpc,
@@ -876,4 +836,9 @@
 	.bundle_token_limit = 0x7c0,
 	.pagepool = nve4_grctx_generate_pagepool,
 	.pagepool_size = 0x8000,
+	.attrib = nvd7_grctx_generate_attrib,
+	.attrib_nr_max = 0x324,
+	.attrib_nr = 0x218,
+	.alpha_nr_max = 0x7ff,
+	.alpha_nr = 0x648,
 }.base;