[alsa-devel] [PATCH v4 1/2] PCI: Add a helper to check Power Resource Requirements _PR3 existence
A driver may want to know the existence of _PR3, to choose different runtime suspend behavior. A user will be add in next patch.
This is mostly the same as nouveau_pr3_present().
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com --- v4: - Let caller to find its upstream port device.
drivers/pci/pci.c | 16 ++++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 18 insertions(+)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e7982af9a5d8..d03f624d8928 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5856,6 +5856,22 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode, return 0; }
+bool pci_pr3_present(struct pci_dev *pdev) +{ + struct acpi_device *adev; + + if (acpi_disabled) + return false; + + adev = ACPI_COMPANION(&pdev->dev); + if (!adev) + return false; + + return adev->power.flags.power_resources && + acpi_has_method(adev->handle, "_PR3"); +} +EXPORT_SYMBOL_GPL(pci_pr3_present); + /** * pci_add_dma_alias - Add a DMA devfn alias for a device * @dev: the PCI device for which alias is added diff --git a/include/linux/pci.h b/include/linux/pci.h index f9088c89a534..1d15c5d49cdd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2310,9 +2310,11 @@ struct irq_domain *pci_host_bridge_acpi_msi_domain(struct pci_bus *bus);
void pci_msi_register_fwnode_provider(struct fwnode_handle *(*fn)(struct device *)); +bool pci_pr3_present(struct pci_dev *pdev); #else static inline struct irq_domain * pci_host_bridge_acpi_msi_domain(struct pci_bus *bus) { return NULL; } +static bool pci_pr3_present(struct pci_dev *pdev) { return false; } #endif
#ifdef CONFIG_EEH
Nvidia proprietary driver doesn't support runtime power management, so when a user only wants to use the integrated GPU, it's a common practice to let dGPU not to bind any driver, and let its upstream port to be runtime suspended. At the end of runtime suspension the port uses platform power management to disable power through _OFF method of power resource, which is listed by _PR3.
After commit b516ea586d71 ("PCI: Enable NVIDIA HDA controllers"), when the dGPU comes with an HDA function, the HDA won't be suspended if the dGPU is unbound, so the power resource can't be turned off by its upstream port driver.
Commit 37a3a98ef601 ("ALSA: hda - Enable runtime PM only for discrete GPU") only allows HDA to be runtime suspended once GPU is bound, to keep APU's HDA working.
However, HDA on dGPU isn't that useful if dGPU is not bound to any driver. So let's relax the runtime suspend requirement for dGPU's HDA function, to disable the power source to save lots of power.
BugLink: https://bugs.launchpad.net/bugs/1840835 Fixes: b516ea586d71 ("PCI: Enable NVIDIA HDA controllers") Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com --- v4: - Find upstream port, it's callee's responsibility now. v3: - Make changelog more clear. v2: - Change wording. - Rebase to Tiwai's branch. sound/pci/hda/hda_intel.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 240f4ca76391..e63b871343e5 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1280,11 +1280,17 @@ static void init_vga_switcheroo(struct azx *chip) { struct hda_intel *hda = container_of(chip, struct hda_intel, chip); struct pci_dev *p = get_bound_vga(chip->pci); + struct pci_dev *parent; if (p) { dev_info(chip->card->dev, "Handle vga_switcheroo audio client\n"); hda->use_vga_switcheroo = 1; - chip->bus.keep_power = 1; /* cleared in either gpu_bound op or codec probe */ + + /* cleared in either gpu_bound op or codec probe, or when its + * upstream port has _PR3 (i.e. dGPU). + */ + parent = pci_upstream_bridge(p); + chip->bus.keep_power = parent ? !pci_pr3_present(parent) : 1; chip->driver_caps |= AZX_DCAPS_PM_RUNTIME; pci_dev_put(p); }
Add pci_pr3_present() to check whether the platform supplies _PR3 to tell us which power resources the device depends on when in D3hot. This information is useful to let drivers choose different runtime suspend behavior. A user will be add in next patch.
This is mostly the same as nouveau_pr3_present().
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com --- v5: - Add wording suggestion from Bjorn. v4: - Let caller to find its upstream port device.
drivers/pci/pci.c | 16 ++++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 18 insertions(+)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e7982af9a5d8..d03f624d8928 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5856,6 +5856,22 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode, return 0; }
+bool pci_pr3_present(struct pci_dev *pdev) +{ + struct acpi_device *adev; + + if (acpi_disabled) + return false; + + adev = ACPI_COMPANION(&pdev->dev); + if (!adev) + return false; + + return adev->power.flags.power_resources && + acpi_has_method(adev->handle, "_PR3"); +} +EXPORT_SYMBOL_GPL(pci_pr3_present); + /** * pci_add_dma_alias - Add a DMA devfn alias for a device * @dev: the PCI device for which alias is added diff --git a/include/linux/pci.h b/include/linux/pci.h index f9088c89a534..1d15c5d49cdd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2310,9 +2310,11 @@ struct irq_domain *pci_host_bridge_acpi_msi_domain(struct pci_bus *bus);
void pci_msi_register_fwnode_provider(struct fwnode_handle *(*fn)(struct device *)); +bool pci_pr3_present(struct pci_dev *pdev); #else static inline struct irq_domain * pci_host_bridge_acpi_msi_domain(struct pci_bus *bus) { return NULL; } +static bool pci_pr3_present(struct pci_dev *pdev) { return false; } #endif
#ifdef CONFIG_EEH
On Wed, Sep 25, 2019 at 07:43:53PM +0800, Kai-Heng Feng wrote:
Add pci_pr3_present() to check whether the platform supplies _PR3 to tell us which power resources the device depends on when in D3hot. This information is useful to let drivers choose different runtime suspend behavior. A user will be add in next patch.
This is mostly the same as nouveau_pr3_present().
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com
Acked-by: Bjorn Helgaas bhelgaas@google.com
I assume Takashi will merge this along with the ALSA patch.
v5:
- Add wording suggestion from Bjorn.
v4:
- Let caller to find its upstream port device.
drivers/pci/pci.c | 16 ++++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 18 insertions(+)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e7982af9a5d8..d03f624d8928 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5856,6 +5856,22 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode, return 0; }
+bool pci_pr3_present(struct pci_dev *pdev) +{
- struct acpi_device *adev;
- if (acpi_disabled)
return false;
- adev = ACPI_COMPANION(&pdev->dev);
- if (!adev)
return false;
- return adev->power.flags.power_resources &&
acpi_has_method(adev->handle, "_PR3");
+} +EXPORT_SYMBOL_GPL(pci_pr3_present);
/**
- pci_add_dma_alias - Add a DMA devfn alias for a device
- @dev: the PCI device for which alias is added
diff --git a/include/linux/pci.h b/include/linux/pci.h index f9088c89a534..1d15c5d49cdd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -2310,9 +2310,11 @@ struct irq_domain *pci_host_bridge_acpi_msi_domain(struct pci_bus *bus);
void pci_msi_register_fwnode_provider(struct fwnode_handle *(*fn)(struct device *)); +bool pci_pr3_present(struct pci_dev *pdev); #else static inline struct irq_domain * pci_host_bridge_acpi_msi_domain(struct pci_bus *bus) { return NULL; } +static bool pci_pr3_present(struct pci_dev *pdev) { return false; } #endif
#ifdef CONFIG_EEH
2.17.1
Hi Takashi,
On Sep 25, 2019, at 19:32, Kai-Heng Feng kai.heng.feng@canonical.com wrote:
Nvidia proprietary driver doesn't support runtime power management, so when a user only wants to use the integrated GPU, it's a common practice to let dGPU not to bind any driver, and let its upstream port to be runtime suspended. At the end of runtime suspension the port uses platform power management to disable power through _OFF method of power resource, which is listed by _PR3.
After commit b516ea586d71 ("PCI: Enable NVIDIA HDA controllers"), when the dGPU comes with an HDA function, the HDA won't be suspended if the dGPU is unbound, so the power resource can't be turned off by its upstream port driver.
Commit 37a3a98ef601 ("ALSA: hda - Enable runtime PM only for discrete GPU") only allows HDA to be runtime suspended once GPU is bound, to keep APU's HDA working.
However, HDA on dGPU isn't that useful if dGPU is not bound to any driver. So let's relax the runtime suspend requirement for dGPU's HDA function, to disable the power source to save lots of power.
BugLink: https://bugs.launchpad.net/bugs/1840835 Fixes: b516ea586d71 ("PCI: Enable NVIDIA HDA controllers") Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com
Do you still have any concern on this patch? Please merge [v5 1/2] and this patch [v4 2/2] if you think it's good.
Thanks!
Kai-Heng
v4:
- Find upstream port, it's callee's responsibility now.
v3:
- Make changelog more clear.
v2:
- Change wording.
- Rebase to Tiwai's branch.
sound/pci/hda/hda_intel.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 240f4ca76391..e63b871343e5 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1280,11 +1280,17 @@ static void init_vga_switcheroo(struct azx *chip) { struct hda_intel *hda = container_of(chip, struct hda_intel, chip); struct pci_dev *p = get_bound_vga(chip->pci);
- struct pci_dev *parent; if (p) { dev_info(chip->card->dev, "Handle vga_switcheroo audio client\n"); hda->use_vga_switcheroo = 1;
chip->bus.keep_power = 1; /* cleared in either gpu_bound op or codec probe */
/* cleared in either gpu_bound op or codec probe, or when its
* upstream port has _PR3 (i.e. dGPU).
*/
parent = pci_upstream_bridge(p);
chip->driver_caps |= AZX_DCAPS_PM_RUNTIME; pci_dev_put(p); }chip->bus.keep_power = parent ? !pci_pr3_present(parent) : 1;
-- 2.17.1
On Mon, 07 Oct 2019 20:49:56 +0200, Kai-Heng Feng wrote:
Hi Takashi,
On Sep 25, 2019, at 19:32, Kai-Heng Feng kai.heng.feng@canonical.com wrote:
Nvidia proprietary driver doesn't support runtime power management, so when a user only wants to use the integrated GPU, it's a common practice to let dGPU not to bind any driver, and let its upstream port to be runtime suspended. At the end of runtime suspension the port uses platform power management to disable power through _OFF method of power resource, which is listed by _PR3.
After commit b516ea586d71 ("PCI: Enable NVIDIA HDA controllers"), when the dGPU comes with an HDA function, the HDA won't be suspended if the dGPU is unbound, so the power resource can't be turned off by its upstream port driver.
Commit 37a3a98ef601 ("ALSA: hda - Enable runtime PM only for discrete GPU") only allows HDA to be runtime suspended once GPU is bound, to keep APU's HDA working.
However, HDA on dGPU isn't that useful if dGPU is not bound to any driver. So let's relax the runtime suspend requirement for dGPU's HDA function, to disable the power source to save lots of power.
BugLink: https://bugs.launchpad.net/bugs/1840835 Fixes: b516ea586d71 ("PCI: Enable NVIDIA HDA controllers") Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com
Do you still have any concern on this patch? Please merge [v5 1/2] and this patch [v4 2/2] if you think it's good.
Sorry for the late reply, as I've been off for a few weeks. Now I applied both patches for 5.4.
Thanks!
Takashi
Thanks!
Kai-Heng
v4:
- Find upstream port, it's callee's responsibility now.
v3:
- Make changelog more clear.
v2:
- Change wording.
- Rebase to Tiwai's branch.
sound/pci/hda/hda_intel.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 240f4ca76391..e63b871343e5 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1280,11 +1280,17 @@ static void init_vga_switcheroo(struct azx *chip) { struct hda_intel *hda = container_of(chip, struct hda_intel, chip); struct pci_dev *p = get_bound_vga(chip->pci);
- struct pci_dev *parent; if (p) { dev_info(chip->card->dev, "Handle vga_switcheroo audio client\n"); hda->use_vga_switcheroo = 1;
chip->bus.keep_power = 1; /* cleared in either gpu_bound op or codec probe */
/* cleared in either gpu_bound op or codec probe, or when its
* upstream port has _PR3 (i.e. dGPU).
*/
parent = pci_upstream_bridge(p);
chip->driver_caps |= AZX_DCAPS_PM_RUNTIME; pci_dev_put(p); }chip->bus.keep_power = parent ? !pci_pr3_present(parent) : 1;
-- 2.17.1
participants (3)
-
Bjorn Helgaas
-
Kai-Heng Feng
-
Takashi Iwai