diff options
-rw-r--r-- | arch/ia64/pci/pci.c | 11 | ||||
-rw-r--r-- | arch/x86/pci/common.c | 11 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 48 | ||||
-rw-r--r-- | drivers/acpi/pci_slot.c | 170 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 1 | ||||
-rw-r--r-- | drivers/pci/bus.c | 11 | ||||
-rw-r--r-- | drivers/pci/hotplug/Kconfig | 7 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 13 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_core.c | 30 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 415 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 30 | ||||
-rw-r--r-- | drivers/pci/probe.c | 15 | ||||
-rw-r--r-- | drivers/pci/remove.c | 4 | ||||
-rw-r--r-- | include/linux/acpi.h | 9 | ||||
-rw-r--r-- | include/linux/pci-acpi.h | 29 | ||||
-rw-r--r-- | include/linux/pci.h | 2 |
16 files changed, 281 insertions, 525 deletions
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 60532ab27346..de1474ff0bc5 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
18 | #include <linux/pci-acpi.h> | ||
18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
19 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
@@ -458,6 +459,16 @@ void pcibios_fixup_bus(struct pci_bus *b) | |||
458 | platform_pci_fixup_bus(b); | 459 | platform_pci_fixup_bus(b); |
459 | } | 460 | } |
460 | 461 | ||
462 | void pcibios_add_bus(struct pci_bus *bus) | ||
463 | { | ||
464 | acpi_pci_add_bus(bus); | ||
465 | } | ||
466 | |||
467 | void pcibios_remove_bus(struct pci_bus *bus) | ||
468 | { | ||
469 | acpi_pci_remove_bus(bus); | ||
470 | } | ||
471 | |||
461 | void pcibios_set_master (struct pci_dev *dev) | 472 | void pcibios_set_master (struct pci_dev *dev) |
462 | { | 473 | { |
463 | /* No special bus mastering setup handling */ | 474 | /* No special bus mastering setup handling */ |
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 901177d75ff5..305c68b8d538 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c | |||
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/pci.h> | 8 | #include <linux/pci.h> |
9 | #include <linux/pci-acpi.h> | ||
9 | #include <linux/ioport.h> | 10 | #include <linux/ioport.h> |
10 | #include <linux/init.h> | 11 | #include <linux/init.h> |
11 | #include <linux/dmi.h> | 12 | #include <linux/dmi.h> |
@@ -170,6 +171,16 @@ void pcibios_fixup_bus(struct pci_bus *b) | |||
170 | pcibios_fixup_device_resources(dev); | 171 | pcibios_fixup_device_resources(dev); |
171 | } | 172 | } |
172 | 173 | ||
174 | void pcibios_add_bus(struct pci_bus *bus) | ||
175 | { | ||
176 | acpi_pci_add_bus(bus); | ||
177 | } | ||
178 | |||
179 | void pcibios_remove_bus(struct pci_bus *bus) | ||
180 | { | ||
181 | acpi_pci_remove_bus(bus); | ||
182 | } | ||
183 | |||
173 | /* | 184 | /* |
174 | * Only use DMI information to set this if nothing was passed | 185 | * Only use DMI information to set this if nothing was passed |
175 | * on the kernel command line (which was parsed earlier). | 186 | * on the kernel command line (which was parsed earlier). |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 0ac546d5e53f..b80e06e0b2d9 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -65,44 +65,12 @@ static struct acpi_scan_handler pci_root_handler = { | |||
65 | .detach = acpi_pci_root_remove, | 65 | .detach = acpi_pci_root_remove, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ | 68 | /* Lock to protect both acpi_pci_roots lists */ |
69 | static DEFINE_MUTEX(acpi_pci_root_lock); | 69 | static DEFINE_MUTEX(acpi_pci_root_lock); |
70 | static LIST_HEAD(acpi_pci_roots); | 70 | static LIST_HEAD(acpi_pci_roots); |
71 | static LIST_HEAD(acpi_pci_drivers); | ||
72 | 71 | ||
73 | static DEFINE_MUTEX(osc_lock); | 72 | static DEFINE_MUTEX(osc_lock); |
74 | 73 | ||
75 | int acpi_pci_register_driver(struct acpi_pci_driver *driver) | ||
76 | { | ||
77 | int n = 0; | ||
78 | struct acpi_pci_root *root; | ||
79 | |||
80 | mutex_lock(&acpi_pci_root_lock); | ||
81 | list_add_tail(&driver->node, &acpi_pci_drivers); | ||
82 | if (driver->add) | ||
83 | list_for_each_entry(root, &acpi_pci_roots, node) { | ||
84 | driver->add(root); | ||
85 | n++; | ||
86 | } | ||
87 | mutex_unlock(&acpi_pci_root_lock); | ||
88 | |||
89 | return n; | ||
90 | } | ||
91 | EXPORT_SYMBOL(acpi_pci_register_driver); | ||
92 | |||
93 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) | ||
94 | { | ||
95 | struct acpi_pci_root *root; | ||
96 | |||
97 | mutex_lock(&acpi_pci_root_lock); | ||
98 | list_del(&driver->node); | ||
99 | if (driver->remove) | ||
100 | list_for_each_entry(root, &acpi_pci_roots, node) | ||
101 | driver->remove(root); | ||
102 | mutex_unlock(&acpi_pci_root_lock); | ||
103 | } | ||
104 | EXPORT_SYMBOL(acpi_pci_unregister_driver); | ||
105 | |||
106 | /** | 74 | /** |
107 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge | 75 | * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge |
108 | * @handle - the ACPI CA node in question. | 76 | * @handle - the ACPI CA node in question. |
@@ -413,7 +381,6 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
413 | acpi_status status; | 381 | acpi_status status; |
414 | int result; | 382 | int result; |
415 | struct acpi_pci_root *root; | 383 | struct acpi_pci_root *root; |
416 | struct acpi_pci_driver *driver; | ||
417 | u32 flags, base_flags; | 384 | u32 flags, base_flags; |
418 | bool is_osc_granted = false; | 385 | bool is_osc_granted = false; |
419 | 386 | ||
@@ -573,12 +540,6 @@ static int acpi_pci_root_add(struct acpi_device *device, | |||
573 | pci_assign_unassigned_bus_resources(root->bus); | 540 | pci_assign_unassigned_bus_resources(root->bus); |
574 | } | 541 | } |
575 | 542 | ||
576 | mutex_lock(&acpi_pci_root_lock); | ||
577 | list_for_each_entry(driver, &acpi_pci_drivers, node) | ||
578 | if (driver->add) | ||
579 | driver->add(root); | ||
580 | mutex_unlock(&acpi_pci_root_lock); | ||
581 | |||
582 | /* need to after hot-added ioapic is registered */ | 543 | /* need to after hot-added ioapic is registered */ |
583 | if (system_state != SYSTEM_BOOTING) | 544 | if (system_state != SYSTEM_BOOTING) |
584 | pci_enable_bridges(root->bus); | 545 | pci_enable_bridges(root->bus); |
@@ -599,16 +560,9 @@ end: | |||
599 | static void acpi_pci_root_remove(struct acpi_device *device) | 560 | static void acpi_pci_root_remove(struct acpi_device *device) |
600 | { | 561 | { |
601 | struct acpi_pci_root *root = acpi_driver_data(device); | 562 | struct acpi_pci_root *root = acpi_driver_data(device); |
602 | struct acpi_pci_driver *driver; | ||
603 | 563 | ||
604 | pci_stop_root_bus(root->bus); | 564 | pci_stop_root_bus(root->bus); |
605 | 565 | ||
606 | mutex_lock(&acpi_pci_root_lock); | ||
607 | list_for_each_entry_reverse(driver, &acpi_pci_drivers, node) | ||
608 | if (driver->remove) | ||
609 | driver->remove(root); | ||
610 | mutex_unlock(&acpi_pci_root_lock); | ||
611 | |||
612 | device_set_run_wake(root->bus->bridge, false); | 566 | device_set_run_wake(root->bus->bridge, false); |
613 | pci_acpi_remove_bus_pm_notifier(device); | 567 | pci_acpi_remove_bus_pm_notifier(device); |
614 | 568 | ||
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index cd1434eb1de8..033d1179bdb5 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c | |||
@@ -9,6 +9,9 @@ | |||
9 | * Copyright (C) 2007-2008 Hewlett-Packard Development Company, L.P. | 9 | * Copyright (C) 2007-2008 Hewlett-Packard Development Company, L.P. |
10 | * Alex Chiang <achiang@hp.com> | 10 | * Alex Chiang <achiang@hp.com> |
11 | * | 11 | * |
12 | * Copyright (C) 2013 Huawei Tech. Co., Ltd. | ||
13 | * Jiang Liu <jiang.liu@huawei.com> | ||
14 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | 15 | * This program is free software; you can redistribute it and/or modify it |
13 | * under the terms and conditions of the GNU General Public License, | 16 | * under the terms and conditions of the GNU General Public License, |
14 | * version 2, as published by the Free Software Foundation. | 17 | * version 2, as published by the Free Software Foundation. |
@@ -28,10 +31,9 @@ | |||
28 | #include <linux/init.h> | 31 | #include <linux/init.h> |
29 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
30 | #include <linux/types.h> | 33 | #include <linux/types.h> |
34 | #include <linux/list.h> | ||
31 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
32 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
33 | #include <acpi/acpi_bus.h> | ||
34 | #include <acpi/acpi_drivers.h> | ||
35 | #include <linux/dmi.h> | 37 | #include <linux/dmi.h> |
36 | 38 | ||
37 | static bool debug; | 39 | static bool debug; |
@@ -61,20 +63,12 @@ ACPI_MODULE_NAME("pci_slot"); | |||
61 | #define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ | 63 | #define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ |
62 | 64 | ||
63 | struct acpi_pci_slot { | 65 | struct acpi_pci_slot { |
64 | acpi_handle root_handle; /* handle of the root bridge */ | ||
65 | struct pci_slot *pci_slot; /* corresponding pci_slot */ | 66 | struct pci_slot *pci_slot; /* corresponding pci_slot */ |
66 | struct list_head list; /* node in the list of slots */ | 67 | struct list_head list; /* node in the list of slots */ |
67 | }; | 68 | }; |
68 | 69 | ||
69 | static int acpi_pci_slot_add(struct acpi_pci_root *root); | ||
70 | static void acpi_pci_slot_remove(struct acpi_pci_root *root); | ||
71 | |||
72 | static LIST_HEAD(slot_list); | 70 | static LIST_HEAD(slot_list); |
73 | static DEFINE_MUTEX(slot_list_lock); | 71 | static DEFINE_MUTEX(slot_list_lock); |
74 | static struct acpi_pci_driver acpi_pci_slot_driver = { | ||
75 | .add = acpi_pci_slot_add, | ||
76 | .remove = acpi_pci_slot_remove, | ||
77 | }; | ||
78 | 72 | ||
79 | static int | 73 | static int |
80 | check_slot(acpi_handle handle, unsigned long long *sun) | 74 | check_slot(acpi_handle handle, unsigned long long *sun) |
@@ -113,21 +107,8 @@ out: | |||
113 | return device; | 107 | return device; |
114 | } | 108 | } |
115 | 109 | ||
116 | struct callback_args { | ||
117 | acpi_walk_callback user_function; /* only for walk_p2p_bridge */ | ||
118 | struct pci_bus *pci_bus; | ||
119 | acpi_handle root_handle; | ||
120 | }; | ||
121 | |||
122 | /* | 110 | /* |
123 | * register_slot | 111 | * Check whether handle has an associated slot and create PCI slot if it has. |
124 | * | ||
125 | * Called once for each SxFy object in the namespace. Don't worry about | ||
126 | * calling pci_create_slot multiple times for the same pci_bus:device, | ||
127 | * since each subsequent call simply bumps the refcount on the pci_slot. | ||
128 | * | ||
129 | * The number of calls to pci_destroy_slot from unregister_slot is | ||
130 | * symmetrical. | ||
131 | */ | 112 | */ |
132 | static acpi_status | 113 | static acpi_status |
133 | register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | 114 | register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) |
@@ -137,13 +118,22 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
137 | char name[SLOT_NAME_SIZE]; | 118 | char name[SLOT_NAME_SIZE]; |
138 | struct acpi_pci_slot *slot; | 119 | struct acpi_pci_slot *slot; |
139 | struct pci_slot *pci_slot; | 120 | struct pci_slot *pci_slot; |
140 | struct callback_args *parent_context = context; | 121 | struct pci_bus *pci_bus = context; |
141 | struct pci_bus *pci_bus = parent_context->pci_bus; | ||
142 | 122 | ||
143 | device = check_slot(handle, &sun); | 123 | device = check_slot(handle, &sun); |
144 | if (device < 0) | 124 | if (device < 0) |
145 | return AE_OK; | 125 | return AE_OK; |
146 | 126 | ||
127 | /* | ||
128 | * There may be multiple PCI functions associated with the same slot. | ||
129 | * Check whether PCI slot has already been created for this PCI device. | ||
130 | */ | ||
131 | list_for_each_entry(slot, &slot_list, list) { | ||
132 | pci_slot = slot->pci_slot; | ||
133 | if (pci_slot->bus == pci_bus && pci_slot->number == device) | ||
134 | return AE_OK; | ||
135 | } | ||
136 | |||
147 | slot = kmalloc(sizeof(*slot), GFP_KERNEL); | 137 | slot = kmalloc(sizeof(*slot), GFP_KERNEL); |
148 | if (!slot) { | 138 | if (!slot) { |
149 | err("%s: cannot allocate memory\n", __func__); | 139 | err("%s: cannot allocate memory\n", __func__); |
@@ -158,12 +148,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
158 | return AE_OK; | 148 | return AE_OK; |
159 | } | 149 | } |
160 | 150 | ||
161 | slot->root_handle = parent_context->root_handle; | ||
162 | slot->pci_slot = pci_slot; | 151 | slot->pci_slot = pci_slot; |
163 | INIT_LIST_HEAD(&slot->list); | ||
164 | mutex_lock(&slot_list_lock); | ||
165 | list_add(&slot->list, &slot_list); | 152 | list_add(&slot->list, &slot_list); |
166 | mutex_unlock(&slot_list_lock); | ||
167 | 153 | ||
168 | get_device(&pci_bus->dev); | 154 | get_device(&pci_bus->dev); |
169 | 155 | ||
@@ -173,131 +159,24 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
173 | return AE_OK; | 159 | return AE_OK; |
174 | } | 160 | } |
175 | 161 | ||
176 | /* | 162 | void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle) |
177 | * walk_p2p_bridge - discover and walk p2p bridges | ||
178 | * @handle: points to an acpi_pci_root | ||
179 | * @context: p2p_bridge_context pointer | ||
180 | * | ||
181 | * Note that when we call ourselves recursively, we pass a different | ||
182 | * value of pci_bus in the child_context. | ||
183 | */ | ||
184 | static acpi_status | ||
185 | walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
186 | { | ||
187 | int device, function; | ||
188 | unsigned long long adr; | ||
189 | acpi_status status; | ||
190 | acpi_handle dummy_handle; | ||
191 | acpi_walk_callback user_function; | ||
192 | |||
193 | struct pci_dev *dev; | ||
194 | struct pci_bus *pci_bus; | ||
195 | struct callback_args child_context; | ||
196 | struct callback_args *parent_context = context; | ||
197 | |||
198 | pci_bus = parent_context->pci_bus; | ||
199 | user_function = parent_context->user_function; | ||
200 | |||
201 | status = acpi_get_handle(handle, "_ADR", &dummy_handle); | ||
202 | if (ACPI_FAILURE(status)) | ||
203 | return AE_OK; | ||
204 | |||
205 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | ||
206 | if (ACPI_FAILURE(status)) | ||
207 | return AE_OK; | ||
208 | |||
209 | device = (adr >> 16) & 0xffff; | ||
210 | function = adr & 0xffff; | ||
211 | |||
212 | dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function)); | ||
213 | if (!dev || !dev->subordinate) | ||
214 | goto out; | ||
215 | |||
216 | child_context.pci_bus = dev->subordinate; | ||
217 | child_context.user_function = user_function; | ||
218 | child_context.root_handle = parent_context->root_handle; | ||
219 | |||
220 | dbg("p2p bridge walk, pci_bus = %x\n", dev->subordinate->number); | ||
221 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | ||
222 | user_function, NULL, &child_context, NULL); | ||
223 | if (ACPI_FAILURE(status)) | ||
224 | goto out; | ||
225 | |||
226 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | ||
227 | walk_p2p_bridge, NULL, &child_context, NULL); | ||
228 | out: | ||
229 | pci_dev_put(dev); | ||
230 | return AE_OK; | ||
231 | } | ||
232 | |||
233 | /* | ||
234 | * walk_root_bridge - generic root bridge walker | ||
235 | * @root: poiner of an acpi_pci_root | ||
236 | * @user_function: user callback for slot objects | ||
237 | * | ||
238 | * Call user_function for all objects underneath this root bridge. | ||
239 | * Walk p2p bridges underneath us and call user_function on those too. | ||
240 | */ | ||
241 | static int | ||
242 | walk_root_bridge(struct acpi_pci_root *root, acpi_walk_callback user_function) | ||
243 | { | ||
244 | acpi_status status; | ||
245 | acpi_handle handle = root->device->handle; | ||
246 | struct pci_bus *pci_bus = root->bus; | ||
247 | struct callback_args context; | ||
248 | |||
249 | context.pci_bus = pci_bus; | ||
250 | context.user_function = user_function; | ||
251 | context.root_handle = handle; | ||
252 | |||
253 | dbg("root bridge walk, pci_bus = %x\n", pci_bus->number); | ||
254 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | ||
255 | user_function, NULL, &context, NULL); | ||
256 | if (ACPI_FAILURE(status)) | ||
257 | return status; | ||
258 | |||
259 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | ||
260 | walk_p2p_bridge, NULL, &context, NULL); | ||
261 | if (ACPI_FAILURE(status)) | ||
262 | err("%s: walk_p2p_bridge failure - %d\n", __func__, status); | ||
263 | |||
264 | return status; | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * acpi_pci_slot_add | ||
269 | * @handle: points to an acpi_pci_root | ||
270 | */ | ||
271 | static int | ||
272 | acpi_pci_slot_add(struct acpi_pci_root *root) | ||
273 | { | 163 | { |
274 | acpi_status status; | 164 | mutex_lock(&slot_list_lock); |
275 | 165 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | |
276 | status = walk_root_bridge(root, register_slot); | 166 | register_slot, NULL, bus, NULL); |
277 | if (ACPI_FAILURE(status)) | 167 | mutex_unlock(&slot_list_lock); |
278 | err("%s: register_slot failure - %d\n", __func__, status); | ||
279 | |||
280 | return status; | ||
281 | } | 168 | } |
282 | 169 | ||
283 | /* | 170 | void acpi_pci_slot_remove(struct pci_bus *bus) |
284 | * acpi_pci_slot_remove | ||
285 | * @handle: points to an acpi_pci_root | ||
286 | */ | ||
287 | static void | ||
288 | acpi_pci_slot_remove(struct acpi_pci_root *root) | ||
289 | { | 171 | { |
290 | struct acpi_pci_slot *slot, *tmp; | 172 | struct acpi_pci_slot *slot, *tmp; |
291 | struct pci_bus *pbus; | ||
292 | acpi_handle handle = root->device->handle; | ||
293 | 173 | ||
294 | mutex_lock(&slot_list_lock); | 174 | mutex_lock(&slot_list_lock); |
295 | list_for_each_entry_safe(slot, tmp, &slot_list, list) { | 175 | list_for_each_entry_safe(slot, tmp, &slot_list, list) { |
296 | if (slot->root_handle == handle) { | 176 | if (slot->pci_slot->bus == bus) { |
297 | list_del(&slot->list); | 177 | list_del(&slot->list); |
298 | pbus = slot->pci_slot->bus; | ||
299 | pci_destroy_slot(slot->pci_slot); | 178 | pci_destroy_slot(slot->pci_slot); |
300 | put_device(&pbus->dev); | 179 | put_device(&bus->dev); |
301 | kfree(slot); | 180 | kfree(slot); |
302 | } | 181 | } |
303 | } | 182 | } |
@@ -332,5 +211,4 @@ static struct dmi_system_id acpi_pci_slot_dmi_table[] __initdata = { | |||
332 | void __init acpi_pci_slot_init(void) | 211 | void __init acpi_pci_slot_init(void) |
333 | { | 212 | { |
334 | dmi_check_system(acpi_pci_slot_dmi_table); | 213 | dmi_check_system(acpi_pci_slot_dmi_table); |
335 | acpi_pci_register_driver(&acpi_pci_slot_driver); | ||
336 | } | 214 | } |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5e7e991717d7..f54d1985e594 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -1790,7 +1790,6 @@ int __init acpi_scan_init(void) | |||
1790 | acpi_platform_init(); | 1790 | acpi_platform_init(); |
1791 | acpi_csrt_init(); | 1791 | acpi_csrt_init(); |
1792 | acpi_container_init(); | 1792 | acpi_container_init(); |
1793 | acpi_pci_slot_init(); | ||
1794 | 1793 | ||
1795 | mutex_lock(&acpi_scan_lock); | 1794 | mutex_lock(&acpi_scan_lock); |
1796 | /* | 1795 | /* |
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 8647dc6f52d0..bdc1e8bf7e60 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
@@ -206,16 +206,9 @@ void pci_bus_add_devices(const struct pci_bus *bus) | |||
206 | 206 | ||
207 | list_for_each_entry(dev, &bus->devices, bus_list) { | 207 | list_for_each_entry(dev, &bus->devices, bus_list) { |
208 | BUG_ON(!dev->is_added); | 208 | BUG_ON(!dev->is_added); |
209 | |||
210 | child = dev->subordinate; | 209 | child = dev->subordinate; |
211 | 210 | if (child) | |
212 | if (!child) | 211 | pci_bus_add_devices(child); |
213 | continue; | ||
214 | pci_bus_add_devices(child); | ||
215 | |||
216 | if (child->is_added) | ||
217 | continue; | ||
218 | child->is_added = 1; | ||
219 | } | 212 | } |
220 | } | 213 | } |
221 | 214 | ||
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index 13e9e63a7266..9fcb87f353d4 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig | |||
@@ -52,15 +52,12 @@ config HOTPLUG_PCI_IBM | |||
52 | When in doubt, say N. | 52 | When in doubt, say N. |
53 | 53 | ||
54 | config HOTPLUG_PCI_ACPI | 54 | config HOTPLUG_PCI_ACPI |
55 | tristate "ACPI PCI Hotplug driver" | 55 | bool "ACPI PCI Hotplug driver" |
56 | depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK) | 56 | depends on HOTPLUG_PCI=y && ((!ACPI_DOCK && ACPI) || (ACPI_DOCK)) |
57 | help | 57 | help |
58 | Say Y here if you have a system that supports PCI Hotplug using | 58 | Say Y here if you have a system that supports PCI Hotplug using |
59 | ACPI. | 59 | ACPI. |
60 | 60 | ||
61 | To compile this driver as a module, choose M here: the | ||
62 | module will be called acpiphp. | ||
63 | |||
64 | When in doubt, say N. | 61 | When in doubt, say N. |
65 | 62 | ||
66 | config HOTPLUG_PCI_ACPI_IBM | 63 | config HOTPLUG_PCI_ACPI_IBM |
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index b70ac00a117e..6a319f42b30c 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -73,8 +73,9 @@ static inline const char *slot_name(struct slot *slot) | |||
73 | */ | 73 | */ |
74 | struct acpiphp_bridge { | 74 | struct acpiphp_bridge { |
75 | struct list_head list; | 75 | struct list_head list; |
76 | struct list_head slots; | ||
77 | struct kref ref; | ||
76 | acpi_handle handle; | 78 | acpi_handle handle; |
77 | struct acpiphp_slot *slots; | ||
78 | 79 | ||
79 | /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ | 80 | /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ |
80 | struct acpiphp_func *func; | 81 | struct acpiphp_func *func; |
@@ -97,7 +98,7 @@ struct acpiphp_bridge { | |||
97 | * PCI slot information for each *physical* PCI slot | 98 | * PCI slot information for each *physical* PCI slot |
98 | */ | 99 | */ |
99 | struct acpiphp_slot { | 100 | struct acpiphp_slot { |
100 | struct acpiphp_slot *next; | 101 | struct list_head node; |
101 | struct acpiphp_bridge *bridge; /* parent */ | 102 | struct acpiphp_bridge *bridge; /* parent */ |
102 | struct list_head funcs; /* one slot may have different | 103 | struct list_head funcs; /* one slot may have different |
103 | objects (i.e. for each function) */ | 104 | objects (i.e. for each function) */ |
@@ -119,7 +120,6 @@ struct acpiphp_slot { | |||
119 | */ | 120 | */ |
120 | struct acpiphp_func { | 121 | struct acpiphp_func { |
121 | struct acpiphp_slot *slot; /* parent */ | 122 | struct acpiphp_slot *slot; /* parent */ |
122 | struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */ | ||
123 | 123 | ||
124 | struct list_head sibling; | 124 | struct list_head sibling; |
125 | struct notifier_block nb; | 125 | struct notifier_block nb; |
@@ -146,10 +146,6 @@ struct acpiphp_attention_info | |||
146 | #define ACPI_PCI_HOST_HID "PNP0A03" | 146 | #define ACPI_PCI_HOST_HID "PNP0A03" |
147 | 147 | ||
148 | /* ACPI _STA method value (ignore bit 4; battery present) */ | 148 | /* ACPI _STA method value (ignore bit 4; battery present) */ |
149 | #define ACPI_STA_PRESENT (0x00000001) | ||
150 | #define ACPI_STA_ENABLED (0x00000002) | ||
151 | #define ACPI_STA_SHOW_IN_UI (0x00000004) | ||
152 | #define ACPI_STA_FUNCTIONING (0x00000008) | ||
153 | #define ACPI_STA_ALL (0x0000000f) | 149 | #define ACPI_STA_ALL (0x0000000f) |
154 | 150 | ||
155 | /* bridge flags */ | 151 | /* bridge flags */ |
@@ -180,8 +176,6 @@ extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); | |||
180 | extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); | 176 | extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); |
181 | 177 | ||
182 | /* acpiphp_glue.c */ | 178 | /* acpiphp_glue.c */ |
183 | extern int acpiphp_glue_init (void); | ||
184 | extern void acpiphp_glue_exit (void); | ||
185 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); | 179 | typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); |
186 | 180 | ||
187 | extern int acpiphp_enable_slot (struct acpiphp_slot *slot); | 181 | extern int acpiphp_enable_slot (struct acpiphp_slot *slot); |
@@ -194,5 +188,6 @@ extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); | |||
194 | 188 | ||
195 | /* variables */ | 189 | /* variables */ |
196 | extern bool acpiphp_debug; | 190 | extern bool acpiphp_debug; |
191 | extern bool acpiphp_disabled; | ||
197 | 192 | ||
198 | #endif /* _ACPIPHP_H */ | 193 | #endif /* _ACPIPHP_H */ |
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index c2fd3095701f..ca8127950fcd 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | #include <linux/pci-acpi.h> | ||
40 | #include <linux/pci_hotplug.h> | 41 | #include <linux/pci_hotplug.h> |
41 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
42 | #include <linux/smp.h> | 43 | #include <linux/smp.h> |
@@ -48,6 +49,7 @@ | |||
48 | #define SLOT_NAME_SIZE 21 /* {_SUN} */ | 49 | #define SLOT_NAME_SIZE 21 /* {_SUN} */ |
49 | 50 | ||
50 | bool acpiphp_debug; | 51 | bool acpiphp_debug; |
52 | bool acpiphp_disabled; | ||
51 | 53 | ||
52 | /* local variables */ | 54 | /* local variables */ |
53 | static struct acpiphp_attention_info *attention_info; | 55 | static struct acpiphp_attention_info *attention_info; |
@@ -60,7 +62,9 @@ MODULE_AUTHOR(DRIVER_AUTHOR); | |||
60 | MODULE_DESCRIPTION(DRIVER_DESC); | 62 | MODULE_DESCRIPTION(DRIVER_DESC); |
61 | MODULE_LICENSE("GPL"); | 63 | MODULE_LICENSE("GPL"); |
62 | MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); | 64 | MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); |
65 | MODULE_PARM_DESC(disable, "disable acpiphp driver"); | ||
63 | module_param_named(debug, acpiphp_debug, bool, 0644); | 66 | module_param_named(debug, acpiphp_debug, bool, 0644); |
67 | module_param_named(disable, acpiphp_disabled, bool, 0444); | ||
64 | 68 | ||
65 | /* export the attention callback registration methods */ | 69 | /* export the attention callback registration methods */ |
66 | EXPORT_SYMBOL_GPL(acpiphp_register_attention); | 70 | EXPORT_SYMBOL_GPL(acpiphp_register_attention); |
@@ -351,27 +355,9 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) | |||
351 | } | 355 | } |
352 | 356 | ||
353 | 357 | ||
354 | static int __init acpiphp_init(void) | 358 | void __init acpiphp_init(void) |
355 | { | 359 | { |
356 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 360 | info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n", |
357 | 361 | acpiphp_disabled ? ", disabled by user; please report a bug" | |
358 | if (acpi_pci_disabled) | 362 | : ""); |
359 | return 0; | ||
360 | |||
361 | /* read all the ACPI info from the system */ | ||
362 | /* initialize internal data structure etc. */ | ||
363 | return acpiphp_glue_init(); | ||
364 | } | ||
365 | |||
366 | |||
367 | static void __exit acpiphp_exit(void) | ||
368 | { | ||
369 | if (acpi_pci_disabled) | ||
370 | return; | ||
371 | |||
372 | /* deallocate internal data structures etc. */ | ||
373 | acpiphp_glue_exit(); | ||
374 | } | 363 | } |
375 | |||
376 | module_init(acpiphp_init); | ||
377 | module_exit(acpiphp_exit); | ||
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 270fdbadc19c..96fed19c6d90 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include "acpiphp.h" | 54 | #include "acpiphp.h" |
55 | 55 | ||
56 | static LIST_HEAD(bridge_list); | 56 | static LIST_HEAD(bridge_list); |
57 | static DEFINE_MUTEX(bridge_mutex); | ||
57 | 58 | ||
58 | #define MY_NAME "acpiphp_glue" | 59 | #define MY_NAME "acpiphp_glue" |
59 | 60 | ||
@@ -61,6 +62,7 @@ static void handle_hotplug_event_bridge (acpi_handle, u32, void *); | |||
61 | static void acpiphp_sanitize_bus(struct pci_bus *bus); | 62 | static void acpiphp_sanitize_bus(struct pci_bus *bus); |
62 | static void acpiphp_set_hpp_values(struct pci_bus *bus); | 63 | static void acpiphp_set_hpp_values(struct pci_bus *bus); |
63 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); | 64 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); |
65 | static void free_bridge(struct kref *kref); | ||
64 | 66 | ||
65 | /* callback routine to check for the existence of a pci dock device */ | 67 | /* callback routine to check for the existence of a pci dock device */ |
66 | static acpi_status | 68 | static acpi_status |
@@ -76,6 +78,39 @@ is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
76 | } | 78 | } |
77 | } | 79 | } |
78 | 80 | ||
81 | static inline void get_bridge(struct acpiphp_bridge *bridge) | ||
82 | { | ||
83 | kref_get(&bridge->ref); | ||
84 | } | ||
85 | |||
86 | static inline void put_bridge(struct acpiphp_bridge *bridge) | ||
87 | { | ||
88 | kref_put(&bridge->ref, free_bridge); | ||
89 | } | ||
90 | |||
91 | static void free_bridge(struct kref *kref) | ||
92 | { | ||
93 | struct acpiphp_bridge *bridge; | ||
94 | struct acpiphp_slot *slot, *next; | ||
95 | struct acpiphp_func *func, *tmp; | ||
96 | |||
97 | bridge = container_of(kref, struct acpiphp_bridge, ref); | ||
98 | |||
99 | list_for_each_entry_safe(slot, next, &bridge->slots, node) { | ||
100 | list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { | ||
101 | kfree(func); | ||
102 | } | ||
103 | kfree(slot); | ||
104 | } | ||
105 | |||
106 | /* Release reference acquired by acpiphp_bridge_handle_to_function() */ | ||
107 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) | ||
108 | put_bridge(bridge->func->slot->bridge); | ||
109 | put_device(&bridge->pci_bus->dev); | ||
110 | pci_dev_put(bridge->pci_dev); | ||
111 | kfree(bridge); | ||
112 | } | ||
113 | |||
79 | /* | 114 | /* |
80 | * the _DCK method can do funny things... and sometimes not | 115 | * the _DCK method can do funny things... and sometimes not |
81 | * hah-hah funny. | 116 | * hah-hah funny. |
@@ -154,9 +189,10 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
154 | acpi_handle tmp; | 189 | acpi_handle tmp; |
155 | acpi_status status = AE_OK; | 190 | acpi_status status = AE_OK; |
156 | unsigned long long adr, sun; | 191 | unsigned long long adr, sun; |
157 | int device, function, retval; | 192 | int device, function, retval, found = 0; |
158 | struct pci_bus *pbus = bridge->pci_bus; | 193 | struct pci_bus *pbus = bridge->pci_bus; |
159 | struct pci_dev *pdev; | 194 | struct pci_dev *pdev; |
195 | u32 val; | ||
160 | 196 | ||
161 | if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) | 197 | if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) |
162 | return AE_OK; | 198 | return AE_OK; |
@@ -170,7 +206,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
170 | device = (adr >> 16) & 0xffff; | 206 | device = (adr >> 16) & 0xffff; |
171 | function = adr & 0xffff; | 207 | function = adr & 0xffff; |
172 | 208 | ||
173 | pdev = pbus->self; | 209 | pdev = bridge->pci_dev; |
174 | if (pdev && device_is_managed_by_native_pciehp(pdev)) | 210 | if (pdev && device_is_managed_by_native_pciehp(pdev)) |
175 | return AE_OK; | 211 | return AE_OK; |
176 | 212 | ||
@@ -178,7 +214,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
178 | if (!newfunc) | 214 | if (!newfunc) |
179 | return AE_NO_MEMORY; | 215 | return AE_NO_MEMORY; |
180 | 216 | ||
181 | INIT_LIST_HEAD(&newfunc->sibling); | ||
182 | newfunc->handle = handle; | 217 | newfunc->handle = handle; |
183 | newfunc->function = function; | 218 | newfunc->function = function; |
184 | 219 | ||
@@ -207,14 +242,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
207 | } | 242 | } |
208 | 243 | ||
209 | /* search for objects that share the same slot */ | 244 | /* search for objects that share the same slot */ |
210 | for (slot = bridge->slots; slot; slot = slot->next) | 245 | list_for_each_entry(slot, &bridge->slots, node) |
211 | if (slot->device == device) { | 246 | if (slot->device == device) { |
212 | if (slot->sun != sun) | 247 | if (slot->sun != sun) |
213 | warn("sibling found, but _SUN doesn't match!\n"); | 248 | warn("sibling found, but _SUN doesn't match!\n"); |
249 | found = 1; | ||
214 | break; | 250 | break; |
215 | } | 251 | } |
216 | 252 | ||
217 | if (!slot) { | 253 | if (!found) { |
218 | slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); | 254 | slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); |
219 | if (!slot) { | 255 | if (!slot) { |
220 | kfree(newfunc); | 256 | kfree(newfunc); |
@@ -227,9 +263,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
227 | INIT_LIST_HEAD(&slot->funcs); | 263 | INIT_LIST_HEAD(&slot->funcs); |
228 | mutex_init(&slot->crit_sect); | 264 | mutex_init(&slot->crit_sect); |
229 | 265 | ||
230 | slot->next = bridge->slots; | 266 | mutex_lock(&bridge_mutex); |
231 | bridge->slots = slot; | 267 | list_add_tail(&slot->node, &bridge->slots); |
232 | 268 | mutex_unlock(&bridge_mutex); | |
233 | bridge->nr_slots++; | 269 | bridge->nr_slots++; |
234 | 270 | ||
235 | dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", | 271 | dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", |
@@ -247,13 +283,13 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
247 | } | 283 | } |
248 | 284 | ||
249 | newfunc->slot = slot; | 285 | newfunc->slot = slot; |
286 | mutex_lock(&bridge_mutex); | ||
250 | list_add_tail(&newfunc->sibling, &slot->funcs); | 287 | list_add_tail(&newfunc->sibling, &slot->funcs); |
288 | mutex_unlock(&bridge_mutex); | ||
251 | 289 | ||
252 | pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); | 290 | if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function), |
253 | if (pdev) { | 291 | &val, 60*1000)) |
254 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); | 292 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); |
255 | pci_dev_put(pdev); | ||
256 | } | ||
257 | 293 | ||
258 | if (is_dock_device(handle)) { | 294 | if (is_dock_device(handle)) { |
259 | /* we don't want to call this device's _EJ0 | 295 | /* we don't want to call this device's _EJ0 |
@@ -290,7 +326,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
290 | 326 | ||
291 | err_exit: | 327 | err_exit: |
292 | bridge->nr_slots--; | 328 | bridge->nr_slots--; |
293 | bridge->slots = slot->next; | 329 | mutex_lock(&bridge_mutex); |
330 | list_del(&slot->node); | ||
331 | mutex_unlock(&bridge_mutex); | ||
294 | kfree(slot); | 332 | kfree(slot); |
295 | kfree(newfunc); | 333 | kfree(newfunc); |
296 | 334 | ||
@@ -315,13 +353,17 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) | |||
315 | acpi_status status; | 353 | acpi_status status; |
316 | 354 | ||
317 | /* must be added to the list prior to calling register_slot */ | 355 | /* must be added to the list prior to calling register_slot */ |
356 | mutex_lock(&bridge_mutex); | ||
318 | list_add(&bridge->list, &bridge_list); | 357 | list_add(&bridge->list, &bridge_list); |
358 | mutex_unlock(&bridge_mutex); | ||
319 | 359 | ||
320 | /* register all slot objects under this bridge */ | 360 | /* register all slot objects under this bridge */ |
321 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, | 361 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, |
322 | register_slot, NULL, bridge, NULL); | 362 | register_slot, NULL, bridge, NULL); |
323 | if (ACPI_FAILURE(status)) { | 363 | if (ACPI_FAILURE(status)) { |
364 | mutex_lock(&bridge_mutex); | ||
324 | list_del(&bridge->list); | 365 | list_del(&bridge->list); |
366 | mutex_unlock(&bridge_mutex); | ||
325 | return; | 367 | return; |
326 | } | 368 | } |
327 | 369 | ||
@@ -351,178 +393,46 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle | |||
351 | { | 393 | { |
352 | struct acpiphp_bridge *bridge; | 394 | struct acpiphp_bridge *bridge; |
353 | struct acpiphp_slot *slot; | 395 | struct acpiphp_slot *slot; |
354 | struct acpiphp_func *func; | 396 | struct acpiphp_func *func = NULL; |
355 | 397 | ||
398 | mutex_lock(&bridge_mutex); | ||
356 | list_for_each_entry(bridge, &bridge_list, list) { | 399 | list_for_each_entry(bridge, &bridge_list, list) { |
357 | for (slot = bridge->slots; slot; slot = slot->next) { | 400 | list_for_each_entry(slot, &bridge->slots, node) { |
358 | list_for_each_entry(func, &slot->funcs, sibling) { | 401 | list_for_each_entry(func, &slot->funcs, sibling) { |
359 | if (func->handle == handle) | 402 | if (func->handle == handle) { |
403 | get_bridge(func->slot->bridge); | ||
404 | mutex_unlock(&bridge_mutex); | ||
360 | return func; | 405 | return func; |
406 | } | ||
361 | } | 407 | } |
362 | } | 408 | } |
363 | } | 409 | } |
410 | mutex_unlock(&bridge_mutex); | ||
364 | 411 | ||
365 | return NULL; | 412 | return NULL; |
366 | } | 413 | } |
367 | 414 | ||
368 | 415 | ||
369 | static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) | ||
370 | { | ||
371 | acpi_handle dummy_handle; | ||
372 | struct acpiphp_func *func; | ||
373 | |||
374 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, | ||
375 | "_EJ0", &dummy_handle))) { | ||
376 | bridge->flags |= BRIDGE_HAS_EJ0; | ||
377 | |||
378 | dbg("found ejectable p2p bridge\n"); | ||
379 | |||
380 | /* make link between PCI bridge and PCI function */ | ||
381 | func = acpiphp_bridge_handle_to_function(bridge->handle); | ||
382 | if (!func) | ||
383 | return; | ||
384 | bridge->func = func; | ||
385 | func->bridge = bridge; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | |||
390 | /* allocate and initialize host bridge data structure */ | ||
391 | static void add_host_bridge(struct acpi_pci_root *root) | ||
392 | { | ||
393 | struct acpiphp_bridge *bridge; | ||
394 | acpi_handle handle = root->device->handle; | ||
395 | |||
396 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); | ||
397 | if (bridge == NULL) | ||
398 | return; | ||
399 | |||
400 | bridge->handle = handle; | ||
401 | |||
402 | bridge->pci_bus = root->bus; | ||
403 | |||
404 | init_bridge_misc(bridge); | ||
405 | } | ||
406 | |||
407 | |||
408 | /* allocate and initialize PCI-to-PCI bridge data structure */ | ||
409 | static void add_p2p_bridge(acpi_handle *handle) | ||
410 | { | ||
411 | struct acpiphp_bridge *bridge; | ||
412 | |||
413 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); | ||
414 | if (bridge == NULL) { | ||
415 | err("out of memory\n"); | ||
416 | return; | ||
417 | } | ||
418 | |||
419 | bridge->handle = handle; | ||
420 | config_p2p_bridge_flags(bridge); | ||
421 | |||
422 | bridge->pci_dev = acpi_get_pci_dev(handle); | ||
423 | bridge->pci_bus = bridge->pci_dev->subordinate; | ||
424 | if (!bridge->pci_bus) { | ||
425 | err("This is not a PCI-to-PCI bridge!\n"); | ||
426 | goto err; | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * Grab a ref to the subordinate PCI bus in case the bus is | ||
431 | * removed via PCI core logical hotplug. The ref pins the bus | ||
432 | * (which we access during module unload). | ||
433 | */ | ||
434 | get_device(&bridge->pci_bus->dev); | ||
435 | |||
436 | init_bridge_misc(bridge); | ||
437 | return; | ||
438 | err: | ||
439 | pci_dev_put(bridge->pci_dev); | ||
440 | kfree(bridge); | ||
441 | return; | ||
442 | } | ||
443 | |||
444 | |||
445 | /* callback routine to find P2P bridges */ | ||
446 | static acpi_status | ||
447 | find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
448 | { | ||
449 | acpi_status status; | ||
450 | struct pci_dev *dev; | ||
451 | |||
452 | dev = acpi_get_pci_dev(handle); | ||
453 | if (!dev || !dev->subordinate) | ||
454 | goto out; | ||
455 | |||
456 | /* check if this bridge has ejectable slots */ | ||
457 | if ((detect_ejectable_slots(handle) > 0)) { | ||
458 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); | ||
459 | add_p2p_bridge(handle); | ||
460 | } | ||
461 | |||
462 | /* search P2P bridges under this p2p bridge */ | ||
463 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | ||
464 | find_p2p_bridge, NULL, NULL, NULL); | ||
465 | if (ACPI_FAILURE(status)) | ||
466 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); | ||
467 | |||
468 | out: | ||
469 | pci_dev_put(dev); | ||
470 | return AE_OK; | ||
471 | } | ||
472 | |||
473 | |||
474 | /* find hot-pluggable slots, and then find P2P bridge */ | ||
475 | static int add_bridge(struct acpi_pci_root *root) | ||
476 | { | ||
477 | acpi_status status; | ||
478 | unsigned long long tmp; | ||
479 | acpi_handle dummy_handle; | ||
480 | acpi_handle handle = root->device->handle; | ||
481 | |||
482 | /* if the bridge doesn't have _STA, we assume it is always there */ | ||
483 | status = acpi_get_handle(handle, "_STA", &dummy_handle); | ||
484 | if (ACPI_SUCCESS(status)) { | ||
485 | status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); | ||
486 | if (ACPI_FAILURE(status)) { | ||
487 | dbg("%s: _STA evaluation failure\n", __func__); | ||
488 | return 0; | ||
489 | } | ||
490 | if ((tmp & ACPI_STA_FUNCTIONING) == 0) | ||
491 | /* don't register this object */ | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | /* check if this bridge has ejectable slots */ | ||
496 | if (detect_ejectable_slots(handle) > 0) { | ||
497 | dbg("found PCI host-bus bridge with hot-pluggable slots\n"); | ||
498 | add_host_bridge(root); | ||
499 | } | ||
500 | |||
501 | /* search P2P bridges under this host bridge */ | ||
502 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | ||
503 | find_p2p_bridge, NULL, NULL, NULL); | ||
504 | |||
505 | if (ACPI_FAILURE(status)) | ||
506 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); | ||
507 | |||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) | 416 | static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) |
512 | { | 417 | { |
513 | struct acpiphp_bridge *bridge; | 418 | struct acpiphp_bridge *bridge; |
514 | 419 | ||
420 | mutex_lock(&bridge_mutex); | ||
515 | list_for_each_entry(bridge, &bridge_list, list) | 421 | list_for_each_entry(bridge, &bridge_list, list) |
516 | if (bridge->handle == handle) | 422 | if (bridge->handle == handle) { |
423 | get_bridge(bridge); | ||
424 | mutex_unlock(&bridge_mutex); | ||
517 | return bridge; | 425 | return bridge; |
426 | } | ||
427 | mutex_unlock(&bridge_mutex); | ||
518 | 428 | ||
519 | return NULL; | 429 | return NULL; |
520 | } | 430 | } |
521 | 431 | ||
522 | static void cleanup_bridge(struct acpiphp_bridge *bridge) | 432 | static void cleanup_bridge(struct acpiphp_bridge *bridge) |
523 | { | 433 | { |
524 | struct acpiphp_slot *slot, *next; | 434 | struct acpiphp_slot *slot; |
525 | struct acpiphp_func *func, *tmp; | 435 | struct acpiphp_func *func; |
526 | acpi_status status; | 436 | acpi_status status; |
527 | acpi_handle handle = bridge->handle; | 437 | acpi_handle handle = bridge->handle; |
528 | 438 | ||
@@ -543,10 +453,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
543 | err("failed to install interrupt notify handler\n"); | 453 | err("failed to install interrupt notify handler\n"); |
544 | } | 454 | } |
545 | 455 | ||
546 | slot = bridge->slots; | 456 | list_for_each_entry(slot, &bridge->slots, node) { |
547 | while (slot) { | 457 | list_for_each_entry(func, &slot->funcs, sibling) { |
548 | next = slot->next; | ||
549 | list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { | ||
550 | if (is_dock_device(func->handle)) { | 458 | if (is_dock_device(func->handle)) { |
551 | unregister_hotplug_dock_device(func->handle); | 459 | unregister_hotplug_dock_device(func->handle); |
552 | unregister_dock_notifier(&func->nb); | 460 | unregister_dock_notifier(&func->nb); |
@@ -558,63 +466,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
558 | if (ACPI_FAILURE(status)) | 466 | if (ACPI_FAILURE(status)) |
559 | err("failed to remove notify handler\n"); | 467 | err("failed to remove notify handler\n"); |
560 | } | 468 | } |
561 | list_del(&func->sibling); | ||
562 | kfree(func); | ||
563 | } | 469 | } |
564 | acpiphp_unregister_hotplug_slot(slot); | 470 | acpiphp_unregister_hotplug_slot(slot); |
565 | list_del(&slot->funcs); | ||
566 | kfree(slot); | ||
567 | slot = next; | ||
568 | } | 471 | } |
569 | 472 | ||
570 | /* | 473 | mutex_lock(&bridge_mutex); |
571 | * Only P2P bridges have a pci_dev | ||
572 | */ | ||
573 | if (bridge->pci_dev) | ||
574 | put_device(&bridge->pci_bus->dev); | ||
575 | |||
576 | pci_dev_put(bridge->pci_dev); | ||
577 | list_del(&bridge->list); | 474 | list_del(&bridge->list); |
578 | kfree(bridge); | 475 | mutex_unlock(&bridge_mutex); |
579 | } | ||
580 | |||
581 | static acpi_status | ||
582 | cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
583 | { | ||
584 | struct acpiphp_bridge *bridge; | ||
585 | |||
586 | /* cleanup p2p bridges under this P2P bridge | ||
587 | in a depth-first manner */ | ||
588 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | ||
589 | cleanup_p2p_bridge, NULL, NULL, NULL); | ||
590 | |||
591 | bridge = acpiphp_handle_to_bridge(handle); | ||
592 | if (bridge) | ||
593 | cleanup_bridge(bridge); | ||
594 | |||
595 | return AE_OK; | ||
596 | } | ||
597 | |||
598 | static void remove_bridge(struct acpi_pci_root *root) | ||
599 | { | ||
600 | struct acpiphp_bridge *bridge; | ||
601 | acpi_handle handle = root->device->handle; | ||
602 | |||
603 | /* cleanup p2p bridges under this host bridge | ||
604 | in a depth-first manner */ | ||
605 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | ||
606 | (u32)1, cleanup_p2p_bridge, NULL, NULL, NULL); | ||
607 | |||
608 | /* | ||
609 | * On root bridges with hotplug slots directly underneath (ie, | ||
610 | * no p2p bridge between), we call cleanup_bridge(). | ||
611 | * | ||
612 | * The else clause cleans up root bridges that either had no | ||
613 | * hotplug slots at all, or had a p2p bridge underneath. | ||
614 | */ | ||
615 | bridge = acpiphp_handle_to_bridge(handle); | ||
616 | if (bridge) | ||
617 | cleanup_bridge(bridge); | ||
618 | } | 476 | } |
619 | 477 | ||
620 | static int power_on_slot(struct acpiphp_slot *slot) | 478 | static int power_on_slot(struct acpiphp_slot *slot) |
@@ -798,6 +656,7 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) | |||
798 | } | 656 | } |
799 | } | 657 | } |
800 | } | 658 | } |
659 | |||
801 | /** | 660 | /** |
802 | * enable_device - enable, configure a slot | 661 | * enable_device - enable, configure a slot |
803 | * @slot: slot to be enabled | 662 | * @slot: slot to be enabled |
@@ -810,9 +669,7 @@ static int __ref enable_device(struct acpiphp_slot *slot) | |||
810 | struct pci_dev *dev; | 669 | struct pci_dev *dev; |
811 | struct pci_bus *bus = slot->bridge->pci_bus; | 670 | struct pci_bus *bus = slot->bridge->pci_bus; |
812 | struct acpiphp_func *func; | 671 | struct acpiphp_func *func; |
813 | int retval = 0; | ||
814 | int num, max, pass; | 672 | int num, max, pass; |
815 | acpi_status status; | ||
816 | 673 | ||
817 | if (slot->flags & SLOT_ENABLED) | 674 | if (slot->flags & SLOT_ENABLED) |
818 | goto err_exit; | 675 | goto err_exit; |
@@ -867,23 +724,11 @@ static int __ref enable_device(struct acpiphp_slot *slot) | |||
867 | slot->flags &= (~SLOT_ENABLED); | 724 | slot->flags &= (~SLOT_ENABLED); |
868 | continue; | 725 | continue; |
869 | } | 726 | } |
870 | |||
871 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && | ||
872 | dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) { | ||
873 | pci_dev_put(dev); | ||
874 | continue; | ||
875 | } | ||
876 | |||
877 | status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); | ||
878 | if (ACPI_FAILURE(status)) | ||
879 | warn("find_p2p_bridge failed (error code = 0x%x)\n", | ||
880 | status); | ||
881 | pci_dev_put(dev); | ||
882 | } | 727 | } |
883 | 728 | ||
884 | 729 | ||
885 | err_exit: | 730 | err_exit: |
886 | return retval; | 731 | return 0; |
887 | } | 732 | } |
888 | 733 | ||
889 | /* return first device in slot, acquiring a reference on it */ | 734 | /* return first device in slot, acquiring a reference on it */ |
@@ -912,23 +757,6 @@ static int disable_device(struct acpiphp_slot *slot) | |||
912 | { | 757 | { |
913 | struct acpiphp_func *func; | 758 | struct acpiphp_func *func; |
914 | struct pci_dev *pdev; | 759 | struct pci_dev *pdev; |
915 | struct pci_bus *bus = slot->bridge->pci_bus; | ||
916 | |||
917 | /* The slot will be enabled when func 0 is added, so check | ||
918 | func 0 before disable the slot. */ | ||
919 | pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0)); | ||
920 | if (!pdev) | ||
921 | goto err_exit; | ||
922 | pci_dev_put(pdev); | ||
923 | |||
924 | list_for_each_entry(func, &slot->funcs, sibling) { | ||
925 | if (func->bridge) { | ||
926 | /* cleanup p2p bridges under this P2P bridge */ | ||
927 | cleanup_p2p_bridge(func->bridge->handle, | ||
928 | (u32)1, NULL, NULL); | ||
929 | func->bridge = NULL; | ||
930 | } | ||
931 | } | ||
932 | 760 | ||
933 | /* | 761 | /* |
934 | * enable_device() enumerates all functions in this device via | 762 | * enable_device() enumerates all functions in this device via |
@@ -947,7 +775,6 @@ static int disable_device(struct acpiphp_slot *slot) | |||
947 | 775 | ||
948 | slot->flags &= (~SLOT_ENABLED); | 776 | slot->flags &= (~SLOT_ENABLED); |
949 | 777 | ||
950 | err_exit: | ||
951 | return 0; | 778 | return 0; |
952 | } | 779 | } |
953 | 780 | ||
@@ -1037,7 +864,7 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
1037 | 864 | ||
1038 | enabled = disabled = 0; | 865 | enabled = disabled = 0; |
1039 | 866 | ||
1040 | for (slot = bridge->slots; slot; slot = slot->next) { | 867 | list_for_each_entry(slot, &bridge->slots, node) { |
1041 | unsigned int status = get_slot_status(slot); | 868 | unsigned int status = get_slot_status(slot); |
1042 | if (slot->flags & SLOT_ENABLED) { | 869 | if (slot->flags & SLOT_ENABLED) { |
1043 | if (status == ACPI_STA_ALL) | 870 | if (status == ACPI_STA_ALL) |
@@ -1082,11 +909,11 @@ static void acpiphp_set_hpp_values(struct pci_bus *bus) | |||
1082 | */ | 909 | */ |
1083 | static void acpiphp_sanitize_bus(struct pci_bus *bus) | 910 | static void acpiphp_sanitize_bus(struct pci_bus *bus) |
1084 | { | 911 | { |
1085 | struct pci_dev *dev; | 912 | struct pci_dev *dev, *tmp; |
1086 | int i; | 913 | int i; |
1087 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; | 914 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; |
1088 | 915 | ||
1089 | list_for_each_entry(dev, &bus->devices, bus_list) { | 916 | list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { |
1090 | for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { | 917 | for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { |
1091 | struct resource *res = &dev->resource[i]; | 918 | struct resource *res = &dev->resource[i]; |
1092 | if ((res->flags & type_mask) && !res->start && | 919 | if ((res->flags & type_mask) && !res->start && |
@@ -1118,6 +945,7 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
1118 | dbg("%s: re-enumerating slots under %s\n", | 945 | dbg("%s: re-enumerating slots under %s\n", |
1119 | __func__, objname); | 946 | __func__, objname); |
1120 | acpiphp_check_bridge(bridge); | 947 | acpiphp_check_bridge(bridge); |
948 | put_bridge(bridge); | ||
1121 | } | 949 | } |
1122 | return AE_OK ; | 950 | return AE_OK ; |
1123 | } | 951 | } |
@@ -1195,6 +1023,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) | |||
1195 | 1023 | ||
1196 | acpi_scan_lock_release(); | 1024 | acpi_scan_lock_release(); |
1197 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | 1025 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ |
1026 | put_bridge(bridge); | ||
1198 | } | 1027 | } |
1199 | 1028 | ||
1200 | /** | 1029 | /** |
@@ -1208,6 +1037,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) | |||
1208 | static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, | 1037 | static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, |
1209 | void *context) | 1038 | void *context) |
1210 | { | 1039 | { |
1040 | struct acpiphp_bridge *bridge = context; | ||
1041 | |||
1211 | /* | 1042 | /* |
1212 | * Currently the code adds all hotplug events to the kacpid_wq | 1043 | * Currently the code adds all hotplug events to the kacpid_wq |
1213 | * queue when it should add hotplug events to the kacpi_hotplug_wq. | 1044 | * queue when it should add hotplug events to the kacpi_hotplug_wq. |
@@ -1216,6 +1047,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, | |||
1216 | * For now just re-add this work to the kacpi_hotplug_wq so we | 1047 | * For now just re-add this work to the kacpi_hotplug_wq so we |
1217 | * don't deadlock on hotplug actions. | 1048 | * don't deadlock on hotplug actions. |
1218 | */ | 1049 | */ |
1050 | get_bridge(bridge); | ||
1219 | alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge); | 1051 | alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge); |
1220 | } | 1052 | } |
1221 | 1053 | ||
@@ -1270,6 +1102,7 @@ static void _handle_hotplug_event_func(struct work_struct *work) | |||
1270 | 1102 | ||
1271 | acpi_scan_lock_release(); | 1103 | acpi_scan_lock_release(); |
1272 | kfree(hp_work); /* allocated in handle_hotplug_event_func */ | 1104 | kfree(hp_work); /* allocated in handle_hotplug_event_func */ |
1105 | put_bridge(func->slot->bridge); | ||
1273 | } | 1106 | } |
1274 | 1107 | ||
1275 | /** | 1108 | /** |
@@ -1283,6 +1116,8 @@ static void _handle_hotplug_event_func(struct work_struct *work) | |||
1283 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, | 1116 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, |
1284 | void *context) | 1117 | void *context) |
1285 | { | 1118 | { |
1119 | struct acpiphp_func *func = context; | ||
1120 | |||
1286 | /* | 1121 | /* |
1287 | * Currently the code adds all hotplug events to the kacpid_wq | 1122 | * Currently the code adds all hotplug events to the kacpid_wq |
1288 | * queue when it should add hotplug events to the kacpi_hotplug_wq. | 1123 | * queue when it should add hotplug events to the kacpi_hotplug_wq. |
@@ -1291,33 +1126,69 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, | |||
1291 | * For now just re-add this work to the kacpi_hotplug_wq so we | 1126 | * For now just re-add this work to the kacpi_hotplug_wq so we |
1292 | * don't deadlock on hotplug actions. | 1127 | * don't deadlock on hotplug actions. |
1293 | */ | 1128 | */ |
1129 | get_bridge(func->slot->bridge); | ||
1294 | alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func); | 1130 | alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func); |
1295 | } | 1131 | } |
1296 | 1132 | ||
1297 | static struct acpi_pci_driver acpi_pci_hp_driver = { | 1133 | /* |
1298 | .add = add_bridge, | 1134 | * Create hotplug slots for the PCI bus. |
1299 | .remove = remove_bridge, | 1135 | * It should always return 0 to avoid skipping following notifiers. |
1300 | }; | ||
1301 | |||
1302 | /** | ||
1303 | * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures | ||
1304 | */ | 1136 | */ |
1305 | int __init acpiphp_glue_init(void) | 1137 | void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) |
1306 | { | 1138 | { |
1307 | acpi_pci_register_driver(&acpi_pci_hp_driver); | 1139 | acpi_handle dummy_handle; |
1140 | struct acpiphp_bridge *bridge; | ||
1308 | 1141 | ||
1309 | return 0; | 1142 | if (acpiphp_disabled) |
1310 | } | 1143 | return; |
1311 | 1144 | ||
1145 | if (detect_ejectable_slots(handle) <= 0) | ||
1146 | return; | ||
1312 | 1147 | ||
1313 | /** | 1148 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); |
1314 | * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures | 1149 | if (bridge == NULL) { |
1315 | * | 1150 | err("out of memory\n"); |
1316 | * This function frees all data allocated in acpiphp_glue_init(). | 1151 | return; |
1317 | */ | 1152 | } |
1318 | void acpiphp_glue_exit(void) | 1153 | |
1154 | INIT_LIST_HEAD(&bridge->slots); | ||
1155 | kref_init(&bridge->ref); | ||
1156 | bridge->handle = handle; | ||
1157 | bridge->pci_dev = pci_dev_get(bus->self); | ||
1158 | bridge->pci_bus = bus; | ||
1159 | |||
1160 | /* | ||
1161 | * Grab a ref to the subordinate PCI bus in case the bus is | ||
1162 | * removed via PCI core logical hotplug. The ref pins the bus | ||
1163 | * (which we access during module unload). | ||
1164 | */ | ||
1165 | get_device(&bus->dev); | ||
1166 | |||
1167 | if (!pci_is_root_bus(bridge->pci_bus) && | ||
1168 | ACPI_SUCCESS(acpi_get_handle(bridge->handle, | ||
1169 | "_EJ0", &dummy_handle))) { | ||
1170 | dbg("found ejectable p2p bridge\n"); | ||
1171 | bridge->flags |= BRIDGE_HAS_EJ0; | ||
1172 | bridge->func = acpiphp_bridge_handle_to_function(handle); | ||
1173 | } | ||
1174 | |||
1175 | init_bridge_misc(bridge); | ||
1176 | } | ||
1177 | |||
1178 | /* Destroy hotplug slots associated with the PCI bus */ | ||
1179 | void acpiphp_remove_slots(struct pci_bus *bus) | ||
1319 | { | 1180 | { |
1320 | acpi_pci_unregister_driver(&acpi_pci_hp_driver); | 1181 | struct acpiphp_bridge *bridge, *tmp; |
1182 | |||
1183 | if (acpiphp_disabled) | ||
1184 | return; | ||
1185 | |||
1186 | list_for_each_entry_safe(bridge, tmp, &bridge_list, list) | ||
1187 | if (bridge->pci_bus == bus) { | ||
1188 | cleanup_bridge(bridge); | ||
1189 | put_bridge(bridge); | ||
1190 | break; | ||
1191 | } | ||
1321 | } | 1192 | } |
1322 | 1193 | ||
1323 | /** | 1194 | /** |
@@ -1396,7 +1267,7 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) | |||
1396 | 1267 | ||
1397 | sta = get_slot_status(slot); | 1268 | sta = get_slot_status(slot); |
1398 | 1269 | ||
1399 | return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1; | 1270 | return (sta & ACPI_STA_DEVICE_UI) ? 0 : 1; |
1400 | } | 1271 | } |
1401 | 1272 | ||
1402 | 1273 | ||
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index dee5dddaa292..d927933dcf44 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -287,6 +287,32 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = { | |||
287 | .run_wake = acpi_pci_run_wake, | 287 | .run_wake = acpi_pci_run_wake, |
288 | }; | 288 | }; |
289 | 289 | ||
290 | void acpi_pci_add_bus(struct pci_bus *bus) | ||
291 | { | ||
292 | acpi_handle handle = NULL; | ||
293 | |||
294 | if (bus->bridge) | ||
295 | handle = ACPI_HANDLE(bus->bridge); | ||
296 | if (acpi_pci_disabled || handle == NULL) | ||
297 | return; | ||
298 | |||
299 | acpi_pci_slot_enumerate(bus, handle); | ||
300 | acpiphp_enumerate_slots(bus, handle); | ||
301 | } | ||
302 | |||
303 | void acpi_pci_remove_bus(struct pci_bus *bus) | ||
304 | { | ||
305 | /* | ||
306 | * bus->bridge->acpi_node.handle has already been reset to NULL | ||
307 | * when acpi_pci_remove_bus() is called, so don't check ACPI handle. | ||
308 | */ | ||
309 | if (acpi_pci_disabled) | ||
310 | return; | ||
311 | |||
312 | acpiphp_remove_slots(bus); | ||
313 | acpi_pci_slot_remove(bus); | ||
314 | } | ||
315 | |||
290 | /* ACPI bus type */ | 316 | /* ACPI bus type */ |
291 | static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) | 317 | static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) |
292 | { | 318 | { |
@@ -361,7 +387,11 @@ static int __init acpi_pci_init(void) | |||
361 | ret = register_acpi_bus_type(&acpi_pci_bus); | 387 | ret = register_acpi_bus_type(&acpi_pci_bus); |
362 | if (ret) | 388 | if (ret) |
363 | return 0; | 389 | return 0; |
390 | |||
364 | pci_set_platform_pm(&acpi_pci_platform_pm); | 391 | pci_set_platform_pm(&acpi_pci_platform_pm); |
392 | acpi_pci_slot_init(); | ||
393 | acpiphp_init(); | ||
394 | |||
365 | return 0; | 395 | return 0; |
366 | } | 396 | } |
367 | arch_initcall(acpi_pci_init); | 397 | arch_initcall(acpi_pci_init); |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b494066ef32f..43ece5d41d36 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -673,6 +673,8 @@ add_dev: | |||
673 | ret = device_register(&child->dev); | 673 | ret = device_register(&child->dev); |
674 | WARN_ON(ret < 0); | 674 | WARN_ON(ret < 0); |
675 | 675 | ||
676 | pcibios_add_bus(child); | ||
677 | |||
676 | /* Create legacy_io and legacy_mem files for this bus */ | 678 | /* Create legacy_io and legacy_mem files for this bus */ |
677 | pci_create_legacy_files(child); | 679 | pci_create_legacy_files(child); |
678 | 680 | ||
@@ -1627,8 +1629,7 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) | |||
1627 | if (!bus->is_added) { | 1629 | if (!bus->is_added) { |
1628 | dev_dbg(&bus->dev, "fixups for bus\n"); | 1630 | dev_dbg(&bus->dev, "fixups for bus\n"); |
1629 | pcibios_fixup_bus(bus); | 1631 | pcibios_fixup_bus(bus); |
1630 | if (pci_is_root_bus(bus)) | 1632 | bus->is_added = 1; |
1631 | bus->is_added = 1; | ||
1632 | } | 1633 | } |
1633 | 1634 | ||
1634 | for (pass=0; pass < 2; pass++) | 1635 | for (pass=0; pass < 2; pass++) |
@@ -1661,6 +1662,14 @@ int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) | |||
1661 | return 0; | 1662 | return 0; |
1662 | } | 1663 | } |
1663 | 1664 | ||
1665 | void __weak pcibios_add_bus(struct pci_bus *bus) | ||
1666 | { | ||
1667 | } | ||
1668 | |||
1669 | void __weak pcibios_remove_bus(struct pci_bus *bus) | ||
1670 | { | ||
1671 | } | ||
1672 | |||
1664 | struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | 1673 | struct pci_bus *pci_create_root_bus(struct device *parent, int bus, |
1665 | struct pci_ops *ops, void *sysdata, struct list_head *resources) | 1674 | struct pci_ops *ops, void *sysdata, struct list_head *resources) |
1666 | { | 1675 | { |
@@ -1715,6 +1724,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, | |||
1715 | if (error) | 1724 | if (error) |
1716 | goto class_dev_reg_err; | 1725 | goto class_dev_reg_err; |
1717 | 1726 | ||
1727 | pcibios_add_bus(b); | ||
1728 | |||
1718 | /* Create legacy_io and legacy_mem files for this bus */ | 1729 | /* Create legacy_io and legacy_mem files for this bus */ |
1719 | pci_create_legacy_files(b); | 1730 | pci_create_legacy_files(b); |
1720 | 1731 | ||
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index cc875e6ed159..8fc54b7327bc 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c | |||
@@ -50,10 +50,8 @@ void pci_remove_bus(struct pci_bus *bus) | |||
50 | list_del(&bus->node); | 50 | list_del(&bus->node); |
51 | pci_bus_release_busn_res(bus); | 51 | pci_bus_release_busn_res(bus); |
52 | up_write(&pci_bus_sem); | 52 | up_write(&pci_bus_sem); |
53 | if (!bus->is_added) | ||
54 | return; | ||
55 | |||
56 | pci_remove_legacy_files(bus); | 53 | pci_remove_legacy_files(bus); |
54 | pcibios_remove_bus(bus); | ||
57 | device_unregister(&bus->dev); | 55 | device_unregister(&bus->dev); |
58 | } | 56 | } |
59 | EXPORT_SYMBOL(pci_remove_bus); | 57 | EXPORT_SYMBOL(pci_remove_bus); |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index bcbdd7484e58..03053aca5b32 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -152,15 +152,6 @@ void acpi_penalize_isa_irq(int irq, int active); | |||
152 | 152 | ||
153 | void acpi_pci_irq_disable (struct pci_dev *dev); | 153 | void acpi_pci_irq_disable (struct pci_dev *dev); |
154 | 154 | ||
155 | struct acpi_pci_driver { | ||
156 | struct list_head node; | ||
157 | int (*add)(struct acpi_pci_root *root); | ||
158 | void (*remove)(struct acpi_pci_root *root); | ||
159 | }; | ||
160 | |||
161 | int acpi_pci_register_driver(struct acpi_pci_driver *driver); | ||
162 | void acpi_pci_unregister_driver(struct acpi_pci_driver *driver); | ||
163 | |||
164 | extern int ec_read(u8 addr, u8 *val); | 155 | extern int ec_read(u8 addr, u8 *val); |
165 | extern int ec_write(u8 addr, u8 val); | 156 | extern int ec_write(u8 addr, u8 val); |
166 | extern int ec_transaction(u8 command, | 157 | extern int ec_transaction(u8 command, |
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 9a22b5efb384..81b31613eb25 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h | |||
@@ -41,8 +41,37 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus) | |||
41 | 41 | ||
42 | return DEVICE_ACPI_HANDLE(dev); | 42 | return DEVICE_ACPI_HANDLE(dev); |
43 | } | 43 | } |
44 | |||
45 | void acpi_pci_add_bus(struct pci_bus *bus); | ||
46 | void acpi_pci_remove_bus(struct pci_bus *bus); | ||
47 | |||
48 | #ifdef CONFIG_ACPI_PCI_SLOT | ||
49 | void acpi_pci_slot_init(void); | ||
50 | void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle); | ||
51 | void acpi_pci_slot_remove(struct pci_bus *bus); | ||
52 | #else | ||
53 | static inline void acpi_pci_slot_init(void) { } | ||
54 | static inline void acpi_pci_slot_enumerate(struct pci_bus *bus, | ||
55 | acpi_handle handle) { } | ||
56 | static inline void acpi_pci_slot_remove(struct pci_bus *bus) { } | ||
44 | #endif | 57 | #endif |
45 | 58 | ||
59 | #ifdef CONFIG_HOTPLUG_PCI_ACPI | ||
60 | void acpiphp_init(void); | ||
61 | void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle); | ||
62 | void acpiphp_remove_slots(struct pci_bus *bus); | ||
63 | #else | ||
64 | static inline void acpiphp_init(void) { } | ||
65 | static inline void acpiphp_enumerate_slots(struct pci_bus *bus, | ||
66 | acpi_handle handle) { } | ||
67 | static inline void acpiphp_remove_slots(struct pci_bus *bus) { } | ||
68 | #endif | ||
69 | |||
70 | #else /* CONFIG_ACPI */ | ||
71 | static inline void acpi_pci_add_bus(struct pci_bus *bus) { } | ||
72 | static inline void acpi_pci_remove_bus(struct pci_bus *bus) { } | ||
73 | #endif /* CONFIG_ACPI */ | ||
74 | |||
46 | #ifdef CONFIG_ACPI_APEI | 75 | #ifdef CONFIG_ACPI_APEI |
47 | extern bool aer_acpi_firmware_first(void); | 76 | extern bool aer_acpi_firmware_first(void); |
48 | #else | 77 | #else |
diff --git a/include/linux/pci.h b/include/linux/pci.h index bcd976976c3e..4a6ee631a0c5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -693,6 +693,8 @@ extern struct list_head pci_root_buses; /* list of all known PCI buses */ | |||
693 | extern int no_pci_devices(void); | 693 | extern int no_pci_devices(void); |
694 | 694 | ||
695 | void pcibios_resource_survey_bus(struct pci_bus *bus); | 695 | void pcibios_resource_survey_bus(struct pci_bus *bus); |
696 | void pcibios_add_bus(struct pci_bus *bus); | ||
697 | void pcibios_remove_bus(struct pci_bus *bus); | ||
696 | void pcibios_fixup_bus(struct pci_bus *); | 698 | void pcibios_fixup_bus(struct pci_bus *); |
697 | int __must_check pcibios_enable_device(struct pci_dev *, int mask); | 699 | int __must_check pcibios_enable_device(struct pci_dev *, int mask); |
698 | /* Architecture specific versions may override this (weak) */ | 700 | /* Architecture specific versions may override this (weak) */ |