]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 | 2 | /* |
a1ccd3d9 | 3 | * Purpose: PCI Express Port Bus Driver |
1da177e4 LT |
4 | * |
5 | * Copyright (C) 2004 Intel | |
6 | * Copyright (C) Tom Long Nguyen ([email protected]) | |
7 | */ | |
8 | ||
8a039557 | 9 | #include <linux/bitfield.h> |
a1ccd3d9 BH |
10 | #include <linux/dmi.h> |
11 | #include <linux/init.h> | |
1da177e4 LT |
12 | #include <linux/module.h> |
13 | #include <linux/pci.h> | |
14 | #include <linux/kernel.h> | |
15 | #include <linux/errno.h> | |
16 | #include <linux/pm.h> | |
006d44e4 | 17 | #include <linux/pm_runtime.h> |
4e57b681 TS |
18 | #include <linux/string.h> |
19 | #include <linux/slab.h> | |
28eb5f27 | 20 | #include <linux/aer.h> |
1da177e4 | 21 | |
1bf83e55 | 22 | #include "../pci.h" |
1da177e4 LT |
23 | #include "portdrv.h" |
24 | ||
29f193fe BH |
25 | /* |
26 | * The PCIe Capability Interrupt Message Number (PCIe r3.1, sec 7.8.2) must | |
27 | * be one of the first 32 MSI-X entries. Per PCI r3.0, sec 6.8.3.1, MSI | |
28 | * supports a maximum of 32 vectors per function. | |
29 | */ | |
30 | #define PCIE_PORT_MAX_MSI_ENTRIES 32 | |
31 | ||
32 | #define get_descriptor_id(type, service) (((type - 4) << 8) | service) | |
33 | ||
f252d062 OP |
34 | struct portdrv_service_data { |
35 | struct pcie_port_service_driver *drv; | |
e76d596a | 36 | struct device *dev; |
f252d062 OP |
37 | u32 service; |
38 | }; | |
39 | ||
facf6d16 RW |
40 | /** |
41 | * release_pcie_device - free PCI Express port service device structure | |
42 | * @dev: Port service device to release | |
43 | * | |
44 | * Invoked automatically when device is being removed in response to | |
45 | * device_unregister(dev). Release all resources being claimed. | |
1da177e4 LT |
46 | */ |
47 | static void release_pcie_device(struct device *dev) | |
48 | { | |
40da4186 | 49 | kfree(to_pcie_device(dev)); |
1da177e4 LT |
50 | } |
51 | ||
3321eafd BH |
52 | /* |
53 | * Fill in *pme, *aer, *dpc with the relevant Interrupt Message Numbers if | |
54 | * services are enabled in "mask". Return the number of MSI/MSI-X vectors | |
55 | * required to accommodate the largest Message Number. | |
b43d4513 | 56 | */ |
3321eafd BH |
57 | static int pcie_message_numbers(struct pci_dev *dev, int mask, |
58 | u32 *pme, u32 *aer, u32 *dpc) | |
b43d4513 | 59 | { |
f0553ba0 | 60 | u32 nvec = 0, pos; |
3321eafd | 61 | u16 reg16; |
b43d4513 RW |
62 | |
63 | /* | |
3321eafd BH |
64 | * The Interrupt Message Number indicates which vector is used, i.e., |
65 | * the MSI-X table entry or the MSI offset between the base Message | |
66 | * Data and the generated interrupt message. See PCIe r3.1, sec | |
67 | * 7.8.2, 7.10.10, 7.31.2. | |
b43d4513 | 68 | */ |
b43d4513 | 69 | |
15d2aba7 | 70 | if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP | |
665745f2 | 71 | PCIE_PORT_SERVICE_BWCTRL)) { |
33e8b34f | 72 | pcie_capability_read_word(dev, PCI_EXP_FLAGS, ®16); |
8a039557 | 73 | *pme = FIELD_GET(PCI_EXP_FLAGS_IRQ, reg16); |
3321eafd | 74 | nvec = *pme + 1; |
b43d4513 RW |
75 | } |
76 | ||
f0553ba0 | 77 | #ifdef CONFIG_PCIEAER |
b43d4513 | 78 | if (mask & PCIE_PORT_SERVICE_AER) { |
f0553ba0 FL |
79 | u32 reg32; |
80 | ||
81 | pos = dev->aer_cap; | |
3321eafd BH |
82 | if (pos) { |
83 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, | |
84 | ®32); | |
8a039557 | 85 | *aer = FIELD_GET(PCI_ERR_ROOT_AER_IRQ, reg32); |
3321eafd BH |
86 | nvec = max(nvec, *aer + 1); |
87 | } | |
b43d4513 | 88 | } |
f0553ba0 | 89 | #endif |
b43d4513 | 90 | |
ae6dc7de | 91 | if (mask & PCIE_PORT_SERVICE_DPC) { |
ae6dc7de | 92 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC); |
3321eafd BH |
93 | if (pos) { |
94 | pci_read_config_word(dev, pos + PCI_EXP_DPC_CAP, | |
95 | ®16); | |
8a039557 | 96 | *dpc = FIELD_GET(PCI_EXP_DPC_IRQ, reg16); |
3321eafd BH |
97 | nvec = max(nvec, *dpc + 1); |
98 | } | |
99 | } | |
100 | ||
101 | return nvec; | |
102 | } | |
103 | ||
b43d4513 | 104 | /** |
a1d5f18c GP |
105 | * pcie_port_enable_irq_vec - try to set up MSI-X or MSI as interrupt mode |
106 | * for given port | |
b43d4513 | 107 | * @dev: PCI Express port to handle |
3674cc49 | 108 | * @irqs: Array of interrupt vectors to populate |
b43d4513 RW |
109 | * @mask: Bitmask of port capabilities returned by get_port_device_capability() |
110 | * | |
111 | * Return value: 0 on success, error code on failure | |
112 | */ | |
a1d5f18c | 113 | static int pcie_port_enable_irq_vec(struct pci_dev *dev, int *irqs, int mask) |
b43d4513 | 114 | { |
e8303bb7 | 115 | int nr_entries, nvec, pcie_irq; |
3321eafd | 116 | u32 pme = 0, aer = 0, dpc = 0; |
ae6dc7de | 117 | |
b8acfd7c | 118 | /* Allocate the maximum possible number of MSI/MSI-X vectors */ |
a1d5f18c GP |
119 | nr_entries = pci_alloc_irq_vectors(dev, 1, PCIE_PORT_MAX_MSI_ENTRIES, |
120 | PCI_IRQ_MSIX | PCI_IRQ_MSI); | |
3674cc49 CH |
121 | if (nr_entries < 0) |
122 | return nr_entries; | |
ae6dc7de | 123 | |
3321eafd BH |
124 | /* See how many and which Interrupt Message Numbers we actually use */ |
125 | nvec = pcie_message_numbers(dev, mask, &pme, &aer, &dpc); | |
126 | if (nvec > nr_entries) { | |
127 | pci_free_irq_vectors(dev); | |
128 | return -EIO; | |
ae6dc7de GP |
129 | } |
130 | ||
b43d4513 | 131 | /* |
a579ba49 BH |
132 | * If we allocated more than we need, free them and reallocate fewer. |
133 | * | |
134 | * Reallocating may change the specific vectors we get, so | |
135 | * pci_irq_vector() must be done *after* the reallocation. | |
136 | * | |
137 | * If we're using MSI, hardware is *allowed* to change the Interrupt | |
138 | * Message Numbers when we free and reallocate the vectors, but we | |
139 | * assume it won't because we allocate enough vectors for the | |
140 | * biggest Message Number we found. | |
b43d4513 | 141 | */ |
3674cc49 | 142 | if (nvec != nr_entries) { |
3674cc49 | 143 | pci_free_irq_vectors(dev); |
b43d4513 | 144 | |
3674cc49 | 145 | nr_entries = pci_alloc_irq_vectors(dev, nvec, nvec, |
a1d5f18c | 146 | PCI_IRQ_MSIX | PCI_IRQ_MSI); |
3674cc49 CH |
147 | if (nr_entries < 0) |
148 | return nr_entries; | |
b43d4513 RW |
149 | } |
150 | ||
e8303bb7 AG |
151 | /* PME, hotplug and bandwidth notification share an MSI/MSI-X vector */ |
152 | if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP | | |
665745f2 | 153 | PCIE_PORT_SERVICE_BWCTRL)) { |
e8303bb7 AG |
154 | pcie_irq = pci_irq_vector(dev, pme); |
155 | irqs[PCIE_PORT_SERVICE_PME_SHIFT] = pcie_irq; | |
156 | irqs[PCIE_PORT_SERVICE_HP_SHIFT] = pcie_irq; | |
665745f2 | 157 | irqs[PCIE_PORT_SERVICE_BWCTRL_SHIFT] = pcie_irq; |
b43d4513 RW |
158 | } |
159 | ||
3321eafd BH |
160 | if (mask & PCIE_PORT_SERVICE_AER) |
161 | irqs[PCIE_PORT_SERVICE_AER_SHIFT] = pci_irq_vector(dev, aer); | |
b43d4513 | 162 | |
3321eafd BH |
163 | if (mask & PCIE_PORT_SERVICE_DPC) |
164 | irqs[PCIE_PORT_SERVICE_DPC_SHIFT] = pci_irq_vector(dev, dpc); | |
ae6dc7de | 165 | |
3674cc49 | 166 | return 0; |
b43d4513 RW |
167 | } |
168 | ||
facf6d16 | 169 | /** |
3674cc49 | 170 | * pcie_init_service_irqs - initialize irqs for PCI Express port services |
facf6d16 | 171 | * @dev: PCI Express port to handle |
dc535178 | 172 | * @irqs: Array of irqs to populate |
facf6d16 RW |
173 | * @mask: Bitmask of port capabilities returned by get_port_device_capability() |
174 | * | |
175 | * Return value: Interrupt mode associated with the port | |
176 | */ | |
3674cc49 | 177 | static int pcie_init_service_irqs(struct pci_dev *dev, int *irqs, int mask) |
1da177e4 | 178 | { |
3674cc49 CH |
179 | int ret, i; |
180 | ||
075b7d36 BH |
181 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) |
182 | irqs[i] = -1; | |
183 | ||
e237d83f | 184 | /* |
1e447c57 BH |
185 | * If we support PME but can't use MSI/MSI-X for it, we have to |
186 | * fall back to INTx or other interrupts, e.g., a system shared | |
187 | * interrupt. | |
e237d83f | 188 | */ |
a1d5f18c | 189 | if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) |
a665b0a9 | 190 | goto intx_irq; |
a1d5f18c | 191 | |
a1d5f18c GP |
192 | /* Try to use MSI-X or MSI if supported */ |
193 | if (pcie_port_enable_irq_vec(dev, irqs, mask) == 0) | |
194 | return 0; | |
90e9cd50 | 195 | |
a665b0a9 DLM |
196 | intx_irq: |
197 | /* fall back to INTX IRQ */ | |
198 | ret = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_INTX); | |
3674cc49 CH |
199 | if (ret < 0) |
200 | return -ENODEV; | |
b43d4513 | 201 | |
168f3ae5 BH |
202 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) |
203 | irqs[i] = pci_irq_vector(dev, 0); | |
1da177e4 | 204 | |
dc535178 | 205 | return 0; |
1da177e4 LT |
206 | } |
207 | ||
facf6d16 RW |
208 | /** |
209 | * get_port_device_capability - discover capabilities of a PCI Express port | |
210 | * @dev: PCI Express port to examine | |
211 | * | |
212 | * The capabilities are read from the port's PCI Express configuration registers | |
213 | * as described in PCI Express Base Specification 1.0a sections 7.8.2, 7.8.9 and | |
214 | * 7.9 - 7.11. | |
215 | * | |
216 | * Return value: Bitmask of discovered port capabilities | |
217 | */ | |
1da177e4 LT |
218 | static int get_port_device_capability(struct pci_dev *dev) |
219 | { | |
02bfeb48 | 220 | struct pci_host_bridge *host = pci_find_host_bridge(dev->bus); |
2dcfaf85 | 221 | int services = 0; |
28eb5f27 | 222 | |
d850882b | 223 | if (dev->is_hotplug_bridge && |
05f57474 RW |
224 | (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || |
225 | pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) && | |
9310f0dc | 226 | (pcie_ports_native || host->native_pcie_hotplug)) { |
f8415222 | 227 | services |= PCIE_PORT_SERVICE_HP; |
02bfeb48 | 228 | |
f8415222 LW |
229 | /* |
230 | * Disable hot-plug interrupts in case they have been enabled | |
231 | * by the BIOS and the hot-plug service driver is not loaded. | |
232 | */ | |
233 | pcie_capability_clear_word(dev, PCI_EXP_SLTCTL, | |
234 | PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE); | |
1bf83e55 | 235 | } |
02bfeb48 | 236 | |
f0553ba0 | 237 | #ifdef CONFIG_PCIEAER |
d8d2b65a BH |
238 | if ((pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || |
239 | pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC) && | |
240 | dev->aer_cap && pci_aer_available() && | |
8795e182 | 241 | (pcie_ports_native || host->native_aer)) |
0927678f | 242 | services |= PCIE_PORT_SERVICE_AER; |
f0553ba0 | 243 | #endif |
02bfeb48 | 244 | |
9a2f604f SK |
245 | /* Root Ports and Root Complex Event Collectors may generate PMEs */ |
246 | if ((pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || | |
247 | pci_pcie_type(dev) == PCI_EXP_TYPE_RC_EC) && | |
d850882b | 248 | (pcie_ports_native || host->native_pme)) { |
9e5d0b16 | 249 | services |= PCIE_PORT_SERVICE_PME; |
02bfeb48 | 250 | |
2bd50dd8 RW |
251 | /* |
252 | * Disable PME interrupt on this port in case it's been enabled | |
253 | * by the BIOS (the PME service driver will enable it when | |
254 | * necessary). | |
255 | */ | |
256 | pcie_pme_interrupt_enable(dev, false); | |
257 | } | |
02bfeb48 | 258 | |
35a0b237 OJ |
259 | /* |
260 | * With dpc-native, allow Linux to use DPC even if it doesn't have | |
261 | * permission to use AER. | |
262 | */ | |
02bfeb48 | 263 | if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC) && |
35a0b237 OJ |
264 | pci_aer_available() && |
265 | (pcie_ports_dpc_native || (services & PCIE_PORT_SERVICE_AER))) | |
10126ac1 | 266 | services |= PCIE_PORT_SERVICE_DPC; |
1da177e4 | 267 | |
e8303bb7 | 268 | if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM || |
00823dcb SH |
269 | pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) { |
270 | u32 linkcap; | |
271 | ||
272 | pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &linkcap); | |
273 | if (linkcap & PCI_EXP_LNKCAP_LBNC) | |
665745f2 | 274 | services |= PCIE_PORT_SERVICE_BWCTRL; |
00823dcb | 275 | } |
e8303bb7 | 276 | |
1da177e4 LT |
277 | return services; |
278 | } | |
279 | ||
facf6d16 | 280 | /** |
52a0f24b KK |
281 | * pcie_device_init - allocate and initialize PCI Express port service device |
282 | * @pdev: PCI Express port to associate the service device with | |
283 | * @service: Type of service to associate with the service device | |
facf6d16 | 284 | * @irq: Interrupt vector to associate with the service device |
facf6d16 | 285 | */ |
52a0f24b | 286 | static int pcie_device_init(struct pci_dev *pdev, int service, int irq) |
1da177e4 | 287 | { |
52a0f24b KK |
288 | int retval; |
289 | struct pcie_device *pcie; | |
1da177e4 LT |
290 | struct device *device; |
291 | ||
52a0f24b KK |
292 | pcie = kzalloc(sizeof(*pcie), GFP_KERNEL); |
293 | if (!pcie) | |
294 | return -ENOMEM; | |
295 | pcie->port = pdev; | |
296 | pcie->irq = irq; | |
297 | pcie->service = service; | |
1da177e4 LT |
298 | |
299 | /* Initialize generic device interface */ | |
52a0f24b | 300 | device = &pcie->device; |
1da177e4 | 301 | device->bus = &pcie_port_bus_type; |
1da177e4 | 302 | device->release = release_pcie_device; /* callback to free pcie dev */ |
6d81417d | 303 | dev_set_name(device, "%s:pcie%03x", |
52a0f24b | 304 | pci_name(pdev), |
62f87c0e | 305 | get_descriptor_id(pci_pcie_type(pdev), service)); |
52a0f24b | 306 | device->parent = &pdev->dev; |
a1e4d72c | 307 | device_enable_async_suspend(device); |
52a0f24b KK |
308 | |
309 | retval = device_register(device); | |
8f3acca9 | 310 | if (retval) { |
f3986205 | 311 | put_device(device); |
8f3acca9 BH |
312 | return retval; |
313 | } | |
314 | ||
006d44e4 MW |
315 | pm_runtime_no_callbacks(device); |
316 | ||
8f3acca9 | 317 | return 0; |
1da177e4 LT |
318 | } |
319 | ||
facf6d16 RW |
320 | /** |
321 | * pcie_port_device_register - register PCI Express port | |
322 | * @dev: PCI Express port to register | |
323 | * | |
324 | * Allocate the port extension structure and register services associated with | |
325 | * the port. | |
326 | */ | |
a1ccd3d9 | 327 | static int pcie_port_device_register(struct pci_dev *dev) |
1da177e4 | 328 | { |
075b7d36 BH |
329 | int status, capabilities, i, nr_service; |
330 | int irqs[PCIE_PORT_DEVICE_MAXSERVICES]; | |
1da177e4 | 331 | |
1ce5e830 KK |
332 | /* Enable PCI Express port device */ |
333 | status = pci_enable_device(dev); | |
334 | if (status) | |
694f88ef | 335 | return status; |
fe31e697 RW |
336 | |
337 | /* Get and check PCI Express port services */ | |
338 | capabilities = get_port_device_capability(dev); | |
eca67315 | 339 | if (!capabilities) |
fe31e697 | 340 | return 0; |
fe31e697 | 341 | |
1ce5e830 | 342 | pci_set_master(dev); |
075b7d36 BH |
343 | /* |
344 | * Initialize service irqs. Don't use service devices that | |
345 | * require interrupts if there is no way to generate them. | |
346 | * However, some drivers may have a polling mode (e.g. pciehp_poll_mode) | |
347 | * that can be used in the absence of irqs. Allow them to determine | |
348 | * if that is to be used. | |
349 | */ | |
350 | status = pcie_init_service_irqs(dev, irqs, capabilities); | |
351 | if (status) { | |
352 | capabilities &= PCIE_PORT_SERVICE_HP; | |
353 | if (!capabilities) | |
354 | goto error_disable; | |
f118c0c3 | 355 | } |
1da177e4 LT |
356 | |
357 | /* Allocate child services if any */ | |
40717c39 KK |
358 | status = -ENODEV; |
359 | nr_service = 0; | |
360 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { | |
90e9cd50 | 361 | int service = 1 << i; |
90e9cd50 RW |
362 | if (!(capabilities & service)) |
363 | continue; | |
40717c39 KK |
364 | if (!pcie_device_init(dev, service, irqs[i])) |
365 | nr_service++; | |
f118c0c3 | 366 | } |
40717c39 | 367 | if (!nr_service) |
fbb5de70 | 368 | goto error_cleanup_irqs; |
40717c39 | 369 | |
1da177e4 | 370 | return 0; |
f118c0c3 | 371 | |
fbb5de70 | 372 | error_cleanup_irqs: |
3674cc49 | 373 | pci_free_irq_vectors(dev); |
1ce5e830 KK |
374 | error_disable: |
375 | pci_disable_device(dev); | |
f118c0c3 | 376 | return status; |
1da177e4 LT |
377 | } |
378 | ||
3134689f | 379 | typedef int (*pcie_callback_t)(struct pcie_device *); |
6ccb127b | 380 | |
a1ccd3d9 | 381 | static int pcie_port_device_iter(struct device *dev, void *data) |
1da177e4 | 382 | { |
1da177e4 | 383 | struct pcie_port_service_driver *service_driver; |
6ccb127b | 384 | size_t offset = *(size_t *)data; |
3134689f | 385 | pcie_callback_t cb; |
d0e2b4a0 | 386 | |
40da4186 HS |
387 | if ((dev->bus == &pcie_port_bus_type) && dev->driver) { |
388 | service_driver = to_service_driver(dev->driver); | |
3134689f | 389 | cb = *(pcie_callback_t *)((void *)service_driver + offset); |
6ccb127b LW |
390 | if (cb) |
391 | return cb(to_pcie_device(dev)); | |
40da4186 | 392 | } |
d0e2b4a0 | 393 | return 0; |
394 | } | |
1da177e4 | 395 | |
3134689f | 396 | #ifdef CONFIG_PM |
facf6d16 RW |
397 | /** |
398 | * pcie_port_device_suspend - suspend port services associated with a PCIe port | |
399 | * @dev: PCI Express port to handle | |
facf6d16 | 400 | */ |
a1ccd3d9 | 401 | static int pcie_port_device_suspend(struct device *dev) |
d0e2b4a0 | 402 | { |
6ccb127b | 403 | size_t off = offsetof(struct pcie_port_service_driver, suspend); |
3134689f | 404 | return device_for_each_child(dev, &off, pcie_port_device_iter); |
d0e2b4a0 | 405 | } |
1da177e4 | 406 | |
a1ccd3d9 | 407 | static int pcie_port_device_resume_noirq(struct device *dev) |
79037824 LW |
408 | { |
409 | size_t off = offsetof(struct pcie_port_service_driver, resume_noirq); | |
3134689f | 410 | return device_for_each_child(dev, &off, pcie_port_device_iter); |
79037824 LW |
411 | } |
412 | ||
facf6d16 | 413 | /** |
e7f6c6d0 | 414 | * pcie_port_device_resume - resume port services associated with a PCIe port |
facf6d16 RW |
415 | * @dev: PCI Express port to handle |
416 | */ | |
a1ccd3d9 | 417 | static int pcie_port_device_resume(struct device *dev) |
d0e2b4a0 | 418 | { |
6ccb127b | 419 | size_t off = offsetof(struct pcie_port_service_driver, resume); |
3134689f | 420 | return device_for_each_child(dev, &off, pcie_port_device_iter); |
1da177e4 | 421 | } |
94c7993f MW |
422 | |
423 | /** | |
424 | * pcie_port_device_runtime_suspend - runtime suspend port services | |
425 | * @dev: PCI Express port to handle | |
426 | */ | |
a1ccd3d9 | 427 | static int pcie_port_device_runtime_suspend(struct device *dev) |
94c7993f MW |
428 | { |
429 | size_t off = offsetof(struct pcie_port_service_driver, runtime_suspend); | |
3134689f | 430 | return device_for_each_child(dev, &off, pcie_port_device_iter); |
94c7993f MW |
431 | } |
432 | ||
433 | /** | |
434 | * pcie_port_device_runtime_resume - runtime resume port services | |
435 | * @dev: PCI Express port to handle | |
436 | */ | |
a1ccd3d9 | 437 | static int pcie_port_device_runtime_resume(struct device *dev) |
94c7993f MW |
438 | { |
439 | size_t off = offsetof(struct pcie_port_service_driver, runtime_resume); | |
3134689f | 440 | return device_for_each_child(dev, &off, pcie_port_device_iter); |
94c7993f | 441 | } |
3a3c244c | 442 | #endif /* PM */ |
1da177e4 | 443 | |
d0e2b4a0 | 444 | static int remove_iter(struct device *dev, void *data) |
1da177e4 | 445 | { |
e75f34ce | 446 | if (dev->bus == &pcie_port_bus_type) |
ae40582e | 447 | device_unregister(dev); |
d0e2b4a0 | 448 | return 0; |
449 | } | |
450 | ||
f252d062 OP |
451 | static int find_service_iter(struct device *device, void *data) |
452 | { | |
453 | struct pcie_port_service_driver *service_driver; | |
454 | struct portdrv_service_data *pdrvs; | |
455 | u32 service; | |
456 | ||
457 | pdrvs = (struct portdrv_service_data *) data; | |
458 | service = pdrvs->service; | |
459 | ||
460 | if (device->bus == &pcie_port_bus_type && device->driver) { | |
461 | service_driver = to_service_driver(device->driver); | |
462 | if (service_driver->service == service) { | |
463 | pdrvs->drv = service_driver; | |
e76d596a | 464 | pdrvs->dev = device; |
f252d062 OP |
465 | return 1; |
466 | } | |
467 | } | |
468 | ||
469 | return 0; | |
470 | } | |
471 | ||
e76d596a OP |
472 | /** |
473 | * pcie_port_find_device - find the struct device | |
474 | * @dev: PCI Express port the service is associated with | |
475 | * @service: For the service to find | |
476 | * | |
477 | * Find the struct device associated with given service on a pci_dev | |
478 | */ | |
479 | struct device *pcie_port_find_device(struct pci_dev *dev, | |
480 | u32 service) | |
481 | { | |
482 | struct device *device; | |
483 | struct portdrv_service_data pdrvs; | |
484 | ||
485 | pdrvs.dev = NULL; | |
486 | pdrvs.service = service; | |
487 | device_for_each_child(&dev->dev, &pdrvs, find_service_iter); | |
488 | ||
489 | device = pdrvs.dev; | |
490 | return device; | |
491 | } | |
0e98db25 | 492 | EXPORT_SYMBOL_GPL(pcie_port_find_device); |
e76d596a | 493 | |
facf6d16 RW |
494 | /** |
495 | * pcie_port_device_remove - unregister PCI Express port service devices | |
496 | * @dev: PCI Express port the service devices to unregister are associated with | |
497 | * | |
498 | * Remove PCI Express port service devices associated with given port and | |
499 | * disable MSI-X or MSI for the port. | |
500 | */ | |
a1ccd3d9 | 501 | static void pcie_port_device_remove(struct pci_dev *dev) |
d0e2b4a0 | 502 | { |
ae40582e | 503 | device_for_each_child(&dev->dev, NULL, remove_iter); |
3674cc49 | 504 | pci_free_irq_vectors(dev); |
1da177e4 LT |
505 | } |
506 | ||
d9347371 RW |
507 | /** |
508 | * pcie_port_probe_service - probe driver for given PCI Express port service | |
509 | * @dev: PCI Express port service device to probe against | |
510 | * | |
511 | * If PCI Express port service driver is registered with | |
512 | * pcie_port_service_register(), this function will be called by the driver core | |
513 | * whenever match is found between the driver and a port service device. | |
514 | */ | |
fa6c9937 | 515 | static int pcie_port_probe_service(struct device *dev) |
1da177e4 | 516 | { |
fa6c9937 RW |
517 | struct pcie_device *pciedev; |
518 | struct pcie_port_service_driver *driver; | |
519 | int status; | |
520 | ||
521 | if (!dev || !dev->driver) | |
522 | return -ENODEV; | |
523 | ||
524 | driver = to_service_driver(dev->driver); | |
525 | if (!driver || !driver->probe) | |
526 | return -ENODEV; | |
527 | ||
528 | pciedev = to_pcie_device(dev); | |
0516c8bc | 529 | status = driver->probe(pciedev); |
8f3acca9 BH |
530 | if (status) |
531 | return status; | |
532 | ||
8f3acca9 BH |
533 | get_device(dev); |
534 | return 0; | |
1da177e4 LT |
535 | } |
536 | ||
d9347371 RW |
537 | /** |
538 | * pcie_port_remove_service - detach driver from given PCI Express port service | |
539 | * @dev: PCI Express port service device to handle | |
540 | * | |
541 | * If PCI Express port service driver is registered with | |
542 | * pcie_port_service_register(), this function will be called by the driver core | |
543 | * when device_unregister() is called for the port service device associated | |
544 | * with the driver. | |
545 | */ | |
fa6c9937 | 546 | static int pcie_port_remove_service(struct device *dev) |
1da177e4 | 547 | { |
fa6c9937 RW |
548 | struct pcie_device *pciedev; |
549 | struct pcie_port_service_driver *driver; | |
550 | ||
551 | if (!dev || !dev->driver) | |
552 | return 0; | |
553 | ||
554 | pciedev = to_pcie_device(dev); | |
555 | driver = to_service_driver(dev->driver); | |
556 | if (driver && driver->remove) { | |
fa6c9937 RW |
557 | driver->remove(pciedev); |
558 | put_device(dev); | |
559 | } | |
560 | return 0; | |
1da177e4 LT |
561 | } |
562 | ||
d9347371 RW |
563 | /** |
564 | * pcie_port_shutdown_service - shut down given PCI Express port service | |
565 | * @dev: PCI Express port service device to handle | |
566 | * | |
567 | * If PCI Express port service driver is registered with | |
568 | * pcie_port_service_register(), this function will be called by the driver core | |
569 | * when device_shutdown() is called for the port service device associated | |
570 | * with the driver. | |
571 | */ | |
fa6c9937 RW |
572 | static void pcie_port_shutdown_service(struct device *dev) {} |
573 | ||
d9347371 RW |
574 | /** |
575 | * pcie_port_service_register - register PCI Express port service driver | |
576 | * @new: PCI Express port service driver to register | |
577 | */ | |
1da177e4 LT |
578 | int pcie_port_service_register(struct pcie_port_service_driver *new) |
579 | { | |
79dd9182 RW |
580 | if (pcie_ports_disabled) |
581 | return -ENODEV; | |
582 | ||
6f825b73 | 583 | new->driver.name = new->name; |
1da177e4 LT |
584 | new->driver.bus = &pcie_port_bus_type; |
585 | new->driver.probe = pcie_port_probe_service; | |
586 | new->driver.remove = pcie_port_remove_service; | |
587 | new->driver.shutdown = pcie_port_shutdown_service; | |
1da177e4 LT |
588 | |
589 | return driver_register(&new->driver); | |
d0e2b4a0 | 590 | } |
1da177e4 | 591 | |
d9347371 RW |
592 | /** |
593 | * pcie_port_service_unregister - unregister PCI Express port service driver | |
594 | * @drv: PCI Express port service driver to unregister | |
595 | */ | |
fa6c9937 | 596 | void pcie_port_service_unregister(struct pcie_port_service_driver *drv) |
1da177e4 | 597 | { |
fa6c9937 | 598 | driver_unregister(&drv->driver); |
1da177e4 | 599 | } |
a1ccd3d9 BH |
600 | |
601 | /* If this switch is set, PCIe port native services should not be enabled. */ | |
602 | bool pcie_ports_disabled; | |
603 | ||
604 | /* | |
605 | * If the user specified "pcie_ports=native", use the PCIe services regardless | |
606 | * of whether the platform has given us permission. On ACPI systems, this | |
607 | * means we ignore _OSC. | |
608 | */ | |
609 | bool pcie_ports_native; | |
610 | ||
611 | /* | |
612 | * If the user specified "pcie_ports=dpc-native", use the Linux DPC PCIe | |
613 | * service even if the platform hasn't given us permission. | |
614 | */ | |
615 | bool pcie_ports_dpc_native; | |
616 | ||
617 | static int __init pcie_port_setup(char *str) | |
618 | { | |
619 | if (!strncmp(str, "compat", 6)) | |
620 | pcie_ports_disabled = true; | |
621 | else if (!strncmp(str, "native", 6)) | |
622 | pcie_ports_native = true; | |
623 | else if (!strncmp(str, "dpc-native", 10)) | |
624 | pcie_ports_dpc_native = true; | |
625 | ||
626 | return 1; | |
627 | } | |
628 | __setup("pcie_ports=", pcie_port_setup); | |
629 | ||
630 | /* global data */ | |
631 | ||
632 | #ifdef CONFIG_PM | |
633 | static int pcie_port_runtime_suspend(struct device *dev) | |
634 | { | |
635 | if (!to_pci_dev(dev)->bridge_d3) | |
636 | return -EBUSY; | |
637 | ||
638 | return pcie_port_device_runtime_suspend(dev); | |
639 | } | |
640 | ||
641 | static int pcie_port_runtime_idle(struct device *dev) | |
642 | { | |
643 | /* | |
644 | * Assume the PCI core has set bridge_d3 whenever it thinks the port | |
645 | * should be good to go to D3. Everything else, including moving | |
646 | * the port to D3, is handled by the PCI core. | |
647 | */ | |
648 | return to_pci_dev(dev)->bridge_d3 ? 0 : -EBUSY; | |
649 | } | |
650 | ||
651 | static const struct dev_pm_ops pcie_portdrv_pm_ops = { | |
652 | .suspend = pcie_port_device_suspend, | |
653 | .resume_noirq = pcie_port_device_resume_noirq, | |
654 | .resume = pcie_port_device_resume, | |
655 | .freeze = pcie_port_device_suspend, | |
656 | .thaw = pcie_port_device_resume, | |
657 | .poweroff = pcie_port_device_suspend, | |
658 | .restore_noirq = pcie_port_device_resume_noirq, | |
659 | .restore = pcie_port_device_resume, | |
660 | .runtime_suspend = pcie_port_runtime_suspend, | |
661 | .runtime_resume = pcie_port_device_runtime_resume, | |
662 | .runtime_idle = pcie_port_runtime_idle, | |
663 | }; | |
664 | ||
665 | #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) | |
666 | ||
667 | #else /* !PM */ | |
668 | ||
669 | #define PCIE_PORTDRV_PM_OPS NULL | |
670 | #endif /* !PM */ | |
671 | ||
672 | /* | |
673 | * pcie_portdrv_probe - Probe PCI-Express port devices | |
674 | * @dev: PCI-Express port device being probed | |
675 | * | |
676 | * If detected invokes the pcie_port_device_register() method for | |
677 | * this port device. | |
678 | * | |
679 | */ | |
680 | static int pcie_portdrv_probe(struct pci_dev *dev, | |
681 | const struct pci_device_id *id) | |
682 | { | |
683 | int type = pci_pcie_type(dev); | |
684 | int status; | |
685 | ||
686 | if (!pci_is_pcie(dev) || | |
687 | ((type != PCI_EXP_TYPE_ROOT_PORT) && | |
688 | (type != PCI_EXP_TYPE_UPSTREAM) && | |
689 | (type != PCI_EXP_TYPE_DOWNSTREAM) && | |
690 | (type != PCI_EXP_TYPE_RC_EC))) | |
691 | return -ENODEV; | |
692 | ||
693 | if (type == PCI_EXP_TYPE_RC_EC) | |
694 | pcie_link_rcec(dev); | |
695 | ||
696 | status = pcie_port_device_register(dev); | |
697 | if (status) | |
698 | return status; | |
699 | ||
700 | pci_save_state(dev); | |
701 | ||
702 | dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_NO_DIRECT_COMPLETE | | |
703 | DPM_FLAG_SMART_SUSPEND); | |
704 | ||
705 | if (pci_bridge_d3_possible(dev)) { | |
706 | /* | |
707 | * Keep the port resumed 100ms to make sure things like | |
708 | * config space accesses from userspace (lspci) will not | |
709 | * cause the port to repeatedly suspend and resume. | |
710 | */ | |
711 | pm_runtime_set_autosuspend_delay(&dev->dev, 100); | |
712 | pm_runtime_use_autosuspend(&dev->dev); | |
713 | pm_runtime_mark_last_busy(&dev->dev); | |
714 | pm_runtime_put_autosuspend(&dev->dev); | |
715 | pm_runtime_allow(&dev->dev); | |
716 | } | |
717 | ||
718 | return 0; | |
719 | } | |
720 | ||
721 | static void pcie_portdrv_remove(struct pci_dev *dev) | |
722 | { | |
723 | if (pci_bridge_d3_possible(dev)) { | |
724 | pm_runtime_forbid(&dev->dev); | |
725 | pm_runtime_get_noresume(&dev->dev); | |
726 | pm_runtime_dont_use_autosuspend(&dev->dev); | |
727 | } | |
728 | ||
729 | pcie_port_device_remove(dev); | |
62b6dee1 HC |
730 | |
731 | pci_disable_device(dev); | |
732 | } | |
733 | ||
734 | static void pcie_portdrv_shutdown(struct pci_dev *dev) | |
735 | { | |
736 | if (pci_bridge_d3_possible(dev)) { | |
737 | pm_runtime_forbid(&dev->dev); | |
738 | pm_runtime_get_noresume(&dev->dev); | |
739 | pm_runtime_dont_use_autosuspend(&dev->dev); | |
740 | } | |
741 | ||
742 | pcie_port_device_remove(dev); | |
a1ccd3d9 BH |
743 | } |
744 | ||
745 | static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev, | |
746 | pci_channel_state_t error) | |
747 | { | |
748 | if (error == pci_channel_io_frozen) | |
749 | return PCI_ERS_RESULT_NEED_RESET; | |
750 | return PCI_ERS_RESULT_CAN_RECOVER; | |
751 | } | |
752 | ||
753 | static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev) | |
754 | { | |
755 | size_t off = offsetof(struct pcie_port_service_driver, slot_reset); | |
756 | device_for_each_child(&dev->dev, &off, pcie_port_device_iter); | |
757 | ||
758 | pci_restore_state(dev); | |
759 | pci_save_state(dev); | |
760 | return PCI_ERS_RESULT_RECOVERED; | |
761 | } | |
762 | ||
763 | static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev) | |
764 | { | |
765 | return PCI_ERS_RESULT_RECOVERED; | |
766 | } | |
767 | ||
768 | /* | |
769 | * LINUX Device Driver Model | |
770 | */ | |
771 | static const struct pci_device_id port_pci_ids[] = { | |
772 | /* handle any PCI-Express port */ | |
773 | { PCI_DEVICE_CLASS(PCI_CLASS_BRIDGE_PCI_NORMAL, ~0) }, | |
774 | /* subtractive decode PCI-to-PCI bridge, class type is 060401h */ | |
775 | { PCI_DEVICE_CLASS(PCI_CLASS_BRIDGE_PCI_SUBTRACTIVE, ~0) }, | |
776 | /* handle any Root Complex Event Collector */ | |
777 | { PCI_DEVICE_CLASS(((PCI_CLASS_SYSTEM_RCEC << 8) | 0x00), ~0) }, | |
778 | { }, | |
779 | }; | |
780 | ||
781 | static const struct pci_error_handlers pcie_portdrv_err_handler = { | |
782 | .error_detected = pcie_portdrv_error_detected, | |
783 | .slot_reset = pcie_portdrv_slot_reset, | |
784 | .mmio_enabled = pcie_portdrv_mmio_enabled, | |
785 | }; | |
786 | ||
787 | static struct pci_driver pcie_portdriver = { | |
788 | .name = "pcieport", | |
7d2ebbc3 | 789 | .id_table = port_pci_ids, |
a1ccd3d9 BH |
790 | |
791 | .probe = pcie_portdrv_probe, | |
792 | .remove = pcie_portdrv_remove, | |
62b6dee1 | 793 | .shutdown = pcie_portdrv_shutdown, |
a1ccd3d9 BH |
794 | |
795 | .err_handler = &pcie_portdrv_err_handler, | |
796 | ||
797 | .driver_managed_dma = true, | |
798 | ||
799 | .driver.pm = PCIE_PORTDRV_PM_OPS, | |
800 | }; | |
801 | ||
802 | static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d) | |
803 | { | |
804 | pr_notice("%s detected: will not use MSI for PCIe PME signaling\n", | |
805 | d->ident); | |
806 | pcie_pme_disable_msi(); | |
807 | return 0; | |
808 | } | |
809 | ||
810 | static const struct dmi_system_id pcie_portdrv_dmi_table[] __initconst = { | |
811 | /* | |
812 | * Boxes that should not use MSI for PCIe PME signaling. | |
813 | */ | |
814 | { | |
815 | .callback = dmi_pcie_pme_disable_msi, | |
816 | .ident = "MSI Wind U-100", | |
817 | .matches = { | |
818 | DMI_MATCH(DMI_SYS_VENDOR, | |
819 | "MICRO-STAR INTERNATIONAL CO., LTD"), | |
820 | DMI_MATCH(DMI_PRODUCT_NAME, "U-100"), | |
821 | }, | |
822 | }, | |
823 | {} | |
824 | }; | |
825 | ||
826 | static void __init pcie_init_services(void) | |
827 | { | |
828 | pcie_aer_init(); | |
829 | pcie_pme_init(); | |
830 | pcie_dpc_init(); | |
665745f2 | 831 | pcie_bwctrl_init(); |
a1ccd3d9 BH |
832 | pcie_hp_init(); |
833 | } | |
834 | ||
835 | static int __init pcie_portdrv_init(void) | |
836 | { | |
837 | if (pcie_ports_disabled) | |
838 | return -EACCES; | |
839 | ||
840 | pcie_init_services(); | |
841 | dmi_check_system(pcie_portdrv_dmi_table); | |
842 | ||
843 | return pci_register_driver(&pcie_portdriver); | |
844 | } | |
845 | device_initcall(pcie_portdrv_init); |