aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2014-03-18 16:52:05 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-03 19:20:25 -0400
commite13fa90ce42d8e7ee501426ea414c8ae4a5366ef (patch)
tree1ef2d46b91edaa0fc60fcb71619a07eefbdd35d9 /drivers/misc/mei
parent04bb139a071fef549892718f8965a7c61b1924e0 (diff)
mei: me: 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 ME power gating protocol to reduce the power consumption. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r--drivers/misc/mei/mei_dev.h3
-rw-r--r--drivers/misc/mei/pci-me.c50
2 files changed, 53 insertions, 0 deletions
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index fe76e5b4cd2a..beff9ef319f8 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -419,6 +419,9 @@ struct mei_device {
419 * Power Gating support 419 * Power Gating support
420 */ 420 */
421 enum mei_pg_event pg_event; 421 enum mei_pg_event pg_event;
422#ifdef CONFIG_PM_RUNTIME
423 struct dev_pm_domain pg_domain;
424#endif /* CONFIG_PM_RUNTIME */
422 425
423 unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */ 426 unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */
424 u32 rd_msg_hdr; 427 u32 rd_msg_hdr;
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index fcbf270c2c2a..88516b02c685 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -87,6 +87,14 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
87 87
88MODULE_DEVICE_TABLE(pci, mei_me_pci_tbl); 88MODULE_DEVICE_TABLE(pci, mei_me_pci_tbl);
89 89
90#ifdef CONFIG_PM_RUNTIME
91static inline void mei_me_set_pm_domain(struct mei_device *dev);
92static inline void mei_me_unset_pm_domain(struct mei_device *dev);
93#else
94static inline void mei_me_set_pm_domain(struct mei_device *dev) {}
95static inline void mei_me_unset_pm_domain(struct mei_device *dev) {}
96#endif /* CONFIG_PM_RUNTIME */
97
90/** 98/**
91 * mei_quirk_probe - probe for devices that doesn't valid ME interface 99 * mei_quirk_probe - probe for devices that doesn't valid ME interface
92 * 100 *
@@ -225,6 +233,14 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
225 233
226 schedule_delayed_work(&dev->timer_work, HZ); 234 schedule_delayed_work(&dev->timer_work, HZ);
227 235
236 /*
237 * For not wake-able HW runtime pm framework
238 * can't be used on pci device level.
239 * Use domain runtime pm callbacks instead.
240 */
241 if (!pci_dev_run_wake(pdev))
242 mei_me_set_pm_domain(dev);
243
228 if (mei_pg_is_enabled(dev)) 244 if (mei_pg_is_enabled(dev))
229 pm_runtime_put_noidle(&pdev->dev); 245 pm_runtime_put_noidle(&pdev->dev);
230 246
@@ -276,6 +292,9 @@ static void mei_me_remove(struct pci_dev *pdev)
276 dev_dbg(&pdev->dev, "stop\n"); 292 dev_dbg(&pdev->dev, "stop\n");
277 mei_stop(dev); 293 mei_stop(dev);
278 294
295 if (!pci_dev_run_wake(pdev))
296 mei_me_unset_pm_domain(dev);
297
279 /* disable interrupts */ 298 /* disable interrupts */
280 mei_disable_interrupts(dev); 299 mei_disable_interrupts(dev);
281 300
@@ -421,6 +440,37 @@ static int mei_me_pm_runtime_resume(struct device *device)
421 440
422 return ret; 441 return ret;
423} 442}
443
444/**
445 * mei_me_set_pm_domain - fill and set pm domian stucture for device
446 *
447 * @dev: mei_device
448 */
449static inline void mei_me_set_pm_domain(struct mei_device *dev)
450{
451 struct pci_dev *pdev = dev->pdev;
452
453 if (pdev->dev.bus && pdev->dev.bus->pm) {
454 dev->pg_domain.ops = *pdev->dev.bus->pm;
455
456 dev->pg_domain.ops.runtime_suspend = mei_me_pm_runtime_suspend;
457 dev->pg_domain.ops.runtime_resume = mei_me_pm_runtime_resume;
458 dev->pg_domain.ops.runtime_idle = mei_me_pm_runtime_idle;
459
460 pdev->dev.pm_domain = &dev->pg_domain;
461 }
462}
463
464/**
465 * mei_me_unset_pm_domain - clean pm domian stucture for device
466 *
467 * @dev: mei_device
468 */
469static inline void mei_me_unset_pm_domain(struct mei_device *dev)
470{
471 /* stop using pm callbacks if any */
472 dev->pdev->dev.pm_domain = NULL;
473}
424#endif /* CONFIG_PM_RUNTIME */ 474#endif /* CONFIG_PM_RUNTIME */
425 475
426#ifdef CONFIG_PM 476#ifdef CONFIG_PM