aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-12-16 14:07:29 -0500
committerLen Brown <len.brown@intel.com>2009-12-16 14:07:29 -0500
commit2900681b25d5a1a1a7b39ab66da3b8c6b1b0b7ad (patch)
tree3c6969f0333f1255a4751086dd1131d5bbc5a157 /drivers/acpi
parent243e1ef842ef9e24fbf1cc7ddf4fd1c01471544a (diff)
parent3563ff964fdc36358cef0330936fdac28e65142a (diff)
Merge branch 'osc' into release
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/bus.c148
-rw-r--r--drivers/acpi/pci_root.c76
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
345EXPORT_SYMBOL(acpi_bus_can_wakeup); 345EXPORT_SYMBOL(acpi_bus_can_wakeup);
346 346
347static 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
365static u8 hex_val(unsigned char c)
366{
367 return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10;
368}
369
370static 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
392acpi_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 }
459out_success:
460 return AE_OK;
461
462out_kfree:
463 kfree(context->ret.pointer);
464 context->ret.pointer = NULL;
465 return status;
466}
467EXPORT_SYMBOL(acpi_run_osc);
468
469static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
470static 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
205static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 205static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
206 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
207 206
208static acpi_status acpi_pci_run_osc(acpi_handle handle, 207static 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 }
265out_success:
266 *retval = *((u32 *)(out_obj->buffer.pointer + 8));
267 status = AE_OK;
268
269out_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