diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-08 16:55:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-08 16:55:39 -0500 |
commit | 00cd25b29ba946b7d0907157577ab5cf421bd50e (patch) | |
tree | 57d76cf7a495ea8f1ac662e12442bf6164ea3024 | |
parent | e2b6d02cca533715d6be40fdfc32d3cc47333358 (diff) | |
parent | b49bfd32901625e4adcfee011d2b32a43b4db67d (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6:
PCIe AER: prevent AER injection if hardware masks error reporting
PCI/PM: Use per-device D3 delays
PCI: Check the node argument passed to cpumask_of_node
PCI: AER: fix aer inject result in kernel oops
PCI: pcie portdrv: style cleanup
-rw-r--r-- | drivers/net/sky2.c | 1 | ||||
-rw-r--r-- | drivers/pci/pci-sysfs.c | 6 | ||||
-rw-r--r-- | drivers/pci/pci.c | 19 | ||||
-rw-r--r-- | drivers/pci/pcie/aer/aer_inject.c | 28 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 16 | ||||
-rw-r--r-- | drivers/pci/pcie/portdrv_pci.c | 17 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
7 files changed, 62 insertions, 26 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 1c01b96c9611..2d28d58200d0 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -4684,6 +4684,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
4684 | INIT_WORK(&hw->restart_work, sky2_restart); | 4684 | INIT_WORK(&hw->restart_work, sky2_restart); |
4685 | 4685 | ||
4686 | pci_set_drvdata(pdev, hw); | 4686 | pci_set_drvdata(pdev, hw); |
4687 | pdev->d3_delay = 150; | ||
4687 | 4688 | ||
4688 | return 0; | 4689 | return 0; |
4689 | 4690 | ||
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index c5df94e86678..807224ec8351 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -75,7 +75,8 @@ static ssize_t local_cpus_show(struct device *dev, | |||
75 | int len; | 75 | int len; |
76 | 76 | ||
77 | #ifdef CONFIG_NUMA | 77 | #ifdef CONFIG_NUMA |
78 | mask = cpumask_of_node(dev_to_node(dev)); | 78 | mask = (dev_to_node(dev) == -1) ? cpu_online_mask : |
79 | cpumask_of_node(dev_to_node(dev)); | ||
79 | #else | 80 | #else |
80 | mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); | 81 | mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); |
81 | #endif | 82 | #endif |
@@ -93,7 +94,8 @@ static ssize_t local_cpulist_show(struct device *dev, | |||
93 | int len; | 94 | int len; |
94 | 95 | ||
95 | #ifdef CONFIG_NUMA | 96 | #ifdef CONFIG_NUMA |
96 | mask = cpumask_of_node(dev_to_node(dev)); | 97 | mask = (dev_to_node(dev) == -1) ? cpu_online_mask : |
98 | cpumask_of_node(dev_to_node(dev)); | ||
97 | #else | 99 | #else |
98 | mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); | 100 | mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); |
99 | #endif | 101 | #endif |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0906599ebfde..315fea47e784 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -29,7 +29,17 @@ const char *pci_power_names[] = { | |||
29 | }; | 29 | }; |
30 | EXPORT_SYMBOL_GPL(pci_power_names); | 30 | EXPORT_SYMBOL_GPL(pci_power_names); |
31 | 31 | ||
32 | unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT; | 32 | unsigned int pci_pm_d3_delay; |
33 | |||
34 | static void pci_dev_d3_sleep(struct pci_dev *dev) | ||
35 | { | ||
36 | unsigned int delay = dev->d3_delay; | ||
37 | |||
38 | if (delay < pci_pm_d3_delay) | ||
39 | delay = pci_pm_d3_delay; | ||
40 | |||
41 | msleep(delay); | ||
42 | } | ||
33 | 43 | ||
34 | #ifdef CONFIG_PCI_DOMAINS | 44 | #ifdef CONFIG_PCI_DOMAINS |
35 | int pci_domains_supported = 1; | 45 | int pci_domains_supported = 1; |
@@ -522,7 +532,7 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
522 | /* Mandatory power management transition delays */ | 532 | /* Mandatory power management transition delays */ |
523 | /* see PCI PM 1.1 5.6.1 table 18 */ | 533 | /* see PCI PM 1.1 5.6.1 table 18 */ |
524 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) | 534 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) |
525 | msleep(pci_pm_d3_delay); | 535 | pci_dev_d3_sleep(dev); |
526 | else if (state == PCI_D2 || dev->current_state == PCI_D2) | 536 | else if (state == PCI_D2 || dev->current_state == PCI_D2) |
527 | udelay(PCI_PM_D2_DELAY); | 537 | udelay(PCI_PM_D2_DELAY); |
528 | 538 | ||
@@ -1409,6 +1419,7 @@ void pci_pm_init(struct pci_dev *dev) | |||
1409 | } | 1419 | } |
1410 | 1420 | ||
1411 | dev->pm_cap = pm; | 1421 | dev->pm_cap = pm; |
1422 | dev->d3_delay = PCI_PM_D3_WAIT; | ||
1412 | 1423 | ||
1413 | dev->d1_support = false; | 1424 | dev->d1_support = false; |
1414 | dev->d2_support = false; | 1425 | dev->d2_support = false; |
@@ -2247,12 +2258,12 @@ static int pci_pm_reset(struct pci_dev *dev, int probe) | |||
2247 | csr &= ~PCI_PM_CTRL_STATE_MASK; | 2258 | csr &= ~PCI_PM_CTRL_STATE_MASK; |
2248 | csr |= PCI_D3hot; | 2259 | csr |= PCI_D3hot; |
2249 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); | 2260 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); |
2250 | msleep(pci_pm_d3_delay); | 2261 | pci_dev_d3_sleep(dev); |
2251 | 2262 | ||
2252 | csr &= ~PCI_PM_CTRL_STATE_MASK; | 2263 | csr &= ~PCI_PM_CTRL_STATE_MASK; |
2253 | csr |= PCI_D0; | 2264 | csr |= PCI_D0; |
2254 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); | 2265 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, csr); |
2255 | msleep(pci_pm_d3_delay); | 2266 | pci_dev_d3_sleep(dev); |
2256 | 2267 | ||
2257 | return 0; | 2268 | return 0; |
2258 | } | 2269 | } |
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 797d47809f7a..8c30a9544d61 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c | |||
@@ -321,7 +321,7 @@ static int aer_inject(struct aer_error_inj *einj) | |||
321 | unsigned long flags; | 321 | unsigned long flags; |
322 | unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn); | 322 | unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn); |
323 | int pos_cap_err, rp_pos_cap_err; | 323 | int pos_cap_err, rp_pos_cap_err; |
324 | u32 sever; | 324 | u32 sever, mask; |
325 | int ret = 0; | 325 | int ret = 0; |
326 | 326 | ||
327 | dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn); | 327 | dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn); |
@@ -374,6 +374,24 @@ static int aer_inject(struct aer_error_inj *einj) | |||
374 | err->header_log2 = einj->header_log2; | 374 | err->header_log2 = einj->header_log2; |
375 | err->header_log3 = einj->header_log3; | 375 | err->header_log3 = einj->header_log3; |
376 | 376 | ||
377 | pci_read_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK, &mask); | ||
378 | if (einj->cor_status && !(einj->cor_status & ~mask)) { | ||
379 | ret = -EINVAL; | ||
380 | printk(KERN_WARNING "The correctable error(s) is masked " | ||
381 | "by device\n"); | ||
382 | spin_unlock_irqrestore(&inject_lock, flags); | ||
383 | goto out_put; | ||
384 | } | ||
385 | |||
386 | pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK, &mask); | ||
387 | if (einj->uncor_status && !(einj->uncor_status & ~mask)) { | ||
388 | ret = -EINVAL; | ||
389 | printk(KERN_WARNING "The uncorrectable error(s) is masked " | ||
390 | "by device\n"); | ||
391 | spin_unlock_irqrestore(&inject_lock, flags); | ||
392 | goto out_put; | ||
393 | } | ||
394 | |||
377 | rperr = __find_aer_error_by_dev(rpdev); | 395 | rperr = __find_aer_error_by_dev(rpdev); |
378 | if (!rperr) { | 396 | if (!rperr) { |
379 | rperr = rperr_alloc; | 397 | rperr = rperr_alloc; |
@@ -413,8 +431,14 @@ static int aer_inject(struct aer_error_inj *einj) | |||
413 | if (ret) | 431 | if (ret) |
414 | goto out_put; | 432 | goto out_put; |
415 | 433 | ||
416 | if (find_aer_device(rpdev, &edev)) | 434 | if (find_aer_device(rpdev, &edev)) { |
435 | if (!get_service_data(edev)) { | ||
436 | printk(KERN_WARNING "AER service is not initialized\n"); | ||
437 | ret = -EINVAL; | ||
438 | goto out_put; | ||
439 | } | ||
417 | aer_irq(-1, edev); | 440 | aer_irq(-1, edev); |
441 | } | ||
418 | else | 442 | else |
419 | ret = -EINVAL; | 443 | ret = -EINVAL; |
420 | out_put: | 444 | out_put: |
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 413262eb95b7..b174188ac121 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
@@ -27,7 +27,7 @@ | |||
27 | */ | 27 | */ |
28 | static void release_pcie_device(struct device *dev) | 28 | static void release_pcie_device(struct device *dev) |
29 | { | 29 | { |
30 | kfree(to_pcie_device(dev)); | 30 | kfree(to_pcie_device(dev)); |
31 | } | 31 | } |
32 | 32 | ||
33 | /** | 33 | /** |
@@ -346,12 +346,11 @@ static int suspend_iter(struct device *dev, void *data) | |||
346 | { | 346 | { |
347 | struct pcie_port_service_driver *service_driver; | 347 | struct pcie_port_service_driver *service_driver; |
348 | 348 | ||
349 | if ((dev->bus == &pcie_port_bus_type) && | 349 | if ((dev->bus == &pcie_port_bus_type) && dev->driver) { |
350 | (dev->driver)) { | 350 | service_driver = to_service_driver(dev->driver); |
351 | service_driver = to_service_driver(dev->driver); | 351 | if (service_driver->suspend) |
352 | if (service_driver->suspend) | 352 | service_driver->suspend(to_pcie_device(dev)); |
353 | service_driver->suspend(to_pcie_device(dev)); | 353 | } |
354 | } | ||
355 | return 0; | 354 | return 0; |
356 | } | 355 | } |
357 | 356 | ||
@@ -494,6 +493,7 @@ int pcie_port_service_register(struct pcie_port_service_driver *new) | |||
494 | 493 | ||
495 | return driver_register(&new->driver); | 494 | return driver_register(&new->driver); |
496 | } | 495 | } |
496 | EXPORT_SYMBOL(pcie_port_service_register); | ||
497 | 497 | ||
498 | /** | 498 | /** |
499 | * pcie_port_service_unregister - unregister PCI Express port service driver | 499 | * pcie_port_service_unregister - unregister PCI Express port service driver |
@@ -503,6 +503,4 @@ void pcie_port_service_unregister(struct pcie_port_service_driver *drv) | |||
503 | { | 503 | { |
504 | driver_unregister(&drv->driver); | 504 | driver_unregister(&drv->driver); |
505 | } | 505 | } |
506 | |||
507 | EXPORT_SYMBOL(pcie_port_service_register); | ||
508 | EXPORT_SYMBOL(pcie_port_service_unregister); | 506 | EXPORT_SYMBOL(pcie_port_service_unregister); |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 34d65172a4d7..13c8972886e6 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -63,7 +63,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = { | |||
63 | * pcie_portdrv_probe - Probe PCI-Express port devices | 63 | * pcie_portdrv_probe - Probe PCI-Express port devices |
64 | * @dev: PCI-Express port device being probed | 64 | * @dev: PCI-Express port device being probed |
65 | * | 65 | * |
66 | * If detected invokes the pcie_port_device_register() method for | 66 | * If detected invokes the pcie_port_device_register() method for |
67 | * this port device. | 67 | * this port device. |
68 | * | 68 | * |
69 | */ | 69 | */ |
@@ -78,7 +78,7 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, | |||
78 | (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))) | 78 | (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))) |
79 | return -ENODEV; | 79 | return -ENODEV; |
80 | 80 | ||
81 | if (!dev->irq && dev->pin) { | 81 | if (!dev->irq && dev->pin) { |
82 | dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; " | 82 | dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; " |
83 | "check vendor BIOS\n", dev->vendor, dev->device); | 83 | "check vendor BIOS\n", dev->vendor, dev->device); |
84 | } | 84 | } |
@@ -91,7 +91,7 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, | |||
91 | return 0; | 91 | return 0; |
92 | } | 92 | } |
93 | 93 | ||
94 | static void pcie_portdrv_remove (struct pci_dev *dev) | 94 | static void pcie_portdrv_remove(struct pci_dev *dev) |
95 | { | 95 | { |
96 | pcie_port_device_remove(dev); | 96 | pcie_port_device_remove(dev); |
97 | pci_disable_device(dev); | 97 | pci_disable_device(dev); |
@@ -129,14 +129,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, | 129 | static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev, |
130 | enum pci_channel_state error) | 130 | enum pci_channel_state error) |
131 | { | 131 | { |
132 | struct aer_broadcast_data result_data = | 132 | struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER}; |
133 | {error, PCI_ERS_RESULT_CAN_RECOVER}; | 133 | int ret; |
134 | int retval; | ||
135 | 134 | ||
136 | /* can not fail */ | 135 | /* can not fail */ |
137 | retval = device_for_each_child(&dev->dev, &result_data, error_detected_iter); | 136 | ret = device_for_each_child(&dev->dev, &data, error_detected_iter); |
138 | 137 | ||
139 | return result_data.result; | 138 | return data.result; |
140 | } | 139 | } |
141 | 140 | ||
142 | static int mmio_enabled_iter(struct device *device, void *data) | 141 | static int mmio_enabled_iter(struct device *device, void *data) |
@@ -290,7 +289,7 @@ static int __init pcie_portdrv_init(void) | |||
290 | return retval; | 289 | return retval; |
291 | } | 290 | } |
292 | 291 | ||
293 | static void __exit pcie_portdrv_exit(void) | 292 | static void __exit pcie_portdrv_exit(void) |
294 | { | 293 | { |
295 | pci_unregister_driver(&pcie_portdriver); | 294 | pci_unregister_driver(&pcie_portdriver); |
296 | pcie_port_bus_unregister(); | 295 | pcie_port_bus_unregister(); |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 5da0690d9cee..174e5392e51e 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -243,6 +243,7 @@ struct pci_dev { | |||
243 | unsigned int d2_support:1; /* Low power state D2 is supported */ | 243 | unsigned int d2_support:1; /* Low power state D2 is supported */ |
244 | unsigned int no_d1d2:1; /* Only allow D0 and D3 */ | 244 | unsigned int no_d1d2:1; /* Only allow D0 and D3 */ |
245 | unsigned int wakeup_prepared:1; | 245 | unsigned int wakeup_prepared:1; |
246 | unsigned int d3_delay; /* D3->D0 transition time in ms */ | ||
246 | 247 | ||
247 | #ifdef CONFIG_PCIEASPM | 248 | #ifdef CONFIG_PCIEASPM |
248 | struct pcie_link_state *link_state; /* ASPM link state. */ | 249 | struct pcie_link_state *link_state; /* ASPM link state. */ |