diff options
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r-- | drivers/pci/pcie/portdrv_pci.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index e0610bda1dea..7c576b9aa01d 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/pm.h> | 13 | #include <linux/pm.h> |
14 | #include <linux/pm_runtime.h> | ||
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/pcieport_if.h> | 16 | #include <linux/pcieport_if.h> |
16 | #include <linux/aer.h> | 17 | #include <linux/aer.h> |
@@ -99,6 +100,15 @@ static int pcie_port_resume_noirq(struct device *dev) | |||
99 | return 0; | 100 | return 0; |
100 | } | 101 | } |
101 | 102 | ||
103 | #ifdef CONFIG_PM_RUNTIME | ||
104 | static int pcie_port_runtime_pm(struct device *dev) | ||
105 | { | ||
106 | return 0; | ||
107 | } | ||
108 | #else | ||
109 | #define pcie_port_runtime_pm NULL | ||
110 | #endif | ||
111 | |||
102 | static const struct dev_pm_ops pcie_portdrv_pm_ops = { | 112 | static const struct dev_pm_ops pcie_portdrv_pm_ops = { |
103 | .suspend = pcie_port_device_suspend, | 113 | .suspend = pcie_port_device_suspend, |
104 | .resume = pcie_port_device_resume, | 114 | .resume = pcie_port_device_resume, |
@@ -107,6 +117,8 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { | |||
107 | .poweroff = pcie_port_device_suspend, | 117 | .poweroff = pcie_port_device_suspend, |
108 | .restore = pcie_port_device_resume, | 118 | .restore = pcie_port_device_resume, |
109 | .resume_noirq = pcie_port_resume_noirq, | 119 | .resume_noirq = pcie_port_resume_noirq, |
120 | .runtime_suspend = pcie_port_runtime_pm, | ||
121 | .runtime_resume = pcie_port_runtime_pm, | ||
110 | }; | 122 | }; |
111 | 123 | ||
112 | #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) | 124 | #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) |
@@ -117,6 +129,14 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { | |||
117 | #endif /* !PM */ | 129 | #endif /* !PM */ |
118 | 130 | ||
119 | /* | 131 | /* |
132 | * PCIe port runtime suspend is broken for some chipsets, so use a | ||
133 | * black list to disable runtime PM for these chipsets. | ||
134 | */ | ||
135 | static const struct pci_device_id port_runtime_pm_black_list[] = { | ||
136 | { /* end: all zeroes */ } | ||
137 | }; | ||
138 | |||
139 | /* | ||
120 | * pcie_portdrv_probe - Probe PCI-Express port devices | 140 | * pcie_portdrv_probe - Probe PCI-Express port devices |
121 | * @dev: PCI-Express port device being probed | 141 | * @dev: PCI-Express port device being probed |
122 | * | 142 | * |
@@ -144,12 +164,16 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, | |||
144 | return status; | 164 | return status; |
145 | 165 | ||
146 | pci_save_state(dev); | 166 | pci_save_state(dev); |
167 | if (!pci_match_id(port_runtime_pm_black_list, dev)) | ||
168 | pm_runtime_put_noidle(&dev->dev); | ||
147 | 169 | ||
148 | return 0; | 170 | return 0; |
149 | } | 171 | } |
150 | 172 | ||
151 | static void pcie_portdrv_remove(struct pci_dev *dev) | 173 | static void pcie_portdrv_remove(struct pci_dev *dev) |
152 | { | 174 | { |
175 | if (!pci_match_id(port_runtime_pm_black_list, dev)) | ||
176 | pm_runtime_get_noresume(&dev->dev); | ||
153 | pcie_port_device_remove(dev); | 177 | pcie_port_device_remove(dev); |
154 | pci_disable_device(dev); | 178 | pci_disable_device(dev); |
155 | } | 179 | } |