Commit 1b9b4f92 authored by Ben Skeggs's avatar Ben Skeggs Committed by Karol Herbst

drm/nouveau/fb/gp102-: cache scrubber binary on first load

During system shutdown nouveau might not be able to request firmware from
Userspace, which then leads to a regression preventing the system from
shutting down.

Cache the scrubber binary for this case.

Fixes: 0e44c217 ("drm/nouveau/flcn: new code to load+boot simple HS FWs (VPR scrubber)")
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Signed-off-by: default avatarKarol Herbst <kherbst@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CACAvsv7Uf5=K44y8YLsiy0aMnc1zvGEQdeDe7RQF=AV+fxxzuQ@mail.gmail.com
parent 3638a820
......@@ -2,6 +2,7 @@
#ifndef __NVKM_FB_H__
#define __NVKM_FB_H__
#include <core/subdev.h>
#include <core/falcon.h>
#include <core/mm.h>
/* memory type/access flags, do not match hardware values */
......@@ -33,7 +34,7 @@ struct nvkm_fb {
const struct nvkm_fb_func *func;
struct nvkm_subdev subdev;
struct nvkm_blob vpr_scrubber;
struct nvkm_falcon_fw vpr_scrubber;
struct {
struct page *flush_page;
......
......@@ -143,6 +143,10 @@ nvkm_fb_mem_unlock(struct nvkm_fb *fb)
if (!fb->func->vpr.scrub_required)
return 0;
ret = nvkm_subdev_oneinit(subdev);
if (ret)
return ret;
if (!fb->func->vpr.scrub_required(fb)) {
nvkm_debug(subdev, "VPR not locked\n");
return 0;
......@@ -150,7 +154,7 @@ nvkm_fb_mem_unlock(struct nvkm_fb *fb)
nvkm_debug(subdev, "VPR locked, running scrubber binary\n");
if (!fb->vpr_scrubber.size) {
if (!fb->vpr_scrubber.fw.img) {
nvkm_warn(subdev, "VPR locked, but no scrubber binary!\n");
return 0;
}
......@@ -229,7 +233,7 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev)
nvkm_ram_del(&fb->ram);
nvkm_blob_dtor(&fb->vpr_scrubber);
nvkm_falcon_fw_dtor(&fb->vpr_scrubber);
if (fb->sysmem.flush_page) {
dma_unmap_page(subdev->device->dev, fb->sysmem.flush_page_addr,
......
......@@ -37,5 +37,5 @@ ga100_fb = {
int
ga100_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)
{
return gp102_fb_new_(&ga100_fb, device, type, inst, pfb);
return gf100_fb_new_(&ga100_fb, device, type, inst, pfb);
}
......@@ -25,25 +25,20 @@
#include <engine/nvdec.h>
static int
ga102_fb_vpr_scrub(struct nvkm_fb *fb)
ga102_fb_oneinit(struct nvkm_fb *fb)
{
struct nvkm_falcon_fw fw = {};
int ret;
struct nvkm_subdev *subdev = &fb->subdev;
ret = nvkm_falcon_fw_ctor_hs_v2(&ga102_flcn_fw, "mem-unlock", &fb->subdev, "nvdec/scrubber",
0, &fb->subdev.device->nvdec[0]->falcon, &fw);
if (ret)
return ret;
nvkm_falcon_fw_ctor_hs_v2(&ga102_flcn_fw, "mem-unlock", subdev, "nvdec/scrubber",
0, &subdev->device->nvdec[0]->falcon, &fb->vpr_scrubber);
ret = nvkm_falcon_fw_boot(&fw, &fb->subdev, true, NULL, NULL, 0, 0);
nvkm_falcon_fw_dtor(&fw);
return ret;
return gf100_fb_oneinit(fb);
}
static const struct nvkm_fb_func
ga102_fb = {
.dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
.oneinit = ga102_fb_oneinit,
.init = gm200_fb_init,
.init_page = gv100_fb_init_page,
.init_unkn = gp100_fb_init_unkn,
......@@ -51,13 +46,13 @@ ga102_fb = {
.ram_new = ga102_ram_new,
.default_bigpage = 16,
.vpr.scrub_required = tu102_fb_vpr_scrub_required,
.vpr.scrub = ga102_fb_vpr_scrub,
.vpr.scrub = gp102_fb_vpr_scrub,
};
int
ga102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)
{
return gp102_fb_new_(&ga102_fb, device, type, inst, pfb);
return gf100_fb_new_(&ga102_fb, device, type, inst, pfb);
}
MODULE_FIRMWARE("nvidia/ga102/nvdec/scrubber.bin");
......
......@@ -29,18 +29,7 @@
int
gp102_fb_vpr_scrub(struct nvkm_fb *fb)
{
struct nvkm_subdev *subdev = &fb->subdev;
struct nvkm_falcon_fw fw = {};
int ret;
ret = nvkm_falcon_fw_ctor_hs(&gm200_flcn_fw, "mem-unlock", subdev, NULL,
"nvdec/scrubber", 0, &subdev->device->nvdec[0]->falcon, &fw);
if (ret)
return ret;
ret = nvkm_falcon_fw_boot(&fw, subdev, true, NULL, NULL, 0, 0x00000000);
nvkm_falcon_fw_dtor(&fw);
return ret;
return nvkm_falcon_fw_boot(&fb->vpr_scrubber, &fb->subdev, true, NULL, NULL, 0, 0x00000000);
}
bool
......@@ -51,10 +40,21 @@ gp102_fb_vpr_scrub_required(struct nvkm_fb *fb)
return (nvkm_rd32(device, 0x100cd0) & 0x00000010) != 0;
}
int
gp102_fb_oneinit(struct nvkm_fb *fb)
{
struct nvkm_subdev *subdev = &fb->subdev;
nvkm_falcon_fw_ctor_hs(&gm200_flcn_fw, "mem-unlock", subdev, NULL, "nvdec/scrubber",
0, &subdev->device->nvdec[0]->falcon, &fb->vpr_scrubber);
return gf100_fb_oneinit(fb);
}
static const struct nvkm_fb_func
gp102_fb = {
.dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
.oneinit = gp102_fb_oneinit,
.init = gm200_fb_init,
.init_remapper = gp100_fb_init_remapper,
.init_page = gm200_fb_init_page,
......@@ -64,23 +64,10 @@ gp102_fb = {
.ram_new = gp100_ram_new,
};
int
gp102_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)
{
int ret = gf100_fb_new_(func, device, type, inst, pfb);
if (ret)
return ret;
nvkm_firmware_load_blob(&(*pfb)->subdev, "nvdec/scrubber", "", 0,
&(*pfb)->vpr_scrubber);
return 0;
}
int
gp102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)
{
return gp102_fb_new_(&gp102_fb, device, type, inst, pfb);
return gf100_fb_new_(&gp102_fb, device, type, inst, pfb);
}
MODULE_FIRMWARE("nvidia/gp102/nvdec/scrubber.bin");
......
......@@ -31,7 +31,7 @@ gv100_fb_init_page(struct nvkm_fb *fb)
static const struct nvkm_fb_func
gv100_fb = {
.dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
.oneinit = gp102_fb_oneinit,
.init = gm200_fb_init,
.init_page = gv100_fb_init_page,
.init_unkn = gp100_fb_init_unkn,
......@@ -45,7 +45,7 @@ gv100_fb = {
int
gv100_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)
{
return gp102_fb_new_(&gv100_fb, device, type, inst, pfb);
return gf100_fb_new_(&gv100_fb, device, type, inst, pfb);
}
MODULE_FIRMWARE("nvidia/gv100/nvdec/scrubber.bin");
......@@ -83,8 +83,7 @@ int gm200_fb_init_page(struct nvkm_fb *);
void gp100_fb_init_remapper(struct nvkm_fb *);
void gp100_fb_init_unkn(struct nvkm_fb *);
int gp102_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
struct nvkm_fb **);
int gp102_fb_oneinit(struct nvkm_fb *);
bool gp102_fb_vpr_scrub_required(struct nvkm_fb *);
int gp102_fb_vpr_scrub(struct nvkm_fb *);
......
......@@ -31,7 +31,7 @@ tu102_fb_vpr_scrub_required(struct nvkm_fb *fb)
static const struct nvkm_fb_func
tu102_fb = {
.dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
.oneinit = gp102_fb_oneinit,
.init = gm200_fb_init,
.init_page = gv100_fb_init_page,
.init_unkn = gp100_fb_init_unkn,
......@@ -45,7 +45,7 @@ tu102_fb = {
int
tu102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)
{
return gp102_fb_new_(&tu102_fb, device, type, inst, pfb);
return gf100_fb_new_(&tu102_fb, device, type, inst, pfb);
}
MODULE_FIRMWARE("nvidia/tu102/nvdec/scrubber.bin");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment