aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c42
-rw-r--r--drivers/pci/search.c2
2 files changed, 34 insertions, 10 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index c8f999102765..73af3374e915 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -878,6 +878,24 @@ static void disable_bridges(struct pci_bus *bus)
878 } 878 }
879} 879}
880 880
881/* return first device in slot, acquiring a reference on it */
882static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
883{
884 struct pci_bus *bus = slot->bridge->pci_bus;
885 struct pci_dev *dev;
886 struct pci_dev *ret = NULL;
887
888 down_read(&pci_bus_sem);
889 list_for_each_entry(dev, &bus->devices, bus_list)
890 if (PCI_SLOT(dev->devfn) == slot->device) {
891 ret = pci_dev_get(dev);
892 break;
893 }
894 up_read(&pci_bus_sem);
895
896 return ret;
897}
898
881/** 899/**
882 * disable_device - disable a slot 900 * disable_device - disable a slot
883 * @slot: ACPI PHP slot 901 * @slot: ACPI PHP slot
@@ -902,18 +920,22 @@ static int disable_device(struct acpiphp_slot *slot)
902 (u32)1, NULL, NULL); 920 (u32)1, NULL, NULL);
903 func->bridge = NULL; 921 func->bridge = NULL;
904 } 922 }
923 }
905 924
906 pdev = pci_get_slot(slot->bridge->pci_bus, 925 /*
907 PCI_DEVFN(slot->device, func->function)); 926 * enable_device() enumerates all functions in this device via
908 if (pdev) { 927 * pci_scan_slot(), whether they have associated ACPI hotplug
909 pci_stop_bus_device(pdev); 928 * methods (_EJ0, etc.) or not. Therefore, we remove all functions
910 if (pdev->subordinate) { 929 * here.
911 disable_bridges(pdev->subordinate); 930 */
912 pci_disable_device(pdev); 931 while ((pdev = dev_in_slot(slot))) {
913 } 932 pci_stop_bus_device(pdev);
914 __pci_remove_bus_device(pdev); 933 if (pdev->subordinate) {
915 pci_dev_put(pdev); 934 disable_bridges(pdev->subordinate);
935 pci_disable_device(pdev);
916 } 936 }
937 __pci_remove_bus_device(pdev);
938 pci_dev_put(pdev);
917 } 939 }
918 940
919 list_for_each_entry(func, &slot->funcs, sibling) { 941 list_for_each_entry(func, &slot->funcs, sibling) {
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 9d75dc8ca602..993d4a0a2469 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -15,6 +15,8 @@
15#include "pci.h" 15#include "pci.h"
16 16
17DECLARE_RWSEM(pci_bus_sem); 17DECLARE_RWSEM(pci_bus_sem);
18EXPORT_SYMBOL_GPL(pci_bus_sem);
19
18/* 20/*
19 * find the upstream PCIe-to-PCI bridge of a PCI device 21 * find the upstream PCIe-to-PCI bridge of a PCI device
20 * if the device is PCIE, return NULL 22 * if the device is PCIE, return NULL