Changes since last sent: * add a patch to set the device into DRM_SWITCH_POWER_CHANGING state (can be dropped actually, I thought I was needing it, came up with a different approach and forgot to delete it, doesn't hurt though) * expose information about runtime suspending to nvkm so that we can run the pcie workaround only on runtime suspend Karol Herbst (8): pci: disable ASPM before changing the link speed pci/gk104: enable dl_mgr safe mode pci/gk104: wait for ltssm idle before changing the link pci: enable pcie link changes for pascal drm: set power_state to DRM_SWITCH_POWER_CHANGING before changing drm: be explicit about runtime suspend in fini pci: set the pcie link speed to 8.0 when suspending drm: abort runtime suspend if we hit an error bin/nv_init.c | 2 +- drm/nouveau/include/nvif/client.h | 2 +- drm/nouveau/include/nvif/driver.h | 2 +- drm/nouveau/include/nvkm/core/device.h | 5 ++- drm/nouveau/include/nvkm/core/engine.h | 2 +- drm/nouveau/include/nvkm/core/object.h | 13 ++++++-- drm/nouveau/include/nvkm/core/oproxy.h | 2 +- drm/nouveau/include/nvkm/core/subdev.h | 5 +-- drm/nouveau/include/nvkm/subdev/pci.h | 3 +- drm/nouveau/nouveau_drm.c | 10 +++++- drm/nouveau/nouveau_nvif.c | 6 ++-- drm/nouveau/nvif/client.c | 4 +-- drm/nouveau/nvkm/core/client.c | 5 ++- drm/nouveau/nvkm/core/engine.c | 4 +-- drm/nouveau/nvkm/core/ioctl.c | 4 +-- drm/nouveau/nvkm/core/object.c | 22 ++++++++++--- drm/nouveau/nvkm/core/oproxy.c | 2 +- drm/nouveau/nvkm/core/subdev.c | 4 +-- drm/nouveau/nvkm/engine/device/base.c | 11 ++++--- drm/nouveau/nvkm/engine/device/pci.c | 2 +- drm/nouveau/nvkm/engine/device/priv.h | 2 +- drm/nouveau/nvkm/engine/device/tegra.c | 3 +- drm/nouveau/nvkm/engine/device/user.c | 2 +- drm/nouveau/nvkm/engine/disp/base.c | 2 +- drm/nouveau/nvkm/engine/disp/channv50.c | 2 +- drm/nouveau/nvkm/engine/falcon.c | 2 +- drm/nouveau/nvkm/engine/fifo/base.c | 2 +- drm/nouveau/nvkm/engine/fifo/chan.c | 5 +-- drm/nouveau/nvkm/engine/fifo/gf100.c | 2 +- drm/nouveau/nvkm/engine/fifo/gk104.c | 2 +- drm/nouveau/nvkm/engine/gr/base.c | 2 +- drm/nouveau/nvkm/engine/gr/nv04.c | 2 +- drm/nouveau/nvkm/engine/gr/nv10.c | 2 +- drm/nouveau/nvkm/engine/gr/nv20.c | 2 +- drm/nouveau/nvkm/engine/gr/nv20.h | 2 +- drm/nouveau/nvkm/engine/gr/nv40.c | 2 +- drm/nouveau/nvkm/engine/mpeg/nv44.c | 2 +- drm/nouveau/nvkm/engine/pm/base.c | 2 +- drm/nouveau/nvkm/engine/sec2/base.c | 2 +- drm/nouveau/nvkm/engine/xtensa.c | 2 +- drm/nouveau/nvkm/subdev/bar/base.c | 2 +- drm/nouveau/nvkm/subdev/clk/base.c | 4 +-- drm/nouveau/nvkm/subdev/devinit/base.c | 2 +- drm/nouveau/nvkm/subdev/fault/base.c | 2 +- drm/nouveau/nvkm/subdev/fault/user.c | 2 +- drm/nouveau/nvkm/subdev/gpio/base.c | 2 +- drm/nouveau/nvkm/subdev/i2c/base.c | 2 +- drm/nouveau/nvkm/subdev/instmem/base.c | 2 +- drm/nouveau/nvkm/subdev/mc/base.c | 2 +- drm/nouveau/nvkm/subdev/pci/base.c | 4 ++- drm/nouveau/nvkm/subdev/pci/g84.c | 9 ++++++ drm/nouveau/nvkm/subdev/pci/g92.c | 1 + drm/nouveau/nvkm/subdev/pci/g94.c | 1 + drm/nouveau/nvkm/subdev/pci/gf100.c | 1 + drm/nouveau/nvkm/subdev/pci/gf106.c | 1 + drm/nouveau/nvkm/subdev/pci/gk104.c | 29 +++++++++++++---- drm/nouveau/nvkm/subdev/pci/gp100.c | 11 +++++++ drm/nouveau/nvkm/subdev/pci/pcie.c | 43 ++++++++++++++++++++++--- drm/nouveau/nvkm/subdev/pci/priv.h | 16 +++++++++ drm/nouveau/nvkm/subdev/pmu/base.c | 2 +- drm/nouveau/nvkm/subdev/secboot/base.c | 2 +- drm/nouveau/nvkm/subdev/therm/base.c | 2 +- drm/nouveau/nvkm/subdev/timer/base.c | 2 +- lib/drm.c | 2 +- lib/main.c | 6 ++-- lib/null.c | 6 ++-- 66 files changed, 224 insertions(+), 88 deletions(-) -- 2.21.0
Karol Herbst
2019-Sep-23 20:39 UTC
[Nouveau] [PATCH 1/8] pci: disable ASPM before changing the link speed
taken from nvgpu v2: rename force_aspm_off to aspm_off rework interface to return old value and take a mask as the input Signed-off-by: Karol Herbst <kherbst at redhat.com> --- drm/nouveau/nvkm/subdev/pci/g84.c | 9 +++++++++ drm/nouveau/nvkm/subdev/pci/g92.c | 1 + drm/nouveau/nvkm/subdev/pci/g94.c | 1 + drm/nouveau/nvkm/subdev/pci/gf100.c | 1 + drm/nouveau/nvkm/subdev/pci/gf106.c | 1 + drm/nouveau/nvkm/subdev/pci/gk104.c | 1 + drm/nouveau/nvkm/subdev/pci/pcie.c | 15 +++++++++++++++ drm/nouveau/nvkm/subdev/pci/priv.h | 10 ++++++++++ 8 files changed, 39 insertions(+) diff --git a/drm/nouveau/nvkm/subdev/pci/g84.c b/drm/nouveau/nvkm/subdev/pci/g84.c index 62438d892..5e17e0589 100644 --- a/drm/nouveau/nvkm/subdev/pci/g84.c +++ b/drm/nouveau/nvkm/subdev/pci/g84.c @@ -122,6 +122,14 @@ g84_pci_init(struct nvkm_pci *pci) nvkm_pci_mask(pci, 0x041c, 0x00000060, 0x00000000); } +enum nvkm_pci_aspm +g84_pcie_aspm_off(struct nvkm_pci *pci, enum nvkm_pci_aspm states) +{ + u32 value = states << 7; + + return (nvkm_pci_mask(pci, 0x150, 0x180, value) & 0x180) >> 7; +} + int g84_pcie_init(struct nvkm_pci *pci) { @@ -147,6 +155,7 @@ g84_pci_func = { .pcie.set_version = g84_pcie_set_version, .pcie.version = g84_pcie_version, .pcie.version_supported = g84_pcie_version_supported, + .pcie.aspm_off = g84_pcie_aspm_off, }; int diff --git a/drm/nouveau/nvkm/subdev/pci/g92.c b/drm/nouveau/nvkm/subdev/pci/g92.c index 48874359d..85629ffee 100644 --- a/drm/nouveau/nvkm/subdev/pci/g92.c +++ b/drm/nouveau/nvkm/subdev/pci/g92.c @@ -48,6 +48,7 @@ g92_pci_func = { .pcie.set_version = g84_pcie_set_version, .pcie.version = g84_pcie_version, .pcie.version_supported = g92_pcie_version_supported, + .pcie.aspm_off = g84_pcie_aspm_off, }; int diff --git a/drm/nouveau/nvkm/subdev/pci/g94.c b/drm/nouveau/nvkm/subdev/pci/g94.c index 09adb37a5..588bea4f6 100644 --- a/drm/nouveau/nvkm/subdev/pci/g94.c +++ b/drm/nouveau/nvkm/subdev/pci/g94.c @@ -40,6 +40,7 @@ g94_pci_func = { .pcie.set_version = g84_pcie_set_version, .pcie.version = g84_pcie_version, .pcie.version_supported = g92_pcie_version_supported, + .pcie.aspm_off = g84_pcie_aspm_off, }; int diff --git a/drm/nouveau/nvkm/subdev/pci/gf100.c b/drm/nouveau/nvkm/subdev/pci/gf100.c index 00a5e7d3e..7948942b6 100644 --- a/drm/nouveau/nvkm/subdev/pci/gf100.c +++ b/drm/nouveau/nvkm/subdev/pci/gf100.c @@ -93,6 +93,7 @@ gf100_pci_func = { .pcie.set_version = gf100_pcie_set_version, .pcie.version = gf100_pcie_version, .pcie.version_supported = g92_pcie_version_supported, + .pcie.aspm_off = g84_pcie_aspm_off, }; int diff --git a/drm/nouveau/nvkm/subdev/pci/gf106.c b/drm/nouveau/nvkm/subdev/pci/gf106.c index 11bf419af..c62c66a2e 100644 --- a/drm/nouveau/nvkm/subdev/pci/gf106.c +++ b/drm/nouveau/nvkm/subdev/pci/gf106.c @@ -40,6 +40,7 @@ gf106_pci_func = { .pcie.set_version = gf100_pcie_set_version, .pcie.version = gf100_pcie_version, .pcie.version_supported = g92_pcie_version_supported, + .pcie.aspm_off = g84_pcie_aspm_off, }; int diff --git a/drm/nouveau/nvkm/subdev/pci/gk104.c b/drm/nouveau/nvkm/subdev/pci/gk104.c index e68030507..a4014d4a7 100644 --- a/drm/nouveau/nvkm/subdev/pci/gk104.c +++ b/drm/nouveau/nvkm/subdev/pci/gk104.c @@ -219,6 +219,7 @@ gk104_pci_func = { .pcie.set_version = gf100_pcie_set_version, .pcie.version = gf100_pcie_version, .pcie.version_supported = gk104_pcie_version_supported, + .pcie.aspm_off = g84_pcie_aspm_off, }; int diff --git a/drm/nouveau/nvkm/subdev/pci/pcie.c b/drm/nouveau/nvkm/subdev/pci/pcie.c index d71e5db50..ed015b252 100644 --- a/drm/nouveau/nvkm/subdev/pci/pcie.c +++ b/drm/nouveau/nvkm/subdev/pci/pcie.c @@ -111,12 +111,21 @@ nvkm_pcie_init(struct nvkm_pci *pci) return 0; } +enum nvkm_pci_aspm +nvkm_pcie_aspm_off(struct nvkm_pci *pci, enum nvkm_pci_aspm states) +{ + if (!pci->func->pcie.aspm_off) + return NVKM_PCI_ASPM_NONE; + return pci->func->pcie.aspm_off(pci, states); +} + int nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width) { struct nvkm_subdev *subdev = &pci->subdev; enum nvkm_pcie_speed cur_speed, max_speed; struct pci_bus *pbus; + enum nvkm_pci_aspm old_aspm_state; int ret; if (!pci || !pci_is_pcie(pci->pdev)) @@ -157,9 +166,15 @@ nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width) nvkm_debug(subdev, "set link to %s x%i\n", nvkm_pcie_speeds[speed], width); + /* disable ASPM */ + old_aspm_state = nvkm_pcie_aspm_off(pci, NVKM_PCI_ASPM_L0S_L1); + ret = pci->func->pcie.set_link(pci, speed, width); if (ret < 0) nvkm_error(subdev, "setting link failed: %i\n", ret); + /* restore old ASPM state */ + nvkm_pcie_aspm_off(pci, old_aspm_state); + return ret; } diff --git a/drm/nouveau/nvkm/subdev/pci/priv.h b/drm/nouveau/nvkm/subdev/pci/priv.h index 7009aad86..8518ff056 100644 --- a/drm/nouveau/nvkm/subdev/pci/priv.h +++ b/drm/nouveau/nvkm/subdev/pci/priv.h @@ -7,6 +7,13 @@ int nvkm_pci_new_(const struct nvkm_pci_func *, struct nvkm_device *, int index, struct nvkm_pci **); +enum nvkm_pci_aspm { + NVKM_PCI_ASPM_NONE = 0, + NVKM_PCI_ASPM_L0S = 1, + NVKM_PCI_ASPM_L1 = 2, + NVKM_PCI_ASPM_L0S_L1 = 3, +}; + struct nvkm_pci_func { void (*init)(struct nvkm_pci *); u32 (*rd32)(struct nvkm_pci *, u16 addr); @@ -24,6 +31,8 @@ struct nvkm_pci_func { void (*set_version)(struct nvkm_pci *, u8); int (*version)(struct nvkm_pci *); int (*version_supported)(struct nvkm_pci *); + enum nvkm_pci_aspm (*aspm_off)(struct nvkm_pci *, + enum nvkm_pci_aspm); } pcie; }; @@ -42,6 +51,7 @@ int g84_pcie_version(struct nvkm_pci *); void g84_pcie_set_link_speed(struct nvkm_pci *, enum nvkm_pcie_speed); enum nvkm_pcie_speed g84_pcie_cur_speed(struct nvkm_pci *); enum nvkm_pcie_speed g84_pcie_max_speed(struct nvkm_pci *); +enum nvkm_pci_aspm g84_pcie_aspm_off(struct nvkm_pci *, enum nvkm_pci_aspm); int g84_pcie_init(struct nvkm_pci *); int g84_pcie_set_link(struct nvkm_pci *, enum nvkm_pcie_speed, u8); -- 2.21.0
Karol Herbst
2019-Sep-23 20:39 UTC
[Nouveau] [PATCH 2/8] pci/gk104: enable dl_mgr safe mode
no idea why and what it does, taken from nvgpu Signed-off-by: Karol Herbst <kherbst at redhat.com> --- drm/nouveau/nvkm/subdev/pci/gk104.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drm/nouveau/nvkm/subdev/pci/gk104.c b/drm/nouveau/nvkm/subdev/pci/gk104.c index a4014d4a7..1c4f9a1cd 100644 --- a/drm/nouveau/nvkm/subdev/pci/gk104.c +++ b/drm/nouveau/nvkm/subdev/pci/gk104.c @@ -184,6 +184,7 @@ gk104_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width) struct nvkm_subdev *subdev = &pci->subdev; enum nvkm_pcie_speed lnk_ctl_speed = gk104_pcie_lnkctl_speed(pci); enum nvkm_pcie_speed lnk_cap_speed = gk104_pcie_cap_speed(pci); + u32 old_dl_mgr; if (speed > lnk_cap_speed) { speed = lnk_cap_speed; @@ -197,7 +198,9 @@ gk104_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width) " lnkctl speed\n"); } + old_dl_mgr = nvkm_mask(subdev->device, 0x8b8c0, 0x4, 0x4); gk104_pcie_set_link_speed(pci, speed); + nvkm_wr32(subdev->device, 0x8b8c0, old_dl_mgr); return 0; } -- 2.21.0
Karol Herbst
2019-Sep-23 20:39 UTC
[Nouveau] [PATCH 3/8] pci/gk104: wait for ltssm idle before changing the link
taken from nvgpu v2: return -EBUSY when the timeout is reached Signed-off-by: Karol Herbst <kherbst at redhat.com> --- drm/nouveau/nvkm/subdev/pci/gk104.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drm/nouveau/nvkm/subdev/pci/gk104.c b/drm/nouveau/nvkm/subdev/pci/gk104.c index 1c4f9a1cd..dda113a45 100644 --- a/drm/nouveau/nvkm/subdev/pci/gk104.c +++ b/drm/nouveau/nvkm/subdev/pci/gk104.c @@ -23,6 +23,8 @@ */ #include "priv.h" +#include <subdev/timer.h> + static int gk104_pcie_version_supported(struct nvkm_pci *pci) { @@ -123,7 +125,7 @@ gk104_pcie_max_speed(struct nvkm_pci *pci) return NVKM_PCIE_SPEED_2_5; } -static void +static int gk104_pcie_set_link_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed) { struct nvkm_device *device = pci->subdev.device; @@ -142,8 +144,16 @@ gk104_pcie_set_link_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed) break; } + /* wait for ltssm idle */ + if (nvkm_msec(device, 200, + if ((nvkm_rd32(device, 0x8c040) & 0x1f) == 0) + break; + ) < 0) { + return -EBUSY; + } nvkm_mask(device, 0x8c040, 0xc0000, mask_value); nvkm_mask(device, 0x8c040, 0x1, 0x1); + return 0; } static int @@ -185,6 +195,7 @@ gk104_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width) enum nvkm_pcie_speed lnk_ctl_speed = gk104_pcie_lnkctl_speed(pci); enum nvkm_pcie_speed lnk_cap_speed = gk104_pcie_cap_speed(pci); u32 old_dl_mgr; + int ret; if (speed > lnk_cap_speed) { speed = lnk_cap_speed; @@ -199,9 +210,9 @@ gk104_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width) } old_dl_mgr = nvkm_mask(subdev->device, 0x8b8c0, 0x4, 0x4); - gk104_pcie_set_link_speed(pci, speed); + ret = gk104_pcie_set_link_speed(pci, speed); nvkm_wr32(subdev->device, 0x8b8c0, old_dl_mgr); - return 0; + return ret; } -- 2.21.0
Karol Herbst
2019-Sep-23 20:39 UTC
[Nouveau] [PATCH 4/8] pci: enable pcie link changes for pascal
v2: add force disable ASPM func pointer Signed-off-by: Karol Herbst <kherbst at redhat.com> Reviewed-by: Lyude Paul <lyude at redhat.com> --- drm/nouveau/nvkm/subdev/pci/gk104.c | 8 ++++---- drm/nouveau/nvkm/subdev/pci/gp100.c | 11 +++++++++++ drm/nouveau/nvkm/subdev/pci/priv.h | 5 +++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/drm/nouveau/nvkm/subdev/pci/gk104.c b/drm/nouveau/nvkm/subdev/pci/gk104.c index dda113a45..d6ba1918e 100644 --- a/drm/nouveau/nvkm/subdev/pci/gk104.c +++ b/drm/nouveau/nvkm/subdev/pci/gk104.c @@ -25,7 +25,7 @@ #include <subdev/timer.h> -static int +int gk104_pcie_version_supported(struct nvkm_pci *pci) { return (nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x4) == 0x4 ? 2 : 1; @@ -110,7 +110,7 @@ gk104_pcie_lnkctl_speed(struct nvkm_pci *pci) return -1; } -static enum nvkm_pcie_speed +enum nvkm_pcie_speed gk104_pcie_max_speed(struct nvkm_pci *pci) { u32 max_speed = nvkm_rd32(pci->subdev.device, 0x8c1c0) & 0x300000; @@ -156,7 +156,7 @@ gk104_pcie_set_link_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed) return 0; } -static int +int gk104_pcie_init(struct nvkm_pci * pci) { enum nvkm_pcie_speed lnkctl_speed, max_speed, cap_speed; @@ -188,7 +188,7 @@ gk104_pcie_init(struct nvkm_pci * pci) return 0; } -static int +int gk104_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width) { struct nvkm_subdev *subdev = &pci->subdev; diff --git a/drm/nouveau/nvkm/subdev/pci/gp100.c b/drm/nouveau/nvkm/subdev/pci/gp100.c index 82c5234a0..c102109d9 100644 --- a/drm/nouveau/nvkm/subdev/pci/gp100.c +++ b/drm/nouveau/nvkm/subdev/pci/gp100.c @@ -35,6 +35,17 @@ gp100_pci_func = { .wr08 = nv40_pci_wr08, .wr32 = nv40_pci_wr32, .msi_rearm = gp100_pci_msi_rearm, + + .pcie.init = gk104_pcie_init, + .pcie.set_link = gk104_pcie_set_link, + + .pcie.max_speed = gk104_pcie_max_speed, + .pcie.cur_speed = g84_pcie_cur_speed, + + .pcie.set_version = gf100_pcie_set_version, + .pcie.version = gf100_pcie_version, + .pcie.version_supported = gk104_pcie_version_supported, + .pcie.aspm_off = g84_pcie_aspm_off, }; int diff --git a/drm/nouveau/nvkm/subdev/pci/priv.h b/drm/nouveau/nvkm/subdev/pci/priv.h index 8518ff056..17be1d563 100644 --- a/drm/nouveau/nvkm/subdev/pci/priv.h +++ b/drm/nouveau/nvkm/subdev/pci/priv.h @@ -64,6 +64,11 @@ int gf100_pcie_cap_speed(struct nvkm_pci *); int gf100_pcie_init(struct nvkm_pci *); int gf100_pcie_set_link(struct nvkm_pci *, enum nvkm_pcie_speed, u8); +int gk104_pcie_init(struct nvkm_pci *); +int gk104_pcie_set_link(struct nvkm_pci *, enum nvkm_pcie_speed, u8 width); +enum nvkm_pcie_speed gk104_pcie_max_speed(struct nvkm_pci *); +int gk104_pcie_version_supported(struct nvkm_pci *); + int nvkm_pcie_oneinit(struct nvkm_pci *); int nvkm_pcie_init(struct nvkm_pci *); #endif -- 2.21.0
Karol Herbst
2019-Sep-23 20:39 UTC
[Nouveau] [PATCH 5/8] drm: set power_state to DRM_SWITCH_POWER_CHANGING before changing
--- drm/nouveau/nouveau_drm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drm/nouveau/nouveau_drm.c b/drm/nouveau/nouveau_drm.c index 3d32afe8a..466271c0c 100644 --- a/drm/nouveau/nouveau_drm.c +++ b/drm/nouveau/nouveau_drm.c @@ -917,6 +917,7 @@ nouveau_pmops_runtime_suspend(struct device *dev) return -EBUSY; } + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; nouveau_switcheroo_optimus_dsm(); ret = nouveau_do_suspend(drm_dev, true); pci_save_state(pdev); @@ -941,6 +942,7 @@ nouveau_pmops_runtime_resume(struct device *dev) return -EBUSY; } + drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); ret = pci_enable_device(pdev); -- 2.21.0
Karol Herbst
2019-Sep-23 20:39 UTC
[Nouveau] [PATCH 6/8] drm: be explicit about runtime suspend in fini
Allows fini functions to check if we do a real system suspend or just runtime suspending the GPU. Signed-off-by: Karol Herbst <kherbst at redhat.com> --- bin/nv_init.c | 2 +- drm/nouveau/include/nvif/client.h | 2 +- drm/nouveau/include/nvif/driver.h | 2 +- drm/nouveau/include/nvkm/core/device.h | 3 ++- drm/nouveau/include/nvkm/core/engine.h | 2 +- drm/nouveau/include/nvkm/core/object.h | 13 +++++++++++-- drm/nouveau/include/nvkm/core/oproxy.h | 2 +- drm/nouveau/include/nvkm/core/subdev.h | 5 +++-- drm/nouveau/nouveau_drm.c | 2 +- drm/nouveau/nouveau_nvif.c | 6 ++++-- drm/nouveau/nvif/client.c | 4 ++-- drm/nouveau/nvkm/core/client.c | 5 ++--- drm/nouveau/nvkm/core/engine.c | 4 ++-- drm/nouveau/nvkm/core/ioctl.c | 4 ++-- drm/nouveau/nvkm/core/object.c | 22 ++++++++++++++++++---- drm/nouveau/nvkm/core/oproxy.c | 2 +- drm/nouveau/nvkm/core/subdev.c | 4 ++-- drm/nouveau/nvkm/engine/device/base.c | 11 ++++++----- drm/nouveau/nvkm/engine/device/pci.c | 2 +- drm/nouveau/nvkm/engine/device/priv.h | 2 +- drm/nouveau/nvkm/engine/device/tegra.c | 3 ++- drm/nouveau/nvkm/engine/device/user.c | 2 +- drm/nouveau/nvkm/engine/disp/base.c | 2 +- drm/nouveau/nvkm/engine/disp/channv50.c | 2 +- drm/nouveau/nvkm/engine/falcon.c | 2 +- drm/nouveau/nvkm/engine/fifo/base.c | 2 +- drm/nouveau/nvkm/engine/fifo/chan.c | 5 +++-- drm/nouveau/nvkm/engine/fifo/gf100.c | 2 +- drm/nouveau/nvkm/engine/fifo/gk104.c | 2 +- drm/nouveau/nvkm/engine/gr/base.c | 2 +- drm/nouveau/nvkm/engine/gr/nv04.c | 2 +- drm/nouveau/nvkm/engine/gr/nv10.c | 2 +- drm/nouveau/nvkm/engine/gr/nv20.c | 2 +- drm/nouveau/nvkm/engine/gr/nv20.h | 2 +- drm/nouveau/nvkm/engine/gr/nv40.c | 2 +- drm/nouveau/nvkm/engine/mpeg/nv44.c | 2 +- drm/nouveau/nvkm/engine/pm/base.c | 2 +- drm/nouveau/nvkm/engine/sec2/base.c | 2 +- drm/nouveau/nvkm/engine/xtensa.c | 2 +- drm/nouveau/nvkm/subdev/bar/base.c | 2 +- drm/nouveau/nvkm/subdev/clk/base.c | 2 +- drm/nouveau/nvkm/subdev/devinit/base.c | 2 +- drm/nouveau/nvkm/subdev/fault/base.c | 2 +- drm/nouveau/nvkm/subdev/fault/user.c | 2 +- drm/nouveau/nvkm/subdev/gpio/base.c | 2 +- drm/nouveau/nvkm/subdev/i2c/base.c | 2 +- drm/nouveau/nvkm/subdev/instmem/base.c | 2 +- drm/nouveau/nvkm/subdev/mc/base.c | 2 +- drm/nouveau/nvkm/subdev/pci/base.c | 2 +- drm/nouveau/nvkm/subdev/pmu/base.c | 2 +- drm/nouveau/nvkm/subdev/secboot/base.c | 2 +- drm/nouveau/nvkm/subdev/therm/base.c | 2 +- drm/nouveau/nvkm/subdev/timer/base.c | 2 +- lib/drm.c | 2 +- lib/main.c | 6 ++++-- lib/null.c | 6 ++++-- 56 files changed, 108 insertions(+), 75 deletions(-) diff --git a/bin/nv_init.c b/bin/nv_init.c index 90c14d5ea..f67ca9844 100644 --- a/bin/nv_init.c +++ b/bin/nv_init.c @@ -38,7 +38,7 @@ main(int argc, char **argv) return ret; if (suspend) { - nvif_client_suspend(&client); + nvif_client_suspend(&client, false); nvif_client_resume(&client); } diff --git a/drm/nouveau/include/nvif/client.h b/drm/nouveau/include/nvif/client.h index e63c6c965..6948ec148 100644 --- a/drm/nouveau/include/nvif/client.h +++ b/drm/nouveau/include/nvif/client.h @@ -16,7 +16,7 @@ int nvif_client_init(struct nvif_client *parent, const char *name, u64 device, struct nvif_client *); void nvif_client_fini(struct nvif_client *); int nvif_client_ioctl(struct nvif_client *, void *, u32); -int nvif_client_suspend(struct nvif_client *); +int nvif_client_suspend(struct nvif_client *, bool runtime); int nvif_client_resume(struct nvif_client *); /*XXX*/ diff --git a/drm/nouveau/include/nvif/driver.h b/drm/nouveau/include/nvif/driver.h index 8e85b936e..a77450add 100644 --- a/drm/nouveau/include/nvif/driver.h +++ b/drm/nouveau/include/nvif/driver.h @@ -9,7 +9,7 @@ struct nvif_driver { int (*init)(const char *name, u64 device, const char *cfg, const char *dbg, void **priv); void (*fini)(void *priv); - int (*suspend)(void *priv); + int (*suspend)(void *priv, bool runtime); int (*resume)(void *priv); int (*ioctl)(void *priv, bool super, void *data, u32 size, void **hack); void __iomem *(*map)(void *priv, u64 handle, u32 size); diff --git a/drm/nouveau/include/nvkm/core/device.h b/drm/nouveau/include/nvkm/core/device.h index 6d55cd047..ef8e652a0 100644 --- a/drm/nouveau/include/nvkm/core/device.h +++ b/drm/nouveau/include/nvkm/core/device.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_DEVICE_H__ #define __NVKM_DEVICE_H__ +#include <core/object.h> #include <core/oclass.h> #include <core/event.h> @@ -188,7 +189,7 @@ struct nvkm_device_func { void *(*dtor)(struct nvkm_device *); int (*preinit)(struct nvkm_device *); int (*init)(struct nvkm_device *); - void (*fini)(struct nvkm_device *, bool suspend); + void (*fini)(struct nvkm_device *, enum nvkm_suspend_type); resource_size_t (*resource_addr)(struct nvkm_device *, unsigned bar); resource_size_t (*resource_size)(struct nvkm_device *, unsigned bar); bool cpu_coherent; diff --git a/drm/nouveau/include/nvkm/core/engine.h b/drm/nouveau/include/nvkm/core/engine.h index c6b401a6e..a020c5589 100644 --- a/drm/nouveau/include/nvkm/core/engine.h +++ b/drm/nouveau/include/nvkm/core/engine.h @@ -20,7 +20,7 @@ struct nvkm_engine_func { int (*oneinit)(struct nvkm_engine *); int (*info)(struct nvkm_engine *, u64 mthd, u64 *data); int (*init)(struct nvkm_engine *); - int (*fini)(struct nvkm_engine *, bool suspend); + int (*fini)(struct nvkm_engine *, enum nvkm_suspend_type); void (*intr)(struct nvkm_engine *); void (*tile)(struct nvkm_engine *, int region, struct nvkm_fb_tile *); bool (*chsw_load)(struct nvkm_engine *); diff --git a/drm/nouveau/include/nvkm/core/object.h b/drm/nouveau/include/nvkm/core/object.h index 7efcd5d2f..2eecf3c60 100644 --- a/drm/nouveau/include/nvkm/core/object.h +++ b/drm/nouveau/include/nvkm/core/object.h @@ -25,10 +25,19 @@ enum nvkm_object_map { NVKM_OBJECT_MAP_VA }; +enum nvkm_suspend_type { + NVKM_SUSPEND_NONE = 0, + NVKM_SUSPEND_SYSTEM = 1, + NVKM_SUSPEND_RUNTIME = 2, +}; + +const char* +nvkm_suspend_type_str(enum nvkm_suspend_type); + struct nvkm_object_func { void *(*dtor)(struct nvkm_object *); int (*init)(struct nvkm_object *); - int (*fini)(struct nvkm_object *, bool suspend); + int (*fini)(struct nvkm_object *, enum nvkm_suspend_type); int (*mthd)(struct nvkm_object *, u32 mthd, void *data, u32 size); int (*ntfy)(struct nvkm_object *, u32 mthd, struct nvkm_event **); int (*map)(struct nvkm_object *, void *argv, u32 argc, @@ -55,7 +64,7 @@ int nvkm_object_new(const struct nvkm_oclass *, void *data, u32 size, void nvkm_object_del(struct nvkm_object **); void *nvkm_object_dtor(struct nvkm_object *); int nvkm_object_init(struct nvkm_object *); -int nvkm_object_fini(struct nvkm_object *, bool suspend); +int nvkm_object_fini(struct nvkm_object *, enum nvkm_suspend_type); int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size); int nvkm_object_ntfy(struct nvkm_object *, u32 mthd, struct nvkm_event **); int nvkm_object_map(struct nvkm_object *, void *argv, u32 argc, diff --git a/drm/nouveau/include/nvkm/core/oproxy.h b/drm/nouveau/include/nvkm/core/oproxy.h index 0e70a9afb..9eb316ad3 100644 --- a/drm/nouveau/include/nvkm/core/oproxy.h +++ b/drm/nouveau/include/nvkm/core/oproxy.h @@ -13,7 +13,7 @@ struct nvkm_oproxy { struct nvkm_oproxy_func { void (*dtor[2])(struct nvkm_oproxy *); int (*init[2])(struct nvkm_oproxy *); - int (*fini[2])(struct nvkm_oproxy *, bool suspend); + int (*fini[2])(struct nvkm_oproxy *, enum nvkm_suspend_type); }; void nvkm_oproxy_ctor(const struct nvkm_oproxy_func *, diff --git a/drm/nouveau/include/nvkm/core/subdev.h b/drm/nouveau/include/nvkm/core/subdev.h index 1218f28c1..6bd9ee200 100644 --- a/drm/nouveau/include/nvkm/core/subdev.h +++ b/drm/nouveau/include/nvkm/core/subdev.h @@ -2,6 +2,7 @@ #ifndef __NVKM_SUBDEV_H__ #define __NVKM_SUBDEV_H__ #include <core/device.h> +#include <core/object.h> struct nvkm_subdev { const struct nvkm_subdev_func *func; @@ -19,7 +20,7 @@ struct nvkm_subdev_func { int (*oneinit)(struct nvkm_subdev *); int (*info)(struct nvkm_subdev *, u64 mthd, u64 *data); int (*init)(struct nvkm_subdev *); - int (*fini)(struct nvkm_subdev *, bool suspend); + int (*fini)(struct nvkm_subdev *, enum nvkm_suspend_type); void (*intr)(struct nvkm_subdev *); }; @@ -29,7 +30,7 @@ void nvkm_subdev_ctor(const struct nvkm_subdev_func *, struct nvkm_device *, void nvkm_subdev_del(struct nvkm_subdev **); int nvkm_subdev_preinit(struct nvkm_subdev *); int nvkm_subdev_init(struct nvkm_subdev *); -int nvkm_subdev_fini(struct nvkm_subdev *, bool suspend); +int nvkm_subdev_fini(struct nvkm_subdev *, enum nvkm_suspend_type); int nvkm_subdev_info(struct nvkm_subdev *, u64, u64 *); void nvkm_subdev_intr(struct nvkm_subdev *); diff --git a/drm/nouveau/nouveau_drm.c b/drm/nouveau/nouveau_drm.c index 466271c0c..0162cea8e 100644 --- a/drm/nouveau/nouveau_drm.c +++ b/drm/nouveau/nouveau_drm.c @@ -783,7 +783,7 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) } NV_DEBUG(drm, "suspending object tree...\n"); - ret = nvif_client_suspend(&drm->master.base); + ret = nvif_client_suspend(&drm->master.base, runtime); if (ret) goto fail_client; diff --git a/drm/nouveau/nouveau_nvif.c b/drm/nouveau/nouveau_nvif.c index b3f29b1ce..885abb3a5 100644 --- a/drm/nouveau/nouveau_nvif.c +++ b/drm/nouveau/nouveau_nvif.c @@ -65,10 +65,12 @@ nvkm_client_resume(void *priv) } static int -nvkm_client_suspend(void *priv) +nvkm_client_suspend(void *priv, bool runtime) { struct nvkm_client *client = priv; - return nvkm_object_fini(&client->object, true); + enum nvkm_suspend_type suspend + runtime ? NVKM_SUSPEND_RUNTIME : NVKM_SUSPEND_SYSTEM; + return nvkm_object_fini(&client->object, suspend); } static int diff --git a/drm/nouveau/nvif/client.c b/drm/nouveau/nvif/client.c index 12db54965..30fc0b284 100644 --- a/drm/nouveau/nvif/client.c +++ b/drm/nouveau/nvif/client.c @@ -36,9 +36,9 @@ nvif_client_ioctl(struct nvif_client *client, void *data, u32 size) } int -nvif_client_suspend(struct nvif_client *client) +nvif_client_suspend(struct nvif_client *client, bool runtime) { - return client->driver->suspend(client->object.priv); + return client->driver->suspend(client->object.priv, runtime); } int diff --git a/drm/nouveau/nvkm/core/client.c b/drm/nouveau/nvkm/core/client.c index ac6712029..42a6850c6 100644 --- a/drm/nouveau/nvkm/core/client.c +++ b/drm/nouveau/nvkm/core/client.c @@ -253,12 +253,11 @@ nvkm_client_child_get(struct nvkm_object *object, int index, } static int -nvkm_client_fini(struct nvkm_object *object, bool suspend) +nvkm_client_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nvkm_client *client = nvkm_client(object); - const char *name[2] = { "fini", "suspend" }; int i; - nvif_debug(object, "%s notify\n", name[suspend]); + nvif_debug(object, "%s notify\n", nvkm_suspend_type_str(suspend)); for (i = 0; i < ARRAY_SIZE(client->notify); i++) nvkm_client_notify_put(client, i); return 0; diff --git a/drm/nouveau/nvkm/core/engine.c b/drm/nouveau/nvkm/core/engine.c index 1a47c40e1..9a5739ca2 100644 --- a/drm/nouveau/nvkm/core/engine.c +++ b/drm/nouveau/nvkm/core/engine.c @@ -42,7 +42,7 @@ nvkm_engine_unref(struct nvkm_engine **pengine) if (engine) { mutex_lock(&engine->subdev.mutex); if (--engine->usecount == 0) - nvkm_subdev_fini(&engine->subdev, false); + nvkm_subdev_fini(&engine->subdev, NVKM_SUSPEND_NONE); mutex_unlock(&engine->subdev.mutex); *pengine = NULL; } @@ -98,7 +98,7 @@ nvkm_engine_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data) } static int -nvkm_engine_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_engine_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type suspend) { struct nvkm_engine *engine = nvkm_engine(subdev); if (engine->func->fini) diff --git a/drm/nouveau/nvkm/core/ioctl.c b/drm/nouveau/nvkm/core/ioctl.c index d777df5a6..b2277e19d 100644 --- a/drm/nouveau/nvkm/core/ioctl.c +++ b/drm/nouveau/nvkm/core/ioctl.c @@ -135,7 +135,7 @@ nvkm_ioctl_new(struct nvkm_client *client, } ret = -EEXIST; } - nvkm_object_fini(object, false); + nvkm_object_fini(object, NVKM_SUSPEND_NONE); } nvkm_object_del(&object); @@ -154,7 +154,7 @@ nvkm_ioctl_del(struct nvkm_client *client, nvif_ioctl(object, "delete size %d\n", size); if (!(ret = nvif_unvers(ret, &data, &size, args->none))) { nvif_ioctl(object, "delete\n"); - nvkm_object_fini(object, false); + nvkm_object_fini(object, NVKM_SUSPEND_NONE); nvkm_object_del(&object); } diff --git a/drm/nouveau/nvkm/core/object.c b/drm/nouveau/nvkm/core/object.c index 301a5e5b5..8ab0e4437 100644 --- a/drm/nouveau/nvkm/core/object.c +++ b/drm/nouveau/nvkm/core/object.c @@ -175,10 +175,24 @@ nvkm_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *gpuobj, return -ENODEV; } +const char * +nvkm_suspend_type_str(enum nvkm_suspend_type type) +{ + switch (type) { + case NVKM_SUSPEND_NONE: + return "fini"; + case NVKM_SUSPEND_SYSTEM: + return "suspend"; + case NVKM_SUSPEND_RUNTIME: + return "runtime suspend"; + } + return ""; +} + int -nvkm_object_fini(struct nvkm_object *object, bool suspend) +nvkm_object_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { - const char *action = suspend ? "suspend" : "fini"; + const char *action = nvkm_suspend_type_str(suspend); struct nvkm_object *child; s64 time; int ret; @@ -246,11 +260,11 @@ nvkm_object_init(struct nvkm_object *object) fail_child: list_for_each_entry_continue_reverse(child, &object->tree, head) - nvkm_object_fini(child, false); + nvkm_object_fini(child, NVKM_SUSPEND_NONE); fail: nvif_error(object, "init failed with %d\n", ret); if (object->func->fini) - object->func->fini(object, false); + object->func->fini(object, NVKM_SUSPEND_NONE); return ret; } diff --git a/drm/nouveau/nvkm/core/oproxy.c b/drm/nouveau/nvkm/core/oproxy.c index 16299837a..91bdd9ea3 100644 --- a/drm/nouveau/nvkm/core/oproxy.c +++ b/drm/nouveau/nvkm/core/oproxy.c @@ -106,7 +106,7 @@ nvkm_oproxy_sclass(struct nvkm_object *object, int index, } static int -nvkm_oproxy_fini(struct nvkm_object *object, bool suspend) +nvkm_oproxy_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nvkm_oproxy *oproxy = nvkm_oproxy(object); int ret; diff --git a/drm/nouveau/nvkm/core/subdev.c b/drm/nouveau/nvkm/core/subdev.c index 245990de1..95402b6c9 100644 --- a/drm/nouveau/nvkm/core/subdev.c +++ b/drm/nouveau/nvkm/core/subdev.c @@ -107,10 +107,10 @@ nvkm_subdev_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data) } int -nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_subdev_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type suspend) { struct nvkm_device *device = subdev->device; - const char *action = suspend ? "suspend" : "fini"; + const char *action = nvkm_suspend_type_str(suspend); s64 time; nvkm_trace(subdev, "%s running...\n", action); diff --git a/drm/nouveau/nvkm/engine/device/base.c b/drm/nouveau/nvkm/engine/device/base.c index c3c7159f3..4c5cdba82 100644 --- a/drm/nouveau/nvkm/engine/device/base.c +++ b/drm/nouveau/nvkm/engine/device/base.c @@ -2724,13 +2724,14 @@ nvkm_device_engine(struct nvkm_device *device, int index) } int -nvkm_device_fini(struct nvkm_device *device, bool suspend) +nvkm_device_fini(struct nvkm_device *device, enum nvkm_suspend_type suspend) { - const char *action = suspend ? "suspend" : "fini"; struct nvkm_subdev *subdev; int ret, i; s64 time; + const char *action = nvkm_suspend_type_str(suspend); + nvdev_trace(device, "%s running...\n", action); time = ktime_to_us(ktime_get()); @@ -2814,7 +2815,7 @@ nvkm_device_init(struct nvkm_device *device) if (ret) return ret; - nvkm_device_fini(device, false); + nvkm_device_fini(device, NVKM_SUSPEND_NONE); nvdev_trace(device, "init running...\n"); time = ktime_to_us(ktime_get()); @@ -2843,11 +2844,11 @@ nvkm_device_init(struct nvkm_device *device) fail_subdev: do { if ((subdev = nvkm_device_subdev(device, i))) - nvkm_subdev_fini(subdev, false); + nvkm_subdev_fini(subdev, NVKM_SUSPEND_NONE); } while (--i >= 0); fail: - nvkm_device_fini(device, false); + nvkm_device_fini(device, NVKM_SUSPEND_NONE); nvdev_error(device, "init failed with %d\n", ret); return ret; diff --git a/drm/nouveau/nvkm/engine/device/pci.c b/drm/nouveau/nvkm/engine/device/pci.c index f302d2b57..83e558b22 100644 --- a/drm/nouveau/nvkm/engine/device/pci.c +++ b/drm/nouveau/nvkm/engine/device/pci.c @@ -1575,7 +1575,7 @@ nvkm_device_pci_resource_size(struct nvkm_device *device, unsigned bar) } static void -nvkm_device_pci_fini(struct nvkm_device *device, bool suspend) +nvkm_device_pci_fini(struct nvkm_device *device, enum nvkm_suspend_type suspend) { struct nvkm_device_pci *pdev = nvkm_device_pci(device); if (suspend) { diff --git a/drm/nouveau/nvkm/engine/device/priv.h b/drm/nouveau/nvkm/engine/device/priv.h index d8be2f77a..f08d27708 100644 --- a/drm/nouveau/nvkm/engine/device/priv.h +++ b/drm/nouveau/nvkm/engine/device/priv.h @@ -56,5 +56,5 @@ int nvkm_device_ctor(const struct nvkm_device_func *, bool detect, bool mmio, u64 subdev_mask, struct nvkm_device *); int nvkm_device_init(struct nvkm_device *); -int nvkm_device_fini(struct nvkm_device *, bool suspend); +int nvkm_device_fini(struct nvkm_device *, enum nvkm_suspend_type); #endif diff --git a/drm/nouveau/nvkm/engine/device/tegra.c b/drm/nouveau/nvkm/engine/device/tegra.c index 0e372a190..cefed7718 100644 --- a/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drm/nouveau/nvkm/engine/device/tegra.c @@ -223,7 +223,8 @@ nvkm_device_tegra_intr(int irq, void *arg) } static void -nvkm_device_tegra_fini(struct nvkm_device *device, bool suspend) +nvkm_device_tegra_fini(struct nvkm_device *device, + enum nvkm_suspend_type suspend) { struct nvkm_device_tegra *tdev = nvkm_device_tegra(device); if (tdev->irq) { diff --git a/drm/nouveau/nvkm/engine/device/user.c b/drm/nouveau/nvkm/engine/device/user.c index 03c6d9aef..46f6c64ad 100644 --- a/drm/nouveau/nvkm/engine/device/user.c +++ b/drm/nouveau/nvkm/engine/device/user.c @@ -291,7 +291,7 @@ nvkm_udevice_map(struct nvkm_object *object, void *argv, u32 argc, } static int -nvkm_udevice_fini(struct nvkm_object *object, bool suspend) +nvkm_udevice_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nvkm_udevice *udev = nvkm_udevice(object); struct nvkm_device *device = udev->device; diff --git a/drm/nouveau/nvkm/engine/disp/base.c b/drm/nouveau/nvkm/engine/disp/base.c index cbd33e87b..b6a11eca8 100644 --- a/drm/nouveau/nvkm/engine/disp/base.c +++ b/drm/nouveau/nvkm/engine/disp/base.c @@ -214,7 +214,7 @@ nvkm_disp_intr(struct nvkm_engine *engine) } static int -nvkm_disp_fini(struct nvkm_engine *engine, bool suspend) +nvkm_disp_fini(struct nvkm_engine *engine, enum nvkm_suspend_type suspend) { struct nvkm_disp *disp = nvkm_disp(engine); struct nvkm_conn *conn; diff --git a/drm/nouveau/nvkm/engine/disp/channv50.c b/drm/nouveau/nvkm/engine/disp/channv50.c index bcf32d92e..043771de2 100644 --- a/drm/nouveau/nvkm/engine/disp/channv50.c +++ b/drm/nouveau/nvkm/engine/disp/channv50.c @@ -293,7 +293,7 @@ nv50_disp_chan_child_get(struct nvkm_object *object, int index, } static int -nv50_disp_chan_fini(struct nvkm_object *object, bool suspend) +nv50_disp_chan_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nv50_disp_chan *chan = nv50_disp_chan(object); chan->func->fini(chan); diff --git a/drm/nouveau/nvkm/engine/falcon.c b/drm/nouveau/nvkm/engine/falcon.c index 8675613e1..f15a7a938 100644 --- a/drm/nouveau/nvkm/engine/falcon.c +++ b/drm/nouveau/nvkm/engine/falcon.c @@ -93,7 +93,7 @@ nvkm_falcon_intr(struct nvkm_engine *engine) } static int -nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend) +nvkm_falcon_fini(struct nvkm_engine *engine, enum nvkm_suspend_type suspend) { struct nvkm_falcon *falcon = nvkm_falcon(engine); struct nvkm_device *device = falcon->engine.subdev.device; diff --git a/drm/nouveau/nvkm/engine/fifo/base.c b/drm/nouveau/nvkm/engine/fifo/base.c index c773caf21..b714bf01c 100644 --- a/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drm/nouveau/nvkm/engine/fifo/base.c @@ -279,7 +279,7 @@ nvkm_fifo_intr(struct nvkm_engine *engine) } static int -nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend) +nvkm_fifo_fini(struct nvkm_engine *engine, enum nvkm_suspend_type suspend) { struct nvkm_fifo *fifo = nvkm_fifo(engine); if (fifo->func->fini) diff --git a/drm/nouveau/nvkm/engine/fifo/chan.c b/drm/nouveau/nvkm/engine/fifo/chan.c index d83485385..9bd1ae91a 100644 --- a/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drm/nouveau/nvkm/engine/fifo/chan.c @@ -36,7 +36,8 @@ struct nvkm_fifo_chan_object { }; static int -nvkm_fifo_chan_child_fini(struct nvkm_oproxy *base, bool suspend) +nvkm_fifo_chan_child_fini(struct nvkm_oproxy *base, + enum nvkm_suspend_type suspend) { struct nvkm_fifo_chan_object *object container_of(base, typeof(*object), oproxy); @@ -294,7 +295,7 @@ nvkm_fifo_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) } static int -nvkm_fifo_chan_fini(struct nvkm_object *object, bool suspend) +nvkm_fifo_chan_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); chan->func->fini(chan); diff --git a/drm/nouveau/nvkm/engine/fifo/gf100.c b/drm/nouveau/nvkm/engine/fifo/gf100.c index 5a39e51d4..2ff9436a1 100644 --- a/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -162,7 +162,7 @@ gf100_fifo_recover_work(struct work_struct *w) for (todo = mask; engn = __ffs64(todo), todo; todo &= ~BIT_ULL(engn)) { if ((engine = nvkm_device_engine(device, engn))) { - nvkm_subdev_fini(&engine->subdev, false); + nvkm_subdev_fini(&engine->subdev, NVKM_SUSPEND_NONE); WARN_ON(nvkm_subdev_init(&engine->subdev)); } } diff --git a/drm/nouveau/nvkm/engine/fifo/gk104.c b/drm/nouveau/nvkm/engine/fifo/gk104.c index 5d4b695ca..4460e6240 100644 --- a/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -292,7 +292,7 @@ gk104_fifo_recover_work(struct work_struct *w) for (todo = engm; engn = __ffs(todo), todo; todo &= ~BIT(engn)) { if ((engine = fifo->engine[engn].engine)) { - nvkm_subdev_fini(&engine->subdev, false); + nvkm_subdev_fini(&engine->subdev, NVKM_SUSPEND_NONE); WARN_ON(nvkm_subdev_init(&engine->subdev)); } } diff --git a/drm/nouveau/nvkm/engine/gr/base.c b/drm/nouveau/nvkm/engine/gr/base.c index d41fb9452..25d6bbe70 100644 --- a/drm/nouveau/nvkm/engine/gr/base.c +++ b/drm/nouveau/nvkm/engine/gr/base.c @@ -143,7 +143,7 @@ nvkm_gr_init(struct nvkm_engine *engine) } static int -nvkm_gr_fini(struct nvkm_engine *engine, bool suspend) +nvkm_gr_fini(struct nvkm_engine *engine, enum nvkm_suspend_type suspend) { struct nvkm_gr *gr = nvkm_gr(engine); if (gr->func->fini) diff --git a/drm/nouveau/nvkm/engine/gr/nv04.c b/drm/nouveau/nvkm/engine/gr/nv04.c index 9c2e985dc..715bdd063 100644 --- a/drm/nouveau/nvkm/engine/gr/nv04.c +++ b/drm/nouveau/nvkm/engine/gr/nv04.c @@ -1158,7 +1158,7 @@ nv04_gr_chan_dtor(struct nvkm_object *object) } static int -nv04_gr_chan_fini(struct nvkm_object *object, bool suspend) +nv04_gr_chan_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nv04_gr_chan *chan = nv04_gr_chan(object); struct nv04_gr *gr = chan->gr; diff --git a/drm/nouveau/nvkm/engine/gr/nv10.c b/drm/nouveau/nvkm/engine/gr/nv10.c index 4ebbfbdd8..f0bb7ed2a 100644 --- a/drm/nouveau/nvkm/engine/gr/nv10.c +++ b/drm/nouveau/nvkm/engine/gr/nv10.c @@ -951,7 +951,7 @@ nv10_gr_context_switch(struct nv10_gr *gr) } static int -nv10_gr_chan_fini(struct nvkm_object *object, bool suspend) +nv10_gr_chan_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nv10_gr_chan *chan = nv10_gr_chan(object); struct nv10_gr *gr = chan->gr; diff --git a/drm/nouveau/nvkm/engine/gr/nv20.c b/drm/nouveau/nvkm/engine/gr/nv20.c index d837630a3..a0730b598 100644 --- a/drm/nouveau/nvkm/engine/gr/nv20.c +++ b/drm/nouveau/nvkm/engine/gr/nv20.c @@ -27,7 +27,7 @@ nv20_gr_chan_init(struct nvkm_object *object) } int -nv20_gr_chan_fini(struct nvkm_object *object, bool suspend) +nv20_gr_chan_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nv20_gr_chan *chan = nv20_gr_chan(object); struct nv20_gr *gr = chan->gr; diff --git a/drm/nouveau/nvkm/engine/gr/nv20.h b/drm/nouveau/nvkm/engine/gr/nv20.h index e57407a8a..cf8e5e2eb 100644 --- a/drm/nouveau/nvkm/engine/gr/nv20.h +++ b/drm/nouveau/nvkm/engine/gr/nv20.h @@ -31,5 +31,5 @@ struct nv20_gr_chan { void *nv20_gr_chan_dtor(struct nvkm_object *); int nv20_gr_chan_init(struct nvkm_object *); -int nv20_gr_chan_fini(struct nvkm_object *, bool); +int nv20_gr_chan_fini(struct nvkm_object *, enum nvkm_suspend_type); #endif diff --git a/drm/nouveau/nvkm/engine/gr/nv40.c b/drm/nouveau/nvkm/engine/gr/nv40.c index 5f1ad8344..e98c7f387 100644 --- a/drm/nouveau/nvkm/engine/gr/nv40.c +++ b/drm/nouveau/nvkm/engine/gr/nv40.c @@ -89,7 +89,7 @@ nv40_gr_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, } static int -nv40_gr_chan_fini(struct nvkm_object *object, bool suspend) +nv40_gr_chan_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nv40_gr_chan *chan = nv40_gr_chan(object); struct nv40_gr *gr = chan->gr; diff --git a/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drm/nouveau/nvkm/engine/mpeg/nv44.c index c3cf02ed4..6c540bc92 100644 --- a/drm/nouveau/nvkm/engine/mpeg/nv44.c +++ b/drm/nouveau/nvkm/engine/mpeg/nv44.c @@ -65,7 +65,7 @@ nv44_mpeg_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, } static int -nv44_mpeg_chan_fini(struct nvkm_object *object, bool suspend) +nv44_mpeg_chan_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nv44_mpeg_chan *chan = nv44_mpeg_chan(object); diff --git a/drm/nouveau/nvkm/engine/pm/base.c b/drm/nouveau/nvkm/engine/pm/base.c index b2785bee4..e87e0c311 100644 --- a/drm/nouveau/nvkm/engine/pm/base.c +++ b/drm/nouveau/nvkm/engine/pm/base.c @@ -820,7 +820,7 @@ nvkm_perfdom_new(struct nvkm_pm *pm, const char *name, u32 mask, } static int -nvkm_pm_fini(struct nvkm_engine *engine, bool suspend) +nvkm_pm_fini(struct nvkm_engine *engine, enum nvkm_suspend_type suspend) { struct nvkm_pm *pm = nvkm_pm(engine); if (pm->func->fini) diff --git a/drm/nouveau/nvkm/engine/sec2/base.c b/drm/nouveau/nvkm/engine/sec2/base.c index 1b49e5b67..22d66f356 100644 --- a/drm/nouveau/nvkm/engine/sec2/base.c +++ b/drm/nouveau/nvkm/engine/sec2/base.c @@ -87,7 +87,7 @@ nvkm_sec2_oneinit(struct nvkm_engine *engine) } static int -nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend) +nvkm_sec2_fini(struct nvkm_engine *engine, enum nvkm_suspend_type suspend) { struct nvkm_sec2 *sec2 = nvkm_sec2(engine); flush_work(&sec2->work); diff --git a/drm/nouveau/nvkm/engine/xtensa.c b/drm/nouveau/nvkm/engine/xtensa.c index 70549381e..9e7bcac13 100644 --- a/drm/nouveau/nvkm/engine/xtensa.c +++ b/drm/nouveau/nvkm/engine/xtensa.c @@ -76,7 +76,7 @@ nvkm_xtensa_intr(struct nvkm_engine *engine) } static int -nvkm_xtensa_fini(struct nvkm_engine *engine, bool suspend) +nvkm_xtensa_fini(struct nvkm_engine *engine, enum nvkm_suspend_type suspend) { struct nvkm_xtensa *xtensa = nvkm_xtensa(engine); struct nvkm_device *device = xtensa->engine.subdev.device; diff --git a/drm/nouveau/nvkm/subdev/bar/base.c b/drm/nouveau/nvkm/subdev/bar/base.c index 209a6a408..d2ddb8a50 100644 --- a/drm/nouveau/nvkm/subdev/bar/base.c +++ b/drm/nouveau/nvkm/subdev/bar/base.c @@ -90,7 +90,7 @@ nvkm_bar_bar2_init(struct nvkm_device *device) } static int -nvkm_bar_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_bar_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type type) { struct nvkm_bar *bar = nvkm_bar(subdev); if (bar->func->bar1.fini) diff --git a/drm/nouveau/nvkm/subdev/clk/base.c b/drm/nouveau/nvkm/subdev/clk/base.c index ba6a868d4..2b15bc74b 100644 --- a/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drm/nouveau/nvkm/subdev/clk/base.c @@ -576,7 +576,7 @@ nvkm_clk_read(struct nvkm_clk *clk, enum nv_clk_src src) } static int -nvkm_clk_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_clk_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type type) { struct nvkm_clk *clk = nvkm_clk(subdev); nvkm_notify_put(&clk->pwrsrc_ntfy); diff --git a/drm/nouveau/nvkm/subdev/devinit/base.c b/drm/nouveau/nvkm/subdev/devinit/base.c index 4756019dd..5a58f4dec 100644 --- a/drm/nouveau/nvkm/subdev/devinit/base.c +++ b/drm/nouveau/nvkm/subdev/devinit/base.c @@ -66,7 +66,7 @@ nvkm_devinit_post(struct nvkm_devinit *init, u64 *disable) } static int -nvkm_devinit_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_devinit_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type suspend) { struct nvkm_devinit *init = nvkm_devinit(subdev); /* force full reinit on resume */ diff --git a/drm/nouveau/nvkm/subdev/fault/base.c b/drm/nouveau/nvkm/subdev/fault/base.c index ca251560d..6b2f9d101 100644 --- a/drm/nouveau/nvkm/subdev/fault/base.c +++ b/drm/nouveau/nvkm/subdev/fault/base.c @@ -67,7 +67,7 @@ nvkm_fault_intr(struct nvkm_subdev *subdev) } static int -nvkm_fault_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_fault_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type type) { struct nvkm_fault *fault = nvkm_fault(subdev); if (fault->func->fini) diff --git a/drm/nouveau/nvkm/subdev/fault/user.c b/drm/nouveau/nvkm/subdev/fault/user.c index ac835c958..3400add40 100644 --- a/drm/nouveau/nvkm/subdev/fault/user.c +++ b/drm/nouveau/nvkm/subdev/fault/user.c @@ -52,7 +52,7 @@ nvkm_ufault_ntfy(struct nvkm_object *object, u32 type, } static int -nvkm_ufault_fini(struct nvkm_object *object, bool suspend) +nvkm_ufault_fini(struct nvkm_object *object, enum nvkm_suspend_type suspend) { struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object); buffer->fault->func->buffer.fini(buffer); diff --git a/drm/nouveau/nvkm/subdev/gpio/base.c b/drm/nouveau/nvkm/subdev/gpio/base.c index 914276410..c71426919 100644 --- a/drm/nouveau/nvkm/subdev/gpio/base.c +++ b/drm/nouveau/nvkm/subdev/gpio/base.c @@ -162,7 +162,7 @@ nvkm_gpio_intr(struct nvkm_subdev *subdev) } static int -nvkm_gpio_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_gpio_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type type) { struct nvkm_gpio *gpio = nvkm_gpio(subdev); u32 mask = (1ULL << gpio->func->lines) - 1; diff --git a/drm/nouveau/nvkm/subdev/i2c/base.c b/drm/nouveau/nvkm/subdev/i2c/base.c index 719345074..0fdab8515 100644 --- a/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/drm/nouveau/nvkm/subdev/i2c/base.c @@ -156,7 +156,7 @@ nvkm_i2c_intr(struct nvkm_subdev *subdev) } static int -nvkm_i2c_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_i2c_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type type) { struct nvkm_i2c *i2c = nvkm_i2c(subdev); struct nvkm_i2c_pad *pad; diff --git a/drm/nouveau/nvkm/subdev/instmem/base.c b/drm/nouveau/nvkm/subdev/instmem/base.c index 364ea4492..3f0587d6b 100644 --- a/drm/nouveau/nvkm/subdev/instmem/base.c +++ b/drm/nouveau/nvkm/subdev/instmem/base.c @@ -157,7 +157,7 @@ nvkm_instmem_boot(struct nvkm_instmem *imem) } static int -nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_instmem_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type suspend) { struct nvkm_instmem *imem = nvkm_instmem(subdev); struct nvkm_instobj *iobj; diff --git a/drm/nouveau/nvkm/subdev/mc/base.c b/drm/nouveau/nvkm/subdev/mc/base.c index 0e57ab2a7..7fef7331f 100644 --- a/drm/nouveau/nvkm/subdev/mc/base.c +++ b/drm/nouveau/nvkm/subdev/mc/base.c @@ -175,7 +175,7 @@ nvkm_mc_enabled(struct nvkm_device *device, enum nvkm_devidx devidx) static int -nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_mc_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type type) { nvkm_mc_intr_unarm(subdev->device); return 0; diff --git a/drm/nouveau/nvkm/subdev/pci/base.c b/drm/nouveau/nvkm/subdev/pci/base.c index ee2431a78..9db880898 100644 --- a/drm/nouveau/nvkm/subdev/pci/base.c +++ b/drm/nouveau/nvkm/subdev/pci/base.c @@ -84,7 +84,7 @@ nvkm_pci_intr(int irq, void *arg) } static int -nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_pci_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type suspend) { struct nvkm_pci *pci = nvkm_pci(subdev); diff --git a/drm/nouveau/nvkm/subdev/pmu/base.c b/drm/nouveau/nvkm/subdev/pmu/base.c index ea2e11771..6df9c5586 100644 --- a/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drm/nouveau/nvkm/subdev/pmu/base.c @@ -77,7 +77,7 @@ nvkm_pmu_intr(struct nvkm_subdev *subdev) } static int -nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_pmu_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type type) { struct nvkm_pmu *pmu = nvkm_pmu(subdev); diff --git a/drm/nouveau/nvkm/subdev/secboot/base.c b/drm/nouveau/nvkm/subdev/secboot/base.c index ee29c6c11..95a65e626 100644 --- a/drm/nouveau/nvkm/subdev/secboot/base.c +++ b/drm/nouveau/nvkm/subdev/secboot/base.c @@ -161,7 +161,7 @@ nvkm_secboot_oneinit(struct nvkm_subdev *subdev) } static int -nvkm_secboot_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_secboot_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type suspend) { struct nvkm_secboot *sb = nvkm_secboot(subdev); int ret = 0; diff --git a/drm/nouveau/nvkm/subdev/therm/base.c b/drm/nouveau/nvkm/subdev/therm/base.c index 4a4d1e224..66884a697 100644 --- a/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drm/nouveau/nvkm/subdev/therm/base.c @@ -341,7 +341,7 @@ nvkm_therm_intr(struct nvkm_subdev *subdev) } static int -nvkm_therm_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_therm_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type suspend) { struct nvkm_therm *therm = nvkm_therm(subdev); diff --git a/drm/nouveau/nvkm/subdev/timer/base.c b/drm/nouveau/nvkm/subdev/timer/base.c index dd9220336..3251c9de0 100644 --- a/drm/nouveau/nvkm/subdev/timer/base.c +++ b/drm/nouveau/nvkm/subdev/timer/base.c @@ -149,7 +149,7 @@ nvkm_timer_intr(struct nvkm_subdev *subdev) } static int -nvkm_timer_fini(struct nvkm_subdev *subdev, bool suspend) +nvkm_timer_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type type) { struct nvkm_timer *tmr = nvkm_timer(subdev); tmr->func->alarm_fini(tmr); diff --git a/lib/drm.c b/lib/drm.c index 39bc36955..6af0babe3 100644 --- a/lib/drm.c +++ b/lib/drm.c @@ -74,7 +74,7 @@ drm_client_resume(void *priv) } static int -drm_client_suspend(void *priv) +drm_client_suspend(void *priv, bool runtime) { return -ENOSYS; } diff --git a/lib/main.c b/lib/main.c index 2e127c250..9a1cbeb87 100644 --- a/lib/main.c +++ b/lib/main.c @@ -250,10 +250,12 @@ os_client_resume(void *priv) } static int -os_client_suspend(void *priv) +os_client_suspend(void *priv, bool runtime) { struct nvkm_client *client = priv; - return nvkm_object_fini(&client->object, true); + enum nvkm_suspend_type suspend + runtime ? NVKM_SUSPEND_RUNTIME : NVKM_SUSPEND_SYSTEM; + return nvkm_object_fini(&client->object, suspend); } static void diff --git a/lib/null.c b/lib/null.c index 912d139fa..2c08b1b61 100644 --- a/lib/null.c +++ b/lib/null.c @@ -88,10 +88,12 @@ null_client_resume(void *priv) } static int -null_client_suspend(void *priv) +null_client_suspend(void *priv, bool runtime) { struct nvkm_client *client = priv; - return nvkm_object_fini(&client->object, true); + enum nvkm_suspend_type suspend + runtime ? NVKM_SUSPEND_RUNTIME : NVKM_SUSPEND_SYSTEM; + return nvkm_object_fini(&client->object, suspend); } static void -- 2.21.0
Karol Herbst
2019-Sep-23 20:39 UTC
[Nouveau] [PATCH 7/8] pci: set the pcie link speed to 8.0 when suspending
Apperantly things go south if we suspend the device with a PCIe link speed set to 2.5. Fixes runtime suspend on my gp107. This all looks like some bug inside the pci subsystem and I would prefer a fix there instead of nouveau, but maybe there is no real nice way of doing that outside of drivers? v2: squashed together patch 4 and 5 v3: only restore pcie speed on machines with runpm add NvRunpmWorkaround config option to disable the workaround v4: only run the code on suspend always put the card into 8.0 mode, not what nouveau detected on load v5: only enable workaround on runtime suspend Signed-off-by: Karol Herbst <kherbst at redhat.com> Reviewed-by: Lyude Paul <lyude at redhat.com> (v4) --- drm/nouveau/include/nvkm/core/device.h | 2 ++ drm/nouveau/include/nvkm/subdev/pci.h | 3 ++- drm/nouveau/nouveau_drm.c | 1 + drm/nouveau/nvkm/subdev/clk/base.c | 2 +- drm/nouveau/nvkm/subdev/pci/base.c | 2 ++ drm/nouveau/nvkm/subdev/pci/pcie.c | 28 ++++++++++++++++++++++---- drm/nouveau/nvkm/subdev/pci/priv.h | 1 + 7 files changed, 33 insertions(+), 6 deletions(-) diff --git a/drm/nouveau/include/nvkm/core/device.h b/drm/nouveau/include/nvkm/core/device.h index ef8e652a0..173dfcb31 100644 --- a/drm/nouveau/include/nvkm/core/device.h +++ b/drm/nouveau/include/nvkm/core/device.h @@ -126,6 +126,8 @@ struct nvkm_device { u8 chiprev; u32 crystal; + bool has_runpm; + struct { struct notifier_block nb; } acpi; diff --git a/drm/nouveau/include/nvkm/subdev/pci.h b/drm/nouveau/include/nvkm/subdev/pci.h index 4803a4fad..10d361e56 100644 --- a/drm/nouveau/include/nvkm/subdev/pci.h +++ b/drm/nouveau/include/nvkm/subdev/pci.h @@ -52,5 +52,6 @@ int gk104_pci_new(struct nvkm_device *, int, struct nvkm_pci **); int gp100_pci_new(struct nvkm_device *, int, struct nvkm_pci **); /* pcie functions */ -int nvkm_pcie_set_link(struct nvkm_pci *, enum nvkm_pcie_speed, u8 width); +int nvkm_pcie_set_link(struct nvkm_pci *, enum nvkm_pcie_speed, u8 width, + bool save); #endif diff --git a/drm/nouveau/nouveau_drm.c b/drm/nouveau/nouveau_drm.c index 0162cea8e..dce8e7fe6 100644 --- a/drm/nouveau/nouveau_drm.c +++ b/drm/nouveau/nouveau_drm.c @@ -676,6 +676,7 @@ static int nouveau_drm_probe(struct pci_dev *pdev, if (nouveau_atomic) driver_pci.driver_features |= DRIVER_ATOMIC; + device->has_runpm = nouveau_pmops_runtime(); drm_dev = drm_dev_alloc(&driver_pci, &pdev->dev); if (IS_ERR(drm_dev)) { diff --git a/drm/nouveau/nvkm/subdev/clk/base.c b/drm/nouveau/nvkm/subdev/clk/base.c index 2b15bc74b..2d1b10f6c 100644 --- a/drm/nouveau/nvkm/subdev/clk/base.c +++ b/drm/nouveau/nvkm/subdev/clk/base.c @@ -277,7 +277,7 @@ nvkm_pstate_prog(struct nvkm_clk *clk, int pstatei) nvkm_debug(subdev, "setting performance state %d\n", pstatei); clk->pstate = pstatei; - nvkm_pcie_set_link(pci, pstate->pcie_speed, pstate->pcie_width); + nvkm_pcie_set_link(pci, pstate->pcie_speed, pstate->pcie_width, true); if (fb && fb->ram && fb->ram->func->calc) { struct nvkm_ram *ram = fb->ram; diff --git a/drm/nouveau/nvkm/subdev/pci/base.c b/drm/nouveau/nvkm/subdev/pci/base.c index 9db880898..986d61ce9 100644 --- a/drm/nouveau/nvkm/subdev/pci/base.c +++ b/drm/nouveau/nvkm/subdev/pci/base.c @@ -90,6 +90,8 @@ nvkm_pci_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_type suspend) if (pci->agp.bridge) nvkm_agp_fini(pci); + else if (pci_is_pcie(pci->pdev)) + nvkm_pcie_fini(pci, suspend); return 0; } diff --git a/drm/nouveau/nvkm/subdev/pci/pcie.c b/drm/nouveau/nvkm/subdev/pci/pcie.c index ed015b252..0363f54ac 100644 --- a/drm/nouveau/nvkm/subdev/pci/pcie.c +++ b/drm/nouveau/nvkm/subdev/pci/pcie.c @@ -23,6 +23,8 @@ */ #include "priv.h" +#include <core/option.h> + static char *nvkm_pcie_speeds[] = { "2.5GT/s", "5.0GT/s", @@ -106,11 +108,26 @@ nvkm_pcie_init(struct nvkm_pci *pci) pci->func->pcie.init(pci); if (pci->pcie.speed != -1) - nvkm_pcie_set_link(pci, pci->pcie.speed, pci->pcie.width); + nvkm_pcie_set_link(pci, pci->pcie.speed, + pci->pcie.width, false); return 0; } +int +nvkm_pcie_fini(struct nvkm_pci *pci, enum nvkm_suspend_type suspend) +{ + struct nvkm_device *device = pci->subdev.device; + + if (!device->has_runpm || suspend != NVKM_SUSPEND_RUNTIME) + return 0; + + if (!nvkm_boolopt(device->cfgopt, "NvRunpmWorkaround", true)) + return 0; + + return nvkm_pcie_set_link(pci, NVKM_PCIE_SPEED_8_0, 16, false); +} + enum nvkm_pci_aspm nvkm_pcie_aspm_off(struct nvkm_pci *pci, enum nvkm_pci_aspm states) { @@ -120,7 +137,8 @@ nvkm_pcie_aspm_off(struct nvkm_pci *pci, enum nvkm_pci_aspm states) } int -nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width) +nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width, + bool save) { struct nvkm_subdev *subdev = &pci->subdev; enum nvkm_pcie_speed cur_speed, max_speed; @@ -155,8 +173,10 @@ nvkm_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width) speed = max_speed; } - pci->pcie.speed = speed; - pci->pcie.width = width; + if (save) { + pci->pcie.speed = speed; + pci->pcie.width = width; + } if (speed == cur_speed) { nvkm_debug(subdev, "requested matches current speed\n"); diff --git a/drm/nouveau/nvkm/subdev/pci/priv.h b/drm/nouveau/nvkm/subdev/pci/priv.h index 17be1d563..120ba2138 100644 --- a/drm/nouveau/nvkm/subdev/pci/priv.h +++ b/drm/nouveau/nvkm/subdev/pci/priv.h @@ -71,4 +71,5 @@ int gk104_pcie_version_supported(struct nvkm_pci *); int nvkm_pcie_oneinit(struct nvkm_pci *); int nvkm_pcie_init(struct nvkm_pci *); +int nvkm_pcie_fini(struct nvkm_pci *, enum nvkm_suspend_type); #endif -- 2.21.0
Karol Herbst
2019-Sep-23 20:39 UTC
[Nouveau] [PATCH 8/8] drm: abort runtime suspend if we hit an error
Signed-off-by: Karol Herbst <kherbst at redhat.com> --- drm/nouveau/nouveau_drm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drm/nouveau/nouveau_drm.c b/drm/nouveau/nouveau_drm.c index dce8e7fe6..ad1311b21 100644 --- a/drm/nouveau/nouveau_drm.c +++ b/drm/nouveau/nouveau_drm.c @@ -911,6 +911,7 @@ nouveau_pmops_runtime_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct nouveau_drm *drm = nouveau_drm(drm_dev); int ret; if (!nouveau_pmops_runtime()) { @@ -921,6 +922,10 @@ nouveau_pmops_runtime_suspend(struct device *dev) drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; nouveau_switcheroo_optimus_dsm(); ret = nouveau_do_suspend(drm_dev, true); + if (ret) { + NV_ERROR(drm, "suspend failed with: %d\n", ret); + return ret; + } pci_save_state(pdev); pci_disable_device(pdev); pci_ignore_hotplug(pdev); -- 2.21.0