aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/nsxfname.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 12:32:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 12:32:11 -0400
commitc11f6c82581e8be4e1829c677db54e7f55cebece (patch)
tree1a116241b0831ded998aabe800bdc24104cbd826 /drivers/acpi/acpica/nsxfname.c
parent40aba218969914d1b225e742617adb921cf94eae (diff)
parent193a6dec1c0246a80b6d0101e4f351ccf877bcac (diff)
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (119 commits) ACPI: don't pass handle for fixed hardware notifications ACPI: remove null pointer checks in deferred execution path ACPI: simplify deferred execution path acerhdf: additional BIOS versions acerhdf: convert to dev_pm_ops acerhdf: fix fan control for AOA150 model thermal: add missing Kconfig dependency acpi: switch /proc/acpi/{debug_layer,debug_level} to seq_file hp-wmi: fix rfkill memory leak on unload ACPI: remove unnecessary #ifdef CONFIG_DMI ACPI: linux/acpi.h should not include linux/dmi.h hwmon driver for ACPI 4.0 power meters topstar-laptop: add new driver for hotkeys support on Topstar N01 thinkpad_acpi: fix rfkill memory leak on unload thinkpad-acpi: report brightness events when required thinkpad-acpi: don't poll by default any of the reserved hotkeys thinkpad-acpi: Fix procfs hotkey reset command thinkpad-acpi: deprecate hotkey_bios_mask thinkpad-acpi: hotkey poll fixes thinkpad-acpi: be more strict when detecting a ThinkPad ...
Diffstat (limited to 'drivers/acpi/acpica/nsxfname.c')
-rw-r--r--drivers/acpi/acpica/nsxfname.c237
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
52ACPI_MODULE_NAME("nsxfname") 52ACPI_MODULE_NAME("nsxfname")
53 53
54/* Local prototypes */
55static 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
71acpi_status 77acpi_status
72acpi_get_handle(acpi_handle parent, 78acpi_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 ******************************************************************************/
230static 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
225acpi_status 265acpi_status
226acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) 266acpi_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 }