summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2020-01-15 06:34:22 +1000
committerBen Skeggs <bskeggs@redhat.com>2020-01-15 10:50:29 +1000
commit86ce2a71539c47241dc8f471d8724f5bd1e41ae6 (patch)
treeafa0764ad6eede100a125bc4e56a963500fed3e9 /drivers/gpu/drm
parent25fd061cc7dd3b8cc37f4874565c14fe18f40c8b (diff)
drm/nouveau/flcn/cmdq: move command generation to subdevs
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>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/include/nvfw/pmu.h47
-rw-r--r--drivers/gpu/drm/nouveau/include/nvfw/sec2.h30
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h23
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c28
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c142
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c76
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c74
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c34
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c36
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c17
16 files changed, 300 insertions, 276 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvfw/pmu.h b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h
new file mode 100644
index 000000000000..6e86ce31f963
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h
@@ -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
index 000000000000..2f7460fe1b76
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h
@@ -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
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h
index bf3e532665fb..acb339f34bb5 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h
@@ -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
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
index 6b342a63e2cb..7e51bd4befce 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
@@ -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
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
index 9a5bae1a03cd..26f738d1202e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
@@ -20,11 +20,53 @@
* 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
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
index e5ba6df3d500..9c00e6634499 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
@@ -5,6 +5,7 @@
struct nvkm_sec2_func {
const struct nvkm_falcon_func *flcn;
+ u8 unit_acr;
void (*intr)(struct nvkm_sec2 *);
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
index 3e14c7bc3e32..9867a32da42a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
@@ -36,34 +36,6 @@ nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *queue, void *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)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
index 65a2a045fae7..bf714f391d42 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
@@ -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);
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c
index b8c0fcdff156..7e450a91c62e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c
@@ -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,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c
index 2826822cd0fc..51ae4a10b213 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c
@@ -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,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
index 11658a4afc7a..6caced3589bc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
@@ -23,19 +23,90 @@
#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))
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h
index 882290423c01..808ba7f191b4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h
@@ -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);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
index 5c262a28aa23..e803cc461227 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
@@ -20,11 +20,45 @@
* 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
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
index 7134ef9d91af..b2baf9b636a3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
@@ -20,10 +20,46 @@
* 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
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
index 91b4a2d3ad4c..0e7965028dcf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
@@ -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 {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
index 53770ecdbb2f..dcb6eb24ba6a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
@@ -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;