aboutsummaryrefslogtreecommitdiffstats
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
commitd114a1393fa01c4034d895072905578319a903f9 (patch)
treeb919222d6234608a07eab974b156945a0cc65ba1
parentdrm/nouveau/flcn/msgq: drop nvkm_msgqueue argument to functions (diff)
downloadlinux-dev-d114a1393fa01c4034d895072905578319a903f9.tar.xz
linux-dev-d114a1393fa01c4034d895072905578319a903f9.zip
drm/nouveau/flcn/msgq: move handling of init message to subdevs
When the PMU/SEC2 LS FWs have booted, they'll send a message to the host with various information, including the configuration of message/command queues that are available. Move the handling for this to the relevant subdevs. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/include/nvfw/pmu.h31
-rw-r--r--drivers/gpu/drm/nouveau/include/nvfw/sec2.h22
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c57
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c118
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c66
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c72
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c2
19 files changed, 202 insertions, 265 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvfw/pmu.h b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h
index 6e86ce31f963..f808998e2ea1 100644
--- a/drivers/gpu/drm/nouveau/include/nvfw/pmu.h
+++ b/drivers/gpu/drm/nouveau/include/nvfw/pmu.h
@@ -1,8 +1,28 @@
#ifndef __NVFW_PMU_H__
#define __NVFW_PMU_H__
+#define NV_PMU_UNIT_INIT 0x07
#define NV_PMU_UNIT_ACR 0x0a
+struct nv_pmu_init_msg {
+ struct nv_falcon_msg hdr;
+#define NV_PMU_INIT_MSG_INIT 0x00
+ u8 msg_type;
+
+ u8 pad;
+ u16 os_debug_entry_point;
+
+ struct {
+ u16 size;
+ u16 offset;
+ u8 index;
+ u8 pad;
+ } queue_info[5];
+
+ u16 sw_managed_area_offset;
+ u16 sw_managed_area_size;
+};
+
struct nv_pmu_acr_cmd {
struct nv_falcon_cmd hdr;
#define NV_PMU_ACR_CMD_INIT_WPR_REGION 0x00
@@ -16,6 +36,17 @@ struct nv_pmu_acr_msg {
u8 msg_type;
};
+struct nv_pmu_acr_init_wpr_region_cmd {
+ struct nv_pmu_acr_cmd cmd;
+ u32 region_id;
+ u32 wpr_offset;
+};
+
+struct nv_pmu_acr_init_wpr_region_msg {
+ struct nv_pmu_acr_msg msg;
+ u32 error_code;
+};
+
struct nv_pmu_acr_bootstrap_falcon_cmd {
struct nv_pmu_acr_cmd cmd;
#define NV_PMU_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES 0x00000000
diff --git a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h
index 2f7460fe1b76..80753cfa4cb3 100644
--- a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h
+++ b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h
@@ -1,8 +1,30 @@
#ifndef __NVFW_SEC2_H__
#define __NVFW_SEC2_H__
+#define NV_SEC2_UNIT_INIT 0x01
#define NV_SEC2_UNIT_ACR 0x08
+struct nv_sec2_init_msg {
+ struct nv_falcon_msg hdr;
+#define NV_SEC2_INIT_MSG_INIT 0x00
+ u8 msg_type;
+
+ u8 num_queues;
+ u16 os_debug_entry_point;
+
+ struct {
+ u32 offset;
+ u16 size;
+ u8 index;
+#define NV_SEC2_INIT_MSG_QUEUE_ID_CMDQ 0x00
+#define NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ 0x01
+ u8 id;
+ } queue_info[2];
+
+ u32 sw_managed_area_offset;
+ u16 sw_managed_area_size;
+};
+
struct nv_sec2_acr_cmd {
struct nv_falcon_cmd hdr;
#define NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON 0x00
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h
index 54e1f4d7568f..a37d2008406b 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h
@@ -72,4 +72,5 @@ int nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *, const char *name,
void nvkm_falcon_msgq_del(struct nvkm_falcon_msgq **);
void nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *,
u32 index, u32 offset, u32 size);
+int nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *, void *, u32 size);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h
index acb339f34bb5..19f2fdb3e754 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h
@@ -32,7 +32,6 @@ int nvkm_msgqueue_new(u32, struct nvkm_falcon *, const struct nvkm_secboot *,
struct nvkm_msgqueue **);
void nvkm_msgqueue_del(struct nvkm_msgqueue **);
void nvkm_msgqueue_recv(struct nvkm_msgqueue *);
-int nvkm_msgqueue_reinit(struct nvkm_msgqueue *);
/* useful if we run a NVIDIA-signed firmware */
void nvkm_msgqueue_write_cmdline(struct nvkm_msgqueue *, void *);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
index ca1b227a81f9..44da8d3ac86e 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
@@ -14,7 +14,9 @@ struct nvkm_sec2 {
struct nvkm_falcon_cmdq *cmdq;
struct nvkm_falcon_msgq *msgq;
struct nvkm_msgqueue *queue;
+
struct work_struct work;
+ bool initmsg_received;
};
int gp102_sec2_new(struct nvkm_device *, int, struct nvkm_sec2 **);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
index 21607b40aee6..79351a74642e 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
@@ -13,6 +13,7 @@ struct nvkm_pmu {
struct nvkm_falcon_cmdq *hpq;
struct nvkm_falcon_cmdq *lpq;
struct nvkm_falcon_msgq *msgq;
+ bool initmsg_received;
struct nvkm_msgqueue *queue;
struct completion wpr_ready;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
index d85aeb059c87..f6a453dc75ad 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
@@ -30,6 +30,17 @@ nvkm_sec2_recv(struct work_struct *work)
{
struct nvkm_sec2 *sec2 = container_of(work, typeof(*sec2), work);
+ if (!sec2->initmsg_received) {
+ int ret = sec2->func->initmsg(sec2);
+ if (ret) {
+ nvkm_error(&sec2->engine.subdev,
+ "error parsing init message: %d\n", ret);
+ return;
+ }
+
+ sec2->initmsg_received = true;
+ }
+
if (!sec2->queue) {
nvkm_warn(&sec2->engine.subdev,
"recv function called while no firmware set!\n");
@@ -50,8 +61,14 @@ static int
nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend)
{
struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
+
flush_work(&sec2->work);
- nvkm_falcon_cmdq_fini(sec2->cmdq);
+
+ if (suspend) {
+ nvkm_falcon_cmdq_fini(sec2->cmdq);
+ sec2->initmsg_received = false;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
index 26f738d1202e..26a468047747 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
@@ -69,6 +69,37 @@ gp102_sec2_acr_0 = {
.bootstrap_falcon = gp102_sec2_acr_bootstrap_falcon,
};
+int
+gp102_sec2_initmsg(struct nvkm_sec2 *sec2)
+{
+ struct nv_sec2_init_msg msg;
+ int ret, i;
+
+ ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg));
+ if (ret)
+ return ret;
+
+ if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT ||
+ msg.msg_type != NV_SEC2_INIT_MSG_INIT)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) {
+ if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) {
+ nvkm_falcon_msgq_init(sec2->msgq,
+ msg.queue_info[i].index,
+ msg.queue_info[i].offset,
+ msg.queue_info[i].size);
+ } else {
+ nvkm_falcon_cmdq_init(sec2->cmdq,
+ msg.queue_info[i].index,
+ msg.queue_info[i].offset,
+ msg.queue_info[i].size);
+ }
+ }
+
+ return 0;
+}
+
void
gp102_sec2_intr(struct nvkm_sec2 *sec2)
{
@@ -161,6 +192,7 @@ gp102_sec2 = {
.flcn = &gp102_sec2_flcn,
.unit_acr = NV_SEC2_UNIT_ACR,
.intr = gp102_sec2_intr,
+ .initmsg = gp102_sec2_initmsg,
};
MODULE_FIRMWARE("nvidia/gp102/sec2/desc.bin");
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
index 9c00e6634499..1992391832a1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
@@ -7,6 +7,7 @@ struct nvkm_sec2_func {
const struct nvkm_falcon_func *flcn;
u8 unit_acr;
void (*intr)(struct nvkm_sec2 *);
+ int (*initmsg)(struct nvkm_sec2 *);
};
void gp102_sec2_intr(struct nvkm_sec2 *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c
index 1c7dab86af80..b906534fc7fa 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c
@@ -136,40 +136,27 @@ msgqueue_msg_handle(struct nvkm_falcon_msgq *msgq, struct nv_falcon_msg *hdr)
return 0;
}
-static int
-msgqueue_handle_init_msg(struct nvkm_msgqueue *priv)
+int
+nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *msgq,
+ void *data, u32 size)
{
- struct nvkm_falcon *falcon = priv->falcon;
- const struct nvkm_subdev *subdev = falcon->owner;
- const u32 tail_reg = falcon->func->msgq.tail;
- u8 msg_buffer[MSG_BUF_SIZE];
- struct nvkm_msgqueue_hdr *hdr = (void *)msg_buffer;
- u32 tail;
+ struct nvkm_falcon *falcon = msgq->qmgr->falcon;
+ struct nv_falcon_msg *hdr = data;
int ret;
- /*
- * Read the message - queues are not initialized yet so we cannot rely
- * on msg_queue_read()
- */
- tail = nvkm_falcon_rd32(falcon, tail_reg);
- nvkm_falcon_read_dmem(falcon, tail, HDR_SIZE, 0, hdr);
+ msgq->head_reg = falcon->func->msgq.head;
+ msgq->tail_reg = falcon->func->msgq.tail;
+ msgq->offset = nvkm_falcon_rd32(falcon, falcon->func->msgq.tail);
- if (hdr->size > MSG_BUF_SIZE) {
- nvkm_error(subdev, "message too big (%d bytes)\n", hdr->size);
- return -ENOSPC;
+ msg_queue_open(msgq);
+ ret = msg_queue_pop(msgq, data, size);
+ if (ret == 0 && hdr->size != size) {
+ FLCN_ERR(falcon, "unexpected init message size %d vs %d",
+ hdr->size, size);
+ ret = -EINVAL;
}
-
- nvkm_falcon_read_dmem(falcon, tail + HDR_SIZE, hdr->size - HDR_SIZE, 0,
- (hdr + 1));
-
- tail += ALIGN(hdr->size, QUEUE_ALIGNMENT);
- nvkm_falcon_wr32(falcon, tail_reg, tail);
-
- ret = priv->func->init_func->init_callback(priv, hdr);
- if (ret)
- return ret;
-
- return 0;
+ msg_queue_close(msgq, ret == 0);
+ return ret;
}
void
@@ -182,17 +169,9 @@ nvkm_msgqueue_process_msgs(struct nvkm_msgqueue *priv,
*/
u8 msg_buffer[MSG_BUF_SIZE];
struct nv_falcon_msg *hdr = (void *)msg_buffer;
- int ret;
- /* the first message we receive must be the init message */
- if ((!priv->init_msg_received)) {
- ret = msgqueue_handle_init_msg(priv);
- if (!ret)
- priv->init_msg_received = true;
- } else {
- while (msg_queue_read(queue, hdr) > 0)
- msgqueue_msg_handle(queue, hdr);
- }
+ while (msg_queue_read(queue, hdr) > 0)
+ msgqueue_msg_handle(queue, hdr);
}
void
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
index 9867a32da42a..46e88937c453 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
@@ -90,17 +90,6 @@ nvkm_msgqueue_recv(struct nvkm_msgqueue *queue)
queue->func->recv(queue);
}
-int
-nvkm_msgqueue_reinit(struct nvkm_msgqueue *queue)
-{
- /* firmware not set yet... */
- if (!queue)
- return 0;
-
- queue->init_msg_received = false;
- return 0;
-}
-
void
nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *func,
struct nvkm_falcon *falcon,
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
index bf714f391d42..1c4780a7856a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
@@ -52,31 +52,6 @@
*
*/
-/**
- * struct nvkm_msgqueue_hdr - header for all commands/messages
- * @unit_id: id of firmware using receiving the command/sending the message
- * @size: total size of command/message
- * @ctrl_flags: type of command/message
- * @seq_id: used to match a message from its corresponding command
- */
-struct nvkm_msgqueue_hdr {
- u8 unit_id;
- u8 size;
- u8 ctrl_flags;
- u8 seq_id;
-};
-
-/**
- * struct nvkm_msgqueue_msg - base message.
- *
- * This is just a header and a message (or command) type. Useful when
- * building command-specific structures.
- */
-struct nvkm_msgqueue_msg {
- struct nvkm_msgqueue_hdr hdr;
- u8 msg_type;
-};
-
struct nvkm_msgqueue;
/**
@@ -87,7 +62,6 @@ struct nvkm_msgqueue;
*/
struct nvkm_msgqueue_init_func {
void (*gen_cmdline)(struct nvkm_msgqueue *, void *);
- int (*init_callback)(struct nvkm_msgqueue *, struct nvkm_msgqueue_hdr *);
};
struct nvkm_msgqueue_func {
@@ -136,7 +110,6 @@ struct nvkm_msgqueue {
struct nvkm_falcon *falcon;
const struct nvkm_msgqueue_func *func;
u32 fw_version;
- bool init_msg_received;
};
void nvkm_msgqueue_ctor(const struct nvkm_msgqueue_func *, struct nvkm_falcon *,
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c
index 7e450a91c62e..f624f9cd9098 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0137c63d.c
@@ -25,11 +25,6 @@
#include <subdev/pmu.h>
#include <subdev/secboot.h>
-/* Queues identifiers */
-enum {
- MSGQUEUE_0137C63D_NUM_QUEUES = 5,
-};
-
struct msgqueue_0137c63d {
struct nvkm_msgqueue base;
};
@@ -52,12 +47,6 @@ msgqueue_0137c63d_process_msgs(struct nvkm_msgqueue *queue)
}
/* Init unit */
-#define MSGQUEUE_0137C63D_UNIT_INIT 0x07
-
-enum {
- INIT_MSG_INIT = 0x0,
-};
-
static void
init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf)
{
@@ -84,118 +73,11 @@ init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf)
args->secure_mode = 1;
}
-/* forward declaration */
-static int acr_init_wpr(struct nvkm_msgqueue *queue);
-
-static int
-init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr)
-{
- struct msgqueue_0137c63d *priv = msgqueue_0137c63d(_queue);
- struct {
- struct nvkm_msgqueue_msg base;
-
- u8 pad;
- u16 os_debug_entry_point;
-
- struct {
- u16 size;
- u16 offset;
- u8 index;
- u8 pad;
- } queue_info[MSGQUEUE_0137C63D_NUM_QUEUES];
-
- u16 sw_managed_area_offset;
- u16 sw_managed_area_size;
- } *init = (void *)hdr;
- const struct nvkm_subdev *subdev = _queue->falcon->owner;
- struct nvkm_pmu *pmu = subdev->device->pmu;
-
- if (init->base.hdr.unit_id != MSGQUEUE_0137C63D_UNIT_INIT) {
- nvkm_error(subdev, "expected message from init unit\n");
- return -EINVAL;
- }
-
- if (init->base.msg_type != INIT_MSG_INIT) {
- nvkm_error(subdev, "expected PMU init msg\n");
- return -EINVAL;
- }
-
- nvkm_falcon_cmdq_init(pmu->hpq, init->queue_info[0].index,
- init->queue_info[0].offset,
- init->queue_info[0].size);
- nvkm_falcon_cmdq_init(pmu->lpq, init->queue_info[1].index,
- init->queue_info[1].offset,
- init->queue_info[1].size);
- nvkm_falcon_msgq_init(pmu->msgq, init->queue_info[4].index,
- init->queue_info[4].offset,
- init->queue_info[4].size);
-
- /* Complete initialization by initializing WPR region */
- return acr_init_wpr(&priv->base);
-}
-
static const struct nvkm_msgqueue_init_func
msgqueue_0137c63d_init_func = {
.gen_cmdline = init_gen_cmdline,
- .init_callback = init_callback,
};
-
-
-/* ACR unit */
-#define MSGQUEUE_0137C63D_UNIT_ACR 0x0a
-
-enum {
- ACR_CMD_INIT_WPR_REGION = 0x00,
-};
-
-static int
-acr_init_wpr_callback(void *priv, struct nv_falcon_msg *hdr)
-{
- struct nvkm_pmu *pmu = priv;
- struct nvkm_subdev *subdev = &pmu->subdev;
- struct {
- struct nv_falcon_msg base;
- u8 msg_type;
- u32 error_code;
- } *msg = (void *)hdr;
-
- if (msg->error_code) {
- nvkm_error(subdev, "ACR WPR init failure: %d\n",
- msg->error_code);
- return -EINVAL;
- }
-
- nvkm_debug(subdev, "ACR WPR init complete\n");
- complete_all(&pmu->wpr_ready);
- return 0;
-}
-
-static int
-acr_init_wpr(struct nvkm_msgqueue *queue)
-{
- struct nvkm_pmu *pmu = queue->falcon->owner->device->pmu;
- /*
- * region_id: region ID in WPR region
- * wpr_offset: offset in WPR region
- */
- struct {
- struct nv_falcon_cmd hdr;
- u8 cmd_type;
- u32 region_id;
- u32 wpr_offset;
- } cmd;
- memset(&cmd, 0, sizeof(cmd));
-
- cmd.hdr.unit_id = MSGQUEUE_0137C63D_UNIT_ACR;
- cmd.hdr.size = sizeof(cmd);
- cmd.cmd_type = ACR_CMD_INIT_WPR_REGION;
- cmd.region_id = 0x01;
- cmd.wpr_offset = 0x00;
- return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.hdr, acr_init_wpr_callback,
- pmu, 0);
-}
-
static void
msgqueue_0137c63d_dtor(struct nvkm_msgqueue *queue)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c
index 51ae4a10b213..0dc243b0b774 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue_0148cdec.c
@@ -31,12 +31,6 @@
* message queue, and uses a different command line and init message.
*/
-enum {
- MSGQUEUE_0148CDEC_COMMAND_QUEUE = 0,
- MSGQUEUE_0148CDEC_MESSAGE_QUEUE = 1,
- MSGQUEUE_0148CDEC_NUM_QUEUES,
-};
-
struct msgqueue_0148cdec {
struct nvkm_msgqueue base;
};
@@ -50,13 +44,6 @@ msgqueue_0148cdec_process_msgs(struct nvkm_msgqueue *queue)
}
-/* Init unit */
-#define MSGQUEUE_0148CDEC_UNIT_INIT 0x01
-
-enum {
- INIT_MSG_INIT = 0x0,
-};
-
static void
init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf)
{
@@ -71,62 +58,9 @@ init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf)
args->secure_mode = false;
}
-static int
-init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr)
-{
- struct {
- struct nvkm_msgqueue_msg base;
-
- u8 num_queues;
- u16 os_debug_entry_point;
-
- struct {
- u32 offset;
- u16 size;
- u8 index;
- u8 id;
- } queue_info[MSGQUEUE_0148CDEC_NUM_QUEUES];
-
- u16 sw_managed_area_offset;
- u16 sw_managed_area_size;
- } *init = (void *)hdr;
- const struct nvkm_subdev *subdev = _queue->falcon->owner;
- struct nvkm_sec2 *sec2 = subdev->device->sec2;
- int i;
-
- if (init->base.hdr.unit_id != MSGQUEUE_0148CDEC_UNIT_INIT) {
- nvkm_error(subdev, "expected message from init unit\n");
- return -EINVAL;
- }
-
- if (init->base.msg_type != INIT_MSG_INIT) {
- nvkm_error(subdev, "expected SEC init msg\n");
- return -EINVAL;
- }
-
- for (i = 0; i < MSGQUEUE_0148CDEC_NUM_QUEUES; i++) {
- u8 id = init->queue_info[i].id;
-
- if (id == MSGQUEUE_0148CDEC_MESSAGE_QUEUE) {
- nvkm_falcon_msgq_init(sec2->msgq,
- init->queue_info[i].index,
- init->queue_info[i].offset,
- init->queue_info[i].size);
- } else {
- nvkm_falcon_cmdq_init(sec2->cmdq,
- init->queue_info[i].index,
- init->queue_info[i].offset,
- init->queue_info[i].size);
- }
- }
-
- return 0;
-}
-
static const struct nvkm_msgqueue_init_func
msgqueue_0148cdec_init_func = {
.gen_cmdline = init_gen_cmdline,
- .init_callback = init_callback,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
index bc0eb84c2c90..706bbb782844 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
@@ -91,6 +91,7 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
nvkm_falcon_cmdq_fini(pmu->lpq);
nvkm_falcon_cmdq_fini(pmu->hpq);
+ pmu->initmsg_received = false;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
index e803cc461227..0e550612acc6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
@@ -61,9 +61,80 @@ gm20b_pmu_acr = {
.bootstrap_falcon = gm20b_pmu_acr_bootstrap_falcon,
};
+static int
+gm20b_pmu_acr_init_wpr_callback(void *priv, struct nv_falcon_msg *hdr)
+{
+ struct nv_pmu_acr_init_wpr_region_msg *msg =
+ container_of(hdr, typeof(*msg), msg.hdr);
+ struct nvkm_pmu *pmu = priv;
+ struct nvkm_subdev *subdev = &pmu->subdev;
+
+ if (msg->error_code) {
+ nvkm_error(subdev, "ACR WPR init failure: %d\n",
+ msg->error_code);
+ return -EINVAL;
+ }
+
+ nvkm_debug(subdev, "ACR WPR init complete\n");
+ complete_all(&pmu->wpr_ready);
+ return 0;
+}
+
+static int
+gm20b_pmu_acr_init_wpr(struct nvkm_pmu *pmu)
+{
+ struct nv_pmu_acr_init_wpr_region_cmd cmd = {
+ .cmd.hdr.unit_id = NV_PMU_UNIT_ACR,
+ .cmd.hdr.size = sizeof(cmd),
+ .cmd.cmd_type = NV_PMU_ACR_CMD_INIT_WPR_REGION,
+ .region_id = 1,
+ .wpr_offset = 0,
+ };
+
+ return nvkm_falcon_cmdq_send(pmu->hpq, &cmd.cmd.hdr,
+ gm20b_pmu_acr_init_wpr_callback, pmu, 0);
+}
+
+int
+gm20b_pmu_initmsg(struct nvkm_pmu *pmu)
+{
+ struct nv_pmu_init_msg msg;
+ int ret;
+
+ ret = nvkm_falcon_msgq_recv_initmsg(pmu->msgq, &msg, sizeof(msg));
+ if (ret)
+ return ret;
+
+ if (msg.hdr.unit_id != NV_PMU_UNIT_INIT ||
+ msg.msg_type != NV_PMU_INIT_MSG_INIT)
+ return -EINVAL;
+
+ nvkm_falcon_cmdq_init(pmu->hpq, msg.queue_info[0].index,
+ msg.queue_info[0].offset,
+ msg.queue_info[0].size);
+ nvkm_falcon_cmdq_init(pmu->lpq, msg.queue_info[1].index,
+ msg.queue_info[1].offset,
+ msg.queue_info[1].size);
+ nvkm_falcon_msgq_init(pmu->msgq, msg.queue_info[4].index,
+ msg.queue_info[4].offset,
+ msg.queue_info[4].size);
+ return gm20b_pmu_acr_init_wpr(pmu);
+}
+
void
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);
+ return;
+ }
+
+ pmu->initmsg_received = true;
+ }
+
if (!pmu->queue) {
nvkm_warn(&pmu->subdev,
"recv function called while no firmware set!\n");
@@ -79,6 +150,7 @@ gm20b_pmu = {
.enabled = gf100_pmu_enabled,
.intr = gt215_pmu_intr,
.recv = gm20b_pmu_recv,
+ .initmsg = gm20b_pmu_initmsg,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
index b2baf9b636a3..0e0ebd6857da 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
@@ -68,6 +68,7 @@ gp10b_pmu = {
.enabled = gf100_pmu_enabled,
.intr = gt215_pmu_intr,
.recv = gm20b_pmu_recv,
+ .initmsg = gm20b_pmu_initmsg,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
index 0e7965028dcf..21ca224fc186 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
@@ -27,6 +27,7 @@ struct nvkm_pmu_func {
int (*send)(struct nvkm_pmu *, u32 reply[2], u32 process,
u32 message, u32 data0, u32 data1);
void (*recv)(struct nvkm_pmu *);
+ int (*initmsg)(struct nvkm_pmu *);
void (*pgob)(struct nvkm_pmu *, bool);
};
@@ -44,6 +45,7 @@ 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 *);
+int gm20b_pmu_initmsg(struct nvkm_pmu *);
struct nvkm_pmu_fwif {
int version;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c
index 39dda09fc344..7994ed1cdf97 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c
@@ -85,8 +85,6 @@ acr_ls_msgqueue_post_run(struct nvkm_msgqueue *queue,
memset(buf, 0, sizeof(buf));
nvkm_msgqueue_write_cmdline(queue, buf);
nvkm_falcon_load_dmem(falcon, buf, addr_args, sizeof(buf), 0);
- /* rearm the queue so it will wait for the init message */
- nvkm_msgqueue_reinit(queue);
/* Enable interrupts */
nvkm_falcon_wr32(falcon, 0x10, 0xff);