[1/6] pci: disable ASPM before changing the link speed

Submitted by Karol Herbst on Sept. 17, 2019, 9 p.m.

Details

Message ID 20190917210050.24457-2-kherbst@redhat.com
State New
Headers show
Series "Add workaround for fixing runpm" ( rev: 1 ) in Nouveau

Not browsing as part of any series.

Commit Message

Karol Herbst Sept. 17, 2019, 9 p.m.
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   |  8 ++++++++
 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, 38 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drm/nouveau/nvkm/subdev/pci/g84.c b/drm/nouveau/nvkm/subdev/pci/g84.c
index 62438d892..6cf0f1c89 100644
--- a/drm/nouveau/nvkm/subdev/pci/g84.c
+++ b/drm/nouveau/nvkm/subdev/pci/g84.c
@@ -122,6 +122,13 @@  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 +154,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);