aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2017-09-26 02:18:27 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-10-04 05:25:09 -0400
commitb42dc0635bf0a6aa59fe4d7c826796ff659908c7 (patch)
tree2bcfd0b11b1ff666f5b439d9a1904332caa39f6c
parentd81fa669e3de7eb8a631d7d95dac5fbcb2bf9d4e (diff)
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: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/misc/mei/pci-me.c21
-rw-r--r--drivers/misc/mei/pci-txe.c30
2 files changed, 22 insertions, 29 deletions
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 4ff40d319676..630757a4b36a 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -226,12 +226,15 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
226 pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME; 226 pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;
227 227
228 /* 228 /*
229 * For not wake-able HW runtime pm framework 229 * ME maps runtime suspend/resume to D0i states,
230 * can't be used on pci device level. 230 * hence we need to go around native PCI runtime service which
231 * Use domain runtime pm callbacks instead. 231 * eventually brings the device into D3cold/hot state,
232 */ 232 * but the mei device cannot wake up from D3 unlike from D0i3.
233 if (!pci_dev_run_wake(pdev)) 233 * To get around the PCI device native runtime pm,
234 mei_me_set_pm_domain(dev); 234 * ME uses runtime pm domain handlers which take precedence
235 * over the driver's pm handlers.
236 */
237 mei_me_set_pm_domain(dev);
235 238
236 if (mei_pg_is_enabled(dev)) 239 if (mei_pg_is_enabled(dev))
237 pm_runtime_put_noidle(&pdev->dev); 240 pm_runtime_put_noidle(&pdev->dev);
@@ -271,8 +274,7 @@ static void mei_me_shutdown(struct pci_dev *pdev)
271 dev_dbg(&pdev->dev, "shutdown\n"); 274 dev_dbg(&pdev->dev, "shutdown\n");
272 mei_stop(dev); 275 mei_stop(dev);
273 276
274 if (!pci_dev_run_wake(pdev)) 277 mei_me_unset_pm_domain(dev);
275 mei_me_unset_pm_domain(dev);
276 278
277 mei_disable_interrupts(dev); 279 mei_disable_interrupts(dev);
278 free_irq(pdev->irq, dev); 280 free_irq(pdev->irq, dev);
@@ -300,8 +302,7 @@ static void mei_me_remove(struct pci_dev *pdev)
300 dev_dbg(&pdev->dev, "stop\n"); 302 dev_dbg(&pdev->dev, "stop\n");
301 mei_stop(dev); 303 mei_stop(dev);
302 304
303 if (!pci_dev_run_wake(pdev)) 305 mei_me_unset_pm_domain(dev);
304 mei_me_unset_pm_domain(dev);
305 306
306 mei_disable_interrupts(dev); 307 mei_disable_interrupts(dev);
307 308
diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c
index e38a5f144373..0566f9bfa7de 100644
--- a/drivers/misc/mei/pci-txe.c
+++ b/drivers/misc/mei/pci-txe.c
@@ -144,12 +144,14 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
144 pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME; 144 pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME;
145 145
146 /* 146 /*
147 * For not wake-able HW runtime pm framework 147 * TXE maps runtime suspend/resume to own power gating states,
148 * can't be used on pci device level. 148 * hence we need to go around native PCI runtime service which
149 * Use domain runtime pm callbacks instead. 149 * eventually brings the device into D3cold/hot state.
150 */ 150 * But the TXE device cannot wake up from D3 unlike from own
151 if (!pci_dev_run_wake(pdev)) 151 * power gating. To get around PCI device native runtime pm,
152 mei_txe_set_pm_domain(dev); 152 * TXE uses runtime pm domain handlers which take precedence.
153 */
154 mei_txe_set_pm_domain(dev);
153 155
154 pm_runtime_put_noidle(&pdev->dev); 156 pm_runtime_put_noidle(&pdev->dev);
155 157
@@ -186,8 +188,7 @@ static void mei_txe_shutdown(struct pci_dev *pdev)
186 dev_dbg(&pdev->dev, "shutdown\n"); 188 dev_dbg(&pdev->dev, "shutdown\n");
187 mei_stop(dev); 189 mei_stop(dev);
188 190
189 if (!pci_dev_run_wake(pdev)) 191 mei_txe_unset_pm_domain(dev);
190 mei_txe_unset_pm_domain(dev);
191 192
192 mei_disable_interrupts(dev); 193 mei_disable_interrupts(dev);
193 free_irq(pdev->irq, dev); 194 free_irq(pdev->irq, dev);
@@ -215,8 +216,7 @@ static void mei_txe_remove(struct pci_dev *pdev)
215 216
216 mei_stop(dev); 217 mei_stop(dev);
217 218
218 if (!pci_dev_run_wake(pdev)) 219 mei_txe_unset_pm_domain(dev);
219 mei_txe_unset_pm_domain(dev);
220 220
221 mei_disable_interrupts(dev); 221 mei_disable_interrupts(dev);
222 free_irq(pdev->irq, dev); 222 free_irq(pdev->irq, dev);
@@ -318,15 +318,7 @@ static int mei_txe_pm_runtime_suspend(struct device *device)
318 else 318 else
319 ret = -EAGAIN; 319 ret = -EAGAIN;
320 320
321 /* 321 /* keep irq on we are staying in D0 */
322 * If everything is okay we're about to enter PCI low
323 * power state (D3) therefor we need to disable the
324 * interrupts towards host.
325 * However if device is not wakeable we do not enter
326 * D-low state and we need to keep the interrupt kicking
327 */
328 if (!ret && pci_dev_run_wake(pdev))
329 mei_disable_interrupts(dev);
330 322
331 dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); 323 dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret);
332 324