diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-22 19:39:28 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-22 19:39:28 -0500 |
| commit | e1ba84597c9012b9f9075aac283ac7537d7561ba (patch) | |
| tree | 41ab1a74c71ce55e72ef73424346e8e0a7f4616e /drivers/pci/hotplug | |
| parent | 60eaa0190f6b39dce18eb1975d9773ed8bc9a534 (diff) | |
| parent | cef09b808e584c13b7126b83dc37c80b00234137 (diff) | |
Merge tag 'pci-v3.14-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
"PCI changes for the v3.14 merge window:
Resource management
- Change pci_bus_region addresses to dma_addr_t (Bjorn Helgaas)
- Support 64-bit AGP BARs (Bjorn Helgaas, Yinghai Lu)
- Add pci_bus_address() to get bus address of a BAR (Bjorn Helgaas)
- Use pci_resource_start() for CPU address of AGP BARs (Bjorn Helgaas)
- Enforce bus address limits in resource allocation (Yinghai Lu)
- Allocate 64-bit BARs above 4G when possible (Yinghai Lu)
- Convert pcibios_resource_to_bus() to take pci_bus, not pci_dev (Yinghai Lu)
PCI device hotplug
- Major rescan/remove locking update (Rafael J. Wysocki)
- Make ioapic builtin only (not modular) (Yinghai Lu)
- Fix release/free issues (Yinghai Lu)
- Clean up pciehp (Bjorn Helgaas)
- Announce pciehp slot info during enumeration (Bjorn Helgaas)
MSI
- Add pci_msi_vec_count(), pci_msix_vec_count() (Alexander Gordeev)
- Add pci_enable_msi_range(), pci_enable_msix_range() (Alexander Gordeev)
- Deprecate "tri-state" interfaces: fail/success/fail+info (Alexander Gordeev)
- Export MSI mode using attributes, not kobjects (Greg Kroah-Hartman)
- Drop "irq" param from *_restore_msi_irqs() (DuanZhenzhong)
SR-IOV
- Clear NumVFs when disabling SR-IOV in sriov_init() (ethan.zhao)
Virtualization
- Add support for save/restore of extended capabilities (Alex Williamson)
- Add Virtual Channel to save/restore support (Alex Williamson)
- Never treat a VF as a multifunction device (Alex Williamson)
- Add pci_try_reset_function(), et al (Alex Williamson)
AER
- Ignore non-PCIe error sources (Betty Dall)
- Support ACPI HEST error sources for domains other than 0 (Betty Dall)
- Consolidate HEST error source parsers (Bjorn Helgaas)
- Add a TLP header print helper (Borislav Petkov)
Freescale i.MX6
- Remove unnecessary code (Fabio Estevam)
- Make reset-gpio optional (Marek Vasut)
- Report "link up" only after link training completes (Marek Vasut)
- Start link in Gen1 before negotiating for Gen2 mode (Marek Vasut)
- Fix PCIe startup code (Richard Zhu)
Marvell MVEBU
- Remove duplicate of_clk_get_by_name() call (Andrew Lunn)
- Drop writes to bridge Secondary Status register (Jason Gunthorpe)
- Obey bridge PCI_COMMAND_MEM and PCI_COMMAND_IO bits (Jason Gunthorpe)
- Support a bridge with no IO port window (Jason Gunthorpe)
- Use max_t() instead of max(resource_size_t,) (Jingoo Han)
- Remove redundant of_match_ptr (Sachin Kamat)
- Call pci_ioremap_io() at startup instead of dynamically (Thomas Petazzoni)
NVIDIA Tegra
- Disable Gen2 for Tegra20 and Tegra30 (Eric Brower)
Renesas R-Car
- Add runtime PM support (Valentine Barshak)
- Fix rcar_pci_probe() return value check (Wei Yongjun)
Synopsys DesignWare
- Fix crash in dw_msi_teardown_irq() (Bjørn Erik Nilsen)
- Remove redundant call to pci_write_config_word() (Bjørn Erik Nilsen)
- Fix missing MSI IRQs (Harro Haan)
- Add dw_pcie prefix before cfg_read/write (Pratyush Anand)
- Fix I/O transfers by using CPU (not realio) address (Pratyush Anand)
- Whitespace cleanup (Jingoo Han)
EISA
- Call put_device() if device_register() fails (Levente Kurusa)
- Revert EISA initialization breakage ((Bjorn Helgaas)
Miscellaneous
- Remove unused code, including PCIe 3.0 interfaces (Stephen Hemminger)
- Prevent bus conflicts while checking for bridge apertures (Bjorn Helgaas)
- Stop clearing bridge Secondary Status when setting up I/O aperture (Bjorn Helgaas)
- Use dev_is_pci() to identify PCI devices (Yijing Wang)
- Deprecate DEFINE_PCI_DEVICE_TABLE (Joe Perches)
- Update documentation 00-INDEX (Erik Ekman)"
* tag 'pci-v3.14-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (119 commits)
Revert "EISA: Initialize device before its resources"
Revert "EISA: Log device resources in dmesg"
vfio-pci: Use pci "try" reset interface
PCI: Check parent kobject in pci_destroy_dev()
xen/pcifront: Use global PCI rescan-remove locking
powerpc/eeh: Use global PCI rescan-remove locking
PCI: Fix pci_check_and_unmask_intx() comment typos
PCI: Add pci_try_reset_function(), pci_try_reset_slot(), pci_try_reset_bus()
MPT / PCI: Use pci_stop_and_remove_bus_device_locked()
platform / x86: Use global PCI rescan-remove locking
PCI: hotplug: Use global PCI rescan-remove locking
pcmcia: Use global PCI rescan-remove locking
ACPI / hotplug / PCI: Use global PCI rescan-remove locking
ACPI / PCI: Use global PCI rescan-remove locking in PCI root hotplug
PCI: Add global pci_lock_rescan_remove()
PCI: Cleanup pci.h whitespace
PCI: Reorder so actual code comes before stubs
PCI/AER: Support ACPI HEST AER error sources for PCI domains other than 0
ACPICA: Add helper macros to extract bus/segment numbers from HEST table.
PCI: Make local functions static
...
Diffstat (limited to 'drivers/pci/hotplug')
| -rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 5 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_core.c | 2 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 43 | ||||
| -rw-r--r-- | drivers/pci/hotplug/cpci_hotplug_pci.c | 14 | ||||
| -rw-r--r-- | drivers/pci/hotplug/cpqphp_pci.c | 8 | ||||
| -rw-r--r-- | drivers/pci/hotplug/ibmphp_core.c | 13 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp.h | 15 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 17 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 90 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 380 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 23 | ||||
| -rw-r--r-- | drivers/pci/hotplug/rpadlpar_core.c | 19 | ||||
| -rw-r--r-- | drivers/pci/hotplug/rpaphp_core.c | 4 | ||||
| -rw-r--r-- | drivers/pci/hotplug/s390_pci_hpc.c | 4 | ||||
| -rw-r--r-- | drivers/pci/hotplug/sgi_hotplug.c | 5 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_pci.c | 18 |
16 files changed, 304 insertions, 356 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 1592dbe4f904..b6162be4df40 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
| @@ -77,6 +77,8 @@ struct acpiphp_bridge { | |||
| 77 | 77 | ||
| 78 | /* PCI-to-PCI bridge device */ | 78 | /* PCI-to-PCI bridge device */ |
| 79 | struct pci_dev *pci_dev; | 79 | struct pci_dev *pci_dev; |
| 80 | |||
| 81 | bool is_going_away; | ||
| 80 | }; | 82 | }; |
| 81 | 83 | ||
| 82 | 84 | ||
| @@ -150,6 +152,7 @@ struct acpiphp_attention_info | |||
| 150 | /* slot flags */ | 152 | /* slot flags */ |
| 151 | 153 | ||
| 152 | #define SLOT_ENABLED (0x00000001) | 154 | #define SLOT_ENABLED (0x00000001) |
| 155 | #define SLOT_IS_GOING_AWAY (0x00000002) | ||
| 153 | 156 | ||
| 154 | /* function flags */ | 157 | /* function flags */ |
| 155 | 158 | ||
| @@ -169,7 +172,7 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); | |||
| 169 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); | 172 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); |
| 170 | 173 | ||
| 171 | int acpiphp_enable_slot(struct acpiphp_slot *slot); | 174 | int acpiphp_enable_slot(struct acpiphp_slot *slot); |
| 172 | int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); | 175 | int acpiphp_disable_slot(struct acpiphp_slot *slot); |
| 173 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot); | 176 | u8 acpiphp_get_power_status(struct acpiphp_slot *slot); |
| 174 | u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); | 177 | u8 acpiphp_get_attention_status(struct acpiphp_slot *slot); |
| 175 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot); | 178 | u8 acpiphp_get_latch_status(struct acpiphp_slot *slot); |
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index dca66bc44578..728c31f4c2c5 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
| @@ -156,7 +156,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) | |||
| 156 | pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); | 156 | pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot)); |
| 157 | 157 | ||
| 158 | /* disable the specified slot */ | 158 | /* disable the specified slot */ |
| 159 | return acpiphp_disable_and_eject_slot(slot->acpi_slot); | 159 | return acpiphp_disable_slot(slot->acpi_slot); |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | 162 | ||
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index e86439283a5d..ee26bac2d378 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
| @@ -432,6 +432,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
| 432 | pr_err("failed to remove notify handler\n"); | 432 | pr_err("failed to remove notify handler\n"); |
| 433 | } | 433 | } |
| 434 | } | 434 | } |
| 435 | slot->flags |= SLOT_IS_GOING_AWAY; | ||
| 435 | if (slot->slot) | 436 | if (slot->slot) |
| 436 | acpiphp_unregister_hotplug_slot(slot); | 437 | acpiphp_unregister_hotplug_slot(slot); |
| 437 | } | 438 | } |
| @@ -439,6 +440,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
| 439 | mutex_lock(&bridge_mutex); | 440 | mutex_lock(&bridge_mutex); |
| 440 | list_del(&bridge->list); | 441 | list_del(&bridge->list); |
| 441 | mutex_unlock(&bridge_mutex); | 442 | mutex_unlock(&bridge_mutex); |
| 443 | |||
| 444 | bridge->is_going_away = true; | ||
| 442 | } | 445 | } |
| 443 | 446 | ||
| 444 | /** | 447 | /** |
| @@ -757,6 +760,10 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
| 757 | { | 760 | { |
| 758 | struct acpiphp_slot *slot; | 761 | struct acpiphp_slot *slot; |
| 759 | 762 | ||
| 763 | /* Bail out if the bridge is going away. */ | ||
| 764 | if (bridge->is_going_away) | ||
| 765 | return; | ||
| 766 | |||
| 760 | list_for_each_entry(slot, &bridge->slots, node) { | 767 | list_for_each_entry(slot, &bridge->slots, node) { |
| 761 | struct pci_bus *bus = slot->bus; | 768 | struct pci_bus *bus = slot->bus; |
| 762 | struct pci_dev *dev, *tmp; | 769 | struct pci_dev *dev, *tmp; |
| @@ -827,6 +834,8 @@ void acpiphp_check_host_bridge(acpi_handle handle) | |||
| 827 | } | 834 | } |
| 828 | } | 835 | } |
| 829 | 836 | ||
| 837 | static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); | ||
| 838 | |||
| 830 | static void hotplug_event(acpi_handle handle, u32 type, void *data) | 839 | static void hotplug_event(acpi_handle handle, u32 type, void *data) |
| 831 | { | 840 | { |
| 832 | struct acpiphp_context *context = data; | 841 | struct acpiphp_context *context = data; |
| @@ -856,6 +865,9 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 856 | } else { | 865 | } else { |
| 857 | struct acpiphp_slot *slot = func->slot; | 866 | struct acpiphp_slot *slot = func->slot; |
| 858 | 867 | ||
| 868 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
| 869 | break; | ||
| 870 | |||
| 859 | mutex_lock(&slot->crit_sect); | 871 | mutex_lock(&slot->crit_sect); |
| 860 | enable_slot(slot); | 872 | enable_slot(slot); |
| 861 | mutex_unlock(&slot->crit_sect); | 873 | mutex_unlock(&slot->crit_sect); |
| @@ -871,6 +883,9 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data) | |||
| 871 | struct acpiphp_slot *slot = func->slot; | 883 | struct acpiphp_slot *slot = func->slot; |
| 872 | int ret; | 884 | int ret; |
| 873 | 885 | ||
| 886 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
| 887 | break; | ||
| 888 | |||
| 874 | /* | 889 | /* |
| 875 | * Check if anything has changed in the slot and rescan | 890 | * Check if anything has changed in the slot and rescan |
| 876 | * from the parent if that's the case. | 891 | * from the parent if that's the case. |
| @@ -900,9 +915,11 @@ static void hotplug_event_work(void *data, u32 type) | |||
| 900 | acpi_handle handle = context->handle; | 915 | acpi_handle handle = context->handle; |
| 901 | 916 | ||
| 902 | acpi_scan_lock_acquire(); | 917 | acpi_scan_lock_acquire(); |
| 918 | pci_lock_rescan_remove(); | ||
| 903 | 919 | ||
| 904 | hotplug_event(handle, type, context); | 920 | hotplug_event(handle, type, context); |
| 905 | 921 | ||
| 922 | pci_unlock_rescan_remove(); | ||
| 906 | acpi_scan_lock_release(); | 923 | acpi_scan_lock_release(); |
| 907 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); | 924 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); |
| 908 | put_bridge(context->func.parent); | 925 | put_bridge(context->func.parent); |
| @@ -1070,12 +1087,19 @@ void acpiphp_remove_slots(struct pci_bus *bus) | |||
| 1070 | */ | 1087 | */ |
| 1071 | int acpiphp_enable_slot(struct acpiphp_slot *slot) | 1088 | int acpiphp_enable_slot(struct acpiphp_slot *slot) |
| 1072 | { | 1089 | { |
| 1090 | pci_lock_rescan_remove(); | ||
| 1091 | |||
| 1092 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
| 1093 | return -ENODEV; | ||
| 1094 | |||
| 1073 | mutex_lock(&slot->crit_sect); | 1095 | mutex_lock(&slot->crit_sect); |
| 1074 | /* configure all functions */ | 1096 | /* configure all functions */ |
| 1075 | if (!(slot->flags & SLOT_ENABLED)) | 1097 | if (!(slot->flags & SLOT_ENABLED)) |
| 1076 | enable_slot(slot); | 1098 | enable_slot(slot); |
| 1077 | 1099 | ||
| 1078 | mutex_unlock(&slot->crit_sect); | 1100 | mutex_unlock(&slot->crit_sect); |
| 1101 | |||
| 1102 | pci_unlock_rescan_remove(); | ||
| 1079 | return 0; | 1103 | return 0; |
| 1080 | } | 1104 | } |
| 1081 | 1105 | ||
| @@ -1083,10 +1107,12 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) | |||
| 1083 | * acpiphp_disable_and_eject_slot - power off and eject slot | 1107 | * acpiphp_disable_and_eject_slot - power off and eject slot |
| 1084 | * @slot: ACPI PHP slot | 1108 | * @slot: ACPI PHP slot |
| 1085 | */ | 1109 | */ |
| 1086 | int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) | 1110 | static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) |
| 1087 | { | 1111 | { |
| 1088 | struct acpiphp_func *func; | 1112 | struct acpiphp_func *func; |
| 1089 | int retval = 0; | 1113 | |
| 1114 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
| 1115 | return -ENODEV; | ||
| 1090 | 1116 | ||
| 1091 | mutex_lock(&slot->crit_sect); | 1117 | mutex_lock(&slot->crit_sect); |
| 1092 | 1118 | ||
| @@ -1104,9 +1130,18 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) | |||
| 1104 | } | 1130 | } |
| 1105 | 1131 | ||
| 1106 | mutex_unlock(&slot->crit_sect); | 1132 | mutex_unlock(&slot->crit_sect); |
| 1107 | return retval; | 1133 | return 0; |
| 1108 | } | 1134 | } |
| 1109 | 1135 | ||
| 1136 | int acpiphp_disable_slot(struct acpiphp_slot *slot) | ||
| 1137 | { | ||
| 1138 | int ret; | ||
| 1139 | |||
| 1140 | pci_lock_rescan_remove(); | ||
| 1141 | ret = acpiphp_disable_and_eject_slot(slot); | ||
| 1142 | pci_unlock_rescan_remove(); | ||
| 1143 | return ret; | ||
| 1144 | } | ||
| 1110 | 1145 | ||
| 1111 | /* | 1146 | /* |
| 1112 | * slot enabled: 1 | 1147 | * slot enabled: 1 |
| @@ -1117,7 +1152,6 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) | |||
| 1117 | return (slot->flags & SLOT_ENABLED); | 1152 | return (slot->flags & SLOT_ENABLED); |
| 1118 | } | 1153 | } |
| 1119 | 1154 | ||
| 1120 | |||
| 1121 | /* | 1155 | /* |
| 1122 | * latch open: 1 | 1156 | * latch open: 1 |
| 1123 | * latch closed: 0 | 1157 | * latch closed: 0 |
| @@ -1127,7 +1161,6 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) | |||
| 1127 | return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI); | 1161 | return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI); |
| 1128 | } | 1162 | } |
| 1129 | 1163 | ||
| 1130 | |||
| 1131 | /* | 1164 | /* |
| 1132 | * adapter presence : 1 | 1165 | * adapter presence : 1 |
| 1133 | * absence : 0 | 1166 | * absence : 0 |
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index d3add9819f63..8c1464851768 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c | |||
| @@ -254,9 +254,12 @@ int __ref cpci_configure_slot(struct slot *slot) | |||
| 254 | { | 254 | { |
| 255 | struct pci_dev *dev; | 255 | struct pci_dev *dev; |
| 256 | struct pci_bus *parent; | 256 | struct pci_bus *parent; |
| 257 | int ret = 0; | ||
| 257 | 258 | ||
| 258 | dbg("%s - enter", __func__); | 259 | dbg("%s - enter", __func__); |
| 259 | 260 | ||
| 261 | pci_lock_rescan_remove(); | ||
| 262 | |||
| 260 | if (slot->dev == NULL) { | 263 | if (slot->dev == NULL) { |
| 261 | dbg("pci_dev null, finding %02x:%02x:%x", | 264 | dbg("pci_dev null, finding %02x:%02x:%x", |
| 262 | slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); | 265 | slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); |
| @@ -277,7 +280,8 @@ int __ref cpci_configure_slot(struct slot *slot) | |||
| 277 | slot->dev = pci_get_slot(slot->bus, slot->devfn); | 280 | slot->dev = pci_get_slot(slot->bus, slot->devfn); |
| 278 | if (slot->dev == NULL) { | 281 | if (slot->dev == NULL) { |
| 279 | err("Could not find PCI device for slot %02x", slot->number); | 282 | err("Could not find PCI device for slot %02x", slot->number); |
| 280 | return -ENODEV; | 283 | ret = -ENODEV; |
| 284 | goto out; | ||
| 281 | } | 285 | } |
| 282 | } | 286 | } |
| 283 | parent = slot->dev->bus; | 287 | parent = slot->dev->bus; |
| @@ -294,8 +298,10 @@ int __ref cpci_configure_slot(struct slot *slot) | |||
| 294 | 298 | ||
| 295 | pci_bus_add_devices(parent); | 299 | pci_bus_add_devices(parent); |
| 296 | 300 | ||
| 301 | out: | ||
| 302 | pci_unlock_rescan_remove(); | ||
| 297 | dbg("%s - exit", __func__); | 303 | dbg("%s - exit", __func__); |
| 298 | return 0; | 304 | return ret; |
| 299 | } | 305 | } |
| 300 | 306 | ||
| 301 | int cpci_unconfigure_slot(struct slot* slot) | 307 | int cpci_unconfigure_slot(struct slot* slot) |
| @@ -308,6 +314,8 @@ int cpci_unconfigure_slot(struct slot* slot) | |||
| 308 | return -ENODEV; | 314 | return -ENODEV; |
| 309 | } | 315 | } |
| 310 | 316 | ||
| 317 | pci_lock_rescan_remove(); | ||
| 318 | |||
| 311 | list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) { | 319 | list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) { |
| 312 | if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) | 320 | if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) |
| 313 | continue; | 321 | continue; |
| @@ -318,6 +326,8 @@ int cpci_unconfigure_slot(struct slot* slot) | |||
| 318 | pci_dev_put(slot->dev); | 326 | pci_dev_put(slot->dev); |
| 319 | slot->dev = NULL; | 327 | slot->dev = NULL; |
| 320 | 328 | ||
| 329 | pci_unlock_rescan_remove(); | ||
| 330 | |||
| 321 | dbg("%s - exit", __func__); | 331 | dbg("%s - exit", __func__); |
| 322 | return 0; | 332 | return 0; |
| 323 | } | 333 | } |
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 6e4a12c91adb..a3e3c2002b58 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c | |||
| @@ -86,6 +86,8 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) | |||
| 86 | struct pci_bus *child; | 86 | struct pci_bus *child; |
| 87 | int num; | 87 | int num; |
| 88 | 88 | ||
| 89 | pci_lock_rescan_remove(); | ||
| 90 | |||
| 89 | if (func->pci_dev == NULL) | 91 | if (func->pci_dev == NULL) |
| 90 | func->pci_dev = pci_get_bus_and_slot(func->bus,PCI_DEVFN(func->device, func->function)); | 92 | func->pci_dev = pci_get_bus_and_slot(func->bus,PCI_DEVFN(func->device, func->function)); |
| 91 | 93 | ||
| @@ -100,7 +102,7 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) | |||
| 100 | func->pci_dev = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, func->function)); | 102 | func->pci_dev = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, func->function)); |
| 101 | if (func->pci_dev == NULL) { | 103 | if (func->pci_dev == NULL) { |
| 102 | dbg("ERROR: pci_dev still null\n"); | 104 | dbg("ERROR: pci_dev still null\n"); |
| 103 | return 0; | 105 | goto out; |
| 104 | } | 106 | } |
| 105 | } | 107 | } |
| 106 | 108 | ||
| @@ -113,6 +115,8 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) | |||
| 113 | 115 | ||
| 114 | pci_dev_put(func->pci_dev); | 116 | pci_dev_put(func->pci_dev); |
| 115 | 117 | ||
| 118 | out: | ||
| 119 | pci_unlock_rescan_remove(); | ||
| 116 | return 0; | 120 | return 0; |
| 117 | } | 121 | } |
| 118 | 122 | ||
| @@ -123,6 +127,7 @@ int cpqhp_unconfigure_device(struct pci_func* func) | |||
| 123 | 127 | ||
| 124 | dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function); | 128 | dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function); |
| 125 | 129 | ||
| 130 | pci_lock_rescan_remove(); | ||
| 126 | for (j=0; j<8 ; j++) { | 131 | for (j=0; j<8 ; j++) { |
| 127 | struct pci_dev* temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j)); | 132 | struct pci_dev* temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j)); |
| 128 | if (temp) { | 133 | if (temp) { |
| @@ -130,6 +135,7 @@ int cpqhp_unconfigure_device(struct pci_func* func) | |||
| 130 | pci_stop_and_remove_bus_device(temp); | 135 | pci_stop_and_remove_bus_device(temp); |
| 131 | } | 136 | } |
| 132 | } | 137 | } |
| 138 | pci_unlock_rescan_remove(); | ||
| 133 | return 0; | 139 | return 0; |
| 134 | } | 140 | } |
| 135 | 141 | ||
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index efdc13adbe41..cf3ac1e4b099 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c | |||
| @@ -718,6 +718,8 @@ static void ibm_unconfigure_device(struct pci_func *func) | |||
| 718 | func->device, func->function); | 718 | func->device, func->function); |
| 719 | debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0); | 719 | debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0); |
| 720 | 720 | ||
| 721 | pci_lock_rescan_remove(); | ||
| 722 | |||
| 721 | for (j = 0; j < 0x08; j++) { | 723 | for (j = 0; j < 0x08; j++) { |
| 722 | temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j); | 724 | temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j); |
| 723 | if (temp) { | 725 | if (temp) { |
| @@ -725,7 +727,10 @@ static void ibm_unconfigure_device(struct pci_func *func) | |||
| 725 | pci_dev_put(temp); | 727 | pci_dev_put(temp); |
| 726 | } | 728 | } |
| 727 | } | 729 | } |
| 730 | |||
| 728 | pci_dev_put(func->dev); | 731 | pci_dev_put(func->dev); |
| 732 | |||
| 733 | pci_unlock_rescan_remove(); | ||
| 729 | } | 734 | } |
| 730 | 735 | ||
| 731 | /* | 736 | /* |
| @@ -780,6 +785,8 @@ static int ibm_configure_device(struct pci_func *func) | |||
| 780 | int flag = 0; /* this is to make sure we don't double scan the bus, | 785 | int flag = 0; /* this is to make sure we don't double scan the bus, |
| 781 | for bridged devices primarily */ | 786 | for bridged devices primarily */ |
| 782 | 787 | ||
| 788 | pci_lock_rescan_remove(); | ||
| 789 | |||
| 783 | if (!(bus_structure_fixup(func->busno))) | 790 | if (!(bus_structure_fixup(func->busno))) |
| 784 | flag = 1; | 791 | flag = 1; |
| 785 | if (func->dev == NULL) | 792 | if (func->dev == NULL) |
| @@ -789,7 +796,7 @@ static int ibm_configure_device(struct pci_func *func) | |||
| 789 | if (func->dev == NULL) { | 796 | if (func->dev == NULL) { |
| 790 | struct pci_bus *bus = pci_find_bus(0, func->busno); | 797 | struct pci_bus *bus = pci_find_bus(0, func->busno); |
| 791 | if (!bus) | 798 | if (!bus) |
| 792 | return 0; | 799 | goto out; |
| 793 | 800 | ||
| 794 | num = pci_scan_slot(bus, | 801 | num = pci_scan_slot(bus, |
| 795 | PCI_DEVFN(func->device, func->function)); | 802 | PCI_DEVFN(func->device, func->function)); |
| @@ -800,7 +807,7 @@ static int ibm_configure_device(struct pci_func *func) | |||
| 800 | PCI_DEVFN(func->device, func->function)); | 807 | PCI_DEVFN(func->device, func->function)); |
| 801 | if (func->dev == NULL) { | 808 | if (func->dev == NULL) { |
| 802 | err("ERROR... : pci_dev still NULL\n"); | 809 | err("ERROR... : pci_dev still NULL\n"); |
| 803 | return 0; | 810 | goto out; |
| 804 | } | 811 | } |
| 805 | } | 812 | } |
| 806 | if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { | 813 | if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { |
| @@ -810,6 +817,8 @@ static int ibm_configure_device(struct pci_func *func) | |||
| 810 | pci_bus_add_devices(child); | 817 | pci_bus_add_devices(child); |
| 811 | } | 818 | } |
| 812 | 819 | ||
| 820 | out: | ||
| 821 | pci_unlock_rescan_remove(); | ||
| 813 | return 0; | 822 | return 0; |
| 814 | } | 823 | } |
| 815 | 824 | ||
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 21e865ded1dc..ccb0925bcd7b 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
| @@ -43,7 +43,6 @@ | |||
| 43 | extern bool pciehp_poll_mode; | 43 | extern bool pciehp_poll_mode; |
| 44 | extern int pciehp_poll_time; | 44 | extern int pciehp_poll_time; |
| 45 | extern bool pciehp_debug; | 45 | extern bool pciehp_debug; |
| 46 | extern bool pciehp_force; | ||
| 47 | 46 | ||
| 48 | #define dbg(format, arg...) \ | 47 | #define dbg(format, arg...) \ |
| 49 | do { \ | 48 | do { \ |
| @@ -140,15 +139,15 @@ struct controller *pcie_init(struct pcie_device *dev); | |||
| 140 | int pcie_init_notification(struct controller *ctrl); | 139 | int pcie_init_notification(struct controller *ctrl); |
| 141 | int pciehp_enable_slot(struct slot *p_slot); | 140 | int pciehp_enable_slot(struct slot *p_slot); |
| 142 | int pciehp_disable_slot(struct slot *p_slot); | 141 | int pciehp_disable_slot(struct slot *p_slot); |
| 143 | int pcie_enable_notification(struct controller *ctrl); | 142 | void pcie_enable_notification(struct controller *ctrl); |
| 144 | int pciehp_power_on_slot(struct slot *slot); | 143 | int pciehp_power_on_slot(struct slot *slot); |
| 145 | int pciehp_power_off_slot(struct slot *slot); | 144 | void pciehp_power_off_slot(struct slot *slot); |
| 146 | int pciehp_get_power_status(struct slot *slot, u8 *status); | 145 | void pciehp_get_power_status(struct slot *slot, u8 *status); |
| 147 | int pciehp_get_attention_status(struct slot *slot, u8 *status); | 146 | void pciehp_get_attention_status(struct slot *slot, u8 *status); |
| 148 | 147 | ||
| 149 | int pciehp_set_attention_status(struct slot *slot, u8 status); | 148 | void pciehp_set_attention_status(struct slot *slot, u8 status); |
| 150 | int pciehp_get_latch_status(struct slot *slot, u8 *status); | 149 | void pciehp_get_latch_status(struct slot *slot, u8 *status); |
| 151 | int pciehp_get_adapter_status(struct slot *slot, u8 *status); | 150 | void pciehp_get_adapter_status(struct slot *slot, u8 *status); |
| 152 | int pciehp_query_power_fault(struct slot *slot); | 151 | int pciehp_query_power_fault(struct slot *slot); |
| 153 | void pciehp_green_led_on(struct slot *slot); | 152 | void pciehp_green_led_on(struct slot *slot); |
| 154 | void pciehp_green_led_off(struct slot *slot); | 153 | void pciehp_green_led_off(struct slot *slot); |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index bbd48bbe4e9b..53b58debc288 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | bool pciehp_debug; | 41 | bool pciehp_debug; |
| 42 | bool pciehp_poll_mode; | 42 | bool pciehp_poll_mode; |
| 43 | int pciehp_poll_time; | 43 | int pciehp_poll_time; |
| 44 | bool pciehp_force; | 44 | static bool pciehp_force; |
| 45 | 45 | ||
| 46 | #define DRIVER_VERSION "0.4" | 46 | #define DRIVER_VERSION "0.4" |
| 47 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 47 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
| @@ -160,7 +160,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) | |||
| 160 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 160 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
| 161 | __func__, slot_name(slot)); | 161 | __func__, slot_name(slot)); |
| 162 | 162 | ||
| 163 | return pciehp_set_attention_status(slot, status); | 163 | pciehp_set_attention_status(slot, status); |
| 164 | return 0; | ||
| 164 | } | 165 | } |
| 165 | 166 | ||
| 166 | 167 | ||
| @@ -192,7 +193,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value) | |||
| 192 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 193 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
| 193 | __func__, slot_name(slot)); | 194 | __func__, slot_name(slot)); |
| 194 | 195 | ||
| 195 | return pciehp_get_power_status(slot, value); | 196 | pciehp_get_power_status(slot, value); |
| 197 | return 0; | ||
| 196 | } | 198 | } |
| 197 | 199 | ||
| 198 | static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) | 200 | static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) |
| @@ -202,7 +204,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) | |||
| 202 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 204 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
| 203 | __func__, slot_name(slot)); | 205 | __func__, slot_name(slot)); |
| 204 | 206 | ||
| 205 | return pciehp_get_attention_status(slot, value); | 207 | pciehp_get_attention_status(slot, value); |
| 208 | return 0; | ||
| 206 | } | 209 | } |
| 207 | 210 | ||
| 208 | static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) | 211 | static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) |
| @@ -212,7 +215,8 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) | |||
| 212 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 215 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
| 213 | __func__, slot_name(slot)); | 216 | __func__, slot_name(slot)); |
| 214 | 217 | ||
| 215 | return pciehp_get_latch_status(slot, value); | 218 | pciehp_get_latch_status(slot, value); |
| 219 | return 0; | ||
| 216 | } | 220 | } |
| 217 | 221 | ||
| 218 | static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) | 222 | static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) |
| @@ -222,7 +226,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) | |||
| 222 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", | 226 | ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n", |
| 223 | __func__, slot_name(slot)); | 227 | __func__, slot_name(slot)); |
| 224 | 228 | ||
| 225 | return pciehp_get_adapter_status(slot, value); | 229 | pciehp_get_adapter_status(slot, value); |
| 230 | return 0; | ||
| 226 | } | 231 | } |
| 227 | 232 | ||
| 228 | static int reset_slot(struct hotplug_slot *hotplug_slot, int probe) | 233 | static int reset_slot(struct hotplug_slot *hotplug_slot, int probe) |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 38f018679175..50628487597d 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
| @@ -158,11 +158,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) | |||
| 158 | { | 158 | { |
| 159 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ | 159 | /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ |
| 160 | if (POWER_CTRL(ctrl)) { | 160 | if (POWER_CTRL(ctrl)) { |
| 161 | if (pciehp_power_off_slot(pslot)) { | 161 | pciehp_power_off_slot(pslot); |
| 162 | ctrl_err(ctrl, | 162 | |
| 163 | "Issue of Slot Power Off command failed\n"); | ||
| 164 | return; | ||
| 165 | } | ||
| 166 | /* | 163 | /* |
| 167 | * After turning power off, we must wait for at least 1 second | 164 | * After turning power off, we must wait for at least 1 second |
| 168 | * before taking any action that relies on power having been | 165 | * before taking any action that relies on power having been |
| @@ -171,16 +168,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) | |||
| 171 | msleep(1000); | 168 | msleep(1000); |
| 172 | } | 169 | } |
| 173 | 170 | ||
| 174 | if (PWR_LED(ctrl)) | 171 | pciehp_green_led_off(pslot); |
| 175 | pciehp_green_led_off(pslot); | 172 | pciehp_set_attention_status(pslot, 1); |
| 176 | |||
| 177 | if (ATTN_LED(ctrl)) { | ||
| 178 | if (pciehp_set_attention_status(pslot, 1)) { | ||
| 179 | ctrl_err(ctrl, | ||
| 180 | "Issue of Set Attention Led command failed\n"); | ||
| 181 | return; | ||
| 182 | } | ||
| 183 | } | ||
| 184 | } | 173 | } |
| 185 | 174 | ||
| 186 | /** | 175 | /** |
| @@ -203,8 +192,7 @@ static int board_added(struct slot *p_slot) | |||
| 203 | return retval; | 192 | return retval; |
| 204 | } | 193 | } |
| 205 | 194 | ||
| 206 | if (PWR_LED(ctrl)) | 195 | pciehp_green_led_blink(p_slot); |
| 207 | pciehp_green_led_blink(p_slot); | ||
| 208 | 196 | ||
| 209 | /* Check link training status */ | 197 | /* Check link training status */ |
| 210 | retval = pciehp_check_link_status(ctrl); | 198 | retval = pciehp_check_link_status(ctrl); |
| @@ -227,9 +215,7 @@ static int board_added(struct slot *p_slot) | |||
| 227 | goto err_exit; | 215 | goto err_exit; |
| 228 | } | 216 | } |
| 229 | 217 | ||
| 230 | if (PWR_LED(ctrl)) | 218 | pciehp_green_led_on(p_slot); |
| 231 | pciehp_green_led_on(p_slot); | ||
| 232 | |||
| 233 | return 0; | 219 | return 0; |
| 234 | 220 | ||
| 235 | err_exit: | 221 | err_exit: |
| @@ -243,7 +229,7 @@ err_exit: | |||
| 243 | */ | 229 | */ |
| 244 | static int remove_board(struct slot *p_slot) | 230 | static int remove_board(struct slot *p_slot) |
| 245 | { | 231 | { |
| 246 | int retval = 0; | 232 | int retval; |
| 247 | struct controller *ctrl = p_slot->ctrl; | 233 | struct controller *ctrl = p_slot->ctrl; |
| 248 | 234 | ||
| 249 | retval = pciehp_unconfigure_device(p_slot); | 235 | retval = pciehp_unconfigure_device(p_slot); |
| @@ -251,13 +237,8 @@ static int remove_board(struct slot *p_slot) | |||
| 251 | return retval; | 237 | return retval; |
| 252 | 238 | ||
| 253 | if (POWER_CTRL(ctrl)) { | 239 | if (POWER_CTRL(ctrl)) { |
| 254 | /* power off slot */ | 240 | pciehp_power_off_slot(p_slot); |
| 255 | retval = pciehp_power_off_slot(p_slot); | 241 | |
| 256 | if (retval) { | ||
| 257 | ctrl_err(ctrl, | ||
| 258 | "Issue of Slot Disable command failed\n"); | ||
| 259 | return retval; | ||
| 260 | } | ||
| 261 | /* | 242 | /* |
| 262 | * After turning power off, we must wait for at least 1 second | 243 | * After turning power off, we must wait for at least 1 second |
| 263 | * before taking any action that relies on power having been | 244 | * before taking any action that relies on power having been |
| @@ -267,9 +248,7 @@ static int remove_board(struct slot *p_slot) | |||
| 267 | } | 248 | } |
| 268 | 249 | ||
| 269 | /* turn off Green LED */ | 250 | /* turn off Green LED */ |
| 270 | if (PWR_LED(ctrl)) | 251 | pciehp_green_led_off(p_slot); |
| 271 | pciehp_green_led_off(p_slot); | ||
| 272 | |||
| 273 | return 0; | 252 | return 0; |
| 274 | } | 253 | } |
| 275 | 254 | ||
| @@ -305,7 +284,7 @@ static void pciehp_power_thread(struct work_struct *work) | |||
| 305 | break; | 284 | break; |
| 306 | case POWERON_STATE: | 285 | case POWERON_STATE: |
| 307 | mutex_unlock(&p_slot->lock); | 286 | mutex_unlock(&p_slot->lock); |
| 308 | if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl)) | 287 | if (pciehp_enable_slot(p_slot)) |
| 309 | pciehp_green_led_off(p_slot); | 288 | pciehp_green_led_off(p_slot); |
| 310 | mutex_lock(&p_slot->lock); | 289 | mutex_lock(&p_slot->lock); |
| 311 | p_slot->state = STATIC_STATE; | 290 | p_slot->state = STATIC_STATE; |
| @@ -372,11 +351,8 @@ static void handle_button_press_event(struct slot *p_slot) | |||
| 372 | "press.\n", slot_name(p_slot)); | 351 | "press.\n", slot_name(p_slot)); |
| 373 | } | 352 | } |
| 374 | /* blink green LED and turn off amber */ | 353 | /* blink green LED and turn off amber */ |
| 375 | if (PWR_LED(ctrl)) | 354 | pciehp_green_led_blink(p_slot); |
| 376 | pciehp_green_led_blink(p_slot); | 355 | pciehp_set_attention_status(p_slot, 0); |
| 377 | if (ATTN_LED(ctrl)) | ||
| 378 | pciehp_set_attention_status(p_slot, 0); | ||
| 379 | |||
| 380 | queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); | 356 | queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); |
| 381 | break; | 357 | break; |
| 382 | case BLINKINGOFF_STATE: | 358 | case BLINKINGOFF_STATE: |
| @@ -389,14 +365,11 @@ static void handle_button_press_event(struct slot *p_slot) | |||
| 389 | ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); | 365 | ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); |
| 390 | cancel_delayed_work(&p_slot->work); | 366 | cancel_delayed_work(&p_slot->work); |
| 391 | if (p_slot->state == BLINKINGOFF_STATE) { | 367 | if (p_slot->state == BLINKINGOFF_STATE) { |
| 392 | if (PWR_LED(ctrl)) | 368 | pciehp_green_led_on(p_slot); |
| 393 | pciehp_green_led_on(p_slot); | ||
| 394 | } else { | 369 | } else { |
| 395 | if (PWR_LED(ctrl)) | 370 | pciehp_green_led_off(p_slot); |
| 396 | pciehp_green_led_off(p_slot); | ||
| 397 | } | 371 | } |
| 398 | if (ATTN_LED(ctrl)) | 372 | pciehp_set_attention_status(p_slot, 0); |
| 399 | pciehp_set_attention_status(p_slot, 0); | ||
| 400 | ctrl_info(ctrl, "PCI slot #%s - action canceled " | 373 | ctrl_info(ctrl, "PCI slot #%s - action canceled " |
| 401 | "due to button press\n", slot_name(p_slot)); | 374 | "due to button press\n", slot_name(p_slot)); |
| 402 | p_slot->state = STATIC_STATE; | 375 | p_slot->state = STATIC_STATE; |
| @@ -456,10 +429,8 @@ static void interrupt_event_handler(struct work_struct *work) | |||
| 456 | case INT_POWER_FAULT: | 429 | case INT_POWER_FAULT: |
| 457 | if (!POWER_CTRL(ctrl)) | 430 | if (!POWER_CTRL(ctrl)) |
| 458 | break; | 431 | break; |
| 459 | if (ATTN_LED(ctrl)) | 432 | pciehp_set_attention_status(p_slot, 1); |
| 460 | pciehp_set_attention_status(p_slot, 1); | 433 | pciehp_green_led_off(p_slot); |
| 461 | if (PWR_LED(ctrl)) | ||
| 462 | pciehp_green_led_off(p_slot); | ||
| 463 | break; | 434 | break; |
| 464 | case INT_PRESENCE_ON: | 435 | case INT_PRESENCE_ON: |
| 465 | case INT_PRESENCE_OFF: | 436 | case INT_PRESENCE_OFF: |
| @@ -482,14 +453,14 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 482 | int rc; | 453 | int rc; |
| 483 | struct controller *ctrl = p_slot->ctrl; | 454 | struct controller *ctrl = p_slot->ctrl; |
| 484 | 455 | ||
| 485 | rc = pciehp_get_adapter_status(p_slot, &getstatus); | 456 | pciehp_get_adapter_status(p_slot, &getstatus); |
| 486 | if (rc || !getstatus) { | 457 | if (!getstatus) { |
| 487 | ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); | 458 | ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot)); |
| 488 | return -ENODEV; | 459 | return -ENODEV; |
| 489 | } | 460 | } |
| 490 | if (MRL_SENS(p_slot->ctrl)) { | 461 | if (MRL_SENS(p_slot->ctrl)) { |
| 491 | rc = pciehp_get_latch_status(p_slot, &getstatus); | 462 | pciehp_get_latch_status(p_slot, &getstatus); |
| 492 | if (rc || getstatus) { | 463 | if (getstatus) { |
| 493 | ctrl_info(ctrl, "Latch open on slot(%s)\n", | 464 | ctrl_info(ctrl, "Latch open on slot(%s)\n", |
| 494 | slot_name(p_slot)); | 465 | slot_name(p_slot)); |
| 495 | return -ENODEV; | 466 | return -ENODEV; |
| @@ -497,8 +468,8 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 497 | } | 468 | } |
| 498 | 469 | ||
| 499 | if (POWER_CTRL(p_slot->ctrl)) { | 470 | if (POWER_CTRL(p_slot->ctrl)) { |
| 500 | rc = pciehp_get_power_status(p_slot, &getstatus); | 471 | pciehp_get_power_status(p_slot, &getstatus); |
| 501 | if (rc || getstatus) { | 472 | if (getstatus) { |
| 502 | ctrl_info(ctrl, "Already enabled on slot(%s)\n", | 473 | ctrl_info(ctrl, "Already enabled on slot(%s)\n", |
| 503 | slot_name(p_slot)); | 474 | slot_name(p_slot)); |
| 504 | return -EINVAL; | 475 | return -EINVAL; |
| @@ -518,15 +489,14 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
| 518 | int pciehp_disable_slot(struct slot *p_slot) | 489 | int pciehp_disable_slot(struct slot *p_slot) |
| 519 | { | 490 | { |
| 520 | u8 getstatus = 0; | 491 | u8 getstatus = 0; |
| 521 | int ret = 0; | ||
| 522 | struct controller *ctrl = p_slot->ctrl; | 492 | struct controller *ctrl = p_slot->ctrl; |
| 523 | 493 | ||
| 524 | if (!p_slot->ctrl) | 494 | if (!p_slot->ctrl) |
| 525 | return 1; | 495 | return 1; |
| 526 | 496 | ||
| 527 | if (!HP_SUPR_RM(p_slot->ctrl)) { | 497 | if (!HP_SUPR_RM(p_slot->ctrl)) { |
| 528 | ret = pciehp_get_adapter_status(p_slot, &getstatus); | 498 | pciehp_get_adapter_status(p_slot, &getstatus); |
| 529 | if (ret || !getstatus) { | 499 | if (!getstatus) { |
| 530 | ctrl_info(ctrl, "No adapter on slot(%s)\n", | 500 | ctrl_info(ctrl, "No adapter on slot(%s)\n", |
| 531 | slot_name(p_slot)); | 501 | slot_name(p_slot)); |
| 532 | return -ENODEV; | 502 | return -ENODEV; |
| @@ -534,8 +504,8 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
| 534 | } | 504 | } |
| 535 | 505 | ||
| 536 | if (MRL_SENS(p_slot->ctrl)) { | 506 | if (MRL_SENS(p_slot->ctrl)) { |
| 537 | ret = pciehp_get_latch_status(p_slot, &getstatus); | 507 | pciehp_get_latch_status(p_slot, &getstatus); |
| 538 | if (ret || getstatus) { | 508 | if (getstatus) { |
| 539 | ctrl_info(ctrl, "Latch open on slot(%s)\n", | 509 | ctrl_info(ctrl, "Latch open on slot(%s)\n", |
| 540 | slot_name(p_slot)); | 510 | slot_name(p_slot)); |
| 541 | return -ENODEV; | 511 | return -ENODEV; |
| @@ -543,8 +513,8 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
| 543 | } | 513 | } |
| 544 | 514 | ||
| 545 | if (POWER_CTRL(p_slot->ctrl)) { | 515 | if (POWER_CTRL(p_slot->ctrl)) { |
| 546 | ret = pciehp_get_power_status(p_slot, &getstatus); | 516 | pciehp_get_power_status(p_slot, &getstatus); |
| 547 | if (ret || !getstatus) { | 517 | if (!getstatus) { |
| 548 | ctrl_info(ctrl, "Already disabled on slot(%s)\n", | 518 | ctrl_info(ctrl, "Already disabled on slot(%s)\n", |
| 549 | slot_name(p_slot)); | 519 | slot_name(p_slot)); |
| 550 | return -EINVAL; | 520 | return -EINVAL; |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 3eea3fdd4b0b..14acfccb7670 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -41,34 +41,11 @@ | |||
| 41 | #include "../pci.h" | 41 | #include "../pci.h" |
| 42 | #include "pciehp.h" | 42 | #include "pciehp.h" |
| 43 | 43 | ||
| 44 | static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) | 44 | static inline struct pci_dev *ctrl_dev(struct controller *ctrl) |
| 45 | { | 45 | { |
| 46 | struct pci_dev *dev = ctrl->pcie->port; | 46 | return ctrl->pcie->port; |
| 47 | return pcie_capability_read_word(dev, reg, value); | ||
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) | ||
| 51 | { | ||
| 52 | struct pci_dev *dev = ctrl->pcie->port; | ||
| 53 | return pcie_capability_read_dword(dev, reg, value); | ||
| 54 | } | ||
| 55 | |||
| 56 | static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) | ||
| 57 | { | ||
| 58 | struct pci_dev *dev = ctrl->pcie->port; | ||
| 59 | return pcie_capability_write_word(dev, reg, value); | ||
| 60 | } | ||
| 61 | |||
| 62 | static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) | ||
| 63 | { | ||
| 64 | struct pci_dev *dev = ctrl->pcie->port; | ||
| 65 | return pcie_capability_write_dword(dev, reg, value); | ||
| 66 | } | ||
| 67 | |||
| 68 | /* Power Control Command */ | ||
| 69 | #define POWER_ON 0 | ||
| 70 | #define POWER_OFF PCI_EXP_SLTCTL_PCC | ||
| 71 | |||
| 72 | static irqreturn_t pcie_isr(int irq, void *dev_id); | 49 | static irqreturn_t pcie_isr(int irq, void *dev_id); |
| 73 | static void start_int_poll_timer(struct controller *ctrl, int sec); | 50 | static void start_int_poll_timer(struct controller *ctrl, int sec); |
| 74 | 51 | ||
| @@ -129,20 +106,23 @@ static inline void pciehp_free_irq(struct controller *ctrl) | |||
| 129 | 106 | ||
| 130 | static int pcie_poll_cmd(struct controller *ctrl) | 107 | static int pcie_poll_cmd(struct controller *ctrl) |
| 131 | { | 108 | { |
| 109 | struct pci_dev *pdev = ctrl_dev(ctrl); | ||
| 132 | u16 slot_status; | 110 | u16 slot_status; |
| 133 | int err, timeout = 1000; | 111 | int timeout = 1000; |
| 134 | 112 | ||
| 135 | err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); | 113 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
| 136 | if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) { | 114 | if (slot_status & PCI_EXP_SLTSTA_CC) { |
| 137 | pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); | 115 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, |
| 116 | PCI_EXP_SLTSTA_CC); | ||
| 138 | return 1; | 117 | return 1; |
| 139 | } | 118 | } |
| 140 | while (timeout > 0) { | 119 | while (timeout > 0) { |
| 141 | msleep(10); | 120 | msleep(10); |
| 142 | timeout -= 10; | 121 | timeout -= 10; |
| 143 | err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); | 122 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
| 144 | if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) { | 123 | if (slot_status & PCI_EXP_SLTSTA_CC) { |
| 145 | pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); | 124 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, |
| 125 | PCI_EXP_SLTSTA_CC); | ||
| 146 | return 1; | 126 | return 1; |
| 147 | } | 127 | } |
| 148 | } | 128 | } |
| @@ -169,21 +149,15 @@ static void pcie_wait_cmd(struct controller *ctrl, int poll) | |||
| 169 | * @cmd: command value written to slot control register | 149 | * @cmd: command value written to slot control register |
| 170 | * @mask: bitmask of slot control register to be modified | 150 | * @mask: bitmask of slot control register to be modified |
| 171 | */ | 151 | */ |
| 172 | static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | 152 | static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) |
| 173 | { | 153 | { |
| 174 | int retval = 0; | 154 | struct pci_dev *pdev = ctrl_dev(ctrl); |
| 175 | u16 slot_status; | 155 | u16 slot_status; |
| 176 | u16 slot_ctrl; | 156 | u16 slot_ctrl; |
| 177 | 157 | ||
| 178 | mutex_lock(&ctrl->ctrl_lock); | 158 | mutex_lock(&ctrl->ctrl_lock); |
| 179 | 159 | ||
| 180 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); | 160 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
| 181 | if (retval) { | ||
| 182 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", | ||
| 183 | __func__); | ||
| 184 | goto out; | ||
| 185 | } | ||
| 186 | |||
| 187 | if (slot_status & PCI_EXP_SLTSTA_CC) { | 161 | if (slot_status & PCI_EXP_SLTSTA_CC) { |
| 188 | if (!ctrl->no_cmd_complete) { | 162 | if (!ctrl->no_cmd_complete) { |
| 189 | /* | 163 | /* |
| @@ -207,24 +181,17 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |||
| 207 | } | 181 | } |
| 208 | } | 182 | } |
| 209 | 183 | ||
| 210 | retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); | 184 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); |
| 211 | if (retval) { | ||
| 212 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); | ||
| 213 | goto out; | ||
| 214 | } | ||
| 215 | |||
| 216 | slot_ctrl &= ~mask; | 185 | slot_ctrl &= ~mask; |
| 217 | slot_ctrl |= (cmd & mask); | 186 | slot_ctrl |= (cmd & mask); |
| 218 | ctrl->cmd_busy = 1; | 187 | ctrl->cmd_busy = 1; |
| 219 | smp_mb(); | 188 | smp_mb(); |
| 220 | retval = pciehp_writew(ctrl, PCI_EXP_SLTCTL, slot_ctrl); | 189 | pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl); |
| 221 | if (retval) | ||
| 222 | ctrl_err(ctrl, "Cannot write to SLOTCTRL register\n"); | ||
| 223 | 190 | ||
| 224 | /* | 191 | /* |
| 225 | * Wait for command completion. | 192 | * Wait for command completion. |
| 226 | */ | 193 | */ |
| 227 | if (!retval && !ctrl->no_cmd_complete) { | 194 | if (!ctrl->no_cmd_complete) { |
| 228 | int poll = 0; | 195 | int poll = 0; |
| 229 | /* | 196 | /* |
| 230 | * if hotplug interrupt is not enabled or command | 197 | * if hotplug interrupt is not enabled or command |
| @@ -236,19 +203,16 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |||
| 236 | poll = 1; | 203 | poll = 1; |
| 237 | pcie_wait_cmd(ctrl, poll); | 204 | pcie_wait_cmd(ctrl, poll); |
| 238 | } | 205 | } |
| 239 | out: | ||
| 240 | mutex_unlock(&ctrl->ctrl_lock); | 206 | mutex_unlock(&ctrl->ctrl_lock); |
| 241 | return retval; | ||
| 242 | } | 207 | } |
| 243 | 208 | ||
| 244 | static bool check_link_active(struct controller *ctrl) | 209 | static bool check_link_active(struct controller *ctrl) |
| 245 | { | 210 | { |
| 246 | bool ret = false; | 211 | struct pci_dev *pdev = ctrl_dev(ctrl); |
| 247 | u16 lnk_status; | 212 | u16 lnk_status; |
| 213 | bool ret; | ||
| 248 | 214 | ||
| 249 | if (pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status)) | 215 | pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); |
| 250 | return ret; | ||
| 251 | |||
| 252 | ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); | 216 | ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA); |
| 253 | 217 | ||
| 254 | if (ret) | 218 | if (ret) |
| @@ -311,9 +275,9 @@ static bool pci_bus_check_dev(struct pci_bus *bus, int devfn) | |||
| 311 | 275 | ||
| 312 | int pciehp_check_link_status(struct controller *ctrl) | 276 | int pciehp_check_link_status(struct controller *ctrl) |
| 313 | { | 277 | { |
| 278 | struct pci_dev *pdev = ctrl_dev(ctrl); | ||
| 279 | bool found; | ||
| 314 | u16 lnk_status; | 280 | u16 lnk_status; |
| 315 | int retval = 0; | ||
| 316 | bool found = false; | ||
| 317 | 281 | ||
| 318 | /* | 282 | /* |
| 319 | * Data Link Layer Link Active Reporting must be capable for | 283 | * Data Link Layer Link Active Reporting must be capable for |
| @@ -330,52 +294,37 @@ int pciehp_check_link_status(struct controller *ctrl) | |||
| 330 | found = pci_bus_check_dev(ctrl->pcie->port->subordinate, | 294 | found = pci_bus_check_dev(ctrl->pcie->port->subordinate, |
| 331 | PCI_DEVFN(0, 0)); | 295 | PCI_DEVFN(0, 0)); |
| 332 | 296 | ||
| 333 | retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); | 297 | pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status); |
| 334 | if (retval) { | ||
| 335 | ctrl_err(ctrl, "Cannot read LNKSTATUS register\n"); | ||
| 336 | return retval; | ||
| 337 | } | ||
| 338 | |||
| 339 | ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); | 298 | ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status); |
| 340 | if ((lnk_status & PCI_EXP_LNKSTA_LT) || | 299 | if ((lnk_status & PCI_EXP_LNKSTA_LT) || |
| 341 | !(lnk_status & PCI_EXP_LNKSTA_NLW)) { | 300 | !(lnk_status & PCI_EXP_LNKSTA_NLW)) { |
| 342 | ctrl_err(ctrl, "Link Training Error occurs \n"); | 301 | ctrl_err(ctrl, "Link Training Error occurs \n"); |
| 343 | retval = -1; | 302 | return -1; |
| 344 | return retval; | ||
| 345 | } | 303 | } |
| 346 | 304 | ||
| 347 | pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); | 305 | pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); |
| 348 | 306 | ||
| 349 | if (!found && !retval) | 307 | if (!found) |
| 350 | retval = -1; | 308 | return -1; |
| 351 | 309 | ||
| 352 | return retval; | 310 | return 0; |
| 353 | } | 311 | } |
| 354 | 312 | ||
| 355 | static int __pciehp_link_set(struct controller *ctrl, bool enable) | 313 | static int __pciehp_link_set(struct controller *ctrl, bool enable) |
| 356 | { | 314 | { |
| 315 | struct pci_dev *pdev = ctrl_dev(ctrl); | ||
| 357 | u16 lnk_ctrl; | 316 | u16 lnk_ctrl; |
| 358 | int retval = 0; | ||
| 359 | 317 | ||
| 360 | retval = pciehp_readw(ctrl, PCI_EXP_LNKCTL, &lnk_ctrl); | 318 | pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnk_ctrl); |
| 361 | if (retval) { | ||
| 362 | ctrl_err(ctrl, "Cannot read LNKCTRL register\n"); | ||
| 363 | return retval; | ||
| 364 | } | ||
| 365 | 319 | ||
| 366 | if (enable) | 320 | if (enable) |
| 367 | lnk_ctrl &= ~PCI_EXP_LNKCTL_LD; | 321 | lnk_ctrl &= ~PCI_EXP_LNKCTL_LD; |
| 368 | else | 322 | else |
| 369 | lnk_ctrl |= PCI_EXP_LNKCTL_LD; | 323 | lnk_ctrl |= PCI_EXP_LNKCTL_LD; |
| 370 | 324 | ||
| 371 | retval = pciehp_writew(ctrl, PCI_EXP_LNKCTL, lnk_ctrl); | 325 | pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnk_ctrl); |
| 372 | if (retval) { | ||
| 373 | ctrl_err(ctrl, "Cannot write LNKCTRL register\n"); | ||
| 374 | return retval; | ||
| 375 | } | ||
| 376 | ctrl_dbg(ctrl, "%s: lnk_ctrl = %x\n", __func__, lnk_ctrl); | 326 | ctrl_dbg(ctrl, "%s: lnk_ctrl = %x\n", __func__, lnk_ctrl); |
| 377 | 327 | return 0; | |
| 378 | return retval; | ||
| 379 | } | 328 | } |
| 380 | 329 | ||
| 381 | static int pciehp_link_enable(struct controller *ctrl) | 330 | static int pciehp_link_enable(struct controller *ctrl) |
| @@ -388,223 +337,165 @@ static int pciehp_link_disable(struct controller *ctrl) | |||
| 388 | return __pciehp_link_set(ctrl, false); | 337 | return __pciehp_link_set(ctrl, false); |
| 389 | } | 338 | } |
| 390 | 339 | ||
| 391 | int pciehp_get_attention_status(struct slot *slot, u8 *status) | 340 | void pciehp_get_attention_status(struct slot *slot, u8 *status) |
| 392 | { | 341 | { |
| 393 | struct controller *ctrl = slot->ctrl; | 342 | struct controller *ctrl = slot->ctrl; |
| 343 | struct pci_dev *pdev = ctrl_dev(ctrl); | ||
| 394 | u16 slot_ctrl; | 344 | u16 slot_ctrl; |
| 395 | u8 atten_led_state; | ||
| 396 | int retval = 0; | ||
| 397 | |||
| 398 | retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); | ||
| 399 | if (retval) { | ||
| 400 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); | ||
| 401 | return retval; | ||
| 402 | } | ||
| 403 | 345 | ||
| 346 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); | ||
| 404 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__, | 347 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__, |
| 405 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); | 348 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); |
| 406 | 349 | ||
| 407 | atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6; | 350 | switch (slot_ctrl & PCI_EXP_SLTCTL_AIC) { |
| 408 | 351 | case PCI_EXP_SLTCTL_ATTN_IND_ON: | |
| 409 | switch (atten_led_state) { | ||
| 410 | case 0: | ||
| 411 | *status = 0xFF; /* Reserved */ | ||
| 412 | break; | ||
| 413 | case 1: | ||
| 414 | *status = 1; /* On */ | 352 | *status = 1; /* On */ |
| 415 | break; | 353 | break; |
| 416 | case 2: | 354 | case PCI_EXP_SLTCTL_ATTN_IND_BLINK: |
| 417 | *status = 2; /* Blink */ | 355 | *status = 2; /* Blink */ |
| 418 | break; | 356 | break; |
| 419 | case 3: | 357 | case PCI_EXP_SLTCTL_ATTN_IND_OFF: |
| 420 | *status = 0; /* Off */ | 358 | *status = 0; /* Off */ |
| 421 | break; | 359 | break; |
| 422 | default: | 360 | default: |
| 423 | *status = 0xFF; | 361 | *status = 0xFF; |
| 424 | break; | 362 | break; |
| 425 | } | 363 | } |
| 426 | |||
| 427 | return 0; | ||
| 428 | } | 364 | } |
| 429 | 365 | ||
| 430 | int pciehp_get_power_status(struct slot *slot, u8 *status) | 366 | void pciehp_get_power_status(struct slot *slot, u8 *status) |
| 431 | { | 367 | { |
| 432 | struct controller *ctrl = slot->ctrl; | 368 | struct controller *ctrl = slot->ctrl; |
| 369 | struct pci_dev *pdev = ctrl_dev(ctrl); | ||
| 433 | u16 slot_ctrl; | 370 | u16 slot_ctrl; |
| 434 | u8 pwr_state; | ||
| 435 | int retval = 0; | ||
| 436 | 371 | ||
| 437 | retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); | 372 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl); |
| 438 | if (retval) { | ||
| 439 | ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); | ||
| 440 | return retval; | ||
| 441 | } | ||
| 442 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__, | 373 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__, |
| 443 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); | 374 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); |
| 444 | 375 | ||
| 445 | pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10; | 376 | switch (slot_ctrl & PCI_EXP_SLTCTL_PCC) { |
| 446 | 377 | case PCI_EXP_SLTCTL_PWR_ON: | |
| 447 | switch (pwr_state) { | 378 | *status = 1; /* On */ |
| 448 | case 0: | ||
| 449 | *status = 1; | ||
| 450 | break; | 379 | break; |
| 451 | case 1: | 380 | case PCI_EXP_SLTCTL_PWR_OFF: |
| 452 | *status = 0; | 381 | *status = 0; /* Off */ |
| 453 | break; | 382 | break; |
| 454 | default: | 383 | default: |
| 455 | *status = 0xFF; | 384 | *status = 0xFF; |
| 456 | break; | 385 | break; |
| 457 | } | 386 | } |
| 458 | |||
| 459 | return retval; | ||
| 460 | } | 387 | } |
| 461 | 388 | ||
| 462 | int pciehp_get_latch_status(struct slot *slot, u8 *status) | 389 | void pciehp_get_latch_status(struct slot *slot, u8 *status) |
| 463 | { | 390 | { |
| 464 | struct controller *ctrl = slot->ctrl; | 391 | struct pci_dev *pdev = ctrl_dev(slot->ctrl); |
| 465 | u16 slot_status; | 392 | u16 slot_status; |
| 466 | int retval; | ||
| 467 | 393 | ||
| 468 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); | 394 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
| 469 | if (retval) { | ||
| 470 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", | ||
| 471 | __func__); | ||
| 472 | return retval; | ||
| 473 | } | ||
| 474 | *status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS); | 395 | *status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS); |
| 475 | return 0; | ||
| 476 | } | 396 | } |
| 477 | 397 | ||
| 478 | int pciehp_get_adapter_status(struct slot *slot, u8 *status) | 398 | void pciehp_get_adapter_status(struct slot *slot, u8 *status) |
| 479 | { | 399 | { |
| 480 | struct controller *ctrl = slot->ctrl; | 400 | struct pci_dev *pdev = ctrl_dev(slot->ctrl); |
| 481 | u16 slot_status; | 401 | u16 slot_status; |
| 482 | int retval; | ||
| 483 | 402 | ||
| 484 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); | 403 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
| 485 | if (retval) { | ||
| 486 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", | ||
| 487 | __func__); | ||
| 488 | return retval; | ||
| 489 | } | ||
| 490 | *status = !!(slot_status & PCI_EXP_SLTSTA_PDS); | 404 | *status = !!(slot_status & PCI_EXP_SLTSTA_PDS); |
| 491 | return 0; | ||
| 492 | } | 405 | } |
| 493 | 406 | ||
| 494 | int pciehp_query_power_fault(struct slot *slot) | 407 | int pciehp_query_power_fault(struct slot *slot) |
| 495 | { | 408 | { |
| 496 | struct controller *ctrl = slot->ctrl; | 409 | struct pci_dev *pdev = ctrl_dev(slot->ctrl); |
| 497 | u16 slot_status; | 410 | u16 slot_status; |
| 498 | int retval; | ||
| 499 | 411 | ||
| 500 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); | 412 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
| 501 | if (retval) { | ||
| 502 | ctrl_err(ctrl, "Cannot check for power fault\n"); | ||
| 503 | return retval; | ||
| 504 | } | ||
| 505 | return !!(slot_status & PCI_EXP_SLTSTA_PFD); | 413 | return !!(slot_status & PCI_EXP_SLTSTA_PFD); |
| 506 | } | 414 | } |
| 507 | 415 | ||
| 508 | int pciehp_set_attention_status(struct slot *slot, u8 value) | 416 | void pciehp_set_attention_status(struct slot *slot, u8 value) |
| 509 | { | 417 | { |
| 510 | struct controller *ctrl = slot->ctrl; | 418 | struct controller *ctrl = slot->ctrl; |
| 511 | u16 slot_cmd; | 419 | u16 slot_cmd; |
| 512 | u16 cmd_mask; | ||
| 513 | 420 | ||
| 514 | cmd_mask = PCI_EXP_SLTCTL_AIC; | 421 | if (!ATTN_LED(ctrl)) |
| 422 | return; | ||
| 423 | |||
| 515 | switch (value) { | 424 | switch (value) { |
| 516 | case 0 : /* turn off */ | 425 | case 0 : /* turn off */ |
| 517 | slot_cmd = 0x00C0; | 426 | slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_OFF; |
| 518 | break; | 427 | break; |
| 519 | case 1: /* turn on */ | 428 | case 1: /* turn on */ |
| 520 | slot_cmd = 0x0040; | 429 | slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_ON; |
| 521 | break; | 430 | break; |
| 522 | case 2: /* turn blink */ | 431 | case 2: /* turn blink */ |
| 523 | slot_cmd = 0x0080; | 432 | slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_BLINK; |
| 524 | break; | 433 | break; |
| 525 | default: | 434 | default: |
| 526 | return -EINVAL; | 435 | return; |
| 527 | } | 436 | } |
| 528 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, | 437 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
| 529 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); | 438 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); |
| 530 | return pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 439 | pcie_write_cmd(ctrl, slot_cmd, PCI_EXP_SLTCTL_AIC); |
| 531 | } | 440 | } |
| 532 | 441 | ||
| 533 | void pciehp_green_led_on(struct slot *slot) | 442 | void pciehp_green_led_on(struct slot *slot) |
| 534 | { | 443 | { |
| 535 | struct controller *ctrl = slot->ctrl; | 444 | struct controller *ctrl = slot->ctrl; |
| 536 | u16 slot_cmd; | ||
| 537 | u16 cmd_mask; | ||
| 538 | 445 | ||
| 539 | slot_cmd = 0x0100; | 446 | if (!PWR_LED(ctrl)) |
| 540 | cmd_mask = PCI_EXP_SLTCTL_PIC; | 447 | return; |
| 541 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 448 | |
| 449 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON, PCI_EXP_SLTCTL_PIC); | ||
| 542 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, | 450 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
| 543 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); | 451 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, |
| 452 | PCI_EXP_SLTCTL_PWR_IND_ON); | ||
| 544 | } | 453 | } |
| 545 | 454 | ||
| 546 | void pciehp_green_led_off(struct slot *slot) | 455 | void pciehp_green_led_off(struct slot *slot) |
| 547 | { | 456 | { |
| 548 | struct controller *ctrl = slot->ctrl; | 457 | struct controller *ctrl = slot->ctrl; |
| 549 | u16 slot_cmd; | ||
| 550 | u16 cmd_mask; | ||
| 551 | 458 | ||
| 552 | slot_cmd = 0x0300; | 459 | if (!PWR_LED(ctrl)) |
| 553 | cmd_mask = PCI_EXP_SLTCTL_PIC; | 460 | return; |
| 554 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 461 | |
| 462 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, PCI_EXP_SLTCTL_PIC); | ||
| 555 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, | 463 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
| 556 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); | 464 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, |
| 465 | PCI_EXP_SLTCTL_PWR_IND_OFF); | ||
| 557 | } | 466 | } |
| 558 | 467 | ||
| 559 | void pciehp_green_led_blink(struct slot *slot) | 468 | void pciehp_green_led_blink(struct slot *slot) |
| 560 | { | 469 | { |
| 561 | struct controller *ctrl = slot->ctrl; | 470 | struct controller *ctrl = slot->ctrl; |
| 562 | u16 slot_cmd; | ||
| 563 | u16 cmd_mask; | ||
| 564 | 471 | ||
| 565 | slot_cmd = 0x0200; | 472 | if (!PWR_LED(ctrl)) |
| 566 | cmd_mask = PCI_EXP_SLTCTL_PIC; | 473 | return; |
| 567 | pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 474 | |
| 475 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK, PCI_EXP_SLTCTL_PIC); | ||
| 568 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, | 476 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
| 569 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); | 477 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, |
| 478 | PCI_EXP_SLTCTL_PWR_IND_BLINK); | ||
| 570 | } | 479 | } |
| 571 | 480 | ||
| 572 | int pciehp_power_on_slot(struct slot * slot) | 481 | int pciehp_power_on_slot(struct slot * slot) |
| 573 | { | 482 | { |
| 574 | struct controller *ctrl = slot->ctrl; | 483 | struct controller *ctrl = slot->ctrl; |
| 575 | u16 slot_cmd; | 484 | struct pci_dev *pdev = ctrl_dev(ctrl); |
| 576 | u16 cmd_mask; | ||
| 577 | u16 slot_status; | 485 | u16 slot_status; |
| 578 | int retval = 0; | 486 | int retval; |
| 579 | 487 | ||
| 580 | /* Clear sticky power-fault bit from previous power failures */ | 488 | /* Clear sticky power-fault bit from previous power failures */ |
| 581 | retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); | 489 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); |
| 582 | if (retval) { | 490 | if (slot_status & PCI_EXP_SLTSTA_PFD) |
| 583 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", | 491 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, |
| 584 | __func__); | 492 | PCI_EXP_SLTSTA_PFD); |
| 585 | return retval; | ||
| 586 | } | ||
| 587 | slot_status &= PCI_EXP_SLTSTA_PFD; | ||
| 588 | if (slot_status) { | ||
| 589 | retval = pciehp_writew(ctrl, PCI_EXP_SLTSTA, slot_status); | ||
| 590 | if (retval) { | ||
| 591 | ctrl_err(ctrl, | ||
| 592 | "%s: Cannot write to SLOTSTATUS register\n", | ||
| 593 | __func__); | ||
| 594 | return retval; | ||
| 595 | } | ||
| 596 | } | ||
| 597 | ctrl->power_fault_detected = 0; | 493 | ctrl->power_fault_detected = 0; |
| 598 | 494 | ||
| 599 | slot_cmd = POWER_ON; | 495 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_ON, PCI_EXP_SLTCTL_PCC); |
| 600 | cmd_mask = PCI_EXP_SLTCTL_PCC; | ||
| 601 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | ||
| 602 | if (retval) { | ||
| 603 | ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); | ||
| 604 | return retval; | ||
| 605 | } | ||
| 606 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, | 496 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
| 607 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); | 497 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, |
| 498 | PCI_EXP_SLTCTL_PWR_ON); | ||
| 608 | 499 | ||
| 609 | retval = pciehp_link_enable(ctrl); | 500 | retval = pciehp_link_enable(ctrl); |
| 610 | if (retval) | 501 | if (retval) |
| @@ -613,12 +504,9 @@ int pciehp_power_on_slot(struct slot * slot) | |||
| 613 | return retval; | 504 | return retval; |
| 614 | } | 505 | } |
| 615 | 506 | ||
| 616 | int pciehp_power_off_slot(struct slot * slot) | 507 | void pciehp_power_off_slot(struct slot * slot) |
| 617 | { | 508 | { |
| 618 | struct controller *ctrl = slot->ctrl; | 509 | struct controller *ctrl = slot->ctrl; |
| 619 | u16 slot_cmd; | ||
| 620 | u16 cmd_mask; | ||
| 621 | int retval; | ||
| 622 | 510 | ||
| 623 | /* Disable the link at first */ | 511 | /* Disable the link at first */ |
| 624 | pciehp_link_disable(ctrl); | 512 | pciehp_link_disable(ctrl); |
| @@ -628,21 +516,16 @@ int pciehp_power_off_slot(struct slot * slot) | |||
| 628 | else | 516 | else |
| 629 | msleep(1000); | 517 | msleep(1000); |
| 630 | 518 | ||
| 631 | slot_cmd = POWER_OFF; | 519 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC); |
| 632 | cmd_mask = PCI_EXP_SLTCTL_PCC; | ||
| 633 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | ||
| 634 | if (retval) { | ||
| 635 | ctrl_err(ctrl, "Write command failed!\n"); | ||
| 636 | return retval; | ||
| 637 | } | ||
| 638 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, | 520 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
| 639 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); | 521 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, |
| 640 | return 0; | 522 | PCI_EXP_SLTCTL_PWR_OFF); |
| 641 | } | 523 | } |
| 642 | 524 | ||
| 643 | static irqreturn_t pcie_isr(int irq, void *dev_id) | 525 | static irqreturn_t pcie_isr(int irq, void *dev_id) |
| 644 | { | 526 | { |
| 645 | struct controller *ctrl = (struct controller *)dev_id; | 527 | struct controller *ctrl = (struct controller *)dev_id; |
| 528 | struct pci_dev *pdev = ctrl_dev(ctrl); | ||
| 646 | struct slot *slot = ctrl->slot; | 529 | struct slot *slot = ctrl->slot; |
| 647 | u16 detected, intr_loc; | 530 | u16 detected, intr_loc; |
| 648 | 531 | ||
| @@ -653,11 +536,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
| 653 | */ | 536 | */ |
| 654 | intr_loc = 0; | 537 | intr_loc = 0; |
| 655 | do { | 538 | do { |
| 656 | if (pciehp_readw(ctrl, PCI_EXP_SLTSTA, &detected)) { | 539 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &detected); |
| 657 | ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS\n", | ||
| 658 | __func__); | ||
| 659 | return IRQ_NONE; | ||
| 660 | } | ||
| 661 | 540 | ||
| 662 | detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | | 541 | detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | |
| 663 | PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | | 542 | PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | |
| @@ -666,11 +545,9 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
| 666 | intr_loc |= detected; | 545 | intr_loc |= detected; |
| 667 | if (!intr_loc) | 546 | if (!intr_loc) |
| 668 | return IRQ_NONE; | 547 | return IRQ_NONE; |
| 669 | if (detected && pciehp_writew(ctrl, PCI_EXP_SLTSTA, intr_loc)) { | 548 | if (detected) |
| 670 | ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n", | 549 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, |
| 671 | __func__); | 550 | intr_loc); |
| 672 | return IRQ_NONE; | ||
| 673 | } | ||
| 674 | } while (detected); | 551 | } while (detected); |
| 675 | 552 | ||
| 676 | ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc); | 553 | ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc); |
| @@ -705,7 +582,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
| 705 | return IRQ_HANDLED; | 582 | return IRQ_HANDLED; |
| 706 | } | 583 | } |
| 707 | 584 | ||
| 708 | int pcie_enable_notification(struct controller *ctrl) | 585 | void pcie_enable_notification(struct controller *ctrl) |
| 709 | { | 586 | { |
| 710 | u16 cmd, mask; | 587 | u16 cmd, mask; |
| 711 | 588 | ||
| @@ -731,22 +608,18 @@ int pcie_enable_notification(struct controller *ctrl) | |||
| 731 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | | 608 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | |
| 732 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE); | 609 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE); |
| 733 | 610 | ||
| 734 | if (pcie_write_cmd(ctrl, cmd, mask)) { | 611 | pcie_write_cmd(ctrl, cmd, mask); |
| 735 | ctrl_err(ctrl, "Cannot enable software notification\n"); | ||
| 736 | return -1; | ||
| 737 | } | ||
| 738 | return 0; | ||
| 739 | } | 612 | } |
| 740 | 613 | ||
| 741 | static void pcie_disable_notification(struct controller *ctrl) | 614 | static void pcie_disable_notification(struct controller *ctrl) |
| 742 | { | 615 | { |
| 743 | u16 mask; | 616 | u16 mask; |
| 617 | |||
| 744 | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | | 618 | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | |
| 745 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | | 619 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | |
| 746 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | | 620 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | |
| 747 | PCI_EXP_SLTCTL_DLLSCE); | 621 | PCI_EXP_SLTCTL_DLLSCE); |
| 748 | if (pcie_write_cmd(ctrl, 0, mask)) | 622 | pcie_write_cmd(ctrl, 0, mask); |
| 749 | ctrl_warn(ctrl, "Cannot disable software notification\n"); | ||
| 750 | } | 623 | } |
| 751 | 624 | ||
| 752 | /* | 625 | /* |
| @@ -758,6 +631,7 @@ static void pcie_disable_notification(struct controller *ctrl) | |||
| 758 | int pciehp_reset_slot(struct slot *slot, int probe) | 631 | int pciehp_reset_slot(struct slot *slot, int probe) |
| 759 | { | 632 | { |
| 760 | struct controller *ctrl = slot->ctrl; | 633 | struct controller *ctrl = slot->ctrl; |
| 634 | struct pci_dev *pdev = ctrl_dev(ctrl); | ||
| 761 | 635 | ||
| 762 | if (probe) | 636 | if (probe) |
| 763 | return 0; | 637 | return 0; |
| @@ -771,7 +645,8 @@ int pciehp_reset_slot(struct slot *slot, int probe) | |||
| 771 | pci_reset_bridge_secondary_bus(ctrl->pcie->port); | 645 | pci_reset_bridge_secondary_bus(ctrl->pcie->port); |
| 772 | 646 | ||
| 773 | if (HP_SUPR_RM(ctrl)) { | 647 | if (HP_SUPR_RM(ctrl)) { |
| 774 | pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDC); | 648 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, |
| 649 | PCI_EXP_SLTSTA_PDC); | ||
| 775 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE); | 650 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE); |
| 776 | if (pciehp_poll_mode) | 651 | if (pciehp_poll_mode) |
| 777 | int_poll_timeout(ctrl->poll_timer.data); | 652 | int_poll_timeout(ctrl->poll_timer.data); |
| @@ -784,10 +659,7 @@ int pcie_init_notification(struct controller *ctrl) | |||
| 784 | { | 659 | { |
| 785 | if (pciehp_request_irq(ctrl)) | 660 | if (pciehp_request_irq(ctrl)) |
| 786 | return -1; | 661 | return -1; |
| 787 | if (pcie_enable_notification(ctrl)) { | 662 | pcie_enable_notification(ctrl); |
| 788 | pciehp_free_irq(ctrl); | ||
| 789 | return -1; | ||
| 790 | } | ||
| 791 | ctrl->notification_enabled = 1; | 663 | ctrl->notification_enabled = 1; |
| 792 | return 0; | 664 | return 0; |
| 793 | } | 665 | } |
| @@ -875,12 +747,14 @@ static inline void dbg_ctrl(struct controller *ctrl) | |||
| 875 | EMI(ctrl) ? "yes" : "no"); | 747 | EMI(ctrl) ? "yes" : "no"); |
| 876 | ctrl_info(ctrl, " Command Completed : %3s\n", | 748 | ctrl_info(ctrl, " Command Completed : %3s\n", |
| 877 | NO_CMD_CMPL(ctrl) ? "no" : "yes"); | 749 | NO_CMD_CMPL(ctrl) ? "no" : "yes"); |
| 878 | pciehp_readw(ctrl, PCI_EXP_SLTSTA, ®16); | 750 | pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, ®16); |
| 879 | ctrl_info(ctrl, "Slot Status : 0x%04x\n", reg16); | 751 | ctrl_info(ctrl, "Slot Status : 0x%04x\n", reg16); |
| 880 | pciehp_readw(ctrl, PCI_EXP_SLTCTL, ®16); | 752 | pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, ®16); |
| 881 | ctrl_info(ctrl, "Slot Control : 0x%04x\n", reg16); | 753 | ctrl_info(ctrl, "Slot Control : 0x%04x\n", reg16); |
| 882 | } | 754 | } |
| 883 | 755 | ||
| 756 | #define FLAG(x,y) (((x) & (y)) ? '+' : '-') | ||
| 757 | |||
| 884 | struct controller *pcie_init(struct pcie_device *dev) | 758 | struct controller *pcie_init(struct pcie_device *dev) |
| 885 | { | 759 | { |
| 886 | struct controller *ctrl; | 760 | struct controller *ctrl; |
| @@ -893,11 +767,7 @@ struct controller *pcie_init(struct pcie_device *dev) | |||
| 893 | goto abort; | 767 | goto abort; |
| 894 | } | 768 | } |
| 895 | ctrl->pcie = dev; | 769 | ctrl->pcie = dev; |
| 896 | if (pciehp_readl(ctrl, PCI_EXP_SLTCAP, &slot_cap)) { | 770 | pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap); |
| 897 | ctrl_err(ctrl, "Cannot read SLOTCAP register\n"); | ||
| 898 | goto abort_ctrl; | ||
| 899 | } | ||
| 900 | |||
| 901 | ctrl->slot_cap = slot_cap; | 771 | ctrl->slot_cap = slot_cap; |
| 902 | mutex_init(&ctrl->ctrl_lock); | 772 | mutex_init(&ctrl->ctrl_lock); |
| 903 | init_waitqueue_head(&ctrl->queue); | 773 | init_waitqueue_head(&ctrl->queue); |
| @@ -913,25 +783,31 @@ struct controller *pcie_init(struct pcie_device *dev) | |||
| 913 | ctrl->no_cmd_complete = 1; | 783 | ctrl->no_cmd_complete = 1; |
| 914 | 784 | ||
| 915 | /* Check if Data Link Layer Link Active Reporting is implemented */ | 785 | /* Check if Data Link Layer Link Active Reporting is implemented */ |
| 916 | if (pciehp_readl(ctrl, PCI_EXP_LNKCAP, &link_cap)) { | 786 | pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); |
| 917 | ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); | ||
| 918 | goto abort_ctrl; | ||
| 919 | } | ||
| 920 | if (link_cap & PCI_EXP_LNKCAP_DLLLARC) { | 787 | if (link_cap & PCI_EXP_LNKCAP_DLLLARC) { |
| 921 | ctrl_dbg(ctrl, "Link Active Reporting supported\n"); | 788 | ctrl_dbg(ctrl, "Link Active Reporting supported\n"); |
| 922 | ctrl->link_active_reporting = 1; | 789 | ctrl->link_active_reporting = 1; |
| 923 | } | 790 | } |
| 924 | 791 | ||
| 925 | /* Clear all remaining event bits in Slot Status register */ | 792 | /* Clear all remaining event bits in Slot Status register */ |
| 926 | if (pciehp_writew(ctrl, PCI_EXP_SLTSTA, 0x1f)) | 793 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, |
| 927 | goto abort_ctrl; | 794 | PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | |
| 795 | PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | | ||
| 796 | PCI_EXP_SLTSTA_CC); | ||
| 928 | 797 | ||
| 929 | /* Disable software notification */ | 798 | /* Disable software notification */ |
| 930 | pcie_disable_notification(ctrl); | 799 | pcie_disable_notification(ctrl); |
| 931 | 800 | ||
| 932 | ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", | 801 | ctrl_info(ctrl, "Slot #%d AttnBtn%c AttnInd%c PwrInd%c PwrCtrl%c MRL%c Interlock%c NoCompl%c LLActRep%c\n", |
| 933 | pdev->vendor, pdev->device, pdev->subsystem_vendor, | 802 | (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19, |
| 934 | pdev->subsystem_device); | 803 | FLAG(slot_cap, PCI_EXP_SLTCAP_ABP), |
| 804 | FLAG(slot_cap, PCI_EXP_SLTCAP_AIP), | ||
| 805 | FLAG(slot_cap, PCI_EXP_SLTCAP_PIP), | ||
| 806 | FLAG(slot_cap, PCI_EXP_SLTCAP_PCP), | ||
| 807 | FLAG(slot_cap, PCI_EXP_SLTCAP_MRLSP), | ||
| 808 | FLAG(slot_cap, PCI_EXP_SLTCAP_EIP), | ||
| 809 | FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS), | ||
| 810 | FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC)); | ||
| 935 | 811 | ||
| 936 | if (pcie_init_slot(ctrl)) | 812 | if (pcie_init_slot(ctrl)) |
| 937 | goto abort_ctrl; | 813 | goto abort_ctrl; |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 0e0d0f7f63fd..b07d7cc2d697 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
| @@ -39,22 +39,26 @@ int pciehp_configure_device(struct slot *p_slot) | |||
| 39 | struct pci_dev *dev; | 39 | struct pci_dev *dev; |
| 40 | struct pci_dev *bridge = p_slot->ctrl->pcie->port; | 40 | struct pci_dev *bridge = p_slot->ctrl->pcie->port; |
| 41 | struct pci_bus *parent = bridge->subordinate; | 41 | struct pci_bus *parent = bridge->subordinate; |
| 42 | int num; | 42 | int num, ret = 0; |
| 43 | struct controller *ctrl = p_slot->ctrl; | 43 | struct controller *ctrl = p_slot->ctrl; |
| 44 | 44 | ||
| 45 | pci_lock_rescan_remove(); | ||
| 46 | |||
| 45 | dev = pci_get_slot(parent, PCI_DEVFN(0, 0)); | 47 | dev = pci_get_slot(parent, PCI_DEVFN(0, 0)); |
| 46 | if (dev) { | 48 | if (dev) { |
| 47 | ctrl_err(ctrl, "Device %s already exists " | 49 | ctrl_err(ctrl, "Device %s already exists " |
| 48 | "at %04x:%02x:00, cannot hot-add\n", pci_name(dev), | 50 | "at %04x:%02x:00, cannot hot-add\n", pci_name(dev), |
| 49 | pci_domain_nr(parent), parent->number); | 51 | pci_domain_nr(parent), parent->number); |
| 50 | pci_dev_put(dev); | 52 | pci_dev_put(dev); |
| 51 | return -EINVAL; | 53 | ret = -EINVAL; |
| 54 | goto out; | ||
| 52 | } | 55 | } |
| 53 | 56 | ||
| 54 | num = pci_scan_slot(parent, PCI_DEVFN(0, 0)); | 57 | num = pci_scan_slot(parent, PCI_DEVFN(0, 0)); |
| 55 | if (num == 0) { | 58 | if (num == 0) { |
| 56 | ctrl_err(ctrl, "No new device found\n"); | 59 | ctrl_err(ctrl, "No new device found\n"); |
| 57 | return -ENODEV; | 60 | ret = -ENODEV; |
| 61 | goto out; | ||
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | list_for_each_entry(dev, &parent->devices, bus_list) | 64 | list_for_each_entry(dev, &parent->devices, bus_list) |
| @@ -73,12 +77,14 @@ int pciehp_configure_device(struct slot *p_slot) | |||
| 73 | 77 | ||
| 74 | pci_bus_add_devices(parent); | 78 | pci_bus_add_devices(parent); |
| 75 | 79 | ||
| 76 | return 0; | 80 | out: |
| 81 | pci_unlock_rescan_remove(); | ||
| 82 | return ret; | ||
| 77 | } | 83 | } |
| 78 | 84 | ||
| 79 | int pciehp_unconfigure_device(struct slot *p_slot) | 85 | int pciehp_unconfigure_device(struct slot *p_slot) |
| 80 | { | 86 | { |
| 81 | int ret, rc = 0; | 87 | int rc = 0; |
| 82 | u8 bctl = 0; | 88 | u8 bctl = 0; |
| 83 | u8 presence = 0; | 89 | u8 presence = 0; |
| 84 | struct pci_dev *dev, *temp; | 90 | struct pci_dev *dev, *temp; |
| @@ -88,9 +94,9 @@ int pciehp_unconfigure_device(struct slot *p_slot) | |||
| 88 | 94 | ||
| 89 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:00\n", | 95 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:00\n", |
| 90 | __func__, pci_domain_nr(parent), parent->number); | 96 | __func__, pci_domain_nr(parent), parent->number); |
| 91 | ret = pciehp_get_adapter_status(p_slot, &presence); | 97 | pciehp_get_adapter_status(p_slot, &presence); |
| 92 | if (ret) | 98 | |
| 93 | presence = 0; | 99 | pci_lock_rescan_remove(); |
| 94 | 100 | ||
| 95 | /* | 101 | /* |
| 96 | * Stopping an SR-IOV PF device removes all the associated VFs, | 102 | * Stopping an SR-IOV PF device removes all the associated VFs, |
| @@ -126,5 +132,6 @@ int pciehp_unconfigure_device(struct slot *p_slot) | |||
| 126 | pci_dev_put(dev); | 132 | pci_dev_put(dev); |
| 127 | } | 133 | } |
| 128 | 134 | ||
| 135 | pci_unlock_rescan_remove(); | ||
| 129 | return rc; | 136 | return rc; |
| 130 | } | 137 | } |
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index e9c044d15add..4fcdeedda31b 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c | |||
| @@ -354,10 +354,15 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
| 354 | { | 354 | { |
| 355 | struct pci_bus *bus; | 355 | struct pci_bus *bus; |
| 356 | struct slot *slot; | 356 | struct slot *slot; |
| 357 | int ret = 0; | ||
| 358 | |||
| 359 | pci_lock_rescan_remove(); | ||
| 357 | 360 | ||
| 358 | bus = pcibios_find_pci_bus(dn); | 361 | bus = pcibios_find_pci_bus(dn); |
| 359 | if (!bus) | 362 | if (!bus) { |
| 360 | return -EINVAL; | 363 | ret = -EINVAL; |
| 364 | goto out; | ||
| 365 | } | ||
| 361 | 366 | ||
| 362 | pr_debug("PCI: Removing PCI slot below EADS bridge %s\n", | 367 | pr_debug("PCI: Removing PCI slot below EADS bridge %s\n", |
| 363 | bus->self ? pci_name(bus->self) : "<!PHB!>"); | 368 | bus->self ? pci_name(bus->self) : "<!PHB!>"); |
| @@ -371,7 +376,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
| 371 | printk(KERN_ERR | 376 | printk(KERN_ERR |
| 372 | "%s: unable to remove hotplug slot %s\n", | 377 | "%s: unable to remove hotplug slot %s\n", |
| 373 | __func__, drc_name); | 378 | __func__, drc_name); |
| 374 | return -EIO; | 379 | ret = -EIO; |
| 380 | goto out; | ||
| 375 | } | 381 | } |
| 376 | } | 382 | } |
| 377 | 383 | ||
| @@ -382,7 +388,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
| 382 | if (pcibios_unmap_io_space(bus)) { | 388 | if (pcibios_unmap_io_space(bus)) { |
| 383 | printk(KERN_ERR "%s: failed to unmap bus range\n", | 389 | printk(KERN_ERR "%s: failed to unmap bus range\n", |
| 384 | __func__); | 390 | __func__); |
| 385 | return -ERANGE; | 391 | ret = -ERANGE; |
| 392 | goto out; | ||
| 386 | } | 393 | } |
| 387 | 394 | ||
| 388 | /* Remove the EADS bridge device itself */ | 395 | /* Remove the EADS bridge device itself */ |
| @@ -390,7 +397,9 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn) | |||
| 390 | pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self)); | 397 | pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self)); |
| 391 | pci_stop_and_remove_bus_device(bus->self); | 398 | pci_stop_and_remove_bus_device(bus->self); |
| 392 | 399 | ||
| 393 | return 0; | 400 | out: |
| 401 | pci_unlock_rescan_remove(); | ||
| 402 | return ret; | ||
| 394 | } | 403 | } |
| 395 | 404 | ||
| 396 | /** | 405 | /** |
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index b7fc5c9255a5..4796c15fba94 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c | |||
| @@ -398,7 +398,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) | |||
| 398 | return retval; | 398 | return retval; |
| 399 | 399 | ||
| 400 | if (state == PRESENT) { | 400 | if (state == PRESENT) { |
| 401 | pci_lock_rescan_remove(); | ||
| 401 | pcibios_add_pci_devices(slot->bus); | 402 | pcibios_add_pci_devices(slot->bus); |
| 403 | pci_unlock_rescan_remove(); | ||
| 402 | slot->state = CONFIGURED; | 404 | slot->state = CONFIGURED; |
| 403 | } else if (state == EMPTY) { | 405 | } else if (state == EMPTY) { |
| 404 | slot->state = EMPTY; | 406 | slot->state = EMPTY; |
| @@ -418,7 +420,9 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) | |||
| 418 | if (slot->state == NOT_CONFIGURED) | 420 | if (slot->state == NOT_CONFIGURED) |
| 419 | return -EINVAL; | 421 | return -EINVAL; |
| 420 | 422 | ||
| 423 | pci_lock_rescan_remove(); | ||
| 421 | pcibios_remove_pci_devices(slot->bus); | 424 | pcibios_remove_pci_devices(slot->bus); |
| 425 | pci_unlock_rescan_remove(); | ||
| 422 | vm_unmap_aliases(); | 426 | vm_unmap_aliases(); |
| 423 | 427 | ||
| 424 | slot->state = NOT_CONFIGURED; | 428 | slot->state = NOT_CONFIGURED; |
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c index 3c7eb5dd91c6..8d2ce22151eb 100644 --- a/drivers/pci/hotplug/s390_pci_hpc.c +++ b/drivers/pci/hotplug/s390_pci_hpc.c | |||
| @@ -80,7 +80,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot) | |||
| 80 | goto out_deconfigure; | 80 | goto out_deconfigure; |
| 81 | 81 | ||
| 82 | pci_scan_slot(slot->zdev->bus, ZPCI_DEVFN); | 82 | pci_scan_slot(slot->zdev->bus, ZPCI_DEVFN); |
| 83 | pci_lock_rescan_remove(); | ||
| 83 | pci_bus_add_devices(slot->zdev->bus); | 84 | pci_bus_add_devices(slot->zdev->bus); |
| 85 | pci_unlock_rescan_remove(); | ||
| 84 | 86 | ||
| 85 | return rc; | 87 | return rc; |
| 86 | 88 | ||
| @@ -98,7 +100,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot) | |||
| 98 | return -EIO; | 100 | return -EIO; |
| 99 | 101 | ||
| 100 | if (slot->zdev->pdev) | 102 | if (slot->zdev->pdev) |
| 101 | pci_stop_and_remove_bus_device(slot->zdev->pdev); | 103 | pci_stop_and_remove_bus_device_locked(slot->zdev->pdev); |
| 102 | 104 | ||
| 103 | rc = zpci_disable_device(slot->zdev); | 105 | rc = zpci_disable_device(slot->zdev); |
| 104 | if (rc) | 106 | if (rc) |
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index 5b05a68cca6c..613043f7576f 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c | |||
| @@ -459,12 +459,15 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
| 459 | acpi_scan_lock_release(); | 459 | acpi_scan_lock_release(); |
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | pci_lock_rescan_remove(); | ||
| 463 | |||
| 462 | /* Call the driver for the new device */ | 464 | /* Call the driver for the new device */ |
| 463 | pci_bus_add_devices(slot->pci_bus); | 465 | pci_bus_add_devices(slot->pci_bus); |
| 464 | /* Call the drivers for the new devices subordinate to PPB */ | 466 | /* Call the drivers for the new devices subordinate to PPB */ |
| 465 | if (new_ppb) | 467 | if (new_ppb) |
| 466 | pci_bus_add_devices(new_bus); | 468 | pci_bus_add_devices(new_bus); |
| 467 | 469 | ||
| 470 | pci_unlock_rescan_remove(); | ||
| 468 | mutex_unlock(&sn_hotplug_mutex); | 471 | mutex_unlock(&sn_hotplug_mutex); |
| 469 | 472 | ||
| 470 | if (rc == 0) | 473 | if (rc == 0) |
| @@ -540,6 +543,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
| 540 | acpi_scan_lock_release(); | 543 | acpi_scan_lock_release(); |
| 541 | } | 544 | } |
| 542 | 545 | ||
| 546 | pci_lock_rescan_remove(); | ||
| 543 | /* Free the SN resources assigned to the Linux device.*/ | 547 | /* Free the SN resources assigned to the Linux device.*/ |
| 544 | list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) { | 548 | list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) { |
| 545 | if (PCI_SLOT(dev->devfn) != slot->device_num + 1) | 549 | if (PCI_SLOT(dev->devfn) != slot->device_num + 1) |
| @@ -550,6 +554,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) | |||
| 550 | pci_stop_and_remove_bus_device(dev); | 554 | pci_stop_and_remove_bus_device(dev); |
| 551 | pci_dev_put(dev); | 555 | pci_dev_put(dev); |
| 552 | } | 556 | } |
| 557 | pci_unlock_rescan_remove(); | ||
| 553 | 558 | ||
| 554 | /* Remove the SSDT for the slot from the ACPI namespace */ | 559 | /* Remove the SSDT for the slot from the ACPI namespace */ |
| 555 | if (SN_ACPI_BASE_SUPPORT() && ssdt_id) { | 560 | if (SN_ACPI_BASE_SUPPORT() && ssdt_id) { |
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index b0e83132542e..2bf69fe1926c 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
| @@ -40,7 +40,9 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
| 40 | struct controller *ctrl = p_slot->ctrl; | 40 | struct controller *ctrl = p_slot->ctrl; |
| 41 | struct pci_dev *bridge = ctrl->pci_dev; | 41 | struct pci_dev *bridge = ctrl->pci_dev; |
| 42 | struct pci_bus *parent = bridge->subordinate; | 42 | struct pci_bus *parent = bridge->subordinate; |
| 43 | int num; | 43 | int num, ret = 0; |
| 44 | |||
| 45 | pci_lock_rescan_remove(); | ||
| 44 | 46 | ||
| 45 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); | 47 | dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); |
| 46 | if (dev) { | 48 | if (dev) { |
| @@ -48,13 +50,15 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
| 48 | "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev), | 50 | "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev), |
| 49 | pci_domain_nr(parent), p_slot->bus, p_slot->device); | 51 | pci_domain_nr(parent), p_slot->bus, p_slot->device); |
| 50 | pci_dev_put(dev); | 52 | pci_dev_put(dev); |
| 51 | return -EINVAL; | 53 | ret = -EINVAL; |
| 54 | goto out; | ||
| 52 | } | 55 | } |
| 53 | 56 | ||
| 54 | num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); | 57 | num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0)); |
| 55 | if (num == 0) { | 58 | if (num == 0) { |
| 56 | ctrl_err(ctrl, "No new device found\n"); | 59 | ctrl_err(ctrl, "No new device found\n"); |
| 57 | return -ENODEV; | 60 | ret = -ENODEV; |
| 61 | goto out; | ||
| 58 | } | 62 | } |
| 59 | 63 | ||
| 60 | list_for_each_entry(dev, &parent->devices, bus_list) { | 64 | list_for_each_entry(dev, &parent->devices, bus_list) { |
| @@ -75,7 +79,9 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
| 75 | 79 | ||
| 76 | pci_bus_add_devices(parent); | 80 | pci_bus_add_devices(parent); |
| 77 | 81 | ||
| 78 | return 0; | 82 | out: |
| 83 | pci_unlock_rescan_remove(); | ||
| 84 | return ret; | ||
| 79 | } | 85 | } |
| 80 | 86 | ||
| 81 | int shpchp_unconfigure_device(struct slot *p_slot) | 87 | int shpchp_unconfigure_device(struct slot *p_slot) |
| @@ -89,6 +95,8 @@ int shpchp_unconfigure_device(struct slot *p_slot) | |||
| 89 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", | 95 | ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", |
| 90 | __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); | 96 | __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); |
| 91 | 97 | ||
| 98 | pci_lock_rescan_remove(); | ||
| 99 | |||
| 92 | list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { | 100 | list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { |
| 93 | if (PCI_SLOT(dev->devfn) != p_slot->device) | 101 | if (PCI_SLOT(dev->devfn) != p_slot->device) |
| 94 | continue; | 102 | continue; |
| @@ -108,6 +116,8 @@ int shpchp_unconfigure_device(struct slot *p_slot) | |||
| 108 | pci_stop_and_remove_bus_device(dev); | 116 | pci_stop_and_remove_bus_device(dev); |
| 109 | pci_dev_put(dev); | 117 | pci_dev_put(dev); |
| 110 | } | 118 | } |
| 119 | |||
| 120 | pci_unlock_rescan_remove(); | ||
| 111 | return rc; | 121 | return rc; |
| 112 | } | 122 | } |
| 113 | 123 | ||
