diff options
author | Len Brown <len.brown@intel.com> | 2009-12-16 14:07:29 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-12-16 14:07:29 -0500 |
commit | 2900681b25d5a1a1a7b39ab66da3b8c6b1b0b7ad (patch) | |
tree | 3c6969f0333f1255a4751086dd1131d5bbc5a157 /drivers/acpi | |
parent | 243e1ef842ef9e24fbf1cc7ddf4fd1c01471544a (diff) | |
parent | 3563ff964fdc36358cef0330936fdac28e65142a (diff) |
Merge branch 'osc' into release
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/bus.c | 148 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 76 |
2 files changed, 162 insertions, 62 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 741191524353..65f7e335f122 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -344,6 +344,152 @@ bool acpi_bus_can_wakeup(acpi_handle handle) | |||
344 | 344 | ||
345 | EXPORT_SYMBOL(acpi_bus_can_wakeup); | 345 | EXPORT_SYMBOL(acpi_bus_can_wakeup); |
346 | 346 | ||
347 | static void acpi_print_osc_error(acpi_handle handle, | ||
348 | struct acpi_osc_context *context, char *error) | ||
349 | { | ||
350 | struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER}; | ||
351 | int i; | ||
352 | |||
353 | if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer))) | ||
354 | printk(KERN_DEBUG "%s\n", error); | ||
355 | else { | ||
356 | printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error); | ||
357 | kfree(buffer.pointer); | ||
358 | } | ||
359 | printk(KERN_DEBUG"_OSC request data:"); | ||
360 | for (i = 0; i < context->cap.length; i += sizeof(u32)) | ||
361 | printk("%x ", *((u32 *)(context->cap.pointer + i))); | ||
362 | printk("\n"); | ||
363 | } | ||
364 | |||
365 | static u8 hex_val(unsigned char c) | ||
366 | { | ||
367 | return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10; | ||
368 | } | ||
369 | |||
370 | static acpi_status acpi_str_to_uuid(char *str, u8 *uuid) | ||
371 | { | ||
372 | int i; | ||
373 | static int opc_map_to_uuid[16] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21, | ||
374 | 24, 26, 28, 30, 32, 34}; | ||
375 | |||
376 | if (strlen(str) != 36) | ||
377 | return AE_BAD_PARAMETER; | ||
378 | for (i = 0; i < 36; i++) { | ||
379 | if (i == 8 || i == 13 || i == 18 || i == 23) { | ||
380 | if (str[i] != '-') | ||
381 | return AE_BAD_PARAMETER; | ||
382 | } else if (!isxdigit(str[i])) | ||
383 | return AE_BAD_PARAMETER; | ||
384 | } | ||
385 | for (i = 0; i < 16; i++) { | ||
386 | uuid[i] = hex_val(str[opc_map_to_uuid[i]]) << 4; | ||
387 | uuid[i] |= hex_val(str[opc_map_to_uuid[i] + 1]); | ||
388 | } | ||
389 | return AE_OK; | ||
390 | } | ||
391 | |||
392 | acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) | ||
393 | { | ||
394 | acpi_status status; | ||
395 | struct acpi_object_list input; | ||
396 | union acpi_object in_params[4]; | ||
397 | union acpi_object *out_obj; | ||
398 | u8 uuid[16]; | ||
399 | u32 errors; | ||
400 | |||
401 | if (!context) | ||
402 | return AE_ERROR; | ||
403 | if (ACPI_FAILURE(acpi_str_to_uuid(context->uuid_str, uuid))) | ||
404 | return AE_ERROR; | ||
405 | context->ret.length = ACPI_ALLOCATE_BUFFER; | ||
406 | context->ret.pointer = NULL; | ||
407 | |||
408 | /* Setting up input parameters */ | ||
409 | input.count = 4; | ||
410 | input.pointer = in_params; | ||
411 | in_params[0].type = ACPI_TYPE_BUFFER; | ||
412 | in_params[0].buffer.length = 16; | ||
413 | in_params[0].buffer.pointer = uuid; | ||
414 | in_params[1].type = ACPI_TYPE_INTEGER; | ||
415 | in_params[1].integer.value = context->rev; | ||
416 | in_params[2].type = ACPI_TYPE_INTEGER; | ||
417 | in_params[2].integer.value = context->cap.length/sizeof(u32); | ||
418 | in_params[3].type = ACPI_TYPE_BUFFER; | ||
419 | in_params[3].buffer.length = context->cap.length; | ||
420 | in_params[3].buffer.pointer = context->cap.pointer; | ||
421 | |||
422 | status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret); | ||
423 | if (ACPI_FAILURE(status)) | ||
424 | return status; | ||
425 | |||
426 | /* return buffer should have the same length as cap buffer */ | ||
427 | if (context->ret.length != context->cap.length) | ||
428 | return AE_NULL_OBJECT; | ||
429 | |||
430 | out_obj = context->ret.pointer; | ||
431 | if (out_obj->type != ACPI_TYPE_BUFFER) { | ||
432 | acpi_print_osc_error(handle, context, | ||
433 | "_OSC evaluation returned wrong type"); | ||
434 | status = AE_TYPE; | ||
435 | goto out_kfree; | ||
436 | } | ||
437 | /* Need to ignore the bit0 in result code */ | ||
438 | errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); | ||
439 | if (errors) { | ||
440 | if (errors & OSC_REQUEST_ERROR) | ||
441 | acpi_print_osc_error(handle, context, | ||
442 | "_OSC request failed"); | ||
443 | if (errors & OSC_INVALID_UUID_ERROR) | ||
444 | acpi_print_osc_error(handle, context, | ||
445 | "_OSC invalid UUID"); | ||
446 | if (errors & OSC_INVALID_REVISION_ERROR) | ||
447 | acpi_print_osc_error(handle, context, | ||
448 | "_OSC invalid revision"); | ||
449 | if (errors & OSC_CAPABILITIES_MASK_ERROR) { | ||
450 | if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE] | ||
451 | & OSC_QUERY_ENABLE) | ||
452 | goto out_success; | ||
453 | status = AE_SUPPORT; | ||
454 | goto out_kfree; | ||
455 | } | ||
456 | status = AE_ERROR; | ||
457 | goto out_kfree; | ||
458 | } | ||
459 | out_success: | ||
460 | return AE_OK; | ||
461 | |||
462 | out_kfree: | ||
463 | kfree(context->ret.pointer); | ||
464 | context->ret.pointer = NULL; | ||
465 | return status; | ||
466 | } | ||
467 | EXPORT_SYMBOL(acpi_run_osc); | ||
468 | |||
469 | static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48"; | ||
470 | static void acpi_bus_osc_support(void) | ||
471 | { | ||
472 | u32 capbuf[2]; | ||
473 | struct acpi_osc_context context = { | ||
474 | .uuid_str = sb_uuid_str, | ||
475 | .rev = 1, | ||
476 | .cap.length = 8, | ||
477 | .cap.pointer = capbuf, | ||
478 | }; | ||
479 | acpi_handle handle; | ||
480 | |||
481 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | ||
482 | capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ | ||
483 | #ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR | ||
484 | capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; | ||
485 | #endif | ||
486 | if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) | ||
487 | return; | ||
488 | if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) | ||
489 | kfree(context.ret.pointer); | ||
490 | /* do we need to check the returned cap? Sounds no */ | ||
491 | } | ||
492 | |||
347 | /* -------------------------------------------------------------------------- | 493 | /* -------------------------------------------------------------------------- |
348 | Event Management | 494 | Event Management |
349 | -------------------------------------------------------------------------- */ | 495 | -------------------------------------------------------------------------- */ |
@@ -734,6 +880,8 @@ static int __init acpi_bus_init(void) | |||
734 | status = acpi_ec_ecdt_probe(); | 880 | status = acpi_ec_ecdt_probe(); |
735 | /* Ignore result. Not having an ECDT is not fatal. */ | 881 | /* Ignore result. Not having an ECDT is not fatal. */ |
736 | 882 | ||
883 | acpi_bus_osc_support(); | ||
884 | |||
737 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); | 885 | status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); |
738 | if (ACPI_FAILURE(status)) { | 886 | if (ACPI_FAILURE(status)) { |
739 | printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); | 887 | printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 1af808171d46..101cce3681d1 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -202,72 +202,24 @@ static void acpi_pci_bridge_scan(struct acpi_device *device) | |||
202 | } | 202 | } |
203 | } | 203 | } |
204 | 204 | ||
205 | static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, | 205 | static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; |
206 | 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; | ||
207 | 206 | ||
208 | static acpi_status acpi_pci_run_osc(acpi_handle handle, | 207 | static acpi_status acpi_pci_run_osc(acpi_handle handle, |
209 | const u32 *capbuf, u32 *retval) | 208 | const u32 *capbuf, u32 *retval) |
210 | { | 209 | { |
210 | struct acpi_osc_context context = { | ||
211 | .uuid_str = pci_osc_uuid_str, | ||
212 | .rev = 1, | ||
213 | .cap.length = 12, | ||
214 | .cap.pointer = (void *)capbuf, | ||
215 | }; | ||
211 | acpi_status status; | 216 | acpi_status status; |
212 | struct acpi_object_list input; | ||
213 | union acpi_object in_params[4]; | ||
214 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
215 | union acpi_object *out_obj; | ||
216 | u32 errors; | ||
217 | |||
218 | /* Setting up input parameters */ | ||
219 | input.count = 4; | ||
220 | input.pointer = in_params; | ||
221 | in_params[0].type = ACPI_TYPE_BUFFER; | ||
222 | in_params[0].buffer.length = 16; | ||
223 | in_params[0].buffer.pointer = OSC_UUID; | ||
224 | in_params[1].type = ACPI_TYPE_INTEGER; | ||
225 | in_params[1].integer.value = 1; | ||
226 | in_params[2].type = ACPI_TYPE_INTEGER; | ||
227 | in_params[2].integer.value = 3; | ||
228 | in_params[3].type = ACPI_TYPE_BUFFER; | ||
229 | in_params[3].buffer.length = 12; | ||
230 | in_params[3].buffer.pointer = (u8 *)capbuf; | ||
231 | |||
232 | status = acpi_evaluate_object(handle, "_OSC", &input, &output); | ||
233 | if (ACPI_FAILURE(status)) | ||
234 | return status; | ||
235 | 217 | ||
236 | if (!output.length) | 218 | status = acpi_run_osc(handle, &context); |
237 | return AE_NULL_OBJECT; | 219 | if (ACPI_SUCCESS(status)) { |
238 | 220 | *retval = *((u32 *)(context.ret.pointer + 8)); | |
239 | out_obj = output.pointer; | 221 | kfree(context.ret.pointer); |
240 | if (out_obj->type != ACPI_TYPE_BUFFER) { | ||
241 | printk(KERN_DEBUG "_OSC evaluation returned wrong type\n"); | ||
242 | status = AE_TYPE; | ||
243 | goto out_kfree; | ||
244 | } | ||
245 | /* Need to ignore the bit0 in result code */ | ||
246 | errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); | ||
247 | if (errors) { | ||
248 | if (errors & OSC_REQUEST_ERROR) | ||
249 | printk(KERN_DEBUG "_OSC request failed\n"); | ||
250 | if (errors & OSC_INVALID_UUID_ERROR) | ||
251 | printk(KERN_DEBUG "_OSC invalid UUID\n"); | ||
252 | if (errors & OSC_INVALID_REVISION_ERROR) | ||
253 | printk(KERN_DEBUG "_OSC invalid revision\n"); | ||
254 | if (errors & OSC_CAPABILITIES_MASK_ERROR) { | ||
255 | if (capbuf[OSC_QUERY_TYPE] & OSC_QUERY_ENABLE) | ||
256 | goto out_success; | ||
257 | printk(KERN_DEBUG | ||
258 | "Firmware did not grant requested _OSC control\n"); | ||
259 | status = AE_SUPPORT; | ||
260 | goto out_kfree; | ||
261 | } | ||
262 | status = AE_ERROR; | ||
263 | goto out_kfree; | ||
264 | } | 222 | } |
265 | out_success: | ||
266 | *retval = *((u32 *)(out_obj->buffer.pointer + 8)); | ||
267 | status = AE_OK; | ||
268 | |||
269 | out_kfree: | ||
270 | kfree(output.pointer); | ||
271 | return status; | 223 | return status; |
272 | } | 224 | } |
273 | 225 | ||
@@ -277,10 +229,10 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags) | |||
277 | u32 support_set, result, capbuf[3]; | 229 | u32 support_set, result, capbuf[3]; |
278 | 230 | ||
279 | /* do _OSC query for all possible controls */ | 231 | /* do _OSC query for all possible controls */ |
280 | support_set = root->osc_support_set | (flags & OSC_SUPPORT_MASKS); | 232 | support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS); |
281 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | 233 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; |
282 | capbuf[OSC_SUPPORT_TYPE] = support_set; | 234 | capbuf[OSC_SUPPORT_TYPE] = support_set; |
283 | capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; | 235 | capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; |
284 | 236 | ||
285 | status = acpi_pci_run_osc(root->device->handle, capbuf, &result); | 237 | status = acpi_pci_run_osc(root->device->handle, capbuf, &result); |
286 | if (ACPI_SUCCESS(status)) { | 238 | if (ACPI_SUCCESS(status)) { |
@@ -427,7 +379,7 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) | |||
427 | if (ACPI_FAILURE(status)) | 379 | if (ACPI_FAILURE(status)) |
428 | return status; | 380 | return status; |
429 | 381 | ||
430 | control_req = (flags & OSC_CONTROL_MASKS); | 382 | control_req = (flags & OSC_PCI_CONTROL_MASKS); |
431 | if (!control_req) | 383 | if (!control_req) |
432 | return AE_TYPE; | 384 | return AE_TYPE; |
433 | 385 | ||