drm/nouveau/gsp: move booter handling to GPU-specific code

GH100/GBxxx have significant changes to the GSP-RM boot process.

Signed-off-by: Ben Skeggs <bskeggs@nvidia.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Timur Tabi <ttabi@nvidia.com>
Tested-by: Timur Tabi <ttabi@nvidia.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Ben Skeggs
2025-01-22 21:21:03 +10:00
committed by Dave Airlie
parent 7f022236b5
commit 594766ca3e
8 changed files with 125 additions and 103 deletions

View File

@@ -36,8 +36,8 @@ ad102_gsp_r535_113_01 = {
.dtor = r535_gsp_dtor,
.oneinit = tu102_gsp_oneinit,
.init = r535_gsp_init,
.fini = r535_gsp_fini,
.init = tu102_gsp_init,
.fini = tu102_gsp_fini,
.reset = ga102_gsp_reset,
.rm = &r535_gsp_rm,

View File

@@ -52,7 +52,7 @@ nvkm_gsp_fini(struct nvkm_subdev *subdev, bool suspend)
{
struct nvkm_gsp *gsp = nvkm_gsp(subdev);
if (!gsp->func->fini)
if (!gsp->func->fini || !gsp->running)
return 0;
return gsp->func->fini(gsp, suspend);

View File

@@ -52,8 +52,8 @@ ga100_gsp_r535_113_01 = {
.dtor = r535_gsp_dtor,
.oneinit = tu102_gsp_oneinit,
.init = r535_gsp_init,
.fini = r535_gsp_fini,
.init = tu102_gsp_init,
.fini = tu102_gsp_fini,
.reset = tu102_gsp_reset,
.rm = &r535_gsp_rm,

View File

@@ -164,8 +164,8 @@ ga102_gsp_r535_113_01 = {
.dtor = r535_gsp_dtor,
.oneinit = tu102_gsp_oneinit,
.init = r535_gsp_init,
.fini = r535_gsp_fini,
.init = tu102_gsp_init,
.fini = tu102_gsp_fini,
.reset = ga102_gsp_reset,
.rm = &r535_gsp_rm,

View File

@@ -59,6 +59,8 @@ extern const struct nvkm_falcon_fw_func tu102_gsp_fwsec;
int tu102_gsp_booter_ctor(struct nvkm_gsp *, const char *, const struct firmware *,
struct nvkm_falcon *, struct nvkm_falcon_fw *);
int tu102_gsp_oneinit(struct nvkm_gsp *);
int tu102_gsp_init(struct nvkm_gsp *);
int tu102_gsp_fini(struct nvkm_gsp *, bool suspend);
int tu102_gsp_reset(struct nvkm_gsp *);
extern const struct nvkm_falcon_func ga102_gsp_flcn;
@@ -72,6 +74,7 @@ int r535_gsp_oneinit(struct nvkm_gsp *);
int r535_gsp_init(struct nvkm_gsp *);
int r535_gsp_fini(struct nvkm_gsp *, bool suspend);
extern const struct nvkm_gsp_rm r535_gsp_rm;
int r535_gsp_rmargs_init(struct nvkm_gsp *gsp, bool resume);
int nvkm_gsp_new_(const struct nvkm_gsp_fwif *, struct nvkm_device *, enum nvkm_subdev_type, int,
struct nvkm_gsp **);

View File

@@ -1145,48 +1145,6 @@ r535_gsp_msg_run_cpu_sequencer(void *priv, u32 fn, void *repv, u32 repc)
return 0;
}
static int
r535_gsp_booter_unload(struct nvkm_gsp *gsp, u32 mbox0, u32 mbox1)
{
struct nvkm_subdev *subdev = &gsp->subdev;
struct nvkm_device *device = subdev->device;
u32 wpr2_hi;
int ret;
wpr2_hi = nvkm_rd32(device, 0x1fa828);
if (!wpr2_hi) {
nvkm_debug(subdev, "WPR2 not set - skipping booter unload\n");
return 0;
}
ret = nvkm_falcon_fw_boot(&gsp->booter.unload, &gsp->subdev, true, &mbox0, &mbox1, 0, 0);
if (WARN_ON(ret))
return ret;
wpr2_hi = nvkm_rd32(device, 0x1fa828);
if (WARN_ON(wpr2_hi))
return -EIO;
return 0;
}
static int
r535_gsp_booter_load(struct nvkm_gsp *gsp, u32 mbox0, u32 mbox1)
{
int ret;
ret = nvkm_falcon_fw_boot(&gsp->booter.load, &gsp->subdev, true, &mbox0, &mbox1, 0, 0);
if (ret)
return ret;
nvkm_falcon_wr32(&gsp->falcon, 0x080, gsp->boot.app_version);
if (WARN_ON(!nvkm_falcon_riscv_active(&gsp->falcon)))
return -EIO;
return 0;
}
static int
r535_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
{
@@ -1287,7 +1245,7 @@ r535_gsp_shared_init(struct nvkm_gsp *gsp)
return 0;
}
static int
int
r535_gsp_rmargs_init(struct nvkm_gsp *gsp, bool resume)
{
GSP_ARGUMENTS_CACHED *args;
@@ -1816,12 +1774,8 @@ nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size,
int
r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
{
u32 mbox0 = 0xff, mbox1 = 0xff;
int ret;
if (!gsp->running)
return 0;
if (suspend) {
GspFwWprMeta *meta = gsp->wpr_meta.data;
u64 len = meta->gspFwWprEnd - meta->gspFwWprStart;
@@ -1844,9 +1798,6 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
sr->revision = GSP_FW_SR_META_REVISION;
sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.lvl0.addr;
sr->sizeOfSuspendResumeData = len;
mbox0 = lower_32_bits(gsp->sr.meta.addr);
mbox1 = upper_32_bits(gsp->sr.meta.addr);
}
ret = r535_gsp_rpc_unloading_guest_driver(gsp, suspend);
@@ -1858,14 +1809,6 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
break;
);
nvkm_falcon_reset(&gsp->falcon);
ret = nvkm_gsp_fwsec_sb(gsp);
WARN_ON(ret);
ret = r535_gsp_booter_unload(gsp, mbox0, mbox1);
WARN_ON(ret);
gsp->running = false;
return 0;
}
@@ -1873,23 +1816,12 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
int
r535_gsp_init(struct nvkm_gsp *gsp)
{
u32 mbox0, mbox1;
int ret;
if (!gsp->sr.meta.data) {
mbox0 = lower_32_bits(gsp->wpr_meta.addr);
mbox1 = upper_32_bits(gsp->wpr_meta.addr);
} else {
r535_gsp_rmargs_init(gsp, true);
nvkm_falcon_wr32(&gsp->falcon, 0x080, gsp->boot.app_version);
mbox0 = lower_32_bits(gsp->sr.meta.addr);
mbox1 = upper_32_bits(gsp->sr.meta.addr);
}
/* Execute booter to handle (eventually...) booting GSP-RM. */
ret = r535_gsp_booter_load(gsp, mbox0, mbox1);
if (WARN_ON(ret))
goto done;
if (WARN_ON(!nvkm_falcon_riscv_active(&gsp->falcon)))
return -EIO;
ret = r535_gsp_rpc_poll(gsp, NV_VGPU_MSG_EVENT_GSP_INIT_DONE);
if (ret)
@@ -2220,16 +2152,6 @@ r535_gsp_oneinit(struct nvkm_gsp *gsp)
mutex_init(&gsp->cmdq.mutex);
mutex_init(&gsp->msgq.mutex);
ret = gsp->func->booter.ctor(gsp, "booter-load", gsp->fws.booter.load,
&device->sec2->falcon, &gsp->booter.load);
if (ret)
return ret;
ret = gsp->func->booter.ctor(gsp, "booter-unload", gsp->fws.booter.unload,
&device->sec2->falcon, &gsp->booter.unload);
if (ret)
return ret;
/* Load GSP firmware from ELF image into DMA-accessible memory. */
ret = r535_gsp_elf_section(gsp, ".fwimage", &data, &size);
if (ret)
@@ -2324,14 +2246,6 @@ r535_gsp_oneinit(struct nvkm_gsp *gsp)
if (WARN_ON(ret))
return ret;
/* Reset GSP into RISC-V mode. */
ret = gsp->func->reset(gsp);
if (WARN_ON(ret))
return ret;
nvkm_falcon_wr32(&gsp->falcon, 0x040, lower_32_bits(gsp->libos.addr));
nvkm_falcon_wr32(&gsp->falcon, 0x044, upper_32_bits(gsp->libos.addr));
mutex_init(&gsp->client_id.mutex);
idr_init(&gsp->client_id.idr);
return 0;

View File

@@ -22,11 +22,43 @@
#include "priv.h"
#include <subdev/fb.h>
#include <engine/sec2.h>
#include <nvfw/flcn.h>
#include <nvfw/fw.h>
#include <nvfw/hs.h>
static int
tu102_gsp_booter_unload(struct nvkm_gsp *gsp, u32 mbox0, u32 mbox1)
{
struct nvkm_subdev *subdev = &gsp->subdev;
struct nvkm_device *device = subdev->device;
u32 wpr2_hi;
int ret;
wpr2_hi = nvkm_rd32(device, 0x1fa828);
if (!wpr2_hi) {
nvkm_debug(subdev, "WPR2 not set - skipping booter unload\n");
return 0;
}
ret = nvkm_falcon_fw_boot(&gsp->booter.unload, &gsp->subdev, true, &mbox0, &mbox1, 0, 0);
if (WARN_ON(ret))
return ret;
wpr2_hi = nvkm_rd32(device, 0x1fa828);
if (WARN_ON(wpr2_hi))
return -EIO;
return 0;
}
static int
tu102_gsp_booter_load(struct nvkm_gsp *gsp, u32 mbox0, u32 mbox1)
{
return nvkm_falcon_fw_boot(&gsp->booter.load, &gsp->subdev, true, &mbox0, &mbox1, 0, 0);
}
int
tu102_gsp_booter_ctor(struct nvkm_gsp *gsp, const char *name, const struct firmware *blob,
struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw)
@@ -114,6 +146,55 @@ tu102_gsp_reset(struct nvkm_gsp *gsp)
return gsp->falcon.func->reset_eng(&gsp->falcon);
}
int
tu102_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
{
u32 mbox0 = 0xff, mbox1 = 0xff;
int ret;
ret = r535_gsp_fini(gsp, suspend);
if (ret && suspend)
return ret;
nvkm_falcon_reset(&gsp->falcon);
ret = nvkm_gsp_fwsec_sb(gsp);
WARN_ON(ret);
if (suspend) {
mbox0 = lower_32_bits(gsp->sr.meta.addr);
mbox1 = upper_32_bits(gsp->sr.meta.addr);
}
ret = tu102_gsp_booter_unload(gsp, mbox0, mbox1);
WARN_ON(ret);
return 0;
}
int
tu102_gsp_init(struct nvkm_gsp *gsp)
{
u32 mbox0, mbox1;
int ret;
if (!gsp->sr.meta.data) {
mbox0 = lower_32_bits(gsp->wpr_meta.addr);
mbox1 = upper_32_bits(gsp->wpr_meta.addr);
} else {
r535_gsp_rmargs_init(gsp, true);
mbox0 = lower_32_bits(gsp->sr.meta.addr);
mbox1 = upper_32_bits(gsp->sr.meta.addr);
}
/* Execute booter to handle (eventually...) booting GSP-RM. */
ret = tu102_gsp_booter_load(gsp, mbox0, mbox1);
if (WARN_ON(ret))
return ret;
return r535_gsp_init(gsp);
}
static u64
tu102_gsp_vga_workspace_addr(struct nvkm_gsp *gsp, u64 fb_size)
{
@@ -136,14 +217,38 @@ tu102_gsp_vga_workspace_addr(struct nvkm_gsp *gsp, u64 fb_size)
int
tu102_gsp_oneinit(struct nvkm_gsp *gsp)
{
gsp->fb.size = nvkm_fb_vidmem_size(gsp->subdev.device);
struct nvkm_device *device = gsp->subdev.device;
int ret;
gsp->fb.size = nvkm_fb_vidmem_size(device);
gsp->fb.bios.vga_workspace.addr = tu102_gsp_vga_workspace_addr(gsp, gsp->fb.size);
gsp->fb.bios.vga_workspace.size = gsp->fb.size - gsp->fb.bios.vga_workspace.addr;
gsp->fb.bios.addr = gsp->fb.bios.vga_workspace.addr;
gsp->fb.bios.size = gsp->fb.bios.vga_workspace.size;
return r535_gsp_oneinit(gsp);
ret = gsp->func->booter.ctor(gsp, "booter-load", gsp->fws.booter.load,
&device->sec2->falcon, &gsp->booter.load);
if (ret)
return ret;
ret = gsp->func->booter.ctor(gsp, "booter-unload", gsp->fws.booter.unload,
&device->sec2->falcon, &gsp->booter.unload);
if (ret)
return ret;
ret = r535_gsp_oneinit(gsp);
if (ret)
return ret;
/* Reset GSP into RISC-V mode. */
ret = gsp->func->reset(gsp);
if (ret)
return ret;
nvkm_falcon_wr32(&gsp->falcon, 0x040, lower_32_bits(gsp->libos.addr));
nvkm_falcon_wr32(&gsp->falcon, 0x044, upper_32_bits(gsp->libos.addr));
return 0;
}
const struct nvkm_falcon_func
@@ -176,8 +281,8 @@ tu102_gsp_r535_113_01 = {
.dtor = r535_gsp_dtor,
.oneinit = tu102_gsp_oneinit,
.init = r535_gsp_init,
.fini = r535_gsp_fini,
.init = tu102_gsp_init,
.fini = tu102_gsp_fini,
.reset = tu102_gsp_reset,
.rm = &r535_gsp_rm,

View File

@@ -35,8 +35,8 @@ tu116_gsp_r535_113_01 = {
.dtor = r535_gsp_dtor,
.oneinit = tu102_gsp_oneinit,
.init = r535_gsp_init,
.fini = r535_gsp_fini,
.init = tu102_gsp_init,
.fini = tu102_gsp_fini,
.reset = tu102_gsp_reset,
.rm = &r535_gsp_rm,