diff options
author | Bob Moore <robert.moore@intel.com> | 2009-06-29 01:39:29 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-08-27 10:17:15 -0400 |
commit | 15b8dd53f5ffaf8e2d9095c423f713423f576c0f (patch) | |
tree | 773f09435b14a810372642502352d46c29b6f148 /drivers/acpi/acpica/nsxfname.c | |
parent | 9c61b34cf7078da72cce276ff8cfae5d6e9955bc (diff) |
ACPICA: Major update for acpi_get_object_info external interface
Completed a major update for the acpi_get_object_info external interface.
Changes include:
- Support for variable, unlimited length HID, UID, and CID strings
- Support Processor objects the same as Devices (HID,UID,CID,ADR,STA, etc.)
- Call the _SxW power methods on behalf of a device object
- Determine if a device is a PCI root bridge
- Change the ACPI_BUFFER parameter to ACPI_DEVICE_INFO.
These changes will require an update to all callers of this interface.
See the ACPICA Programmer Reference for details.
Also, update all invocations of acpi_get_object_info interface
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica/nsxfname.c')
-rw-r--r-- | drivers/acpi/acpica/nsxfname.c | 237 |
1 files changed, 182 insertions, 55 deletions
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index f23593d6add4..ddc84af6336e 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c | |||
@@ -51,6 +51,11 @@ | |||
51 | #define _COMPONENT ACPI_NAMESPACE | 51 | #define _COMPONENT ACPI_NAMESPACE |
52 | ACPI_MODULE_NAME("nsxfname") | 52 | ACPI_MODULE_NAME("nsxfname") |
53 | 53 | ||
54 | /* Local prototypes */ | ||
55 | static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, | ||
56 | struct acpica_device_id *source, | ||
57 | char *string_area); | ||
58 | |||
54 | /****************************************************************************** | 59 | /****************************************************************************** |
55 | * | 60 | * |
56 | * FUNCTION: acpi_get_handle | 61 | * FUNCTION: acpi_get_handle |
@@ -68,6 +73,7 @@ ACPI_MODULE_NAME("nsxfname") | |||
68 | * namespace handle. | 73 | * namespace handle. |
69 | * | 74 | * |
70 | ******************************************************************************/ | 75 | ******************************************************************************/ |
76 | |||
71 | acpi_status | 77 | acpi_status |
72 | acpi_get_handle(acpi_handle parent, | 78 | acpi_get_handle(acpi_handle parent, |
73 | acpi_string pathname, acpi_handle * ret_handle) | 79 | acpi_string pathname, acpi_handle * ret_handle) |
@@ -210,10 +216,38 @@ ACPI_EXPORT_SYMBOL(acpi_get_name) | |||
210 | 216 | ||
211 | /****************************************************************************** | 217 | /****************************************************************************** |
212 | * | 218 | * |
219 | * FUNCTION: acpi_ns_copy_device_id | ||
220 | * | ||
221 | * PARAMETERS: Dest - Pointer to the destination DEVICE_ID | ||
222 | * Source - Pointer to the source DEVICE_ID | ||
223 | * string_area - Pointer to where to copy the dest string | ||
224 | * | ||
225 | * RETURN: Pointer to the next string area | ||
226 | * | ||
227 | * DESCRIPTION: Copy a single DEVICE_ID, including the string data. | ||
228 | * | ||
229 | ******************************************************************************/ | ||
230 | static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, | ||
231 | struct acpica_device_id *source, | ||
232 | char *string_area) | ||
233 | { | ||
234 | /* Create the destination DEVICE_ID */ | ||
235 | |||
236 | dest->string = string_area; | ||
237 | dest->length = source->length; | ||
238 | |||
239 | /* Copy actual string and return a pointer to the next string area */ | ||
240 | |||
241 | ACPI_MEMCPY(string_area, source->string, source->length); | ||
242 | return (string_area + source->length); | ||
243 | } | ||
244 | |||
245 | /****************************************************************************** | ||
246 | * | ||
213 | * FUNCTION: acpi_get_object_info | 247 | * FUNCTION: acpi_get_object_info |
214 | * | 248 | * |
215 | * PARAMETERS: Handle - Object Handle | 249 | * PARAMETERS: Handle - Object Handle |
216 | * Buffer - Where the info is returned | 250 | * return_buffer - Where the info is returned |
217 | * | 251 | * |
218 | * RETURN: Status | 252 | * RETURN: Status |
219 | * | 253 | * |
@@ -221,33 +255,37 @@ ACPI_EXPORT_SYMBOL(acpi_get_name) | |||
221 | * namespace node and possibly by running several standard | 255 | * namespace node and possibly by running several standard |
222 | * control methods (Such as in the case of a device.) | 256 | * control methods (Such as in the case of a device.) |
223 | * | 257 | * |
258 | * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA, | ||
259 | * _ADR, _sx_w, and _sx_d methods. | ||
260 | * | ||
261 | * Note: Allocates the return buffer, must be freed by the caller. | ||
262 | * | ||
224 | ******************************************************************************/ | 263 | ******************************************************************************/ |
264 | |||
225 | acpi_status | 265 | acpi_status |
226 | acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) | 266 | acpi_get_object_info(acpi_handle handle, |
267 | struct acpi_device_info **return_buffer) | ||
227 | { | 268 | { |
228 | acpi_status status; | ||
229 | struct acpi_namespace_node *node; | 269 | struct acpi_namespace_node *node; |
230 | struct acpi_device_info *info; | 270 | struct acpi_device_info *info; |
231 | struct acpi_device_info *return_info; | 271 | struct acpica_device_id_list *cid_list = NULL; |
232 | struct acpi_compatible_id_list *cid_list = NULL; | 272 | struct acpica_device_id *hid = NULL; |
233 | acpi_size size; | 273 | struct acpica_device_id *uid = NULL; |
274 | char *next_id_string; | ||
275 | acpi_object_type type; | ||
276 | acpi_name name; | ||
277 | u8 param_count = 0; | ||
278 | u8 valid = 0; | ||
279 | u32 info_size; | ||
280 | u32 i; | ||
281 | acpi_status status; | ||
234 | 282 | ||
235 | /* Parameter validation */ | 283 | /* Parameter validation */ |
236 | 284 | ||
237 | if (!handle || !buffer) { | 285 | if (!handle || !return_buffer) { |
238 | return (AE_BAD_PARAMETER); | 286 | return (AE_BAD_PARAMETER); |
239 | } | 287 | } |
240 | 288 | ||
241 | status = acpi_ut_validate_buffer(buffer); | ||
242 | if (ACPI_FAILURE(status)) { | ||
243 | return (status); | ||
244 | } | ||
245 | |||
246 | info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info)); | ||
247 | if (!info) { | ||
248 | return (AE_NO_MEMORY); | ||
249 | } | ||
250 | |||
251 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | 289 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
252 | if (ACPI_FAILURE(status)) { | 290 | if (ACPI_FAILURE(status)) { |
253 | goto cleanup; | 291 | goto cleanup; |
@@ -256,66 +294,91 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) | |||
256 | node = acpi_ns_map_handle_to_node(handle); | 294 | node = acpi_ns_map_handle_to_node(handle); |
257 | if (!node) { | 295 | if (!node) { |
258 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 296 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
259 | status = AE_BAD_PARAMETER; | 297 | return (AE_BAD_PARAMETER); |
260 | goto cleanup; | ||
261 | } | 298 | } |
262 | 299 | ||
263 | /* Init return structure */ | 300 | /* Get the namespace node data while the namespace is locked */ |
264 | |||
265 | size = sizeof(struct acpi_device_info); | ||
266 | 301 | ||
267 | info->type = node->type; | 302 | info_size = sizeof(struct acpi_device_info); |
268 | info->name = node->name.integer; | 303 | type = node->type; |
269 | info->valid = 0; | 304 | name = node->name.integer; |
270 | 305 | ||
271 | if (node->type == ACPI_TYPE_METHOD) { | 306 | if (node->type == ACPI_TYPE_METHOD) { |
272 | info->param_count = node->object->method.param_count; | 307 | param_count = node->object->method.param_count; |
273 | } | 308 | } |
274 | 309 | ||
275 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 310 | status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
276 | if (ACPI_FAILURE(status)) { | 311 | if (ACPI_FAILURE(status)) { |
277 | goto cleanup; | 312 | return (status); |
278 | } | 313 | } |
279 | 314 | ||
280 | /* If not a device, we are all done */ | 315 | if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { |
281 | |||
282 | if (info->type == ACPI_TYPE_DEVICE) { | ||
283 | /* | 316 | /* |
284 | * Get extra info for ACPI Devices objects only: | 317 | * Get extra info for ACPI Device/Processor objects only: |
285 | * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods. | 318 | * Run the Device _HID, _UID, and _CID methods. |
286 | * | 319 | * |
287 | * Note: none of these methods are required, so they may or may | 320 | * Note: none of these methods are required, so they may or may |
288 | * not be present for this device. The Info->Valid bitfield is used | 321 | * not be present for this device. The Info->Valid bitfield is used |
289 | * to indicate which methods were found and ran successfully. | 322 | * to indicate which methods were found and run successfully. |
290 | */ | 323 | */ |
291 | 324 | ||
292 | /* Execute the Device._HID method */ | 325 | /* Execute the Device._HID method */ |
293 | 326 | ||
294 | status = acpi_ut_execute_HID(node, &info->hardware_id); | 327 | status = acpi_ut_execute_HID(node, &hid); |
295 | if (ACPI_SUCCESS(status)) { | 328 | if (ACPI_SUCCESS(status)) { |
296 | info->valid |= ACPI_VALID_HID; | 329 | info_size += hid->length; |
330 | valid |= ACPI_VALID_HID; | ||
297 | } | 331 | } |
298 | 332 | ||
299 | /* Execute the Device._UID method */ | 333 | /* Execute the Device._UID method */ |
300 | 334 | ||
301 | status = acpi_ut_execute_UID(node, &info->unique_id); | 335 | status = acpi_ut_execute_UID(node, &uid); |
302 | if (ACPI_SUCCESS(status)) { | 336 | if (ACPI_SUCCESS(status)) { |
303 | info->valid |= ACPI_VALID_UID; | 337 | info_size += uid->length; |
338 | valid |= ACPI_VALID_UID; | ||
304 | } | 339 | } |
305 | 340 | ||
306 | /* Execute the Device._CID method */ | 341 | /* Execute the Device._CID method */ |
307 | 342 | ||
308 | status = acpi_ut_execute_CID(node, &cid_list); | 343 | status = acpi_ut_execute_CID(node, &cid_list); |
309 | if (ACPI_SUCCESS(status)) { | 344 | if (ACPI_SUCCESS(status)) { |
310 | size += cid_list->size; | 345 | |
311 | info->valid |= ACPI_VALID_CID; | 346 | /* Add size of CID strings and CID pointer array */ |
347 | |||
348 | info_size += | ||
349 | (cid_list->list_size - | ||
350 | sizeof(struct acpica_device_id_list)); | ||
351 | valid |= ACPI_VALID_CID; | ||
312 | } | 352 | } |
353 | } | ||
354 | |||
355 | /* | ||
356 | * Now that we have the variable-length data, we can allocate the | ||
357 | * return buffer | ||
358 | */ | ||
359 | info = ACPI_ALLOCATE_ZEROED(info_size); | ||
360 | if (!info) { | ||
361 | status = AE_NO_MEMORY; | ||
362 | goto cleanup; | ||
363 | } | ||
364 | |||
365 | /* Get the fixed-length data */ | ||
366 | |||
367 | if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { | ||
368 | /* | ||
369 | * Get extra info for ACPI Device/Processor objects only: | ||
370 | * Run the _STA, _ADR and, sx_w, and _sx_d methods. | ||
371 | * | ||
372 | * Note: none of these methods are required, so they may or may | ||
373 | * not be present for this device. The Info->Valid bitfield is used | ||
374 | * to indicate which methods were found and run successfully. | ||
375 | */ | ||
313 | 376 | ||
314 | /* Execute the Device._STA method */ | 377 | /* Execute the Device._STA method */ |
315 | 378 | ||
316 | status = acpi_ut_execute_STA(node, &info->current_status); | 379 | status = acpi_ut_execute_STA(node, &info->current_status); |
317 | if (ACPI_SUCCESS(status)) { | 380 | if (ACPI_SUCCESS(status)) { |
318 | info->valid |= ACPI_VALID_STA; | 381 | valid |= ACPI_VALID_STA; |
319 | } | 382 | } |
320 | 383 | ||
321 | /* Execute the Device._ADR method */ | 384 | /* Execute the Device._ADR method */ |
@@ -323,36 +386,100 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) | |||
323 | status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, | 386 | status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, |
324 | &info->address); | 387 | &info->address); |
325 | if (ACPI_SUCCESS(status)) { | 388 | if (ACPI_SUCCESS(status)) { |
326 | info->valid |= ACPI_VALID_ADR; | 389 | valid |= ACPI_VALID_ADR; |
390 | } | ||
391 | |||
392 | /* Execute the Device._sx_w methods */ | ||
393 | |||
394 | status = acpi_ut_execute_power_methods(node, | ||
395 | acpi_gbl_lowest_dstate_names, | ||
396 | ACPI_NUM_sx_w_METHODS, | ||
397 | info->lowest_dstates); | ||
398 | if (ACPI_SUCCESS(status)) { | ||
399 | valid |= ACPI_VALID_SXWS; | ||
327 | } | 400 | } |
328 | 401 | ||
329 | /* Execute the Device._sx_d methods */ | 402 | /* Execute the Device._sx_d methods */ |
330 | 403 | ||
331 | status = acpi_ut_execute_sxds(node, info->highest_dstates); | 404 | status = acpi_ut_execute_power_methods(node, |
405 | acpi_gbl_highest_dstate_names, | ||
406 | ACPI_NUM_sx_d_METHODS, | ||
407 | info->highest_dstates); | ||
332 | if (ACPI_SUCCESS(status)) { | 408 | if (ACPI_SUCCESS(status)) { |
333 | info->valid |= ACPI_VALID_SXDS; | 409 | valid |= ACPI_VALID_SXDS; |
334 | } | 410 | } |
335 | } | 411 | } |
336 | 412 | ||
337 | /* Validate/Allocate/Clear caller buffer */ | 413 | /* |
414 | * Create a pointer to the string area of the return buffer. | ||
415 | * Point to the end of the base struct acpi_device_info structure. | ||
416 | */ | ||
417 | next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids); | ||
418 | if (cid_list) { | ||
338 | 419 | ||
339 | status = acpi_ut_initialize_buffer(buffer, size); | 420 | /* Point past the CID DEVICE_ID array */ |
340 | if (ACPI_FAILURE(status)) { | 421 | |
341 | goto cleanup; | 422 | next_id_string += |
423 | ((acpi_size) cid_list->count * | ||
424 | sizeof(struct acpica_device_id)); | ||
342 | } | 425 | } |
343 | 426 | ||
344 | /* Populate the return buffer */ | 427 | /* |
428 | * Copy the HID, UID, and CIDs to the return buffer. The variable-length | ||
429 | * strings are copied to the reserved area at the end of the buffer. | ||
430 | * | ||
431 | * For HID and CID, check if the ID is a PCI Root Bridge. | ||
432 | */ | ||
433 | if (hid) { | ||
434 | next_id_string = acpi_ns_copy_device_id(&info->hardware_id, | ||
435 | hid, next_id_string); | ||
436 | |||
437 | if (acpi_ut_is_pci_root_bridge(hid->string)) { | ||
438 | info->flags |= ACPI_PCI_ROOT_BRIDGE; | ||
439 | } | ||
440 | } | ||
345 | 441 | ||
346 | return_info = buffer->pointer; | 442 | if (uid) { |
347 | ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info)); | 443 | next_id_string = acpi_ns_copy_device_id(&info->unique_id, |
444 | uid, next_id_string); | ||
445 | } | ||
348 | 446 | ||
349 | if (cid_list) { | 447 | if (cid_list) { |
350 | ACPI_MEMCPY(&return_info->compatibility_id, cid_list, | 448 | info->compatible_id_list.count = cid_list->count; |
351 | cid_list->size); | 449 | info->compatible_id_list.list_size = cid_list->list_size; |
450 | |||
451 | /* Copy each CID */ | ||
452 | |||
453 | for (i = 0; i < cid_list->count; i++) { | ||
454 | next_id_string = | ||
455 | acpi_ns_copy_device_id(&info->compatible_id_list. | ||
456 | ids[i], &cid_list->ids[i], | ||
457 | next_id_string); | ||
458 | |||
459 | if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) { | ||
460 | info->flags |= ACPI_PCI_ROOT_BRIDGE; | ||
461 | } | ||
462 | } | ||
352 | } | 463 | } |
353 | 464 | ||
465 | /* Copy the fixed-length data */ | ||
466 | |||
467 | info->info_size = info_size; | ||
468 | info->type = type; | ||
469 | info->name = name; | ||
470 | info->param_count = param_count; | ||
471 | info->valid = valid; | ||
472 | |||
473 | *return_buffer = info; | ||
474 | status = AE_OK; | ||
475 | |||
354 | cleanup: | 476 | cleanup: |
355 | ACPI_FREE(info); | 477 | if (hid) { |
478 | ACPI_FREE(hid); | ||
479 | } | ||
480 | if (uid) { | ||
481 | ACPI_FREE(uid); | ||
482 | } | ||
356 | if (cid_list) { | 483 | if (cid_list) { |
357 | ACPI_FREE(cid_list); | 484 | ACPI_FREE(cid_list); |
358 | } | 485 | } |