diff options
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 527 |
1 files changed, 196 insertions, 331 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index aee6a0acbbe9..bccc27ee1030 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -58,71 +58,59 @@ | |||
58 | 58 | ||
59 | static LIST_HEAD(bridge_list); | 59 | static LIST_HEAD(bridge_list); |
60 | static DEFINE_MUTEX(bridge_mutex); | 60 | static DEFINE_MUTEX(bridge_mutex); |
61 | static DEFINE_MUTEX(acpiphp_context_lock); | ||
62 | 61 | ||
63 | static void handle_hotplug_event(acpi_handle handle, u32 type, void *data); | 62 | static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type); |
63 | static void acpiphp_post_dock_fixup(struct acpi_device *adev); | ||
64 | static void acpiphp_sanitize_bus(struct pci_bus *bus); | 64 | static void acpiphp_sanitize_bus(struct pci_bus *bus); |
65 | static void acpiphp_set_hpp_values(struct pci_bus *bus); | 65 | static void acpiphp_set_hpp_values(struct pci_bus *bus); |
66 | static void hotplug_event(acpi_handle handle, u32 type, void *data); | 66 | static void hotplug_event(u32 type, struct acpiphp_context *context); |
67 | static void free_bridge(struct kref *kref); | 67 | static void free_bridge(struct kref *kref); |
68 | 68 | ||
69 | static void acpiphp_context_handler(acpi_handle handle, void *context) | ||
70 | { | ||
71 | /* Intentionally empty. */ | ||
72 | } | ||
73 | |||
74 | /** | 69 | /** |
75 | * acpiphp_init_context - Create hotplug context and grab a reference to it. | 70 | * acpiphp_init_context - Create hotplug context and grab a reference to it. |
76 | * @handle: ACPI object handle to create the context for. | 71 | * @adev: ACPI device object to create the context for. |
77 | * | 72 | * |
78 | * Call under acpiphp_context_lock. | 73 | * Call under acpi_hp_context_lock. |
79 | */ | 74 | */ |
80 | static struct acpiphp_context *acpiphp_init_context(acpi_handle handle) | 75 | static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev) |
81 | { | 76 | { |
82 | struct acpiphp_context *context; | 77 | struct acpiphp_context *context; |
83 | acpi_status status; | ||
84 | 78 | ||
85 | context = kzalloc(sizeof(*context), GFP_KERNEL); | 79 | context = kzalloc(sizeof(*context), GFP_KERNEL); |
86 | if (!context) | 80 | if (!context) |
87 | return NULL; | 81 | return NULL; |
88 | 82 | ||
89 | context->handle = handle; | ||
90 | context->refcount = 1; | 83 | context->refcount = 1; |
91 | status = acpi_attach_data(handle, acpiphp_context_handler, context); | 84 | acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_notify, NULL, |
92 | if (ACPI_FAILURE(status)) { | 85 | acpiphp_post_dock_fixup); |
93 | kfree(context); | ||
94 | return NULL; | ||
95 | } | ||
96 | return context; | 86 | return context; |
97 | } | 87 | } |
98 | 88 | ||
99 | /** | 89 | /** |
100 | * acpiphp_get_context - Get hotplug context and grab a reference to it. | 90 | * acpiphp_get_context - Get hotplug context and grab a reference to it. |
101 | * @handle: ACPI object handle to get the context for. | 91 | * @adev: ACPI device object to get the context for. |
102 | * | 92 | * |
103 | * Call under acpiphp_context_lock. | 93 | * Call under acpi_hp_context_lock. |
104 | */ | 94 | */ |
105 | static struct acpiphp_context *acpiphp_get_context(acpi_handle handle) | 95 | static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev) |
106 | { | 96 | { |
107 | struct acpiphp_context *context = NULL; | 97 | struct acpiphp_context *context; |
108 | acpi_status status; | ||
109 | void *data; | ||
110 | 98 | ||
111 | status = acpi_get_data(handle, acpiphp_context_handler, &data); | 99 | if (!adev->hp) |
112 | if (ACPI_SUCCESS(status)) { | 100 | return NULL; |
113 | context = data; | 101 | |
114 | context->refcount++; | 102 | context = to_acpiphp_context(adev->hp); |
115 | } | 103 | context->refcount++; |
116 | return context; | 104 | return context; |
117 | } | 105 | } |
118 | 106 | ||
119 | /** | 107 | /** |
120 | * acpiphp_put_context - Drop a reference to ACPI hotplug context. | 108 | * acpiphp_put_context - Drop a reference to ACPI hotplug context. |
121 | * @handle: ACPI object handle to put the context for. | 109 | * @context: ACPI hotplug context to drop a reference to. |
122 | * | 110 | * |
123 | * The context object is removed if there are no more references to it. | 111 | * The context object is removed if there are no more references to it. |
124 | * | 112 | * |
125 | * Call under acpiphp_context_lock. | 113 | * Call under acpi_hp_context_lock. |
126 | */ | 114 | */ |
127 | static void acpiphp_put_context(struct acpiphp_context *context) | 115 | static void acpiphp_put_context(struct acpiphp_context *context) |
128 | { | 116 | { |
@@ -130,7 +118,7 @@ static void acpiphp_put_context(struct acpiphp_context *context) | |||
130 | return; | 118 | return; |
131 | 119 | ||
132 | WARN_ON(context->bridge); | 120 | WARN_ON(context->bridge); |
133 | acpi_detach_data(context->handle, acpiphp_context_handler); | 121 | context->hp.self->hp = NULL; |
134 | kfree(context); | 122 | kfree(context); |
135 | } | 123 | } |
136 | 124 | ||
@@ -144,6 +132,27 @@ static inline void put_bridge(struct acpiphp_bridge *bridge) | |||
144 | kref_put(&bridge->ref, free_bridge); | 132 | kref_put(&bridge->ref, free_bridge); |
145 | } | 133 | } |
146 | 134 | ||
135 | static struct acpiphp_context *acpiphp_grab_context(struct acpi_device *adev) | ||
136 | { | ||
137 | struct acpiphp_context *context; | ||
138 | |||
139 | acpi_lock_hp_context(); | ||
140 | context = acpiphp_get_context(adev); | ||
141 | if (!context || context->func.parent->is_going_away) { | ||
142 | acpi_unlock_hp_context(); | ||
143 | return NULL; | ||
144 | } | ||
145 | get_bridge(context->func.parent); | ||
146 | acpiphp_put_context(context); | ||
147 | acpi_unlock_hp_context(); | ||
148 | return context; | ||
149 | } | ||
150 | |||
151 | static void acpiphp_let_context_go(struct acpiphp_context *context) | ||
152 | { | ||
153 | put_bridge(context->func.parent); | ||
154 | } | ||
155 | |||
147 | static void free_bridge(struct kref *kref) | 156 | static void free_bridge(struct kref *kref) |
148 | { | 157 | { |
149 | struct acpiphp_context *context; | 158 | struct acpiphp_context *context; |
@@ -151,7 +160,7 @@ static void free_bridge(struct kref *kref) | |||
151 | struct acpiphp_slot *slot, *next; | 160 | struct acpiphp_slot *slot, *next; |
152 | struct acpiphp_func *func, *tmp; | 161 | struct acpiphp_func *func, *tmp; |
153 | 162 | ||
154 | mutex_lock(&acpiphp_context_lock); | 163 | acpi_lock_hp_context(); |
155 | 164 | ||
156 | bridge = container_of(kref, struct acpiphp_bridge, ref); | 165 | bridge = container_of(kref, struct acpiphp_bridge, ref); |
157 | 166 | ||
@@ -175,31 +184,32 @@ static void free_bridge(struct kref *kref) | |||
175 | pci_dev_put(bridge->pci_dev); | 184 | pci_dev_put(bridge->pci_dev); |
176 | kfree(bridge); | 185 | kfree(bridge); |
177 | 186 | ||
178 | mutex_unlock(&acpiphp_context_lock); | 187 | acpi_unlock_hp_context(); |
179 | } | 188 | } |
180 | 189 | ||
181 | /* | 190 | /** |
182 | * the _DCK method can do funny things... and sometimes not | 191 | * acpiphp_post_dock_fixup - Post-dock fixups for PCI devices. |
183 | * hah-hah funny. | 192 | * @adev: ACPI device object corresponding to a PCI device. |
184 | * | 193 | * |
185 | * TBD - figure out a way to only call fixups for | 194 | * TBD - figure out a way to only call fixups for systems that require them. |
186 | * systems that require them. | ||
187 | */ | 195 | */ |
188 | static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) | 196 | static void acpiphp_post_dock_fixup(struct acpi_device *adev) |
189 | { | 197 | { |
190 | struct acpiphp_context *context = data; | 198 | struct acpiphp_context *context = acpiphp_grab_context(adev); |
191 | struct pci_bus *bus = context->func.slot->bus; | 199 | struct pci_bus *bus; |
192 | u32 buses; | 200 | u32 buses; |
193 | 201 | ||
194 | if (!bus->self) | 202 | if (!context) |
195 | return; | 203 | return; |
196 | 204 | ||
205 | bus = context->func.slot->bus; | ||
206 | if (!bus->self) | ||
207 | goto out; | ||
208 | |||
197 | /* fixup bad _DCK function that rewrites | 209 | /* fixup bad _DCK function that rewrites |
198 | * secondary bridge on slot | 210 | * secondary bridge on slot |
199 | */ | 211 | */ |
200 | pci_read_config_dword(bus->self, | 212 | pci_read_config_dword(bus->self, PCI_PRIMARY_BUS, &buses); |
201 | PCI_PRIMARY_BUS, | ||
202 | &buses); | ||
203 | 213 | ||
204 | if (((buses >> 8) & 0xff) != bus->busn_res.start) { | 214 | if (((buses >> 8) & 0xff) != bus->busn_res.start) { |
205 | buses = (buses & 0xff000000) | 215 | buses = (buses & 0xff000000) |
@@ -208,13 +218,10 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) | |||
208 | | ((unsigned int)(bus->busn_res.end) << 16); | 218 | | ((unsigned int)(bus->busn_res.end) << 16); |
209 | pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); | 219 | pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); |
210 | } | 220 | } |
211 | } | ||
212 | |||
213 | 221 | ||
214 | static const struct acpi_dock_ops acpiphp_dock_ops = { | 222 | out: |
215 | .fixup = post_dock_fixups, | 223 | acpiphp_let_context_go(context); |
216 | .handler = hotplug_event, | 224 | } |
217 | }; | ||
218 | 225 | ||
219 | /* Check whether the PCI device is managed by native PCIe hotplug driver */ | 226 | /* Check whether the PCI device is managed by native PCIe hotplug driver */ |
220 | static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) | 227 | static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) |
@@ -245,26 +252,19 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) | |||
245 | return true; | 252 | return true; |
246 | } | 253 | } |
247 | 254 | ||
248 | static void acpiphp_dock_init(void *data) | 255 | /** |
249 | { | 256 | * acpiphp_add_context - Add ACPIPHP context to an ACPI device object. |
250 | struct acpiphp_context *context = data; | 257 | * @handle: ACPI handle of the object to add a context to. |
251 | 258 | * @lvl: Not used. | |
252 | get_bridge(context->func.parent); | 259 | * @data: The object's parent ACPIPHP bridge. |
253 | } | 260 | * @rv: Not used. |
254 | 261 | */ | |
255 | static void acpiphp_dock_release(void *data) | 262 | static acpi_status acpiphp_add_context(acpi_handle handle, u32 lvl, void *data, |
256 | { | 263 | void **rv) |
257 | struct acpiphp_context *context = data; | ||
258 | |||
259 | put_bridge(context->func.parent); | ||
260 | } | ||
261 | |||
262 | /* callback routine to register each ACPI PCI slot object */ | ||
263 | static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, | ||
264 | void **rv) | ||
265 | { | 264 | { |
266 | struct acpiphp_bridge *bridge = data; | 265 | struct acpiphp_bridge *bridge = data; |
267 | struct acpiphp_context *context; | 266 | struct acpiphp_context *context; |
267 | struct acpi_device *adev; | ||
268 | struct acpiphp_slot *slot; | 268 | struct acpiphp_slot *slot; |
269 | struct acpiphp_func *newfunc; | 269 | struct acpiphp_func *newfunc; |
270 | acpi_status status = AE_OK; | 270 | acpi_status status = AE_OK; |
@@ -274,9 +274,6 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, | |||
274 | struct pci_dev *pdev = bridge->pci_dev; | 274 | struct pci_dev *pdev = bridge->pci_dev; |
275 | u32 val; | 275 | u32 val; |
276 | 276 | ||
277 | if (pdev && device_is_managed_by_native_pciehp(pdev)) | ||
278 | return AE_OK; | ||
279 | |||
280 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); | 277 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); |
281 | if (ACPI_FAILURE(status)) { | 278 | if (ACPI_FAILURE(status)) { |
282 | if (status != AE_NOT_FOUND) | 279 | if (status != AE_NOT_FOUND) |
@@ -284,31 +281,34 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, | |||
284 | "can't evaluate _ADR (%#x)\n", status); | 281 | "can't evaluate _ADR (%#x)\n", status); |
285 | return AE_OK; | 282 | return AE_OK; |
286 | } | 283 | } |
284 | if (acpi_bus_get_device(handle, &adev)) | ||
285 | return AE_OK; | ||
287 | 286 | ||
288 | device = (adr >> 16) & 0xffff; | 287 | device = (adr >> 16) & 0xffff; |
289 | function = adr & 0xffff; | 288 | function = adr & 0xffff; |
290 | 289 | ||
291 | mutex_lock(&acpiphp_context_lock); | 290 | acpi_lock_hp_context(); |
292 | context = acpiphp_init_context(handle); | 291 | context = acpiphp_init_context(adev); |
293 | if (!context) { | 292 | if (!context) { |
294 | mutex_unlock(&acpiphp_context_lock); | 293 | acpi_unlock_hp_context(); |
295 | acpi_handle_err(handle, "No hotplug context\n"); | 294 | acpi_handle_err(handle, "No hotplug context\n"); |
296 | return AE_NOT_EXIST; | 295 | return AE_NOT_EXIST; |
297 | } | 296 | } |
298 | newfunc = &context->func; | 297 | newfunc = &context->func; |
299 | newfunc->function = function; | 298 | newfunc->function = function; |
300 | newfunc->parent = bridge; | 299 | newfunc->parent = bridge; |
301 | mutex_unlock(&acpiphp_context_lock); | 300 | acpi_unlock_hp_context(); |
302 | 301 | ||
303 | if (acpi_has_method(handle, "_EJ0")) | 302 | /* |
303 | * If this is a dock device, its _EJ0 should be executed by the dock | ||
304 | * notify handler after calling _DCK. | ||
305 | */ | ||
306 | if (!is_dock_device(adev) && acpi_has_method(handle, "_EJ0")) | ||
304 | newfunc->flags = FUNC_HAS_EJ0; | 307 | newfunc->flags = FUNC_HAS_EJ0; |
305 | 308 | ||
306 | if (acpi_has_method(handle, "_STA")) | 309 | if (acpi_has_method(handle, "_STA")) |
307 | newfunc->flags |= FUNC_HAS_STA; | 310 | newfunc->flags |= FUNC_HAS_STA; |
308 | 311 | ||
309 | if (acpi_has_method(handle, "_DCK")) | ||
310 | newfunc->flags |= FUNC_HAS_DCK; | ||
311 | |||
312 | /* search for objects that share the same slot */ | 312 | /* search for objects that share the same slot */ |
313 | list_for_each_entry(slot, &bridge->slots, node) | 313 | list_for_each_entry(slot, &bridge->slots, node) |
314 | if (slot->device == device) | 314 | if (slot->device == device) |
@@ -316,19 +316,26 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, | |||
316 | 316 | ||
317 | slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); | 317 | slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); |
318 | if (!slot) { | 318 | if (!slot) { |
319 | status = AE_NO_MEMORY; | 319 | acpi_lock_hp_context(); |
320 | goto err; | 320 | acpiphp_put_context(context); |
321 | acpi_unlock_hp_context(); | ||
322 | return AE_NO_MEMORY; | ||
321 | } | 323 | } |
322 | 324 | ||
323 | slot->bus = bridge->pci_bus; | 325 | slot->bus = bridge->pci_bus; |
324 | slot->device = device; | 326 | slot->device = device; |
325 | INIT_LIST_HEAD(&slot->funcs); | 327 | INIT_LIST_HEAD(&slot->funcs); |
326 | mutex_init(&slot->crit_sect); | ||
327 | 328 | ||
328 | list_add_tail(&slot->node, &bridge->slots); | 329 | list_add_tail(&slot->node, &bridge->slots); |
329 | 330 | ||
330 | /* Register slots for ejectable functions only. */ | 331 | /* |
331 | if (acpi_pci_check_ejectable(pbus, handle) || is_dock_device(handle)) { | 332 | * Expose slots to user space for functions that have _EJ0 or _RMV or |
333 | * are located in dock stations. Do not expose them for devices handled | ||
334 | * by the native PCIe hotplug (PCIeHP), becuase that code is supposed to | ||
335 | * expose slots to user space in those cases. | ||
336 | */ | ||
337 | if ((acpi_pci_check_ejectable(pbus, handle) || is_dock_device(adev)) | ||
338 | && !(pdev && device_is_managed_by_native_pciehp(pdev))) { | ||
332 | unsigned long long sun; | 339 | unsigned long long sun; |
333 | int retval; | 340 | int retval; |
334 | 341 | ||
@@ -362,44 +369,16 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, | |||
362 | &val, 60*1000)) | 369 | &val, 60*1000)) |
363 | slot->flags |= SLOT_ENABLED; | 370 | slot->flags |= SLOT_ENABLED; |
364 | 371 | ||
365 | if (is_dock_device(handle)) { | ||
366 | /* we don't want to call this device's _EJ0 | ||
367 | * because we want the dock notify handler | ||
368 | * to call it after it calls _DCK | ||
369 | */ | ||
370 | newfunc->flags &= ~FUNC_HAS_EJ0; | ||
371 | if (register_hotplug_dock_device(handle, | ||
372 | &acpiphp_dock_ops, context, | ||
373 | acpiphp_dock_init, acpiphp_dock_release)) | ||
374 | pr_debug("failed to register dock device\n"); | ||
375 | } | ||
376 | |||
377 | /* install notify handler */ | ||
378 | if (!(newfunc->flags & FUNC_HAS_DCK)) { | ||
379 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
380 | handle_hotplug_event, | ||
381 | context); | ||
382 | if (ACPI_FAILURE(status)) | ||
383 | acpi_handle_err(handle, | ||
384 | "failed to install notify handler\n"); | ||
385 | } | ||
386 | |||
387 | return AE_OK; | 372 | return AE_OK; |
388 | |||
389 | err: | ||
390 | mutex_lock(&acpiphp_context_lock); | ||
391 | acpiphp_put_context(context); | ||
392 | mutex_unlock(&acpiphp_context_lock); | ||
393 | return status; | ||
394 | } | 373 | } |
395 | 374 | ||
396 | static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) | 375 | static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev) |
397 | { | 376 | { |
398 | struct acpiphp_context *context; | 377 | struct acpiphp_context *context; |
399 | struct acpiphp_bridge *bridge = NULL; | 378 | struct acpiphp_bridge *bridge = NULL; |
400 | 379 | ||
401 | mutex_lock(&acpiphp_context_lock); | 380 | acpi_lock_hp_context(); |
402 | context = acpiphp_get_context(handle); | 381 | context = acpiphp_get_context(adev); |
403 | if (context) { | 382 | if (context) { |
404 | bridge = context->bridge; | 383 | bridge = context->bridge; |
405 | if (bridge) | 384 | if (bridge) |
@@ -407,7 +386,7 @@ static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) | |||
407 | 386 | ||
408 | acpiphp_put_context(context); | 387 | acpiphp_put_context(context); |
409 | } | 388 | } |
410 | mutex_unlock(&acpiphp_context_lock); | 389 | acpi_unlock_hp_context(); |
411 | return bridge; | 390 | return bridge; |
412 | } | 391 | } |
413 | 392 | ||
@@ -415,22 +394,15 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
415 | { | 394 | { |
416 | struct acpiphp_slot *slot; | 395 | struct acpiphp_slot *slot; |
417 | struct acpiphp_func *func; | 396 | struct acpiphp_func *func; |
418 | acpi_status status; | ||
419 | 397 | ||
420 | list_for_each_entry(slot, &bridge->slots, node) { | 398 | list_for_each_entry(slot, &bridge->slots, node) { |
421 | list_for_each_entry(func, &slot->funcs, sibling) { | 399 | list_for_each_entry(func, &slot->funcs, sibling) { |
422 | acpi_handle handle = func_to_handle(func); | 400 | struct acpi_device *adev = func_to_acpi_device(func); |
423 | |||
424 | if (is_dock_device(handle)) | ||
425 | unregister_hotplug_dock_device(handle); | ||
426 | 401 | ||
427 | if (!(func->flags & FUNC_HAS_DCK)) { | 402 | acpi_lock_hp_context(); |
428 | status = acpi_remove_notify_handler(handle, | 403 | adev->hp->notify = NULL; |
429 | ACPI_SYSTEM_NOTIFY, | 404 | adev->hp->fixup = NULL; |
430 | handle_hotplug_event); | 405 | acpi_unlock_hp_context(); |
431 | if (ACPI_FAILURE(status)) | ||
432 | pr_err("failed to remove notify handler\n"); | ||
433 | } | ||
434 | } | 406 | } |
435 | slot->flags |= SLOT_IS_GOING_AWAY; | 407 | slot->flags |= SLOT_IS_GOING_AWAY; |
436 | if (slot->slot) | 408 | if (slot->slot) |
@@ -441,7 +413,9 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
441 | list_del(&bridge->list); | 413 | list_del(&bridge->list); |
442 | mutex_unlock(&bridge_mutex); | 414 | mutex_unlock(&bridge_mutex); |
443 | 415 | ||
416 | acpi_lock_hp_context(); | ||
444 | bridge->is_going_away = true; | 417 | bridge->is_going_away = true; |
418 | acpi_unlock_hp_context(); | ||
445 | } | 419 | } |
446 | 420 | ||
447 | /** | 421 | /** |
@@ -471,33 +445,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) | |||
471 | return max; | 445 | return max; |
472 | } | 446 | } |
473 | 447 | ||
474 | /** | ||
475 | * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree. | ||
476 | * @handle: ACPI device object handle to start from. | ||
477 | */ | ||
478 | static void acpiphp_bus_trim(acpi_handle handle) | ||
479 | { | ||
480 | struct acpi_device *adev = NULL; | ||
481 | |||
482 | acpi_bus_get_device(handle, &adev); | ||
483 | if (adev) | ||
484 | acpi_bus_trim(adev); | ||
485 | } | ||
486 | |||
487 | /** | ||
488 | * acpiphp_bus_add - Scan ACPI namespace subtree. | ||
489 | * @handle: ACPI object handle to start the scan from. | ||
490 | */ | ||
491 | static void acpiphp_bus_add(acpi_handle handle) | ||
492 | { | ||
493 | struct acpi_device *adev = NULL; | ||
494 | |||
495 | acpi_bus_scan(handle); | ||
496 | acpi_bus_get_device(handle, &adev); | ||
497 | if (acpi_device_enumerated(adev)) | ||
498 | acpi_device_set_power(adev, ACPI_STATE_D0); | ||
499 | } | ||
500 | |||
501 | static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) | 448 | static void acpiphp_set_acpi_region(struct acpiphp_slot *slot) |
502 | { | 449 | { |
503 | struct acpiphp_func *func; | 450 | struct acpiphp_func *func; |
@@ -537,9 +484,13 @@ static int acpiphp_rescan_slot(struct acpiphp_slot *slot) | |||
537 | { | 484 | { |
538 | struct acpiphp_func *func; | 485 | struct acpiphp_func *func; |
539 | 486 | ||
540 | list_for_each_entry(func, &slot->funcs, sibling) | 487 | list_for_each_entry(func, &slot->funcs, sibling) { |
541 | acpiphp_bus_add(func_to_handle(func)); | 488 | struct acpi_device *adev = func_to_acpi_device(func); |
542 | 489 | ||
490 | acpi_bus_scan(adev->handle); | ||
491 | if (acpi_device_enumerated(adev)) | ||
492 | acpi_device_set_power(adev, ACPI_STATE_D0); | ||
493 | } | ||
543 | return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0)); | 494 | return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0)); |
544 | } | 495 | } |
545 | 496 | ||
@@ -604,32 +555,15 @@ static void __ref enable_slot(struct acpiphp_slot *slot) | |||
604 | } | 555 | } |
605 | } | 556 | } |
606 | 557 | ||
607 | /* return first device in slot, acquiring a reference on it */ | ||
608 | static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot) | ||
609 | { | ||
610 | struct pci_bus *bus = slot->bus; | ||
611 | struct pci_dev *dev; | ||
612 | struct pci_dev *ret = NULL; | ||
613 | |||
614 | down_read(&pci_bus_sem); | ||
615 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
616 | if (PCI_SLOT(dev->devfn) == slot->device) { | ||
617 | ret = pci_dev_get(dev); | ||
618 | break; | ||
619 | } | ||
620 | up_read(&pci_bus_sem); | ||
621 | |||
622 | return ret; | ||
623 | } | ||
624 | |||
625 | /** | 558 | /** |
626 | * disable_slot - disable a slot | 559 | * disable_slot - disable a slot |
627 | * @slot: ACPI PHP slot | 560 | * @slot: ACPI PHP slot |
628 | */ | 561 | */ |
629 | static void disable_slot(struct acpiphp_slot *slot) | 562 | static void disable_slot(struct acpiphp_slot *slot) |
630 | { | 563 | { |
564 | struct pci_bus *bus = slot->bus; | ||
565 | struct pci_dev *dev, *prev; | ||
631 | struct acpiphp_func *func; | 566 | struct acpiphp_func *func; |
632 | struct pci_dev *pdev; | ||
633 | 567 | ||
634 | /* | 568 | /* |
635 | * enable_slot() enumerates all functions in this device via | 569 | * enable_slot() enumerates all functions in this device via |
@@ -637,22 +571,18 @@ static void disable_slot(struct acpiphp_slot *slot) | |||
637 | * methods (_EJ0, etc.) or not. Therefore, we remove all functions | 571 | * methods (_EJ0, etc.) or not. Therefore, we remove all functions |
638 | * here. | 572 | * here. |
639 | */ | 573 | */ |
640 | while ((pdev = dev_in_slot(slot))) { | 574 | list_for_each_entry_safe_reverse(dev, prev, &bus->devices, bus_list) |
641 | pci_stop_and_remove_bus_device(pdev); | 575 | if (PCI_SLOT(dev->devfn) == slot->device) |
642 | pci_dev_put(pdev); | 576 | pci_stop_and_remove_bus_device(dev); |
643 | } | ||
644 | 577 | ||
645 | list_for_each_entry(func, &slot->funcs, sibling) | 578 | list_for_each_entry(func, &slot->funcs, sibling) |
646 | acpiphp_bus_trim(func_to_handle(func)); | 579 | acpi_bus_trim(func_to_acpi_device(func)); |
647 | 580 | ||
648 | slot->flags &= (~SLOT_ENABLED); | 581 | slot->flags &= (~SLOT_ENABLED); |
649 | } | 582 | } |
650 | 583 | ||
651 | static bool acpiphp_no_hotplug(acpi_handle handle) | 584 | static bool acpiphp_no_hotplug(struct acpi_device *adev) |
652 | { | 585 | { |
653 | struct acpi_device *adev = NULL; | ||
654 | |||
655 | acpi_bus_get_device(handle, &adev); | ||
656 | return adev && adev->flags.no_hotplug; | 586 | return adev && adev->flags.no_hotplug; |
657 | } | 587 | } |
658 | 588 | ||
@@ -661,7 +591,7 @@ static bool slot_no_hotplug(struct acpiphp_slot *slot) | |||
661 | struct acpiphp_func *func; | 591 | struct acpiphp_func *func; |
662 | 592 | ||
663 | list_for_each_entry(func, &slot->funcs, sibling) | 593 | list_for_each_entry(func, &slot->funcs, sibling) |
664 | if (acpiphp_no_hotplug(func_to_handle(func))) | 594 | if (acpiphp_no_hotplug(func_to_acpi_device(func))) |
665 | return true; | 595 | return true; |
666 | 596 | ||
667 | return false; | 597 | return false; |
@@ -709,40 +639,48 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot) | |||
709 | return (unsigned int)sta; | 639 | return (unsigned int)sta; |
710 | } | 640 | } |
711 | 641 | ||
642 | static inline bool device_status_valid(unsigned int sta) | ||
643 | { | ||
644 | /* | ||
645 | * ACPI spec says that _STA may return bit 0 clear with bit 3 set | ||
646 | * if the device is valid but does not require a device driver to be | ||
647 | * loaded (Section 6.3.7 of ACPI 5.0A). | ||
648 | */ | ||
649 | unsigned int mask = ACPI_STA_DEVICE_ENABLED | ACPI_STA_DEVICE_FUNCTIONING; | ||
650 | return (sta & mask) == mask; | ||
651 | } | ||
652 | |||
712 | /** | 653 | /** |
713 | * trim_stale_devices - remove PCI devices that are not responding. | 654 | * trim_stale_devices - remove PCI devices that are not responding. |
714 | * @dev: PCI device to start walking the hierarchy from. | 655 | * @dev: PCI device to start walking the hierarchy from. |
715 | */ | 656 | */ |
716 | static void trim_stale_devices(struct pci_dev *dev) | 657 | static void trim_stale_devices(struct pci_dev *dev) |
717 | { | 658 | { |
718 | acpi_handle handle = ACPI_HANDLE(&dev->dev); | 659 | struct acpi_device *adev = ACPI_COMPANION(&dev->dev); |
719 | struct pci_bus *bus = dev->subordinate; | 660 | struct pci_bus *bus = dev->subordinate; |
720 | bool alive = false; | 661 | bool alive = false; |
721 | 662 | ||
722 | if (handle) { | 663 | if (adev) { |
723 | acpi_status status; | 664 | acpi_status status; |
724 | unsigned long long sta; | 665 | unsigned long long sta; |
725 | 666 | ||
726 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | 667 | status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); |
727 | alive = (ACPI_SUCCESS(status) && sta == ACPI_STA_ALL) | 668 | alive = (ACPI_SUCCESS(status) && device_status_valid(sta)) |
728 | || acpiphp_no_hotplug(handle); | 669 | || acpiphp_no_hotplug(adev); |
729 | } | 670 | } |
730 | if (!alive) { | 671 | if (!alive) |
731 | u32 v; | 672 | alive = pci_device_is_present(dev); |
732 | 673 | ||
733 | /* Check if the device responds. */ | ||
734 | alive = pci_bus_read_dev_vendor_id(dev->bus, dev->devfn, &v, 0); | ||
735 | } | ||
736 | if (!alive) { | 674 | if (!alive) { |
737 | pci_stop_and_remove_bus_device(dev); | 675 | pci_stop_and_remove_bus_device(dev); |
738 | if (handle) | 676 | if (adev) |
739 | acpiphp_bus_trim(handle); | 677 | acpi_bus_trim(adev); |
740 | } else if (bus) { | 678 | } else if (bus) { |
741 | struct pci_dev *child, *tmp; | 679 | struct pci_dev *child, *tmp; |
742 | 680 | ||
743 | /* The device is a bridge. so check the bus below it. */ | 681 | /* The device is a bridge. so check the bus below it. */ |
744 | pm_runtime_get_sync(&dev->dev); | 682 | pm_runtime_get_sync(&dev->dev); |
745 | list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) | 683 | list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list) |
746 | trim_stale_devices(child); | 684 | trim_stale_devices(child); |
747 | 685 | ||
748 | pm_runtime_put(&dev->dev); | 686 | pm_runtime_put(&dev->dev); |
@@ -768,13 +706,12 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
768 | struct pci_bus *bus = slot->bus; | 706 | struct pci_bus *bus = slot->bus; |
769 | struct pci_dev *dev, *tmp; | 707 | struct pci_dev *dev, *tmp; |
770 | 708 | ||
771 | mutex_lock(&slot->crit_sect); | ||
772 | if (slot_no_hotplug(slot)) { | 709 | if (slot_no_hotplug(slot)) { |
773 | ; /* do nothing */ | 710 | ; /* do nothing */ |
774 | } else if (get_slot_status(slot) == ACPI_STA_ALL) { | 711 | } else if (device_status_valid(get_slot_status(slot))) { |
775 | /* remove stale devices if any */ | 712 | /* remove stale devices if any */ |
776 | list_for_each_entry_safe(dev, tmp, &bus->devices, | 713 | list_for_each_entry_safe_reverse(dev, tmp, |
777 | bus_list) | 714 | &bus->devices, bus_list) |
778 | if (PCI_SLOT(dev->devfn) == slot->device) | 715 | if (PCI_SLOT(dev->devfn) == slot->device) |
779 | trim_stale_devices(dev); | 716 | trim_stale_devices(dev); |
780 | 717 | ||
@@ -783,7 +720,6 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
783 | } else { | 720 | } else { |
784 | disable_slot(slot); | 721 | disable_slot(slot); |
785 | } | 722 | } |
786 | mutex_unlock(&slot->crit_sect); | ||
787 | } | 723 | } |
788 | } | 724 | } |
789 | 725 | ||
@@ -805,7 +741,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) | |||
805 | int i; | 741 | int i; |
806 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; | 742 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; |
807 | 743 | ||
808 | list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { | 744 | list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) { |
809 | for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { | 745 | for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { |
810 | struct resource *res = &dev->resource[i]; | 746 | struct resource *res = &dev->resource[i]; |
811 | if ((res->flags & type_mask) && !res->start && | 747 | if ((res->flags & type_mask) && !res->start && |
@@ -823,186 +759,112 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) | |||
823 | * ACPI event handlers | 759 | * ACPI event handlers |
824 | */ | 760 | */ |
825 | 761 | ||
826 | void acpiphp_check_host_bridge(acpi_handle handle) | 762 | void acpiphp_check_host_bridge(struct acpi_device *adev) |
827 | { | 763 | { |
828 | struct acpiphp_bridge *bridge; | 764 | struct acpiphp_bridge *bridge; |
829 | 765 | ||
830 | bridge = acpiphp_handle_to_bridge(handle); | 766 | bridge = acpiphp_dev_to_bridge(adev); |
831 | if (bridge) { | 767 | if (bridge) { |
768 | pci_lock_rescan_remove(); | ||
769 | |||
832 | acpiphp_check_bridge(bridge); | 770 | acpiphp_check_bridge(bridge); |
771 | |||
772 | pci_unlock_rescan_remove(); | ||
833 | put_bridge(bridge); | 773 | put_bridge(bridge); |
834 | } | 774 | } |
835 | } | 775 | } |
836 | 776 | ||
837 | static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); | 777 | static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); |
838 | 778 | ||
839 | static void hotplug_event(acpi_handle handle, u32 type, void *data) | 779 | static void hotplug_event(u32 type, struct acpiphp_context *context) |
840 | { | 780 | { |
841 | struct acpiphp_context *context = data; | 781 | acpi_handle handle = context->hp.self->handle; |
842 | struct acpiphp_func *func = &context->func; | 782 | struct acpiphp_func *func = &context->func; |
783 | struct acpiphp_slot *slot = func->slot; | ||
843 | struct acpiphp_bridge *bridge; | 784 | struct acpiphp_bridge *bridge; |
844 | char objname[64]; | ||
845 | struct acpi_buffer buffer = { .length = sizeof(objname), | ||
846 | .pointer = objname }; | ||
847 | 785 | ||
848 | mutex_lock(&acpiphp_context_lock); | 786 | acpi_lock_hp_context(); |
849 | bridge = context->bridge; | 787 | bridge = context->bridge; |
850 | if (bridge) | 788 | if (bridge) |
851 | get_bridge(bridge); | 789 | get_bridge(bridge); |
852 | 790 | ||
853 | mutex_unlock(&acpiphp_context_lock); | 791 | acpi_unlock_hp_context(); |
854 | 792 | ||
855 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 793 | pci_lock_rescan_remove(); |
856 | 794 | ||
857 | switch (type) { | 795 | switch (type) { |
858 | case ACPI_NOTIFY_BUS_CHECK: | 796 | case ACPI_NOTIFY_BUS_CHECK: |
859 | /* bus re-enumerate */ | 797 | /* bus re-enumerate */ |
860 | pr_debug("%s: Bus check notify on %s\n", __func__, objname); | 798 | acpi_handle_debug(handle, "Bus check in %s()\n", __func__); |
861 | pr_debug("%s: re-enumerating slots under %s\n", | 799 | if (bridge) |
862 | __func__, objname); | ||
863 | if (bridge) { | ||
864 | acpiphp_check_bridge(bridge); | 800 | acpiphp_check_bridge(bridge); |
865 | } else { | 801 | else if (!(slot->flags & SLOT_IS_GOING_AWAY)) |
866 | struct acpiphp_slot *slot = func->slot; | ||
867 | |||
868 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
869 | break; | ||
870 | |||
871 | mutex_lock(&slot->crit_sect); | ||
872 | enable_slot(slot); | 802 | enable_slot(slot); |
873 | mutex_unlock(&slot->crit_sect); | 803 | |
874 | } | ||
875 | break; | 804 | break; |
876 | 805 | ||
877 | case ACPI_NOTIFY_DEVICE_CHECK: | 806 | case ACPI_NOTIFY_DEVICE_CHECK: |
878 | /* device check */ | 807 | /* device check */ |
879 | pr_debug("%s: Device check notify on %s\n", __func__, objname); | 808 | acpi_handle_debug(handle, "Device check in %s()\n", __func__); |
880 | if (bridge) { | 809 | if (bridge) { |
881 | acpiphp_check_bridge(bridge); | 810 | acpiphp_check_bridge(bridge); |
882 | } else { | 811 | } else if (!(slot->flags & SLOT_IS_GOING_AWAY)) { |
883 | struct acpiphp_slot *slot = func->slot; | ||
884 | int ret; | ||
885 | |||
886 | if (slot->flags & SLOT_IS_GOING_AWAY) | ||
887 | break; | ||
888 | |||
889 | /* | 812 | /* |
890 | * Check if anything has changed in the slot and rescan | 813 | * Check if anything has changed in the slot and rescan |
891 | * from the parent if that's the case. | 814 | * from the parent if that's the case. |
892 | */ | 815 | */ |
893 | mutex_lock(&slot->crit_sect); | 816 | if (acpiphp_rescan_slot(slot)) |
894 | ret = acpiphp_rescan_slot(slot); | ||
895 | mutex_unlock(&slot->crit_sect); | ||
896 | if (ret) | ||
897 | acpiphp_check_bridge(func->parent); | 817 | acpiphp_check_bridge(func->parent); |
898 | } | 818 | } |
899 | break; | 819 | break; |
900 | 820 | ||
901 | case ACPI_NOTIFY_EJECT_REQUEST: | 821 | case ACPI_NOTIFY_EJECT_REQUEST: |
902 | /* request device eject */ | 822 | /* request device eject */ |
903 | pr_debug("%s: Device eject notify on %s\n", __func__, objname); | 823 | acpi_handle_debug(handle, "Eject request in %s()\n", __func__); |
904 | acpiphp_disable_and_eject_slot(func->slot); | 824 | acpiphp_disable_and_eject_slot(slot); |
905 | break; | 825 | break; |
906 | } | 826 | } |
907 | 827 | ||
828 | pci_unlock_rescan_remove(); | ||
908 | if (bridge) | 829 | if (bridge) |
909 | put_bridge(bridge); | 830 | put_bridge(bridge); |
910 | } | 831 | } |
911 | 832 | ||
912 | static void hotplug_event_work(void *data, u32 type) | 833 | static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type) |
913 | { | 834 | { |
914 | struct acpiphp_context *context = data; | 835 | struct acpiphp_context *context; |
915 | acpi_handle handle = context->handle; | ||
916 | |||
917 | acpi_scan_lock_acquire(); | ||
918 | pci_lock_rescan_remove(); | ||
919 | 836 | ||
920 | hotplug_event(handle, type, context); | 837 | context = acpiphp_grab_context(adev); |
838 | if (!context) | ||
839 | return -ENODATA; | ||
921 | 840 | ||
922 | pci_unlock_rescan_remove(); | 841 | hotplug_event(type, context); |
923 | acpi_scan_lock_release(); | 842 | acpiphp_let_context_go(context); |
924 | acpi_evaluate_hotplug_ost(handle, type, ACPI_OST_SC_SUCCESS, NULL); | 843 | return 0; |
925 | put_bridge(context->func.parent); | ||
926 | } | 844 | } |
927 | 845 | ||
928 | /** | 846 | /** |
929 | * handle_hotplug_event - handle ACPI hotplug event | 847 | * acpiphp_enumerate_slots - Enumerate PCI slots for a given bus. |
930 | * @handle: Notify()'ed acpi_handle | 848 | * @bus: PCI bus to enumerate the slots for. |
931 | * @type: Notify code | ||
932 | * @data: pointer to acpiphp_context structure | ||
933 | * | 849 | * |
934 | * Handles ACPI event notification on slots. | 850 | * A "slot" is an object associated with a PCI device number. All functions |
935 | */ | 851 | * (PCI devices) with the same bus and device number belong to the same slot. |
936 | static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) | ||
937 | { | ||
938 | struct acpiphp_context *context; | ||
939 | u32 ost_code = ACPI_OST_SC_SUCCESS; | ||
940 | |||
941 | switch (type) { | ||
942 | case ACPI_NOTIFY_BUS_CHECK: | ||
943 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
944 | break; | ||
945 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
946 | ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS; | ||
947 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | ||
948 | break; | ||
949 | |||
950 | case ACPI_NOTIFY_DEVICE_WAKE: | ||
951 | return; | ||
952 | |||
953 | case ACPI_NOTIFY_FREQUENCY_MISMATCH: | ||
954 | acpi_handle_err(handle, "Device cannot be configured due " | ||
955 | "to a frequency mismatch\n"); | ||
956 | goto out; | ||
957 | |||
958 | case ACPI_NOTIFY_BUS_MODE_MISMATCH: | ||
959 | acpi_handle_err(handle, "Device cannot be configured due " | ||
960 | "to a bus mode mismatch\n"); | ||
961 | goto out; | ||
962 | |||
963 | case ACPI_NOTIFY_POWER_FAULT: | ||
964 | acpi_handle_err(handle, "Device has suffered a power fault\n"); | ||
965 | goto out; | ||
966 | |||
967 | default: | ||
968 | acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); | ||
969 | ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; | ||
970 | goto out; | ||
971 | } | ||
972 | |||
973 | mutex_lock(&acpiphp_context_lock); | ||
974 | context = acpiphp_get_context(handle); | ||
975 | if (context && !WARN_ON(context->handle != handle)) { | ||
976 | get_bridge(context->func.parent); | ||
977 | acpiphp_put_context(context); | ||
978 | acpi_hotplug_execute(hotplug_event_work, context, type); | ||
979 | mutex_unlock(&acpiphp_context_lock); | ||
980 | return; | ||
981 | } | ||
982 | mutex_unlock(&acpiphp_context_lock); | ||
983 | ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
984 | |||
985 | out: | ||
986 | acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); | ||
987 | } | ||
988 | |||
989 | /* | ||
990 | * Create hotplug slots for the PCI bus. | ||
991 | * It should always return 0 to avoid skipping following notifiers. | ||
992 | */ | 852 | */ |
993 | void acpiphp_enumerate_slots(struct pci_bus *bus) | 853 | void acpiphp_enumerate_slots(struct pci_bus *bus) |
994 | { | 854 | { |
995 | struct acpiphp_bridge *bridge; | 855 | struct acpiphp_bridge *bridge; |
856 | struct acpi_device *adev; | ||
996 | acpi_handle handle; | 857 | acpi_handle handle; |
997 | acpi_status status; | 858 | acpi_status status; |
998 | 859 | ||
999 | if (acpiphp_disabled) | 860 | if (acpiphp_disabled) |
1000 | return; | 861 | return; |
1001 | 862 | ||
1002 | handle = ACPI_HANDLE(bus->bridge); | 863 | adev = ACPI_COMPANION(bus->bridge); |
1003 | if (!handle) | 864 | if (!adev) |
1004 | return; | 865 | return; |
1005 | 866 | ||
867 | handle = adev->handle; | ||
1006 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); | 868 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); |
1007 | if (!bridge) { | 869 | if (!bridge) { |
1008 | acpi_handle_err(handle, "No memory for bridge object\n"); | 870 | acpi_handle_err(handle, "No memory for bridge object\n"); |
@@ -1030,10 +892,10 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) | |||
1030 | * parent is going to be handled by pciehp, in which case this | 892 | * parent is going to be handled by pciehp, in which case this |
1031 | * bridge is not interesting to us either. | 893 | * bridge is not interesting to us either. |
1032 | */ | 894 | */ |
1033 | mutex_lock(&acpiphp_context_lock); | 895 | acpi_lock_hp_context(); |
1034 | context = acpiphp_get_context(handle); | 896 | context = acpiphp_get_context(adev); |
1035 | if (!context) { | 897 | if (!context) { |
1036 | mutex_unlock(&acpiphp_context_lock); | 898 | acpi_unlock_hp_context(); |
1037 | put_device(&bus->dev); | 899 | put_device(&bus->dev); |
1038 | pci_dev_put(bridge->pci_dev); | 900 | pci_dev_put(bridge->pci_dev); |
1039 | kfree(bridge); | 901 | kfree(bridge); |
@@ -1043,17 +905,17 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) | |||
1043 | context->bridge = bridge; | 905 | context->bridge = bridge; |
1044 | /* Get a reference to the parent bridge. */ | 906 | /* Get a reference to the parent bridge. */ |
1045 | get_bridge(context->func.parent); | 907 | get_bridge(context->func.parent); |
1046 | mutex_unlock(&acpiphp_context_lock); | 908 | acpi_unlock_hp_context(); |
1047 | } | 909 | } |
1048 | 910 | ||
1049 | /* must be added to the list prior to calling register_slot */ | 911 | /* Must be added to the list prior to calling acpiphp_add_context(). */ |
1050 | mutex_lock(&bridge_mutex); | 912 | mutex_lock(&bridge_mutex); |
1051 | list_add(&bridge->list, &bridge_list); | 913 | list_add(&bridge->list, &bridge_list); |
1052 | mutex_unlock(&bridge_mutex); | 914 | mutex_unlock(&bridge_mutex); |
1053 | 915 | ||
1054 | /* register all slot objects under this bridge */ | 916 | /* register all slot objects under this bridge */ |
1055 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | 917 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, |
1056 | register_slot, NULL, bridge, NULL); | 918 | acpiphp_add_context, NULL, bridge, NULL); |
1057 | if (ACPI_FAILURE(status)) { | 919 | if (ACPI_FAILURE(status)) { |
1058 | acpi_handle_err(handle, "failed to register slots\n"); | 920 | acpi_handle_err(handle, "failed to register slots\n"); |
1059 | cleanup_bridge(bridge); | 921 | cleanup_bridge(bridge); |
@@ -1061,7 +923,10 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) | |||
1061 | } | 923 | } |
1062 | } | 924 | } |
1063 | 925 | ||
1064 | /* Destroy hotplug slots associated with the PCI bus */ | 926 | /** |
927 | * acpiphp_remove_slots - Remove slot objects associated with a given bus. | ||
928 | * @bus: PCI bus to remove the slot objects for. | ||
929 | */ | ||
1065 | void acpiphp_remove_slots(struct pci_bus *bus) | 930 | void acpiphp_remove_slots(struct pci_bus *bus) |
1066 | { | 931 | { |
1067 | struct acpiphp_bridge *bridge; | 932 | struct acpiphp_bridge *bridge; |
@@ -1092,13 +957,10 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot) | |||
1092 | if (slot->flags & SLOT_IS_GOING_AWAY) | 957 | if (slot->flags & SLOT_IS_GOING_AWAY) |
1093 | return -ENODEV; | 958 | return -ENODEV; |
1094 | 959 | ||
1095 | mutex_lock(&slot->crit_sect); | ||
1096 | /* configure all functions */ | 960 | /* configure all functions */ |
1097 | if (!(slot->flags & SLOT_ENABLED)) | 961 | if (!(slot->flags & SLOT_ENABLED)) |
1098 | enable_slot(slot); | 962 | enable_slot(slot); |
1099 | 963 | ||
1100 | mutex_unlock(&slot->crit_sect); | ||
1101 | |||
1102 | pci_unlock_rescan_remove(); | 964 | pci_unlock_rescan_remove(); |
1103 | return 0; | 965 | return 0; |
1104 | } | 966 | } |
@@ -1114,8 +976,6 @@ static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) | |||
1114 | if (slot->flags & SLOT_IS_GOING_AWAY) | 976 | if (slot->flags & SLOT_IS_GOING_AWAY) |
1115 | return -ENODEV; | 977 | return -ENODEV; |
1116 | 978 | ||
1117 | mutex_lock(&slot->crit_sect); | ||
1118 | |||
1119 | /* unconfigure all functions */ | 979 | /* unconfigure all functions */ |
1120 | disable_slot(slot); | 980 | disable_slot(slot); |
1121 | 981 | ||
@@ -1129,7 +989,6 @@ static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) | |||
1129 | break; | 989 | break; |
1130 | } | 990 | } |
1131 | 991 | ||
1132 | mutex_unlock(&slot->crit_sect); | ||
1133 | return 0; | 992 | return 0; |
1134 | } | 993 | } |
1135 | 994 | ||
@@ -1137,9 +996,15 @@ int acpiphp_disable_slot(struct acpiphp_slot *slot) | |||
1137 | { | 996 | { |
1138 | int ret; | 997 | int ret; |
1139 | 998 | ||
999 | /* | ||
1000 | * Acquire acpi_scan_lock to ensure that the execution of _EJ0 in | ||
1001 | * acpiphp_disable_and_eject_slot() will be synchronized properly. | ||
1002 | */ | ||
1003 | acpi_scan_lock_acquire(); | ||
1140 | pci_lock_rescan_remove(); | 1004 | pci_lock_rescan_remove(); |
1141 | ret = acpiphp_disable_and_eject_slot(slot); | 1005 | ret = acpiphp_disable_and_eject_slot(slot); |
1142 | pci_unlock_rescan_remove(); | 1006 | pci_unlock_rescan_remove(); |
1007 | acpi_scan_lock_release(); | ||
1143 | return ret; | 1008 | return ret; |
1144 | } | 1009 | } |
1145 | 1010 | ||