diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-16 10:49:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-16 10:49:54 -0400 |
commit | 4406c56d0a4da7a37b9180abeaece6cd00bcc874 (patch) | |
tree | 65a85fa73a25d24cbed6d163fdcf8df1b934a0be /drivers/pci/pci.c | |
parent | 6b7b352f2102e21f9d8f38e932f01d9c5705c073 (diff) | |
parent | 5e3573db2bd5db6925159279d99576a4635bdb66 (diff) |
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (75 commits)
PCI hotplug: clean up acpi_run_hpp()
PCI hotplug: acpiphp: use generic pci_configure_slot()
PCI hotplug: shpchp: use generic pci_configure_slot()
PCI hotplug: pciehp: use generic pci_configure_slot()
PCI hotplug: add pci_configure_slot()
PCI hotplug: clean up acpi_get_hp_params_from_firmware() interface
PCI hotplug: acpiphp: don't cache hotplug_params in acpiphp_bridge
PCI hotplug: acpiphp: remove superfluous _HPP/_HPX evaluation
PCI: Clear saved_state after the state has been restored
PCI PM: Return error codes from pci_pm_resume()
PCI: use dev_printk in quirk messages
PCI / PCIe portdrv: Fix pcie_portdrv_slot_reset()
PCI Hotplug: convert acpi_pci_detect_ejectable() to take an acpi_handle
PCI Hotplug: acpiphp: find bridges the easy way
PCI: pcie portdrv: remove unused variable
PCI / ACPI PM: Propagate wake-up enable for devices w/o ACPI support
ACPI PM: Replace wakeup.prepared with reference counter
PCI PM: Introduce device flag wakeup_prepared
PCI / ACPI PM: Rework some debug messages
PCI PM: Simplify PCI wake-up code
...
Fixed up conflict in arch/powerpc/kernel/pci_64.c due to OF device tree
scanning having been moved and merged for the 32- and 64-bit cases. The
'needs_freset' initialization added in 6e19314cc ("PCI/powerpc: support
PCIe fundamental reset") is now in arch/powerpc/kernel/pci_of_scan.c.
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 106 |
1 files changed, 95 insertions, 11 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7b70312181d7..6edecff0b419 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -41,6 +41,12 @@ int pci_domains_supported = 1; | |||
41 | unsigned long pci_cardbus_io_size = DEFAULT_CARDBUS_IO_SIZE; | 41 | unsigned long pci_cardbus_io_size = DEFAULT_CARDBUS_IO_SIZE; |
42 | unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE; | 42 | unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE; |
43 | 43 | ||
44 | #define DEFAULT_HOTPLUG_IO_SIZE (256) | ||
45 | #define DEFAULT_HOTPLUG_MEM_SIZE (2*1024*1024) | ||
46 | /* pci=hpmemsize=nnM,hpiosize=nn can override this */ | ||
47 | unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE; | ||
48 | unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE; | ||
49 | |||
44 | /** | 50 | /** |
45 | * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children | 51 | * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children |
46 | * @bus: pointer to PCI bus structure to search | 52 | * @bus: pointer to PCI bus structure to search |
@@ -848,6 +854,7 @@ pci_restore_state(struct pci_dev *dev) | |||
848 | 854 | ||
849 | if (!dev->state_saved) | 855 | if (!dev->state_saved) |
850 | return 0; | 856 | return 0; |
857 | |||
851 | /* PCI Express register must be restored first */ | 858 | /* PCI Express register must be restored first */ |
852 | pci_restore_pcie_state(dev); | 859 | pci_restore_pcie_state(dev); |
853 | 860 | ||
@@ -869,6 +876,8 @@ pci_restore_state(struct pci_dev *dev) | |||
869 | pci_restore_msi_state(dev); | 876 | pci_restore_msi_state(dev); |
870 | pci_restore_iov_state(dev); | 877 | pci_restore_iov_state(dev); |
871 | 878 | ||
879 | dev->state_saved = false; | ||
880 | |||
872 | return 0; | 881 | return 0; |
873 | } | 882 | } |
874 | 883 | ||
@@ -1214,30 +1223,40 @@ void pci_pme_active(struct pci_dev *dev, bool enable) | |||
1214 | */ | 1223 | */ |
1215 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) | 1224 | int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable) |
1216 | { | 1225 | { |
1217 | int error = 0; | 1226 | int ret = 0; |
1218 | bool pme_done = false; | ||
1219 | 1227 | ||
1220 | if (enable && !device_may_wakeup(&dev->dev)) | 1228 | if (enable && !device_may_wakeup(&dev->dev)) |
1221 | return -EINVAL; | 1229 | return -EINVAL; |
1222 | 1230 | ||
1231 | /* Don't do the same thing twice in a row for one device. */ | ||
1232 | if (!!enable == !!dev->wakeup_prepared) | ||
1233 | return 0; | ||
1234 | |||
1223 | /* | 1235 | /* |
1224 | * According to "PCI System Architecture" 4th ed. by Tom Shanley & Don | 1236 | * According to "PCI System Architecture" 4th ed. by Tom Shanley & Don |
1225 | * Anderson we should be doing PME# wake enable followed by ACPI wake | 1237 | * Anderson we should be doing PME# wake enable followed by ACPI wake |
1226 | * enable. To disable wake-up we call the platform first, for symmetry. | 1238 | * enable. To disable wake-up we call the platform first, for symmetry. |
1227 | */ | 1239 | */ |
1228 | 1240 | ||
1229 | if (!enable && platform_pci_can_wakeup(dev)) | 1241 | if (enable) { |
1230 | error = platform_pci_sleep_wake(dev, false); | 1242 | int error; |
1231 | |||
1232 | if (!enable || pci_pme_capable(dev, state)) { | ||
1233 | pci_pme_active(dev, enable); | ||
1234 | pme_done = true; | ||
1235 | } | ||
1236 | 1243 | ||
1237 | if (enable && platform_pci_can_wakeup(dev)) | 1244 | if (pci_pme_capable(dev, state)) |
1245 | pci_pme_active(dev, true); | ||
1246 | else | ||
1247 | ret = 1; | ||
1238 | error = platform_pci_sleep_wake(dev, true); | 1248 | error = platform_pci_sleep_wake(dev, true); |
1249 | if (ret) | ||
1250 | ret = error; | ||
1251 | if (!ret) | ||
1252 | dev->wakeup_prepared = true; | ||
1253 | } else { | ||
1254 | platform_pci_sleep_wake(dev, false); | ||
1255 | pci_pme_active(dev, false); | ||
1256 | dev->wakeup_prepared = false; | ||
1257 | } | ||
1239 | 1258 | ||
1240 | return pme_done ? 0 : error; | 1259 | return ret; |
1241 | } | 1260 | } |
1242 | 1261 | ||
1243 | /** | 1262 | /** |
@@ -1356,6 +1375,7 @@ void pci_pm_init(struct pci_dev *dev) | |||
1356 | int pm; | 1375 | int pm; |
1357 | u16 pmc; | 1376 | u16 pmc; |
1358 | 1377 | ||
1378 | dev->wakeup_prepared = false; | ||
1359 | dev->pm_cap = 0; | 1379 | dev->pm_cap = 0; |
1360 | 1380 | ||
1361 | /* find PCI PM capability in list */ | 1381 | /* find PCI PM capability in list */ |
@@ -2262,6 +2282,22 @@ int __pci_reset_function(struct pci_dev *dev) | |||
2262 | EXPORT_SYMBOL_GPL(__pci_reset_function); | 2282 | EXPORT_SYMBOL_GPL(__pci_reset_function); |
2263 | 2283 | ||
2264 | /** | 2284 | /** |
2285 | * pci_probe_reset_function - check whether the device can be safely reset | ||
2286 | * @dev: PCI device to reset | ||
2287 | * | ||
2288 | * Some devices allow an individual function to be reset without affecting | ||
2289 | * other functions in the same device. The PCI device must be responsive | ||
2290 | * to PCI config space in order to use this function. | ||
2291 | * | ||
2292 | * Returns 0 if the device function can be reset or negative if the | ||
2293 | * device doesn't support resetting a single function. | ||
2294 | */ | ||
2295 | int pci_probe_reset_function(struct pci_dev *dev) | ||
2296 | { | ||
2297 | return pci_dev_reset(dev, 1); | ||
2298 | } | ||
2299 | |||
2300 | /** | ||
2265 | * pci_reset_function - quiesce and reset a PCI device function | 2301 | * pci_reset_function - quiesce and reset a PCI device function |
2266 | * @dev: PCI device to reset | 2302 | * @dev: PCI device to reset |
2267 | * | 2303 | * |
@@ -2504,6 +2540,50 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) | |||
2504 | return 0; | 2540 | return 0; |
2505 | } | 2541 | } |
2506 | 2542 | ||
2543 | /** | ||
2544 | * pci_set_vga_state - set VGA decode state on device and parents if requested | ||
2545 | * @dev the PCI device | ||
2546 | * @decode - true = enable decoding, false = disable decoding | ||
2547 | * @command_bits PCI_COMMAND_IO and/or PCI_COMMAND_MEMORY | ||
2548 | * @change_bridge - traverse ancestors and change bridges | ||
2549 | */ | ||
2550 | int pci_set_vga_state(struct pci_dev *dev, bool decode, | ||
2551 | unsigned int command_bits, bool change_bridge) | ||
2552 | { | ||
2553 | struct pci_bus *bus; | ||
2554 | struct pci_dev *bridge; | ||
2555 | u16 cmd; | ||
2556 | |||
2557 | WARN_ON(command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY)); | ||
2558 | |||
2559 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
2560 | if (decode == true) | ||
2561 | cmd |= command_bits; | ||
2562 | else | ||
2563 | cmd &= ~command_bits; | ||
2564 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
2565 | |||
2566 | if (change_bridge == false) | ||
2567 | return 0; | ||
2568 | |||
2569 | bus = dev->bus; | ||
2570 | while (bus) { | ||
2571 | bridge = bus->self; | ||
2572 | if (bridge) { | ||
2573 | pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, | ||
2574 | &cmd); | ||
2575 | if (decode == true) | ||
2576 | cmd |= PCI_BRIDGE_CTL_VGA; | ||
2577 | else | ||
2578 | cmd &= ~PCI_BRIDGE_CTL_VGA; | ||
2579 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, | ||
2580 | cmd); | ||
2581 | } | ||
2582 | bus = bus->parent; | ||
2583 | } | ||
2584 | return 0; | ||
2585 | } | ||
2586 | |||
2507 | #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE | 2587 | #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE |
2508 | static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0}; | 2588 | static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0}; |
2509 | spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED; | 2589 | spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED; |
@@ -2672,6 +2752,10 @@ static int __init pci_setup(char *str) | |||
2672 | strlen(str + 19)); | 2752 | strlen(str + 19)); |
2673 | } else if (!strncmp(str, "ecrc=", 5)) { | 2753 | } else if (!strncmp(str, "ecrc=", 5)) { |
2674 | pcie_ecrc_get_policy(str + 5); | 2754 | pcie_ecrc_get_policy(str + 5); |
2755 | } else if (!strncmp(str, "hpiosize=", 9)) { | ||
2756 | pci_hotplug_io_size = memparse(str + 9, &str); | ||
2757 | } else if (!strncmp(str, "hpmemsize=", 10)) { | ||
2758 | pci_hotplug_mem_size = memparse(str + 10, &str); | ||
2675 | } else { | 2759 | } else { |
2676 | printk(KERN_ERR "PCI: Unknown option `%s'\n", | 2760 | printk(KERN_ERR "PCI: Unknown option `%s'\n", |
2677 | str); | 2761 | str); |