aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2014-03-18 16:52:06 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-03 19:20:25 -0400
commitd2d56faebaed1dd9bc011fcceed7df6b1bea8fac (patch)
tree4b8dc1bb8d47698d410ea3088d051f9826551a49
parente13fa90ce42d8e7ee501426ea414c8ae4a5366ef (diff)
mei: txe: use runtime PG pm domain for non wakeable devices
For non wakeable devices we can't use pci runtime framework as we are not able to wakeup from D3 states. Instead we create new pg runtime domain that only drives TXE power gating protocol to reduce the power consumption. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/misc/mei/pci-txe.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c
index 31d86e76fb7f..2c3f5625a04e 100644
--- a/drivers/misc/mei/pci-txe.c
+++ b/drivers/misc/mei/pci-txe.c
@@ -41,6 +41,13 @@ static const struct pci_device_id mei_txe_pci_tbl[] = {
41}; 41};
42MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl); 42MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl);
43 43
44#ifdef CONFIG_PM_RUNTIME
45static inline void mei_txe_set_pm_domain(struct mei_device *dev);
46static inline void mei_txe_unset_pm_domain(struct mei_device *dev);
47#else
48static inline void mei_txe_set_pm_domain(struct mei_device *dev) {}
49static inline void mei_txe_unset_pm_domain(struct mei_device *dev) {}
50#endif /* CONFIG_PM_RUNTIME */
44 51
45static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw) 52static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw)
46{ 53{
@@ -147,6 +154,14 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
147 154
148 pci_set_drvdata(pdev, dev); 155 pci_set_drvdata(pdev, dev);
149 156
157 /*
158 * For not wake-able HW runtime pm framework
159 * can't be used on pci device level.
160 * Use domain runtime pm callbacks instead.
161 */
162 if (!pci_dev_run_wake(pdev))
163 mei_txe_set_pm_domain(dev);
164
150 pm_runtime_put_noidle(&pdev->dev); 165 pm_runtime_put_noidle(&pdev->dev);
151 166
152 return 0; 167 return 0;
@@ -199,6 +214,9 @@ static void mei_txe_remove(struct pci_dev *pdev)
199 214
200 mei_stop(dev); 215 mei_stop(dev);
201 216
217 if (!pci_dev_run_wake(pdev))
218 mei_txe_unset_pm_domain(dev);
219
202 /* disable interrupts */ 220 /* disable interrupts */
203 mei_disable_interrupts(dev); 221 mei_disable_interrupts(dev);
204 free_irq(pdev->irq, dev); 222 free_irq(pdev->irq, dev);
@@ -350,6 +368,37 @@ static int mei_txe_pm_runtime_resume(struct device *device)
350 368
351 return ret; 369 return ret;
352} 370}
371
372/**
373 * mei_txe_set_pm_domain - fill and set pm domian stucture for device
374 *
375 * @dev: mei_device
376 */
377static inline void mei_txe_set_pm_domain(struct mei_device *dev)
378{
379 struct pci_dev *pdev = dev->pdev;
380
381 if (pdev->dev.bus && pdev->dev.bus->pm) {
382 dev->pg_domain.ops = *pdev->dev.bus->pm;
383
384 dev->pg_domain.ops.runtime_suspend = mei_txe_pm_runtime_suspend;
385 dev->pg_domain.ops.runtime_resume = mei_txe_pm_runtime_resume;
386 dev->pg_domain.ops.runtime_idle = mei_txe_pm_runtime_idle;
387
388 pdev->dev.pm_domain = &dev->pg_domain;
389 }
390}
391
392/**
393 * mei_txe_unset_pm_domain - clean pm domian stucture for device
394 *
395 * @dev: mei_device
396 */
397static inline void mei_txe_unset_pm_domain(struct mei_device *dev)
398{
399 /* stop using pm callbacks if any */
400 dev->pdev->dev.pm_domain = NULL;
401}
353#endif /* CONFIG_PM_RUNTIME */ 402#endif /* CONFIG_PM_RUNTIME */
354 403
355#ifdef CONFIG_PM 404#ifdef CONFIG_PM