mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
drm/nouveau/gsp: add hals for fbsr.suspend/resume()
555.42.02 has incompatible changes to FBSR. At the same time, move the calling of FBSR functions from the instmem subdev's suspend/resume paths, to GSP's. This is needed to fix ordering issues that arise from changes to FBSR in newer RM versions. 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:
parent
207c445b31
commit
c21b039715
7 changed files with 38 additions and 23 deletions
|
@ -133,6 +133,7 @@ struct nvkm_gsp {
|
||||||
struct sg_table sgt;
|
struct sg_table sgt;
|
||||||
struct nvkm_gsp_radix3 radix3;
|
struct nvkm_gsp_radix3 radix3;
|
||||||
struct nvkm_gsp_mem meta;
|
struct nvkm_gsp_mem meta;
|
||||||
|
struct sg_table fbsr;
|
||||||
} sr;
|
} sr;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -24,11 +24,6 @@ struct nvkm_instmem {
|
||||||
struct nvkm_ramht *ramht;
|
struct nvkm_ramht *ramht;
|
||||||
struct nvkm_memory *ramro;
|
struct nvkm_memory *ramro;
|
||||||
struct nvkm_memory *ramfc;
|
struct nvkm_memory *ramfc;
|
||||||
|
|
||||||
struct {
|
|
||||||
struct sg_table fbsr;
|
|
||||||
bool fbsr_valid;
|
|
||||||
} rm;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 nvkm_instmem_rd32(struct nvkm_instmem *, u32 addr);
|
u32 nvkm_instmem_rd32(struct nvkm_instmem *, u32 addr);
|
||||||
|
|
|
@ -201,21 +201,18 @@ fbsr_inst(struct fbsr *fbsr, const char *type, struct nvkm_memory *memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
r535_instmem_resume(struct nvkm_instmem *imem)
|
r535_fbsr_resume(struct nvkm_gsp *gsp)
|
||||||
{
|
{
|
||||||
/* RM has restored VRAM contents already, so just need to free the sysmem buffer. */
|
/* RM has restored VRAM contents already, so just need to free the sysmem buffer. */
|
||||||
if (imem->rm.fbsr_valid) {
|
nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.fbsr);
|
||||||
nvkm_gsp_sg_free(imem->subdev.device, &imem->rm.fbsr);
|
|
||||||
imem->rm.fbsr_valid = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
r535_instmem_suspend(struct nvkm_instmem *imem)
|
r535_fbsr_suspend(struct nvkm_gsp *gsp)
|
||||||
{
|
{
|
||||||
struct nvkm_subdev *subdev = &imem->subdev;
|
struct nvkm_subdev *subdev = &gsp->subdev;
|
||||||
struct nvkm_device *device = subdev->device;
|
struct nvkm_device *device = subdev->device;
|
||||||
struct nvkm_gsp *gsp = device->gsp;
|
struct nvkm_instmem *imem = device->imem;
|
||||||
struct nvkm_instobj *iobj;
|
struct nvkm_instobj *iobj;
|
||||||
struct fbsr fbsr = {};
|
struct fbsr fbsr = {};
|
||||||
struct fbsr_item *item, *temp;
|
struct fbsr_item *item, *temp;
|
||||||
|
@ -256,7 +253,7 @@ r535_instmem_suspend(struct nvkm_instmem *imem)
|
||||||
fbsr.size += gsp->fb.bios.vga_workspace.size;
|
fbsr.size += gsp->fb.bios.vga_workspace.size;
|
||||||
nvkm_debug(subdev, "fbsr: size: 0x%llx bytes\n", fbsr.size);
|
nvkm_debug(subdev, "fbsr: size: 0x%llx bytes\n", fbsr.size);
|
||||||
|
|
||||||
ret = nvkm_gsp_sg(gsp->subdev.device, fbsr.size, &imem->rm.fbsr);
|
ret = nvkm_gsp_sg(gsp->subdev.device, fbsr.size, &gsp->sr.fbsr);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -265,7 +262,7 @@ r535_instmem_suspend(struct nvkm_instmem *imem)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto done_sgt;
|
goto done_sgt;
|
||||||
|
|
||||||
ret = fbsr_init(&fbsr, &imem->rm.fbsr, items_size);
|
ret = fbsr_init(&fbsr, &gsp->sr.fbsr, items_size);
|
||||||
if (WARN_ON(ret))
|
if (WARN_ON(ret))
|
||||||
goto done_sgt;
|
goto done_sgt;
|
||||||
|
|
||||||
|
@ -276,12 +273,10 @@ r535_instmem_suspend(struct nvkm_instmem *imem)
|
||||||
goto done_sgt;
|
goto done_sgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
imem->rm.fbsr_valid = true;
|
|
||||||
|
|
||||||
/* Cleanup everything except the sysmem backup, which will be removed after resume. */
|
/* Cleanup everything except the sysmem backup, which will be removed after resume. */
|
||||||
done_sgt:
|
done_sgt:
|
||||||
if (ret) /* ... unless we failed already. */
|
if (ret) /* ... unless we failed already. */
|
||||||
nvkm_gsp_sg_free(device, &imem->rm.fbsr);
|
nvkm_gsp_sg_free(device, &gsp->sr.fbsr);
|
||||||
done:
|
done:
|
||||||
list_for_each_entry_safe(item, temp, &fbsr.items, head) {
|
list_for_each_entry_safe(item, temp, &fbsr.items, head) {
|
||||||
list_del(&item->head);
|
list_del(&item->head);
|
||||||
|
@ -293,6 +288,12 @@ done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct nvkm_rm_api_fbsr
|
||||||
|
r535_fbsr = {
|
||||||
|
.suspend = r535_fbsr_suspend,
|
||||||
|
.resume = r535_fbsr_resume,
|
||||||
|
};
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
r535_instmem_dtor(struct nvkm_instmem *imem)
|
r535_instmem_dtor(struct nvkm_instmem *imem)
|
||||||
{
|
{
|
||||||
|
@ -313,8 +314,6 @@ r535_instmem_new(const struct nvkm_instmem_func *hw,
|
||||||
|
|
||||||
rm->dtor = r535_instmem_dtor;
|
rm->dtor = r535_instmem_dtor;
|
||||||
rm->fini = hw->fini;
|
rm->fini = hw->fini;
|
||||||
rm->suspend = r535_instmem_suspend;
|
|
||||||
rm->resume = r535_instmem_resume;
|
|
||||||
rm->memory_new = hw->memory_new;
|
rm->memory_new = hw->memory_new;
|
||||||
rm->memory_wrap = hw->memory_wrap;
|
rm->memory_wrap = hw->memory_wrap;
|
||||||
rm->zero = false;
|
rm->zero = false;
|
||||||
|
|
|
@ -1730,6 +1730,7 @@ lvl1_fail:
|
||||||
int
|
int
|
||||||
r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
|
r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
|
||||||
{
|
{
|
||||||
|
struct nvkm_rm *rm = gsp->rm;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (suspend) {
|
if (suspend) {
|
||||||
|
@ -1754,6 +1755,14 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
|
||||||
sr->revision = GSP_FW_SR_META_REVISION;
|
sr->revision = GSP_FW_SR_META_REVISION;
|
||||||
sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.lvl0.addr;
|
sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.lvl0.addr;
|
||||||
sr->sizeOfSuspendResumeData = len;
|
sr->sizeOfSuspendResumeData = len;
|
||||||
|
|
||||||
|
ret = rm->api->fbsr->suspend(gsp);
|
||||||
|
if (ret) {
|
||||||
|
nvkm_gsp_mem_dtor(&gsp->sr.meta);
|
||||||
|
nvkm_gsp_radix3_dtor(gsp, &gsp->sr.radix3);
|
||||||
|
nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.sgt);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = r535_gsp_rpc_unloading_guest_driver(gsp, suspend);
|
ret = r535_gsp_rpc_unloading_guest_driver(gsp, suspend);
|
||||||
|
@ -1787,6 +1796,8 @@ r535_gsp_init(struct nvkm_gsp *gsp)
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (gsp->sr.meta.data) {
|
if (gsp->sr.meta.data) {
|
||||||
|
gsp->rm->api->fbsr->resume(gsp);
|
||||||
|
|
||||||
nvkm_gsp_mem_dtor(&gsp->sr.meta);
|
nvkm_gsp_mem_dtor(&gsp->sr.meta);
|
||||||
nvkm_gsp_radix3_dtor(gsp, &gsp->sr.radix3);
|
nvkm_gsp_radix3_dtor(gsp, &gsp->sr.radix3);
|
||||||
nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.sgt);
|
nvkm_gsp_sg_free(gsp->subdev.device, &gsp->sr.sgt);
|
||||||
|
|
|
@ -28,6 +28,7 @@ r535_api = {
|
||||||
.alloc = &r535_alloc,
|
.alloc = &r535_alloc,
|
||||||
.client = &r535_client,
|
.client = &r535_client,
|
||||||
.device = &r535_device,
|
.device = &r535_device,
|
||||||
|
.fbsr = &r535_fbsr,
|
||||||
.disp = &r535_disp,
|
.disp = &r535_disp,
|
||||||
.fifo = &r535_fifo,
|
.fifo = &r535_fifo,
|
||||||
.ce = &r535_ce,
|
.ce = &r535_ce,
|
||||||
|
|
|
@ -73,6 +73,11 @@ struct nvkm_rm_api {
|
||||||
} event;
|
} event;
|
||||||
} *device;
|
} *device;
|
||||||
|
|
||||||
|
const struct nvkm_rm_api_fbsr {
|
||||||
|
int (*suspend)(struct nvkm_gsp *);
|
||||||
|
void (*resume)(struct nvkm_gsp *);
|
||||||
|
} *fbsr;
|
||||||
|
|
||||||
const struct nvkm_rm_api_disp {
|
const struct nvkm_rm_api_disp {
|
||||||
int (*get_static_info)(struct nvkm_disp *);
|
int (*get_static_info)(struct nvkm_disp *);
|
||||||
|
|
||||||
|
@ -113,6 +118,7 @@ extern const struct nvkm_rm_api_ctrl r535_ctrl;
|
||||||
extern const struct nvkm_rm_api_alloc r535_alloc;
|
extern const struct nvkm_rm_api_alloc r535_alloc;
|
||||||
extern const struct nvkm_rm_api_client r535_client;
|
extern const struct nvkm_rm_api_client r535_client;
|
||||||
extern const struct nvkm_rm_api_device r535_device;
|
extern const struct nvkm_rm_api_device r535_device;
|
||||||
|
extern const struct nvkm_rm_api_fbsr r535_fbsr;
|
||||||
extern const struct nvkm_rm_api_disp r535_disp;
|
extern const struct nvkm_rm_api_disp r535_disp;
|
||||||
extern const struct nvkm_rm_api_fifo r535_fifo;
|
extern const struct nvkm_rm_api_fifo r535_fifo;
|
||||||
extern const struct nvkm_rm_api_engine r535_ce;
|
extern const struct nvkm_rm_api_engine r535_ce;
|
||||||
|
|
|
@ -182,9 +182,11 @@ nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (suspend) {
|
if (suspend) {
|
||||||
ret = imem->func->suspend(imem);
|
if (imem->func->suspend) {
|
||||||
if (ret)
|
ret = imem->func->suspend(imem);
|
||||||
return ret;
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
imem->suspend = true;
|
imem->suspend = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue