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. */ |
