drm/nouveau/pmu/gm20b,gp10b: boot RTOS from PMU init
authorBen Skeggs <bskeggs@redhat.com>
Wed, 1 Jun 2022 10:47:49 +0000 (20:47 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 9 Nov 2022 00:44:58 +0000 (10:44 +1000)
Cleanup before falcon changes.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
drivers/gpu/drm/nouveau/nvkm/falcon/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h

index 176f092..780e25f 100644 (file)
@@ -16,7 +16,7 @@ enum nvkm_falcon_dmaidx {
 
 struct nvkm_falcon {
        const struct nvkm_falcon_func *func;
-       const struct nvkm_subdev *owner;
+       struct nvkm_subdev *owner;
        const char *name;
        u32 addr;
 
@@ -24,7 +24,7 @@ struct nvkm_falcon {
        struct mutex dmem_mutex;
        bool oneinit;
 
-       const struct nvkm_subdev *user;
+       struct nvkm_subdev *user;
 
        u8 version;
        u8 secret;
@@ -50,8 +50,8 @@ struct nvkm_falcon {
        struct nvkm_engine engine;
 };
 
-int nvkm_falcon_get(struct nvkm_falcon *, const struct nvkm_subdev *);
-void nvkm_falcon_put(struct nvkm_falcon *, const struct nvkm_subdev *);
+int nvkm_falcon_get(struct nvkm_falcon *, struct nvkm_subdev *);
+void nvkm_falcon_put(struct nvkm_falcon *, struct nvkm_subdev *);
 
 int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *,
                     enum nvkm_subdev_type, int inst, bool enable, u32 addr, struct nvkm_engine **);
index c0b254f..3a269bb 100644 (file)
@@ -50,6 +50,7 @@ struct nvkm_acr {
        struct nvkm_vmm *vmm;
 
        bool done;
+       struct nvkm_acr_lsf *rtos;
 
        const struct firmware *wpr_fw;
        bool wpr_comp;
index f3f90c1..5a5b96d 100644 (file)
@@ -169,7 +169,7 @@ nvkm_falcon_oneinit(struct nvkm_falcon *falcon)
 }
 
 void
-nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
+nvkm_falcon_put(struct nvkm_falcon *falcon, struct nvkm_subdev *user)
 {
        if (unlikely(!falcon))
                return;
@@ -183,7 +183,7 @@ nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
 }
 
 int
-nvkm_falcon_get(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
+nvkm_falcon_get(struct nvkm_falcon *falcon, struct nvkm_subdev *user)
 {
        int ret = 0;
 
index af6cac6..777b6cb 100644 (file)
@@ -63,10 +63,30 @@ nvkm_acr_hsf_boot(struct nvkm_acr *acr, const char *name)
        return 0;
 }
 
+static struct nvkm_acr_lsf *
+nvkm_acr_rtos(struct nvkm_acr *acr)
+{
+       struct nvkm_acr_lsf *lsf;
+
+       if (acr) {
+               list_for_each_entry(lsf, &acr->lsf, head) {
+                       if (lsf->func->bootstrap_falcon)
+                               return lsf;
+               }
+       }
+
+       return NULL;
+}
+
 static void
 nvkm_acr_unload(struct nvkm_acr *acr)
 {
        if (acr->done) {
+               if (acr->rtos) {
+                       nvkm_subdev_unref(acr->rtos->falcon->owner);
+                       acr->rtos = NULL;
+               }
+
                nvkm_acr_hsf_boot(acr, "unload");
                acr->done = false;
        }
@@ -76,6 +96,7 @@ static int
 nvkm_acr_load(struct nvkm_acr *acr)
 {
        struct nvkm_subdev *subdev = &acr->subdev;
+       struct nvkm_acr_lsf *rtos = nvkm_acr_rtos(acr);
        struct nvkm_acr_lsf *lsf;
        u64 start, limit;
        int ret;
@@ -100,6 +121,14 @@ nvkm_acr_load(struct nvkm_acr *acr)
 
        acr->done = true;
 
+       if (rtos) {
+               ret = nvkm_subdev_ref(rtos->falcon->owner);
+               if (ret)
+                       return ret;
+
+               acr->rtos = rtos;
+       }
+
        list_for_each_entry(lsf, &acr->lsf, head) {
                if (lsf->func->boot) {
                        ret = lsf->func->boot(lsf->falcon);
@@ -118,33 +147,17 @@ nvkm_acr_reload(struct nvkm_acr *acr)
        return nvkm_acr_load(acr);
 }
 
-static struct nvkm_acr_lsf *
-nvkm_acr_falcon(struct nvkm_device *device)
-{
-       struct nvkm_acr *acr = device->acr;
-       struct nvkm_acr_lsf *lsf;
-
-       if (acr) {
-               list_for_each_entry(lsf, &acr->lsf, head) {
-                       if (lsf->func->bootstrap_falcon)
-                               return lsf;
-               }
-       }
-
-       return NULL;
-}
-
 int
 nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask)
 {
-       struct nvkm_acr_lsf *acrflcn = nvkm_acr_falcon(device);
        struct nvkm_acr *acr = device->acr;
+       struct nvkm_acr_lsf *rtos = nvkm_acr_rtos(acr);
        unsigned long id;
 
        /* If there's no LS FW managing bootstrapping of other LS falcons,
         * we depend on the HS firmware being able to do it instead.
         */
-       if (!acrflcn) {
+       if (!rtos) {
                /* Which isn't possible everywhere... */
                if ((mask & acr->func->bootstrap_falcons) == mask) {
                        int ret = nvkm_acr_reload(acr);
@@ -156,16 +169,14 @@ nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask)
                return -ENOSYS;
        }
 
-       if ((mask & acrflcn->func->bootstrap_falcons) != mask)
+       if ((mask & rtos->func->bootstrap_falcons) != mask)
                return -ENOSYS;
 
-       if (acrflcn->func->bootstrap_multiple_falcons) {
-               return acrflcn->func->
-                       bootstrap_multiple_falcons(acrflcn->falcon, mask);
-       }
+       if (rtos->func->bootstrap_multiple_falcons)
+               return rtos->func->bootstrap_multiple_falcons(rtos->falcon, mask);
 
        for_each_set_bit(id, &mask, NVKM_ACR_LSF_NUM) {
-               int ret = acrflcn->func->bootstrap_falcon(acrflcn->falcon, id);
+               int ret = rtos->func->bootstrap_falcon(rtos->falcon, id);
                if (ret)
                        return ret;
        }
@@ -189,6 +200,9 @@ nvkm_acr_managed_falcon(struct nvkm_device *device, enum nvkm_acr_lsf_id id)
 static int
 nvkm_acr_fini(struct nvkm_subdev *subdev, bool suspend)
 {
+       if (!subdev->use.enabled)
+               return 0;
+
        nvkm_acr_unload(nvkm_acr(subdev));
        return 0;
 }
@@ -196,10 +210,12 @@ nvkm_acr_fini(struct nvkm_subdev *subdev, bool suspend)
 static int
 nvkm_acr_init(struct nvkm_subdev *subdev)
 {
-       if (!nvkm_acr_falcon(subdev->device))
+       struct nvkm_acr *acr = nvkm_acr(subdev);
+
+       if (!nvkm_acr_rtos(acr))
                return 0;
 
-       return nvkm_acr_load(nvkm_acr(subdev));
+       return nvkm_acr_load(acr);
 }
 
 static void
@@ -218,7 +234,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
        struct nvkm_acr *acr = nvkm_acr(subdev);
        struct nvkm_acr_hsfw *hsfw;
        struct nvkm_acr_lsfw *lsfw, *lsft;
-       struct nvkm_acr_lsf *lsf;
+       struct nvkm_acr_lsf *lsf, *rtos;
        u32 wpr_size = 0;
        u64 falcons;
        int ret, i;
@@ -260,10 +276,10 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
        }
 
        /* Ensure the falcon that'll provide ACR functions is booted first. */
-       lsf = nvkm_acr_falcon(device);
-       if (lsf) {
-               falcons = lsf->func->bootstrap_falcons;
-               list_move(&lsf->head, &acr->lsf);
+       rtos = nvkm_acr_rtos(acr);
+       if (rtos) {
+               falcons = rtos->func->bootstrap_falcons;
+               list_move(&rtos->head, &acr->lsf);
        } else {
                falcons = acr->func->bootstrap_falcons;
        }
@@ -301,7 +317,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
                nvkm_wobj(acr->wpr, 0, acr->wpr_fw->data, acr->wpr_fw->size);
 
        if (!acr->wpr_fw || acr->wpr_comp)
-               acr->func->wpr_build(acr, nvkm_acr_falcon(device));
+               acr->func->wpr_build(acr, rtos);
        acr->func->wpr_patch(acr, (s64)acr->wpr_start - acr->wpr_prev);
 
        if (acr->wpr_fw && acr->wpr_comp) {
index 51808a4..8f2f50a 100644 (file)
@@ -87,13 +87,6 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
        if (pmu->func->fini)
                pmu->func->fini(pmu);
 
-       flush_work(&pmu->recv.work);
-
-       reinit_completion(&pmu->wpr_ready);
-
-       nvkm_falcon_cmdq_fini(pmu->lpq);
-       nvkm_falcon_cmdq_fini(pmu->hpq);
-       pmu->initmsg_received = false;
        return 0;
 }
 
index 2b73848..a724037 100644 (file)
@@ -62,16 +62,6 @@ gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
        return ret;
 }
 
-int
-gm20b_pmu_acr_boot(struct nvkm_falcon *falcon)
-{
-       struct nv_pmu_args args = { .secure_mode = true };
-       const u32 addr_args = falcon->data.limit - sizeof(struct nv_pmu_args);
-       nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0);
-       nvkm_falcon_start(falcon);
-       return 0;
-}
-
 void
 gm20b_pmu_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
 {
@@ -125,7 +115,6 @@ gm20b_pmu_acr = {
        .bld_size = sizeof(struct loader_config),
        .bld_write = gm20b_pmu_acr_bld_write,
        .bld_patch = gm20b_pmu_acr_bld_patch,
-       .boot = gm20b_pmu_acr_boot,
        .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_PMU) |
                             BIT_ULL(NVKM_ACR_LSF_FECS) |
                             BIT_ULL(NVKM_ACR_LSF_GPCCS),
@@ -198,8 +187,7 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu)
        if (!pmu->initmsg_received) {
                int ret = pmu->func->initmsg(pmu);
                if (ret) {
-                       nvkm_error(&pmu->subdev,
-                                  "error parsing init message: %d\n", ret);
+                       nvkm_error(&pmu->subdev, "error parsing init message: %d\n", ret);
                        return;
                }
 
@@ -209,9 +197,44 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu)
        nvkm_falcon_msgq_recv(pmu->msgq);
 }
 
+static void
+gm20b_pmu_fini(struct nvkm_pmu *pmu)
+{
+       /*TODO: shutdown RTOS. */
+
+       flush_work(&pmu->recv.work);
+       nvkm_falcon_cmdq_fini(pmu->lpq);
+       nvkm_falcon_cmdq_fini(pmu->hpq);
+
+       reinit_completion(&pmu->wpr_ready);
+
+       nvkm_falcon_put(&pmu->falcon, &pmu->subdev);
+}
+
+static int
+gm20b_pmu_init(struct nvkm_pmu *pmu)
+{
+       struct nvkm_falcon *falcon = &pmu->falcon;
+       struct nv_pmu_args args = { .secure_mode = true };
+       u32 addr_args = falcon->data.limit - sizeof(args);
+       int ret;
+
+       ret = nvkm_falcon_get(&pmu->falcon, &pmu->subdev);
+       if (ret)
+               return ret;
+
+       pmu->initmsg_received = false;
+
+       nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0);
+       nvkm_falcon_start(falcon);
+       return 0;
+}
+
 const struct nvkm_pmu_func
 gm20b_pmu = {
        .flcn = &gm200_pmu_flcn,
+       .init = gm20b_pmu_init,
+       .fini = gm20b_pmu_fini,
        .intr = gt215_pmu_intr,
        .recv = gm20b_pmu_recv,
        .initmsg = gm20b_pmu_initmsg,
index 9fba37e..a6f410b 100644 (file)
@@ -68,7 +68,6 @@ gp10b_pmu_acr = {
        .bld_size = sizeof(struct loader_config),
        .bld_write = gm20b_pmu_acr_bld_write,
        .bld_patch = gm20b_pmu_acr_bld_patch,
-       .boot = gm20b_pmu_acr_boot,
        .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_PMU) |
                             BIT_ULL(NVKM_ACR_LSF_FECS) |
                             BIT_ULL(NVKM_ACR_LSF_GPCCS),
index 6d1a966..32cee21 100644 (file)
@@ -178,6 +178,7 @@ void
 gt215_pmu_fini(struct nvkm_pmu *pmu)
 {
        nvkm_wr32(pmu->subdev.device, 0x10a014, 0x00000060);
+       flush_work(&pmu->recv.work);
 }
 
 static void
index 1e7815b..75ede26 100644 (file)
@@ -50,7 +50,6 @@ extern const struct nvkm_falcon_func gm200_pmu_flcn;
 extern const struct nvkm_pmu_func gm20b_pmu;
 void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64);
 void gm20b_pmu_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *);
-int gm20b_pmu_acr_boot(struct nvkm_falcon *);
 int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
 
 struct nvkm_pmu_fwif {