Change the secboot and msgqueue interfaces to take a mask of falcons to
reset instead of a single falcon. The GP10B firmware interface requires
FECS and GPCCS to be booted in a single firmware command.

For firmwares that only support single falcon boot, it is trivial to
loop over the mask and boot each falcons individually.

Signed-off-by: Alexandre Courbot <acour...@nvidia.com>
---
 drm/nouveau/include/nvkm/core/msgqueue.h   |  3 +--
 drm/nouveau/include/nvkm/subdev/secboot.h  |  2 +-
 drm/nouveau/nvkm/engine/gr/gf100.c         | 16 +++++++++-------
 drm/nouveau/nvkm/falcon/msgqueue.c         | 25 ++++++++++++++++++++++---
 drm/nouveau/nvkm/falcon/msgqueue.h         |  2 ++
 drm/nouveau/nvkm/subdev/secboot/acr.h      |  3 +--
 drm/nouveau/nvkm/subdev/secboot/acr_r352.c | 25 +++++++++++++++----------
 drm/nouveau/nvkm/subdev/secboot/base.c     |  6 +++---
 8 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/drm/nouveau/include/nvkm/core/msgqueue.h 
b/drm/nouveau/include/nvkm/core/msgqueue.h
index fac0824197f1..5c902f8c042a 100644
--- a/drm/nouveau/include/nvkm/core/msgqueue.h
+++ b/drm/nouveau/include/nvkm/core/msgqueue.h
@@ -41,7 +41,6 @@ int nvkm_msgqueue_reinit(struct nvkm_msgqueue *);
 void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *);
 
 /* interface to ACR unit running on falcon (NVIDIA signed firmware) */
-int nvkm_msgqueue_acr_boot_falcon(struct nvkm_msgqueue *,
-                                 enum nvkm_secboot_falcon);
+int nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *, unsigned long);
 
 #endif
diff --git a/drm/nouveau/include/nvkm/subdev/secboot.h 
b/drm/nouveau/include/nvkm/subdev/secboot.h
index d6a4bdb6573b..a2d54d81e338 100644
--- a/drm/nouveau/include/nvkm/subdev/secboot.h
+++ b/drm/nouveau/include/nvkm/subdev/secboot.h
@@ -55,7 +55,7 @@ struct nvkm_secboot {
 #define nvkm_secboot(p) container_of((p), struct nvkm_secboot, subdev)
 
 bool nvkm_secboot_is_managed(struct nvkm_secboot *, enum nvkm_secboot_falcon);
-int nvkm_secboot_reset(struct nvkm_secboot *, enum nvkm_secboot_falcon);
+int nvkm_secboot_reset(struct nvkm_secboot *, unsigned long);
 
 int gm200_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **);
 int gm20b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **);
diff --git a/drm/nouveau/nvkm/engine/gr/gf100.c 
b/drm/nouveau/nvkm/engine/gr/gf100.c
index a4410ef19db5..99689f4de502 100644
--- a/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -1463,25 +1463,27 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr)
        struct nvkm_subdev *subdev = &gr->base.engine.subdev;
        struct nvkm_device *device = subdev->device;
        struct nvkm_secboot *sb = device->secboot;
-       int ret = 0;
+       u32 secboot_mask = 0;
 
        /* load fuc microcode */
        nvkm_mc_unk260(device, 0);
 
        /* securely-managed falcons must be reset using secure boot */
        if (nvkm_secboot_is_managed(sb, NVKM_SECBOOT_FALCON_FECS))
-               ret = nvkm_secboot_reset(sb, NVKM_SECBOOT_FALCON_FECS);
+               secboot_mask |= BIT(NVKM_SECBOOT_FALCON_FECS);
        else
                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);
+               secboot_mask |= BIT(NVKM_SECBOOT_FALCON_GPCCS);
        else
                gf100_gr_init_fw(gr->gpccs, &gr->fuc41ac, &gr->fuc41ad);
-       if (ret)
-               return ret;
+
+       if (secboot_mask != 0) {
+               int ret = nvkm_secboot_reset(sb, secboot_mask);
+               if (ret)
+                       return ret;
+       }
 
        nvkm_mc_unk260(device, 1);
 
diff --git a/drm/nouveau/nvkm/falcon/msgqueue.c 
b/drm/nouveau/nvkm/falcon/msgqueue.c
index 982efedb4b13..0780d340c3eb 100644
--- a/drm/nouveau/nvkm/falcon/msgqueue.c
+++ b/drm/nouveau/nvkm/falcon/msgqueue.c
@@ -463,12 +463,31 @@ nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *queue, 
void *buf)
 }
 
 int
-nvkm_msgqueue_acr_boot_falcon(struct nvkm_msgqueue *queue, enum 
nvkm_secboot_falcon falcon)
+nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *queue,
+                              unsigned long falcon_mask)
 {
-       if (!queue || !queue->func->acr_func || 
!queue->func->acr_func->boot_falcon)
+       unsigned long falcon;
+
+       if (!queue || !queue->func->acr_func)
+               return -ENODEV;
+
+       /* Does the firmware support booting multiple falcons? */
+       if (queue->func->acr_func->boot_multiple_falcons)
+               return queue->func->acr_func->boot_multiple_falcons(queue,
+                                                                  falcon_mask);
+
+       /* Else boot all requested falcons individually */
+       if (!queue->func->acr_func->boot_falcon)
                return -ENODEV;
 
-       return queue->func->acr_func->boot_falcon(queue, falcon);
+       for_each_set_bit(falcon, &falcon_mask, NVKM_SECBOOT_FALCON_END) {
+               int ret = queue->func->acr_func->boot_falcon(queue, falcon);
+
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
 }
 
 int
diff --git a/drm/nouveau/nvkm/falcon/msgqueue.h 
b/drm/nouveau/nvkm/falcon/msgqueue.h
index f37afe963d3e..ea67a522a12e 100644
--- a/drm/nouveau/nvkm/falcon/msgqueue.h
+++ b/drm/nouveau/nvkm/falcon/msgqueue.h
@@ -101,9 +101,11 @@ struct nvkm_msgqueue_init_func {
  * struct nvkm_msgqueue_acr_func - msgqueue functions related to ACR
  *
  * @boot_falcon:       build and send the command to reset a given falcon
+ * @boot_multiple_falcons: build and send the command to reset several falcons
  */
 struct nvkm_msgqueue_acr_func {
        int (*boot_falcon)(struct nvkm_msgqueue *, enum nvkm_secboot_falcon);
+       int (*boot_multiple_falcons)(struct nvkm_msgqueue *, unsigned long);
 };
 
 struct nvkm_msgqueue_func {
diff --git a/drm/nouveau/nvkm/subdev/secboot/acr.h 
b/drm/nouveau/nvkm/subdev/secboot/acr.h
index 93d804652d44..b615fc81aca4 100644
--- a/drm/nouveau/nvkm/subdev/secboot/acr.h
+++ b/drm/nouveau/nvkm/subdev/secboot/acr.h
@@ -39,8 +39,7 @@ struct nvkm_acr_func {
        int (*fini)(struct nvkm_acr *, struct nvkm_secboot *, bool);
        int (*load)(struct nvkm_acr *, struct nvkm_falcon *,
                    struct nvkm_gpuobj *, u64);
-       int (*reset)(struct nvkm_acr *, struct nvkm_secboot *,
-                    enum nvkm_secboot_falcon);
+       int (*reset)(struct nvkm_acr *, struct nvkm_secboot *, unsigned long);
 };
 
 /**
diff --git a/drm/nouveau/nvkm/subdev/secboot/acr_r352.c 
b/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
index 993a38eb3ed5..aa4e75f0eb0a 100644
--- a/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
+++ b/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
@@ -976,15 +976,16 @@ acr_r352_bootstrap(struct acr_r352 *acr, struct 
nvkm_secboot *sb)
  */
 static int
 acr_r352_reset_nopmu(struct acr_r352 *acr, struct nvkm_secboot *sb,
-                    enum nvkm_secboot_falcon falcon)
+                    unsigned long falcon_mask)
 {
+       int falcon;
        int ret;
 
        /*
         * Perform secure boot each time we are called on FECS. Since only FECS
         * and GPCCS are managed and started together, this ought to be safe.
         */
-       if (falcon != NVKM_SECBOOT_FALCON_FECS)
+       if (!(falcon_mask & BIT(NVKM_SECBOOT_FALCON_FECS)))
                goto end;
 
        ret = acr_r352_shutdown(acr, sb);
@@ -996,7 +997,9 @@ acr_r352_reset_nopmu(struct acr_r352 *acr, struct 
nvkm_secboot *sb,
                return ret;
 
 end:
-       acr->falcon_state[falcon] = RESET;
+       for_each_set_bit(falcon, &falcon_mask, NVKM_SECBOOT_FALCON_END) {
+               acr->falcon_state[falcon] = RESET;
+       }
        return 0;
 }
 
@@ -1009,11 +1012,11 @@ end:
  */
 static int
 acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
-              enum nvkm_secboot_falcon falcon)
+              unsigned long falcon_mask)
 {
        struct acr_r352 *acr = acr_r352(_acr);
        struct nvkm_msgqueue *queue;
-       const char *fname = nvkm_secboot_falcon_name[falcon];
+       int falcon;
        bool wpr_already_set = sb->wpr_set;
        int ret;
 
@@ -1026,7 +1029,7 @@ acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot 
*sb,
        if (!nvkm_secboot_is_managed(sb, _acr->boot_falcon)) {
                /* Redo secure boot entirely if it was already done */
                if (wpr_already_set)
-                       return acr_r352_reset_nopmu(acr, sb, falcon);
+                       return acr_r352_reset_nopmu(acr, sb, falcon_mask);
                /* Else return the result of the initial invokation */
                else
                        return ret;
@@ -1044,13 +1047,15 @@ acr_r352_reset(struct nvkm_acr *_acr, struct 
nvkm_secboot *sb,
        }
 
        /* Otherwise just ask the LS firmware to reset the falcon */
-       nvkm_debug(&sb->subdev, "resetting %s falcon\n", fname);
-       ret = nvkm_msgqueue_acr_boot_falcon(queue, falcon);
+       for_each_set_bit(falcon, &falcon_mask, NVKM_SECBOOT_FALCON_END)
+               nvkm_debug(&sb->subdev, "resetting %s falcon\n",
+                          nvkm_secboot_falcon_name[falcon]);
+       ret = nvkm_msgqueue_acr_boot_falcons(queue, falcon_mask);
        if (ret) {
-               nvkm_error(&sb->subdev, "cannot boot %s falcon\n", fname);
+               nvkm_error(&sb->subdev, "error during falcon reset: %d\n", ret);
                return ret;
        }
-       nvkm_debug(&sb->subdev, "falcon %s reset\n", fname);
+       nvkm_debug(&sb->subdev, "falcon reset done\n");
 
        return 0;
 }
diff --git a/drm/nouveau/nvkm/subdev/secboot/base.c 
b/drm/nouveau/nvkm/subdev/secboot/base.c
index 5c11e8c50964..ee29c6c11afd 100644
--- a/drm/nouveau/nvkm/subdev/secboot/base.c
+++ b/drm/nouveau/nvkm/subdev/secboot/base.c
@@ -102,15 +102,15 @@ nvkm_secboot_falcon_name[] = {
  * nvkm_secboot_reset() - reset specified falcon
  */
 int
-nvkm_secboot_reset(struct nvkm_secboot *sb, enum nvkm_secboot_falcon falcon)
+nvkm_secboot_reset(struct nvkm_secboot *sb, unsigned long falcon_mask)
 {
        /* Unmanaged falcon? */
-       if (!(BIT(falcon) & sb->acr->managed_falcons)) {
+       if ((falcon_mask | sb->acr->managed_falcons) != 
sb->acr->managed_falcons) {
                nvkm_error(&sb->subdev, "cannot reset unmanaged falcon!\n");
                return -EINVAL;
        }
 
-       return sb->acr->func->reset(sb->acr, sb, falcon);
+       return sb->acr->func->reset(sb->acr, sb, falcon_mask);
 }
 
 /**
-- 
2.12.0

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

Reply via email to