diff options
Diffstat (limited to 'drivers/pci/pcie/portdrv_pci.c')
-rw-r--r-- | drivers/pci/pcie/portdrv_pci.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index a49452e2aed9..127e8f169d9c 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/pcieport_if.h> | 16 | #include <linux/pcieport_if.h> |
17 | #include <linux/aer.h> | 17 | #include <linux/aer.h> |
18 | #include <linux/dmi.h> | ||
18 | 19 | ||
19 | #include "portdrv.h" | 20 | #include "portdrv.h" |
20 | #include "aer/aerdrv.h" | 21 | #include "aer/aerdrv.h" |
@@ -24,7 +25,7 @@ | |||
24 | */ | 25 | */ |
25 | #define DRIVER_VERSION "v1.0" | 26 | #define DRIVER_VERSION "v1.0" |
26 | #define DRIVER_AUTHOR "tom.l.nguyen@intel.com" | 27 | #define DRIVER_AUTHOR "tom.l.nguyen@intel.com" |
27 | #define DRIVER_DESC "PCIE Port Bus Driver" | 28 | #define DRIVER_DESC "PCIe Port Bus Driver" |
28 | MODULE_AUTHOR(DRIVER_AUTHOR); | 29 | MODULE_AUTHOR(DRIVER_AUTHOR); |
29 | MODULE_DESCRIPTION(DRIVER_DESC); | 30 | MODULE_DESCRIPTION(DRIVER_DESC); |
30 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
@@ -63,7 +64,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { | |||
63 | * pcie_portdrv_probe - Probe PCI-Express port devices | 64 | * pcie_portdrv_probe - Probe PCI-Express port devices |
64 | * @dev: PCI-Express port device being probed | 65 | * @dev: PCI-Express port device being probed |
65 | * | 66 | * |
66 | * If detected invokes the pcie_port_device_register() method for | 67 | * If detected invokes the pcie_port_device_register() method for |
67 | * this port device. | 68 | * this port device. |
68 | * | 69 | * |
69 | */ | 70 | */ |
@@ -78,7 +79,7 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, | |||
78 | (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))) | 79 | (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))) |
79 | return -ENODEV; | 80 | return -ENODEV; |
80 | 81 | ||
81 | if (!dev->irq && dev->pin) { | 82 | if (!dev->irq && dev->pin) { |
82 | dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; " | 83 | dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; " |
83 | "check vendor BIOS\n", dev->vendor, dev->device); | 84 | "check vendor BIOS\n", dev->vendor, dev->device); |
84 | } | 85 | } |
@@ -91,7 +92,7 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, | |||
91 | return 0; | 92 | return 0; |
92 | } | 93 | } |
93 | 94 | ||
94 | static void pcie_portdrv_remove (struct pci_dev *dev) | 95 | static void pcie_portdrv_remove(struct pci_dev *dev) |
95 | { | 96 | { |
96 | pcie_port_device_remove(dev); | 97 | pcie_port_device_remove(dev); |
97 | pci_disable_device(dev); | 98 | pci_disable_device(dev); |
@@ -129,14 +130,13 @@ static int error_detected_iter(struct device *device, void *data) | |||
129 | static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev, | 130 | static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev, |
130 | enum pci_channel_state error) | 131 | enum pci_channel_state error) |
131 | { | 132 | { |
132 | struct aer_broadcast_data result_data = | 133 | struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER}; |
133 | {error, PCI_ERS_RESULT_CAN_RECOVER}; | 134 | int ret; |
134 | int retval; | ||
135 | 135 | ||
136 | /* can not fail */ | 136 | /* can not fail */ |
137 | retval = device_for_each_child(&dev->dev, &result_data, error_detected_iter); | 137 | ret = device_for_each_child(&dev->dev, &data, error_detected_iter); |
138 | 138 | ||
139 | return result_data.result; | 139 | return data.result; |
140 | } | 140 | } |
141 | 141 | ||
142 | static int mmio_enabled_iter(struct device *device, void *data) | 142 | static int mmio_enabled_iter(struct device *device, void *data) |
@@ -274,10 +274,36 @@ static struct pci_driver pcie_portdriver = { | |||
274 | .driver.pm = PCIE_PORTDRV_PM_OPS, | 274 | .driver.pm = PCIE_PORTDRV_PM_OPS, |
275 | }; | 275 | }; |
276 | 276 | ||
277 | static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d) | ||
278 | { | ||
279 | pr_notice("%s detected: will not use MSI for PCIe PME signaling\n", | ||
280 | d->ident); | ||
281 | pcie_pme_disable_msi(); | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static struct dmi_system_id __initdata pcie_portdrv_dmi_table[] = { | ||
286 | /* | ||
287 | * Boxes that should not use MSI for PCIe PME signaling. | ||
288 | */ | ||
289 | { | ||
290 | .callback = dmi_pcie_pme_disable_msi, | ||
291 | .ident = "MSI Wind U-100", | ||
292 | .matches = { | ||
293 | DMI_MATCH(DMI_SYS_VENDOR, | ||
294 | "MICRO-STAR INTERNATIONAL CO., LTD"), | ||
295 | DMI_MATCH(DMI_PRODUCT_NAME, "U-100"), | ||
296 | }, | ||
297 | }, | ||
298 | {} | ||
299 | }; | ||
300 | |||
277 | static int __init pcie_portdrv_init(void) | 301 | static int __init pcie_portdrv_init(void) |
278 | { | 302 | { |
279 | int retval; | 303 | int retval; |
280 | 304 | ||
305 | dmi_check_system(pcie_portdrv_dmi_table); | ||
306 | |||
281 | retval = pcie_port_bus_register(); | 307 | retval = pcie_port_bus_register(); |
282 | if (retval) { | 308 | if (retval) { |
283 | printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval); | 309 | printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval); |
@@ -290,7 +316,7 @@ static int __init pcie_portdrv_init(void) | |||
290 | return retval; | 316 | return retval; |
291 | } | 317 | } |
292 | 318 | ||
293 | static void __exit pcie_portdrv_exit(void) | 319 | static void __exit pcie_portdrv_exit(void) |
294 | { | 320 | { |
295 | pci_unregister_driver(&pcie_portdriver); | 321 | pci_unregister_driver(&pcie_portdriver); |
296 | pcie_port_bus_unregister(); | 322 | pcie_port_bus_unregister(); |