diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 18:14:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-01 18:14:04 -0400 |
commit | 4b1779c2cf030c68aefe939d946475e4136c1895 (patch) | |
tree | 27e4bda2f6c8d269d02dec52a62dd1443880c6dc /drivers/pci/hotplug | |
parent | 62ff577fa2fec87edbf26f53e87210ba726d4d44 (diff) | |
parent | 30723cbf6f7aec2ab4810bdc4bf12c5749a09e33 (diff) |
Merge tag 'pci-v3.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI changes from Bjorn Helgaas:
"Enumeration
- Increment max correctly in pci_scan_bridge() (Andreas Noever)
- Clarify the "scan anyway" comment in pci_scan_bridge() (Andreas Noever)
- Assign CardBus bus number only during the second pass (Andreas Noever)
- Use request_resource_conflict() instead of insert_ for bus numbers (Andreas Noever)
- Make sure bus number resources stay within their parents bounds (Andreas Noever)
- Remove pci_fixup_parent_subordinate_busnr() (Andreas Noever)
- Check for child busses which use more bus numbers than allocated (Andreas Noever)
- Don't scan random busses in pci_scan_bridge() (Andreas Noever)
- x86: Drop pcibios_scan_root() check for bus already scanned (Bjorn Helgaas)
- x86: Use pcibios_scan_root() instead of pci_scan_bus_with_sysdata() (Bjorn Helgaas)
- x86: Use pcibios_scan_root() instead of pci_scan_bus_on_node() (Bjorn Helgaas)
- x86: Merge pci_scan_bus_on_node() into pcibios_scan_root() (Bjorn Helgaas)
- x86: Drop return value of pcibios_scan_root() (Bjorn Helgaas)
NUMA
- x86: Add x86_pci_root_bus_node() to look up NUMA node from PCI bus (Bjorn Helgaas)
- x86: Use x86_pci_root_bus_node() instead of get_mp_bus_to_node() (Bjorn Helgaas)
- x86: Remove mp_bus_to_node[], set_mp_bus_to_node(), get_mp_bus_to_node() (Bjorn Helgaas)
- x86: Use NUMA_NO_NODE, not -1, for unknown node (Bjorn Helgaas)
- x86: Remove acpi_get_pxm() usage (Bjorn Helgaas)
- ia64: Use NUMA_NO_NODE, not MAX_NUMNODES, for unknown node (Bjorn Helgaas)
- ia64: Remove acpi_get_pxm() usage (Bjorn Helgaas)
- ACPI: Fix acpi_get_node() prototype (Bjorn Helgaas)
Resource management
- i2o: Fix and refactor PCI space allocation (Bjorn Helgaas)
- Add resource_contains() (Bjorn Helgaas)
- Add %pR support for IORESOURCE_UNSET (Bjorn Helgaas)
- Mark resources as IORESOURCE_UNSET if we can't assign them (Bjorn Helgaas)
- Don't clear IORESOURCE_UNSET when updating BAR (Bjorn Helgaas)
- Check IORESOURCE_UNSET before updating BAR (Bjorn Helgaas)
- Don't try to claim IORESOURCE_UNSET resources (Bjorn Helgaas)
- Mark 64-bit resource as IORESOURCE_UNSET if we only support 32-bit (Bjorn Helgaas)
- Don't enable decoding if BAR hasn't been assigned an address (Bjorn Helgaas)
- Add "weak" generic pcibios_enable_device() implementation (Bjorn Helgaas)
- alpha, microblaze, sh, sparc, tile: Use default pcibios_enable_device() (Bjorn Helgaas)
- s390: Use generic pci_enable_resources() (Bjorn Helgaas)
- Don't check resource_size() in pci_bus_alloc_resource() (Bjorn Helgaas)
- Set type in __request_region() (Bjorn Helgaas)
- Check all IORESOURCE_TYPE_BITS in pci_bus_alloc_from_region() (Bjorn Helgaas)
- Change pci_bus_alloc_resource() type_mask to unsigned long (Bjorn Helgaas)
- Log IDE resource quirk in dmesg (Bjorn Helgaas)
- Revert "[PATCH] Insert GART region into resource map" (Bjorn Helgaas)
PCI device hotplug
- Make check_link_active() non-static (Rajat Jain)
- Use link change notifications for hot-plug and removal (Rajat Jain)
- Enable link state change notifications (Rajat Jain)
- Don't disable the link permanently during removal (Rajat Jain)
- Don't check adapter or latch status while disabling (Rajat Jain)
- Disable link notification across slot reset (Rajat Jain)
- Ensure very fast hotplug events are also processed (Rajat Jain)
- Add hotplug_lock to serialize hotplug events (Rajat Jain)
- Remove a non-existent card, regardless of "surprise" capability (Rajat Jain)
- Don't turn slot off when hot-added device already exists (Yijing Wang)
MSI
- Keep pci_enable_msi() documentation (Alexander Gordeev)
- ahci: Fix broken single MSI fallback (Alexander Gordeev)
- ahci, vfio: Use pci_enable_msi_range() (Alexander Gordeev)
- Check kmalloc() return value, fix leak of name (Greg Kroah-Hartman)
- Fix leak of msi_attrs (Greg Kroah-Hartman)
- Fix pci_msix_vec_count() htmldocs failure (Masanari Iida)
Virtualization
- Device-specific ACS support (Alex Williamson)
Freescale i.MX6
- Wait for retraining (Marek Vasut)
Marvell MVEBU
- Use Device ID and revision from underlying endpoint (Andrew Lunn)
- Fix incorrect size for PCI aperture resources (Jason Gunthorpe)
- Call request_resource() on the apertures (Jason Gunthorpe)
- Fix potential issue in range parsing (Jean-Jacques Hiblot)
Renesas R-Car
- Check platform_get_irq() return code (Ben Dooks)
- Add error interrupt handling (Ben Dooks)
- Fix bridge logic configuration accesses (Ben Dooks)
- Register each instance independently (Magnus Damm)
- Break out window size handling (Magnus Damm)
- Make the Kconfig dependencies more generic (Magnus Damm)
Synopsys DesignWare
- Fix RC BAR to be single 64-bit non-prefetchable memory (Mohit Kumar)
Miscellaneous
- Remove unused SR-IOV VF Migration support (Bjorn Helgaas)
- Enable INTx if BIOS left them disabled (Bjorn Helgaas)
- Fix hex vs decimal typo in cpqhpc_probe() (Dan Carpenter)
- Clean up par-arch object file list (Liviu Dudau)
- Set IORESOURCE_ROM_SHADOW only for the default VGA device (Sander Eikelenboom)
- ACPI, ARM, drm, powerpc, pcmcia, PCI: Use list_for_each_entry() for bus traversal (Yijing Wang)
- Fix pci_bus_b() build failure (Paul Gortmaker)"
* tag 'pci-v3.15-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (108 commits)
Revert "[PATCH] Insert GART region into resource map"
PCI: Log IDE resource quirk in dmesg
PCI: Change pci_bus_alloc_resource() type_mask to unsigned long
PCI: Check all IORESOURCE_TYPE_BITS in pci_bus_alloc_from_region()
resources: Set type in __request_region()
PCI: Don't check resource_size() in pci_bus_alloc_resource()
s390/PCI: Use generic pci_enable_resources()
tile PCI RC: Use default pcibios_enable_device()
sparc/PCI: Use default pcibios_enable_device() (Leon only)
sh/PCI: Use default pcibios_enable_device()
microblaze/PCI: Use default pcibios_enable_device()
alpha/PCI: Use default pcibios_enable_device()
PCI: Add "weak" generic pcibios_enable_device() implementation
PCI: Don't enable decoding if BAR hasn't been assigned an address
PCI: Enable INTx in pci_reenable_device() only when MSI/MSI-X not enabled
PCI: Mark 64-bit resource as IORESOURCE_UNSET if we only support 32-bit
PCI: Don't try to claim IORESOURCE_UNSET resources
PCI: Check IORESOURCE_UNSET before updating BAR
PCI: Don't clear IORESOURCE_UNSET when updating BAR
PCI: Mark resources as IORESOURCE_UNSET if we can't assign them
...
Conflicts:
arch/x86/include/asm/topology.h
drivers/ata/ahci.c
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 6 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_core.c | 4 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 5 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_acpi.c | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 8 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 173 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 75 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 2 |
8 files changed, 194 insertions, 80 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 828acf422c17..bccc27ee1030 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -424,7 +424,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
424 | */ | 424 | */ |
425 | static unsigned char acpiphp_max_busnr(struct pci_bus *bus) | 425 | static unsigned char acpiphp_max_busnr(struct pci_bus *bus) |
426 | { | 426 | { |
427 | struct list_head *tmp; | 427 | struct pci_bus *tmp; |
428 | unsigned char max, n; | 428 | unsigned char max, n; |
429 | 429 | ||
430 | /* | 430 | /* |
@@ -437,8 +437,8 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) | |||
437 | */ | 437 | */ |
438 | max = bus->busn_res.start; | 438 | max = bus->busn_res.start; |
439 | 439 | ||
440 | list_for_each(tmp, &bus->children) { | 440 | list_for_each_entry(tmp, &bus->children, node) { |
441 | n = pci_bus_max_busnr(pci_bus_b(tmp)); | 441 | n = pci_bus_max_busnr(tmp); |
442 | if (n > max) | 442 | if (n > max) |
443 | max = n; | 443 | max = n; |
444 | } | 444 | } |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 31273e155e6c..037e2612c5bd 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
@@ -920,12 +920,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
920 | bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; | 920 | bus->max_bus_speed = PCI_SPEED_100MHz_PCIX; |
921 | break; | 921 | break; |
922 | } | 922 | } |
923 | if (bus_cap & 20) { | 923 | if (bus_cap & 0x20) { |
924 | dbg("bus max supports 66MHz PCI-X\n"); | 924 | dbg("bus max supports 66MHz PCI-X\n"); |
925 | bus->max_bus_speed = PCI_SPEED_66MHz_PCIX; | 925 | bus->max_bus_speed = PCI_SPEED_66MHz_PCIX; |
926 | break; | 926 | break; |
927 | } | 927 | } |
928 | if (bus_cap & 10) { | 928 | if (bus_cap & 0x10) { |
929 | dbg("bus max supports 66MHz PCI\n"); | 929 | dbg("bus max supports 66MHz PCI\n"); |
930 | bus->max_bus_speed = PCI_SPEED_66MHz; | 930 | bus->max_bus_speed = PCI_SPEED_66MHz; |
931 | break; | 931 | break; |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 88b37cad4b35..8a66866b8cf1 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -76,6 +76,7 @@ struct slot { | |||
76 | struct hotplug_slot *hotplug_slot; | 76 | struct hotplug_slot *hotplug_slot; |
77 | struct delayed_work work; /* work for button event */ | 77 | struct delayed_work work; /* work for button event */ |
78 | struct mutex lock; | 78 | struct mutex lock; |
79 | struct mutex hotplug_lock; | ||
79 | struct workqueue_struct *wq; | 80 | struct workqueue_struct *wq; |
80 | }; | 81 | }; |
81 | 82 | ||
@@ -109,6 +110,8 @@ struct controller { | |||
109 | #define INT_BUTTON_PRESS 7 | 110 | #define INT_BUTTON_PRESS 7 |
110 | #define INT_BUTTON_RELEASE 8 | 111 | #define INT_BUTTON_RELEASE 8 |
111 | #define INT_BUTTON_CANCEL 9 | 112 | #define INT_BUTTON_CANCEL 9 |
113 | #define INT_LINK_UP 10 | ||
114 | #define INT_LINK_DOWN 11 | ||
112 | 115 | ||
113 | #define STATIC_STATE 0 | 116 | #define STATIC_STATE 0 |
114 | #define BLINKINGON_STATE 1 | 117 | #define BLINKINGON_STATE 1 |
@@ -132,6 +135,7 @@ u8 pciehp_handle_attention_button(struct slot *p_slot); | |||
132 | u8 pciehp_handle_switch_change(struct slot *p_slot); | 135 | u8 pciehp_handle_switch_change(struct slot *p_slot); |
133 | u8 pciehp_handle_presence_change(struct slot *p_slot); | 136 | u8 pciehp_handle_presence_change(struct slot *p_slot); |
134 | u8 pciehp_handle_power_fault(struct slot *p_slot); | 137 | u8 pciehp_handle_power_fault(struct slot *p_slot); |
138 | void pciehp_handle_linkstate_change(struct slot *p_slot); | ||
135 | int pciehp_configure_device(struct slot *p_slot); | 139 | int pciehp_configure_device(struct slot *p_slot); |
136 | int pciehp_unconfigure_device(struct slot *p_slot); | 140 | int pciehp_unconfigure_device(struct slot *p_slot); |
137 | void pciehp_queue_pushbutton_work(struct work_struct *work); | 141 | void pciehp_queue_pushbutton_work(struct work_struct *work); |
@@ -153,6 +157,7 @@ void pciehp_green_led_on(struct slot *slot); | |||
153 | void pciehp_green_led_off(struct slot *slot); | 157 | void pciehp_green_led_off(struct slot *slot); |
154 | void pciehp_green_led_blink(struct slot *slot); | 158 | void pciehp_green_led_blink(struct slot *slot); |
155 | int pciehp_check_link_status(struct controller *ctrl); | 159 | int pciehp_check_link_status(struct controller *ctrl); |
160 | bool pciehp_check_link_active(struct controller *ctrl); | ||
156 | void pciehp_release_ctrl(struct controller *ctrl); | 161 | void pciehp_release_ctrl(struct controller *ctrl); |
157 | int pciehp_reset_slot(struct slot *slot, int probe); | 162 | int pciehp_reset_slot(struct slot *slot, int probe); |
158 | 163 | ||
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index eddddd447d0d..20fea57d2149 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c | |||
@@ -112,6 +112,7 @@ static struct pcie_port_service_driver __initdata dummy_driver = { | |||
112 | static int __init select_detection_mode(void) | 112 | static int __init select_detection_mode(void) |
113 | { | 113 | { |
114 | struct dummy_slot *slot, *tmp; | 114 | struct dummy_slot *slot, *tmp; |
115 | |||
115 | if (pcie_port_service_register(&dummy_driver)) | 116 | if (pcie_port_service_register(&dummy_driver)) |
116 | return PCIEHP_DETECT_ACPI; | 117 | return PCIEHP_DETECT_ACPI; |
117 | pcie_port_service_unregister(&dummy_driver); | 118 | pcie_port_service_unregister(&dummy_driver); |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 53b58debc288..0e0a2fff20a3 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -108,6 +108,7 @@ static int init_slot(struct controller *ctrl) | |||
108 | ops = kzalloc(sizeof(*ops), GFP_KERNEL); | 108 | ops = kzalloc(sizeof(*ops), GFP_KERNEL); |
109 | if (!ops) | 109 | if (!ops) |
110 | goto out; | 110 | goto out; |
111 | |||
111 | ops->enable_slot = enable_slot; | 112 | ops->enable_slot = enable_slot; |
112 | ops->disable_slot = disable_slot; | 113 | ops->disable_slot = disable_slot; |
113 | ops->get_power_status = get_power_status; | 114 | ops->get_power_status = get_power_status; |
@@ -283,8 +284,11 @@ static int pciehp_probe(struct pcie_device *dev) | |||
283 | slot = ctrl->slot; | 284 | slot = ctrl->slot; |
284 | pciehp_get_adapter_status(slot, &occupied); | 285 | pciehp_get_adapter_status(slot, &occupied); |
285 | pciehp_get_power_status(slot, &poweron); | 286 | pciehp_get_power_status(slot, &poweron); |
286 | if (occupied && pciehp_force) | 287 | if (occupied && pciehp_force) { |
288 | mutex_lock(&slot->hotplug_lock); | ||
287 | pciehp_enable_slot(slot); | 289 | pciehp_enable_slot(slot); |
290 | mutex_unlock(&slot->hotplug_lock); | ||
291 | } | ||
288 | /* If empty slot's power status is on, turn power off */ | 292 | /* If empty slot's power status is on, turn power off */ |
289 | if (!occupied && poweron && POWER_CTRL(ctrl)) | 293 | if (!occupied && poweron && POWER_CTRL(ctrl)) |
290 | pciehp_power_off_slot(slot); | 294 | pciehp_power_off_slot(slot); |
@@ -328,10 +332,12 @@ static int pciehp_resume (struct pcie_device *dev) | |||
328 | 332 | ||
329 | /* Check if slot is occupied */ | 333 | /* Check if slot is occupied */ |
330 | pciehp_get_adapter_status(slot, &status); | 334 | pciehp_get_adapter_status(slot, &status); |
335 | mutex_lock(&slot->hotplug_lock); | ||
331 | if (status) | 336 | if (status) |
332 | pciehp_enable_slot(slot); | 337 | pciehp_enable_slot(slot); |
333 | else | 338 | else |
334 | pciehp_disable_slot(slot); | 339 | pciehp_disable_slot(slot); |
340 | mutex_unlock(&slot->hotplug_lock); | ||
335 | return 0; | 341 | return 0; |
336 | } | 342 | } |
337 | #endif /* PM */ | 343 | #endif /* PM */ |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 50628487597d..c75e6a678dcc 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -150,6 +150,27 @@ u8 pciehp_handle_power_fault(struct slot *p_slot) | |||
150 | return 1; | 150 | return 1; |
151 | } | 151 | } |
152 | 152 | ||
153 | void pciehp_handle_linkstate_change(struct slot *p_slot) | ||
154 | { | ||
155 | u32 event_type; | ||
156 | struct controller *ctrl = p_slot->ctrl; | ||
157 | |||
158 | /* Link Status Change */ | ||
159 | ctrl_dbg(ctrl, "Data Link Layer State change\n"); | ||
160 | |||
161 | if (pciehp_check_link_active(ctrl)) { | ||
162 | ctrl_info(ctrl, "slot(%s): Link Up event\n", | ||
163 | slot_name(p_slot)); | ||
164 | event_type = INT_LINK_UP; | ||
165 | } else { | ||
166 | ctrl_info(ctrl, "slot(%s): Link Down event\n", | ||
167 | slot_name(p_slot)); | ||
168 | event_type = INT_LINK_DOWN; | ||
169 | } | ||
170 | |||
171 | queue_interrupt_event(p_slot, event_type); | ||
172 | } | ||
173 | |||
153 | /* The following routines constitute the bulk of the | 174 | /* The following routines constitute the bulk of the |
154 | hotplug controller logic | 175 | hotplug controller logic |
155 | */ | 176 | */ |
@@ -212,7 +233,8 @@ static int board_added(struct slot *p_slot) | |||
212 | if (retval) { | 233 | if (retval) { |
213 | ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n", | 234 | ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n", |
214 | pci_domain_nr(parent), parent->number); | 235 | pci_domain_nr(parent), parent->number); |
215 | goto err_exit; | 236 | if (retval != -EEXIST) |
237 | goto err_exit; | ||
216 | } | 238 | } |
217 | 239 | ||
218 | pciehp_green_led_on(p_slot); | 240 | pciehp_green_led_on(p_slot); |
@@ -255,6 +277,9 @@ static int remove_board(struct slot *p_slot) | |||
255 | struct power_work_info { | 277 | struct power_work_info { |
256 | struct slot *p_slot; | 278 | struct slot *p_slot; |
257 | struct work_struct work; | 279 | struct work_struct work; |
280 | unsigned int req; | ||
281 | #define DISABLE_REQ 0 | ||
282 | #define ENABLE_REQ 1 | ||
258 | }; | 283 | }; |
259 | 284 | ||
260 | /** | 285 | /** |
@@ -269,30 +294,38 @@ static void pciehp_power_thread(struct work_struct *work) | |||
269 | struct power_work_info *info = | 294 | struct power_work_info *info = |
270 | container_of(work, struct power_work_info, work); | 295 | container_of(work, struct power_work_info, work); |
271 | struct slot *p_slot = info->p_slot; | 296 | struct slot *p_slot = info->p_slot; |
297 | int ret; | ||
272 | 298 | ||
273 | mutex_lock(&p_slot->lock); | 299 | switch (info->req) { |
274 | switch (p_slot->state) { | 300 | case DISABLE_REQ: |
275 | case POWEROFF_STATE: | ||
276 | mutex_unlock(&p_slot->lock); | ||
277 | ctrl_dbg(p_slot->ctrl, | 301 | ctrl_dbg(p_slot->ctrl, |
278 | "Disabling domain:bus:device=%04x:%02x:00\n", | 302 | "Disabling domain:bus:device=%04x:%02x:00\n", |
279 | pci_domain_nr(p_slot->ctrl->pcie->port->subordinate), | 303 | pci_domain_nr(p_slot->ctrl->pcie->port->subordinate), |
280 | p_slot->ctrl->pcie->port->subordinate->number); | 304 | p_slot->ctrl->pcie->port->subordinate->number); |
305 | mutex_lock(&p_slot->hotplug_lock); | ||
281 | pciehp_disable_slot(p_slot); | 306 | pciehp_disable_slot(p_slot); |
307 | mutex_unlock(&p_slot->hotplug_lock); | ||
282 | mutex_lock(&p_slot->lock); | 308 | mutex_lock(&p_slot->lock); |
283 | p_slot->state = STATIC_STATE; | 309 | p_slot->state = STATIC_STATE; |
284 | break; | ||
285 | case POWERON_STATE: | ||
286 | mutex_unlock(&p_slot->lock); | 310 | mutex_unlock(&p_slot->lock); |
287 | if (pciehp_enable_slot(p_slot)) | 311 | break; |
312 | case ENABLE_REQ: | ||
313 | ctrl_dbg(p_slot->ctrl, | ||
314 | "Enabling domain:bus:device=%04x:%02x:00\n", | ||
315 | pci_domain_nr(p_slot->ctrl->pcie->port->subordinate), | ||
316 | p_slot->ctrl->pcie->port->subordinate->number); | ||
317 | mutex_lock(&p_slot->hotplug_lock); | ||
318 | ret = pciehp_enable_slot(p_slot); | ||
319 | mutex_unlock(&p_slot->hotplug_lock); | ||
320 | if (ret) | ||
288 | pciehp_green_led_off(p_slot); | 321 | pciehp_green_led_off(p_slot); |
289 | mutex_lock(&p_slot->lock); | 322 | mutex_lock(&p_slot->lock); |
290 | p_slot->state = STATIC_STATE; | 323 | p_slot->state = STATIC_STATE; |
324 | mutex_unlock(&p_slot->lock); | ||
291 | break; | 325 | break; |
292 | default: | 326 | default: |
293 | break; | 327 | break; |
294 | } | 328 | } |
295 | mutex_unlock(&p_slot->lock); | ||
296 | 329 | ||
297 | kfree(info); | 330 | kfree(info); |
298 | } | 331 | } |
@@ -315,9 +348,11 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) | |||
315 | switch (p_slot->state) { | 348 | switch (p_slot->state) { |
316 | case BLINKINGOFF_STATE: | 349 | case BLINKINGOFF_STATE: |
317 | p_slot->state = POWEROFF_STATE; | 350 | p_slot->state = POWEROFF_STATE; |
351 | info->req = DISABLE_REQ; | ||
318 | break; | 352 | break; |
319 | case BLINKINGON_STATE: | 353 | case BLINKINGON_STATE: |
320 | p_slot->state = POWERON_STATE; | 354 | p_slot->state = POWERON_STATE; |
355 | info->req = ENABLE_REQ; | ||
321 | break; | 356 | break; |
322 | default: | 357 | default: |
323 | kfree(info); | 358 | kfree(info); |
@@ -364,11 +399,10 @@ static void handle_button_press_event(struct slot *p_slot) | |||
364 | */ | 399 | */ |
365 | ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); | 400 | ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot)); |
366 | cancel_delayed_work(&p_slot->work); | 401 | cancel_delayed_work(&p_slot->work); |
367 | if (p_slot->state == BLINKINGOFF_STATE) { | 402 | if (p_slot->state == BLINKINGOFF_STATE) |
368 | pciehp_green_led_on(p_slot); | 403 | pciehp_green_led_on(p_slot); |
369 | } else { | 404 | else |
370 | pciehp_green_led_off(p_slot); | 405 | pciehp_green_led_off(p_slot); |
371 | } | ||
372 | pciehp_set_attention_status(p_slot, 0); | 406 | pciehp_set_attention_status(p_slot, 0); |
373 | ctrl_info(ctrl, "PCI slot #%s - action canceled " | 407 | ctrl_info(ctrl, "PCI slot #%s - action canceled " |
374 | "due to button press\n", slot_name(p_slot)); | 408 | "due to button press\n", slot_name(p_slot)); |
@@ -407,14 +441,81 @@ static void handle_surprise_event(struct slot *p_slot) | |||
407 | INIT_WORK(&info->work, pciehp_power_thread); | 441 | INIT_WORK(&info->work, pciehp_power_thread); |
408 | 442 | ||
409 | pciehp_get_adapter_status(p_slot, &getstatus); | 443 | pciehp_get_adapter_status(p_slot, &getstatus); |
410 | if (!getstatus) | 444 | if (!getstatus) { |
411 | p_slot->state = POWEROFF_STATE; | 445 | p_slot->state = POWEROFF_STATE; |
412 | else | 446 | info->req = DISABLE_REQ; |
447 | } else { | ||
413 | p_slot->state = POWERON_STATE; | 448 | p_slot->state = POWERON_STATE; |
449 | info->req = ENABLE_REQ; | ||
450 | } | ||
414 | 451 | ||
415 | queue_work(p_slot->wq, &info->work); | 452 | queue_work(p_slot->wq, &info->work); |
416 | } | 453 | } |
417 | 454 | ||
455 | /* | ||
456 | * Note: This function must be called with slot->lock held | ||
457 | */ | ||
458 | static void handle_link_event(struct slot *p_slot, u32 event) | ||
459 | { | ||
460 | struct controller *ctrl = p_slot->ctrl; | ||
461 | struct power_work_info *info; | ||
462 | |||
463 | info = kmalloc(sizeof(*info), GFP_KERNEL); | ||
464 | if (!info) { | ||
465 | ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", | ||
466 | __func__); | ||
467 | return; | ||
468 | } | ||
469 | info->p_slot = p_slot; | ||
470 | info->req = event == INT_LINK_UP ? ENABLE_REQ : DISABLE_REQ; | ||
471 | INIT_WORK(&info->work, pciehp_power_thread); | ||
472 | |||
473 | switch (p_slot->state) { | ||
474 | case BLINKINGON_STATE: | ||
475 | case BLINKINGOFF_STATE: | ||
476 | cancel_delayed_work(&p_slot->work); | ||
477 | /* Fall through */ | ||
478 | case STATIC_STATE: | ||
479 | p_slot->state = event == INT_LINK_UP ? | ||
480 | POWERON_STATE : POWEROFF_STATE; | ||
481 | queue_work(p_slot->wq, &info->work); | ||
482 | break; | ||
483 | case POWERON_STATE: | ||
484 | if (event == INT_LINK_UP) { | ||
485 | ctrl_info(ctrl, | ||
486 | "Link Up event ignored on slot(%s): already powering on\n", | ||
487 | slot_name(p_slot)); | ||
488 | kfree(info); | ||
489 | } else { | ||
490 | ctrl_info(ctrl, | ||
491 | "Link Down event queued on slot(%s): currently getting powered on\n", | ||
492 | slot_name(p_slot)); | ||
493 | p_slot->state = POWEROFF_STATE; | ||
494 | queue_work(p_slot->wq, &info->work); | ||
495 | } | ||
496 | break; | ||
497 | case POWEROFF_STATE: | ||
498 | if (event == INT_LINK_UP) { | ||
499 | ctrl_info(ctrl, | ||
500 | "Link Up event queued on slot(%s): currently getting powered off\n", | ||
501 | slot_name(p_slot)); | ||
502 | p_slot->state = POWERON_STATE; | ||
503 | queue_work(p_slot->wq, &info->work); | ||
504 | } else { | ||
505 | ctrl_info(ctrl, | ||
506 | "Link Down event ignored on slot(%s): already powering off\n", | ||
507 | slot_name(p_slot)); | ||
508 | kfree(info); | ||
509 | } | ||
510 | break; | ||
511 | default: | ||
512 | ctrl_err(ctrl, "Not a valid state on slot(%s)\n", | ||
513 | slot_name(p_slot)); | ||
514 | kfree(info); | ||
515 | break; | ||
516 | } | ||
517 | } | ||
518 | |||
418 | static void interrupt_event_handler(struct work_struct *work) | 519 | static void interrupt_event_handler(struct work_struct *work) |
419 | { | 520 | { |
420 | struct event_info *info = container_of(work, struct event_info, work); | 521 | struct event_info *info = container_of(work, struct event_info, work); |
@@ -433,12 +534,23 @@ static void interrupt_event_handler(struct work_struct *work) | |||
433 | pciehp_green_led_off(p_slot); | 534 | pciehp_green_led_off(p_slot); |
434 | break; | 535 | break; |
435 | case INT_PRESENCE_ON: | 536 | case INT_PRESENCE_ON: |
436 | case INT_PRESENCE_OFF: | ||
437 | if (!HP_SUPR_RM(ctrl)) | 537 | if (!HP_SUPR_RM(ctrl)) |
438 | break; | 538 | break; |
539 | ctrl_dbg(ctrl, "Surprise Insertion\n"); | ||
540 | handle_surprise_event(p_slot); | ||
541 | break; | ||
542 | case INT_PRESENCE_OFF: | ||
543 | /* | ||
544 | * Regardless of surprise capability, we need to | ||
545 | * definitely remove a card that has been pulled out! | ||
546 | */ | ||
439 | ctrl_dbg(ctrl, "Surprise Removal\n"); | 547 | ctrl_dbg(ctrl, "Surprise Removal\n"); |
440 | handle_surprise_event(p_slot); | 548 | handle_surprise_event(p_slot); |
441 | break; | 549 | break; |
550 | case INT_LINK_UP: | ||
551 | case INT_LINK_DOWN: | ||
552 | handle_link_event(p_slot, info->event_type); | ||
553 | break; | ||
442 | default: | 554 | default: |
443 | break; | 555 | break; |
444 | } | 556 | } |
@@ -447,6 +559,9 @@ static void interrupt_event_handler(struct work_struct *work) | |||
447 | kfree(info); | 559 | kfree(info); |
448 | } | 560 | } |
449 | 561 | ||
562 | /* | ||
563 | * Note: This function must be called with slot->hotplug_lock held | ||
564 | */ | ||
450 | int pciehp_enable_slot(struct slot *p_slot) | 565 | int pciehp_enable_slot(struct slot *p_slot) |
451 | { | 566 | { |
452 | u8 getstatus = 0; | 567 | u8 getstatus = 0; |
@@ -479,13 +594,15 @@ int pciehp_enable_slot(struct slot *p_slot) | |||
479 | pciehp_get_latch_status(p_slot, &getstatus); | 594 | pciehp_get_latch_status(p_slot, &getstatus); |
480 | 595 | ||
481 | rc = board_added(p_slot); | 596 | rc = board_added(p_slot); |
482 | if (rc) { | 597 | if (rc) |
483 | pciehp_get_latch_status(p_slot, &getstatus); | 598 | pciehp_get_latch_status(p_slot, &getstatus); |
484 | } | 599 | |
485 | return rc; | 600 | return rc; |
486 | } | 601 | } |
487 | 602 | ||
488 | 603 | /* | |
604 | * Note: This function must be called with slot->hotplug_lock held | ||
605 | */ | ||
489 | int pciehp_disable_slot(struct slot *p_slot) | 606 | int pciehp_disable_slot(struct slot *p_slot) |
490 | { | 607 | { |
491 | u8 getstatus = 0; | 608 | u8 getstatus = 0; |
@@ -494,24 +611,6 @@ int pciehp_disable_slot(struct slot *p_slot) | |||
494 | if (!p_slot->ctrl) | 611 | if (!p_slot->ctrl) |
495 | return 1; | 612 | return 1; |
496 | 613 | ||
497 | if (!HP_SUPR_RM(p_slot->ctrl)) { | ||
498 | pciehp_get_adapter_status(p_slot, &getstatus); | ||
499 | if (!getstatus) { | ||
500 | ctrl_info(ctrl, "No adapter on slot(%s)\n", | ||
501 | slot_name(p_slot)); | ||
502 | return -ENODEV; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | if (MRL_SENS(p_slot->ctrl)) { | ||
507 | pciehp_get_latch_status(p_slot, &getstatus); | ||
508 | if (getstatus) { | ||
509 | ctrl_info(ctrl, "Latch open on slot(%s)\n", | ||
510 | slot_name(p_slot)); | ||
511 | return -ENODEV; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | if (POWER_CTRL(p_slot->ctrl)) { | 614 | if (POWER_CTRL(p_slot->ctrl)) { |
516 | pciehp_get_power_status(p_slot, &getstatus); | 615 | pciehp_get_power_status(p_slot, &getstatus); |
517 | if (!getstatus) { | 616 | if (!getstatus) { |
@@ -536,7 +635,9 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot) | |||
536 | case STATIC_STATE: | 635 | case STATIC_STATE: |
537 | p_slot->state = POWERON_STATE; | 636 | p_slot->state = POWERON_STATE; |
538 | mutex_unlock(&p_slot->lock); | 637 | mutex_unlock(&p_slot->lock); |
638 | mutex_lock(&p_slot->hotplug_lock); | ||
539 | retval = pciehp_enable_slot(p_slot); | 639 | retval = pciehp_enable_slot(p_slot); |
640 | mutex_unlock(&p_slot->hotplug_lock); | ||
540 | mutex_lock(&p_slot->lock); | 641 | mutex_lock(&p_slot->lock); |
541 | p_slot->state = STATIC_STATE; | 642 | p_slot->state = STATIC_STATE; |
542 | break; | 643 | break; |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 14acfccb7670..d7d058fa19a4 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -206,7 +206,7 @@ static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) | |||
206 | mutex_unlock(&ctrl->ctrl_lock); | 206 | mutex_unlock(&ctrl->ctrl_lock); |
207 | } | 207 | } |
208 | 208 | ||
209 | static bool check_link_active(struct controller *ctrl) | 209 | bool pciehp_check_link_active(struct controller *ctrl) |
210 | { | 210 | { |
211 | struct pci_dev *pdev = ctrl_dev(ctrl); | 211 | struct pci_dev *pdev = ctrl_dev(ctrl); |
212 | u16 lnk_status; | 212 | u16 lnk_status; |
@@ -225,12 +225,12 @@ static void __pcie_wait_link_active(struct controller *ctrl, bool active) | |||
225 | { | 225 | { |
226 | int timeout = 1000; | 226 | int timeout = 1000; |
227 | 227 | ||
228 | if (check_link_active(ctrl) == active) | 228 | if (pciehp_check_link_active(ctrl) == active) |
229 | return; | 229 | return; |
230 | while (timeout > 0) { | 230 | while (timeout > 0) { |
231 | msleep(10); | 231 | msleep(10); |
232 | timeout -= 10; | 232 | timeout -= 10; |
233 | if (check_link_active(ctrl) == active) | 233 | if (pciehp_check_link_active(ctrl) == active) |
234 | return; | 234 | return; |
235 | } | 235 | } |
236 | ctrl_dbg(ctrl, "Data Link Layer Link Active not %s in 1000 msec\n", | 236 | ctrl_dbg(ctrl, "Data Link Layer Link Active not %s in 1000 msec\n", |
@@ -242,11 +242,6 @@ static void pcie_wait_link_active(struct controller *ctrl) | |||
242 | __pcie_wait_link_active(ctrl, true); | 242 | __pcie_wait_link_active(ctrl, true); |
243 | } | 243 | } |
244 | 244 | ||
245 | static void pcie_wait_link_not_active(struct controller *ctrl) | ||
246 | { | ||
247 | __pcie_wait_link_active(ctrl, false); | ||
248 | } | ||
249 | |||
250 | static bool pci_bus_check_dev(struct pci_bus *bus, int devfn) | 245 | static bool pci_bus_check_dev(struct pci_bus *bus, int devfn) |
251 | { | 246 | { |
252 | u32 l; | 247 | u32 l; |
@@ -332,11 +327,6 @@ static int pciehp_link_enable(struct controller *ctrl) | |||
332 | return __pciehp_link_set(ctrl, true); | 327 | return __pciehp_link_set(ctrl, true); |
333 | } | 328 | } |
334 | 329 | ||
335 | static int pciehp_link_disable(struct controller *ctrl) | ||
336 | { | ||
337 | return __pciehp_link_set(ctrl, false); | ||
338 | } | ||
339 | |||
340 | void pciehp_get_attention_status(struct slot *slot, u8 *status) | 330 | void pciehp_get_attention_status(struct slot *slot, u8 *status) |
341 | { | 331 | { |
342 | struct controller *ctrl = slot->ctrl; | 332 | struct controller *ctrl = slot->ctrl; |
@@ -508,14 +498,6 @@ void pciehp_power_off_slot(struct slot * slot) | |||
508 | { | 498 | { |
509 | struct controller *ctrl = slot->ctrl; | 499 | struct controller *ctrl = slot->ctrl; |
510 | 500 | ||
511 | /* Disable the link at first */ | ||
512 | pciehp_link_disable(ctrl); | ||
513 | /* wait the link is down */ | ||
514 | if (ctrl->link_active_reporting) | ||
515 | pcie_wait_link_not_active(ctrl); | ||
516 | else | ||
517 | msleep(1000); | ||
518 | |||
519 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC); | 501 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC); |
520 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, | 502 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, |
521 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, | 503 | pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, |
@@ -540,7 +522,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
540 | 522 | ||
541 | detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | | 523 | detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | |
542 | PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | | 524 | PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | |
543 | PCI_EXP_SLTSTA_CC); | 525 | PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC); |
544 | detected &= ~intr_loc; | 526 | detected &= ~intr_loc; |
545 | intr_loc |= detected; | 527 | intr_loc |= detected; |
546 | if (!intr_loc) | 528 | if (!intr_loc) |
@@ -579,6 +561,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
579 | ctrl->power_fault_detected = 1; | 561 | ctrl->power_fault_detected = 1; |
580 | pciehp_handle_power_fault(slot); | 562 | pciehp_handle_power_fault(slot); |
581 | } | 563 | } |
564 | |||
565 | if (intr_loc & PCI_EXP_SLTSTA_DLLSC) | ||
566 | pciehp_handle_linkstate_change(slot); | ||
567 | |||
582 | return IRQ_HANDLED; | 568 | return IRQ_HANDLED; |
583 | } | 569 | } |
584 | 570 | ||
@@ -596,9 +582,17 @@ void pcie_enable_notification(struct controller *ctrl) | |||
596 | * when it is cleared in the interrupt service routine, and | 582 | * when it is cleared in the interrupt service routine, and |
597 | * next power fault detected interrupt was notified again. | 583 | * next power fault detected interrupt was notified again. |
598 | */ | 584 | */ |
599 | cmd = PCI_EXP_SLTCTL_PDCE; | 585 | |
586 | /* | ||
587 | * Always enable link events: thus link-up and link-down shall | ||
588 | * always be treated as hotplug and unplug respectively. Enable | ||
589 | * presence detect only if Attention Button is not present. | ||
590 | */ | ||
591 | cmd = PCI_EXP_SLTCTL_DLLSCE; | ||
600 | if (ATTN_BUTTN(ctrl)) | 592 | if (ATTN_BUTTN(ctrl)) |
601 | cmd |= PCI_EXP_SLTCTL_ABPE; | 593 | cmd |= PCI_EXP_SLTCTL_ABPE; |
594 | else | ||
595 | cmd |= PCI_EXP_SLTCTL_PDCE; | ||
602 | if (MRL_SENS(ctrl)) | 596 | if (MRL_SENS(ctrl)) |
603 | cmd |= PCI_EXP_SLTCTL_MRLSCE; | 597 | cmd |= PCI_EXP_SLTCTL_MRLSCE; |
604 | if (!pciehp_poll_mode) | 598 | if (!pciehp_poll_mode) |
@@ -606,7 +600,8 @@ void pcie_enable_notification(struct controller *ctrl) | |||
606 | 600 | ||
607 | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | | 601 | mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE | |
608 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | | 602 | PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | |
609 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE); | 603 | PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | |
604 | PCI_EXP_SLTCTL_DLLSCE); | ||
610 | 605 | ||
611 | pcie_write_cmd(ctrl, cmd, mask); | 606 | pcie_write_cmd(ctrl, cmd, mask); |
612 | } | 607 | } |
@@ -624,33 +619,38 @@ static void pcie_disable_notification(struct controller *ctrl) | |||
624 | 619 | ||
625 | /* | 620 | /* |
626 | * pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary | 621 | * pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary |
627 | * bus reset of the bridge, but if the slot supports surprise removal we need | 622 | * bus reset of the bridge, but at the same time we want to ensure that it is |
628 | * to disable presence detection around the bus reset and clear any spurious | 623 | * not seen as a hot-unplug, followed by the hot-plug of the device. Thus, |
624 | * disable link state notification and presence detection change notification | ||
625 | * momentarily, if we see that they could interfere. Also, clear any spurious | ||
629 | * events after. | 626 | * events after. |
630 | */ | 627 | */ |
631 | int pciehp_reset_slot(struct slot *slot, int probe) | 628 | int pciehp_reset_slot(struct slot *slot, int probe) |
632 | { | 629 | { |
633 | struct controller *ctrl = slot->ctrl; | 630 | struct controller *ctrl = slot->ctrl; |
634 | struct pci_dev *pdev = ctrl_dev(ctrl); | 631 | struct pci_dev *pdev = ctrl_dev(ctrl); |
632 | u16 stat_mask = 0, ctrl_mask = 0; | ||
635 | 633 | ||
636 | if (probe) | 634 | if (probe) |
637 | return 0; | 635 | return 0; |
638 | 636 | ||
639 | if (HP_SUPR_RM(ctrl)) { | 637 | if (!ATTN_BUTTN(ctrl)) { |
640 | pcie_write_cmd(ctrl, 0, PCI_EXP_SLTCTL_PDCE); | 638 | ctrl_mask |= PCI_EXP_SLTCTL_PDCE; |
641 | if (pciehp_poll_mode) | 639 | stat_mask |= PCI_EXP_SLTSTA_PDC; |
642 | del_timer_sync(&ctrl->poll_timer); | ||
643 | } | 640 | } |
641 | ctrl_mask |= PCI_EXP_SLTCTL_DLLSCE; | ||
642 | stat_mask |= PCI_EXP_SLTSTA_DLLSC; | ||
643 | |||
644 | pcie_write_cmd(ctrl, 0, ctrl_mask); | ||
645 | if (pciehp_poll_mode) | ||
646 | del_timer_sync(&ctrl->poll_timer); | ||
644 | 647 | ||
645 | pci_reset_bridge_secondary_bus(ctrl->pcie->port); | 648 | pci_reset_bridge_secondary_bus(ctrl->pcie->port); |
646 | 649 | ||
647 | if (HP_SUPR_RM(ctrl)) { | 650 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, stat_mask); |
648 | pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, | 651 | pcie_write_cmd(ctrl, ctrl_mask, ctrl_mask); |
649 | PCI_EXP_SLTSTA_PDC); | 652 | if (pciehp_poll_mode) |
650 | pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE); | 653 | int_poll_timeout(ctrl->poll_timer.data); |
651 | if (pciehp_poll_mode) | ||
652 | int_poll_timeout(ctrl->poll_timer.data); | ||
653 | } | ||
654 | 654 | ||
655 | return 0; | 655 | return 0; |
656 | } | 656 | } |
@@ -687,6 +687,7 @@ static int pcie_init_slot(struct controller *ctrl) | |||
687 | 687 | ||
688 | slot->ctrl = ctrl; | 688 | slot->ctrl = ctrl; |
689 | mutex_init(&slot->lock); | 689 | mutex_init(&slot->lock); |
690 | mutex_init(&slot->hotplug_lock); | ||
690 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); | 691 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); |
691 | ctrl->slot = slot; | 692 | ctrl->slot = slot; |
692 | return 0; | 693 | return 0; |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index b07d7cc2d697..1b533060ce65 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
@@ -50,7 +50,7 @@ int pciehp_configure_device(struct slot *p_slot) | |||
50 | "at %04x:%02x:00, cannot hot-add\n", pci_name(dev), | 50 | "at %04x:%02x:00, cannot hot-add\n", pci_name(dev), |
51 | pci_domain_nr(parent), parent->number); | 51 | pci_domain_nr(parent), parent->number); |
52 | pci_dev_put(dev); | 52 | pci_dev_put(dev); |
53 | ret = -EINVAL; | 53 | ret = -EEXIST; |
54 | goto out; | 54 | goto out; |
55 | } | 55 | } |
56 | 56 | ||