diff options
Diffstat (limited to 'drivers/misc')
| -rw-r--r-- | drivers/misc/mei/pci-txe.c | 49 |
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 | }; |
| 42 | MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl); | 42 | MODULE_DEVICE_TABLE(pci, mei_txe_pci_tbl); |
| 43 | 43 | ||
| 44 | #ifdef CONFIG_PM_RUNTIME | ||
| 45 | static inline void mei_txe_set_pm_domain(struct mei_device *dev); | ||
| 46 | static inline void mei_txe_unset_pm_domain(struct mei_device *dev); | ||
| 47 | #else | ||
| 48 | static inline void mei_txe_set_pm_domain(struct mei_device *dev) {} | ||
| 49 | static inline void mei_txe_unset_pm_domain(struct mei_device *dev) {} | ||
| 50 | #endif /* CONFIG_PM_RUNTIME */ | ||
| 44 | 51 | ||
| 45 | static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw) | 52 | static 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 | */ | ||
| 377 | static 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 | */ | ||
| 397 | static 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 |
