| .. | .. |
|---|
| 29 | 29 | */ |
|---|
| 30 | 30 | bool pcie_ports_native; |
|---|
| 31 | 31 | |
|---|
| 32 | +/* |
|---|
| 33 | + * If the user specified "pcie_ports=dpc-native", use the Linux DPC PCIe |
|---|
| 34 | + * service even if the platform hasn't given us permission. |
|---|
| 35 | + */ |
|---|
| 36 | +bool pcie_ports_dpc_native; |
|---|
| 37 | + |
|---|
| 32 | 38 | static int __init pcie_port_setup(char *str) |
|---|
| 33 | 39 | { |
|---|
| 34 | 40 | if (!strncmp(str, "compat", 6)) |
|---|
| 35 | 41 | pcie_ports_disabled = true; |
|---|
| 36 | 42 | else if (!strncmp(str, "native", 6)) |
|---|
| 37 | 43 | pcie_ports_native = true; |
|---|
| 44 | + else if (!strncmp(str, "dpc-native", 10)) |
|---|
| 45 | + pcie_ports_dpc_native = true; |
|---|
| 38 | 46 | |
|---|
| 39 | 47 | return 1; |
|---|
| 40 | 48 | } |
|---|
| .. | .. |
|---|
| 45 | 53 | #ifdef CONFIG_PM |
|---|
| 46 | 54 | static int pcie_port_runtime_suspend(struct device *dev) |
|---|
| 47 | 55 | { |
|---|
| 48 | | - return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY; |
|---|
| 49 | | -} |
|---|
| 56 | + if (!to_pci_dev(dev)->bridge_d3) |
|---|
| 57 | + return -EBUSY; |
|---|
| 50 | 58 | |
|---|
| 51 | | -static int pcie_port_runtime_resume(struct device *dev) |
|---|
| 52 | | -{ |
|---|
| 53 | | - return 0; |
|---|
| 59 | + return pcie_port_device_runtime_suspend(dev); |
|---|
| 54 | 60 | } |
|---|
| 55 | 61 | |
|---|
| 56 | 62 | static int pcie_port_runtime_idle(struct device *dev) |
|---|
| .. | .. |
|---|
| 73 | 79 | .restore_noirq = pcie_port_device_resume_noirq, |
|---|
| 74 | 80 | .restore = pcie_port_device_resume, |
|---|
| 75 | 81 | .runtime_suspend = pcie_port_runtime_suspend, |
|---|
| 76 | | - .runtime_resume = pcie_port_runtime_resume, |
|---|
| 82 | + .runtime_resume = pcie_port_device_runtime_resume, |
|---|
| 77 | 83 | .runtime_idle = pcie_port_runtime_idle, |
|---|
| 78 | 84 | }; |
|---|
| 79 | 85 | |
|---|
| .. | .. |
|---|
| 95 | 101 | static int pcie_portdrv_probe(struct pci_dev *dev, |
|---|
| 96 | 102 | const struct pci_device_id *id) |
|---|
| 97 | 103 | { |
|---|
| 104 | + int type = pci_pcie_type(dev); |
|---|
| 98 | 105 | int status; |
|---|
| 99 | 106 | |
|---|
| 100 | 107 | if (!pci_is_pcie(dev) || |
|---|
| 101 | | - ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) && |
|---|
| 102 | | - (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) && |
|---|
| 103 | | - (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM))) |
|---|
| 108 | + ((type != PCI_EXP_TYPE_ROOT_PORT) && |
|---|
| 109 | + (type != PCI_EXP_TYPE_UPSTREAM) && |
|---|
| 110 | + (type != PCI_EXP_TYPE_DOWNSTREAM) && |
|---|
| 111 | + (type != PCI_EXP_TYPE_RC_EC))) |
|---|
| 104 | 112 | return -ENODEV; |
|---|
| 105 | 113 | |
|---|
| 106 | 114 | status = pcie_port_device_register(dev); |
|---|
| .. | .. |
|---|
| 109 | 117 | |
|---|
| 110 | 118 | pci_save_state(dev); |
|---|
| 111 | 119 | |
|---|
| 112 | | - dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_SMART_SUSPEND | |
|---|
| 113 | | - DPM_FLAG_LEAVE_SUSPENDED); |
|---|
| 120 | + dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE | |
|---|
| 121 | + DPM_FLAG_SMART_SUSPEND); |
|---|
| 114 | 122 | |
|---|
| 115 | 123 | if (pci_bridge_d3_possible(dev)) { |
|---|
| 116 | 124 | /* |
|---|
| .. | .. |
|---|
| 140 | 148 | } |
|---|
| 141 | 149 | |
|---|
| 142 | 150 | static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev, |
|---|
| 143 | | - enum pci_channel_state error) |
|---|
| 151 | + pci_channel_state_t error) |
|---|
| 144 | 152 | { |
|---|
| 145 | 153 | /* Root Port has no impact. Always recovers. */ |
|---|
| 146 | 154 | return PCI_ERS_RESULT_CAN_RECOVER; |
|---|
| 155 | +} |
|---|
| 156 | + |
|---|
| 157 | +static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev) |
|---|
| 158 | +{ |
|---|
| 159 | + pci_restore_state(dev); |
|---|
| 160 | + pci_save_state(dev); |
|---|
| 161 | + return PCI_ERS_RESULT_RECOVERED; |
|---|
| 147 | 162 | } |
|---|
| 148 | 163 | |
|---|
| 149 | 164 | static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev) |
|---|
| .. | .. |
|---|
| 177 | 192 | /* |
|---|
| 178 | 193 | * LINUX Device Driver Model |
|---|
| 179 | 194 | */ |
|---|
| 180 | | -static const struct pci_device_id port_pci_ids[] = { { |
|---|
| 195 | +static const struct pci_device_id port_pci_ids[] = { |
|---|
| 181 | 196 | /* handle any PCI-Express port */ |
|---|
| 182 | | - PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0), |
|---|
| 183 | | - }, { /* end: all zeroes */ } |
|---|
| 197 | + { PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0) }, |
|---|
| 198 | + /* subtractive decode PCI-to-PCI bridge, class type is 060401h */ |
|---|
| 199 | + { PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x01), ~0) }, |
|---|
| 200 | + /* handle any Root Complex Event Collector */ |
|---|
| 201 | + { PCI_DEVICE_CLASS(((PCI_CLASS_SYSTEM_RCEC << 8) | 0x00), ~0) }, |
|---|
| 202 | + { }, |
|---|
| 184 | 203 | }; |
|---|
| 185 | 204 | |
|---|
| 186 | 205 | static const struct pci_error_handlers pcie_portdrv_err_handler = { |
|---|
| 187 | 206 | .error_detected = pcie_portdrv_error_detected, |
|---|
| 207 | + .slot_reset = pcie_portdrv_slot_reset, |
|---|
| 188 | 208 | .mmio_enabled = pcie_portdrv_mmio_enabled, |
|---|
| 189 | 209 | .resume = pcie_portdrv_err_resume, |
|---|
| 190 | 210 | }; |
|---|