[v2,14/15] gr/gf100: instantiate and reserve GR falcons

Submitted by Alexandre Courbot on Dec. 13, 2016, 8:11 a.m.

Details

Message ID 297b87046315ec84ef00cf0814c5bebab3499288.1481616662.git-series.acourbot@nvidia.com
State New
Headers show
Series "Falcon library" ( rev: 3 ) in Nouveau

Not browsing as part of any series.

Commit Message

Alexandre Courbot Dec. 13, 2016, 8:11 a.m.
Create instances for the FECS and GPCCS falcons and use the init() and
fini() hooks to reserve them for as long as GR controls them.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
 drm/nouveau/nvkm/engine/gr/gf100.c | 110 ++++++++++++++++--------------
 drm/nouveau/nvkm/engine/gr/gf100.h |   3 +-
 2 files changed, 63 insertions(+), 50 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drm/nouveau/nvkm/engine/gr/gf100.c b/drm/nouveau/nvkm/engine/gr/gf100.c
index 7cf1492d3922..4330e8417a25 100644
--- a/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -1391,26 +1391,11 @@  gf100_gr_intr(struct nvkm_gr *base)
 }
 
 static void
-gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base,
+gf100_gr_init_fw(struct nvkm_falcon *falcon,
 		 struct gf100_gr_fuc *code, struct gf100_gr_fuc *data)
 {
-	struct nvkm_device *device = gr->base.engine.subdev.device;
-	int i;
-
-	nvkm_wr32(device, fuc_base + 0x01c0, 0x01000000);
-	for (i = 0; i < data->size / 4; i++)
-		nvkm_wr32(device, fuc_base + 0x01c4, data->data[i]);
-
-	nvkm_wr32(device, fuc_base + 0x0180, 0x01000000);
-	for (i = 0; i < code->size / 4; i++) {
-		if ((i & 0x3f) == 0)
-			nvkm_wr32(device, fuc_base + 0x0188, i >> 6);
-		nvkm_wr32(device, fuc_base + 0x0184, code->data[i]);
-	}
-
-	/* code must be padded to 0x40 words */
-	for (; i & 0x3f; i++)
-		nvkm_wr32(device, fuc_base + 0x0184, 0);
+	nvkm_falcon_load_dmem(falcon, data->data, 0x0, data->size, 0);
+	nvkm_falcon_load_imem(falcon, code->data, 0x0, code->size, 0, 0, false);
 }
 
 static void
@@ -1471,14 +1456,14 @@  gf100_gr_init_ctxctl_ext(struct gf100_gr *gr)
 	if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS))
 		ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_FECS);
 	else
-		gf100_gr_init_fw(gr, 0x409000, &gr->fuc409c, &gr->fuc409d);
+		gf100_gr_init_fw(&gr->fecs, &gr->fuc409c, &gr->fuc409d);
 	if (ret)
 		return ret;
 
 	if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS))
 		ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_GPCCS);
 	else
-		gf100_gr_init_fw(gr, 0x41a000, &gr->fuc41ac, &gr->fuc41ad);
+		gf100_gr_init_fw(&gr->gpccs, &gr->fuc41ac, &gr->fuc41ad);
 	if (ret)
 		return ret;
 
@@ -1489,14 +1474,9 @@  gf100_gr_init_ctxctl_ext(struct gf100_gr *gr)
 	nvkm_wr32(device, 0x41a10c, 0x00000000);
 	nvkm_wr32(device, 0x40910c, 0x00000000);
 
-	if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_GPCCS))
-		nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_GPCCS);
-	else
-		nvkm_wr32(device, 0x41a100, 0x00000002);
-	if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS))
-		nvkm_secboot_start(sb, NVKM_SECBOOT_FALCON_FECS);
-	else
-		nvkm_wr32(device, 0x409100, 0x00000002);
+	nvkm_falcon_start(&gr->gpccs);
+	nvkm_falcon_start(&gr->fecs);
+
 	if (nvkm_msec(device, 2000,
 		if (nvkm_rd32(device, 0x409800) & 0x00000001)
 			break;
@@ -1586,7 +1566,6 @@  gf100_gr_init_ctxctl_int(struct gf100_gr *gr)
 	const struct gf100_grctx_func *grctx = gr->func->grctx;
 	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
 	struct nvkm_device *device = subdev->device;
-	int i;
 
 	if (!gr->func->fecs.ucode) {
 		return -ENOSYS;
@@ -1594,28 +1573,16 @@  gf100_gr_init_ctxctl_int(struct gf100_gr *gr)
 
 	/* load HUB microcode */
 	nvkm_mc_unk260(device, 0);
-	nvkm_wr32(device, 0x4091c0, 0x01000000);
-	for (i = 0; i < gr->func->fecs.ucode->data.size / 4; i++)
-		nvkm_wr32(device, 0x4091c4, gr->func->fecs.ucode->data.data[i]);
-
-	nvkm_wr32(device, 0x409180, 0x01000000);
-	for (i = 0; i < gr->func->fecs.ucode->code.size / 4; i++) {
-		if ((i & 0x3f) == 0)
-			nvkm_wr32(device, 0x409188, i >> 6);
-		nvkm_wr32(device, 0x409184, gr->func->fecs.ucode->code.data[i]);
-	}
+	nvkm_falcon_load_dmem(&gr->fecs, gr->func->fecs.ucode->data.data, 0x0,
+			      gr->func->fecs.ucode->data.size, 0);
+	nvkm_falcon_load_imem(&gr->fecs, gr->func->fecs.ucode->code.data, 0x0,
+			      gr->func->fecs.ucode->code.size, 0, 0, false);
 
 	/* load GPC microcode */
-	nvkm_wr32(device, 0x41a1c0, 0x01000000);
-	for (i = 0; i < gr->func->gpccs.ucode->data.size / 4; i++)
-		nvkm_wr32(device, 0x41a1c4, gr->func->gpccs.ucode->data.data[i]);
-
-	nvkm_wr32(device, 0x41a180, 0x01000000);
-	for (i = 0; i < gr->func->gpccs.ucode->code.size / 4; i++) {
-		if ((i & 0x3f) == 0)
-			nvkm_wr32(device, 0x41a188, i >> 6);
-		nvkm_wr32(device, 0x41a184, gr->func->gpccs.ucode->code.data[i]);
-	}
+	nvkm_falcon_load_dmem(&gr->gpccs, gr->func->gpccs.ucode->data.data, 0x0,
+			      gr->func->gpccs.ucode->data.size, 0);
+	nvkm_falcon_load_imem(&gr->gpccs, gr->func->gpccs.ucode->code.data, 0x0,
+			      gr->func->gpccs.ucode->code.size, 0, 0, false);
 	nvkm_mc_unk260(device, 1);
 
 	/* load register lists */
@@ -1729,8 +1696,44 @@  static int
 gf100_gr_init_(struct nvkm_gr *base)
 {
 	struct gf100_gr *gr = gf100_gr(base);
+	struct nvkm_subdev *subdev = &base->engine.subdev;
+	u32 ret;
+
 	nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false);
-	return gr->func->init(gr);
+
+	ret = nvkm_falcon_get(&gr->fecs, subdev);
+	if (ret)
+		return ret;
+	ret = nvkm_falcon_get(&gr->gpccs, subdev);
+	if (ret)
+		goto gpccs_failed;
+
+	ret = gr->func->init(gr);
+	if (ret)
+		goto init_failed;
+
+	return 0;
+
+init_failed:
+	nvkm_falcon_put(&gr->gpccs);
+gpccs_failed:
+	nvkm_falcon_put(&gr->fecs);
+
+	return ret;
+}
+
+static int
+gf100_gr_fini_(struct nvkm_gr *base, bool suspend)
+{
+	struct gf100_gr *gr = gf100_gr(base);
+
+	/* We only own the falcons if init has been performed at this stage */
+	if (gr->gpccs.user == &base->engine.subdev) {
+		nvkm_falcon_put(&gr->gpccs);
+		nvkm_falcon_put(&gr->fecs);
+	}
+
+	return 0;
 }
 
 void
@@ -1773,6 +1776,7 @@  gf100_gr_ = {
 	.dtor = gf100_gr_dtor,
 	.oneinit = gf100_gr_oneinit,
 	.init = gf100_gr_init_,
+	.fini = gf100_gr_fini_,
 	.intr = gf100_gr_intr,
 	.units = gf100_gr_units,
 	.chan_new = gf100_gr_chan_new,
@@ -1846,6 +1850,7 @@  int
 gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device,
 	      int index, struct gf100_gr *gr)
 {
+	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
 	int ret;
 
 	gr->func = func;
@@ -1858,6 +1863,11 @@  gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device,
 	if (ret)
 		return ret;
 
+	nvkm_falcon_ctor(subdev, &nvkm_falcon_v1_func, "FECS", 0x409000,
+			 &gr->fecs);
+	nvkm_falcon_ctor(subdev, &nvkm_falcon_v1_func, "GPCCS", 0x41a000,
+			 &gr->gpccs);
+
 	return 0;
 }
 
diff --git a/drm/nouveau/nvkm/engine/gr/gf100.h b/drm/nouveau/nvkm/engine/gr/gf100.h
index 268b8d60ff73..cc90f924def4 100644
--- a/drm/nouveau/nvkm/engine/gr/gf100.h
+++ b/drm/nouveau/nvkm/engine/gr/gf100.h
@@ -29,6 +29,7 @@ 
 #include <core/gpuobj.h>
 #include <subdev/ltc.h>
 #include <subdev/mmu.h>
+#include <engine/falcon.h>
 
 #define GPC_MAX 32
 #define TPC_MAX_PER_GPC 8
@@ -75,6 +76,8 @@  struct gf100_gr {
 	const struct gf100_gr_func *func;
 	struct nvkm_gr base;
 
+	struct nvkm_falcon fecs;
+	struct nvkm_falcon gpccs;
 	struct gf100_gr_fuc fuc409c;
 	struct gf100_gr_fuc fuc409d;
 	struct gf100_gr_fuc fuc41ac;