| .. | .. |
|---|
| 48 | 48 | #define PCI_PM_D3HOT_WAIT 10 /* msec */ |
|---|
| 49 | 49 | #define PCI_PM_D3COLD_WAIT 100 /* msec */ |
|---|
| 50 | 50 | |
|---|
| 51 | +/* |
|---|
| 52 | + * Following exit from Conventional Reset, devices must be ready within 1 sec |
|---|
| 53 | + * (PCIe r6.0 sec 6.6.1). A D3cold to D0 transition implies a Conventional |
|---|
| 54 | + * Reset (PCIe r6.0 sec 5.8). |
|---|
| 55 | + */ |
|---|
| 56 | +#define PCI_RESET_WAIT 1000 /* msec */ |
|---|
| 57 | +/* |
|---|
| 58 | + * Devices may extend the 1 sec period through Request Retry Status completions |
|---|
| 59 | + * (PCIe r6.0 sec 2.3.1). The spec does not provide an upper limit, but 60 sec |
|---|
| 60 | + * ought to be enough for any device to become responsive. |
|---|
| 61 | + */ |
|---|
| 62 | +#define PCIE_RESET_READY_POLL_MS 60000 /* msec */ |
|---|
| 63 | + |
|---|
| 51 | 64 | /** |
|---|
| 52 | 65 | * struct pci_platform_pm_ops - Firmware PM callbacks |
|---|
| 53 | 66 | * |
|---|
| .. | .. |
|---|
| 109 | 122 | void pci_free_cap_save_buffers(struct pci_dev *dev); |
|---|
| 110 | 123 | bool pci_bridge_d3_possible(struct pci_dev *dev); |
|---|
| 111 | 124 | void pci_bridge_d3_update(struct pci_dev *dev); |
|---|
| 112 | | -void pci_bridge_wait_for_secondary_bus(struct pci_dev *dev); |
|---|
| 125 | +int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type, |
|---|
| 126 | + int timeout); |
|---|
| 113 | 127 | |
|---|
| 114 | 128 | static inline void pci_wakeup_event(struct pci_dev *dev) |
|---|
| 115 | 129 | { |
|---|
| .. | .. |
|---|
| 357 | 371 | * @dev - pci device to set new error_state |
|---|
| 358 | 372 | * @new - the state we want dev to be in |
|---|
| 359 | 373 | * |
|---|
| 360 | | - * Must be called with device_lock held. |
|---|
| 374 | + * If the device is experiencing perm_failure, it has to remain in that state. |
|---|
| 375 | + * Any other transition is allowed. |
|---|
| 361 | 376 | * |
|---|
| 362 | 377 | * Returns true if state has been changed to the requested state. |
|---|
| 363 | 378 | */ |
|---|
| 364 | 379 | static inline bool pci_dev_set_io_state(struct pci_dev *dev, |
|---|
| 365 | 380 | pci_channel_state_t new) |
|---|
| 366 | 381 | { |
|---|
| 367 | | - bool changed = false; |
|---|
| 382 | + pci_channel_state_t old; |
|---|
| 368 | 383 | |
|---|
| 369 | | - device_lock_assert(&dev->dev); |
|---|
| 370 | 384 | switch (new) { |
|---|
| 371 | 385 | case pci_channel_io_perm_failure: |
|---|
| 372 | | - switch (dev->error_state) { |
|---|
| 373 | | - case pci_channel_io_frozen: |
|---|
| 374 | | - case pci_channel_io_normal: |
|---|
| 375 | | - case pci_channel_io_perm_failure: |
|---|
| 376 | | - changed = true; |
|---|
| 377 | | - break; |
|---|
| 378 | | - } |
|---|
| 379 | | - break; |
|---|
| 386 | + xchg(&dev->error_state, pci_channel_io_perm_failure); |
|---|
| 387 | + return true; |
|---|
| 380 | 388 | case pci_channel_io_frozen: |
|---|
| 381 | | - switch (dev->error_state) { |
|---|
| 382 | | - case pci_channel_io_frozen: |
|---|
| 383 | | - case pci_channel_io_normal: |
|---|
| 384 | | - changed = true; |
|---|
| 385 | | - break; |
|---|
| 386 | | - } |
|---|
| 387 | | - break; |
|---|
| 389 | + old = cmpxchg(&dev->error_state, pci_channel_io_normal, |
|---|
| 390 | + pci_channel_io_frozen); |
|---|
| 391 | + return old != pci_channel_io_perm_failure; |
|---|
| 388 | 392 | case pci_channel_io_normal: |
|---|
| 389 | | - switch (dev->error_state) { |
|---|
| 390 | | - case pci_channel_io_frozen: |
|---|
| 391 | | - case pci_channel_io_normal: |
|---|
| 392 | | - changed = true; |
|---|
| 393 | | - break; |
|---|
| 394 | | - } |
|---|
| 395 | | - break; |
|---|
| 393 | + old = cmpxchg(&dev->error_state, pci_channel_io_frozen, |
|---|
| 394 | + pci_channel_io_normal); |
|---|
| 395 | + return old != pci_channel_io_perm_failure; |
|---|
| 396 | + default: |
|---|
| 397 | + return false; |
|---|
| 396 | 398 | } |
|---|
| 397 | | - if (changed) |
|---|
| 398 | | - dev->error_state = new; |
|---|
| 399 | | - return changed; |
|---|
| 400 | 399 | } |
|---|
| 401 | 400 | |
|---|
| 402 | 401 | static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused) |
|---|
| 403 | 402 | { |
|---|
| 404 | | - device_lock(&dev->dev); |
|---|
| 405 | 403 | pci_dev_set_io_state(dev, pci_channel_io_perm_failure); |
|---|
| 406 | | - device_unlock(&dev->dev); |
|---|
| 407 | 404 | |
|---|
| 408 | 405 | return 0; |
|---|
| 409 | 406 | } |
|---|