Commit b42dc063 authored by Alexander Usyskin's avatar Alexander Usyskin Committed by Greg Kroah-Hartman

mei: always use domain runtime pm callbacks.

This patch fixes a regression caused by the new changes
in the "run wake" handlers.

The mei devices that support D0i3 are no longer receiving an interrupt
after entering runtime suspend state and will stall.

pci_dev_run_wake function now returns "true" for some devices
(including mei) for which it used to return "false",
arguably incorrectly as "run wake" used to mean that
wakeup signals can be generated for a device in
the working state of the system, so it could not be enabled
or disabled before too.

MEI maps runtime suspend/resume to its own defined
power gating (PG) states, (D0i3 or other depending on generation),
hence we need to go around the native PCI runtime service which
eventually brings the device into D3cold/hot state,
but the mei devices cannot wake up from D3 unlike from D0i3/PG state,
which keeps irq running.
To get around PCI device native runtime pm,
MEI uses runtime pm domain handlers which take precedence.

Cc: <stable@vger.kernel.org> #4.13+
Signed-off-by: default avatarAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d81fa669
...@@ -226,12 +226,15 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -226,12 +226,15 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME; pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;
/* /*
* For not wake-able HW runtime pm framework * ME maps runtime suspend/resume to D0i states,
* can't be used on pci device level. * hence we need to go around native PCI runtime service which
* Use domain runtime pm callbacks instead. * eventually brings the device into D3cold/hot state,
*/ * but the mei device cannot wake up from D3 unlike from D0i3.
if (!pci_dev_run_wake(pdev)) * To get around the PCI device native runtime pm,
mei_me_set_pm_domain(dev); * ME uses runtime pm domain handlers which take precedence
* over the driver's pm handlers.
*/
mei_me_set_pm_domain(dev);
if (mei_pg_is_enabled(dev)) if (mei_pg_is_enabled(dev))
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
...@@ -271,8 +274,7 @@ static void mei_me_shutdown(struct pci_dev *pdev) ...@@ -271,8 +274,7 @@ static void mei_me_shutdown(struct pci_dev *pdev)
dev_dbg(&pdev->dev, "shutdown\n"); dev_dbg(&pdev->dev, "shutdown\n");
mei_stop(dev); mei_stop(dev);
if (!pci_dev_run_wake(pdev)) mei_me_unset_pm_domain(dev);
mei_me_unset_pm_domain(dev);
mei_disable_interrupts(dev); mei_disable_interrupts(dev);
free_irq(pdev->irq, dev); free_irq(pdev->irq, dev);
...@@ -300,8 +302,7 @@ static void mei_me_remove(struct pci_dev *pdev) ...@@ -300,8 +302,7 @@ static void mei_me_remove(struct pci_dev *pdev)
dev_dbg(&pdev->dev, "stop\n"); dev_dbg(&pdev->dev, "stop\n");
mei_stop(dev); mei_stop(dev);
if (!pci_dev_run_wake(pdev)) mei_me_unset_pm_domain(dev);
mei_me_unset_pm_domain(dev);
mei_disable_interrupts(dev); mei_disable_interrupts(dev);
......
...@@ -144,12 +144,14 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -144,12 +144,14 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME; pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;
/* /*
* For not wake-able HW runtime pm framework * TXE maps runtime suspend/resume to own power gating states,
* can't be used on pci device level. * hence we need to go around native PCI runtime service which
* Use domain runtime pm callbacks instead. * eventually brings the device into D3cold/hot state.
*/ * But the TXE device cannot wake up from D3 unlike from own
if (!pci_dev_run_wake(pdev)) * power gating. To get around PCI device native runtime pm,
mei_txe_set_pm_domain(dev); * TXE uses runtime pm domain handlers which take precedence.
*/
mei_txe_set_pm_domain(dev);
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
...@@ -186,8 +188,7 @@ static void mei_txe_shutdown(struct pci_dev *pdev) ...@@ -186,8 +188,7 @@ static void mei_txe_shutdown(struct pci_dev *pdev)
dev_dbg(&pdev->dev, "shutdown\n"); dev_dbg(&pdev->dev, "shutdown\n");
mei_stop(dev); mei_stop(dev);
if (!pci_dev_run_wake(pdev)) mei_txe_unset_pm_domain(dev);
mei_txe_unset_pm_domain(dev);
mei_disable_interrupts(dev); mei_disable_interrupts(dev);
free_irq(pdev->irq, dev); free_irq(pdev->irq, dev);
...@@ -215,8 +216,7 @@ static void mei_txe_remove(struct pci_dev *pdev) ...@@ -215,8 +216,7 @@ static void mei_txe_remove(struct pci_dev *pdev)
mei_stop(dev); mei_stop(dev);
if (!pci_dev_run_wake(pdev)) mei_txe_unset_pm_domain(dev);
mei_txe_unset_pm_domain(dev);
mei_disable_interrupts(dev); mei_disable_interrupts(dev);
free_irq(pdev->irq, dev); free_irq(pdev->irq, dev);
...@@ -318,15 +318,7 @@ static int mei_txe_pm_runtime_suspend(struct device *device) ...@@ -318,15 +318,7 @@ static int mei_txe_pm_runtime_suspend(struct device *device)
else else
ret = -EAGAIN; ret = -EAGAIN;
/* /* keep irq on we are staying in D0 */
* If everything is okay we're about to enter PCI low
* power state (D3) therefor we need to disable the
* interrupts towards host.
* However if device is not wakeable we do not enter
* D-low state and we need to keep the interrupt kicking
*/
if (!ret && pci_dev_run_wake(pdev))
mei_disable_interrupts(dev);
dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment