diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 531 |
1 files changed, 393 insertions, 138 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f54d1985e594..fe158fd4f1df 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -63,6 +63,19 @@ int acpi_scan_add_handler(struct acpi_scan_handler *handler) | |||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, | ||
67 | const char *hotplug_profile_name) | ||
68 | { | ||
69 | int error; | ||
70 | |||
71 | error = acpi_scan_add_handler(handler); | ||
72 | if (error) | ||
73 | return error; | ||
74 | |||
75 | acpi_sysfs_add_hotplug_profile(&handler->hotplug, hotplug_profile_name); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
66 | /* | 79 | /* |
67 | * Creates hid/cid(s) string needed for modalias and uevent | 80 | * Creates hid/cid(s) string needed for modalias and uevent |
68 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: | 81 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: |
@@ -107,32 +120,20 @@ acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, cha | |||
107 | } | 120 | } |
108 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 121 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
109 | 122 | ||
110 | /** | 123 | static int acpi_scan_hot_remove(struct acpi_device *device) |
111 | * acpi_bus_hot_remove_device: hot-remove a device and its children | ||
112 | * @context: struct acpi_eject_event pointer (freed in this func) | ||
113 | * | ||
114 | * Hot-remove a device and its children. This function frees up the | ||
115 | * memory space passed by arg context, so that the caller may call | ||
116 | * this function asynchronously through acpi_os_hotplug_execute(). | ||
117 | */ | ||
118 | void acpi_bus_hot_remove_device(void *context) | ||
119 | { | 124 | { |
120 | struct acpi_eject_event *ej_event = context; | ||
121 | struct acpi_device *device = ej_event->device; | ||
122 | acpi_handle handle = device->handle; | 125 | acpi_handle handle = device->handle; |
123 | acpi_handle temp; | 126 | acpi_handle not_used; |
124 | struct acpi_object_list arg_list; | 127 | struct acpi_object_list arg_list; |
125 | union acpi_object arg; | 128 | union acpi_object arg; |
126 | acpi_status status = AE_OK; | 129 | acpi_status status; |
127 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */ | 130 | unsigned long long sta; |
128 | |||
129 | mutex_lock(&acpi_scan_lock); | ||
130 | 131 | ||
131 | /* If there is no handle, the device node has been unregistered. */ | 132 | /* If there is no handle, the device node has been unregistered. */ |
132 | if (!device->handle) { | 133 | if (!handle) { |
133 | dev_dbg(&device->dev, "ACPI handle missing\n"); | 134 | dev_dbg(&device->dev, "ACPI handle missing\n"); |
134 | put_device(&device->dev); | 135 | put_device(&device->dev); |
135 | goto out; | 136 | return -EINVAL; |
136 | } | 137 | } |
137 | 138 | ||
138 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 139 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
@@ -143,7 +144,7 @@ void acpi_bus_hot_remove_device(void *context) | |||
143 | put_device(&device->dev); | 144 | put_device(&device->dev); |
144 | device = NULL; | 145 | device = NULL; |
145 | 146 | ||
146 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) { | 147 | if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", ¬_used))) { |
147 | arg_list.count = 1; | 148 | arg_list.count = 1; |
148 | arg_list.pointer = &arg; | 149 | arg_list.pointer = &arg; |
149 | arg.type = ACPI_TYPE_INTEGER; | 150 | arg.type = ACPI_TYPE_INTEGER; |
@@ -161,18 +162,205 @@ void acpi_bus_hot_remove_device(void *context) | |||
161 | */ | 162 | */ |
162 | status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); | 163 | status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL); |
163 | if (ACPI_FAILURE(status)) { | 164 | if (ACPI_FAILURE(status)) { |
164 | if (status != AE_NOT_FOUND) | 165 | if (status == AE_NOT_FOUND) { |
165 | acpi_handle_warn(handle, "Eject failed\n"); | 166 | return -ENODEV; |
167 | } else { | ||
168 | acpi_handle_warn(handle, "Eject failed (0x%x)\n", | ||
169 | status); | ||
170 | return -EIO; | ||
171 | } | ||
172 | } | ||
166 | 173 | ||
167 | /* Tell the firmware the hot-remove operation has failed. */ | 174 | /* |
168 | acpi_evaluate_hotplug_ost(handle, ej_event->event, | 175 | * Verify if eject was indeed successful. If not, log an error |
169 | ost_code, NULL); | 176 | * message. No need to call _OST since _EJ0 call was made OK. |
177 | */ | ||
178 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); | ||
179 | if (ACPI_FAILURE(status)) { | ||
180 | acpi_handle_warn(handle, | ||
181 | "Status check after eject failed (0x%x)\n", status); | ||
182 | } else if (sta & ACPI_STA_DEVICE_ENABLED) { | ||
183 | acpi_handle_warn(handle, | ||
184 | "Eject incomplete - status 0x%llx\n", sta); | ||
185 | } | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static void acpi_bus_device_eject(void *context) | ||
191 | { | ||
192 | acpi_handle handle = context; | ||
193 | struct acpi_device *device = NULL; | ||
194 | struct acpi_scan_handler *handler; | ||
195 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
196 | |||
197 | mutex_lock(&acpi_scan_lock); | ||
198 | |||
199 | acpi_bus_get_device(handle, &device); | ||
200 | if (!device) | ||
201 | goto err_out; | ||
202 | |||
203 | handler = device->handler; | ||
204 | if (!handler || !handler->hotplug.enabled) { | ||
205 | ost_code = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | ||
206 | goto err_out; | ||
207 | } | ||
208 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, | ||
209 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | ||
210 | if (handler->hotplug.mode == AHM_CONTAINER) { | ||
211 | device->flags.eject_pending = true; | ||
212 | kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); | ||
213 | } else { | ||
214 | int error; | ||
215 | |||
216 | get_device(&device->dev); | ||
217 | error = acpi_scan_hot_remove(device); | ||
218 | if (error) | ||
219 | goto err_out; | ||
170 | } | 220 | } |
171 | 221 | ||
172 | out: | 222 | out: |
173 | mutex_unlock(&acpi_scan_lock); | 223 | mutex_unlock(&acpi_scan_lock); |
174 | kfree(context); | ||
175 | return; | 224 | return; |
225 | |||
226 | err_out: | ||
227 | acpi_evaluate_hotplug_ost(handle, ACPI_NOTIFY_EJECT_REQUEST, ost_code, | ||
228 | NULL); | ||
229 | goto out; | ||
230 | } | ||
231 | |||
232 | static void acpi_scan_bus_device_check(acpi_handle handle, u32 ost_source) | ||
233 | { | ||
234 | struct acpi_device *device = NULL; | ||
235 | u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; | ||
236 | int error; | ||
237 | |||
238 | mutex_lock(&acpi_scan_lock); | ||
239 | |||
240 | acpi_bus_get_device(handle, &device); | ||
241 | if (device) { | ||
242 | dev_warn(&device->dev, "Attempt to re-insert\n"); | ||
243 | goto out; | ||
244 | } | ||
245 | acpi_evaluate_hotplug_ost(handle, ost_source, | ||
246 | ACPI_OST_SC_INSERT_IN_PROGRESS, NULL); | ||
247 | error = acpi_bus_scan(handle); | ||
248 | if (error) { | ||
249 | acpi_handle_warn(handle, "Namespace scan failure\n"); | ||
250 | goto out; | ||
251 | } | ||
252 | error = acpi_bus_get_device(handle, &device); | ||
253 | if (error) { | ||
254 | acpi_handle_warn(handle, "Missing device node object\n"); | ||
255 | goto out; | ||
256 | } | ||
257 | ost_code = ACPI_OST_SC_SUCCESS; | ||
258 | if (device->handler && device->handler->hotplug.mode == AHM_CONTAINER) | ||
259 | kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); | ||
260 | |||
261 | out: | ||
262 | acpi_evaluate_hotplug_ost(handle, ost_source, ost_code, NULL); | ||
263 | mutex_unlock(&acpi_scan_lock); | ||
264 | } | ||
265 | |||
266 | static void acpi_scan_bus_check(void *context) | ||
267 | { | ||
268 | acpi_scan_bus_device_check((acpi_handle)context, | ||
269 | ACPI_NOTIFY_BUS_CHECK); | ||
270 | } | ||
271 | |||
272 | static void acpi_scan_device_check(void *context) | ||
273 | { | ||
274 | acpi_scan_bus_device_check((acpi_handle)context, | ||
275 | ACPI_NOTIFY_DEVICE_CHECK); | ||
276 | } | ||
277 | |||
278 | static void acpi_hotplug_unsupported(acpi_handle handle, u32 type) | ||
279 | { | ||
280 | u32 ost_status; | ||
281 | |||
282 | switch (type) { | ||
283 | case ACPI_NOTIFY_BUS_CHECK: | ||
284 | acpi_handle_debug(handle, | ||
285 | "ACPI_NOTIFY_BUS_CHECK event: unsupported\n"); | ||
286 | ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; | ||
287 | break; | ||
288 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
289 | acpi_handle_debug(handle, | ||
290 | "ACPI_NOTIFY_DEVICE_CHECK event: unsupported\n"); | ||
291 | ost_status = ACPI_OST_SC_INSERT_NOT_SUPPORTED; | ||
292 | break; | ||
293 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
294 | acpi_handle_debug(handle, | ||
295 | "ACPI_NOTIFY_EJECT_REQUEST event: unsupported\n"); | ||
296 | ost_status = ACPI_OST_SC_EJECT_NOT_SUPPORTED; | ||
297 | break; | ||
298 | default: | ||
299 | /* non-hotplug event; possibly handled by other handler */ | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | acpi_evaluate_hotplug_ost(handle, type, ost_status, NULL); | ||
304 | } | ||
305 | |||
306 | static void acpi_hotplug_notify_cb(acpi_handle handle, u32 type, void *data) | ||
307 | { | ||
308 | acpi_osd_exec_callback callback; | ||
309 | struct acpi_scan_handler *handler = data; | ||
310 | acpi_status status; | ||
311 | |||
312 | if (!handler->hotplug.enabled) | ||
313 | return acpi_hotplug_unsupported(handle, type); | ||
314 | |||
315 | switch (type) { | ||
316 | case ACPI_NOTIFY_BUS_CHECK: | ||
317 | acpi_handle_debug(handle, "ACPI_NOTIFY_BUS_CHECK event\n"); | ||
318 | callback = acpi_scan_bus_check; | ||
319 | break; | ||
320 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
321 | acpi_handle_debug(handle, "ACPI_NOTIFY_DEVICE_CHECK event\n"); | ||
322 | callback = acpi_scan_device_check; | ||
323 | break; | ||
324 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
325 | acpi_handle_debug(handle, "ACPI_NOTIFY_EJECT_REQUEST event\n"); | ||
326 | callback = acpi_bus_device_eject; | ||
327 | break; | ||
328 | default: | ||
329 | /* non-hotplug event; possibly handled by other handler */ | ||
330 | return; | ||
331 | } | ||
332 | status = acpi_os_hotplug_execute(callback, handle); | ||
333 | if (ACPI_FAILURE(status)) | ||
334 | acpi_evaluate_hotplug_ost(handle, type, | ||
335 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, | ||
336 | NULL); | ||
337 | } | ||
338 | |||
339 | /** | ||
340 | * acpi_bus_hot_remove_device: hot-remove a device and its children | ||
341 | * @context: struct acpi_eject_event pointer (freed in this func) | ||
342 | * | ||
343 | * Hot-remove a device and its children. This function frees up the | ||
344 | * memory space passed by arg context, so that the caller may call | ||
345 | * this function asynchronously through acpi_os_hotplug_execute(). | ||
346 | */ | ||
347 | void acpi_bus_hot_remove_device(void *context) | ||
348 | { | ||
349 | struct acpi_eject_event *ej_event = context; | ||
350 | struct acpi_device *device = ej_event->device; | ||
351 | acpi_handle handle = device->handle; | ||
352 | int error; | ||
353 | |||
354 | mutex_lock(&acpi_scan_lock); | ||
355 | |||
356 | error = acpi_scan_hot_remove(device); | ||
357 | if (error && handle) | ||
358 | acpi_evaluate_hotplug_ost(handle, ej_event->event, | ||
359 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, | ||
360 | NULL); | ||
361 | |||
362 | mutex_unlock(&acpi_scan_lock); | ||
363 | kfree(context); | ||
176 | } | 364 | } |
177 | EXPORT_SYMBOL(acpi_bus_hot_remove_device); | 365 | EXPORT_SYMBOL(acpi_bus_hot_remove_device); |
178 | 366 | ||
@@ -206,51 +394,61 @@ static ssize_t | |||
206 | acpi_eject_store(struct device *d, struct device_attribute *attr, | 394 | acpi_eject_store(struct device *d, struct device_attribute *attr, |
207 | const char *buf, size_t count) | 395 | const char *buf, size_t count) |
208 | { | 396 | { |
209 | int ret = count; | ||
210 | acpi_status status; | ||
211 | acpi_object_type type = 0; | ||
212 | struct acpi_device *acpi_device = to_acpi_device(d); | 397 | struct acpi_device *acpi_device = to_acpi_device(d); |
213 | struct acpi_eject_event *ej_event; | 398 | struct acpi_eject_event *ej_event; |
399 | acpi_object_type not_used; | ||
400 | acpi_status status; | ||
401 | u32 ost_source; | ||
402 | int ret; | ||
214 | 403 | ||
215 | if ((!count) || (buf[0] != '1')) { | 404 | if (!count || buf[0] != '1') |
216 | return -EINVAL; | 405 | return -EINVAL; |
217 | } | ||
218 | if (!acpi_device->driver && !acpi_device->handler) { | ||
219 | ret = -ENODEV; | ||
220 | goto err; | ||
221 | } | ||
222 | status = acpi_get_type(acpi_device->handle, &type); | ||
223 | if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) { | ||
224 | ret = -ENODEV; | ||
225 | goto err; | ||
226 | } | ||
227 | 406 | ||
228 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | 407 | if ((!acpi_device->handler || !acpi_device->handler->hotplug.enabled) |
229 | if (!ej_event) { | 408 | && !acpi_device->driver) |
230 | ret = -ENOMEM; | 409 | return -ENODEV; |
231 | goto err; | 410 | |
232 | } | 411 | status = acpi_get_type(acpi_device->handle, ¬_used); |
412 | if (ACPI_FAILURE(status) || !acpi_device->flags.ejectable) | ||
413 | return -ENODEV; | ||
414 | |||
415 | mutex_lock(&acpi_scan_lock); | ||
233 | 416 | ||
234 | get_device(&acpi_device->dev); | ||
235 | ej_event->device = acpi_device; | ||
236 | if (acpi_device->flags.eject_pending) { | 417 | if (acpi_device->flags.eject_pending) { |
237 | /* event originated from ACPI eject notification */ | 418 | /* ACPI eject notification event. */ |
238 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | 419 | ost_source = ACPI_NOTIFY_EJECT_REQUEST; |
239 | acpi_device->flags.eject_pending = 0; | 420 | acpi_device->flags.eject_pending = 0; |
240 | } else { | 421 | } else { |
241 | /* event originated from user */ | 422 | /* Eject initiated by user space. */ |
242 | ej_event->event = ACPI_OST_EC_OSPM_EJECT; | 423 | ost_source = ACPI_OST_EC_OSPM_EJECT; |
243 | (void) acpi_evaluate_hotplug_ost(acpi_device->handle, | ||
244 | ej_event->event, ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | ||
245 | } | 424 | } |
246 | 425 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | |
426 | if (!ej_event) { | ||
427 | ret = -ENOMEM; | ||
428 | goto err_out; | ||
429 | } | ||
430 | acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source, | ||
431 | ACPI_OST_SC_EJECT_IN_PROGRESS, NULL); | ||
432 | ej_event->device = acpi_device; | ||
433 | ej_event->event = ost_source; | ||
434 | get_device(&acpi_device->dev); | ||
247 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); | 435 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); |
248 | if (ACPI_FAILURE(status)) { | 436 | if (ACPI_FAILURE(status)) { |
249 | put_device(&acpi_device->dev); | 437 | put_device(&acpi_device->dev); |
250 | kfree(ej_event); | 438 | kfree(ej_event); |
439 | ret = status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; | ||
440 | goto err_out; | ||
251 | } | 441 | } |
252 | err: | 442 | ret = count; |
443 | |||
444 | out: | ||
445 | mutex_unlock(&acpi_scan_lock); | ||
253 | return ret; | 446 | return ret; |
447 | |||
448 | err_out: | ||
449 | acpi_evaluate_hotplug_ost(acpi_device->handle, ost_source, | ||
450 | ACPI_OST_SC_NON_SPECIFIC_FAILURE, NULL); | ||
451 | goto out; | ||
254 | } | 452 | } |
255 | 453 | ||
256 | static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); | 454 | static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); |
@@ -376,7 +574,7 @@ static int acpi_device_setup_files(struct acpi_device *dev) | |||
376 | goto end; | 574 | goto end; |
377 | } | 575 | } |
378 | 576 | ||
379 | if (dev->flags.bus_address) | 577 | if (dev->pnp.type.bus_address) |
380 | result = device_create_file(&dev->dev, &dev_attr_adr); | 578 | result = device_create_file(&dev->dev, &dev_attr_adr); |
381 | if (dev->pnp.unique_id) | 579 | if (dev->pnp.unique_id) |
382 | result = device_create_file(&dev->dev, &dev_attr_uid); | 580 | result = device_create_file(&dev->dev, &dev_attr_uid); |
@@ -449,7 +647,7 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
449 | 647 | ||
450 | if (dev->pnp.unique_id) | 648 | if (dev->pnp.unique_id) |
451 | device_remove_file(&dev->dev, &dev_attr_uid); | 649 | device_remove_file(&dev->dev, &dev_attr_uid); |
452 | if (dev->flags.bus_address) | 650 | if (dev->pnp.type.bus_address) |
453 | device_remove_file(&dev->dev, &dev_attr_adr); | 651 | device_remove_file(&dev->dev, &dev_attr_adr); |
454 | device_remove_file(&dev->dev, &dev_attr_modalias); | 652 | device_remove_file(&dev->dev, &dev_attr_modalias); |
455 | device_remove_file(&dev->dev, &dev_attr_hid); | 653 | device_remove_file(&dev->dev, &dev_attr_hid); |
@@ -512,17 +710,6 @@ int acpi_match_device_ids(struct acpi_device *device, | |||
512 | } | 710 | } |
513 | EXPORT_SYMBOL(acpi_match_device_ids); | 711 | EXPORT_SYMBOL(acpi_match_device_ids); |
514 | 712 | ||
515 | void acpi_free_ids(struct acpi_device *device) | ||
516 | { | ||
517 | struct acpi_hardware_id *id, *tmp; | ||
518 | |||
519 | list_for_each_entry_safe(id, tmp, &device->pnp.ids, list) { | ||
520 | kfree(id->id); | ||
521 | kfree(id); | ||
522 | } | ||
523 | kfree(device->pnp.unique_id); | ||
524 | } | ||
525 | |||
526 | static void acpi_free_power_resources_lists(struct acpi_device *device) | 713 | static void acpi_free_power_resources_lists(struct acpi_device *device) |
527 | { | 714 | { |
528 | int i; | 715 | int i; |
@@ -543,7 +730,7 @@ static void acpi_device_release(struct device *dev) | |||
543 | { | 730 | { |
544 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 731 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
545 | 732 | ||
546 | acpi_free_ids(acpi_dev); | 733 | acpi_free_pnp_ids(&acpi_dev->pnp); |
547 | acpi_free_power_resources_lists(acpi_dev); | 734 | acpi_free_power_resources_lists(acpi_dev); |
548 | kfree(acpi_dev); | 735 | kfree(acpi_dev); |
549 | } | 736 | } |
@@ -1256,19 +1443,17 @@ static void acpi_device_get_busid(struct acpi_device *device) | |||
1256 | } | 1443 | } |
1257 | 1444 | ||
1258 | /* | 1445 | /* |
1259 | * acpi_bay_match - see if a device is an ejectable driver bay | 1446 | * acpi_bay_match - see if an acpi object is an ejectable driver bay |
1260 | * | 1447 | * |
1261 | * If an acpi object is ejectable and has one of the ACPI ATA methods defined, | 1448 | * If an acpi object is ejectable and has one of the ACPI ATA methods defined, |
1262 | * then we can safely call it an ejectable drive bay | 1449 | * then we can safely call it an ejectable drive bay |
1263 | */ | 1450 | */ |
1264 | static int acpi_bay_match(struct acpi_device *device){ | 1451 | static int acpi_bay_match(acpi_handle handle) |
1452 | { | ||
1265 | acpi_status status; | 1453 | acpi_status status; |
1266 | acpi_handle handle; | ||
1267 | acpi_handle tmp; | 1454 | acpi_handle tmp; |
1268 | acpi_handle phandle; | 1455 | acpi_handle phandle; |
1269 | 1456 | ||
1270 | handle = device->handle; | ||
1271 | |||
1272 | status = acpi_get_handle(handle, "_EJ0", &tmp); | 1457 | status = acpi_get_handle(handle, "_EJ0", &tmp); |
1273 | if (ACPI_FAILURE(status)) | 1458 | if (ACPI_FAILURE(status)) |
1274 | return -ENODEV; | 1459 | return -ENODEV; |
@@ -1292,12 +1477,12 @@ static int acpi_bay_match(struct acpi_device *device){ | |||
1292 | } | 1477 | } |
1293 | 1478 | ||
1294 | /* | 1479 | /* |
1295 | * acpi_dock_match - see if a device has a _DCK method | 1480 | * acpi_dock_match - see if an acpi object has a _DCK method |
1296 | */ | 1481 | */ |
1297 | static int acpi_dock_match(struct acpi_device *device) | 1482 | static int acpi_dock_match(acpi_handle handle) |
1298 | { | 1483 | { |
1299 | acpi_handle tmp; | 1484 | acpi_handle tmp; |
1300 | return acpi_get_handle(device->handle, "_DCK", &tmp); | 1485 | return acpi_get_handle(handle, "_DCK", &tmp); |
1301 | } | 1486 | } |
1302 | 1487 | ||
1303 | const char *acpi_device_hid(struct acpi_device *device) | 1488 | const char *acpi_device_hid(struct acpi_device *device) |
@@ -1312,7 +1497,7 @@ const char *acpi_device_hid(struct acpi_device *device) | |||
1312 | } | 1497 | } |
1313 | EXPORT_SYMBOL(acpi_device_hid); | 1498 | EXPORT_SYMBOL(acpi_device_hid); |
1314 | 1499 | ||
1315 | static void acpi_add_id(struct acpi_device *device, const char *dev_id) | 1500 | static void acpi_add_id(struct acpi_device_pnp *pnp, const char *dev_id) |
1316 | { | 1501 | { |
1317 | struct acpi_hardware_id *id; | 1502 | struct acpi_hardware_id *id; |
1318 | 1503 | ||
@@ -1326,7 +1511,8 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id) | |||
1326 | return; | 1511 | return; |
1327 | } | 1512 | } |
1328 | 1513 | ||
1329 | list_add_tail(&id->list, &device->pnp.ids); | 1514 | list_add_tail(&id->list, &pnp->ids); |
1515 | pnp->type.hardware_id = 1; | ||
1330 | } | 1516 | } |
1331 | 1517 | ||
1332 | /* | 1518 | /* |
@@ -1334,7 +1520,7 @@ static void acpi_add_id(struct acpi_device *device, const char *dev_id) | |||
1334 | * lacks the SMBUS01 HID and the methods do not have the necessary "_" | 1520 | * lacks the SMBUS01 HID and the methods do not have the necessary "_" |
1335 | * prefix. Work around this. | 1521 | * prefix. Work around this. |
1336 | */ | 1522 | */ |
1337 | static int acpi_ibm_smbus_match(struct acpi_device *device) | 1523 | static int acpi_ibm_smbus_match(acpi_handle handle) |
1338 | { | 1524 | { |
1339 | acpi_handle h_dummy; | 1525 | acpi_handle h_dummy; |
1340 | struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; | 1526 | struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; |
@@ -1344,7 +1530,7 @@ static int acpi_ibm_smbus_match(struct acpi_device *device) | |||
1344 | return -ENODEV; | 1530 | return -ENODEV; |
1345 | 1531 | ||
1346 | /* Look for SMBS object */ | 1532 | /* Look for SMBS object */ |
1347 | result = acpi_get_name(device->handle, ACPI_SINGLE_NAME, &path); | 1533 | result = acpi_get_name(handle, ACPI_SINGLE_NAME, &path); |
1348 | if (result) | 1534 | if (result) |
1349 | return result; | 1535 | return result; |
1350 | 1536 | ||
@@ -1355,48 +1541,50 @@ static int acpi_ibm_smbus_match(struct acpi_device *device) | |||
1355 | 1541 | ||
1356 | /* Does it have the necessary (but misnamed) methods? */ | 1542 | /* Does it have the necessary (but misnamed) methods? */ |
1357 | result = -ENODEV; | 1543 | result = -ENODEV; |
1358 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "SBI", &h_dummy)) && | 1544 | if (ACPI_SUCCESS(acpi_get_handle(handle, "SBI", &h_dummy)) && |
1359 | ACPI_SUCCESS(acpi_get_handle(device->handle, "SBR", &h_dummy)) && | 1545 | ACPI_SUCCESS(acpi_get_handle(handle, "SBR", &h_dummy)) && |
1360 | ACPI_SUCCESS(acpi_get_handle(device->handle, "SBW", &h_dummy))) | 1546 | ACPI_SUCCESS(acpi_get_handle(handle, "SBW", &h_dummy))) |
1361 | result = 0; | 1547 | result = 0; |
1362 | out: | 1548 | out: |
1363 | kfree(path.pointer); | 1549 | kfree(path.pointer); |
1364 | return result; | 1550 | return result; |
1365 | } | 1551 | } |
1366 | 1552 | ||
1367 | static void acpi_device_set_id(struct acpi_device *device) | 1553 | static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, |
1554 | int device_type) | ||
1368 | { | 1555 | { |
1369 | acpi_status status; | 1556 | acpi_status status; |
1370 | struct acpi_device_info *info; | 1557 | struct acpi_device_info *info; |
1371 | struct acpi_pnp_device_id_list *cid_list; | 1558 | struct acpi_pnp_device_id_list *cid_list; |
1372 | int i; | 1559 | int i; |
1373 | 1560 | ||
1374 | switch (device->device_type) { | 1561 | switch (device_type) { |
1375 | case ACPI_BUS_TYPE_DEVICE: | 1562 | case ACPI_BUS_TYPE_DEVICE: |
1376 | if (ACPI_IS_ROOT_DEVICE(device)) { | 1563 | if (handle == ACPI_ROOT_OBJECT) { |
1377 | acpi_add_id(device, ACPI_SYSTEM_HID); | 1564 | acpi_add_id(pnp, ACPI_SYSTEM_HID); |
1378 | break; | 1565 | break; |
1379 | } | 1566 | } |
1380 | 1567 | ||
1381 | status = acpi_get_object_info(device->handle, &info); | 1568 | status = acpi_get_object_info(handle, &info); |
1382 | if (ACPI_FAILURE(status)) { | 1569 | if (ACPI_FAILURE(status)) { |
1383 | printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); | 1570 | pr_err(PREFIX "%s: Error reading device info\n", |
1571 | __func__); | ||
1384 | return; | 1572 | return; |
1385 | } | 1573 | } |
1386 | 1574 | ||
1387 | if (info->valid & ACPI_VALID_HID) | 1575 | if (info->valid & ACPI_VALID_HID) |
1388 | acpi_add_id(device, info->hardware_id.string); | 1576 | acpi_add_id(pnp, info->hardware_id.string); |
1389 | if (info->valid & ACPI_VALID_CID) { | 1577 | if (info->valid & ACPI_VALID_CID) { |
1390 | cid_list = &info->compatible_id_list; | 1578 | cid_list = &info->compatible_id_list; |
1391 | for (i = 0; i < cid_list->count; i++) | 1579 | for (i = 0; i < cid_list->count; i++) |
1392 | acpi_add_id(device, cid_list->ids[i].string); | 1580 | acpi_add_id(pnp, cid_list->ids[i].string); |
1393 | } | 1581 | } |
1394 | if (info->valid & ACPI_VALID_ADR) { | 1582 | if (info->valid & ACPI_VALID_ADR) { |
1395 | device->pnp.bus_address = info->address; | 1583 | pnp->bus_address = info->address; |
1396 | device->flags.bus_address = 1; | 1584 | pnp->type.bus_address = 1; |
1397 | } | 1585 | } |
1398 | if (info->valid & ACPI_VALID_UID) | 1586 | if (info->valid & ACPI_VALID_UID) |
1399 | device->pnp.unique_id = kstrdup(info->unique_id.string, | 1587 | pnp->unique_id = kstrdup(info->unique_id.string, |
1400 | GFP_KERNEL); | 1588 | GFP_KERNEL); |
1401 | 1589 | ||
1402 | kfree(info); | 1590 | kfree(info); |
@@ -1405,40 +1593,50 @@ static void acpi_device_set_id(struct acpi_device *device) | |||
1405 | * Some devices don't reliably have _HIDs & _CIDs, so add | 1593 | * Some devices don't reliably have _HIDs & _CIDs, so add |
1406 | * synthetic HIDs to make sure drivers can find them. | 1594 | * synthetic HIDs to make sure drivers can find them. |
1407 | */ | 1595 | */ |
1408 | if (acpi_is_video_device(device)) | 1596 | if (acpi_is_video_device(handle)) |
1409 | acpi_add_id(device, ACPI_VIDEO_HID); | 1597 | acpi_add_id(pnp, ACPI_VIDEO_HID); |
1410 | else if (ACPI_SUCCESS(acpi_bay_match(device))) | 1598 | else if (ACPI_SUCCESS(acpi_bay_match(handle))) |
1411 | acpi_add_id(device, ACPI_BAY_HID); | 1599 | acpi_add_id(pnp, ACPI_BAY_HID); |
1412 | else if (ACPI_SUCCESS(acpi_dock_match(device))) | 1600 | else if (ACPI_SUCCESS(acpi_dock_match(handle))) |
1413 | acpi_add_id(device, ACPI_DOCK_HID); | 1601 | acpi_add_id(pnp, ACPI_DOCK_HID); |
1414 | else if (!acpi_ibm_smbus_match(device)) | 1602 | else if (!acpi_ibm_smbus_match(handle)) |
1415 | acpi_add_id(device, ACPI_SMBUS_IBM_HID); | 1603 | acpi_add_id(pnp, ACPI_SMBUS_IBM_HID); |
1416 | else if (list_empty(&device->pnp.ids) && | 1604 | else if (list_empty(&pnp->ids) && handle == ACPI_ROOT_OBJECT) { |
1417 | ACPI_IS_ROOT_DEVICE(device->parent)) { | 1605 | acpi_add_id(pnp, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ |
1418 | acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ | 1606 | strcpy(pnp->device_name, ACPI_BUS_DEVICE_NAME); |
1419 | strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME); | 1607 | strcpy(pnp->device_class, ACPI_BUS_CLASS); |
1420 | strcpy(device->pnp.device_class, ACPI_BUS_CLASS); | ||
1421 | } | 1608 | } |
1422 | 1609 | ||
1423 | break; | 1610 | break; |
1424 | case ACPI_BUS_TYPE_POWER: | 1611 | case ACPI_BUS_TYPE_POWER: |
1425 | acpi_add_id(device, ACPI_POWER_HID); | 1612 | acpi_add_id(pnp, ACPI_POWER_HID); |
1426 | break; | 1613 | break; |
1427 | case ACPI_BUS_TYPE_PROCESSOR: | 1614 | case ACPI_BUS_TYPE_PROCESSOR: |
1428 | acpi_add_id(device, ACPI_PROCESSOR_OBJECT_HID); | 1615 | acpi_add_id(pnp, ACPI_PROCESSOR_OBJECT_HID); |
1429 | break; | 1616 | break; |
1430 | case ACPI_BUS_TYPE_THERMAL: | 1617 | case ACPI_BUS_TYPE_THERMAL: |
1431 | acpi_add_id(device, ACPI_THERMAL_HID); | 1618 | acpi_add_id(pnp, ACPI_THERMAL_HID); |
1432 | break; | 1619 | break; |
1433 | case ACPI_BUS_TYPE_POWER_BUTTON: | 1620 | case ACPI_BUS_TYPE_POWER_BUTTON: |
1434 | acpi_add_id(device, ACPI_BUTTON_HID_POWERF); | 1621 | acpi_add_id(pnp, ACPI_BUTTON_HID_POWERF); |
1435 | break; | 1622 | break; |
1436 | case ACPI_BUS_TYPE_SLEEP_BUTTON: | 1623 | case ACPI_BUS_TYPE_SLEEP_BUTTON: |
1437 | acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF); | 1624 | acpi_add_id(pnp, ACPI_BUTTON_HID_SLEEPF); |
1438 | break; | 1625 | break; |
1439 | } | 1626 | } |
1440 | } | 1627 | } |
1441 | 1628 | ||
1629 | void acpi_free_pnp_ids(struct acpi_device_pnp *pnp) | ||
1630 | { | ||
1631 | struct acpi_hardware_id *id, *tmp; | ||
1632 | |||
1633 | list_for_each_entry_safe(id, tmp, &pnp->ids, list) { | ||
1634 | kfree(id->id); | ||
1635 | kfree(id); | ||
1636 | } | ||
1637 | kfree(pnp->unique_id); | ||
1638 | } | ||
1639 | |||
1442 | void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | 1640 | void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, |
1443 | int type, unsigned long long sta) | 1641 | int type, unsigned long long sta) |
1444 | { | 1642 | { |
@@ -1448,7 +1646,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | |||
1448 | device->parent = acpi_bus_get_parent(handle); | 1646 | device->parent = acpi_bus_get_parent(handle); |
1449 | STRUCT_TO_INT(device->status) = sta; | 1647 | STRUCT_TO_INT(device->status) = sta; |
1450 | acpi_device_get_busid(device); | 1648 | acpi_device_get_busid(device); |
1451 | acpi_device_set_id(device); | 1649 | acpi_set_pnp_ids(handle, &device->pnp, type); |
1452 | acpi_bus_get_flags(device); | 1650 | acpi_bus_get_flags(device); |
1453 | device->flags.match_driver = false; | 1651 | device->flags.match_driver = false; |
1454 | device_initialize(&device->dev); | 1652 | device_initialize(&device->dev); |
@@ -1536,6 +1734,75 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, | |||
1536 | return 0; | 1734 | return 0; |
1537 | } | 1735 | } |
1538 | 1736 | ||
1737 | static bool acpi_scan_handler_matching(struct acpi_scan_handler *handler, | ||
1738 | char *idstr, | ||
1739 | const struct acpi_device_id **matchid) | ||
1740 | { | ||
1741 | const struct acpi_device_id *devid; | ||
1742 | |||
1743 | for (devid = handler->ids; devid->id[0]; devid++) | ||
1744 | if (!strcmp((char *)devid->id, idstr)) { | ||
1745 | if (matchid) | ||
1746 | *matchid = devid; | ||
1747 | |||
1748 | return true; | ||
1749 | } | ||
1750 | |||
1751 | return false; | ||
1752 | } | ||
1753 | |||
1754 | static struct acpi_scan_handler *acpi_scan_match_handler(char *idstr, | ||
1755 | const struct acpi_device_id **matchid) | ||
1756 | { | ||
1757 | struct acpi_scan_handler *handler; | ||
1758 | |||
1759 | list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) | ||
1760 | if (acpi_scan_handler_matching(handler, idstr, matchid)) | ||
1761 | return handler; | ||
1762 | |||
1763 | return NULL; | ||
1764 | } | ||
1765 | |||
1766 | void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val) | ||
1767 | { | ||
1768 | if (!!hotplug->enabled == !!val) | ||
1769 | return; | ||
1770 | |||
1771 | mutex_lock(&acpi_scan_lock); | ||
1772 | |||
1773 | hotplug->enabled = val; | ||
1774 | |||
1775 | mutex_unlock(&acpi_scan_lock); | ||
1776 | } | ||
1777 | |||
1778 | static void acpi_scan_init_hotplug(acpi_handle handle, int type) | ||
1779 | { | ||
1780 | struct acpi_device_pnp pnp = {}; | ||
1781 | struct acpi_hardware_id *hwid; | ||
1782 | struct acpi_scan_handler *handler; | ||
1783 | |||
1784 | INIT_LIST_HEAD(&pnp.ids); | ||
1785 | acpi_set_pnp_ids(handle, &pnp, type); | ||
1786 | |||
1787 | if (!pnp.type.hardware_id) | ||
1788 | return; | ||
1789 | |||
1790 | /* | ||
1791 | * This relies on the fact that acpi_install_notify_handler() will not | ||
1792 | * install the same notify handler routine twice for the same handle. | ||
1793 | */ | ||
1794 | list_for_each_entry(hwid, &pnp.ids, list) { | ||
1795 | handler = acpi_scan_match_handler(hwid->id, NULL); | ||
1796 | if (handler) { | ||
1797 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | ||
1798 | acpi_hotplug_notify_cb, handler); | ||
1799 | break; | ||
1800 | } | ||
1801 | } | ||
1802 | |||
1803 | acpi_free_pnp_ids(&pnp); | ||
1804 | } | ||
1805 | |||
1539 | static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | 1806 | static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, |
1540 | void *not_used, void **return_value) | 1807 | void *not_used, void **return_value) |
1541 | { | 1808 | { |
@@ -1558,6 +1825,8 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | |||
1558 | return AE_OK; | 1825 | return AE_OK; |
1559 | } | 1826 | } |
1560 | 1827 | ||
1828 | acpi_scan_init_hotplug(handle, type); | ||
1829 | |||
1561 | if (!(sta & ACPI_STA_DEVICE_PRESENT) && | 1830 | if (!(sta & ACPI_STA_DEVICE_PRESENT) && |
1562 | !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { | 1831 | !(sta & ACPI_STA_DEVICE_FUNCTIONING)) { |
1563 | struct acpi_device_wakeup wakeup; | 1832 | struct acpi_device_wakeup wakeup; |
@@ -1583,42 +1852,26 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, | |||
1583 | return AE_OK; | 1852 | return AE_OK; |
1584 | } | 1853 | } |
1585 | 1854 | ||
1586 | static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id) | 1855 | static int acpi_scan_attach_handler(struct acpi_device *device) |
1587 | { | 1856 | { |
1588 | struct acpi_scan_handler *handler; | 1857 | struct acpi_hardware_id *hwid; |
1858 | int ret = 0; | ||
1589 | 1859 | ||
1590 | list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) { | 1860 | list_for_each_entry(hwid, &device->pnp.ids, list) { |
1591 | const struct acpi_device_id *devid; | 1861 | const struct acpi_device_id *devid; |
1862 | struct acpi_scan_handler *handler; | ||
1592 | 1863 | ||
1593 | for (devid = handler->ids; devid->id[0]; devid++) { | 1864 | handler = acpi_scan_match_handler(hwid->id, &devid); |
1594 | int ret; | 1865 | if (handler) { |
1595 | |||
1596 | if (strcmp((char *)devid->id, id)) | ||
1597 | continue; | ||
1598 | |||
1599 | ret = handler->attach(device, devid); | 1866 | ret = handler->attach(device, devid); |
1600 | if (ret > 0) { | 1867 | if (ret > 0) { |
1601 | device->handler = handler; | 1868 | device->handler = handler; |
1602 | return ret; | 1869 | break; |
1603 | } else if (ret < 0) { | 1870 | } else if (ret < 0) { |
1604 | return ret; | 1871 | break; |
1605 | } | 1872 | } |
1606 | } | 1873 | } |
1607 | } | 1874 | } |
1608 | return 0; | ||
1609 | } | ||
1610 | |||
1611 | static int acpi_scan_attach_handler(struct acpi_device *device) | ||
1612 | { | ||
1613 | struct acpi_hardware_id *hwid; | ||
1614 | int ret = 0; | ||
1615 | |||
1616 | list_for_each_entry(hwid, &device->pnp.ids, list) { | ||
1617 | ret = acpi_scan_do_attach_handler(device, hwid->id); | ||
1618 | if (ret) | ||
1619 | break; | ||
1620 | |||
1621 | } | ||
1622 | return ret; | 1875 | return ret; |
1623 | } | 1876 | } |
1624 | 1877 | ||
@@ -1788,8 +2041,10 @@ int __init acpi_scan_init(void) | |||
1788 | acpi_pci_root_init(); | 2041 | acpi_pci_root_init(); |
1789 | acpi_pci_link_init(); | 2042 | acpi_pci_link_init(); |
1790 | acpi_platform_init(); | 2043 | acpi_platform_init(); |
2044 | acpi_lpss_init(); | ||
1791 | acpi_csrt_init(); | 2045 | acpi_csrt_init(); |
1792 | acpi_container_init(); | 2046 | acpi_container_init(); |
2047 | acpi_memory_hotplug_init(); | ||
1793 | 2048 | ||
1794 | mutex_lock(&acpi_scan_lock); | 2049 | mutex_lock(&acpi_scan_lock); |
1795 | /* | 2050 | /* |