drm/nouveau/sec2: unload RTOS before tearing down WPR
Reset regs won't be available on Ampere while SEC2 RTOS is running, and we're apparently supposed to be doing this on earlier GPUs too. v2: - fixed some excessive indentation Signed-off-by: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com>
This commit is contained in:
parent
a9d90860c4
commit
3b330f0875
@ -10,6 +10,7 @@ struct nv_sec2_args {
|
||||
};
|
||||
|
||||
#define NV_SEC2_UNIT_INIT 0x01
|
||||
#define NV_SEC2_UNIT_UNLOAD 0x06
|
||||
#define NV_SEC2_UNIT_ACR 0x08
|
||||
|
||||
struct nv_sec2_init_msg {
|
||||
@ -57,4 +58,8 @@ struct nv_sec2_acr_bootstrap_falcon_msg {
|
||||
u32 error_code;
|
||||
u32 falcon_id;
|
||||
};
|
||||
|
||||
#define NV_SEC2_UNIT_V2_INIT 0x01
|
||||
#define NV_SEC2_UNIT_V2_UNLOAD 0x05
|
||||
#define NV_SEC2_UNIT_V2_ACR 0x07
|
||||
#endif
|
||||
|
@ -72,6 +72,7 @@ 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);
|
||||
bool nvkm_falcon_msgq_empty(struct nvkm_falcon_msgq *);
|
||||
int nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *, void *, u32 size);
|
||||
void nvkm_falcon_msgq_recv(struct nvkm_falcon_msgq *);
|
||||
#endif
|
||||
|
@ -10,12 +10,14 @@ struct nvkm_sec2 {
|
||||
struct nvkm_engine engine;
|
||||
struct nvkm_falcon falcon;
|
||||
|
||||
atomic_t running;
|
||||
atomic_t initmsg;
|
||||
|
||||
struct nvkm_falcon_qmgr *qmgr;
|
||||
struct nvkm_falcon_cmdq *cmdq;
|
||||
struct nvkm_falcon_msgq *msgq;
|
||||
|
||||
struct work_struct work;
|
||||
bool initmsg_received;
|
||||
};
|
||||
|
||||
int gp102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **);
|
||||
|
@ -109,7 +109,6 @@ struct nvkm_acr_lsf_func {
|
||||
u32 bld_size;
|
||||
void (*bld_write)(struct nvkm_acr *, u32 bld, struct nvkm_acr_lsfw *);
|
||||
void (*bld_patch)(struct nvkm_acr *, u32 bld, s64 adjust);
|
||||
int (*boot)(struct nvkm_falcon *);
|
||||
u64 bootstrap_falcons;
|
||||
int (*bootstrap_falcon)(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
|
||||
int (*bootstrap_multiple_falcons)(struct nvkm_falcon *, u32 mask);
|
||||
|
@ -22,25 +22,17 @@
|
||||
#include "priv.h"
|
||||
|
||||
#include <core/firmware.h>
|
||||
#include <subdev/top.h>
|
||||
#include <subdev/timer.h>
|
||||
|
||||
static void
|
||||
nvkm_sec2_recv(struct work_struct *work)
|
||||
#include <nvfw/sec2.h>
|
||||
|
||||
static int
|
||||
nvkm_sec2_finimsg(void *priv, struct nvfw_falcon_msg *hdr)
|
||||
{
|
||||
struct nvkm_sec2 *sec2 = container_of(work, typeof(*sec2), work);
|
||||
struct nvkm_sec2 *sec2 = priv;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
nvkm_falcon_msgq_recv(sec2->msgq);
|
||||
atomic_set(&sec2->running, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -54,14 +46,52 @@ static int
|
||||
nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend)
|
||||
{
|
||||
struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
|
||||
struct nvkm_subdev *subdev = &sec2->engine.subdev;
|
||||
struct nvkm_falcon *falcon = &sec2->falcon;
|
||||
struct nvkm_falcon_cmdq *cmdq = sec2->cmdq;
|
||||
struct nvfw_falcon_cmd cmd = {
|
||||
.unit_id = sec2->func->unit_unload,
|
||||
.size = sizeof(cmd),
|
||||
};
|
||||
int ret;
|
||||
|
||||
flush_work(&sec2->work);
|
||||
if (!subdev->use.enabled)
|
||||
return 0;
|
||||
|
||||
if (suspend) {
|
||||
nvkm_falcon_cmdq_fini(sec2->cmdq);
|
||||
sec2->initmsg_received = false;
|
||||
if (atomic_read(&sec2->initmsg) == 1) {
|
||||
ret = nvkm_falcon_cmdq_send(cmdq, &cmd, nvkm_sec2_finimsg, sec2,
|
||||
msecs_to_jiffies(1000));
|
||||
WARN_ON(ret);
|
||||
|
||||
nvkm_msec(subdev->device, 2000,
|
||||
if (nvkm_falcon_rd32(falcon, 0x100) & 0x00000010)
|
||||
break;
|
||||
);
|
||||
}
|
||||
|
||||
nvkm_falcon_cmdq_fini(cmdq);
|
||||
falcon->func->disable(falcon);
|
||||
nvkm_falcon_put(falcon, subdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvkm_sec2_init(struct nvkm_engine *engine)
|
||||
{
|
||||
struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
|
||||
struct nvkm_subdev *subdev = &sec2->engine.subdev;
|
||||
struct nvkm_falcon *falcon = &sec2->falcon;
|
||||
int ret;
|
||||
|
||||
ret = nvkm_falcon_get(falcon, subdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
nvkm_falcon_wr32(falcon, 0x014, 0xffffffff);
|
||||
atomic_set(&sec2->initmsg, 0);
|
||||
atomic_set(&sec2->running, 1);
|
||||
|
||||
nvkm_falcon_start(falcon);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -69,6 +99,7 @@ static void *
|
||||
nvkm_sec2_dtor(struct nvkm_engine *engine)
|
||||
{
|
||||
struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
|
||||
|
||||
nvkm_falcon_msgq_del(&sec2->msgq);
|
||||
nvkm_falcon_cmdq_del(&sec2->cmdq);
|
||||
nvkm_falcon_qmgr_del(&sec2->qmgr);
|
||||
@ -79,6 +110,7 @@ nvkm_sec2_dtor(struct nvkm_engine *engine)
|
||||
static const struct nvkm_engine_func
|
||||
nvkm_sec2 = {
|
||||
.dtor = nvkm_sec2_dtor,
|
||||
.init = nvkm_sec2_init,
|
||||
.fini = nvkm_sec2_fini,
|
||||
.intr = nvkm_sec2_intr,
|
||||
};
|
||||
@ -113,6 +145,5 @@ nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device,
|
||||
(ret = nvkm_falcon_msgq_new(sec2->qmgr, "msgq", &sec2->msgq)))
|
||||
return ret;
|
||||
|
||||
INIT_WORK(&sec2->work, nvkm_sec2_recv);
|
||||
return 0;
|
||||
};
|
||||
|
@ -74,16 +74,6 @@ gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
|
||||
msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
static int
|
||||
gp102_sec2_acr_boot(struct nvkm_falcon *falcon)
|
||||
{
|
||||
struct nv_sec2_args args = {};
|
||||
nvkm_falcon_load_dmem(falcon, &args,
|
||||
falcon->func->emem_addr, sizeof(args), 0);
|
||||
nvkm_falcon_start(falcon);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gp102_sec2_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
|
||||
{
|
||||
@ -122,7 +112,6 @@ gp102_sec2_acr_0 = {
|
||||
.bld_size = sizeof(struct loader_config_v1),
|
||||
.bld_write = gp102_sec2_acr_bld_write,
|
||||
.bld_patch = gp102_sec2_acr_bld_patch,
|
||||
.boot = gp102_sec2_acr_boot,
|
||||
.bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
|
||||
BIT_ULL(NVKM_ACR_LSF_GPCCS) |
|
||||
BIT_ULL(NVKM_ACR_LSF_SEC2),
|
||||
@ -169,11 +158,29 @@ gp102_sec2_intr(struct nvkm_sec2 *sec2)
|
||||
u32 intr = nvkm_falcon_rd32(falcon, 0x008) & disp & ~(disp >> 16);
|
||||
|
||||
if (intr & 0x00000040) {
|
||||
schedule_work(&sec2->work);
|
||||
if (unlikely(atomic_read(&sec2->initmsg) == 0)) {
|
||||
int ret = sec2->func->initmsg(sec2);
|
||||
|
||||
if (ret)
|
||||
nvkm_error(subdev, "error parsing init message: %d\n", ret);
|
||||
|
||||
atomic_set(&sec2->initmsg, ret ?: 1);
|
||||
}
|
||||
|
||||
if (atomic_read(&sec2->initmsg) > 0) {
|
||||
if (!nvkm_falcon_msgq_empty(sec2->msgq))
|
||||
nvkm_falcon_msgq_recv(sec2->msgq);
|
||||
}
|
||||
|
||||
nvkm_falcon_wr32(falcon, 0x004, 0x00000040);
|
||||
intr &= ~0x00000040;
|
||||
}
|
||||
|
||||
if (intr & 0x00000010) {
|
||||
nvkm_falcon_wr32(falcon, 0x004, 0x00000010);
|
||||
intr &= ~0x00000010;
|
||||
}
|
||||
|
||||
if (intr) {
|
||||
nvkm_error(subdev, "unhandled intr %08x\n", intr);
|
||||
nvkm_falcon_wr32(falcon, 0x004, intr);
|
||||
@ -250,6 +257,7 @@ gp102_sec2_flcn = {
|
||||
const struct nvkm_sec2_func
|
||||
gp102_sec2 = {
|
||||
.flcn = &gp102_sec2_flcn,
|
||||
.unit_unload = NV_SEC2_UNIT_UNLOAD,
|
||||
.unit_acr = NV_SEC2_UNIT_ACR,
|
||||
.intr = gp102_sec2_intr,
|
||||
.initmsg = gp102_sec2_initmsg,
|
||||
@ -304,7 +312,6 @@ gp102_sec2_acr_1 = {
|
||||
.bld_size = sizeof(struct flcn_bl_dmem_desc_v2),
|
||||
.bld_write = gp102_sec2_acr_bld_write_1,
|
||||
.bld_patch = gp102_sec2_acr_bld_patch_1,
|
||||
.boot = gp102_sec2_acr_boot,
|
||||
.bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
|
||||
BIT_ULL(NVKM_ACR_LSF_GPCCS) |
|
||||
BIT_ULL(NVKM_ACR_LSF_SEC2),
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
struct nvkm_sec2_func {
|
||||
const struct nvkm_falcon_func *flcn;
|
||||
u8 unit_unload;
|
||||
u8 unit_acr;
|
||||
void (*intr)(struct nvkm_sec2 *);
|
||||
int (*initmsg)(struct nvkm_sec2 *);
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "priv.h"
|
||||
#include <subdev/acr.h>
|
||||
|
||||
#include <nvfw/sec2.h>
|
||||
|
||||
static const struct nvkm_falcon_func
|
||||
tu102_sec2_flcn = {
|
||||
.debug = 0x408,
|
||||
@ -44,7 +46,8 @@ tu102_sec2_flcn = {
|
||||
static const struct nvkm_sec2_func
|
||||
tu102_sec2 = {
|
||||
.flcn = &tu102_sec2_flcn,
|
||||
.unit_acr = 0x07,
|
||||
.unit_unload = NV_SEC2_UNIT_V2_UNLOAD,
|
||||
.unit_acr = NV_SEC2_UNIT_V2_ACR,
|
||||
.intr = gp102_sec2_intr,
|
||||
.initmsg = gp102_sec2_initmsg,
|
||||
};
|
||||
|
@ -25,7 +25,7 @@
|
||||
static void
|
||||
nvkm_falcon_msgq_open(struct nvkm_falcon_msgq *msgq)
|
||||
{
|
||||
mutex_lock(&msgq->mutex);
|
||||
spin_lock(&msgq->lock);
|
||||
msgq->position = nvkm_falcon_rd32(msgq->qmgr->falcon, msgq->tail_reg);
|
||||
}
|
||||
|
||||
@ -37,10 +37,10 @@ nvkm_falcon_msgq_close(struct nvkm_falcon_msgq *msgq, bool commit)
|
||||
if (commit)
|
||||
nvkm_falcon_wr32(falcon, msgq->tail_reg, msgq->position);
|
||||
|
||||
mutex_unlock(&msgq->mutex);
|
||||
spin_unlock(&msgq->lock);
|
||||
}
|
||||
|
||||
static bool
|
||||
bool
|
||||
nvkm_falcon_msgq_empty(struct nvkm_falcon_msgq *msgq)
|
||||
{
|
||||
u32 head = nvkm_falcon_rd32(msgq->qmgr->falcon, msgq->head_reg);
|
||||
@ -208,6 +208,6 @@ nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *qmgr, const char *name,
|
||||
|
||||
msgq->qmgr = qmgr;
|
||||
msgq->name = name;
|
||||
mutex_init(&msgq->mutex);
|
||||
spin_lock_init(&msgq->lock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ struct nvkm_falcon_cmdq {
|
||||
struct nvkm_falcon_msgq {
|
||||
struct nvkm_falcon_qmgr *qmgr;
|
||||
const char *name;
|
||||
struct mutex mutex;
|
||||
spinlock_t lock;
|
||||
|
||||
u32 head_reg;
|
||||
u32 tail_reg;
|
||||
|
@ -97,7 +97,6 @@ nvkm_acr_load(struct nvkm_acr *acr)
|
||||
{
|
||||
struct nvkm_subdev *subdev = &acr->subdev;
|
||||
struct nvkm_acr_lsf *rtos = nvkm_acr_rtos(acr);
|
||||
struct nvkm_acr_lsf *lsf;
|
||||
u64 start, limit;
|
||||
int ret;
|
||||
|
||||
@ -129,14 +128,6 @@ nvkm_acr_load(struct nvkm_acr *acr)
|
||||
acr->rtos = rtos;
|
||||
}
|
||||
|
||||
list_for_each_entry(lsf, &acr->lsf, head) {
|
||||
if (lsf->func->boot) {
|
||||
ret = lsf->func->boot(lsf->falcon);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user