diff options
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r-- | drivers/pci/pci-acpi.c | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 61e2fefeedab..fbf7b26c7c8a 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -48,6 +48,12 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) | |||
48 | if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev) | 48 | if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev) |
49 | return; | 49 | return; |
50 | 50 | ||
51 | if (pci_dev->current_state == PCI_D3cold) { | ||
52 | pci_wakeup_event(pci_dev); | ||
53 | pm_runtime_resume(&pci_dev->dev); | ||
54 | return; | ||
55 | } | ||
56 | |||
51 | if (!pci_dev->pm_cap || !pci_dev->pme_support | 57 | if (!pci_dev->pm_cap || !pci_dev->pme_support |
52 | || pci_check_pme_status(pci_dev)) { | 58 | || pci_check_pme_status(pci_dev)) { |
53 | if (pci_dev->pme_poll) | 59 | if (pci_dev->pme_poll) |
@@ -162,6 +168,20 @@ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) | |||
162 | return remove_pm_notifier(dev, pci_acpi_wake_dev); | 168 | return remove_pm_notifier(dev, pci_acpi_wake_dev); |
163 | } | 169 | } |
164 | 170 | ||
171 | phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle) | ||
172 | { | ||
173 | acpi_status status = AE_NOT_EXIST; | ||
174 | unsigned long long mcfg_addr; | ||
175 | |||
176 | if (handle) | ||
177 | status = acpi_evaluate_integer(handle, METHOD_NAME__CBA, | ||
178 | NULL, &mcfg_addr); | ||
179 | if (ACPI_FAILURE(status)) | ||
180 | return 0; | ||
181 | |||
182 | return (phys_addr_t)mcfg_addr; | ||
183 | } | ||
184 | |||
165 | /* | 185 | /* |
166 | * _SxD returns the D-state with the highest power | 186 | * _SxD returns the D-state with the highest power |
167 | * (lowest D-state number) supported in the S-state "x". | 187 | * (lowest D-state number) supported in the S-state "x". |
@@ -187,9 +207,13 @@ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) | |||
187 | 207 | ||
188 | static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev) | 208 | static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev) |
189 | { | 209 | { |
190 | int acpi_state; | 210 | int acpi_state, d_max; |
191 | 211 | ||
192 | acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL); | 212 | if (pdev->no_d3cold) |
213 | d_max = ACPI_STATE_D3_HOT; | ||
214 | else | ||
215 | d_max = ACPI_STATE_D3_COLD; | ||
216 | acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL, d_max); | ||
193 | if (acpi_state < 0) | 217 | if (acpi_state < 0) |
194 | return PCI_POWER_ERROR; | 218 | return PCI_POWER_ERROR; |
195 | 219 | ||
@@ -296,7 +320,13 @@ static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) | |||
296 | 320 | ||
297 | static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) | 321 | static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) |
298 | { | 322 | { |
299 | if (dev->pme_interrupt) | 323 | /* |
324 | * Per PCI Express Base Specification Revision 2.0 section | ||
325 | * 5.3.3.2 Link Wakeup, platform support is needed for D3cold | ||
326 | * waking up to power on the main link even if there is PME | ||
327 | * support for D3cold | ||
328 | */ | ||
329 | if (dev->pme_interrupt && !dev->runtime_d3cold) | ||
300 | return 0; | 330 | return 0; |
301 | 331 | ||
302 | if (!acpi_pm_device_run_wake(&dev->dev, enable)) | 332 | if (!acpi_pm_device_run_wake(&dev->dev, enable)) |