Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Tomas Winkler and committed by
Greg Kroah-Hartman
e13fa90c 04bb139a

+53
+3
drivers/misc/mei/mei_dev.h
··· 419 419 * Power Gating support 420 420 */ 421 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 426 unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */ 424 427 u32 rd_msg_hdr;
+50
drivers/misc/mei/pci-me.c
··· 87 87 88 88 MODULE_DEVICE_TABLE(pci, mei_me_pci_tbl); 89 89 90 + #ifdef CONFIG_PM_RUNTIME 91 + static inline void mei_me_set_pm_domain(struct mei_device *dev); 92 + static inline void mei_me_unset_pm_domain(struct mei_device *dev); 93 + #else 94 + static inline void mei_me_set_pm_domain(struct mei_device *dev) {} 95 + static inline void mei_me_unset_pm_domain(struct mei_device *dev) {} 96 + #endif /* CONFIG_PM_RUNTIME */ 97 + 90 98 /** 91 99 * mei_quirk_probe - probe for devices that doesn't valid ME interface 92 100 * ··· 233 225 234 226 schedule_delayed_work(&dev->timer_work, HZ); 235 227 228 + /* 229 + * For not wake-able HW runtime pm framework 230 + * can't be used on pci device level. 231 + * Use domain runtime pm callbacks instead. 232 + */ 233 + if (!pci_dev_run_wake(pdev)) 234 + mei_me_set_pm_domain(dev); 235 + 236 236 if (mei_pg_is_enabled(dev)) 237 237 pm_runtime_put_noidle(&pdev->dev); 238 238 ··· 291 275 292 276 dev_dbg(&pdev->dev, "stop\n"); 293 277 mei_stop(dev); 278 + 279 + if (!pci_dev_run_wake(pdev)) 280 + mei_me_unset_pm_domain(dev); 294 281 295 282 /* disable interrupts */ 296 283 mei_disable_interrupts(dev); ··· 439 420 dev_dbg(&pdev->dev, "rpm: me: runtime resume ret = %d\n", ret); 440 421 441 422 return ret; 423 + } 424 + 425 + /** 426 + * mei_me_set_pm_domain - fill and set pm domian stucture for device 427 + * 428 + * @dev: mei_device 429 + */ 430 + static inline void mei_me_set_pm_domain(struct mei_device *dev) 431 + { 432 + struct pci_dev *pdev = dev->pdev; 433 + 434 + if (pdev->dev.bus && pdev->dev.bus->pm) { 435 + dev->pg_domain.ops = *pdev->dev.bus->pm; 436 + 437 + dev->pg_domain.ops.runtime_suspend = mei_me_pm_runtime_suspend; 438 + dev->pg_domain.ops.runtime_resume = mei_me_pm_runtime_resume; 439 + dev->pg_domain.ops.runtime_idle = mei_me_pm_runtime_idle; 440 + 441 + pdev->dev.pm_domain = &dev->pg_domain; 442 + } 443 + } 444 + 445 + /** 446 + * mei_me_unset_pm_domain - clean pm domian stucture for device 447 + * 448 + * @dev: mei_device 449 + */ 450 + static inline void mei_me_unset_pm_domain(struct mei_device *dev) 451 + { 452 + /* stop using pm callbacks if any */ 453 + dev->pdev->dev.pm_domain = NULL; 442 454 } 443 455 #endif /* CONFIG_PM_RUNTIME */ 444 456