Commit 3b330f08 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

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: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent a9d90860
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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
+3 −1
Original line number Diff line number Diff line
@@ -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 **);
+0 −1
Original line number Diff line number Diff line
@@ -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);
+52 −21
Original line number Diff line number Diff line
@@ -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)
{
	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;
		}
#include <nvfw/sec2.h>

		sec2->initmsg_received = true;
	}
static int
nvkm_sec2_finimsg(void *priv, struct nvfw_falcon_msg *hdr)
{
	struct nvkm_sec2 *sec2 = priv;

	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;

	if (!subdev->use.enabled)
		return 0;

	if (atomic_read(&sec2->initmsg) == 1) {
		ret = nvkm_falcon_cmdq_send(cmdq, &cmd, nvkm_sec2_finimsg, sec2,
					    msecs_to_jiffies(1000));
		WARN_ON(ret);

	flush_work(&sec2->work);
		nvkm_msec(subdev->device, 2000,
			if (nvkm_falcon_rd32(falcon, 0x100) & 0x00000010)
				break;
		);
	}

	if (suspend) {
		nvkm_falcon_cmdq_fini(sec2->cmdq);
		sec2->initmsg_received = false;
	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;
};
Loading