Commit 2541626c authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/acr: use common falcon HS FW code for ACR FWs



Adds context binding and support for FWs with a bootloader to the code
that was added to load VPR scrubber HS binaries, and ports ACR over to
using all of it.

- gv100 split from gp108 to handle FW exit status differences

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Reviewed-by: default avatarLyude Paul <lyude@redhat.com>
parent e3f32495
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
enum nvkm_falcon_mem {
	IMEM,
	DMEM,
	EMEM,
};

static inline const char *
@@ -14,6 +15,7 @@ nvkm_falcon_mem(enum nvkm_falcon_mem mem)
	switch (mem) {
	case IMEM: return "imem";
	case DMEM: return "dmem";
	case EMEM: return "emem";
	default:
		WARN_ON(1);
		return "?mem";
@@ -25,6 +27,8 @@ struct nvkm_falcon_func_pio {
	int max;
	void (*wr_init)(struct nvkm_falcon *, u8 port, bool sec, u32 mem_base);
	void (*wr)(struct nvkm_falcon *, u8 port, const u8 *img, int len, u16 tag);
	void (*rd_init)(struct nvkm_falcon *, u8 port, u32 mem_base);
	void (*rd)(struct nvkm_falcon *, u8 port, const u8 *img, int len);
};

int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner,
@@ -33,27 +37,25 @@ void nvkm_falcon_dtor(struct nvkm_falcon *);
int nvkm_falcon_reset(struct nvkm_falcon *);
int nvkm_falcon_pio_wr(struct nvkm_falcon *, const u8 *img, u32 img_base, u8 port,
		       enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec);
int nvkm_falcon_pio_rd(struct nvkm_falcon *, u8 port, enum nvkm_falcon_mem type, u32 mem_base,
		       const u8 *img, u32 img_base, int len);

int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *);
int gm200_flcn_disable(struct nvkm_falcon *);
int gm200_flcn_enable(struct nvkm_falcon *);
void gm200_flcn_bind_inst(struct nvkm_falcon *, int, u64);
int gm200_flcn_bind_stat(struct nvkm_falcon *, bool);
extern const struct nvkm_falcon_func_pio gm200_flcn_imem_pio;
extern const struct nvkm_falcon_func_pio gm200_flcn_dmem_pio;

int gp102_flcn_reset_eng(struct nvkm_falcon *);
extern const struct nvkm_falcon_func_pio gp102_flcn_emem_pio;

void nvkm_falcon_v1_load_imem(struct nvkm_falcon *,
			      void *, u32, u32, u16, u8, bool);
void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8);
void nvkm_falcon_v1_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *);
void nvkm_falcon_v1_bind_context(struct nvkm_falcon *, struct nvkm_memory *);
int nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *, u32);
int nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *, u32);
void nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *, u32 start_addr);
void nvkm_falcon_v1_start(struct nvkm_falcon *);

void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *);

#define FLCN_PRINTK(f,l,p,fmt,a...) ({                                                          \
	if ((f)->owner->name != (f)->name)                                                      \
		nvkm_printk___((f)->owner, (f)->user, NV_DBG_##l, p, "%s:"fmt, (f)->name, ##a); \
@@ -70,7 +72,9 @@ struct nvkm_falcon_fw {
	const struct nvkm_falcon_fw_func {
		int (*signature)(struct nvkm_falcon_fw *, u32 *sig_base_src);
		int (*reset)(struct nvkm_falcon_fw *);
		int (*setup)(struct nvkm_falcon_fw *);
		int (*load)(struct nvkm_falcon_fw *);
		int (*load_bld)(struct nvkm_falcon_fw *);
		int (*boot)(struct nvkm_falcon_fw *,
			    u32 *mbox0, u32 *mbox1, u32 mbox0_ok, u32 irqsclr);
	} *func;
@@ -96,11 +100,14 @@ struct nvkm_falcon_fw {
	u32 dmem_size;
	u32 dmem_sign;

	u8 *boot;
	u32 boot_size;
	u32 boot_addr;

	struct nvkm_falcon *falcon;
	struct nvkm_memory *inst;
	struct nvkm_vmm *vmm;
	struct nvkm_vma *vma;
};

int nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *, const char *name, struct nvkm_device *,
+8 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: MIT */
#ifndef __NVKM_FIRMWARE_H__
#define __NVKM_FIRMWARE_H__
#include <core/memory.h>
#include <core/option.h>
#include <core/subdev.h>

@@ -8,6 +9,7 @@ struct nvkm_firmware {
	const struct nvkm_firmware_func {
		enum nvkm_firmware_type {
			NVKM_FIRMWARE_IMG_RAM,
			NVKM_FIRMWARE_IMG_DMA,
		} type;
	} *func;
	const char *name;
@@ -15,6 +17,12 @@ struct nvkm_firmware {

	int len;
	u8 *img;
	u64 phys;

	struct nvkm_firmware_mem {
		struct nvkm_memory memory;
		struct scatterlist sgl;
	} mem;
};

int nvkm_firmware_ctor(const struct nvkm_firmware_func *, const char *name, struct nvkm_device *,
+13 −19
Original line number Diff line number Diff line
@@ -64,9 +64,22 @@ struct nvkm_falcon_func {
	int (*reset_wait_mem_scrubbing)(struct nvkm_falcon *);

	u32 debug;
	void (*bind_inst)(struct nvkm_falcon *, int target, u64 addr);
	int (*bind_stat)(struct nvkm_falcon *, bool intr);
	bool bind_intr;

	const struct nvkm_falcon_func_pio *imem_pio;
	const struct nvkm_falcon_func_pio *dmem_pio;

	u32 emem_addr;
	const struct nvkm_falcon_func_pio *emem_pio;

	struct {
		u32 head;
		u32 tail;
		u32 stride;
	} cmdq, msgq;

	struct {
		u32 *data;
		u32  size;
@@ -78,24 +91,10 @@ struct nvkm_falcon_func {
	void (*init)(struct nvkm_falcon *);
	void (*intr)(struct nvkm_falcon *, struct nvkm_chan *);

	u32 fbif;

	void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool);
	void (*load_dmem)(struct nvkm_falcon *, void *, u32, u32, u8);
	void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *);
	u32 emem_addr;
	void (*bind_context)(struct nvkm_falcon *, struct nvkm_memory *);
	int (*wait_for_halt)(struct nvkm_falcon *, u32);
	int (*clear_interrupt)(struct nvkm_falcon *, u32);
	void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr);
	void (*start)(struct nvkm_falcon *);

	struct {
		u32 head;
		u32 tail;
		u32 stride;
	} cmdq, msgq;

	struct nvkm_sclass sclass[];
};

@@ -122,10 +121,5 @@ nvkm_falcon_mask(struct nvkm_falcon *falcon, u32 addr, u32 mask, u32 val)
void nvkm_falcon_load_imem(struct nvkm_falcon *, void *, u32, u32, u16, u8,
			   bool);
void nvkm_falcon_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8);
void nvkm_falcon_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *);
void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_memory *);
void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32);
void nvkm_falcon_start(struct nvkm_falcon *);
int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32);
int nvkm_falcon_clear_interrupt(struct nvkm_falcon *, u32);
#endif
+2 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ struct nvkm_acr {
	const struct nvkm_acr_func *func;
	struct nvkm_subdev subdev;

	struct list_head hsfw, hsf;
	struct list_head hsfw;
	struct list_head lsfw, lsf;

	u64 managed_falcons;
@@ -65,6 +65,7 @@ int gm20b_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
int gp102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
int gp108_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
int gp10b_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
int gv100_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
int tu102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);

struct nvkm_acr_lsfw {
+86 −1
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@
#include <core/device.h>
#include <core/firmware.h>

#include <subdev/fb.h>
#include <subdev/mmu.h>

int
nvkm_firmware_load_name(const struct nvkm_subdev *subdev, const char *base,
			const char *name, int ver, const struct firmware **pfw)
@@ -108,9 +111,70 @@ nvkm_firmware_put(const struct firmware *fw)
	release_firmware(fw);
}

#define nvkm_firmware_mem(p) container_of((p), struct nvkm_firmware, mem.memory)

static int
nvkm_firmware_mem_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
		      struct nvkm_vma *vma, void *argv, u32 argc)
{
	struct nvkm_firmware *fw = nvkm_firmware_mem(memory);
	struct nvkm_vmm_map map = {
		.memory = &fw->mem.memory,
		.offset = offset,
		.sgl = &fw->mem.sgl,
	};

	if (WARN_ON(fw->func->type != NVKM_FIRMWARE_IMG_DMA))
		return -ENOSYS;

	return nvkm_vmm_map(vmm, vma, argv, argc, &map);
}

static u64
nvkm_firmware_mem_size(struct nvkm_memory *memory)
{
	return sg_dma_len(&nvkm_firmware_mem(memory)->mem.sgl);
}

static u64
nvkm_firmware_mem_addr(struct nvkm_memory *memory)
{
	return nvkm_firmware_mem(memory)->phys;
}

static u8
nvkm_firmware_mem_page(struct nvkm_memory *memory)
{
	return PAGE_SHIFT;
}

static enum nvkm_memory_target
nvkm_firmware_mem_target(struct nvkm_memory *memory)
{
	return NVKM_MEM_TARGET_HOST;
}

static void *
nvkm_firmware_mem_dtor(struct nvkm_memory *memory)
{
	return NULL;
}

static const struct nvkm_memory_func
nvkm_firmware_mem = {
	.dtor = nvkm_firmware_mem_dtor,
	.target = nvkm_firmware_mem_target,
	.page = nvkm_firmware_mem_page,
	.addr = nvkm_firmware_mem_addr,
	.size = nvkm_firmware_mem_size,
	.map = nvkm_firmware_mem_map,
};

void
nvkm_firmware_dtor(struct nvkm_firmware *fw)
{
	struct nvkm_memory *memory = &fw->mem.memory;

	if (!fw->img)
		return;

@@ -118,6 +182,10 @@ nvkm_firmware_dtor(struct nvkm_firmware *fw)
	case NVKM_FIRMWARE_IMG_RAM:
		kfree(fw->img);
		break;
	case NVKM_FIRMWARE_IMG_DMA:
		nvkm_memory_unref(&memory);
		dma_free_coherent(fw->device->dev, sg_dma_len(&fw->mem.sgl), fw->img, fw->phys);
		break;
	default:
		WARN_ON(1);
		break;
@@ -133,12 +201,28 @@ nvkm_firmware_ctor(const struct nvkm_firmware_func *func, const char *name,
	fw->func = func;
	fw->name = name;
	fw->device = device;
	fw->len = len;

	switch (fw->func->type) {
	case NVKM_FIRMWARE_IMG_RAM:
		fw->len = len;
		fw->img = kmemdup(src, fw->len, GFP_KERNEL);
		break;
	case NVKM_FIRMWARE_IMG_DMA: {
		dma_addr_t addr;

		len = ALIGN(fw->len, PAGE_SIZE);

		fw->img = dma_alloc_coherent(fw->device->dev, len, &addr, GFP_KERNEL);
		if (fw->img) {
			memcpy(fw->img, src, fw->len);
			fw->phys = addr;
		}

		sg_init_one(&fw->mem.sgl, fw->img, len);
		sg_dma_address(&fw->mem.sgl) = fw->phys;
		sg_dma_len(&fw->mem.sgl) = len;
	}
		break;
	default:
		WARN_ON(1);
		return -EINVAL;
@@ -147,5 +231,6 @@ nvkm_firmware_ctor(const struct nvkm_firmware_func *func, const char *name,
	if (!fw->img)
		return -ENOMEM;

	nvkm_memory_ctor(&nvkm_firmware_mem, &fw->mem.memory);
	return 0;
}
Loading