]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
drm/nouveau/flcn/cmdq: move command generation to subdevs
authorBen Skeggs <bskeggs@redhat.com>
Tue, 14 Jan 2020 20:34:22 +0000 (06:34 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 15 Jan 2020 00:50:29 +0000 (10:50 +1000)
This moves the code to generate commands for the ACR unit of the PMU/SEC2 LS
firmwares to those subdevs.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
16 files changed:
drivers/gpu/drm/nouveau/include/nvfw/pmu.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/include/nvfw/sec2.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c
drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c
drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h
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/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c

diff --git a/drivers/gpu/drm/nouveau/include/nvfw/pmu.h b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h
new file mode 100644 (file)
index 0000000..6e86ce3
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __NVFW_PMU_H__
+#define __NVFW_PMU_H__
+
+#define NV_PMU_UNIT_ACR                                                    0x0a
+
+struct nv_pmu_acr_cmd {
+       struct nv_falcon_cmd hdr;
+#define NV_PMU_ACR_CMD_INIT_WPR_REGION                                     0x00
+#define NV_PMU_ACR_CMD_BOOTSTRAP_FALCON                                    0x01
+#define NV_PMU_ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS                          0x03
+       u8 cmd_type;
+};
+
+struct nv_pmu_acr_msg {
+       struct nv_falcon_cmd hdr;
+       u8 msg_type;
+};
+
+struct nv_pmu_acr_bootstrap_falcon_cmd {
+       struct nv_pmu_acr_cmd cmd;
+#define NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES                  0x00000000
+#define NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_NO                   0x00000001
+       u32 flags;
+       u32 falcon_id;
+};
+
+struct nv_pmu_acr_bootstrap_falcon_msg {
+       struct nv_pmu_acr_msg msg;
+       u32 falcon_id;
+};
+
+struct nv_pmu_acr_bootstrap_multiple_falcons_cmd {
+       struct nv_pmu_acr_cmd cmd;
+#define NV_PMU_ACR_BOOTSTRAP_MULTIPLE_FALCONS_FLAGS_RESET_YES        0x00000000
+#define NV_PMU_ACR_BOOTSTRAP_MULTIPLE_FALCONS_FLAGS_RESET_NO         0x00000001
+       u32 flags;
+       u32 falcon_mask;
+       u32 use_va_mask;
+       u32 wpr_lo;
+       u32 wpr_hi;
+};
+
+struct nv_pmu_acr_bootstrap_multiple_falcons_msg {
+       struct nv_pmu_acr_msg msg;
+       u32 falcon_mask;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h
new file mode 100644 (file)
index 0000000..2f7460f
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __NVFW_SEC2_H__
+#define __NVFW_SEC2_H__
+
+#define NV_SEC2_UNIT_ACR                                                   0x08
+
+struct nv_sec2_acr_cmd {
+       struct nv_falcon_cmd hdr;
+#define NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON                                   0x00
+       u8 cmd_type;
+};
+
+struct nv_sec2_acr_msg {
+       struct nv_falcon_cmd hdr;
+       u8 msg_type;
+};
+
+struct nv_sec2_acr_bootstrap_falcon_cmd {
+       struct nv_sec2_acr_cmd cmd;
+#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES                 0x00000000
+#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_NO                  0x00000001
+       u32 flags;
+       u32 falcon_id;
+};
+
+struct nv_sec2_acr_bootstrap_falcon_msg {
+       struct nv_sec2_acr_msg msg;
+       u32 error_code;
+       u32 falcon_id;
+};
+#endif
index bf3e532665fbf93b91d87611c1dc0a623d73c9bf..acb339f34bb5e6f27990fb08edb73eb10def48bb 100644 (file)
@@ -37,7 +37,4 @@ int nvkm_msgqueue_reinit(struct nvkm_msgqueue *);
 /* useful if we run a NVIDIA-signed firmware */
 void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *);
 
-/* interface to ACR unit running on falcon (NVIDIA signed firmware) */
-int nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *, unsigned long);
-
 #endif
index 6b342a63e2cbeef0aed65a7edf61c34c1dfbc4e6..7e51bd4befce4174f5a53b7fd68990b84b368034 100644 (file)
@@ -13,15 +13,34 @@ enum nvkm_acr_lsf_id {
        NVKM_ACR_LSF_NVDEC = 4,
        NVKM_ACR_LSF_SEC2 = 7,
        NVKM_ACR_LSF_MINION = 10,
+       NVKM_ACR_LSF_NUM
 };
 
+static inline const char *
+nvkm_acr_lsf_id(enum nvkm_acr_lsf_id id)
+{
+       switch (id) {
+       case NVKM_ACR_LSF_PMU    : return "pmu";
+       case NVKM_ACR_LSF_GSPLITE: return "gsplite";
+       case NVKM_ACR_LSF_FECS   : return "fecs";
+       case NVKM_ACR_LSF_GPCCS  : return "gpccs";
+       case NVKM_ACR_LSF_NVDEC  : return "nvdec";
+       case NVKM_ACR_LSF_SEC2   : return "sec2";
+       case NVKM_ACR_LSF_MINION : return "minion";
+       default:
+               return "unknown";
+       }
+}
+
 struct nvkm_acr {
        const struct nvkm_acr_func *func;
        struct nvkm_subdev subdev;
 
-       struct list_head lsfw;
+       struct list_head lsfw, lsf;
 };
 
+int nvkm_acr_bootstrap_falcons(struct nvkm_device *, unsigned long mask);
+
 int gm200_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
 int gm20b_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
 int gp102_acr_new(struct nvkm_device *, int, struct nvkm_acr **);
@@ -55,6 +74,8 @@ struct nvkm_acr_lsfw {
 };
 
 struct nvkm_acr_lsf_func {
+       int (*bootstrap_falcon)(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
+       int (*bootstrap_multiple_falcons)(struct nvkm_falcon *, u32 mask);
 };
 
 int
index 9a5bae1a03cdb1862f030b50ae70169329c92739..26f738d1202ed6a9a55a42be29b40dc694431ee0 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  */
 #include "priv.h"
+
 #include <subdev/acr.h>
 #include <subdev/timer.h>
 
+#include <nvfw/sec2.h>
+
+static int
+gp102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nv_falcon_msg *hdr)
+{
+       struct nv_sec2_acr_bootstrap_falcon_msg *msg =
+               container_of(hdr, typeof(*msg), msg.hdr);
+       struct nvkm_subdev *subdev = priv;
+       const char *name = nvkm_acr_lsf_id(msg->falcon_id);
+
+       if (msg->error_code) {
+               nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for "
+                                  "falcon %d [%s]: %08x\n",
+                          msg->falcon_id, name, msg->error_code);
+               return -EINVAL;
+       }
+
+       nvkm_debug(subdev, "%s booted\n", name);
+       return 0;
+}
+
+static int
+gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
+                               enum nvkm_acr_lsf_id id)
+{
+       struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon);
+       struct nv_sec2_acr_bootstrap_falcon_cmd cmd = {
+               .cmd.hdr.unit_id = sec2->func->unit_acr,
+               .cmd.hdr.size = sizeof(cmd),
+               .cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON,
+               .flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES,
+               .falcon_id = id,
+       };
+
+       return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr,
+                                    gp102_sec2_acr_bootstrap_falcon_callback,
+                                    &sec2->engine.subdev,
+                                    msecs_to_jiffies(1000));
+}
+
 static const struct nvkm_acr_lsf_func
 gp102_sec2_acr_0 = {
+       .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
 };
 
 void
@@ -117,6 +159,7 @@ gp102_sec2_flcn = {
 const struct nvkm_sec2_func
 gp102_sec2 = {
        .flcn = &gp102_sec2_flcn,
+       .unit_acr = NV_SEC2_UNIT_ACR,
        .intr = gp102_sec2_intr,
 };
 
@@ -135,6 +178,7 @@ MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin");
 
 const struct nvkm_acr_lsf_func
 gp102_sec2_acr_1 = {
+       .bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
 };
 
 int
index e5ba6df3d500548c88bcee75bad2b412cf93bb28..9c00e663449951d8eb448929facf439260a43c11 100644 (file)
@@ -5,6 +5,7 @@
 
 struct nvkm_sec2_func {
        const struct nvkm_falcon_func *flcn;
+       u8 unit_acr;
        void (*intr)(struct nvkm_sec2 *);
 };
 
index 3e14c7bc3e32257a90f8c9d8f7067342efe05480..9867a32da42a7431298bf9b8de0ba5e17bbde62f 100644 (file)
@@ -35,34 +35,6 @@ nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *queue, void *buf)
        queue->func->init_func->gen_cmdline(queue, buf);
 }
 
-int
-nvkm_msgqueue_acr_boot_falcons(struct nvkm_msgqueue *queue,
-                              unsigned long falcon_mask)
-{
-       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;
-
-       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
 nvkm_msgqueue_new(u32 version, struct nvkm_falcon *falcon,
                  const struct nvkm_secboot *sb, struct nvkm_msgqueue **queue)
index 65a2a045fae75430252e97f8384592697a1d500b..bf714f391d42f88ae3cb67990109c40f41b47d10 100644 (file)
@@ -90,20 +90,8 @@ struct nvkm_msgqueue_init_func {
        int (*init_callback)(struct nvkm_msgqueue *, struct nvkm_msgqueue_hdr *);
 };
 
-/**
- * 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 {
        const struct nvkm_msgqueue_init_func *init_func;
-       const struct nvkm_msgqueue_acr_func *acr_func;
        void (*dtor)(struct nvkm_msgqueue *);
        void (*recv)(struct nvkm_msgqueue *queue);
 };
index b8c0fcdff156751c5082cbda522b2e3bb115f93e..7e450a91c62e8eb0d318bc8f5aecd3889a69da6c 100644 (file)
@@ -147,8 +147,6 @@ msgqueue_0137c63d_init_func = {
 
 enum {
        ACR_CMD_INIT_WPR_REGION = 0x00,
-       ACR_CMD_BOOTSTRAP_FALCON = 0x01,
-       ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS = 0x03,
 };
 
 static int
@@ -198,144 +196,6 @@ acr_init_wpr(struct nvkm_msgqueue *queue)
                                     pmu, 0);
 }
 
-
-static int
-acr_boot_falcon_callback(void *priv, struct nv_falcon_msg *hdr)
-{
-       struct acr_bootstrap_falcon_msg {
-               struct nv_falcon_msg base;
-               u8 msg_type;
-               u32 falcon_id;
-       } *msg = (void *)hdr;
-       struct nvkm_subdev *subdev = priv;
-       u32 falcon_id = msg->falcon_id;
-
-       if (falcon_id >= NVKM_SECBOOT_FALCON_END) {
-               nvkm_error(subdev, "in bootstrap falcon callback:\n");
-               nvkm_error(subdev, "invalid falcon ID 0x%x\n", falcon_id);
-               return -EINVAL;
-       }
-
-       nvkm_debug(subdev, "%s booted\n", nvkm_secboot_falcon_name[falcon_id]);
-       return 0;
-}
-
-enum {
-       ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES = 0,
-       ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_NO = 1,
-};
-
-static int
-acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon)
-{
-       struct nvkm_pmu *pmu = priv->falcon->owner->device->pmu;
-       /*
-        * flags      - Flag specifying RESET or no RESET.
-        * falcon id  - Falcon id specifying falcon to bootstrap.
-        */
-       struct {
-               struct nv_falcon_cmd hdr;
-               u8 cmd_type;
-               u32 flags;
-               u32 falcon_id;
-       } cmd;
-
-       if (!wait_for_completion_timeout(&pmu->wpr_ready,
-                                        msecs_to_jiffies(1000))) {
-               nvkm_error(&pmu->subdev, "timeout waiting for WPR init\n");
-               return -ETIMEDOUT;
-       }
-
-       memset(&cmd, 0, sizeof(cmd));
-
-       cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR;
-       cmd.hdr.size = sizeof(cmd);
-       cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON;
-       cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES;
-       cmd.falcon_id = falcon;
-       return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr,
-                                    acr_boot_falcon_callback, &pmu->subdev,
-                                    msecs_to_jiffies(1000));
-}
-
-static int
-acr_boot_multiple_falcons_callback(void *priv, struct nv_falcon_msg *hdr)
-{
-       struct acr_bootstrap_falcon_msg {
-               struct nv_falcon_msg base;
-               u8 msg_type;
-               u32 falcon_mask;
-       } *msg = (void *)hdr;
-       const struct nvkm_subdev *subdev = priv;
-       unsigned long falcon_mask = msg->falcon_mask;
-       u32 falcon_id, falcon_treated = 0;
-
-       for_each_set_bit(falcon_id, &falcon_mask, NVKM_SECBOOT_FALCON_END) {
-               nvkm_debug(subdev, "%s booted\n",
-                          nvkm_secboot_falcon_name[falcon_id]);
-               falcon_treated |= BIT(falcon_id);
-       }
-
-       if (falcon_treated != msg->falcon_mask) {
-               nvkm_error(subdev, "in bootstrap falcon callback:\n");
-               nvkm_error(subdev, "invalid falcon mask 0x%x\n",
-                          msg->falcon_mask);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int
-acr_boot_multiple_falcons(struct nvkm_msgqueue *priv, unsigned long falcon_mask)
-{
-       struct nvkm_pmu *pmu = priv->falcon->owner->device->pmu;
-       /*
-        * flags      - Flag specifying RESET or no RESET.
-        * falcon id  - Falcon id specifying falcon to bootstrap.
-        */
-       struct {
-               struct nv_falcon_cmd hdr;
-               u8 cmd_type;
-               u32 flags;
-               u32 falcon_mask;
-               u32 use_va_mask;
-               u32 wpr_lo;
-               u32 wpr_hi;
-       } cmd;
-       struct msgqueue_0137bca5 *queue = msgqueue_0137bca5(priv);
-
-       if (!wait_for_completion_timeout(&pmu->wpr_ready,
-                                        msecs_to_jiffies(1000))) {
-               nvkm_error(&pmu->subdev, "timeout waiting for WPR init\n");
-               return -ETIMEDOUT;
-       }
-
-       memset(&cmd, 0, sizeof(cmd));
-
-       cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR;
-       cmd.hdr.size = sizeof(cmd);
-       cmd.cmd_type = ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS;
-       cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES;
-       cmd.falcon_mask = falcon_mask;
-       cmd.wpr_lo = lower_32_bits(queue->wpr_addr);
-       cmd.wpr_hi = upper_32_bits(queue->wpr_addr);
-       return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr,
-                                    acr_boot_multiple_falcons_callback,
-                                    &pmu->subdev, msecs_to_jiffies(1000));
-}
-
-static const struct nvkm_msgqueue_acr_func
-msgqueue_0137c63d_acr_func = {
-       .boot_falcon = acr_boot_falcon,
-};
-
-static const struct nvkm_msgqueue_acr_func
-msgqueue_0137bca5_acr_func = {
-       .boot_falcon = acr_boot_falcon,
-       .boot_multiple_falcons = acr_boot_multiple_falcons,
-};
-
 static void
 msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue)
 {
@@ -345,7 +205,6 @@ msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue)
 static const struct nvkm_msgqueue_func
 msgqueue_0137c63d_func = {
        .init_func = &msgqueue_0137c63d_init_func,
-       .acr_func = &msgqueue_0137c63d_acr_func,
        .recv = msgqueue_0137c63d_process_msgs,
        .dtor = msgqueue_0137c63d_dtor,
 };
@@ -370,7 +229,6 @@ msgqueue_0137c63d_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb,
 static const struct nvkm_msgqueue_func
 msgqueue_0137bca5_func = {
        .init_func = &msgqueue_0137c63d_init_func,
-       .acr_func = &msgqueue_0137bca5_acr_func,
        .recv = msgqueue_0137c63d_process_msgs,
        .dtor = msgqueue_0137c63d_dtor,
 };
index 2826822cd0fce509d2d4e03213debcde8599df96..51ae4a10b2131b16ff9c415960ae6634cbfe1410 100644 (file)
@@ -130,81 +130,6 @@ msgqueue_0148cdec_init_func = {
 };
 
 
-
-/* ACR unit */
-#define MSGQUEUE_0148CDEC_UNIT_ACR 0x08
-
-enum {
-       ACR_CMD_BOOTSTRAP_FALCON = 0x00,
-};
-
-static int
-acr_boot_falcon_callback(void *priv, struct nv_falcon_msg *hdr)
-{
-       struct acr_bootstrap_falcon_msg {
-               struct nv_falcon_msg base;
-               u8 msg_type;
-               u32 error_code;
-               u32 falcon_id;
-       } *msg = (void *)hdr;
-       const struct nvkm_subdev *subdev = priv;
-       u32 falcon_id = msg->falcon_id;
-
-       if (msg->error_code) {
-               nvkm_error(subdev, "in bootstrap falcon callback:\n");
-               nvkm_error(subdev, "expected error code 0x%x\n",
-                          msg->error_code);
-               return -EINVAL;
-       }
-
-       if (falcon_id >= NVKM_SECBOOT_FALCON_END) {
-               nvkm_error(subdev, "in bootstrap falcon callback:\n");
-               nvkm_error(subdev, "invalid falcon ID 0x%x\n", falcon_id);
-               return -EINVAL;
-       }
-
-       nvkm_debug(subdev, "%s booted\n", nvkm_secboot_falcon_name[falcon_id]);
-       return 0;
-}
-
-enum {
-       ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES = 0,
-       ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_NO = 1,
-};
-
-static int
-acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon)
-{
-       struct nvkm_sec2 *sec2 = priv->falcon->owner->device->sec2;
-       /*
-        * flags      - Flag specifying RESET or no RESET.
-        * falcon id  - Falcon id specifying falcon to bootstrap.
-        */
-       struct {
-               struct nv_falcon_cmd hdr;
-               u8 cmd_type;
-               u32 flags;
-               u32 falcon_id;
-       } cmd;
-
-       memset(&cmd, 0, sizeof(cmd));
-
-       cmd.hdr.unit_id = MSGQUEUE_0148CDEC_UNIT_ACR;
-       cmd.hdr.size = sizeof(cmd);
-       cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON;
-       cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES;
-       cmd.falcon_id = falcon;
-       return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.hdr,
-                                    acr_boot_falcon_callback,
-                                    &sec2->engine.subdev,
-                                    msecs_to_jiffies(1000));
-}
-
-const struct nvkm_msgqueue_acr_func
-msgqueue_0148cdec_acr_func = {
-       .boot_falcon = acr_boot_falcon,
-};
-
 static void
 msgqueue_0148cdec_dtor(struct nvkm_msgqueue *queue)
 {
@@ -214,7 +139,6 @@ msgqueue_0148cdec_dtor(struct nvkm_msgqueue *queue)
 const struct nvkm_msgqueue_func
 msgqueue_0148cdec_func = {
        .init_func = &msgqueue_0148cdec_init_func,
-       .acr_func = &msgqueue_0148cdec_acr_func,
        .recv = msgqueue_0148cdec_process_msgs,
        .dtor = msgqueue_0148cdec_dtor,
 };
index 11658a4afc7a59e94594e76a4a7f3d415cca7fe4..6caced3589bc8877fbc4675f8056bd0c6b4266cf 100644 (file)
 
 #include <core/firmware.h>
 
+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);
+       unsigned long id;
+
+       if (!acrflcn)
+               return -ENOSYS;
+
+       if (acrflcn->func->bootstrap_multiple_falcons) {
+               return acrflcn->func->
+                       bootstrap_multiple_falcons(acrflcn->falcon, mask);
+       }
+
+       for_each_set_bit(id, &mask, NVKM_ACR_LSF_NUM) {
+               int ret = acrflcn->func->bootstrap_falcon(acrflcn->falcon, id);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static void
+nvkm_acr_cleanup(struct nvkm_acr *acr)
+{
+       nvkm_acr_lsfw_del_all(acr);
+}
+
+static int
+nvkm_acr_oneinit(struct nvkm_subdev *subdev)
+{
+       struct nvkm_acr *acr = nvkm_acr(subdev);
+       struct nvkm_acr_lsfw *lsfw;
+       struct nvkm_acr_lsf *lsf;
+
+       list_for_each_entry(lsfw, &acr->lsfw, head) {
+               if (!(lsf = kmalloc(sizeof(*lsf), GFP_KERNEL)))
+                       return -ENOMEM;
+               lsf->func = lsfw->func;
+               lsf->falcon = lsfw->falcon;
+               lsf->id = lsfw->id;
+               list_add_tail(&lsf->head, &acr->lsf);
+       }
+
+       nvkm_acr_cleanup(acr);
+       return 0;
+}
+
 static void *
 nvkm_acr_dtor(struct nvkm_subdev *subdev)
 {
        struct nvkm_acr *acr = nvkm_acr(subdev);
+       struct nvkm_acr_lsf *lsf, *lst;
 
-       nvkm_acr_lsfw_del_all(acr);
+       list_for_each_entry_safe(lsf, lst, &acr->lsf, head) {
+               list_del(&lsf->head);
+               kfree(lsf);
+       }
 
+       nvkm_acr_cleanup(acr);
        return acr;
 }
 
 static const struct nvkm_subdev_func
 nvkm_acr = {
        .dtor = nvkm_acr_dtor,
+       .oneinit = nvkm_acr_oneinit,
 };
 
 int
@@ -48,6 +119,7 @@ nvkm_acr_new_(const struct nvkm_acr_fwif *fwif, struct nvkm_device *device,
                return -ENOMEM;
        nvkm_subdev_ctor(&nvkm_acr, device, index, &acr->subdev);
        INIT_LIST_HEAD(&acr->lsfw);
+       INIT_LIST_HEAD(&acr->lsf);
 
        fwif = nvkm_firmware_load(&acr->subdev, fwif, "Acr", acr);
        if (IS_ERR(fwif))
index 882290423c017f78e8c0fa5683fa077b189f74b7..808ba7f191b453f2130b9ce5b9c3364be2d6d884 100644 (file)
@@ -18,6 +18,13 @@ struct nvkm_acr_func {
 int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, int,
                  struct nvkm_acr **);
 
+struct nvkm_acr_lsf {
+       const struct nvkm_acr_lsf_func *func;
+       struct nvkm_falcon *falcon;
+       enum nvkm_acr_lsf_id id;
+       struct list_head head;
+};
+
 struct nvkm_acr_lsfw *nvkm_acr_lsfw_add(const struct nvkm_acr_lsf_func *,
                                        struct nvkm_acr *, struct nvkm_falcon *,
                                        enum nvkm_acr_lsf_id);
index 5c262a28aa23119a89d1468c878b141b67a5387c..e803cc4612274261cdba0b34841b15bcffb2257e 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  */
 #include "priv.h"
+
 #include <core/msgqueue.h>
 #include <subdev/acr.h>
 
+#include <nvfw/pmu.h>
+
+static int
+gm20b_pmu_acr_bootstrap_falcon_cb(void *priv, struct nv_falcon_msg *hdr)
+{
+       struct nv_pmu_acr_bootstrap_falcon_msg *msg =
+               container_of(hdr, typeof(*msg), msg.hdr);
+       return msg->falcon_id;
+}
+
+int
+gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
+                              enum nvkm_acr_lsf_id id)
+{
+       struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon);
+       struct nv_pmu_acr_bootstrap_falcon_cmd cmd = {
+               .cmd.hdr.unit_id = NV_PMU_UNIT_ACR,
+               .cmd.hdr.size = sizeof(cmd),
+               .cmd.cmd_type = NV_PMU_ACR_CMD_BOOTSTRAP_FALCON,
+               .flags = NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES,
+               .falcon_id = id,
+       };
+       int ret;
+
+       ret = nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr,
+                                   gm20b_pmu_acr_bootstrap_falcon_cb,
+                                   &pmu->subdev, msecs_to_jiffies(1000));
+       if (ret >= 0 && ret != cmd.falcon_id)
+               ret = -EIO;
+       return ret;
+}
+
 static const struct nvkm_acr_lsf_func
 gm20b_pmu_acr = {
+       .bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon,
 };
 
 void
index 7134ef9d91afed9405dbf1b944e597c5b1408baf..b2baf9b636a32b13ed2156d2d362bfcf946ce4b1 100644 (file)
  * DEALINGS IN THE SOFTWARE.
  */
 #include "priv.h"
+
 #include <subdev/acr.h>
 
+#include <nvfw/pmu.h>
+
+static int
+gp10b_pmu_acr_bootstrap_multiple_falcons_cb(void *priv,
+                                           struct nv_falcon_msg *hdr)
+{
+       struct nv_pmu_acr_bootstrap_multiple_falcons_msg *msg =
+               container_of(hdr, typeof(*msg), msg.hdr);
+       return msg->falcon_mask;
+}
+static int
+gp10b_pmu_acr_bootstrap_multiple_falcons(struct nvkm_falcon *falcon, u32 mask)
+{
+       struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon);
+       struct nv_pmu_acr_bootstrap_multiple_falcons_cmd cmd = {
+               .cmd.hdr.unit_id = NV_PMU_UNIT_ACR,
+               .cmd.hdr.size = sizeof(cmd),
+               .cmd.cmd_type = NV_PMU_ACR_CMD_BOOTSTRAP_MULTIPLE_FALCONS,
+               .flags = NV_PMU_ACR_BOOTSTRAP_MULTIPLE_FALCONS_FLAGS_RESET_YES,
+               .falcon_mask = mask,
+               .wpr_lo = 0, /*XXX*/
+               .wpr_hi = 0, /*XXX*/
+       };
+       int ret;
+
+       ret = nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr,
+                                   gp10b_pmu_acr_bootstrap_multiple_falcons_cb,
+                                   &pmu->subdev, msecs_to_jiffies(1000));
+       if (ret >= 0 && ret != cmd.falcon_mask)
+               ret = -EIO;
+       return ret;
+}
+
 static const struct nvkm_acr_lsf_func
 gp10b_pmu_acr = {
+       .bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon,
+       .bootstrap_multiple_falcons = gp10b_pmu_acr_bootstrap_multiple_falcons,
 };
 
 static const struct nvkm_pmu_func
index 91b4a2d3ad4c9d2f171f993124e1bb21bafad120..0e7965028dcfa08bb9f0eecfb6423fc4eaf49c65 100644 (file)
@@ -4,6 +4,7 @@
 #define nvkm_pmu(p) container_of((p), struct nvkm_pmu, subdev)
 #include <subdev/pmu.h>
 #include <subdev/pmu/fuc/os.h>
+enum nvkm_acr_lsf_id;
 
 struct nvkm_pmu_func {
        const struct nvkm_falcon_func *flcn;
@@ -41,6 +42,7 @@ void gf100_pmu_reset(struct nvkm_pmu *);
 
 void gk110_pmu_pgob(struct nvkm_pmu *, bool);
 
+int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
 void gm20b_pmu_recv(struct nvkm_pmu *);
 
 struct nvkm_pmu_fwif {
index 53770ecdbb2f75dd87cdb5f393434f18627798dd..dcb6eb24ba6af4bb7b3b1cc6e75a1a97d33f1848 100644 (file)
@@ -991,12 +991,13 @@ end:
  * load the HS firmware and run it, so once the falcon stops all the managed
  * falcons should have their LS firmware loaded and be ready to run.
  */
+int nvkm_acr_bootstrap_falcons(struct nvkm_device *, unsigned long);
+
 static int
 acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
               unsigned long falcon_mask)
 {
        struct acr_r352 *acr = acr_r352(_acr);
-       struct nvkm_msgqueue *queue;
        int falcon;
        bool wpr_already_set = sb->wpr_set;
        int ret;
@@ -1016,22 +1017,12 @@ acr_r352_reset(struct nvkm_acr *_acr, struct nvkm_secboot *sb,
                        return ret;
        }
 
-       switch (_acr->boot_falcon) {
-       case NVKM_SECBOOT_FALCON_PMU:
-               queue = sb->subdev.device->pmu->queue;
-               break;
-       case NVKM_SECBOOT_FALCON_SEC2:
-               queue = sb->subdev.device->sec2->queue;
-               break;
-       default:
-               return -EINVAL;
-       }
-
        /* Otherwise just ask the LS firmware to reset the 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);
+
+       ret = nvkm_acr_bootstrap_falcons(sb->subdev.device, falcon_mask);
        if (ret) {
                nvkm_error(&sb->subdev, "error during falcon reset: %d\n", ret);
                return ret;