aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/acpiphp_glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c67
1 files changed, 46 insertions, 21 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 806c44fa645..ad6fd669549 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -100,11 +100,11 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
100 PCI_PRIMARY_BUS, 100 PCI_PRIMARY_BUS,
101 &buses); 101 &buses);
102 102
103 if (((buses >> 8) & 0xff) != bus->secondary) { 103 if (((buses >> 8) & 0xff) != bus->busn_res.start) {
104 buses = (buses & 0xff000000) 104 buses = (buses & 0xff000000)
105 | ((unsigned int)(bus->primary) << 0) 105 | ((unsigned int)(bus->primary) << 0)
106 | ((unsigned int)(bus->secondary) << 8) 106 | ((unsigned int)(bus->busn_res.start) << 8)
107 | ((unsigned int)(bus->subordinate) << 16); 107 | ((unsigned int)(bus->busn_res.end) << 16);
108 pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); 108 pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
109 } 109 }
110 return NOTIFY_OK; 110 return NOTIFY_OK;
@@ -132,6 +132,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
132 if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) 132 if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
133 return AE_OK; 133 return AE_OK;
134 134
135 status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
136 if (ACPI_FAILURE(status)) {
137 warn("can't evaluate _ADR (%#x)\n", status);
138 return AE_OK;
139 }
140
141 device = (adr >> 16) & 0xffff;
142 function = adr & 0xffff;
143
135 pdev = pbus->self; 144 pdev = pbus->self;
136 if (pdev && pci_is_pcie(pdev)) { 145 if (pdev && pci_is_pcie(pdev)) {
137 tmp = acpi_find_root_bridge_handle(pdev); 146 tmp = acpi_find_root_bridge_handle(pdev);
@@ -144,10 +153,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
144 } 153 }
145 } 154 }
146 155
147 acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
148 device = (adr >> 16) & 0xffff;
149 function = adr & 0xffff;
150
151 newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); 156 newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
152 if (!newfunc) 157 if (!newfunc)
153 return AE_NO_MEMORY; 158 return AE_NO_MEMORY;
@@ -391,8 +396,6 @@ static void add_host_bridge(acpi_handle *handle)
391 396
392 bridge->pci_bus = root->bus; 397 bridge->pci_bus = root->bus;
393 398
394 spin_lock_init(&bridge->res_lock);
395
396 init_bridge_misc(bridge); 399 init_bridge_misc(bridge);
397} 400}
398 401
@@ -425,7 +428,6 @@ static void add_p2p_bridge(acpi_handle *handle)
425 * (which we access during module unload). 428 * (which we access during module unload).
426 */ 429 */
427 get_device(&bridge->pci_bus->dev); 430 get_device(&bridge->pci_bus->dev);
428 spin_lock_init(&bridge->res_lock);
429 431
430 init_bridge_misc(bridge); 432 init_bridge_misc(bridge);
431 return; 433 return;
@@ -692,7 +694,7 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
692 * bus->subordinate value because it could have 694 * bus->subordinate value because it could have
693 * padding in it. 695 * padding in it.
694 */ 696 */
695 max = bus->secondary; 697 max = bus->busn_res.start;
696 698
697 list_for_each(tmp, &bus->children) { 699 list_for_each(tmp, &bus->children) {
698 n = pci_bus_max_busnr(pci_bus_b(tmp)); 700 n = pci_bus_max_busnr(pci_bus_b(tmp));
@@ -878,6 +880,24 @@ static void disable_bridges(struct pci_bus *bus)
878 } 880 }
879} 881}
880 882
883/* return first device in slot, acquiring a reference on it */
884static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
885{
886 struct pci_bus *bus = slot->bridge->pci_bus;
887 struct pci_dev *dev;
888 struct pci_dev *ret = NULL;
889
890 down_read(&pci_bus_sem);
891 list_for_each_entry(dev, &bus->devices, bus_list)
892 if (PCI_SLOT(dev->devfn) == slot->device) {
893 ret = pci_dev_get(dev);
894 break;
895 }
896 up_read(&pci_bus_sem);
897
898 return ret;
899}
900
881/** 901/**
882 * disable_device - disable a slot 902 * disable_device - disable a slot
883 * @slot: ACPI PHP slot 903 * @slot: ACPI PHP slot
@@ -893,6 +913,7 @@ static int disable_device(struct acpiphp_slot *slot)
893 pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0)); 913 pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
894 if (!pdev) 914 if (!pdev)
895 goto err_exit; 915 goto err_exit;
916 pci_dev_put(pdev);
896 917
897 list_for_each_entry(func, &slot->funcs, sibling) { 918 list_for_each_entry(func, &slot->funcs, sibling) {
898 if (func->bridge) { 919 if (func->bridge) {
@@ -901,18 +922,22 @@ static int disable_device(struct acpiphp_slot *slot)
901 (u32)1, NULL, NULL); 922 (u32)1, NULL, NULL);
902 func->bridge = NULL; 923 func->bridge = NULL;
903 } 924 }
925 }
904 926
905 pdev = pci_get_slot(slot->bridge->pci_bus, 927 /*
906 PCI_DEVFN(slot->device, func->function)); 928 * enable_device() enumerates all functions in this device via
907 if (pdev) { 929 * pci_scan_slot(), whether they have associated ACPI hotplug
908 pci_stop_bus_device(pdev); 930 * methods (_EJ0, etc.) or not. Therefore, we remove all functions
909 if (pdev->subordinate) { 931 * here.
910 disable_bridges(pdev->subordinate); 932 */
911 pci_disable_device(pdev); 933 while ((pdev = dev_in_slot(slot))) {
912 } 934 pci_stop_bus_device(pdev);
913 __pci_remove_bus_device(pdev); 935 if (pdev->subordinate) {
914 pci_dev_put(pdev); 936 disable_bridges(pdev->subordinate);
937 pci_disable_device(pdev);
915 } 938 }
939 __pci_remove_bus_device(pdev);
940 pci_dev_put(pdev);
916 } 941 }
917 942
918 list_for_each_entry(func, &slot->funcs, sibling) { 943 list_for_each_entry(func, &slot->funcs, sibling) {