Skip to content

Commit

Permalink
drm/nouveau/acr: use common falcon HS FW code for ACR FWs
Browse files Browse the repository at this point in the history
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: Ben Skeggs <bskeggs@redhat.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
  • Loading branch information
Ben Skeggs committed Nov 9, 2022
1 parent e3f3249 commit 2541626
Show file tree
Hide file tree
Showing 30 changed files with 648 additions and 856 deletions.
21 changes: 14 additions & 7 deletions drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
enum nvkm_falcon_mem {
IMEM,
DMEM,
EMEM,
};

static inline const char *
Expand All @@ -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";
Expand All @@ -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,
Expand All @@ -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); \
Expand All @@ -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;
Expand All @@ -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 *,
Expand Down
8 changes: 8 additions & 0 deletions drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NVKM_FIRMWARE_H__
#define __NVKM_FIRMWARE_H__
#include <core/memory.h>
#include <core/option.h>
#include <core/subdev.h>

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;
struct nvkm_device *device;

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 *,
Expand Down
32 changes: 13 additions & 19 deletions drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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[];
};

Expand All @@ -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
3 changes: 2 additions & 1 deletion drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
87 changes: 86 additions & 1 deletion drivers/gpu/drm/nouveau/nvkm/core/firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -108,16 +111,81 @@ 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;

switch (fw->func->type) {
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;
Expand All @@ -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;
Expand All @@ -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;
}
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -2364,7 +2364,7 @@ nv13b_chipset = {
static const struct nvkm_device_chip
nv140_chipset = {
.name = "GV100",
.acr = { 0x00000001, gp108_acr_new },
.acr = { 0x00000001, gv100_acr_new },
.bar = { 0x00000001, gm107_bar_new },
.bios = { 0x00000001, nvkm_bios_new },
.bus = { 0x00000001, gf100_bus_new },
Expand Down
53 changes: 6 additions & 47 deletions drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,45 +190,6 @@ gp102_sec2_intr(struct nvkm_inth *inth)
return IRQ_HANDLED;
}

void
gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon,
struct nvkm_memory *ctx)
{
struct nvkm_device *device = falcon->owner->device;

nvkm_falcon_v1_bind_context(falcon, ctx);
if (!ctx)
return;

/* Not sure if this is a WAR for a HW issue, or some additional
* programming sequence that's needed to properly complete the
* context switch we trigger above.
*
* Fixes unreliability of booting the SEC2 RTOS on Quadro P620,
* particularly when resuming from suspend.
*
* Also removes the need for an odd workaround where we needed
* to program SEC2's FALCON_CPUCTL_ALIAS_STARTCPU twice before
* the SEC2 RTOS would begin executing.
*/
nvkm_msec(device, 10,
u32 irqstat = nvkm_falcon_rd32(falcon, 0x008);
u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc);
if ((irqstat & 0x00000008) &&
(flcn0dc & 0x00007000) == 0x00005000)
break;
);

nvkm_falcon_mask(falcon, 0x004, 0x00000008, 0x00000008);
nvkm_falcon_mask(falcon, 0x058, 0x00000002, 0x00000002);

nvkm_msec(device, 10,
u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc);
if ((flcn0dc & 0x00007000) == 0x00000000)
break;
);
}

static const struct nvkm_falcon_func
gp102_sec2_flcn = {
.disable = gm200_flcn_disable,
Expand All @@ -237,15 +198,13 @@ gp102_sec2_flcn = {
.reset_eng = gp102_flcn_reset_eng,
.reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.debug = 0x408,
.fbif = 0x600,
.load_imem = nvkm_falcon_v1_load_imem,
.load_dmem = nvkm_falcon_v1_load_dmem,
.read_dmem = nvkm_falcon_v1_read_dmem,
.bind_inst = gm200_flcn_bind_inst,
.bind_stat = gm200_flcn_bind_stat,
.bind_intr = true,
.imem_pio = &gm200_flcn_imem_pio,
.dmem_pio = &gm200_flcn_dmem_pio,
.emem_addr = 0x01000000,
.bind_context = gp102_sec2_flcn_bind_context,
.wait_for_halt = nvkm_falcon_v1_wait_for_halt,
.clear_interrupt = nvkm_falcon_v1_clear_interrupt,
.set_start_addr = nvkm_falcon_v1_set_start_addr,
.emem_pio = &gp102_flcn_emem_pio,
.start = nvkm_falcon_v1_start,
.cmdq = { 0xa00, 0xa04, 8 },
.msgq = { 0xa30, 0xa34, 8 },
Expand Down
Loading

0 comments on commit 2541626

Please sign in to comment.