ACPI / hotplug / PCI: Runtime resume bridge before rescan
[deliverable/linux.git] / drivers / pci / pcie / portdrv_pci.c
CommitLineData
1da177e4
LT
1/*
2 * File: portdrv_pci.c
3 * Purpose: PCI Express Port Bus Driver
4 *
5 * Copyright (C) 2004 Intel
6 * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
7 */
8
9#include <linux/module.h>
10#include <linux/pci.h>
11#include <linux/kernel.h>
12#include <linux/errno.h>
13#include <linux/pm.h>
71a83bd7 14#include <linux/pm_runtime.h>
1da177e4
LT
15#include <linux/init.h>
16#include <linux/pcieport_if.h>
4bf3392e 17#include <linux/aer.h>
c39fae14 18#include <linux/dmi.h>
28eb5f27 19#include <linux/pci-aspm.h>
1da177e4
LT
20
21#include "portdrv.h"
4bf3392e 22#include "aer/aerdrv.h"
1da177e4
LT
23
24/*
25 * Version Information
26 */
27#define DRIVER_VERSION "v1.0"
28#define DRIVER_AUTHOR "tom.l.nguyen@intel.com"
7e8af37a 29#define DRIVER_DESC "PCIe Port Bus Driver"
1da177e4
LT
30MODULE_AUTHOR(DRIVER_AUTHOR);
31MODULE_DESCRIPTION(DRIVER_DESC);
32MODULE_LICENSE("GPL");
33
79dd9182
RW
34/* If this switch is set, PCIe port native services should not be enabled. */
35bool pcie_ports_disabled;
36
28eb5f27
RW
37/*
38 * If this switch is set, ACPI _OSC will be used to determine whether or not to
39 * enable PCIe port native services.
40 */
41bool pcie_ports_auto = true;
42
79dd9182
RW
43static int __init pcie_port_setup(char *str)
44{
28eb5f27 45 if (!strncmp(str, "compat", 6)) {
79dd9182 46 pcie_ports_disabled = true;
28eb5f27
RW
47 } else if (!strncmp(str, "native", 6)) {
48 pcie_ports_disabled = false;
49 pcie_ports_auto = false;
50 } else if (!strncmp(str, "auto", 4)) {
51 pcie_ports_disabled = false;
52 pcie_ports_auto = true;
53 }
79dd9182
RW
54
55 return 1;
56}
57__setup("pcie_ports=", pcie_port_setup);
58
1da177e4 59/* global data */
1da177e4 60
fe31e697
RW
61/**
62 * pcie_clear_root_pme_status - Clear root port PME interrupt status.
63 * @dev: PCIe root port or event collector.
64 */
65void pcie_clear_root_pme_status(struct pci_dev *dev)
66{
2dcfaf85 67 pcie_capability_set_dword(dev, PCI_EXP_RTSTA, PCI_EXP_RTSTA_PME);
fe31e697
RW
68}
69
4bf3392e
ZY
70static int pcie_portdrv_restore_config(struct pci_dev *dev)
71{
72 int retval;
73
4bf3392e
ZY
74 retval = pci_enable_device(dev);
75 if (retval)
76 return retval;
77 pci_set_master(dev);
78 return 0;
79}
80
0bed208e 81#ifdef CONFIG_PM
fe31e697
RW
82static int pcie_port_resume_noirq(struct device *dev)
83{
84 struct pci_dev *pdev = to_pci_dev(dev);
85
86 /*
87 * Some BIOSes forget to clear Root PME Status bits after system wakeup
88 * which breaks ACPI-based runtime wakeup on PCI Express, so clear those
89 * bits now just in case (shouldn't hurt).
90 */
62f87c0e 91 if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT)
fe31e697
RW
92 pcie_clear_root_pme_status(pdev);
93 return 0;
94}
95
47145210 96static const struct dev_pm_ops pcie_portdrv_pm_ops = {
3a3c244c
RW
97 .suspend = pcie_port_device_suspend,
98 .resume = pcie_port_device_resume,
99 .freeze = pcie_port_device_suspend,
100 .thaw = pcie_port_device_resume,
101 .poweroff = pcie_port_device_suspend,
102 .restore = pcie_port_device_resume,
fe31e697 103 .resume_noirq = pcie_port_resume_noirq,
3a3c244c 104};
4bf3392e 105
3a3c244c 106#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
a79d682f 107
3a3c244c
RW
108#else /* !PM */
109
110#define PCIE_PORTDRV_PM_OPS NULL
111#endif /* !PM */
4bf3392e 112
1da177e4
LT
113/*
114 * pcie_portdrv_probe - Probe PCI-Express port devices
115 * @dev: PCI-Express port device being probed
116 *
40da4186 117 * If detected invokes the pcie_port_device_register() method for
1da177e4
LT
118 * this port device.
119 *
120 */
15856ad5 121static int pcie_portdrv_probe(struct pci_dev *dev,
898294c9 122 const struct pci_device_id *id)
1da177e4 123{
898294c9 124 int status;
1da177e4 125
898294c9 126 if (!pci_is_pcie(dev) ||
62f87c0e
YW
127 ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) &&
128 (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) &&
129 (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
898294c9 130 return -ENODEV;
1da177e4 131
f118c0c3
RW
132 status = pcie_port_device_register(dev);
133 if (status)
134 return status;
1da177e4 135
87d2e2ec 136 pci_save_state(dev);
1da177e4
LT
137 return 0;
138}
139
40da4186 140static void pcie_portdrv_remove(struct pci_dev *dev)
1da177e4
LT
141{
142 pcie_port_device_remove(dev);
143}
144
4bf3392e 145static int error_detected_iter(struct device *device, void *data)
60854838 146{
4bf3392e
ZY
147 struct pcie_device *pcie_device;
148 struct pcie_port_service_driver *driver;
149 struct aer_broadcast_data *result_data;
150 pci_ers_result_t status;
151
152 result_data = (struct aer_broadcast_data *) data;
153
154 if (device->bus == &pcie_port_bus_type && device->driver) {
155 driver = to_service_driver(device->driver);
156 if (!driver ||
157 !driver->err_handler ||
158 !driver->err_handler->error_detected)
159 return 0;
160
161 pcie_device = to_pcie_device(device);
162
163 /* Forward error detected message to service drivers */
164 status = driver->err_handler->error_detected(
165 pcie_device->port,
166 result_data->state);
167 result_data->result =
168 merge_result(result_data->result, status);
169 }
170
171 return 0;
60854838
HK
172}
173
4bf3392e
ZY
174static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
175 enum pci_channel_state error)
60854838 176{
40da4186 177 struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER};
4bf3392e 178
b638d7e7
BH
179 /* get true return value from &data */
180 device_for_each_child(&dev->dev, &data, error_detected_iter);
40da4186 181 return data.result;
4bf3392e
ZY
182}
183
184static int mmio_enabled_iter(struct device *device, void *data)
185{
186 struct pcie_device *pcie_device;
187 struct pcie_port_service_driver *driver;
188 pci_ers_result_t status, *result;
189
190 result = (pci_ers_result_t *) data;
191
192 if (device->bus == &pcie_port_bus_type && device->driver) {
193 driver = to_service_driver(device->driver);
194 if (driver &&
195 driver->err_handler &&
196 driver->err_handler->mmio_enabled) {
197 pcie_device = to_pcie_device(device);
198
199 /* Forward error message to service drivers */
200 status = driver->err_handler->mmio_enabled(
201 pcie_device->port);
202 *result = merge_result(*result, status);
203 }
204 }
60854838 205
60854838
HK
206 return 0;
207}
208
4bf3392e 209static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
1da177e4 210{
4bf3392e 211 pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
5823d100 212
b19441af 213 /* get true return value from &status */
b638d7e7 214 device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
4bf3392e 215 return status;
1da177e4
LT
216}
217
4bf3392e 218static int slot_reset_iter(struct device *device, void *data)
1da177e4 219{
4bf3392e
ZY
220 struct pcie_device *pcie_device;
221 struct pcie_port_service_driver *driver;
222 pci_ers_result_t status, *result;
223
224 result = (pci_ers_result_t *) data;
225
226 if (device->bus == &pcie_port_bus_type && device->driver) {
227 driver = to_service_driver(device->driver);
228 if (driver &&
229 driver->err_handler &&
230 driver->err_handler->slot_reset) {
231 pcie_device = to_pcie_device(device);
232
233 /* Forward error message to service drivers */
234 status = driver->err_handler->slot_reset(
235 pcie_device->port);
236 *result = merge_result(*result, status);
237 }
238 }
239
240 return 0;
241}
242
243static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
244{
029091df 245 pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
4bf3392e
ZY
246
247 /* If fatal, restore cfg space for possible link reset at upstream */
248 if (dev->error_state == pci_channel_io_frozen) {
e9d82888 249 dev->state_saved = true;
a79d682f 250 pci_restore_state(dev);
4bf3392e
ZY
251 pcie_portdrv_restore_config(dev);
252 pci_enable_pcie_error_reporting(dev);
253 }
254
b19441af 255 /* get true return value from &status */
b638d7e7 256 device_for_each_child(&dev->dev, &status, slot_reset_iter);
4bf3392e
ZY
257 return status;
258}
259
260static int resume_iter(struct device *device, void *data)
261{
262 struct pcie_device *pcie_device;
263 struct pcie_port_service_driver *driver;
264
265 if (device->bus == &pcie_port_bus_type && device->driver) {
266 driver = to_service_driver(device->driver);
267 if (driver &&
268 driver->err_handler &&
269 driver->err_handler->resume) {
270 pcie_device = to_pcie_device(device);
271
272 /* Forward error message to service drivers */
273 driver->err_handler->resume(pcie_device->port);
274 }
275 }
276
277 return 0;
278}
279
280static void pcie_portdrv_err_resume(struct pci_dev *dev)
281{
b638d7e7 282 device_for_each_child(&dev->dev, NULL, resume_iter);
1da177e4 283}
1da177e4
LT
284
285/*
286 * LINUX Device Driver Model
287 */
288static const struct pci_device_id port_pci_ids[] = { {
289 /* handle any PCI-Express port */
290 PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0),
291 }, { /* end: all zeroes */ }
292};
293MODULE_DEVICE_TABLE(pci, port_pci_ids);
294
49453028
SH
295static const struct pci_error_handlers pcie_portdrv_err_handler = {
296 .error_detected = pcie_portdrv_error_detected,
297 .mmio_enabled = pcie_portdrv_mmio_enabled,
298 .slot_reset = pcie_portdrv_slot_reset,
299 .resume = pcie_portdrv_err_resume,
4bf3392e
ZY
300};
301
3603a6a3 302static struct pci_driver pcie_portdriver = {
e3fb20f9 303 .name = "pcieport",
1da177e4
LT
304 .id_table = &port_pci_ids[0],
305
306 .probe = pcie_portdrv_probe,
307 .remove = pcie_portdrv_remove,
308
f7625980 309 .err_handler = &pcie_portdrv_err_handler,
3a3c244c 310
f7625980 311 .driver.pm = PCIE_PORTDRV_PM_OPS,
1da177e4
LT
312};
313
c39fae14
RW
314static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d)
315{
316 pr_notice("%s detected: will not use MSI for PCIe PME signaling\n",
227f0647 317 d->ident);
c39fae14
RW
318 pcie_pme_disable_msi();
319 return 0;
320}
321
322static struct dmi_system_id __initdata pcie_portdrv_dmi_table[] = {
323 /*
324 * Boxes that should not use MSI for PCIe PME signaling.
325 */
326 {
327 .callback = dmi_pcie_pme_disable_msi,
328 .ident = "MSI Wind U-100",
329 .matches = {
330 DMI_MATCH(DMI_SYS_VENDOR,
f7625980 331 "MICRO-STAR INTERNATIONAL CO., LTD"),
c39fae14
RW
332 DMI_MATCH(DMI_PRODUCT_NAME, "U-100"),
333 },
334 },
335 {}
336};
337
1da177e4
LT
338static int __init pcie_portdrv_init(void)
339{
20d51660 340 int retval;
1da177e4 341
fe31e697
RW
342 if (pcie_ports_disabled)
343 return pci_register_driver(&pcie_portdriver);
79dd9182 344
c39fae14
RW
345 dmi_check_system(pcie_portdrv_dmi_table);
346
20d51660
RD
347 retval = pcie_port_bus_register();
348 if (retval) {
349 printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
350 goto out;
351 }
3603a6a3 352 retval = pci_register_driver(&pcie_portdriver);
1da177e4
LT
353 if (retval)
354 pcie_port_bus_unregister();
20d51660 355 out:
1da177e4
LT
356 return retval;
357}
358
1da177e4 359module_init(pcie_portdrv_init);
This page took 1.095379 seconds and 5 git commands to generate.