Skip to content

Commit

Permalink
drm/nouveau/flcn/msgq: move handling of init message to subdevs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ben Skeggs committed Jan 15, 2020
1 parent 2d06398 commit d114a13
Show file tree
Hide file tree
Showing 19 changed files with 202 additions and 265 deletions.
31 changes: 31 additions & 0 deletions drivers/gpu/drm/nouveau/include/nvfw/pmu.h
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
22 changes: 22 additions & 0 deletions drivers/gpu/drm/nouveau/include/nvfw/sec2.h
Original file line number Diff line number Diff line change
@@ -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
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 0 additions & 1 deletion drivers/gpu/drm/nouveau/include/nvkm/core/msgqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 **);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/include/nvkm/subdev/pmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
19 changes: 18 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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;
}

Expand Down
32 changes: 32 additions & 0 deletions drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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");
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);
Expand Down
57 changes: 18 additions & 39 deletions drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
11 changes: 0 additions & 11 deletions drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
27 changes: 0 additions & 27 deletions drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand All @@ -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 {
Expand Down Expand Up @@ -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 *,
Expand Down
Loading

0 comments on commit d114a13

Please sign in to comment.