aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c91
1 files changed, 62 insertions, 29 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 21a6269501e1..e2e5e3088816 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -46,6 +46,7 @@
46#include <linux/pci.h> 46#include <linux/pci.h>
47#include <linux/pci_hotplug.h> 47#include <linux/pci_hotplug.h>
48#include <linux/pci-acpi.h> 48#include <linux/pci-acpi.h>
49#include <linux/pm_runtime.h>
49#include <linux/mutex.h> 50#include <linux/mutex.h>
50#include <linux/slab.h> 51#include <linux/slab.h>
51#include <linux/acpi.h> 52#include <linux/acpi.h>
@@ -687,47 +688,75 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
687} 688}
688 689
689/** 690/**
691 * trim_stale_devices - remove PCI devices that are not responding.
692 * @dev: PCI device to start walking the hierarchy from.
693 */
694static void trim_stale_devices(struct pci_dev *dev)
695{
696 acpi_handle handle = ACPI_HANDLE(&dev->dev);
697 struct pci_bus *bus = dev->subordinate;
698 bool alive = false;
699
700 if (handle) {
701 acpi_status status;
702 unsigned long long sta;
703
704 status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
705 alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL;
706 }
707 if (!alive) {
708 u32 v;
709
710 /* Check if the device responds. */
711 alive = pci_bus_read_dev_vendor_id(dev->bus, dev->devfn, &v, 0);
712 }
713 if (!alive) {
714 pci_stop_and_remove_bus_device(dev);
715 if (handle)
716 acpiphp_bus_trim(handle);
717 } else if (bus) {
718 struct pci_dev *child, *tmp;
719
720 /* The device is a bridge. so check the bus below it. */
721 pm_runtime_get_sync(&dev->dev);
722 list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
723 trim_stale_devices(child);
724
725 pm_runtime_put(&dev->dev);
726 }
727}
728
729/**
690 * acpiphp_check_bridge - re-enumerate devices 730 * acpiphp_check_bridge - re-enumerate devices
691 * @bridge: where to begin re-enumeration 731 * @bridge: where to begin re-enumeration
692 * 732 *
693 * Iterate over all slots under this bridge and make sure that if a 733 * Iterate over all slots under this bridge and make sure that if a
694 * card is present they are enabled, and if not they are disabled. 734 * card is present they are enabled, and if not they are disabled.
695 */ 735 */
696static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) 736static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
697{ 737{
698 struct acpiphp_slot *slot; 738 struct acpiphp_slot *slot;
699 int retval = 0;
700 int enabled, disabled;
701
702 enabled = disabled = 0;
703 739
704 list_for_each_entry(slot, &bridge->slots, node) { 740 list_for_each_entry(slot, &bridge->slots, node) {
705 unsigned int status = get_slot_status(slot); 741 struct pci_bus *bus = slot->bus;
706 if (slot->flags & SLOT_ENABLED) { 742 struct pci_dev *dev, *tmp;
707 if (status == ACPI_STA_ALL) 743
708 continue; 744 mutex_lock(&slot->crit_sect);
709 745 /* wake up all functions */
710 retval = acpiphp_disable_and_eject_slot(slot); 746 if (get_slot_status(slot) == ACPI_STA_ALL) {
711 if (retval) 747 /* remove stale devices if any */
712 goto err_exit; 748 list_for_each_entry_safe(dev, tmp, &bus->devices,
713 749 bus_list)
714 disabled++; 750 if (PCI_SLOT(dev->devfn) == slot->device)
751 trim_stale_devices(dev);
752
753 /* configure all functions */
754 enable_device(slot);
715 } else { 755 } else {
716 if (status != ACPI_STA_ALL) 756 disable_device(slot);
717 continue;
718 retval = acpiphp_enable_slot(slot);
719 if (retval) {
720 err("Error occurred in enabling\n");
721 goto err_exit;
722 }
723 enabled++;
724 } 757 }
758 mutex_unlock(&slot->crit_sect);
725 } 759 }
726
727 dbg("%s: %d enabled, %d disabled\n", __func__, enabled, disabled);
728
729 err_exit:
730 return retval;
731} 760}
732 761
733static void acpiphp_set_hpp_values(struct pci_bus *bus) 762static void acpiphp_set_hpp_values(struct pci_bus *bus)
@@ -828,7 +857,11 @@ static void hotplug_event(acpi_handle handle, u32 type, void *data)
828 ACPI_UINT32_MAX, check_sub_bridges, 857 ACPI_UINT32_MAX, check_sub_bridges,
829 NULL, NULL, NULL); 858 NULL, NULL, NULL);
830 } else { 859 } else {
831 acpiphp_enable_slot(func->slot); 860 struct acpiphp_slot *slot = func->slot;
861
862 mutex_lock(&slot->crit_sect);
863 enable_device(slot);
864 mutex_unlock(&slot->crit_sect);
832 } 865 }
833 break; 866 break;
834 867