drm/nouveau/gr/gf100: instantiate and reserve GR falcons
authorAlexandre Courbot <acourbot@nvidia.com>
Tue, 13 Dec 2016 08:11:30 +0000 (17:11 +0900)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 17 Feb 2017 05:14:31 +0000 (15:14 +1000)
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>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h

index 7cf1492d392269aba4e6285c7249dbff189cc38d..c0c25cf5404befd349151388ee39430276d748e8 100644 (file)
@@ -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,10 +1696,32 @@ 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);
+
+       ret = nvkm_falcon_get(gr->fecs, subdev);
+       if (ret)
+               return ret;
+
+       ret = nvkm_falcon_get(gr->gpccs, subdev);
+       if (ret)
+               return ret;
+
        return gr->func->init(gr);
 }
 
+static int
+gf100_gr_fini_(struct nvkm_gr *base, bool suspend)
+{
+       struct gf100_gr *gr = gf100_gr(base);
+       struct nvkm_subdev *subdev = &gr->base.engine.subdev;
+       nvkm_falcon_put(gr->gpccs, subdev);
+       nvkm_falcon_put(gr->fecs, subdev);
+       return 0;
+}
+
 void
 gf100_gr_dtor_fw(struct gf100_gr_fuc *fuc)
 {
@@ -1755,6 +1744,9 @@ gf100_gr_dtor(struct nvkm_gr *base)
                gr->func->dtor(gr);
        kfree(gr->data);
 
+       nvkm_falcon_del(&gr->gpccs);
+       nvkm_falcon_del(&gr->fecs);
+
        gf100_gr_dtor_fw(&gr->fuc409c);
        gf100_gr_dtor_fw(&gr->fuc409d);
        gf100_gr_dtor_fw(&gr->fuc41ac);
@@ -1773,6 +1765,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 +1839,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,7 +1852,11 @@ gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device,
        if (ret)
                return ret;
 
-       return 0;
+       ret = nvkm_falcon_v1_new(subdev, "FECS", 0x409000, &gr->fecs);
+       if (ret)
+               return ret;
+
+       return nvkm_falcon_v1_new(subdev, "GPCCS", 0x41a000, &gr->gpccs);
 }
 
 int
index 268b8d60ff73c286215e541be987c204e16a3469..db6ee3b06841e2be188b816b2859bb426ff089ef 100644 (file)
@@ -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;