diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/engine')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h | 1 |
3 files changed, 51 insertions, 1 deletions
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 *); |