All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] Add workaround for fixing runpm
@ 2019-09-23 20:39 Karol Herbst
       [not found] ` <20190923203951.1652-1-kherbst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: Karol Herbst @ 2019-09-23 20:39 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/8] pci: disable ASPM before changing the link speed
       [not found] ` <20190923203951.1652-1-kherbst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2019-09-23 20:39   ` Karol Herbst
  2019-09-23 20:39   ` [PATCH 2/8] pci/gk104: enable dl_mgr safe mode Karol Herbst
                     ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Karol Herbst @ 2019-09-23 20:39 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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@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

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/8] pci/gk104: enable dl_mgr safe mode
       [not found] ` <20190923203951.1652-1-kherbst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2019-09-23 20:39   ` [PATCH 1/8] pci: disable ASPM before changing the link speed Karol Herbst
@ 2019-09-23 20:39   ` Karol Herbst
  2019-09-23 20:39   ` [PATCH 3/8] pci/gk104: wait for ltssm idle before changing the link Karol Herbst
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Karol Herbst @ 2019-09-23 20:39 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

no idea why and what it does, taken from nvgpu

Signed-off-by: Karol Herbst <kherbst@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

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/8] pci/gk104: wait for ltssm idle before changing the link
       [not found] ` <20190923203951.1652-1-kherbst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2019-09-23 20:39   ` [PATCH 1/8] pci: disable ASPM before changing the link speed Karol Herbst
  2019-09-23 20:39   ` [PATCH 2/8] pci/gk104: enable dl_mgr safe mode Karol Herbst
@ 2019-09-23 20:39   ` Karol Herbst
  2019-09-23 20:39   ` [PATCH 4/8] pci: enable pcie link changes for pascal Karol Herbst
                     ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Karol Herbst @ 2019-09-23 20:39 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

taken from nvgpu

v2: return -EBUSY when the timeout is reached

Signed-off-by: Karol Herbst <kherbst@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

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/8] pci: enable pcie link changes for pascal
       [not found] ` <20190923203951.1652-1-kherbst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (2 preceding siblings ...)
  2019-09-23 20:39   ` [PATCH 3/8] pci/gk104: wait for ltssm idle before changing the link Karol Herbst
@ 2019-09-23 20:39   ` Karol Herbst
  2019-09-23 20:39   ` [PATCH 5/8] drm: set power_state to DRM_SWITCH_POWER_CHANGING before changing Karol Herbst
                     ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Karol Herbst @ 2019-09-23 20:39 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

v2: add force disable ASPM func pointer

Signed-off-by: Karol Herbst <kherbst@redhat.com>
Reviewed-by: Lyude Paul <lyude@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

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/8] drm: set power_state to DRM_SWITCH_POWER_CHANGING before changing
       [not found] ` <20190923203951.1652-1-kherbst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (3 preceding siblings ...)
  2019-09-23 20:39   ` [PATCH 4/8] pci: enable pcie link changes for pascal Karol Herbst
@ 2019-09-23 20:39   ` Karol Herbst
  2019-09-23 20:39   ` [PATCH 6/8] drm: be explicit about runtime suspend in fini Karol Herbst
                     ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Karol Herbst @ 2019-09-23 20:39 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

---
 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

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/8] drm: be explicit about runtime suspend in fini
       [not found] ` <20190923203951.1652-1-kherbst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (4 preceding siblings ...)
  2019-09-23 20:39   ` [PATCH 5/8] drm: set power_state to DRM_SWITCH_POWER_CHANGING before changing Karol Herbst
@ 2019-09-23 20:39   ` Karol Herbst
  2019-09-23 20:39   ` [PATCH 7/8] pci: set the pcie link speed to 8.0 when suspending Karol Herbst
  2019-09-23 20:39   ` [PATCH 8/8] drm: abort runtime suspend if we hit an error Karol Herbst
  7 siblings, 0 replies; 9+ messages in thread
From: Karol Herbst @ 2019-09-23 20:39 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

Allows fini functions to check if we do a real system suspend or just
runtime suspending the GPU.

Signed-off-by: Karol Herbst <kherbst@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

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/8] pci: set the pcie link speed to 8.0 when suspending
       [not found] ` <20190923203951.1652-1-kherbst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (5 preceding siblings ...)
  2019-09-23 20:39   ` [PATCH 6/8] drm: be explicit about runtime suspend in fini Karol Herbst
@ 2019-09-23 20:39   ` Karol Herbst
  2019-09-23 20:39   ` [PATCH 8/8] drm: abort runtime suspend if we hit an error Karol Herbst
  7 siblings, 0 replies; 9+ messages in thread
From: Karol Herbst @ 2019-09-23 20:39 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

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@redhat.com>
Reviewed-by: Lyude Paul <lyude@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

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 8/8] drm: abort runtime suspend if we hit an error
       [not found] ` <20190923203951.1652-1-kherbst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (6 preceding siblings ...)
  2019-09-23 20:39   ` [PATCH 7/8] pci: set the pcie link speed to 8.0 when suspending Karol Herbst
@ 2019-09-23 20:39   ` Karol Herbst
  7 siblings, 0 replies; 9+ messages in thread
From: Karol Herbst @ 2019-09-23 20:39 UTC (permalink / raw)
  To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

Signed-off-by: Karol Herbst <kherbst@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

_______________________________________________
Nouveau mailing list
Nouveau@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/nouveau

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-09-23 20:39 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-23 20:39 [PATCH 0/8] Add workaround for fixing runpm Karol Herbst
     [not found] ` <20190923203951.1652-1-kherbst-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2019-09-23 20:39   ` [PATCH 1/8] pci: disable ASPM before changing the link speed Karol Herbst
2019-09-23 20:39   ` [PATCH 2/8] pci/gk104: enable dl_mgr safe mode Karol Herbst
2019-09-23 20:39   ` [PATCH 3/8] pci/gk104: wait for ltssm idle before changing the link Karol Herbst
2019-09-23 20:39   ` [PATCH 4/8] pci: enable pcie link changes for pascal Karol Herbst
2019-09-23 20:39   ` [PATCH 5/8] drm: set power_state to DRM_SWITCH_POWER_CHANGING before changing Karol Herbst
2019-09-23 20:39   ` [PATCH 6/8] drm: be explicit about runtime suspend in fini Karol Herbst
2019-09-23 20:39   ` [PATCH 7/8] pci: set the pcie link speed to 8.0 when suspending Karol Herbst
2019-09-23 20:39   ` [PATCH 8/8] drm: abort runtime suspend if we hit an error Karol Herbst

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.