diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/core/engine/graph')
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c | 51 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nv20.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nv25.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nv30.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nv34.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nv35.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nv40.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | 230 |
15 files changed, 324 insertions, 44 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c index 0b7951a8594..4cc6269d407 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnvc0.c @@ -36,7 +36,6 @@ int nvc0_grctx_init(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) { struct nouveau_bar *bar = nouveau_bar(priv); - struct nouveau_object *parent = nv_object(priv); struct nouveau_gpuobj *chan; u32 size = (0x80000 + priv->size + 4095) & ~4095; int ret, i; @@ -44,7 +43,7 @@ nvc0_grctx_init(struct nvc0_graph_priv *priv, struct nvc0_grctx *info) /* allocate memory to for a "channel", which we'll use to generate * the default context values */ - ret = nouveau_gpuobj_new(parent, NULL, size, 0x1000, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, size, 0x1000, NVOBJ_FLAG_ZERO_ALLOC, &info->chan); chan = info->chan; if (ret) { @@ -1399,7 +1398,7 @@ nvc0_grctx_generate_90c0(struct nvc0_graph_priv *priv) { int i; - for (i = 0; nv_device(priv)->chipset == 0xd9 && i < 4; i++) { + for (i = 0; nv_device(priv)->chipset >= 0xd0 && i < 4; i++) { nv_mthd(priv, 0x90c0, 0x2700 + (i * 0x40), 0x00000000); nv_mthd(priv, 0x90c0, 0x2720 + (i * 0x40), 0x00000000); nv_mthd(priv, 0x90c0, 0x2704 + (i * 0x40), 0x00000000); @@ -1415,7 +1414,7 @@ nvc0_grctx_generate_90c0(struct nvc0_graph_priv *priv) nv_mthd(priv, 0x90c0, 0x27ac, 0x00000000); nv_mthd(priv, 0x90c0, 0x27cc, 0x00000000); nv_mthd(priv, 0x90c0, 0x27ec, 0x00000000); - for (i = 0; nv_device(priv)->chipset == 0xd9 && i < 4; i++) { + for (i = 0; nv_device(priv)->chipset >= 0xd0 && i < 4; i++) { nv_mthd(priv, 0x90c0, 0x2710 + (i * 0x40), 0x00014000); nv_mthd(priv, 0x90c0, 0x2730 + (i * 0x40), 0x00014000); nv_mthd(priv, 0x90c0, 0x2714 + (i * 0x40), 0x00000040); @@ -1615,7 +1614,7 @@ static void nvc0_grctx_generate_shaders(struct nvc0_graph_priv *priv) { - if (nv_device(priv)->chipset == 0xd9) { + if (nv_device(priv)->chipset >= 0xd0) { nv_wr32(priv, 0x405800, 0x0f8000bf); nv_wr32(priv, 0x405830, 0x02180218); nv_wr32(priv, 0x405834, 0x08000000); @@ -1658,10 +1657,10 @@ nvc0_grctx_generate_unk64xx(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x4064ac, 0x00003fff); nv_wr32(priv, 0x4064b4, 0x00000000); nv_wr32(priv, 0x4064b8, 0x00000000); - if (nv_device(priv)->chipset == 0xd9) + if (nv_device(priv)->chipset >= 0xd0) nv_wr32(priv, 0x4064bc, 0x00000000); if (nv_device(priv)->chipset == 0xc1 || - nv_device(priv)->chipset == 0xd9) { + nv_device(priv)->chipset >= 0xd0) { nv_wr32(priv, 0x4064c0, 0x80140078); nv_wr32(priv, 0x4064c4, 0x0086ffff); } @@ -1701,7 +1700,7 @@ nvc0_grctx_generate_rop(struct nvc0_graph_priv *priv) /* ROPC_BROADCAST */ nv_wr32(priv, 0x408800, 0x02802a3c); nv_wr32(priv, 0x408804, 0x00000040); - if (chipset == 0xd9) { + if (chipset >= 0xd0) { nv_wr32(priv, 0x408808, 0x1043e005); nv_wr32(priv, 0x408900, 0x3080b801); nv_wr32(priv, 0x408904, 0x1043e005); @@ -1735,7 +1734,7 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x418408, 0x00000000); nv_wr32(priv, 0x41840c, 0x00001008); nv_wr32(priv, 0x418410, 0x0fff0fff); - nv_wr32(priv, 0x418414, chipset != 0xd9 ? 0x00200fff : 0x02200fff); + nv_wr32(priv, 0x418414, chipset < 0xd0 ? 0x00200fff : 0x02200fff); nv_wr32(priv, 0x418450, 0x00000000); nv_wr32(priv, 0x418454, 0x00000000); nv_wr32(priv, 0x418458, 0x00000000); @@ -1750,14 +1749,14 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x418700, 0x00000002); nv_wr32(priv, 0x418704, 0x00000080); nv_wr32(priv, 0x418708, 0x00000000); - nv_wr32(priv, 0x41870c, chipset != 0xd9 ? 0x07c80000 : 0x00000000); + nv_wr32(priv, 0x41870c, chipset < 0xd0 ? 0x07c80000 : 0x00000000); nv_wr32(priv, 0x418710, 0x00000000); - nv_wr32(priv, 0x418800, chipset != 0xd9 ? 0x0006860a : 0x7006860a); + nv_wr32(priv, 0x418800, chipset < 0xd0 ? 0x0006860a : 0x7006860a); nv_wr32(priv, 0x418808, 0x00000000); nv_wr32(priv, 0x41880c, 0x00000000); nv_wr32(priv, 0x418810, 0x00000000); nv_wr32(priv, 0x418828, 0x00008442); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x418830, 0x10000001); else nv_wr32(priv, 0x418830, 0x00000001); @@ -1768,7 +1767,7 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x4188f0, 0x00000000); nv_wr32(priv, 0x4188f4, 0x00000000); nv_wr32(priv, 0x4188f8, 0x00000000); - if (chipset == 0xd9) + if (chipset >= 0xd0) nv_wr32(priv, 0x4188fc, 0x20100008); else if (chipset == 0xc1) nv_wr32(priv, 0x4188fc, 0x00100018); @@ -1787,7 +1786,7 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x418a14 + (i * 0x20), 0x00000000); nv_wr32(priv, 0x418a18 + (i * 0x20), 0x00000000); } - nv_wr32(priv, 0x418b00, chipset != 0xd9 ? 0x00000000 : 0x00000006); + nv_wr32(priv, 0x418b00, chipset < 0xd0 ? 0x00000000 : 0x00000006); nv_wr32(priv, 0x418b08, 0x0a418820); nv_wr32(priv, 0x418b0c, 0x062080e6); nv_wr32(priv, 0x418b10, 0x020398a4); @@ -1804,7 +1803,7 @@ nvc0_grctx_generate_gpc(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x418c24, 0x00000000); nv_wr32(priv, 0x418c28, 0x00000000); nv_wr32(priv, 0x418c2c, 0x00000000); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x418c6c, 0x00000001); nv_wr32(priv, 0x418c80, 0x20200004); nv_wr32(priv, 0x418c8c, 0x00000001); @@ -1823,7 +1822,7 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x419818, 0x00000000); nv_wr32(priv, 0x41983c, 0x00038bc7); nv_wr32(priv, 0x419848, 0x00000000); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x419864, 0x00000129); else nv_wr32(priv, 0x419864, 0x0000012a); @@ -1836,7 +1835,7 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x419a14, 0x00000200); nv_wr32(priv, 0x419a1c, 0x00000000); nv_wr32(priv, 0x419a20, 0x00000800); - if (chipset == 0xd9) + if (chipset >= 0xd0) nv_wr32(priv, 0x00419ac4, 0x0017f440); else if (chipset != 0xc0 && chipset != 0xc8) nv_wr32(priv, 0x00419ac4, 0x0007f440); @@ -1847,16 +1846,16 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x419b10, 0x0a418820); nv_wr32(priv, 0x419b14, 0x000000e6); nv_wr32(priv, 0x419bd0, 0x00900103); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x419be0, 0x00400001); else nv_wr32(priv, 0x419be0, 0x00000001); nv_wr32(priv, 0x419be4, 0x00000000); - nv_wr32(priv, 0x419c00, chipset != 0xd9 ? 0x00000002 : 0x0000000a); + nv_wr32(priv, 0x419c00, chipset < 0xd0 ? 0x00000002 : 0x0000000a); nv_wr32(priv, 0x419c04, 0x00000006); nv_wr32(priv, 0x419c08, 0x00000002); nv_wr32(priv, 0x419c20, 0x00000000); - if (nv_device(priv)->chipset == 0xd9) { + if (nv_device(priv)->chipset >= 0xd0) { nv_wr32(priv, 0x419c24, 0x00084210); nv_wr32(priv, 0x419c28, 0x3cf3cf3c); nv_wr32(priv, 0x419cb0, 0x00020048); @@ -1868,12 +1867,12 @@ nvc0_grctx_generate_tp(struct nvc0_graph_priv *priv) } nv_wr32(priv, 0x419ce8, 0x00000000); nv_wr32(priv, 0x419cf4, 0x00000183); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x419d20, 0x12180000); else nv_wr32(priv, 0x419d20, 0x02180000); nv_wr32(priv, 0x419d24, 0x00001fff); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1 || chipset >= 0xd0) nv_wr32(priv, 0x419d44, 0x02180218); nv_wr32(priv, 0x419e04, 0x00000000); nv_wr32(priv, 0x419e08, 0x00000000); @@ -2210,7 +2209,7 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv) nv_icmd(priv, 0x00000215, 0x00000040); nv_icmd(priv, 0x00000216, 0x00000040); nv_icmd(priv, 0x00000217, 0x00000040); - if (nv_device(priv)->chipset == 0xd9) { + if (nv_device(priv)->chipset >= 0xd0) { for (i = 0x0400; i <= 0x0417; i++) nv_icmd(priv, i, 0x00000040); } @@ -2222,7 +2221,7 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv) nv_icmd(priv, 0x0000021d, 0x0000c080); nv_icmd(priv, 0x0000021e, 0x0000c080); nv_icmd(priv, 0x0000021f, 0x0000c080); - if (nv_device(priv)->chipset == 0xd9) { + if (nv_device(priv)->chipset >= 0xd0) { for (i = 0x0440; i <= 0x0457; i++) nv_icmd(priv, i, 0x0000c080); } @@ -2789,7 +2788,7 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv) nv_icmd(priv, 0x00000585, 0x0000003f); nv_icmd(priv, 0x00000576, 0x00000003); if (nv_device(priv)->chipset == 0xc1 || - nv_device(priv)->chipset == 0xd9) + nv_device(priv)->chipset >= 0xd0) nv_icmd(priv, 0x0000057b, 0x00000059); nv_icmd(priv, 0x00000586, 0x00000040); nv_icmd(priv, 0x00000582, 0x00000080); @@ -2891,7 +2890,7 @@ nvc0_grctx_generate(struct nvc0_graph_priv *priv) nv_icmd(priv, 0x00000957, 0x00000003); nv_icmd(priv, 0x0000095e, 0x20164010); nv_icmd(priv, 0x0000095f, 0x00000020); - if (nv_device(priv)->chipset == 0xd9) + if (nv_device(priv)->chipset >= 0xd0) nv_icmd(priv, 0x0000097d, 0x00000020); nv_icmd(priv, 0x00000683, 0x00000006); nv_icmd(priv, 0x00000685, 0x003fffff); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c index 6d8c63931ee..ae27dae3fe3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnve0.c @@ -2772,10 +2772,15 @@ nve0_grctx_generate(struct nvc0_graph_priv *priv) for (i = 0; i < 8; i++) nv_wr32(priv, 0x4064d0 + (i * 0x04), 0x00000000); - nv_wr32(priv, 0x405b00, 0x201); - nv_wr32(priv, 0x408850, 0x2); - nv_wr32(priv, 0x408958, 0x2); - nv_wr32(priv, 0x419f78, 0xa); + nv_wr32(priv, 0x405b00, (priv->tpc_total << 8) | priv->gpc_nr); + if (priv->gpc_nr == 1) { + nv_mask(priv, 0x408850, 0x0000000f, priv->tpc_nr[0]); + nv_mask(priv, 0x408958, 0x0000000f, priv->tpc_nr[0]); + } else { + nv_mask(priv, 0x408850, 0x0000000f, priv->gpc_nr); + nv_mask(priv, 0x408958, 0x0000000f, priv->gpc_nr); + } + nv_mask(priv, 0x419f78, 0x00000001, 0x00000000); nve0_grctx_generate_icmd(priv); nve0_grctx_generate_a097(priv); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc index b86cc60dcd5..f7055af0f2a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/gpcnvc0.fuc @@ -87,6 +87,11 @@ chipsets: .b16 #nvd9_gpc_mmio_tail .b16 #nvd9_tpc_mmio_head .b16 #nvd9_tpc_mmio_tail +.b8 0xd7 0 0 0 +.b16 #nvd9_gpc_mmio_head +.b16 #nvd9_gpc_mmio_tail +.b16 #nvd9_tpc_mmio_head +.b16 #nvd9_tpc_mmio_tail .b8 0 0 0 0 // GPC mmio lists diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc index 0bcfa4d447e..7fbdebb2baf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc +++ b/drivers/gpu/drm/nouveau/core/engine/graph/fuc/hubnvc0.fuc @@ -62,6 +62,9 @@ chipsets: .b8 0xd9 0 0 0 .b16 #nvd9_hub_mmio_head .b16 #nvd9_hub_mmio_tail +.b8 0xd7 0 0 0 +.b16 #nvd9_hub_mmio_head +.b16 #nvd9_hub_mmio_tail .b8 0 0 0 0 nvc0_hub_mmio_head: diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index 0607b980174..b2455931590 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -254,7 +254,7 @@ nv20_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c index b2b650dd8b2..7a80d005a97 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv25.c @@ -142,7 +142,7 @@ nv25_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c index 700462fa0ae..3e1f32ee43d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv2a.c @@ -109,7 +109,7 @@ nv2a_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c index cedadaa92d3..e451db32e92 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv30.c @@ -143,7 +143,7 @@ nv30_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c index 273f6320027..9385ac7b44a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv34.c @@ -143,7 +143,7 @@ nv34_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c index f40ee2116ee..9ce84b73f86 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv35.c @@ -141,7 +141,7 @@ nv35_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, 32 * 4, 16, + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 32 * 4, 16, NVOBJ_FLAG_ZERO_ALLOC, &priv->ctxtab); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 17049d5c723..193a5de1b48 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -46,6 +46,14 @@ struct nv40_graph_chan { struct nouveau_graph_chan base; }; +static u64 +nv40_graph_units(struct nouveau_graph *graph) +{ + struct nv40_graph_priv *priv = (void *)graph; + + return nv_rd32(priv, 0x1540); +} + /******************************************************************************* * Graphics object classes ******************************************************************************/ @@ -359,6 +367,8 @@ nv40_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, else nv_engine(priv)->sclass = nv40_graph_sclass; nv_engine(priv)->tile_prog = nv40_graph_tile_prog; + + priv->base.units = nv40_graph_units; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index f2b1a7a124f..1ac36110ca1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -48,6 +48,14 @@ struct nv50_graph_chan { struct nouveau_graph_chan base; }; +static u64 +nv50_graph_units(struct nouveau_graph *graph) +{ + struct nv50_graph_priv *priv = (void *)graph; + + return nv_rd32(priv, 0x1540); +} + /******************************************************************************* * Graphics object classes ******************************************************************************/ @@ -819,6 +827,8 @@ nv50_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_subdev(priv)->intr = nv50_graph_intr; nv_engine(priv)->cclass = &nv50_graph_cclass; + priv->base.units = nv50_graph_units; + switch (nv_device(priv)->chipset) { case 0x50: nv_engine(priv)->sclass = nv50_graph_sclass; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 0de0dd724af..f9b9d82c287 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -60,6 +60,19 @@ nvc8_graph_sclass[] = { {} }; +u64 +nvc0_graph_units(struct nouveau_graph *graph) +{ + struct nvc0_graph_priv *priv = (void *)graph; + u64 cfg; + + cfg = (u32)priv->gpc_nr; + cfg |= (u32)priv->tpc_total << 8; + cfg |= (u64)priv->rop_nr << 32; + + return cfg; +} + /******************************************************************************* * PGRAPH context ******************************************************************************/ @@ -89,7 +102,8 @@ nvc0_graph_context_ctor(struct nouveau_object *parent, * fuc to modify some per-context register settings on first load * of the context. */ - ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 0x100, 0, &chan->mmio); + ret = nouveau_gpuobj_new(nv_object(chan), NULL, 0x1000, 0x100, 0, + &chan->mmio); if (ret) return ret; @@ -101,8 +115,8 @@ nvc0_graph_context_ctor(struct nouveau_object *parent, /* allocate buffers referenced by mmio list */ for (i = 0; data->size && i < ARRAY_SIZE(priv->mmio_data); i++) { - ret = nouveau_gpuobj_new(parent, NULL, data->size, data->align, - 0, &chan->data[i].mem); + ret = nouveau_gpuobj_new(nv_object(chan), NULL, data->size, + data->align, 0, &chan->data[i].mem); if (ret) return ret; @@ -518,9 +532,10 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, { struct nouveau_device *device = nv_device(parent); struct nvc0_graph_priv *priv; + bool enable = device->chipset != 0xd7; int ret, i; - ret = nouveau_graph_create(parent, engine, oclass, true, &priv); + ret = nouveau_graph_create(parent, engine, oclass, enable, &priv); *pobject = nv_object(priv); if (ret) return ret; @@ -529,6 +544,8 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_subdev(priv)->intr = nvc0_graph_intr; nv_engine(priv)->cclass = &nvc0_graph_cclass; + priv->base.units = nvc0_graph_units; + if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) { nv_info(priv, "using external firmware\n"); if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) || @@ -551,11 +568,13 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, break; } - ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4); + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0, + &priv->unk4188b4); if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8); + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0, + &priv->unk4188b8); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h index a1e78de4645..c870dad0f67 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.h @@ -118,6 +118,7 @@ nvc0_graph_class(void *obj) return 0x9197; case 0xc8: case 0xd9: + case 0xd7: return 0x9297; case 0xe4: case 0xe7: @@ -169,4 +170,6 @@ int nvc0_graph_context_ctor(struct nouveau_object *, struct nouveau_object *, struct nouveau_object **); void nvc0_graph_context_dtor(struct nouveau_object *); +u64 nvc0_graph_units(struct nouveau_graph *); + #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 4857f913efd..678c16f6305 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -77,11 +77,207 @@ nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) nv_wr32(priv, 0x409c20, ustat); } +static const struct nouveau_enum nve0_mp_warp_error[] = { + { 0x00, "NO_ERROR" }, + { 0x01, "STACK_MISMATCH" }, + { 0x05, "MISALIGNED_PC" }, + { 0x08, "MISALIGNED_GPR" }, + { 0x09, "INVALID_OPCODE" }, + { 0x0d, "GPR_OUT_OF_BOUNDS" }, + { 0x0e, "MEM_OUT_OF_BOUNDS" }, + { 0x0f, "UNALIGNED_MEM_ACCESS" }, + { 0x11, "INVALID_PARAM" }, + {} +}; + +static const struct nouveau_enum nve0_mp_global_error[] = { + { 2, "MULTIPLE_WARP_ERRORS" }, + { 3, "OUT_OF_STACK_SPACE" }, + {} +}; + +static const struct nouveau_enum nve0_gpc_rop_error[] = { + { 1, "RT_PITCH_OVERRUN" }, + { 4, "RT_WIDTH_OVERRUN" }, + { 5, "RT_HEIGHT_OVERRUN" }, + { 7, "ZETA_STORAGE_TYPE_MISMATCH" }, + { 8, "RT_STORAGE_TYPE_MISMATCH" }, + { 10, "RT_LINEAR_MISMATCH" }, + {} +}; + +static const struct nouveau_enum nve0_sked_error[] = { + { 7, "CONSTANT_BUFFER_SIZE" }, + { 9, "LOCAL_MEMORY_SIZE_POS" }, + { 10, "LOCAL_MEMORY_SIZE_NEG" }, + { 11, "WARP_CSTACK_SIZE" }, + { 12, "TOTAL_TEMP_SIZE" }, + { 13, "REGISTER_COUNT" }, + { 18, "TOTAL_THREADS" }, + { 20, "PROGRAM_OFFSET" }, + { 21, "SHARED_MEMORY_SIZE" }, + { 25, "SHARED_CONFIG_TOO_SMALL" }, + { 26, "TOTAL_REGISTER_COUNT" }, + {} +}; + +static void +nve0_graph_mp_trap(struct nvc0_graph_priv *priv, int gpc, int tp) +{ + int i; + u32 werr = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x648)); + u32 gerr = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x650)); + + nv_error(priv, "GPC%i/TP%i/MP trap:", gpc, tp); + + for (i = 0; i <= 31; ++i) { + if (!(gerr & (1 << i))) + continue; + pr_cont(" "); + nouveau_enum_print(nve0_mp_global_error, i); + } + if (werr) { + pr_cont(" "); + nouveau_enum_print(nve0_mp_warp_error, werr & 0xffff); + } + pr_cont("\n"); + + /* disable MP trap to avoid spam */ + nv_mask(priv, TPC_UNIT(gpc, tp, 0x50c), 0x2, 0x0); + + /* TODO: figure out how to resume after an MP trap */ +} + +static void +nve0_graph_tp_trap(struct nvc0_graph_priv *priv, int gpc, int tp) +{ + u32 stat = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x508)); + + if (stat & 0x1) { + u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x224)); + nv_error(priv, "GPC%i/TP%i/TEX trap: %08x\n", + gpc, tp, trap); + + nv_wr32(priv, TPC_UNIT(gpc, tp, 0x224), 0xc0000000); + stat &= ~0x1; + } + + if (stat & 0x2) { + nve0_graph_mp_trap(priv, gpc, tp); + stat &= ~0x2; + } + + if (stat & 0x4) { + u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x084)); + nv_error(priv, "GPC%i/TP%i/POLY trap: %08x\n", + gpc, tp, trap); + + nv_wr32(priv, TPC_UNIT(gpc, tp, 0x084), 0xc0000000); + stat &= ~0x4; + } + + if (stat & 0x8) { + u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tp, 0x48c)); + nv_error(priv, "GPC%i/TP%i/L1C trap: %08x\n", + gpc, tp, trap); + + nv_wr32(priv, TPC_UNIT(gpc, tp, 0x48c), 0xc0000000); + stat &= ~0x8; + } + + if (stat) { + nv_error(priv, "GPC%i/TP%i: unknown stat %08x\n", + gpc, tp, stat); + } +} + +static void +nve0_graph_gpc_trap(struct nvc0_graph_priv *priv) +{ + const u32 mask = nv_rd32(priv, 0x400118); + int gpc; + + for (gpc = 0; gpc < 4; ++gpc) { + u32 stat; + int tp; + + if (!(mask & (1 << gpc))) + continue; + stat = nv_rd32(priv, GPC_UNIT(gpc, 0x2c90)); + + if (stat & 0x0001) { + u32 trap[4]; + int i; + + trap[0] = nv_rd32(priv, GPC_UNIT(gpc, 0x0420)); + trap[1] = nv_rd32(priv, GPC_UNIT(gpc, 0x0434)); + trap[2] = nv_rd32(priv, GPC_UNIT(gpc, 0x0438)); + trap[3] = nv_rd32(priv, GPC_UNIT(gpc, 0x043c)); + + nv_error(priv, "GPC%i/PROP trap:", gpc); + for (i = 0; i <= 29; ++i) { + if (!(trap[0] & (1 << i))) + continue; + pr_cont(" "); + nouveau_enum_print(nve0_gpc_rop_error, i); + } + pr_cont("\n"); + + nv_error(priv, "x = %u, y = %u, " + "format = %x, storage type = %x\n", + trap[1] & 0xffff, + trap[1] >> 16, + (trap[2] >> 8) & 0x3f, + trap[3] & 0xff); + + nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000); + stat &= ~0x0001; + } + + if (stat & 0x0002) { + u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0900)); + nv_error(priv, "GPC%i/ZCULL trap: %08x\n", gpc, + trap); + nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000); + stat &= ~0x0002; + } + + if (stat & 0x0004) { + u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x1028)); + nv_error(priv, "GPC%i/CCACHE trap: %08x\n", gpc, + trap); + nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000); + stat &= ~0x0004; + } + + if (stat & 0x0008) { + u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0824)); + nv_error(priv, "GPC%i/ESETUP trap %08x\n", gpc, + trap); + nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000); + stat &= ~0x0008; + } + + for (tp = 0; tp < 8; ++tp) { + if (stat & (1 << (16 + tp))) + nve0_graph_tp_trap(priv, gpc, tp); + } + stat &= ~0xff0000; + + if (stat) { + nv_error(priv, "GPC%i: unknown stat %08x\n", + gpc, stat); + } + } +} + + static void nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst, struct nouveau_object *engctx) { u32 trap = nv_rd32(priv, 0x400108); + int i; int rop; if (trap & 0x00000001) { @@ -102,6 +298,32 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst, trap &= ~0x00000010; } + if (trap & 0x00000100) { + u32 stat = nv_rd32(priv, 0x407020); + nv_error(priv, "SKED ch %d [0x%010llx %s]:", + chid, inst, nouveau_client_name(engctx)); + + for (i = 0; i <= 29; ++i) { + if (!(stat & (1 << i))) + continue; + pr_cont(" "); + nouveau_enum_print(nve0_sked_error, i); + } + pr_cont("\n"); + + if (stat & 0x3fffffff) + nv_wr32(priv, 0x407020, 0x40000000); + nv_wr32(priv, 0x400108, 0x00000100); + trap &= ~0x00000100; + } + + if (trap & 0x01000000) { + nv_error(priv, "GPC ch %d [0x%010llx %s]:\n", + chid, inst, nouveau_client_name(engctx)); + nve0_graph_gpc_trap(priv); + trap &= ~0x01000000; + } + if (trap & 0x02000000) { for (rop = 0; rop < priv->rop_nr; rop++) { u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070)); @@ -217,6 +439,8 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->cclass = &nve0_graph_cclass; nv_engine(priv)->sclass = nve0_graph_sclass; + priv->base.units = nvc0_graph_units; + if (nouveau_boolopt(device->cfgopt, "NvGrUseFW", false)) { nv_info(priv, "using external firmware\n"); if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) || @@ -227,11 +451,13 @@ nve0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->firmware = true; } - ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b4); + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0, + &priv->unk4188b4); if (ret) return ret; - ret = nouveau_gpuobj_new(parent, NULL, 0x1000, 256, 0, &priv->unk4188b8); + ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0, + &priv->unk4188b8); if (ret) return ret; |