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/pciehp_ctrl.c | |
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/pciehp_ctrl.c')
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 173 |
1 files changed, 137 insertions, 36 deletions
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; |