.. | .. |
---|
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 | }; |
---|