diff options
Diffstat (limited to 'drivers')
151 files changed, 5587 insertions, 2923 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index b4f5e8542829..c52fca833268 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -140,6 +140,7 @@ config ACPI_VIDEO | |||
140 | tristate "Video" | 140 | tristate "Video" |
141 | depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL | 141 | depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL |
142 | depends on INPUT | 142 | depends on INPUT |
143 | select THERMAL | ||
143 | help | 144 | help |
144 | This driver implement the ACPI Extensions For Display Adapters | 145 | This driver implement the ACPI Extensions For Display Adapters |
145 | for integrated graphics devices on motherboard, as specified in | 146 | for integrated graphics devices on motherboard, as specified in |
@@ -151,6 +152,7 @@ config ACPI_VIDEO | |||
151 | 152 | ||
152 | config ACPI_FAN | 153 | config ACPI_FAN |
153 | tristate "Fan" | 154 | tristate "Fan" |
155 | select THERMAL | ||
154 | default y | 156 | default y |
155 | help | 157 | help |
156 | This driver adds support for ACPI fan devices, allowing user-mode | 158 | This driver adds support for ACPI fan devices, allowing user-mode |
@@ -172,6 +174,7 @@ config ACPI_BAY | |||
172 | 174 | ||
173 | config ACPI_PROCESSOR | 175 | config ACPI_PROCESSOR |
174 | tristate "Processor" | 176 | tristate "Processor" |
177 | select THERMAL | ||
175 | default y | 178 | default y |
176 | help | 179 | help |
177 | This driver installs ACPI as the idle handler for Linux, and uses | 180 | This driver installs ACPI as the idle handler for Linux, and uses |
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index 1fa86811b8ee..d2fc94161848 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c | |||
@@ -201,6 +201,7 @@ static int is_ejectable_bay(acpi_handle handle) | |||
201 | return 0; | 201 | return 0; |
202 | } | 202 | } |
203 | 203 | ||
204 | #if 0 | ||
204 | /** | 205 | /** |
205 | * eject_removable_drive - try to eject this drive | 206 | * eject_removable_drive - try to eject this drive |
206 | * @dev : the device structure of the drive | 207 | * @dev : the device structure of the drive |
@@ -225,6 +226,7 @@ int eject_removable_drive(struct device *dev) | |||
225 | return 0; | 226 | return 0; |
226 | } | 227 | } |
227 | EXPORT_SYMBOL_GPL(eject_removable_drive); | 228 | EXPORT_SYMBOL_GPL(eject_removable_drive); |
229 | #endif /* 0 */ | ||
228 | 230 | ||
229 | static int acpi_bay_add_fs(struct bay *bay) | 231 | static int acpi_bay_add_fs(struct bay *bay) |
230 | { | 232 | { |
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c index f049639bac35..c78078315be9 100644 --- a/drivers/acpi/dispatcher/dsfield.c +++ b/drivers/acpi/dispatcher/dsfield.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -89,12 +89,16 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, | |||
89 | 89 | ||
90 | ACPI_FUNCTION_TRACE(ds_create_buffer_field); | 90 | ACPI_FUNCTION_TRACE(ds_create_buffer_field); |
91 | 91 | ||
92 | /* Get the name_string argument */ | 92 | /* |
93 | 93 | * Get the name_string argument (name of the new buffer_field) | |
94 | */ | ||
94 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { | 95 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { |
96 | |||
97 | /* For create_field, name is the 4th argument */ | ||
98 | |||
95 | arg = acpi_ps_get_arg(op, 3); | 99 | arg = acpi_ps_get_arg(op, 3); |
96 | } else { | 100 | } else { |
97 | /* Create Bit/Byte/Word/Dword field */ | 101 | /* For all other create_xXXField operators, name is the 3rd argument */ |
98 | 102 | ||
99 | arg = acpi_ps_get_arg(op, 2); | 103 | arg = acpi_ps_get_arg(op, 2); |
100 | } | 104 | } |
@@ -107,26 +111,30 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, | |||
107 | node = walk_state->deferred_node; | 111 | node = walk_state->deferred_node; |
108 | status = AE_OK; | 112 | status = AE_OK; |
109 | } else { | 113 | } else { |
110 | /* | 114 | /* Execute flag should always be set when this function is entered */ |
111 | * During the load phase, we want to enter the name of the field into | 115 | |
112 | * the namespace. During the execute phase (when we evaluate the size | 116 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { |
113 | * operand), we want to lookup the name | 117 | return_ACPI_STATUS(AE_AML_INTERNAL); |
114 | */ | ||
115 | if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) { | ||
116 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE; | ||
117 | } else { | ||
118 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | ||
119 | ACPI_NS_ERROR_IF_FOUND; | ||
120 | } | 118 | } |
121 | 119 | ||
122 | /* | 120 | /* Creating new namespace node, should not already exist */ |
123 | * Enter the name_string into the namespace | 121 | |
124 | */ | 122 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | |
123 | ACPI_NS_ERROR_IF_FOUND; | ||
124 | |||
125 | /* Mark node temporary if we are executing a method */ | ||
126 | |||
127 | if (walk_state->method_node) { | ||
128 | flags |= ACPI_NS_TEMPORARY; | ||
129 | } | ||
130 | |||
131 | /* Enter the name_string into the namespace */ | ||
132 | |||
125 | status = | 133 | status = |
126 | acpi_ns_lookup(walk_state->scope_info, | 134 | acpi_ns_lookup(walk_state->scope_info, |
127 | arg->common.value.string, ACPI_TYPE_ANY, | 135 | arg->common.value.string, ACPI_TYPE_ANY, |
128 | ACPI_IMODE_LOAD_PASS1, flags, walk_state, | 136 | ACPI_IMODE_LOAD_PASS1, flags, walk_state, |
129 | &(node)); | 137 | &node); |
130 | if (ACPI_FAILURE(status)) { | 138 | if (ACPI_FAILURE(status)) { |
131 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | 139 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); |
132 | return_ACPI_STATUS(status); | 140 | return_ACPI_STATUS(status); |
@@ -136,13 +144,13 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, | |||
136 | /* | 144 | /* |
137 | * We could put the returned object (Node) on the object stack for later, | 145 | * We could put the returned object (Node) on the object stack for later, |
138 | * but for now, we will put it in the "op" object that the parser uses, | 146 | * but for now, we will put it in the "op" object that the parser uses, |
139 | * so we can get it again at the end of this scope | 147 | * so we can get it again at the end of this scope. |
140 | */ | 148 | */ |
141 | op->common.node = node; | 149 | op->common.node = node; |
142 | 150 | ||
143 | /* | 151 | /* |
144 | * If there is no object attached to the node, this node was just created | 152 | * If there is no object attached to the node, this node was just created |
145 | * and we need to create the field object. Otherwise, this was a lookup | 153 | * and we need to create the field object. Otherwise, this was a lookup |
146 | * of an existing node and we don't want to create the field object again. | 154 | * of an existing node and we don't want to create the field object again. |
147 | */ | 155 | */ |
148 | obj_desc = acpi_ns_get_attached_object(node); | 156 | obj_desc = acpi_ns_get_attached_object(node); |
@@ -164,9 +172,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, | |||
164 | } | 172 | } |
165 | 173 | ||
166 | /* | 174 | /* |
167 | * Remember location in AML stream of the field unit | 175 | * Remember location in AML stream of the field unit opcode and operands -- |
168 | * opcode and operands -- since the buffer and index | 176 | * since the buffer and index operands must be evaluated. |
169 | * operands must be evaluated. | ||
170 | */ | 177 | */ |
171 | second_desc = obj_desc->common.next_object; | 178 | second_desc = obj_desc->common.next_object; |
172 | second_desc->extra.aml_start = op->named.data; | 179 | second_desc->extra.aml_start = op->named.data; |
@@ -261,7 +268,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, | |||
261 | 268 | ||
262 | case AML_INT_NAMEDFIELD_OP: | 269 | case AML_INT_NAMEDFIELD_OP: |
263 | 270 | ||
264 | /* Lookup the name */ | 271 | /* Lookup the name, it should already exist */ |
265 | 272 | ||
266 | status = acpi_ns_lookup(walk_state->scope_info, | 273 | status = acpi_ns_lookup(walk_state->scope_info, |
267 | (char *)&arg->named.name, | 274 | (char *)&arg->named.name, |
@@ -272,20 +279,23 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, | |||
272 | if (ACPI_FAILURE(status)) { | 279 | if (ACPI_FAILURE(status)) { |
273 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | 280 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, |
274 | status); | 281 | status); |
275 | if (status != AE_ALREADY_EXISTS) { | 282 | return_ACPI_STATUS(status); |
276 | return_ACPI_STATUS(status); | ||
277 | } | ||
278 | |||
279 | /* Already exists, ignore error */ | ||
280 | } else { | 283 | } else { |
281 | arg->common.node = info->field_node; | 284 | arg->common.node = info->field_node; |
282 | info->field_bit_length = arg->common.value.size; | 285 | info->field_bit_length = arg->common.value.size; |
283 | 286 | ||
284 | /* Create and initialize an object for the new Field Node */ | 287 | /* |
285 | 288 | * If there is no object attached to the node, this node was | |
286 | status = acpi_ex_prep_field_value(info); | 289 | * just created and we need to create the field object. |
287 | if (ACPI_FAILURE(status)) { | 290 | * Otherwise, this was a lookup of an existing node and we |
288 | return_ACPI_STATUS(status); | 291 | * don't want to create the field object again. |
292 | */ | ||
293 | if (!acpi_ns_get_attached_object | ||
294 | (info->field_node)) { | ||
295 | status = acpi_ex_prep_field_value(info); | ||
296 | if (ACPI_FAILURE(status)) { | ||
297 | return_ACPI_STATUS(status); | ||
298 | } | ||
289 | } | 299 | } |
290 | } | 300 | } |
291 | 301 | ||
@@ -399,9 +409,27 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
399 | union acpi_parse_object *arg = NULL; | 409 | union acpi_parse_object *arg = NULL; |
400 | struct acpi_namespace_node *node; | 410 | struct acpi_namespace_node *node; |
401 | u8 type = 0; | 411 | u8 type = 0; |
412 | u32 flags; | ||
402 | 413 | ||
403 | ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); | 414 | ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); |
404 | 415 | ||
416 | /* Execute flag should always be set when this function is entered */ | ||
417 | |||
418 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { | ||
419 | if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { | ||
420 | |||
421 | /* bank_field Op is deferred, just return OK */ | ||
422 | |||
423 | return_ACPI_STATUS(AE_OK); | ||
424 | } | ||
425 | |||
426 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * Get the field_list argument for this opcode. This is the start of the | ||
431 | * list of field elements. | ||
432 | */ | ||
405 | switch (walk_state->opcode) { | 433 | switch (walk_state->opcode) { |
406 | case AML_FIELD_OP: | 434 | case AML_FIELD_OP: |
407 | arg = acpi_ps_get_arg(op, 2); | 435 | arg = acpi_ps_get_arg(op, 2); |
@@ -422,20 +450,33 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
422 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 450 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
423 | } | 451 | } |
424 | 452 | ||
453 | if (!arg) { | ||
454 | return_ACPI_STATUS(AE_AML_NO_OPERAND); | ||
455 | } | ||
456 | |||
457 | /* Creating new namespace node(s), should not already exist */ | ||
458 | |||
459 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | ||
460 | ACPI_NS_ERROR_IF_FOUND; | ||
461 | |||
462 | /* Mark node(s) temporary if we are executing a method */ | ||
463 | |||
464 | if (walk_state->method_node) { | ||
465 | flags |= ACPI_NS_TEMPORARY; | ||
466 | } | ||
467 | |||
425 | /* | 468 | /* |
426 | * Walk the list of entries in the field_list | 469 | * Walk the list of entries in the field_list |
427 | */ | 470 | */ |
428 | while (arg) { | 471 | while (arg) { |
429 | 472 | /* | |
430 | /* Ignore OFFSET and ACCESSAS terms here */ | 473 | * Ignore OFFSET and ACCESSAS terms here; we are only interested in the |
431 | 474 | * field names in order to enter them into the namespace. | |
475 | */ | ||
432 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | 476 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { |
433 | status = acpi_ns_lookup(walk_state->scope_info, | 477 | status = acpi_ns_lookup(walk_state->scope_info, |
434 | (char *)&arg->named.name, | 478 | (char *)&arg->named.name, type, |
435 | type, ACPI_IMODE_LOAD_PASS1, | 479 | ACPI_IMODE_LOAD_PASS1, flags, |
436 | ACPI_NS_NO_UPSEARCH | | ||
437 | ACPI_NS_DONT_OPEN_SCOPE | | ||
438 | ACPI_NS_ERROR_IF_FOUND, | ||
439 | walk_state, &node); | 480 | walk_state, &node); |
440 | if (ACPI_FAILURE(status)) { | 481 | if (ACPI_FAILURE(status)) { |
441 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | 482 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, |
@@ -452,7 +493,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
452 | arg->common.node = node; | 493 | arg->common.node = node; |
453 | } | 494 | } |
454 | 495 | ||
455 | /* Move to next field in the list */ | 496 | /* Get the next field element in the list */ |
456 | 497 | ||
457 | arg = arg->common.next; | 498 | arg = arg->common.next; |
458 | } | 499 | } |
@@ -466,7 +507,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, | |||
466 | * | 507 | * |
467 | * PARAMETERS: Op - Op containing the Field definition and args | 508 | * PARAMETERS: Op - Op containing the Field definition and args |
468 | * region_node - Object for the containing Operation Region | 509 | * region_node - Object for the containing Operation Region |
469 | * ` walk_state - Current method state | 510 | * walk_state - Current method state |
470 | * | 511 | * |
471 | * RETURN: Status | 512 | * RETURN: Status |
472 | * | 513 | * |
@@ -513,36 +554,13 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, | |||
513 | return_ACPI_STATUS(status); | 554 | return_ACPI_STATUS(status); |
514 | } | 555 | } |
515 | 556 | ||
516 | /* Third arg is the bank_value */ | 557 | /* |
517 | 558 | * Third arg is the bank_value | |
518 | /* TBD: This arg is a term_arg, not a constant, and must be evaluated */ | 559 | * This arg is a term_arg, not a constant |
519 | 560 | * It will be evaluated later, by acpi_ds_eval_bank_field_operands | |
561 | */ | ||
520 | arg = arg->common.next; | 562 | arg = arg->common.next; |
521 | 563 | ||
522 | /* Currently, only the following constants are supported */ | ||
523 | |||
524 | switch (arg->common.aml_opcode) { | ||
525 | case AML_ZERO_OP: | ||
526 | info.bank_value = 0; | ||
527 | break; | ||
528 | |||
529 | case AML_ONE_OP: | ||
530 | info.bank_value = 1; | ||
531 | break; | ||
532 | |||
533 | case AML_BYTE_OP: | ||
534 | case AML_WORD_OP: | ||
535 | case AML_DWORD_OP: | ||
536 | case AML_QWORD_OP: | ||
537 | info.bank_value = (u32) arg->common.value.integer; | ||
538 | break; | ||
539 | |||
540 | default: | ||
541 | info.bank_value = 0; | ||
542 | ACPI_ERROR((AE_INFO, | ||
543 | "Non-constant BankValue for BankField is not implemented")); | ||
544 | } | ||
545 | |||
546 | /* Fourth arg is the field flags */ | 564 | /* Fourth arg is the field flags */ |
547 | 565 | ||
548 | arg = arg->common.next; | 566 | arg = arg->common.next; |
@@ -553,8 +571,17 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, | |||
553 | info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; | 571 | info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; |
554 | info.region_node = region_node; | 572 | info.region_node = region_node; |
555 | 573 | ||
556 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | 574 | /* |
575 | * Use Info.data_register_node to store bank_field Op | ||
576 | * It's safe because data_register_node will never be used when create bank field | ||
577 | * We store aml_start and aml_length in the bank_field Op for late evaluation | ||
578 | * Used in acpi_ex_prep_field_value(Info) | ||
579 | * | ||
580 | * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? | ||
581 | */ | ||
582 | info.data_register_node = (struct acpi_namespace_node *)op; | ||
557 | 583 | ||
584 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | ||
558 | return_ACPI_STATUS(status); | 585 | return_ACPI_STATUS(status); |
559 | } | 586 | } |
560 | 587 | ||
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c index af923c388520..610b1ee102b0 100644 --- a/drivers/acpi/dispatcher/dsinit.c +++ b/drivers/acpi/dispatcher/dsinit.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index 1cbe61905824..e48a3ea03117 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -42,7 +42,6 @@ | |||
42 | */ | 42 | */ |
43 | 43 | ||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include <acpi/acparser.h> | ||
46 | #include <acpi/amlcode.h> | 45 | #include <acpi/amlcode.h> |
47 | #include <acpi/acdispat.h> | 46 | #include <acpi/acdispat.h> |
48 | #include <acpi/acinterp.h> | 47 | #include <acpi/acinterp.h> |
@@ -102,7 +101,7 @@ acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) | |||
102 | walk_state->opcode, | 101 | walk_state->opcode, |
103 | walk_state->aml_offset, | 102 | walk_state->aml_offset, |
104 | NULL); | 103 | NULL); |
105 | (void)acpi_ex_enter_interpreter(); | 104 | acpi_ex_enter_interpreter(); |
106 | } | 105 | } |
107 | #ifdef ACPI_DISASSEMBLER | 106 | #ifdef ACPI_DISASSEMBLER |
108 | if (ACPI_FAILURE(status)) { | 107 | if (ACPI_FAILURE(status)) { |
@@ -232,9 +231,9 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, | |||
232 | * recursive call. | 231 | * recursive call. |
233 | */ | 232 | */ |
234 | if (!walk_state || | 233 | if (!walk_state || |
235 | !obj_desc->method.mutex->mutex.owner_thread || | 234 | !obj_desc->method.mutex->mutex.thread_id || |
236 | (walk_state->thread != | 235 | (walk_state->thread->thread_id != |
237 | obj_desc->method.mutex->mutex.owner_thread)) { | 236 | obj_desc->method.mutex->mutex.thread_id)) { |
238 | /* | 237 | /* |
239 | * Acquire the method mutex. This releases the interpreter if we | 238 | * Acquire the method mutex. This releases the interpreter if we |
240 | * block (and reacquires it before it returns) | 239 | * block (and reacquires it before it returns) |
@@ -254,8 +253,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, | |||
254 | original_sync_level = | 253 | original_sync_level = |
255 | walk_state->thread->current_sync_level; | 254 | walk_state->thread->current_sync_level; |
256 | 255 | ||
257 | obj_desc->method.mutex->mutex.owner_thread = | 256 | obj_desc->method.mutex->mutex.thread_id = |
258 | walk_state->thread; | 257 | walk_state->thread->thread_id; |
259 | walk_state->thread->current_sync_level = | 258 | walk_state->thread->current_sync_level = |
260 | obj_desc->method.sync_level; | 259 | obj_desc->method.sync_level; |
261 | } else { | 260 | } else { |
@@ -535,8 +534,6 @@ void | |||
535 | acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | 534 | acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, |
536 | struct acpi_walk_state *walk_state) | 535 | struct acpi_walk_state *walk_state) |
537 | { | 536 | { |
538 | struct acpi_namespace_node *method_node; | ||
539 | acpi_status status; | ||
540 | 537 | ||
541 | ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state); | 538 | ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state); |
542 | 539 | ||
@@ -551,34 +548,26 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
551 | /* Delete all arguments and locals */ | 548 | /* Delete all arguments and locals */ |
552 | 549 | ||
553 | acpi_ds_method_data_delete_all(walk_state); | 550 | acpi_ds_method_data_delete_all(walk_state); |
554 | } | ||
555 | 551 | ||
556 | /* | 552 | /* |
557 | * If method is serialized, release the mutex and restore the | 553 | * If method is serialized, release the mutex and restore the |
558 | * current sync level for this thread | 554 | * current sync level for this thread |
559 | */ | 555 | */ |
560 | if (method_desc->method.mutex) { | 556 | if (method_desc->method.mutex) { |
561 | 557 | ||
562 | /* Acquisition Depth handles recursive calls */ | 558 | /* Acquisition Depth handles recursive calls */ |
563 | 559 | ||
564 | method_desc->method.mutex->mutex.acquisition_depth--; | 560 | method_desc->method.mutex->mutex.acquisition_depth--; |
565 | if (!method_desc->method.mutex->mutex.acquisition_depth) { | 561 | if (!method_desc->method.mutex->mutex.acquisition_depth) { |
566 | walk_state->thread->current_sync_level = | 562 | walk_state->thread->current_sync_level = |
567 | method_desc->method.mutex->mutex. | 563 | method_desc->method.mutex->mutex. |
568 | original_sync_level; | 564 | original_sync_level; |
569 | 565 | ||
570 | acpi_os_release_mutex(method_desc->method.mutex->mutex. | 566 | acpi_os_release_mutex(method_desc->method. |
571 | os_mutex); | 567 | mutex->mutex.os_mutex); |
572 | method_desc->method.mutex->mutex.owner_thread = NULL; | 568 | method_desc->method.mutex->mutex.thread_id = 0; |
569 | } | ||
573 | } | 570 | } |
574 | } | ||
575 | |||
576 | if (walk_state) { | ||
577 | /* | ||
578 | * Delete any objects created by this method during execution. | ||
579 | * The method Node is stored in the walk state | ||
580 | */ | ||
581 | method_node = walk_state->method_node; | ||
582 | 571 | ||
583 | /* | 572 | /* |
584 | * Delete any namespace objects created anywhere within | 573 | * Delete any namespace objects created anywhere within |
@@ -620,7 +609,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | |||
620 | */ | 609 | */ |
621 | if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) | 610 | if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) |
622 | && (!method_desc->method.mutex)) { | 611 | && (!method_desc->method.mutex)) { |
623 | status = acpi_ds_create_method_mutex(method_desc); | 612 | (void)acpi_ds_create_method_mutex(method_desc); |
624 | } | 613 | } |
625 | 614 | ||
626 | /* No more threads, we can free the owner_id */ | 615 | /* No more threads, we can free the owner_id */ |
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c index ba4626e06a5e..13c43eac35db 100644 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ b/drivers/acpi/dispatcher/dsmthdat.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c index 954ac8ce958a..1022e38994c2 100644 --- a/drivers/acpi/dispatcher/dsobject.c +++ b/drivers/acpi/dispatcher/dsobject.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -157,7 +157,9 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
157 | * will remain as named references. This behavior is not described | 157 | * will remain as named references. This behavior is not described |
158 | * in the ACPI spec, but it appears to be an oversight. | 158 | * in the ACPI spec, but it appears to be an oversight. |
159 | */ | 159 | */ |
160 | obj_desc = (union acpi_operand_object *)op->common.node; | 160 | obj_desc = |
161 | ACPI_CAST_PTR(union acpi_operand_object, | ||
162 | op->common.node); | ||
161 | 163 | ||
162 | status = | 164 | status = |
163 | acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR | 165 | acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR |
@@ -172,7 +174,19 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
172 | switch (op->common.node->type) { | 174 | switch (op->common.node->type) { |
173 | /* | 175 | /* |
174 | * For these types, we need the actual node, not the subobject. | 176 | * For these types, we need the actual node, not the subobject. |
175 | * However, the subobject got an extra reference count above. | 177 | * However, the subobject did not get an extra reference count above. |
178 | * | ||
179 | * TBD: should ex_resolve_node_to_value be changed to fix this? | ||
180 | */ | ||
181 | case ACPI_TYPE_DEVICE: | ||
182 | case ACPI_TYPE_THERMAL: | ||
183 | |||
184 | acpi_ut_add_reference(op->common.node->object); | ||
185 | |||
186 | /*lint -fallthrough */ | ||
187 | /* | ||
188 | * For these types, we need the actual node, not the subobject. | ||
189 | * The subobject got an extra reference count in ex_resolve_node_to_value. | ||
176 | */ | 190 | */ |
177 | case ACPI_TYPE_MUTEX: | 191 | case ACPI_TYPE_MUTEX: |
178 | case ACPI_TYPE_METHOD: | 192 | case ACPI_TYPE_METHOD: |
@@ -180,25 +194,15 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
180 | case ACPI_TYPE_PROCESSOR: | 194 | case ACPI_TYPE_PROCESSOR: |
181 | case ACPI_TYPE_EVENT: | 195 | case ACPI_TYPE_EVENT: |
182 | case ACPI_TYPE_REGION: | 196 | case ACPI_TYPE_REGION: |
183 | case ACPI_TYPE_DEVICE: | ||
184 | case ACPI_TYPE_THERMAL: | ||
185 | 197 | ||
186 | obj_desc = | 198 | /* We will create a reference object for these types below */ |
187 | (union acpi_operand_object *)op->common. | ||
188 | node; | ||
189 | break; | 199 | break; |
190 | 200 | ||
191 | default: | 201 | default: |
192 | break; | 202 | /* |
193 | } | 203 | * All other types - the node was resolved to an actual |
194 | 204 | * object, we are done. | |
195 | /* | 205 | */ |
196 | * If above resolved to an operand object, we are done. Otherwise, | ||
197 | * we have a NS node, we must create the package entry as a named | ||
198 | * reference. | ||
199 | */ | ||
200 | if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != | ||
201 | ACPI_DESC_TYPE_NAMED) { | ||
202 | goto exit; | 206 | goto exit; |
203 | } | 207 | } |
204 | } | 208 | } |
@@ -223,7 +227,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | |||
223 | 227 | ||
224 | exit: | 228 | exit: |
225 | *obj_desc_ptr = obj_desc; | 229 | *obj_desc_ptr = obj_desc; |
226 | return_ACPI_STATUS(AE_OK); | 230 | return_ACPI_STATUS(status); |
227 | } | 231 | } |
228 | 232 | ||
229 | /******************************************************************************* | 233 | /******************************************************************************* |
@@ -369,7 +373,9 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
369 | union acpi_parse_object *parent; | 373 | union acpi_parse_object *parent; |
370 | union acpi_operand_object *obj_desc = NULL; | 374 | union acpi_operand_object *obj_desc = NULL; |
371 | acpi_status status = AE_OK; | 375 | acpi_status status = AE_OK; |
372 | acpi_native_uint i; | 376 | unsigned i; |
377 | u16 index; | ||
378 | u16 reference_count; | ||
373 | 379 | ||
374 | ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); | 380 | ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); |
375 | 381 | ||
@@ -447,13 +453,60 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | |||
447 | package. | 453 | package. |
448 | elements[i]); | 454 | elements[i]); |
449 | } | 455 | } |
456 | |||
457 | if (*obj_desc_ptr) { | ||
458 | |||
459 | /* Existing package, get existing reference count */ | ||
460 | |||
461 | reference_count = | ||
462 | (*obj_desc_ptr)->common.reference_count; | ||
463 | if (reference_count > 1) { | ||
464 | |||
465 | /* Make new element ref count match original ref count */ | ||
466 | |||
467 | for (index = 0; index < (reference_count - 1); | ||
468 | index++) { | ||
469 | acpi_ut_add_reference((obj_desc-> | ||
470 | package. | ||
471 | elements[i])); | ||
472 | } | ||
473 | } | ||
474 | } | ||
475 | |||
450 | arg = arg->common.next; | 476 | arg = arg->common.next; |
451 | } | 477 | } |
452 | 478 | ||
453 | if (!arg) { | 479 | /* Check for match between num_elements and actual length of package_list */ |
480 | |||
481 | if (arg) { | ||
482 | /* | ||
483 | * num_elements was exhausted, but there are remaining elements in the | ||
484 | * package_list. | ||
485 | * | ||
486 | * Note: technically, this is an error, from ACPI spec: "It is an error | ||
487 | * for NumElements to be less than the number of elements in the | ||
488 | * PackageList". However, for now, we just print an error message and | ||
489 | * no exception is returned. | ||
490 | */ | ||
491 | while (arg) { | ||
492 | |||
493 | /* Find out how many elements there really are */ | ||
494 | |||
495 | i++; | ||
496 | arg = arg->common.next; | ||
497 | } | ||
498 | |||
499 | ACPI_ERROR((AE_INFO, | ||
500 | "Package List length (%X) larger than NumElements count (%X), truncated\n", | ||
501 | i, element_count)); | ||
502 | } else if (i < element_count) { | ||
503 | /* | ||
504 | * Arg list (elements) was exhausted, but we did not reach num_elements count. | ||
505 | * Note: this is not an error, the package is padded out with NULLs. | ||
506 | */ | ||
454 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 507 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
455 | "Package List length larger than NumElements count (%X), truncated\n", | 508 | "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n", |
456 | element_count)); | 509 | i, element_count)); |
457 | } | 510 | } |
458 | 511 | ||
459 | obj_desc->package.flags |= AOPOBJ_DATA_VALID; | 512 | obj_desc->package.flags |= AOPOBJ_DATA_VALID; |
@@ -721,6 +774,8 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, | |||
721 | /* Node was saved in Op */ | 774 | /* Node was saved in Op */ |
722 | 775 | ||
723 | obj_desc->reference.node = op->common.node; | 776 | obj_desc->reference.node = op->common.node; |
777 | obj_desc->reference.object = | ||
778 | op->common.node->object; | ||
724 | } | 779 | } |
725 | 780 | ||
726 | obj_desc->reference.opcode = opcode; | 781 | obj_desc->reference.opcode = opcode; |
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c index f501e083aac7..a818e0ddb996 100644 --- a/drivers/acpi/dispatcher/dsopcode.c +++ b/drivers/acpi/dispatcher/dsopcode.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -49,6 +49,7 @@ | |||
49 | #include <acpi/acinterp.h> | 49 | #include <acpi/acinterp.h> |
50 | #include <acpi/acnamesp.h> | 50 | #include <acpi/acnamesp.h> |
51 | #include <acpi/acevents.h> | 51 | #include <acpi/acevents.h> |
52 | #include <acpi/actables.h> | ||
52 | 53 | ||
53 | #define _COMPONENT ACPI_DISPATCHER | 54 | #define _COMPONENT ACPI_DISPATCHER |
54 | ACPI_MODULE_NAME("dsopcode") | 55 | ACPI_MODULE_NAME("dsopcode") |
@@ -219,6 +220,50 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) | |||
219 | 220 | ||
220 | /******************************************************************************* | 221 | /******************************************************************************* |
221 | * | 222 | * |
223 | * FUNCTION: acpi_ds_get_bank_field_arguments | ||
224 | * | ||
225 | * PARAMETERS: obj_desc - A valid bank_field object | ||
226 | * | ||
227 | * RETURN: Status. | ||
228 | * | ||
229 | * DESCRIPTION: Get bank_field bank_value. This implements the late | ||
230 | * evaluation of these field attributes. | ||
231 | * | ||
232 | ******************************************************************************/ | ||
233 | |||
234 | acpi_status | ||
235 | acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) | ||
236 | { | ||
237 | union acpi_operand_object *extra_desc; | ||
238 | struct acpi_namespace_node *node; | ||
239 | acpi_status status; | ||
240 | |||
241 | ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); | ||
242 | |||
243 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
244 | return_ACPI_STATUS(AE_OK); | ||
245 | } | ||
246 | |||
247 | /* Get the AML pointer (method object) and bank_field node */ | ||
248 | |||
249 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
250 | node = obj_desc->bank_field.node; | ||
251 | |||
252 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
253 | (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); | ||
254 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", | ||
255 | acpi_ut_get_node_name(node))); | ||
256 | |||
257 | /* Execute the AML code for the term_arg arguments */ | ||
258 | |||
259 | status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), | ||
260 | extra_desc->extra.aml_length, | ||
261 | extra_desc->extra.aml_start); | ||
262 | return_ACPI_STATUS(status); | ||
263 | } | ||
264 | |||
265 | /******************************************************************************* | ||
266 | * | ||
222 | * FUNCTION: acpi_ds_get_buffer_arguments | 267 | * FUNCTION: acpi_ds_get_buffer_arguments |
223 | * | 268 | * |
224 | * PARAMETERS: obj_desc - A valid Buffer object | 269 | * PARAMETERS: obj_desc - A valid Buffer object |
@@ -770,7 +815,109 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, | |||
770 | 815 | ||
771 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", | 816 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", |
772 | obj_desc, | 817 | obj_desc, |
773 | ACPI_FORMAT_UINT64(obj_desc->region.address), | 818 | ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), |
819 | obj_desc->region.length)); | ||
820 | |||
821 | /* Now the address and length are valid for this opregion */ | ||
822 | |||
823 | obj_desc->region.flags |= AOPOBJ_DATA_VALID; | ||
824 | |||
825 | return_ACPI_STATUS(status); | ||
826 | } | ||
827 | |||
828 | /******************************************************************************* | ||
829 | * | ||
830 | * FUNCTION: acpi_ds_eval_table_region_operands | ||
831 | * | ||
832 | * PARAMETERS: walk_state - Current walk | ||
833 | * Op - A valid region Op object | ||
834 | * | ||
835 | * RETURN: Status | ||
836 | * | ||
837 | * DESCRIPTION: Get region address and length | ||
838 | * Called from acpi_ds_exec_end_op during data_table_region parse tree walk | ||
839 | * | ||
840 | ******************************************************************************/ | ||
841 | |||
842 | acpi_status | ||
843 | acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, | ||
844 | union acpi_parse_object *op) | ||
845 | { | ||
846 | acpi_status status; | ||
847 | union acpi_operand_object *obj_desc; | ||
848 | union acpi_operand_object **operand; | ||
849 | struct acpi_namespace_node *node; | ||
850 | union acpi_parse_object *next_op; | ||
851 | acpi_native_uint table_index; | ||
852 | struct acpi_table_header *table; | ||
853 | |||
854 | ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); | ||
855 | |||
856 | /* | ||
857 | * This is where we evaluate the signature_string and oem_iDString | ||
858 | * and oem_table_iDString of the data_table_region declaration | ||
859 | */ | ||
860 | node = op->common.node; | ||
861 | |||
862 | /* next_op points to signature_string op */ | ||
863 | |||
864 | next_op = op->common.value.arg; | ||
865 | |||
866 | /* | ||
867 | * Evaluate/create the signature_string and oem_iDString | ||
868 | * and oem_table_iDString operands | ||
869 | */ | ||
870 | status = acpi_ds_create_operands(walk_state, next_op); | ||
871 | if (ACPI_FAILURE(status)) { | ||
872 | return_ACPI_STATUS(status); | ||
873 | } | ||
874 | |||
875 | /* | ||
876 | * Resolve the signature_string and oem_iDString | ||
877 | * and oem_table_iDString operands | ||
878 | */ | ||
879 | status = acpi_ex_resolve_operands(op->common.aml_opcode, | ||
880 | ACPI_WALK_OPERANDS, walk_state); | ||
881 | if (ACPI_FAILURE(status)) { | ||
882 | return_ACPI_STATUS(status); | ||
883 | } | ||
884 | |||
885 | ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, | ||
886 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
887 | 1, "after AcpiExResolveOperands"); | ||
888 | |||
889 | operand = &walk_state->operands[0]; | ||
890 | |||
891 | /* Find the ACPI table */ | ||
892 | |||
893 | status = acpi_tb_find_table(operand[0]->string.pointer, | ||
894 | operand[1]->string.pointer, | ||
895 | operand[2]->string.pointer, &table_index); | ||
896 | if (ACPI_FAILURE(status)) { | ||
897 | return_ACPI_STATUS(status); | ||
898 | } | ||
899 | |||
900 | acpi_ut_remove_reference(operand[0]); | ||
901 | acpi_ut_remove_reference(operand[1]); | ||
902 | acpi_ut_remove_reference(operand[2]); | ||
903 | |||
904 | status = acpi_get_table_by_index(table_index, &table); | ||
905 | if (ACPI_FAILURE(status)) { | ||
906 | return_ACPI_STATUS(status); | ||
907 | } | ||
908 | |||
909 | obj_desc = acpi_ns_get_attached_object(node); | ||
910 | if (!obj_desc) { | ||
911 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
912 | } | ||
913 | |||
914 | obj_desc->region.address = | ||
915 | (acpi_physical_address) ACPI_TO_INTEGER(table); | ||
916 | obj_desc->region.length = table->length; | ||
917 | |||
918 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", | ||
919 | obj_desc, | ||
920 | ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), | ||
774 | obj_desc->region.length)); | 921 | obj_desc->region.length)); |
775 | 922 | ||
776 | /* Now the address and length are valid for this opregion */ | 923 | /* Now the address and length are valid for this opregion */ |
@@ -808,6 +955,12 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, | |||
808 | 955 | ||
809 | /* The first operand (for all of these data objects) is the length */ | 956 | /* The first operand (for all of these data objects) is the length */ |
810 | 957 | ||
958 | /* | ||
959 | * Set proper index into operand stack for acpi_ds_obj_stack_push | ||
960 | * invoked inside acpi_ds_create_operand. | ||
961 | */ | ||
962 | walk_state->operand_index = walk_state->num_operands; | ||
963 | |||
811 | status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); | 964 | status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); |
812 | if (ACPI_FAILURE(status)) { | 965 | if (ACPI_FAILURE(status)) { |
813 | return_ACPI_STATUS(status); | 966 | return_ACPI_STATUS(status); |
@@ -878,6 +1031,106 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, | |||
878 | 1031 | ||
879 | /******************************************************************************* | 1032 | /******************************************************************************* |
880 | * | 1033 | * |
1034 | * FUNCTION: acpi_ds_eval_bank_field_operands | ||
1035 | * | ||
1036 | * PARAMETERS: walk_state - Current walk | ||
1037 | * Op - A valid bank_field Op object | ||
1038 | * | ||
1039 | * RETURN: Status | ||
1040 | * | ||
1041 | * DESCRIPTION: Get bank_field bank_value | ||
1042 | * Called from acpi_ds_exec_end_op during bank_field parse tree walk | ||
1043 | * | ||
1044 | ******************************************************************************/ | ||
1045 | |||
1046 | acpi_status | ||
1047 | acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, | ||
1048 | union acpi_parse_object *op) | ||
1049 | { | ||
1050 | acpi_status status; | ||
1051 | union acpi_operand_object *obj_desc; | ||
1052 | union acpi_operand_object *operand_desc; | ||
1053 | struct acpi_namespace_node *node; | ||
1054 | union acpi_parse_object *next_op; | ||
1055 | union acpi_parse_object *arg; | ||
1056 | |||
1057 | ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); | ||
1058 | |||
1059 | /* | ||
1060 | * This is where we evaluate the bank_value field of the | ||
1061 | * bank_field declaration | ||
1062 | */ | ||
1063 | |||
1064 | /* next_op points to the op that holds the Region */ | ||
1065 | |||
1066 | next_op = op->common.value.arg; | ||
1067 | |||
1068 | /* next_op points to the op that holds the Bank Register */ | ||
1069 | |||
1070 | next_op = next_op->common.next; | ||
1071 | |||
1072 | /* next_op points to the op that holds the Bank Value */ | ||
1073 | |||
1074 | next_op = next_op->common.next; | ||
1075 | |||
1076 | /* | ||
1077 | * Set proper index into operand stack for acpi_ds_obj_stack_push | ||
1078 | * invoked inside acpi_ds_create_operand. | ||
1079 | * | ||
1080 | * We use walk_state->Operands[0] to store the evaluated bank_value | ||
1081 | */ | ||
1082 | walk_state->operand_index = 0; | ||
1083 | |||
1084 | status = acpi_ds_create_operand(walk_state, next_op, 0); | ||
1085 | if (ACPI_FAILURE(status)) { | ||
1086 | return_ACPI_STATUS(status); | ||
1087 | } | ||
1088 | |||
1089 | status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); | ||
1090 | if (ACPI_FAILURE(status)) { | ||
1091 | return_ACPI_STATUS(status); | ||
1092 | } | ||
1093 | |||
1094 | ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, | ||
1095 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
1096 | 1, "after AcpiExResolveOperands"); | ||
1097 | |||
1098 | /* | ||
1099 | * Get the bank_value operand and save it | ||
1100 | * (at Top of stack) | ||
1101 | */ | ||
1102 | operand_desc = walk_state->operands[0]; | ||
1103 | |||
1104 | /* Arg points to the start Bank Field */ | ||
1105 | |||
1106 | arg = acpi_ps_get_arg(op, 4); | ||
1107 | while (arg) { | ||
1108 | |||
1109 | /* Ignore OFFSET and ACCESSAS terms here */ | ||
1110 | |||
1111 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | ||
1112 | node = arg->common.node; | ||
1113 | |||
1114 | obj_desc = acpi_ns_get_attached_object(node); | ||
1115 | if (!obj_desc) { | ||
1116 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
1117 | } | ||
1118 | |||
1119 | obj_desc->bank_field.value = | ||
1120 | (u32) operand_desc->integer.value; | ||
1121 | } | ||
1122 | |||
1123 | /* Move to next field in the list */ | ||
1124 | |||
1125 | arg = arg->common.next; | ||
1126 | } | ||
1127 | |||
1128 | acpi_ut_remove_reference(operand_desc); | ||
1129 | return_ACPI_STATUS(status); | ||
1130 | } | ||
1131 | |||
1132 | /******************************************************************************* | ||
1133 | * | ||
881 | * FUNCTION: acpi_ds_exec_begin_control_op | 1134 | * FUNCTION: acpi_ds_exec_begin_control_op |
882 | * | 1135 | * |
883 | * PARAMETERS: walk_list - The list that owns the walk stack | 1136 | * PARAMETERS: walk_list - The list that owns the walk stack |
@@ -1070,8 +1323,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, | |||
1070 | * is set to anything other than zero! | 1323 | * is set to anything other than zero! |
1071 | */ | 1324 | */ |
1072 | walk_state->return_desc = walk_state->operands[0]; | 1325 | walk_state->return_desc = walk_state->operands[0]; |
1073 | } else if ((walk_state->results) && | 1326 | } else if (walk_state->result_count) { |
1074 | (walk_state->results->results.num_results > 0)) { | ||
1075 | 1327 | ||
1076 | /* Since we have a real Return(), delete any implicit return */ | 1328 | /* Since we have a real Return(), delete any implicit return */ |
1077 | 1329 | ||
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c index 71503c036f7c..b398982f0d8b 100644 --- a/drivers/acpi/dispatcher/dsutils.c +++ b/drivers/acpi/dispatcher/dsutils.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -278,7 +278,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op, | |||
278 | AML_VAR_PACKAGE_OP) | 278 | AML_VAR_PACKAGE_OP) |
279 | || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) | 279 | || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) |
280 | || (op->common.parent->common.aml_opcode == | 280 | || (op->common.parent->common.aml_opcode == |
281 | AML_INT_EVAL_SUBTREE_OP)) { | 281 | AML_INT_EVAL_SUBTREE_OP) |
282 | || (op->common.parent->common.aml_opcode == | ||
283 | AML_BANK_FIELD_OP)) { | ||
282 | /* | 284 | /* |
283 | * These opcodes allow term_arg(s) as operands and therefore | 285 | * These opcodes allow term_arg(s) as operands and therefore |
284 | * the operands can be method calls. The result is used. | 286 | * the operands can be method calls. The result is used. |
@@ -472,7 +474,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
472 | /* A valid name must be looked up in the namespace */ | 474 | /* A valid name must be looked up in the namespace */ |
473 | 475 | ||
474 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && | 476 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && |
475 | (arg->common.value.string)) { | 477 | (arg->common.value.string) && |
478 | !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
476 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", | 479 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", |
477 | arg)); | 480 | arg)); |
478 | 481 | ||
@@ -595,7 +598,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
595 | } else { | 598 | } else { |
596 | /* Check for null name case */ | 599 | /* Check for null name case */ |
597 | 600 | ||
598 | if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) { | 601 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && |
602 | !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
599 | /* | 603 | /* |
600 | * If the name is null, this means that this is an | 604 | * If the name is null, this means that this is an |
601 | * optional result parameter that was not specified | 605 | * optional result parameter that was not specified |
@@ -617,7 +621,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
617 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); | 621 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); |
618 | } | 622 | } |
619 | 623 | ||
620 | if (op_info->flags & AML_HAS_RETVAL) { | 624 | if ((op_info->flags & AML_HAS_RETVAL) |
625 | || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
621 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 626 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, |
622 | "Argument previously created, already stacked\n")); | 627 | "Argument previously created, already stacked\n")); |
623 | 628 | ||
@@ -630,9 +635,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, | |||
630 | * Use value that was already previously returned | 635 | * Use value that was already previously returned |
631 | * by the evaluation of this argument | 636 | * by the evaluation of this argument |
632 | */ | 637 | */ |
633 | status = | 638 | status = acpi_ds_result_pop(&obj_desc, walk_state); |
634 | acpi_ds_result_pop_from_bottom(&obj_desc, | ||
635 | walk_state); | ||
636 | if (ACPI_FAILURE(status)) { | 639 | if (ACPI_FAILURE(status)) { |
637 | /* | 640 | /* |
638 | * Only error is underflow, and this indicates | 641 | * Only error is underflow, and this indicates |
@@ -698,27 +701,52 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, | |||
698 | { | 701 | { |
699 | acpi_status status = AE_OK; | 702 | acpi_status status = AE_OK; |
700 | union acpi_parse_object *arg; | 703 | union acpi_parse_object *arg; |
704 | union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS]; | ||
701 | u32 arg_count = 0; | 705 | u32 arg_count = 0; |
706 | u32 index = walk_state->num_operands; | ||
707 | u32 i; | ||
702 | 708 | ||
703 | ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); | 709 | ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); |
704 | 710 | ||
705 | /* For all arguments in the list... */ | 711 | /* Get all arguments in the list */ |
706 | 712 | ||
707 | arg = first_arg; | 713 | arg = first_arg; |
708 | while (arg) { | 714 | while (arg) { |
709 | status = acpi_ds_create_operand(walk_state, arg, arg_count); | 715 | if (index >= ACPI_OBJ_NUM_OPERANDS) { |
710 | if (ACPI_FAILURE(status)) { | 716 | return_ACPI_STATUS(AE_BAD_DATA); |
711 | goto cleanup; | ||
712 | } | 717 | } |
713 | 718 | ||
714 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | 719 | arguments[index] = arg; |
715 | "Arg #%d (%p) done, Arg1=%p\n", arg_count, | 720 | walk_state->operands[index] = NULL; |
716 | arg, first_arg)); | ||
717 | 721 | ||
718 | /* Move on to next argument, if any */ | 722 | /* Move on to next argument, if any */ |
719 | 723 | ||
720 | arg = arg->common.next; | 724 | arg = arg->common.next; |
721 | arg_count++; | 725 | arg_count++; |
726 | index++; | ||
727 | } | ||
728 | |||
729 | index--; | ||
730 | |||
731 | /* It is the appropriate order to get objects from the Result stack */ | ||
732 | |||
733 | for (i = 0; i < arg_count; i++) { | ||
734 | arg = arguments[index]; | ||
735 | |||
736 | /* Force the filling of the operand stack in inverse order */ | ||
737 | |||
738 | walk_state->operand_index = (u8) index; | ||
739 | |||
740 | status = acpi_ds_create_operand(walk_state, arg, index); | ||
741 | if (ACPI_FAILURE(status)) { | ||
742 | goto cleanup; | ||
743 | } | ||
744 | |||
745 | index--; | ||
746 | |||
747 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
748 | "Arg #%d (%p) done, Arg1=%p\n", index, arg, | ||
749 | first_arg)); | ||
722 | } | 750 | } |
723 | 751 | ||
724 | return_ACPI_STATUS(status); | 752 | return_ACPI_STATUS(status); |
@@ -729,9 +757,112 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, | |||
729 | * pop everything off of the operand stack and delete those | 757 | * pop everything off of the operand stack and delete those |
730 | * objects | 758 | * objects |
731 | */ | 759 | */ |
732 | (void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); | 760 | acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); |
761 | |||
762 | ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); | ||
763 | return_ACPI_STATUS(status); | ||
764 | } | ||
765 | |||
766 | /***************************************************************************** | ||
767 | * | ||
768 | * FUNCTION: acpi_ds_evaluate_name_path | ||
769 | * | ||
770 | * PARAMETERS: walk_state - Current state of the parse tree walk, | ||
771 | * the opcode of current operation should be | ||
772 | * AML_INT_NAMEPATH_OP | ||
773 | * | ||
774 | * RETURN: Status | ||
775 | * | ||
776 | * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent | ||
777 | * interpreter object, convert it to value, if needed, duplicate | ||
778 | * it, if needed, and push it onto the current result stack. | ||
779 | * | ||
780 | ****************************************************************************/ | ||
781 | |||
782 | acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) | ||
783 | { | ||
784 | acpi_status status = AE_OK; | ||
785 | union acpi_parse_object *op = walk_state->op; | ||
786 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
787 | union acpi_operand_object *new_obj_desc; | ||
788 | u8 type; | ||
789 | |||
790 | ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state); | ||
791 | |||
792 | if (!op->common.parent) { | ||
793 | |||
794 | /* This happens after certain exception processing */ | ||
795 | |||
796 | goto exit; | ||
797 | } | ||
798 | |||
799 | if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || | ||
800 | (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) || | ||
801 | (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) { | ||
802 | |||
803 | /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */ | ||
804 | |||
805 | goto exit; | ||
806 | } | ||
807 | |||
808 | status = acpi_ds_create_operand(walk_state, op, 0); | ||
809 | if (ACPI_FAILURE(status)) { | ||
810 | goto exit; | ||
811 | } | ||
812 | |||
813 | if (op->common.flags & ACPI_PARSEOP_TARGET) { | ||
814 | new_obj_desc = *operand; | ||
815 | goto push_result; | ||
816 | } | ||
817 | |||
818 | type = ACPI_GET_OBJECT_TYPE(*operand); | ||
819 | |||
820 | status = acpi_ex_resolve_to_value(operand, walk_state); | ||
821 | if (ACPI_FAILURE(status)) { | ||
822 | goto exit; | ||
823 | } | ||
824 | |||
825 | if (type == ACPI_TYPE_INTEGER) { | ||
826 | |||
827 | /* It was incremented by acpi_ex_resolve_to_value */ | ||
828 | |||
829 | acpi_ut_remove_reference(*operand); | ||
830 | |||
831 | status = | ||
832 | acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc, | ||
833 | walk_state); | ||
834 | if (ACPI_FAILURE(status)) { | ||
835 | goto exit; | ||
836 | } | ||
837 | } else { | ||
838 | /* | ||
839 | * The object either was anew created or is | ||
840 | * a Namespace node - don't decrement it. | ||
841 | */ | ||
842 | new_obj_desc = *operand; | ||
843 | } | ||
844 | |||
845 | /* Cleanup for name-path operand */ | ||
846 | |||
847 | status = acpi_ds_obj_stack_pop(1, walk_state); | ||
848 | if (ACPI_FAILURE(status)) { | ||
849 | walk_state->result_obj = new_obj_desc; | ||
850 | goto exit; | ||
851 | } | ||
852 | |||
853 | push_result: | ||
854 | |||
855 | walk_state->result_obj = new_obj_desc; | ||
856 | |||
857 | status = acpi_ds_result_push(walk_state->result_obj, walk_state); | ||
858 | if (ACPI_SUCCESS(status)) { | ||
859 | |||
860 | /* Force to take it from stack */ | ||
861 | |||
862 | op->common.flags |= ACPI_PARSEOP_IN_STACK; | ||
863 | } | ||
864 | |||
865 | exit: | ||
733 | 866 | ||
734 | ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", | ||
735 | (arg_count + 1))); | ||
736 | return_ACPI_STATUS(status); | 867 | return_ACPI_STATUS(status); |
737 | } | 868 | } |
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c index 69693fa07224..b246b9657ead 100644 --- a/drivers/acpi/dispatcher/dswexec.c +++ b/drivers/acpi/dispatcher/dswexec.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -285,11 +285,6 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, | |||
285 | switch (opcode_class) { | 285 | switch (opcode_class) { |
286 | case AML_CLASS_CONTROL: | 286 | case AML_CLASS_CONTROL: |
287 | 287 | ||
288 | status = acpi_ds_result_stack_push(walk_state); | ||
289 | if (ACPI_FAILURE(status)) { | ||
290 | goto error_exit; | ||
291 | } | ||
292 | |||
293 | status = acpi_ds_exec_begin_control_op(walk_state, op); | 288 | status = acpi_ds_exec_begin_control_op(walk_state, op); |
294 | break; | 289 | break; |
295 | 290 | ||
@@ -305,20 +300,11 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, | |||
305 | status = acpi_ds_load2_begin_op(walk_state, NULL); | 300 | status = acpi_ds_load2_begin_op(walk_state, NULL); |
306 | } | 301 | } |
307 | 302 | ||
308 | if (op->common.aml_opcode == AML_REGION_OP) { | ||
309 | status = acpi_ds_result_stack_push(walk_state); | ||
310 | } | ||
311 | break; | 303 | break; |
312 | 304 | ||
313 | case AML_CLASS_EXECUTE: | 305 | case AML_CLASS_EXECUTE: |
314 | case AML_CLASS_CREATE: | 306 | case AML_CLASS_CREATE: |
315 | /* | 307 | |
316 | * Most operators with arguments (except create_xxx_field operators) | ||
317 | * Start a new result/operand state | ||
318 | */ | ||
319 | if (walk_state->op_info->object_type != ACPI_TYPE_BUFFER_FIELD) { | ||
320 | status = acpi_ds_result_stack_push(walk_state); | ||
321 | } | ||
322 | break; | 308 | break; |
323 | 309 | ||
324 | default: | 310 | default: |
@@ -374,6 +360,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) | |||
374 | /* Init the walk state */ | 360 | /* Init the walk state */ |
375 | 361 | ||
376 | walk_state->num_operands = 0; | 362 | walk_state->num_operands = 0; |
363 | walk_state->operand_index = 0; | ||
377 | walk_state->return_desc = NULL; | 364 | walk_state->return_desc = NULL; |
378 | walk_state->result_obj = NULL; | 365 | walk_state->result_obj = NULL; |
379 | 366 | ||
@@ -388,10 +375,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) | |||
388 | /* Decode the Opcode Class */ | 375 | /* Decode the Opcode Class */ |
389 | 376 | ||
390 | switch (op_class) { | 377 | switch (op_class) { |
391 | case AML_CLASS_ARGUMENT: /* constants, literals, etc. - do nothing */ | 378 | case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ |
379 | |||
380 | if (walk_state->opcode == AML_INT_NAMEPATH_OP) { | ||
381 | status = acpi_ds_evaluate_name_path(walk_state); | ||
382 | if (ACPI_FAILURE(status)) { | ||
383 | goto cleanup; | ||
384 | } | ||
385 | } | ||
392 | break; | 386 | break; |
393 | 387 | ||
394 | case AML_CLASS_EXECUTE: /* most operators with arguments */ | 388 | case AML_CLASS_EXECUTE: /* Most operators with arguments */ |
395 | 389 | ||
396 | /* Build resolved operand stack */ | 390 | /* Build resolved operand stack */ |
397 | 391 | ||
@@ -400,13 +394,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) | |||
400 | goto cleanup; | 394 | goto cleanup; |
401 | } | 395 | } |
402 | 396 | ||
403 | /* Done with this result state (Now that operand stack is built) */ | ||
404 | |||
405 | status = acpi_ds_result_stack_pop(walk_state); | ||
406 | if (ACPI_FAILURE(status)) { | ||
407 | goto cleanup; | ||
408 | } | ||
409 | |||
410 | /* | 397 | /* |
411 | * All opcodes require operand resolution, with the only exceptions | 398 | * All opcodes require operand resolution, with the only exceptions |
412 | * being the object_type and size_of operators. | 399 | * being the object_type and size_of operators. |
@@ -487,16 +474,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) | |||
487 | 474 | ||
488 | status = acpi_ds_exec_end_control_op(walk_state, op); | 475 | status = acpi_ds_exec_end_control_op(walk_state, op); |
489 | 476 | ||
490 | /* Make sure to properly pop the result stack */ | ||
491 | |||
492 | if (ACPI_SUCCESS(status)) { | ||
493 | status = acpi_ds_result_stack_pop(walk_state); | ||
494 | } else if (status == AE_CTRL_PENDING) { | ||
495 | status = acpi_ds_result_stack_pop(walk_state); | ||
496 | if (ACPI_SUCCESS(status)) { | ||
497 | status = AE_CTRL_PENDING; | ||
498 | } | ||
499 | } | ||
500 | break; | 477 | break; |
501 | 478 | ||
502 | case AML_TYPE_METHOD_CALL: | 479 | case AML_TYPE_METHOD_CALL: |
@@ -516,7 +493,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) | |||
516 | 493 | ||
517 | op->common.node = | 494 | op->common.node = |
518 | (struct acpi_namespace_node *)op->asl.value. | 495 | (struct acpi_namespace_node *)op->asl.value. |
519 | arg->asl.node->object; | 496 | arg->asl.node; |
520 | acpi_ut_add_reference(op->asl.value.arg->asl. | 497 | acpi_ut_add_reference(op->asl.value.arg->asl. |
521 | node->object); | 498 | node->object); |
522 | return_ACPI_STATUS(AE_OK); | 499 | return_ACPI_STATUS(AE_OK); |
@@ -632,13 +609,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) | |||
632 | break; | 609 | break; |
633 | } | 610 | } |
634 | 611 | ||
635 | /* Done with result state (Now that operand stack is built) */ | ||
636 | |||
637 | status = acpi_ds_result_stack_pop(walk_state); | ||
638 | if (ACPI_FAILURE(status)) { | ||
639 | goto cleanup; | ||
640 | } | ||
641 | |||
642 | /* | 612 | /* |
643 | * If a result object was returned from above, push it on the | 613 | * If a result object was returned from above, push it on the |
644 | * current result stack | 614 | * current result stack |
@@ -671,8 +641,28 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) | |||
671 | if (ACPI_FAILURE(status)) { | 641 | if (ACPI_FAILURE(status)) { |
672 | break; | 642 | break; |
673 | } | 643 | } |
644 | } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { | ||
645 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
646 | "Executing DataTableRegion Strings Op=%p\n", | ||
647 | op)); | ||
648 | |||
649 | status = | ||
650 | acpi_ds_eval_table_region_operands | ||
651 | (walk_state, op); | ||
652 | if (ACPI_FAILURE(status)) { | ||
653 | break; | ||
654 | } | ||
655 | } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) { | ||
656 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
657 | "Executing BankField Op=%p\n", | ||
658 | op)); | ||
674 | 659 | ||
675 | status = acpi_ds_result_stack_pop(walk_state); | 660 | status = |
661 | acpi_ds_eval_bank_field_operands(walk_state, | ||
662 | op); | ||
663 | if (ACPI_FAILURE(status)) { | ||
664 | break; | ||
665 | } | ||
676 | } | 666 | } |
677 | break; | 667 | break; |
678 | 668 | ||
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c index 8ab9d1b29a4c..dff7a3e445a8 100644 --- a/drivers/acpi/dispatcher/dswload.c +++ b/drivers/acpi/dispatcher/dswload.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -443,6 +443,15 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) | |||
443 | if (ACPI_FAILURE(status)) { | 443 | if (ACPI_FAILURE(status)) { |
444 | return_ACPI_STATUS(status); | 444 | return_ACPI_STATUS(status); |
445 | } | 445 | } |
446 | } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { | ||
447 | status = | ||
448 | acpi_ex_create_region(op->named.data, | ||
449 | op->named.length, | ||
450 | REGION_DATA_TABLE, | ||
451 | walk_state); | ||
452 | if (ACPI_FAILURE(status)) { | ||
453 | return_ACPI_STATUS(status); | ||
454 | } | ||
446 | } | 455 | } |
447 | } | 456 | } |
448 | #endif | 457 | #endif |
@@ -767,6 +776,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, | |||
767 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | 776 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, |
768 | object_type, ACPI_IMODE_LOAD_PASS2, flags, | 777 | object_type, ACPI_IMODE_LOAD_PASS2, flags, |
769 | walk_state, &node); | 778 | walk_state, &node); |
779 | |||
780 | if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { | ||
781 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
782 | "***New Node [%4.4s] %p is temporary\n", | ||
783 | acpi_ut_get_node_name(node), node)); | ||
784 | } | ||
770 | break; | 785 | break; |
771 | } | 786 | } |
772 | 787 | ||
@@ -823,6 +838,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | |||
823 | struct acpi_namespace_node *new_node; | 838 | struct acpi_namespace_node *new_node; |
824 | #ifndef ACPI_NO_METHOD_EXECUTION | 839 | #ifndef ACPI_NO_METHOD_EXECUTION |
825 | u32 i; | 840 | u32 i; |
841 | u8 region_space; | ||
826 | #endif | 842 | #endif |
827 | 843 | ||
828 | ACPI_FUNCTION_TRACE(ds_load2_end_op); | 844 | ACPI_FUNCTION_TRACE(ds_load2_end_op); |
@@ -1003,11 +1019,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | |||
1003 | status = acpi_ex_create_event(walk_state); | 1019 | status = acpi_ex_create_event(walk_state); |
1004 | break; | 1020 | break; |
1005 | 1021 | ||
1006 | case AML_DATA_REGION_OP: | ||
1007 | |||
1008 | status = acpi_ex_create_table_region(walk_state); | ||
1009 | break; | ||
1010 | |||
1011 | case AML_ALIAS_OP: | 1022 | case AML_ALIAS_OP: |
1012 | 1023 | ||
1013 | status = acpi_ex_create_alias(walk_state); | 1024 | status = acpi_ex_create_alias(walk_state); |
@@ -1035,6 +1046,15 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | |||
1035 | switch (op->common.aml_opcode) { | 1046 | switch (op->common.aml_opcode) { |
1036 | #ifndef ACPI_NO_METHOD_EXECUTION | 1047 | #ifndef ACPI_NO_METHOD_EXECUTION |
1037 | case AML_REGION_OP: | 1048 | case AML_REGION_OP: |
1049 | case AML_DATA_REGION_OP: | ||
1050 | |||
1051 | if (op->common.aml_opcode == AML_REGION_OP) { | ||
1052 | region_space = (acpi_adr_space_type) | ||
1053 | ((op->common.value.arg)->common.value. | ||
1054 | integer); | ||
1055 | } else { | ||
1056 | region_space = REGION_DATA_TABLE; | ||
1057 | } | ||
1038 | 1058 | ||
1039 | /* | 1059 | /* |
1040 | * If we are executing a method, initialize the region | 1060 | * If we are executing a method, initialize the region |
@@ -1043,10 +1063,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | |||
1043 | status = | 1063 | status = |
1044 | acpi_ex_create_region(op->named.data, | 1064 | acpi_ex_create_region(op->named.data, |
1045 | op->named.length, | 1065 | op->named.length, |
1046 | (acpi_adr_space_type) | 1066 | region_space, |
1047 | ((op->common.value. | ||
1048 | arg)->common.value. | ||
1049 | integer), | ||
1050 | walk_state); | 1067 | walk_state); |
1051 | if (ACPI_FAILURE(status)) { | 1068 | if (ACPI_FAILURE(status)) { |
1052 | return (status); | 1069 | return (status); |
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c index 3927c495e4bf..9e6073265873 100644 --- a/drivers/acpi/dispatcher/dswscope.c +++ b/drivers/acpi/dispatcher/dswscope.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c index 5afcdd9c7449..1386ced332ec 100644 --- a/drivers/acpi/dispatcher/dswstate.c +++ b/drivers/acpi/dispatcher/dswstate.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -49,85 +49,9 @@ | |||
49 | #define _COMPONENT ACPI_DISPATCHER | 49 | #define _COMPONENT ACPI_DISPATCHER |
50 | ACPI_MODULE_NAME("dswstate") | 50 | ACPI_MODULE_NAME("dswstate") |
51 | 51 | ||
52 | /* Local prototypes */ | 52 | /* Local prototypes */ |
53 | #ifdef ACPI_OBSOLETE_FUNCTIONS | 53 | static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws); |
54 | acpi_status | 54 | static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws); |
55 | acpi_ds_result_insert(void *object, | ||
56 | u32 index, struct acpi_walk_state *walk_state); | ||
57 | |||
58 | acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state *walk_state); | ||
59 | |||
60 | acpi_status | ||
61 | acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, | ||
62 | struct acpi_walk_state *walk_state); | ||
63 | |||
64 | void *acpi_ds_obj_stack_get_value(u32 index, | ||
65 | struct acpi_walk_state *walk_state); | ||
66 | #endif | ||
67 | |||
68 | #ifdef ACPI_FUTURE_USAGE | ||
69 | /******************************************************************************* | ||
70 | * | ||
71 | * FUNCTION: acpi_ds_result_remove | ||
72 | * | ||
73 | * PARAMETERS: Object - Where to return the popped object | ||
74 | * Index - Where to extract the object | ||
75 | * walk_state - Current Walk state | ||
76 | * | ||
77 | * RETURN: Status | ||
78 | * | ||
79 | * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In | ||
80 | * other words, this is a FIFO. | ||
81 | * | ||
82 | ******************************************************************************/ | ||
83 | |||
84 | acpi_status | ||
85 | acpi_ds_result_remove(union acpi_operand_object **object, | ||
86 | u32 index, struct acpi_walk_state *walk_state) | ||
87 | { | ||
88 | union acpi_generic_state *state; | ||
89 | |||
90 | ACPI_FUNCTION_NAME(ds_result_remove); | ||
91 | |||
92 | state = walk_state->results; | ||
93 | if (!state) { | ||
94 | ACPI_ERROR((AE_INFO, "No result object pushed! State=%p", | ||
95 | walk_state)); | ||
96 | return (AE_NOT_EXIST); | ||
97 | } | ||
98 | |||
99 | if (index >= ACPI_OBJ_MAX_OPERAND) { | ||
100 | ACPI_ERROR((AE_INFO, | ||
101 | "Index out of range: %X State=%p Num=%X", | ||
102 | index, walk_state, state->results.num_results)); | ||
103 | } | ||
104 | |||
105 | /* Check for a valid result object */ | ||
106 | |||
107 | if (!state->results.obj_desc[index]) { | ||
108 | ACPI_ERROR((AE_INFO, | ||
109 | "Null operand! State=%p #Ops=%X, Index=%X", | ||
110 | walk_state, state->results.num_results, index)); | ||
111 | return (AE_AML_NO_RETURN_VALUE); | ||
112 | } | ||
113 | |||
114 | /* Remove the object */ | ||
115 | |||
116 | state->results.num_results--; | ||
117 | |||
118 | *object = state->results.obj_desc[index]; | ||
119 | state->results.obj_desc[index] = NULL; | ||
120 | |||
121 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
122 | "Obj=%p [%s] Index=%X State=%p Num=%X\n", | ||
123 | *object, | ||
124 | (*object) ? acpi_ut_get_object_type_name(*object) : | ||
125 | "NULL", index, walk_state, | ||
126 | state->results.num_results)); | ||
127 | |||
128 | return (AE_OK); | ||
129 | } | ||
130 | #endif /* ACPI_FUTURE_USAGE */ | ||
131 | 55 | ||
132 | /******************************************************************************* | 56 | /******************************************************************************* |
133 | * | 57 | * |
@@ -138,122 +62,67 @@ acpi_ds_result_remove(union acpi_operand_object **object, | |||
138 | * | 62 | * |
139 | * RETURN: Status | 63 | * RETURN: Status |
140 | * | 64 | * |
141 | * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In | 65 | * DESCRIPTION: Pop an object off the top of this walk's result stack |
142 | * other words, this is a FIFO. | ||
143 | * | 66 | * |
144 | ******************************************************************************/ | 67 | ******************************************************************************/ |
145 | 68 | ||
146 | acpi_status | 69 | acpi_status |
147 | acpi_ds_result_pop(union acpi_operand_object ** object, | 70 | acpi_ds_result_pop(union acpi_operand_object **object, |
148 | struct acpi_walk_state * walk_state) | 71 | struct acpi_walk_state *walk_state) |
149 | { | 72 | { |
150 | acpi_native_uint index; | 73 | acpi_native_uint index; |
151 | union acpi_generic_state *state; | 74 | union acpi_generic_state *state; |
75 | acpi_status status; | ||
152 | 76 | ||
153 | ACPI_FUNCTION_NAME(ds_result_pop); | 77 | ACPI_FUNCTION_NAME(ds_result_pop); |
154 | 78 | ||
155 | state = walk_state->results; | 79 | state = walk_state->results; |
156 | if (!state) { | ||
157 | return (AE_OK); | ||
158 | } | ||
159 | |||
160 | if (!state->results.num_results) { | ||
161 | ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", | ||
162 | walk_state)); | ||
163 | return (AE_AML_NO_RETURN_VALUE); | ||
164 | } | ||
165 | 80 | ||
166 | /* Remove top element */ | 81 | /* Incorrect state of result stack */ |
167 | 82 | ||
168 | state->results.num_results--; | 83 | if (state && !walk_state->result_count) { |
169 | 84 | ACPI_ERROR((AE_INFO, "No results on result stack")); | |
170 | for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) { | 85 | return (AE_AML_INTERNAL); |
171 | |||
172 | /* Check for a valid result object */ | ||
173 | |||
174 | if (state->results.obj_desc[index - 1]) { | ||
175 | *object = state->results.obj_desc[index - 1]; | ||
176 | state->results.obj_desc[index - 1] = NULL; | ||
177 | |||
178 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
179 | "Obj=%p [%s] Index=%X State=%p Num=%X\n", | ||
180 | *object, | ||
181 | (*object) ? | ||
182 | acpi_ut_get_object_type_name(*object) | ||
183 | : "NULL", (u32) index - 1, walk_state, | ||
184 | state->results.num_results)); | ||
185 | |||
186 | return (AE_OK); | ||
187 | } | ||
188 | } | 86 | } |
189 | 87 | ||
190 | ACPI_ERROR((AE_INFO, "No result objects! State=%p", walk_state)); | 88 | if (!state && walk_state->result_count) { |
191 | return (AE_AML_NO_RETURN_VALUE); | 89 | ACPI_ERROR((AE_INFO, "No result state for result stack")); |
192 | } | 90 | return (AE_AML_INTERNAL); |
193 | 91 | } | |
194 | /******************************************************************************* | ||
195 | * | ||
196 | * FUNCTION: acpi_ds_result_pop_from_bottom | ||
197 | * | ||
198 | * PARAMETERS: Object - Where to return the popped object | ||
199 | * walk_state - Current Walk state | ||
200 | * | ||
201 | * RETURN: Status | ||
202 | * | ||
203 | * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In | ||
204 | * other words, this is a FIFO. | ||
205 | * | ||
206 | ******************************************************************************/ | ||
207 | |||
208 | acpi_status | ||
209 | acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object, | ||
210 | struct acpi_walk_state * walk_state) | ||
211 | { | ||
212 | acpi_native_uint index; | ||
213 | union acpi_generic_state *state; | ||
214 | 92 | ||
215 | ACPI_FUNCTION_NAME(ds_result_pop_from_bottom); | 93 | /* Empty result stack */ |
216 | 94 | ||
217 | state = walk_state->results; | ||
218 | if (!state) { | 95 | if (!state) { |
219 | ACPI_ERROR((AE_INFO, | 96 | ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", |
220 | "No result object pushed! State=%p", walk_state)); | ||
221 | return (AE_NOT_EXIST); | ||
222 | } | ||
223 | |||
224 | if (!state->results.num_results) { | ||
225 | ACPI_ERROR((AE_INFO, "No result objects! State=%p", | ||
226 | walk_state)); | 97 | walk_state)); |
227 | return (AE_AML_NO_RETURN_VALUE); | 98 | return (AE_AML_NO_RETURN_VALUE); |
228 | } | 99 | } |
229 | 100 | ||
230 | /* Remove Bottom element */ | 101 | /* Return object of the top element and clean that top element result stack */ |
231 | |||
232 | *object = state->results.obj_desc[0]; | ||
233 | |||
234 | /* Push entire stack down one element */ | ||
235 | |||
236 | for (index = 0; index < state->results.num_results; index++) { | ||
237 | state->results.obj_desc[index] = | ||
238 | state->results.obj_desc[index + 1]; | ||
239 | } | ||
240 | 102 | ||
241 | state->results.num_results--; | 103 | walk_state->result_count--; |
242 | 104 | index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; | |
243 | /* Check for a valid result object */ | ||
244 | 105 | ||
106 | *object = state->results.obj_desc[index]; | ||
245 | if (!*object) { | 107 | if (!*object) { |
246 | ACPI_ERROR((AE_INFO, | 108 | ACPI_ERROR((AE_INFO, |
247 | "Null operand! State=%p #Ops=%X Index=%X", | 109 | "No result objects on result stack, State=%p", |
248 | walk_state, state->results.num_results, | 110 | walk_state)); |
249 | (u32) index)); | ||
250 | return (AE_AML_NO_RETURN_VALUE); | 111 | return (AE_AML_NO_RETURN_VALUE); |
251 | } | 112 | } |
252 | 113 | ||
253 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Results=%p State=%p\n", | 114 | state->results.obj_desc[index] = NULL; |
254 | *object, | 115 | if (index == 0) { |
255 | (*object) ? acpi_ut_get_object_type_name(*object) : | 116 | status = acpi_ds_result_stack_pop(walk_state); |
256 | "NULL", state, walk_state)); | 117 | if (ACPI_FAILURE(status)) { |
118 | return (status); | ||
119 | } | ||
120 | } | ||
121 | |||
122 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
123 | "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, | ||
124 | acpi_ut_get_object_type_name(*object), | ||
125 | (u32) index, walk_state, walk_state->result_count)); | ||
257 | 126 | ||
258 | return (AE_OK); | 127 | return (AE_OK); |
259 | } | 128 | } |
@@ -276,39 +145,56 @@ acpi_ds_result_push(union acpi_operand_object * object, | |||
276 | struct acpi_walk_state * walk_state) | 145 | struct acpi_walk_state * walk_state) |
277 | { | 146 | { |
278 | union acpi_generic_state *state; | 147 | union acpi_generic_state *state; |
148 | acpi_status status; | ||
149 | acpi_native_uint index; | ||
279 | 150 | ||
280 | ACPI_FUNCTION_NAME(ds_result_push); | 151 | ACPI_FUNCTION_NAME(ds_result_push); |
281 | 152 | ||
153 | if (walk_state->result_count > walk_state->result_size) { | ||
154 | ACPI_ERROR((AE_INFO, "Result stack is full")); | ||
155 | return (AE_AML_INTERNAL); | ||
156 | } else if (walk_state->result_count == walk_state->result_size) { | ||
157 | |||
158 | /* Extend the result stack */ | ||
159 | |||
160 | status = acpi_ds_result_stack_push(walk_state); | ||
161 | if (ACPI_FAILURE(status)) { | ||
162 | ACPI_ERROR((AE_INFO, | ||
163 | "Failed to extend the result stack")); | ||
164 | return (status); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | if (!(walk_state->result_count < walk_state->result_size)) { | ||
169 | ACPI_ERROR((AE_INFO, "No free elements in result stack")); | ||
170 | return (AE_AML_INTERNAL); | ||
171 | } | ||
172 | |||
282 | state = walk_state->results; | 173 | state = walk_state->results; |
283 | if (!state) { | 174 | if (!state) { |
284 | ACPI_ERROR((AE_INFO, "No result stack frame during push")); | 175 | ACPI_ERROR((AE_INFO, "No result stack frame during push")); |
285 | return (AE_AML_INTERNAL); | 176 | return (AE_AML_INTERNAL); |
286 | } | 177 | } |
287 | 178 | ||
288 | if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) { | ||
289 | ACPI_ERROR((AE_INFO, | ||
290 | "Result stack overflow: Obj=%p State=%p Num=%X", | ||
291 | object, walk_state, state->results.num_results)); | ||
292 | return (AE_STACK_OVERFLOW); | ||
293 | } | ||
294 | |||
295 | if (!object) { | 179 | if (!object) { |
296 | ACPI_ERROR((AE_INFO, | 180 | ACPI_ERROR((AE_INFO, |
297 | "Null Object! Obj=%p State=%p Num=%X", | 181 | "Null Object! Obj=%p State=%p Num=%X", |
298 | object, walk_state, state->results.num_results)); | 182 | object, walk_state, walk_state->result_count)); |
299 | return (AE_BAD_PARAMETER); | 183 | return (AE_BAD_PARAMETER); |
300 | } | 184 | } |
301 | 185 | ||
302 | state->results.obj_desc[state->results.num_results] = object; | 186 | /* Assign the address of object to the top free element of result stack */ |
303 | state->results.num_results++; | 187 | |
188 | index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; | ||
189 | state->results.obj_desc[index] = object; | ||
190 | walk_state->result_count++; | ||
304 | 191 | ||
305 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", | 192 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", |
306 | object, | 193 | object, |
307 | object ? | ||
308 | acpi_ut_get_object_type_name((union | 194 | acpi_ut_get_object_type_name((union |
309 | acpi_operand_object *) | 195 | acpi_operand_object *) |
310 | object) : "NULL", | 196 | object), walk_state, |
311 | walk_state, state->results.num_results, | 197 | walk_state->result_count, |
312 | walk_state->current_result)); | 198 | walk_state->current_result)); |
313 | 199 | ||
314 | return (AE_OK); | 200 | return (AE_OK); |
@@ -322,16 +208,25 @@ acpi_ds_result_push(union acpi_operand_object * object, | |||
322 | * | 208 | * |
323 | * RETURN: Status | 209 | * RETURN: Status |
324 | * | 210 | * |
325 | * DESCRIPTION: Push an object onto the walk_state result stack. | 211 | * DESCRIPTION: Push an object onto the walk_state result stack |
326 | * | 212 | * |
327 | ******************************************************************************/ | 213 | ******************************************************************************/ |
328 | 214 | ||
329 | acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) | 215 | static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state) |
330 | { | 216 | { |
331 | union acpi_generic_state *state; | 217 | union acpi_generic_state *state; |
332 | 218 | ||
333 | ACPI_FUNCTION_NAME(ds_result_stack_push); | 219 | ACPI_FUNCTION_NAME(ds_result_stack_push); |
334 | 220 | ||
221 | /* Check for stack overflow */ | ||
222 | |||
223 | if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) > | ||
224 | ACPI_RESULTS_OBJ_NUM_MAX) { | ||
225 | ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%X", | ||
226 | walk_state, walk_state->result_size)); | ||
227 | return (AE_STACK_OVERFLOW); | ||
228 | } | ||
229 | |||
335 | state = acpi_ut_create_generic_state(); | 230 | state = acpi_ut_create_generic_state(); |
336 | if (!state) { | 231 | if (!state) { |
337 | return (AE_NO_MEMORY); | 232 | return (AE_NO_MEMORY); |
@@ -340,6 +235,10 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) | |||
340 | state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; | 235 | state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; |
341 | acpi_ut_push_generic_state(&walk_state->results, state); | 236 | acpi_ut_push_generic_state(&walk_state->results, state); |
342 | 237 | ||
238 | /* Increase the length of the result stack by the length of frame */ | ||
239 | |||
240 | walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM; | ||
241 | |||
343 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", | 242 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", |
344 | state, walk_state)); | 243 | state, walk_state)); |
345 | 244 | ||
@@ -354,11 +253,11 @@ acpi_status acpi_ds_result_stack_push(struct acpi_walk_state * walk_state) | |||
354 | * | 253 | * |
355 | * RETURN: Status | 254 | * RETURN: Status |
356 | * | 255 | * |
357 | * DESCRIPTION: Pop an object off of the walk_state result stack. | 256 | * DESCRIPTION: Pop an object off of the walk_state result stack |
358 | * | 257 | * |
359 | ******************************************************************************/ | 258 | ******************************************************************************/ |
360 | 259 | ||
361 | acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state) | 260 | static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state) |
362 | { | 261 | { |
363 | union acpi_generic_state *state; | 262 | union acpi_generic_state *state; |
364 | 263 | ||
@@ -367,18 +266,27 @@ acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state * walk_state) | |||
367 | /* Check for stack underflow */ | 266 | /* Check for stack underflow */ |
368 | 267 | ||
369 | if (walk_state->results == NULL) { | 268 | if (walk_state->results == NULL) { |
370 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Underflow - State=%p\n", | 269 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
270 | "Result stack underflow - State=%p\n", | ||
371 | walk_state)); | 271 | walk_state)); |
372 | return (AE_AML_NO_OPERAND); | 272 | return (AE_AML_NO_OPERAND); |
373 | } | 273 | } |
374 | 274 | ||
275 | if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) { | ||
276 | ACPI_ERROR((AE_INFO, "Insufficient result stack size")); | ||
277 | return (AE_AML_INTERNAL); | ||
278 | } | ||
279 | |||
375 | state = acpi_ut_pop_generic_state(&walk_state->results); | 280 | state = acpi_ut_pop_generic_state(&walk_state->results); |
281 | acpi_ut_delete_generic_state(state); | ||
282 | |||
283 | /* Decrease the length of result stack by the length of frame */ | ||
284 | |||
285 | walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM; | ||
376 | 286 | ||
377 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 287 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
378 | "Result=%p RemainingResults=%X State=%p\n", | 288 | "Result=%p RemainingResults=%X State=%p\n", |
379 | state, state->results.num_results, walk_state)); | 289 | state, walk_state->result_count, walk_state)); |
380 | |||
381 | acpi_ut_delete_generic_state(state); | ||
382 | 290 | ||
383 | return (AE_OK); | 291 | return (AE_OK); |
384 | } | 292 | } |
@@ -412,9 +320,13 @@ acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) | |||
412 | 320 | ||
413 | /* Put the object onto the stack */ | 321 | /* Put the object onto the stack */ |
414 | 322 | ||
415 | walk_state->operands[walk_state->num_operands] = object; | 323 | walk_state->operands[walk_state->operand_index] = object; |
416 | walk_state->num_operands++; | 324 | walk_state->num_operands++; |
417 | 325 | ||
326 | /* For the usual order of filling the operand stack */ | ||
327 | |||
328 | walk_state->operand_index++; | ||
329 | |||
418 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", | 330 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", |
419 | object, | 331 | object, |
420 | acpi_ut_get_object_type_name((union | 332 | acpi_ut_get_object_type_name((union |
@@ -484,43 +396,36 @@ acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state) | |||
484 | * | 396 | * |
485 | ******************************************************************************/ | 397 | ******************************************************************************/ |
486 | 398 | ||
487 | acpi_status | 399 | void |
488 | acpi_ds_obj_stack_pop_and_delete(u32 pop_count, | 400 | acpi_ds_obj_stack_pop_and_delete(u32 pop_count, |
489 | struct acpi_walk_state * walk_state) | 401 | struct acpi_walk_state *walk_state) |
490 | { | 402 | { |
491 | u32 i; | 403 | acpi_native_int i; |
492 | union acpi_operand_object *obj_desc; | 404 | union acpi_operand_object *obj_desc; |
493 | 405 | ||
494 | ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); | 406 | ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); |
495 | 407 | ||
496 | for (i = 0; i < pop_count; i++) { | 408 | if (pop_count == 0) { |
497 | 409 | return; | |
498 | /* Check for stack underflow */ | 410 | } |
499 | 411 | ||
412 | for (i = (acpi_native_int) (pop_count - 1); i >= 0; i--) { | ||
500 | if (walk_state->num_operands == 0) { | 413 | if (walk_state->num_operands == 0) { |
501 | ACPI_ERROR((AE_INFO, | 414 | return; |
502 | "Object stack underflow! Count=%X State=%p #Ops=%X", | ||
503 | pop_count, walk_state, | ||
504 | walk_state->num_operands)); | ||
505 | return (AE_STACK_UNDERFLOW); | ||
506 | } | 415 | } |
507 | 416 | ||
508 | /* Pop the stack and delete an object if present in this stack entry */ | 417 | /* Pop the stack and delete an object if present in this stack entry */ |
509 | 418 | ||
510 | walk_state->num_operands--; | 419 | walk_state->num_operands--; |
511 | obj_desc = walk_state->operands[walk_state->num_operands]; | 420 | obj_desc = walk_state->operands[i]; |
512 | if (obj_desc) { | 421 | if (obj_desc) { |
513 | acpi_ut_remove_reference(walk_state-> | 422 | acpi_ut_remove_reference(walk_state->operands[i]); |
514 | operands[walk_state-> | 423 | walk_state->operands[i] = NULL; |
515 | num_operands]); | ||
516 | walk_state->operands[walk_state->num_operands] = NULL; | ||
517 | } | 424 | } |
518 | } | 425 | } |
519 | 426 | ||
520 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", | 427 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", |
521 | pop_count, walk_state, walk_state->num_operands)); | 428 | pop_count, walk_state, walk_state->num_operands)); |
522 | |||
523 | return (AE_OK); | ||
524 | } | 429 | } |
525 | 430 | ||
526 | /******************************************************************************* | 431 | /******************************************************************************* |
@@ -560,7 +465,7 @@ struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state | |||
560 | * | 465 | * |
561 | * RETURN: None | 466 | * RETURN: None |
562 | * | 467 | * |
563 | * DESCRIPTION: Place the Thread state at the head of the state list. | 468 | * DESCRIPTION: Place the Thread state at the head of the state list |
564 | * | 469 | * |
565 | ******************************************************************************/ | 470 | ******************************************************************************/ |
566 | 471 | ||
@@ -636,7 +541,6 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union | |||
636 | *thread) | 541 | *thread) |
637 | { | 542 | { |
638 | struct acpi_walk_state *walk_state; | 543 | struct acpi_walk_state *walk_state; |
639 | acpi_status status; | ||
640 | 544 | ||
641 | ACPI_FUNCTION_TRACE(ds_create_walk_state); | 545 | ACPI_FUNCTION_TRACE(ds_create_walk_state); |
642 | 546 | ||
@@ -659,14 +563,6 @@ struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union | |||
659 | acpi_ds_method_data_init(walk_state); | 563 | acpi_ds_method_data_init(walk_state); |
660 | #endif | 564 | #endif |
661 | 565 | ||
662 | /* Create an initial result stack entry */ | ||
663 | |||
664 | status = acpi_ds_result_stack_push(walk_state); | ||
665 | if (ACPI_FAILURE(status)) { | ||
666 | ACPI_FREE(walk_state); | ||
667 | return_PTR(NULL); | ||
668 | } | ||
669 | |||
670 | /* Put the new state at the head of the walk list */ | 566 | /* Put the new state at the head of the walk list */ |
671 | 567 | ||
672 | if (thread) { | 568 | if (thread) { |
@@ -860,190 +756,3 @@ void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) | |||
860 | ACPI_FREE(walk_state); | 756 | ACPI_FREE(walk_state); |
861 | return_VOID; | 757 | return_VOID; |
862 | } | 758 | } |
863 | |||
864 | #ifdef ACPI_OBSOLETE_FUNCTIONS | ||
865 | /******************************************************************************* | ||
866 | * | ||
867 | * FUNCTION: acpi_ds_result_insert | ||
868 | * | ||
869 | * PARAMETERS: Object - Object to push | ||
870 | * Index - Where to insert the object | ||
871 | * walk_state - Current Walk state | ||
872 | * | ||
873 | * RETURN: Status | ||
874 | * | ||
875 | * DESCRIPTION: Insert an object onto this walk's result stack | ||
876 | * | ||
877 | ******************************************************************************/ | ||
878 | |||
879 | acpi_status | ||
880 | acpi_ds_result_insert(void *object, | ||
881 | u32 index, struct acpi_walk_state *walk_state) | ||
882 | { | ||
883 | union acpi_generic_state *state; | ||
884 | |||
885 | ACPI_FUNCTION_NAME(ds_result_insert); | ||
886 | |||
887 | state = walk_state->results; | ||
888 | if (!state) { | ||
889 | ACPI_ERROR((AE_INFO, "No result object pushed! State=%p", | ||
890 | walk_state)); | ||
891 | return (AE_NOT_EXIST); | ||
892 | } | ||
893 | |||
894 | if (index >= ACPI_OBJ_NUM_OPERANDS) { | ||
895 | ACPI_ERROR((AE_INFO, | ||
896 | "Index out of range: %X Obj=%p State=%p Num=%X", | ||
897 | index, object, walk_state, | ||
898 | state->results.num_results)); | ||
899 | return (AE_BAD_PARAMETER); | ||
900 | } | ||
901 | |||
902 | if (!object) { | ||
903 | ACPI_ERROR((AE_INFO, | ||
904 | "Null Object! Index=%X Obj=%p State=%p Num=%X", | ||
905 | index, object, walk_state, | ||
906 | state->results.num_results)); | ||
907 | return (AE_BAD_PARAMETER); | ||
908 | } | ||
909 | |||
910 | state->results.obj_desc[index] = object; | ||
911 | state->results.num_results++; | ||
912 | |||
913 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
914 | "Obj=%p [%s] State=%p Num=%X Cur=%X\n", | ||
915 | object, | ||
916 | object ? | ||
917 | acpi_ut_get_object_type_name((union | ||
918 | acpi_operand_object *) | ||
919 | object) : "NULL", | ||
920 | walk_state, state->results.num_results, | ||
921 | walk_state->current_result)); | ||
922 | |||
923 | return (AE_OK); | ||
924 | } | ||
925 | |||
926 | /******************************************************************************* | ||
927 | * | ||
928 | * FUNCTION: acpi_ds_obj_stack_delete_all | ||
929 | * | ||
930 | * PARAMETERS: walk_state - Current Walk state | ||
931 | * | ||
932 | * RETURN: Status | ||
933 | * | ||
934 | * DESCRIPTION: Clear the object stack by deleting all objects that are on it. | ||
935 | * Should be used with great care, if at all! | ||
936 | * | ||
937 | ******************************************************************************/ | ||
938 | |||
939 | acpi_status acpi_ds_obj_stack_delete_all(struct acpi_walk_state * walk_state) | ||
940 | { | ||
941 | u32 i; | ||
942 | |||
943 | ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_delete_all, walk_state); | ||
944 | |||
945 | /* The stack size is configurable, but fixed */ | ||
946 | |||
947 | for (i = 0; i < ACPI_OBJ_NUM_OPERANDS; i++) { | ||
948 | if (walk_state->operands[i]) { | ||
949 | acpi_ut_remove_reference(walk_state->operands[i]); | ||
950 | walk_state->operands[i] = NULL; | ||
951 | } | ||
952 | } | ||
953 | |||
954 | return_ACPI_STATUS(AE_OK); | ||
955 | } | ||
956 | |||
957 | /******************************************************************************* | ||
958 | * | ||
959 | * FUNCTION: acpi_ds_obj_stack_pop_object | ||
960 | * | ||
961 | * PARAMETERS: Object - Where to return the popped object | ||
962 | * walk_state - Current Walk state | ||
963 | * | ||
964 | * RETURN: Status | ||
965 | * | ||
966 | * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT | ||
967 | * deleted by this routine. | ||
968 | * | ||
969 | ******************************************************************************/ | ||
970 | |||
971 | acpi_status | ||
972 | acpi_ds_obj_stack_pop_object(union acpi_operand_object **object, | ||
973 | struct acpi_walk_state *walk_state) | ||
974 | { | ||
975 | ACPI_FUNCTION_NAME(ds_obj_stack_pop_object); | ||
976 | |||
977 | /* Check for stack underflow */ | ||
978 | |||
979 | if (walk_state->num_operands == 0) { | ||
980 | ACPI_ERROR((AE_INFO, | ||
981 | "Missing operand/stack empty! State=%p #Ops=%X", | ||
982 | walk_state, walk_state->num_operands)); | ||
983 | *object = NULL; | ||
984 | return (AE_AML_NO_OPERAND); | ||
985 | } | ||
986 | |||
987 | /* Pop the stack */ | ||
988 | |||
989 | walk_state->num_operands--; | ||
990 | |||
991 | /* Check for a valid operand */ | ||
992 | |||
993 | if (!walk_state->operands[walk_state->num_operands]) { | ||
994 | ACPI_ERROR((AE_INFO, | ||
995 | "Null operand! State=%p #Ops=%X", | ||
996 | walk_state, walk_state->num_operands)); | ||
997 | *object = NULL; | ||
998 | return (AE_AML_NO_OPERAND); | ||
999 | } | ||
1000 | |||
1001 | /* Get operand and set stack entry to null */ | ||
1002 | |||
1003 | *object = walk_state->operands[walk_state->num_operands]; | ||
1004 | walk_state->operands[walk_state->num_operands] = NULL; | ||
1005 | |||
1006 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", | ||
1007 | *object, acpi_ut_get_object_type_name(*object), | ||
1008 | walk_state, walk_state->num_operands)); | ||
1009 | |||
1010 | return (AE_OK); | ||
1011 | } | ||
1012 | |||
1013 | /******************************************************************************* | ||
1014 | * | ||
1015 | * FUNCTION: acpi_ds_obj_stack_get_value | ||
1016 | * | ||
1017 | * PARAMETERS: Index - Stack index whose value is desired. Based | ||
1018 | * on the top of the stack (index=0 == top) | ||
1019 | * walk_state - Current Walk state | ||
1020 | * | ||
1021 | * RETURN: Pointer to the requested operand | ||
1022 | * | ||
1023 | * DESCRIPTION: Retrieve an object from this walk's operand stack. Index must | ||
1024 | * be within the range of the current stack pointer. | ||
1025 | * | ||
1026 | ******************************************************************************/ | ||
1027 | |||
1028 | void *acpi_ds_obj_stack_get_value(u32 index, struct acpi_walk_state *walk_state) | ||
1029 | { | ||
1030 | |||
1031 | ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_get_value, walk_state); | ||
1032 | |||
1033 | /* Can't do it if the stack is empty */ | ||
1034 | |||
1035 | if (walk_state->num_operands == 0) { | ||
1036 | return_PTR(NULL); | ||
1037 | } | ||
1038 | |||
1039 | /* or if the index is past the top of the stack */ | ||
1040 | |||
1041 | if (index > (walk_state->num_operands - (u32) 1)) { | ||
1042 | return_PTR(NULL); | ||
1043 | } | ||
1044 | |||
1045 | return_PTR(walk_state-> | ||
1046 | operands[(acpi_native_uint) (walk_state->num_operands - 1) - | ||
1047 | index]); | ||
1048 | } | ||
1049 | #endif | ||
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index e3f04b272f3f..0924992187e8 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -73,38 +73,14 @@ enum ec_event { | |||
73 | 73 | ||
74 | #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ | 74 | #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ |
75 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ | 75 | #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ |
76 | #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ | ||
76 | 77 | ||
77 | enum { | 78 | enum { |
78 | EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ | 79 | EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ |
79 | EC_FLAGS_QUERY_PENDING, /* Query is pending */ | 80 | EC_FLAGS_QUERY_PENDING, /* Query is pending */ |
80 | EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ | 81 | EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ |
81 | EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */ | 82 | EC_FLAGS_NO_GPE, /* Don't use GPE mode */ |
82 | EC_FLAGS_ADDRESS, /* Address is being written */ | 83 | EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ |
83 | EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */ | ||
84 | EC_FLAGS_WDATA, /* Data is being written */ | ||
85 | EC_FLAGS_NO_OBF1_GPE, /* Don't expect GPE before read */ | ||
86 | }; | ||
87 | |||
88 | static int acpi_ec_remove(struct acpi_device *device, int type); | ||
89 | static int acpi_ec_start(struct acpi_device *device); | ||
90 | static int acpi_ec_stop(struct acpi_device *device, int type); | ||
91 | static int acpi_ec_add(struct acpi_device *device); | ||
92 | |||
93 | static const struct acpi_device_id ec_device_ids[] = { | ||
94 | {"PNP0C09", 0}, | ||
95 | {"", 0}, | ||
96 | }; | ||
97 | |||
98 | static struct acpi_driver acpi_ec_driver = { | ||
99 | .name = "ec", | ||
100 | .class = ACPI_EC_CLASS, | ||
101 | .ids = ec_device_ids, | ||
102 | .ops = { | ||
103 | .add = acpi_ec_add, | ||
104 | .remove = acpi_ec_remove, | ||
105 | .start = acpi_ec_start, | ||
106 | .stop = acpi_ec_stop, | ||
107 | }, | ||
108 | }; | 84 | }; |
109 | 85 | ||
110 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ | 86 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ |
@@ -129,6 +105,8 @@ static struct acpi_ec { | |||
129 | struct mutex lock; | 105 | struct mutex lock; |
130 | wait_queue_head_t wait; | 106 | wait_queue_head_t wait; |
131 | struct list_head list; | 107 | struct list_head list; |
108 | struct delayed_work work; | ||
109 | atomic_t irq_count; | ||
132 | u8 handlers_installed; | 110 | u8 handlers_installed; |
133 | } *boot_ec, *first_ec; | 111 | } *boot_ec, *first_ec; |
134 | 112 | ||
@@ -177,65 +155,52 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) | |||
177 | return 0; | 155 | return 0; |
178 | } | 156 | } |
179 | 157 | ||
180 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) | 158 | static void ec_schedule_ec_poll(struct acpi_ec *ec) |
181 | { | 159 | { |
182 | int ret = 0; | 160 | if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags)) |
161 | schedule_delayed_work(&ec->work, | ||
162 | msecs_to_jiffies(ACPI_EC_DELAY)); | ||
163 | } | ||
183 | 164 | ||
184 | if (unlikely(event == ACPI_EC_EVENT_OBF_1 && | 165 | static void ec_switch_to_poll_mode(struct acpi_ec *ec) |
185 | test_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags))) | 166 | { |
186 | force_poll = 1; | 167 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); |
187 | if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) && | 168 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
188 | test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags))) | 169 | acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); |
189 | force_poll = 1; | 170 | set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); |
190 | if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) && | 171 | } |
191 | test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags))) | 172 | |
192 | force_poll = 1; | 173 | static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) |
174 | { | ||
175 | atomic_set(&ec->irq_count, 0); | ||
193 | if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && | 176 | if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && |
194 | likely(!force_poll)) { | 177 | likely(!force_poll)) { |
195 | if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), | 178 | if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), |
196 | msecs_to_jiffies(ACPI_EC_DELAY))) | 179 | msecs_to_jiffies(ACPI_EC_DELAY))) |
197 | goto end; | 180 | return 0; |
198 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 181 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
199 | if (acpi_ec_check_status(ec, event)) { | 182 | if (acpi_ec_check_status(ec, event)) { |
200 | if (event == ACPI_EC_EVENT_OBF_1) { | 183 | /* missing GPEs, switch back to poll mode */ |
201 | /* miss OBF_1 GPE, don't expect it */ | 184 | if (printk_ratelimit()) |
202 | pr_info(PREFIX "missing OBF confirmation, " | 185 | pr_info(PREFIX "missing confirmations, " |
203 | "don't expect it any longer.\n"); | ||
204 | set_bit(EC_FLAGS_NO_OBF1_GPE, &ec->flags); | ||
205 | } else if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) { | ||
206 | /* miss address GPE, don't expect it anymore */ | ||
207 | pr_info(PREFIX "missing address confirmation, " | ||
208 | "don't expect it any longer.\n"); | ||
209 | set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags); | ||
210 | } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) { | ||
211 | /* miss write data GPE, don't expect it */ | ||
212 | pr_info(PREFIX "missing write data confirmation, " | ||
213 | "don't expect it any longer.\n"); | ||
214 | set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags); | ||
215 | } else { | ||
216 | /* missing GPEs, switch back to poll mode */ | ||
217 | if (printk_ratelimit()) | ||
218 | pr_info(PREFIX "missing confirmations, " | ||
219 | "switch off interrupt mode.\n"); | 186 | "switch off interrupt mode.\n"); |
220 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 187 | ec_switch_to_poll_mode(ec); |
221 | } | 188 | ec_schedule_ec_poll(ec); |
222 | goto end; | 189 | return 0; |
223 | } | 190 | } |
224 | } else { | 191 | } else { |
225 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); | 192 | unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); |
226 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 193 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
227 | while (time_before(jiffies, delay)) { | 194 | while (time_before(jiffies, delay)) { |
228 | if (acpi_ec_check_status(ec, event)) | 195 | if (acpi_ec_check_status(ec, event)) |
229 | goto end; | 196 | return 0; |
197 | udelay(ACPI_EC_UDELAY); | ||
230 | } | 198 | } |
231 | } | 199 | } |
232 | pr_err(PREFIX "acpi_ec_wait timeout," | 200 | pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", |
233 | " status = %d, expect_event = %d\n", | 201 | acpi_ec_read_status(ec), |
234 | acpi_ec_read_status(ec), event); | 202 | (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); |
235 | ret = -ETIME; | 203 | return -ETIME; |
236 | end: | ||
237 | clear_bit(EC_FLAGS_ADDRESS, &ec->flags); | ||
238 | return ret; | ||
239 | } | 204 | } |
240 | 205 | ||
241 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | 206 | static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, |
@@ -245,8 +210,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | |||
245 | { | 210 | { |
246 | int result = 0; | 211 | int result = 0; |
247 | set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 212 | set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
248 | acpi_ec_write_cmd(ec, command); | ||
249 | pr_debug(PREFIX "transaction start\n"); | 213 | pr_debug(PREFIX "transaction start\n"); |
214 | acpi_ec_write_cmd(ec, command); | ||
250 | for (; wdata_len > 0; --wdata_len) { | 215 | for (; wdata_len > 0; --wdata_len) { |
251 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); | 216 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); |
252 | if (result) { | 217 | if (result) { |
@@ -254,15 +219,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, | |||
254 | "write_cmd timeout, command = %d\n", command); | 219 | "write_cmd timeout, command = %d\n", command); |
255 | goto end; | 220 | goto end; |
256 | } | 221 | } |
257 | /* mark the address byte written to EC */ | ||
258 | if (rdata_len + wdata_len > 1) | ||
259 | set_bit(EC_FLAGS_ADDRESS, &ec->flags); | ||
260 | set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 222 | set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
261 | acpi_ec_write_data(ec, *(wdata++)); | 223 | acpi_ec_write_data(ec, *(wdata++)); |
262 | } | 224 | } |
263 | 225 | ||
264 | if (!rdata_len) { | 226 | if (!rdata_len) { |
265 | set_bit(EC_FLAGS_WDATA, &ec->flags); | ||
266 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); | 227 | result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); |
267 | if (result) { | 228 | if (result) { |
268 | pr_err(PREFIX | 229 | pr_err(PREFIX |
@@ -527,47 +488,51 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
527 | { | 488 | { |
528 | acpi_status status = AE_OK; | 489 | acpi_status status = AE_OK; |
529 | struct acpi_ec *ec = data; | 490 | struct acpi_ec *ec = data; |
491 | u8 state = acpi_ec_read_status(ec); | ||
530 | 492 | ||
531 | pr_debug(PREFIX "~~~> interrupt\n"); | 493 | pr_debug(PREFIX "~~~> interrupt\n"); |
494 | atomic_inc(&ec->irq_count); | ||
495 | if (atomic_read(&ec->irq_count) > 5) { | ||
496 | pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); | ||
497 | ec_switch_to_poll_mode(ec); | ||
498 | goto end; | ||
499 | } | ||
532 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); | 500 | clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); |
533 | if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) | 501 | if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) |
534 | wake_up(&ec->wait); | 502 | wake_up(&ec->wait); |
535 | 503 | ||
536 | if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) { | 504 | if (state & ACPI_EC_FLAG_SCI) { |
537 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) | 505 | if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) |
538 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, | 506 | status = acpi_os_execute(OSL_EC_BURST_HANDLER, |
539 | acpi_ec_gpe_query, ec); | 507 | acpi_ec_gpe_query, ec); |
540 | } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { | 508 | } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && |
509 | !test_bit(EC_FLAGS_NO_GPE, &ec->flags) && | ||
510 | in_interrupt()) { | ||
541 | /* this is non-query, must be confirmation */ | 511 | /* this is non-query, must be confirmation */ |
542 | if (printk_ratelimit()) | 512 | if (printk_ratelimit()) |
543 | pr_info(PREFIX "non-query interrupt received," | 513 | pr_info(PREFIX "non-query interrupt received," |
544 | " switching to interrupt mode\n"); | 514 | " switching to interrupt mode\n"); |
545 | set_bit(EC_FLAGS_GPE_MODE, &ec->flags); | 515 | set_bit(EC_FLAGS_GPE_MODE, &ec->flags); |
516 | clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); | ||
546 | } | 517 | } |
547 | 518 | end: | |
519 | ec_schedule_ec_poll(ec); | ||
548 | return ACPI_SUCCESS(status) ? | 520 | return ACPI_SUCCESS(status) ? |
549 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; | 521 | ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; |
550 | } | 522 | } |
551 | 523 | ||
524 | static void do_ec_poll(struct work_struct *work) | ||
525 | { | ||
526 | struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work); | ||
527 | atomic_set(&ec->irq_count, 0); | ||
528 | (void)acpi_ec_gpe_handler(ec); | ||
529 | } | ||
530 | |||
552 | /* -------------------------------------------------------------------------- | 531 | /* -------------------------------------------------------------------------- |
553 | Address Space Management | 532 | Address Space Management |
554 | -------------------------------------------------------------------------- */ | 533 | -------------------------------------------------------------------------- */ |
555 | 534 | ||
556 | static acpi_status | 535 | static acpi_status |
557 | acpi_ec_space_setup(acpi_handle region_handle, | ||
558 | u32 function, void *handler_context, void **return_context) | ||
559 | { | ||
560 | /* | ||
561 | * The EC object is in the handler context and is needed | ||
562 | * when calling the acpi_ec_space_handler. | ||
563 | */ | ||
564 | *return_context = (function != ACPI_REGION_DEACTIVATE) ? | ||
565 | handler_context : NULL; | ||
566 | |||
567 | return AE_OK; | ||
568 | } | ||
569 | |||
570 | static acpi_status | ||
571 | acpi_ec_space_handler(u32 function, acpi_physical_address address, | 536 | acpi_ec_space_handler(u32 function, acpi_physical_address address, |
572 | u32 bits, acpi_integer *value, | 537 | u32 bits, acpi_integer *value, |
573 | void *handler_context, void *region_context) | 538 | void *handler_context, void *region_context) |
@@ -704,6 +669,8 @@ static struct acpi_ec *make_acpi_ec(void) | |||
704 | mutex_init(&ec->lock); | 669 | mutex_init(&ec->lock); |
705 | init_waitqueue_head(&ec->wait); | 670 | init_waitqueue_head(&ec->wait); |
706 | INIT_LIST_HEAD(&ec->list); | 671 | INIT_LIST_HEAD(&ec->list); |
672 | INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll); | ||
673 | atomic_set(&ec->irq_count, 0); | ||
707 | return ec; | 674 | return ec; |
708 | } | 675 | } |
709 | 676 | ||
@@ -736,17 +703,21 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) | |||
736 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); | 703 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); |
737 | if (ACPI_FAILURE(status)) | 704 | if (ACPI_FAILURE(status)) |
738 | return status; | 705 | return status; |
739 | /* Find and register all query methods */ | ||
740 | acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1, | ||
741 | acpi_ec_register_query_methods, ec, NULL); | ||
742 | /* Use the global lock for all EC transactions? */ | 706 | /* Use the global lock for all EC transactions? */ |
743 | acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); | 707 | acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); |
744 | ec->handle = handle; | 708 | ec->handle = handle; |
745 | return AE_CTRL_TERMINATE; | 709 | return AE_CTRL_TERMINATE; |
746 | } | 710 | } |
747 | 711 | ||
712 | static void ec_poll_stop(struct acpi_ec *ec) | ||
713 | { | ||
714 | clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); | ||
715 | cancel_delayed_work(&ec->work); | ||
716 | } | ||
717 | |||
748 | static void ec_remove_handlers(struct acpi_ec *ec) | 718 | static void ec_remove_handlers(struct acpi_ec *ec) |
749 | { | 719 | { |
720 | ec_poll_stop(ec); | ||
750 | if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, | 721 | if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, |
751 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) | 722 | ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) |
752 | pr_err(PREFIX "failed to remove space handler\n"); | 723 | pr_err(PREFIX "failed to remove space handler\n"); |
@@ -766,31 +737,28 @@ static int acpi_ec_add(struct acpi_device *device) | |||
766 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); | 737 | strcpy(acpi_device_class(device), ACPI_EC_CLASS); |
767 | 738 | ||
768 | /* Check for boot EC */ | 739 | /* Check for boot EC */ |
769 | if (boot_ec) { | 740 | if (boot_ec && |
770 | if (boot_ec->handle == device->handle) { | 741 | (boot_ec->handle == device->handle || |
771 | /* Pre-loaded EC from DSDT, just move pointer */ | 742 | boot_ec->handle == ACPI_ROOT_OBJECT)) { |
772 | ec = boot_ec; | 743 | ec = boot_ec; |
773 | boot_ec = NULL; | 744 | boot_ec = NULL; |
774 | goto end; | 745 | } else { |
775 | } else if (boot_ec->handle == ACPI_ROOT_OBJECT) { | 746 | ec = make_acpi_ec(); |
776 | /* ECDT-based EC, time to shut it down */ | 747 | if (!ec) |
777 | ec_remove_handlers(boot_ec); | 748 | return -ENOMEM; |
778 | kfree(boot_ec); | 749 | if (ec_parse_device(device->handle, 0, ec, NULL) != |
779 | first_ec = boot_ec = NULL; | 750 | AE_CTRL_TERMINATE) { |
751 | kfree(ec); | ||
752 | return -EINVAL; | ||
780 | } | 753 | } |
781 | } | 754 | } |
782 | 755 | ||
783 | ec = make_acpi_ec(); | ||
784 | if (!ec) | ||
785 | return -ENOMEM; | ||
786 | |||
787 | if (ec_parse_device(device->handle, 0, ec, NULL) != | ||
788 | AE_CTRL_TERMINATE) { | ||
789 | kfree(ec); | ||
790 | return -EINVAL; | ||
791 | } | ||
792 | ec->handle = device->handle; | 756 | ec->handle = device->handle; |
793 | end: | 757 | |
758 | /* Find and register all query methods */ | ||
759 | acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1, | ||
760 | acpi_ec_register_query_methods, ec, NULL); | ||
761 | |||
794 | if (!first_ec) | 762 | if (!first_ec) |
795 | first_ec = ec; | 763 | first_ec = ec; |
796 | acpi_driver_data(device) = ec; | 764 | acpi_driver_data(device) = ec; |
@@ -865,7 +833,7 @@ static int ec_install_handlers(struct acpi_ec *ec) | |||
865 | status = acpi_install_address_space_handler(ec->handle, | 833 | status = acpi_install_address_space_handler(ec->handle, |
866 | ACPI_ADR_SPACE_EC, | 834 | ACPI_ADR_SPACE_EC, |
867 | &acpi_ec_space_handler, | 835 | &acpi_ec_space_handler, |
868 | &acpi_ec_space_setup, ec); | 836 | NULL, ec); |
869 | if (ACPI_FAILURE(status)) { | 837 | if (ACPI_FAILURE(status)) { |
870 | acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler); | 838 | acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler); |
871 | return -ENODEV; | 839 | return -ENODEV; |
@@ -892,6 +860,7 @@ static int acpi_ec_start(struct acpi_device *device) | |||
892 | 860 | ||
893 | /* EC is fully operational, allow queries */ | 861 | /* EC is fully operational, allow queries */ |
894 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 862 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
863 | ec_schedule_ec_poll(ec); | ||
895 | return ret; | 864 | return ret; |
896 | } | 865 | } |
897 | 866 | ||
@@ -919,6 +888,11 @@ int __init acpi_boot_ec_enable(void) | |||
919 | return -EFAULT; | 888 | return -EFAULT; |
920 | } | 889 | } |
921 | 890 | ||
891 | static const struct acpi_device_id ec_device_ids[] = { | ||
892 | {"PNP0C09", 0}, | ||
893 | {"", 0}, | ||
894 | }; | ||
895 | |||
922 | int __init acpi_ec_ecdt_probe(void) | 896 | int __init acpi_ec_ecdt_probe(void) |
923 | { | 897 | { |
924 | int ret; | 898 | int ret; |
@@ -939,6 +913,7 @@ int __init acpi_ec_ecdt_probe(void) | |||
939 | boot_ec->data_addr = ecdt_ptr->data.address; | 913 | boot_ec->data_addr = ecdt_ptr->data.address; |
940 | boot_ec->gpe = ecdt_ptr->gpe; | 914 | boot_ec->gpe = ecdt_ptr->gpe; |
941 | boot_ec->handle = ACPI_ROOT_OBJECT; | 915 | boot_ec->handle = ACPI_ROOT_OBJECT; |
916 | acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle); | ||
942 | } else { | 917 | } else { |
943 | /* This workaround is needed only on some broken machines, | 918 | /* This workaround is needed only on some broken machines, |
944 | * which require early EC, but fail to provide ECDT */ | 919 | * which require early EC, but fail to provide ECDT */ |
@@ -968,6 +943,39 @@ int __init acpi_ec_ecdt_probe(void) | |||
968 | return -ENODEV; | 943 | return -ENODEV; |
969 | } | 944 | } |
970 | 945 | ||
946 | static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) | ||
947 | { | ||
948 | struct acpi_ec *ec = acpi_driver_data(device); | ||
949 | /* Stop using GPE */ | ||
950 | set_bit(EC_FLAGS_NO_GPE, &ec->flags); | ||
951 | clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); | ||
952 | acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | ||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | static int acpi_ec_resume(struct acpi_device *device) | ||
957 | { | ||
958 | struct acpi_ec *ec = acpi_driver_data(device); | ||
959 | /* Enable use of GPE back */ | ||
960 | clear_bit(EC_FLAGS_NO_GPE, &ec->flags); | ||
961 | acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); | ||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | static struct acpi_driver acpi_ec_driver = { | ||
966 | .name = "ec", | ||
967 | .class = ACPI_EC_CLASS, | ||
968 | .ids = ec_device_ids, | ||
969 | .ops = { | ||
970 | .add = acpi_ec_add, | ||
971 | .remove = acpi_ec_remove, | ||
972 | .start = acpi_ec_start, | ||
973 | .stop = acpi_ec_stop, | ||
974 | .suspend = acpi_ec_suspend, | ||
975 | .resume = acpi_ec_resume, | ||
976 | }, | ||
977 | }; | ||
978 | |||
971 | static int __init acpi_ec_init(void) | 979 | static int __init acpi_ec_init(void) |
972 | { | 980 | { |
973 | int result = 0; | 981 | int result = 0; |
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c index 3048801a37b5..5d30e5be1b1c 100644 --- a/drivers/acpi/events/evevent.c +++ b/drivers/acpi/events/evevent.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c index 0dadd2adc800..5354be44f876 100644 --- a/drivers/acpi/events/evgpe.c +++ b/drivers/acpi/events/evgpe.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -248,10 +248,6 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) | |||
248 | 248 | ||
249 | ACPI_FUNCTION_TRACE(ev_disable_gpe); | 249 | ACPI_FUNCTION_TRACE(ev_disable_gpe); |
250 | 250 | ||
251 | if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) { | ||
252 | return_ACPI_STATUS(AE_OK); | ||
253 | } | ||
254 | |||
255 | /* Make sure HW enable masks are updated */ | 251 | /* Make sure HW enable masks are updated */ |
256 | 252 | ||
257 | status = | 253 | status = |
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index 361ebe6c4a6f..e6c4d4c49e79 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c index 21cb749d0c75..2113e58e2221 100644 --- a/drivers/acpi/events/evmisc.c +++ b/drivers/acpi/events/evmisc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -49,22 +49,7 @@ | |||
49 | #define _COMPONENT ACPI_EVENTS | 49 | #define _COMPONENT ACPI_EVENTS |
50 | ACPI_MODULE_NAME("evmisc") | 50 | ACPI_MODULE_NAME("evmisc") |
51 | 51 | ||
52 | /* Names for Notify() values, used for debug output */ | ||
53 | #ifdef ACPI_DEBUG_OUTPUT | ||
54 | static const char *acpi_notify_value_names[] = { | ||
55 | "Bus Check", | ||
56 | "Device Check", | ||
57 | "Device Wake", | ||
58 | "Eject Request", | ||
59 | "Device Check Light", | ||
60 | "Frequency Mismatch", | ||
61 | "Bus Mode Mismatch", | ||
62 | "Power Fault" | ||
63 | }; | ||
64 | #endif | ||
65 | |||
66 | /* Pointer to FACS needed for the Global Lock */ | 52 | /* Pointer to FACS needed for the Global Lock */ |
67 | |||
68 | static struct acpi_table_facs *facs = NULL; | 53 | static struct acpi_table_facs *facs = NULL; |
69 | 54 | ||
70 | /* Local prototypes */ | 55 | /* Local prototypes */ |
@@ -94,7 +79,6 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) | |||
94 | switch (node->type) { | 79 | switch (node->type) { |
95 | case ACPI_TYPE_DEVICE: | 80 | case ACPI_TYPE_DEVICE: |
96 | case ACPI_TYPE_PROCESSOR: | 81 | case ACPI_TYPE_PROCESSOR: |
97 | case ACPI_TYPE_POWER: | ||
98 | case ACPI_TYPE_THERMAL: | 82 | case ACPI_TYPE_THERMAL: |
99 | /* | 83 | /* |
100 | * These are the ONLY objects that can receive ACPI notifications | 84 | * These are the ONLY objects that can receive ACPI notifications |
@@ -139,17 +123,9 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, | |||
139 | * initiate soft-off or sleep operation? | 123 | * initiate soft-off or sleep operation? |
140 | */ | 124 | */ |
141 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 125 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
142 | "Dispatching Notify(%X) on node %p\n", notify_value, | 126 | "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", |
143 | node)); | 127 | acpi_ut_get_node_name(node), node, notify_value, |
144 | 128 | acpi_ut_get_notify_name(notify_value))); | |
145 | if (notify_value <= 7) { | ||
146 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Notify value: %s\n", | ||
147 | acpi_notify_value_names[notify_value])); | ||
148 | } else { | ||
149 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
150 | "Notify value: 0x%2.2X **Device Specific**\n", | ||
151 | notify_value)); | ||
152 | } | ||
153 | 129 | ||
154 | /* Get the notify object attached to the NS Node */ | 130 | /* Get the notify object attached to the NS Node */ |
155 | 131 | ||
@@ -159,10 +135,12 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, | |||
159 | /* We have the notify object, Get the right handler */ | 135 | /* We have the notify object, Get the right handler */ |
160 | 136 | ||
161 | switch (node->type) { | 137 | switch (node->type) { |
138 | |||
139 | /* Notify allowed only on these types */ | ||
140 | |||
162 | case ACPI_TYPE_DEVICE: | 141 | case ACPI_TYPE_DEVICE: |
163 | case ACPI_TYPE_THERMAL: | 142 | case ACPI_TYPE_THERMAL: |
164 | case ACPI_TYPE_PROCESSOR: | 143 | case ACPI_TYPE_PROCESSOR: |
165 | case ACPI_TYPE_POWER: | ||
166 | 144 | ||
167 | if (notify_value <= ACPI_MAX_SYS_NOTIFY) { | 145 | if (notify_value <= ACPI_MAX_SYS_NOTIFY) { |
168 | handler_obj = | 146 | handler_obj = |
@@ -179,8 +157,13 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, | |||
179 | } | 157 | } |
180 | } | 158 | } |
181 | 159 | ||
182 | /* If there is any handler to run, schedule the dispatcher */ | 160 | /* |
183 | 161 | * If there is any handler to run, schedule the dispatcher. | |
162 | * Check for: | ||
163 | * 1) Global system notify handler | ||
164 | * 2) Global device notify handler | ||
165 | * 3) Per-device notify handler | ||
166 | */ | ||
184 | if ((acpi_gbl_system_notify.handler | 167 | if ((acpi_gbl_system_notify.handler |
185 | && (notify_value <= ACPI_MAX_SYS_NOTIFY)) | 168 | && (notify_value <= ACPI_MAX_SYS_NOTIFY)) |
186 | || (acpi_gbl_device_notify.handler | 169 | || (acpi_gbl_device_notify.handler |
@@ -190,6 +173,13 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, | |||
190 | return (AE_NO_MEMORY); | 173 | return (AE_NO_MEMORY); |
191 | } | 174 | } |
192 | 175 | ||
176 | if (!handler_obj) { | ||
177 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
178 | "Executing system notify handler for Notify (%4.4s, %X) node %p\n", | ||
179 | acpi_ut_get_node_name(node), | ||
180 | notify_value, node)); | ||
181 | } | ||
182 | |||
193 | notify_info->common.descriptor_type = | 183 | notify_info->common.descriptor_type = |
194 | ACPI_DESC_TYPE_STATE_NOTIFY; | 184 | ACPI_DESC_TYPE_STATE_NOTIFY; |
195 | notify_info->notify.node = node; | 185 | notify_info->notify.node = node; |
@@ -202,15 +192,12 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, | |||
202 | if (ACPI_FAILURE(status)) { | 192 | if (ACPI_FAILURE(status)) { |
203 | acpi_ut_delete_generic_state(notify_info); | 193 | acpi_ut_delete_generic_state(notify_info); |
204 | } | 194 | } |
205 | } | 195 | } else { |
206 | |||
207 | if (!handler_obj) { | ||
208 | /* | 196 | /* |
209 | * There is no per-device notify handler for this device. | 197 | * There is no notify handler (per-device or system) for this device. |
210 | * This may or may not be a problem. | ||
211 | */ | 198 | */ |
212 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 199 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
213 | "No notify handler for Notify(%4.4s, %X) node %p\n", | 200 | "No notify handler for Notify (%4.4s, %X) node %p\n", |
214 | acpi_ut_get_node_name(node), notify_value, | 201 | acpi_ut_get_node_name(node), notify_value, |
215 | node)); | 202 | node)); |
216 | } | 203 | } |
@@ -349,9 +336,10 @@ acpi_status acpi_ev_init_global_lock_handler(void) | |||
349 | 336 | ||
350 | ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); | 337 | ACPI_FUNCTION_TRACE(ev_init_global_lock_handler); |
351 | 338 | ||
352 | status = | 339 | status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, |
353 | acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, | 340 | ACPI_CAST_INDIRECT_PTR(struct |
354 | (struct acpi_table_header **)&facs); | 341 | acpi_table_header, |
342 | &facs)); | ||
355 | if (ACPI_FAILURE(status)) { | 343 | if (ACPI_FAILURE(status)) { |
356 | return_ACPI_STATUS(status); | 344 | return_ACPI_STATUS(status); |
357 | } | 345 | } |
@@ -439,7 +427,8 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) | |||
439 | * Only one thread can acquire the GL at a time, the global_lock_mutex | 427 | * Only one thread can acquire the GL at a time, the global_lock_mutex |
440 | * enforces this. This interface releases the interpreter if we must wait. | 428 | * enforces this. This interface releases the interpreter if we must wait. |
441 | */ | 429 | */ |
442 | status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, 0); | 430 | status = acpi_ex_system_wait_mutex( |
431 | acpi_gbl_global_lock_mutex->mutex.os_mutex, 0); | ||
443 | if (status == AE_TIME) { | 432 | if (status == AE_TIME) { |
444 | if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { | 433 | if (acpi_ev_global_lock_thread_id == acpi_os_get_thread_id()) { |
445 | acpi_ev_global_lock_acquired++; | 434 | acpi_ev_global_lock_acquired++; |
@@ -448,9 +437,9 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) | |||
448 | } | 437 | } |
449 | 438 | ||
450 | if (ACPI_FAILURE(status)) { | 439 | if (ACPI_FAILURE(status)) { |
451 | status = | 440 | status = acpi_ex_system_wait_mutex( |
452 | acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, | 441 | acpi_gbl_global_lock_mutex->mutex.os_mutex, |
453 | timeout); | 442 | timeout); |
454 | } | 443 | } |
455 | if (ACPI_FAILURE(status)) { | 444 | if (ACPI_FAILURE(status)) { |
456 | return_ACPI_STATUS(status); | 445 | return_ACPI_STATUS(status); |
@@ -460,6 +449,19 @@ acpi_status acpi_ev_acquire_global_lock(u16 timeout) | |||
460 | acpi_ev_global_lock_acquired++; | 449 | acpi_ev_global_lock_acquired++; |
461 | 450 | ||
462 | /* | 451 | /* |
452 | * Update the global lock handle and check for wraparound. The handle is | ||
453 | * only used for the external global lock interfaces, but it is updated | ||
454 | * here to properly handle the case where a single thread may acquire the | ||
455 | * lock via both the AML and the acpi_acquire_global_lock interfaces. The | ||
456 | * handle is therefore updated on the first acquire from a given thread | ||
457 | * regardless of where the acquisition request originated. | ||
458 | */ | ||
459 | acpi_gbl_global_lock_handle++; | ||
460 | if (acpi_gbl_global_lock_handle == 0) { | ||
461 | acpi_gbl_global_lock_handle = 1; | ||
462 | } | ||
463 | |||
464 | /* | ||
463 | * Make sure that a global lock actually exists. If not, just treat | 465 | * Make sure that a global lock actually exists. If not, just treat |
464 | * the lock as a standard mutex. | 466 | * the lock as a standard mutex. |
465 | */ | 467 | */ |
@@ -555,7 +557,7 @@ acpi_status acpi_ev_release_global_lock(void) | |||
555 | /* Release the local GL mutex */ | 557 | /* Release the local GL mutex */ |
556 | acpi_ev_global_lock_thread_id = NULL; | 558 | acpi_ev_global_lock_thread_id = NULL; |
557 | acpi_ev_global_lock_acquired = 0; | 559 | acpi_ev_global_lock_acquired = 0; |
558 | acpi_os_release_mutex(acpi_gbl_global_lock_mutex); | 560 | acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex); |
559 | return_ACPI_STATUS(status); | 561 | return_ACPI_STATUS(status); |
560 | } | 562 | } |
561 | 563 | ||
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 58ad09725dd2..1628f5934752 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -394,7 +394,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
394 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, | 394 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, |
395 | "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", | 395 | "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", |
396 | ®ion_obj->region.handler->address_space, handler, | 396 | ®ion_obj->region.handler->address_space, handler, |
397 | ACPI_FORMAT_UINT64(address), | 397 | ACPI_FORMAT_NATIVE_UINT(address), |
398 | acpi_ut_get_region_name(region_obj->region. | 398 | acpi_ut_get_region_name(region_obj->region. |
399 | space_id))); | 399 | space_id))); |
400 | 400 | ||
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index b1aaa0e84588..2e3d2c5e4f4d 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c index 7e5d15ce2395..2a8b77877610 100644 --- a/drivers/acpi/events/evsci.c +++ b/drivers/acpi/events/evsci.c | |||
@@ -6,7 +6,7 @@ | |||
6 | ******************************************************************************/ | 6 | ******************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c index 6d866a01f5f4..94a6efe020be 100644 --- a/drivers/acpi/events/evxface.c +++ b/drivers/acpi/events/evxface.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -758,6 +758,12 @@ ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler) | |||
758 | * | 758 | * |
759 | * DESCRIPTION: Acquire the ACPI Global Lock | 759 | * DESCRIPTION: Acquire the ACPI Global Lock |
760 | * | 760 | * |
761 | * Note: Allows callers with the same thread ID to acquire the global lock | ||
762 | * multiple times. In other words, externally, the behavior of the global lock | ||
763 | * is identical to an AML mutex. On the first acquire, a new handle is | ||
764 | * returned. On any subsequent calls to acquire by the same thread, the same | ||
765 | * handle is returned. | ||
766 | * | ||
761 | ******************************************************************************/ | 767 | ******************************************************************************/ |
762 | acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) | 768 | acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) |
763 | { | 769 | { |
@@ -770,14 +776,19 @@ acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle) | |||
770 | /* Must lock interpreter to prevent race conditions */ | 776 | /* Must lock interpreter to prevent race conditions */ |
771 | 777 | ||
772 | acpi_ex_enter_interpreter(); | 778 | acpi_ex_enter_interpreter(); |
773 | status = acpi_ev_acquire_global_lock(timeout); | 779 | |
774 | acpi_ex_exit_interpreter(); | 780 | status = acpi_ex_acquire_mutex_object(timeout, |
781 | acpi_gbl_global_lock_mutex, | ||
782 | acpi_os_get_thread_id()); | ||
775 | 783 | ||
776 | if (ACPI_SUCCESS(status)) { | 784 | if (ACPI_SUCCESS(status)) { |
777 | acpi_gbl_global_lock_handle++; | 785 | |
786 | /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */ | ||
787 | |||
778 | *handle = acpi_gbl_global_lock_handle; | 788 | *handle = acpi_gbl_global_lock_handle; |
779 | } | 789 | } |
780 | 790 | ||
791 | acpi_ex_exit_interpreter(); | ||
781 | return (status); | 792 | return (status); |
782 | } | 793 | } |
783 | 794 | ||
@@ -798,11 +809,11 @@ acpi_status acpi_release_global_lock(u32 handle) | |||
798 | { | 809 | { |
799 | acpi_status status; | 810 | acpi_status status; |
800 | 811 | ||
801 | if (handle != acpi_gbl_global_lock_handle) { | 812 | if (!handle || (handle != acpi_gbl_global_lock_handle)) { |
802 | return (AE_NOT_ACQUIRED); | 813 | return (AE_NOT_ACQUIRED); |
803 | } | 814 | } |
804 | 815 | ||
805 | status = acpi_ev_release_global_lock(); | 816 | status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); |
806 | return (status); | 817 | return (status); |
807 | } | 818 | } |
808 | 819 | ||
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c index 9cbd3414a574..99a7502e6a87 100644 --- a/drivers/acpi/events/evxfevnt.c +++ b/drivers/acpi/events/evxfevnt.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c index 7bf09c5fb242..e8750807e57d 100644 --- a/drivers/acpi/events/evxfregn.c +++ b/drivers/acpi/events/evxfregn.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c index 25802f302ffe..24da921d13e3 100644 --- a/drivers/acpi/executer/exconfig.c +++ b/drivers/acpi/executer/exconfig.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -45,7 +45,6 @@ | |||
45 | #include <acpi/acinterp.h> | 45 | #include <acpi/acinterp.h> |
46 | #include <acpi/amlcode.h> | 46 | #include <acpi/amlcode.h> |
47 | #include <acpi/acnamesp.h> | 47 | #include <acpi/acnamesp.h> |
48 | #include <acpi/acevents.h> | ||
49 | #include <acpi/actables.h> | 48 | #include <acpi/actables.h> |
50 | #include <acpi/acdispat.h> | 49 | #include <acpi/acdispat.h> |
51 | 50 | ||
@@ -138,6 +137,14 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
138 | 137 | ||
139 | ACPI_FUNCTION_TRACE(ex_load_table_op); | 138 | ACPI_FUNCTION_TRACE(ex_load_table_op); |
140 | 139 | ||
140 | /* Validate lengths for the signature_string, OEMIDString, OEMtable_iD */ | ||
141 | |||
142 | if ((operand[0]->string.length > ACPI_NAME_SIZE) || | ||
143 | (operand[1]->string.length > ACPI_OEM_ID_SIZE) || | ||
144 | (operand[2]->string.length > ACPI_OEM_TABLE_ID_SIZE)) { | ||
145 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
146 | } | ||
147 | |||
141 | /* Find the ACPI table in the RSDT/XSDT */ | 148 | /* Find the ACPI table in the RSDT/XSDT */ |
142 | 149 | ||
143 | status = acpi_tb_find_table(operand[0]->string.pointer, | 150 | status = acpi_tb_find_table(operand[0]->string.pointer, |
@@ -229,11 +236,18 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
229 | status = acpi_get_table_by_index(table_index, &table); | 236 | status = acpi_get_table_by_index(table_index, &table); |
230 | if (ACPI_SUCCESS(status)) { | 237 | if (ACPI_SUCCESS(status)) { |
231 | ACPI_INFO((AE_INFO, | 238 | ACPI_INFO((AE_INFO, |
232 | "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", | 239 | "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]", |
233 | table->signature, table->oem_id, | 240 | table->signature, table->oem_id, |
234 | table->oem_table_id)); | 241 | table->oem_table_id)); |
235 | } | 242 | } |
236 | 243 | ||
244 | /* Invoke table handler if present */ | ||
245 | |||
246 | if (acpi_gbl_table_handler) { | ||
247 | (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table, | ||
248 | acpi_gbl_table_handler_context); | ||
249 | } | ||
250 | |||
237 | *return_desc = ddb_handle; | 251 | *return_desc = ddb_handle; |
238 | return_ACPI_STATUS(status); | 252 | return_ACPI_STATUS(status); |
239 | } | 253 | } |
@@ -268,6 +282,7 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
268 | struct acpi_table_desc table_desc; | 282 | struct acpi_table_desc table_desc; |
269 | acpi_native_uint table_index; | 283 | acpi_native_uint table_index; |
270 | acpi_status status; | 284 | acpi_status status; |
285 | u32 length; | ||
271 | 286 | ||
272 | ACPI_FUNCTION_TRACE(ex_load_op); | 287 | ACPI_FUNCTION_TRACE(ex_load_op); |
273 | 288 | ||
@@ -278,16 +293,16 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
278 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { | 293 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { |
279 | case ACPI_TYPE_REGION: | 294 | case ACPI_TYPE_REGION: |
280 | 295 | ||
296 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", | ||
297 | obj_desc, | ||
298 | acpi_ut_get_object_type_name(obj_desc))); | ||
299 | |||
281 | /* Region must be system_memory (from ACPI spec) */ | 300 | /* Region must be system_memory (from ACPI spec) */ |
282 | 301 | ||
283 | if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { | 302 | if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) { |
284 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 303 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
285 | } | 304 | } |
286 | 305 | ||
287 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", | ||
288 | obj_desc, | ||
289 | acpi_ut_get_object_type_name(obj_desc))); | ||
290 | |||
291 | /* | 306 | /* |
292 | * If the Region Address and Length have not been previously evaluated, | 307 | * If the Region Address and Length have not been previously evaluated, |
293 | * evaluate them now and save the results. | 308 | * evaluate them now and save the results. |
@@ -299,6 +314,11 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
299 | } | 314 | } |
300 | } | 315 | } |
301 | 316 | ||
317 | /* | ||
318 | * We will simply map the memory region for the table. However, the | ||
319 | * memory region is technically not guaranteed to remain stable and | ||
320 | * we may eventually have to copy the table to a local buffer. | ||
321 | */ | ||
302 | table_desc.address = obj_desc->region.address; | 322 | table_desc.address = obj_desc->region.address; |
303 | table_desc.length = obj_desc->region.length; | 323 | table_desc.length = obj_desc->region.length; |
304 | table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; | 324 | table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; |
@@ -306,18 +326,41 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
306 | 326 | ||
307 | case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ | 327 | case ACPI_TYPE_BUFFER: /* Buffer or resolved region_field */ |
308 | 328 | ||
309 | /* Simply extract the buffer from the buffer object */ | ||
310 | |||
311 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | 329 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, |
312 | "Load from Buffer or Field %p %s\n", obj_desc, | 330 | "Load from Buffer or Field %p %s\n", obj_desc, |
313 | acpi_ut_get_object_type_name(obj_desc))); | 331 | acpi_ut_get_object_type_name(obj_desc))); |
314 | 332 | ||
315 | table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header, | 333 | length = obj_desc->buffer.length; |
316 | obj_desc->buffer.pointer); | 334 | |
317 | table_desc.length = table_desc.pointer->length; | 335 | /* Must have at least an ACPI table header */ |
318 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | 336 | |
337 | if (length < sizeof(struct acpi_table_header)) { | ||
338 | return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); | ||
339 | } | ||
340 | |||
341 | /* Validate checksum here. It won't get validated in tb_add_table */ | ||
319 | 342 | ||
320 | obj_desc->buffer.pointer = NULL; | 343 | status = |
344 | acpi_tb_verify_checksum(ACPI_CAST_PTR | ||
345 | (struct acpi_table_header, | ||
346 | obj_desc->buffer.pointer), length); | ||
347 | if (ACPI_FAILURE(status)) { | ||
348 | return_ACPI_STATUS(status); | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * We need to copy the buffer since the original buffer could be | ||
353 | * changed or deleted in the future | ||
354 | */ | ||
355 | table_desc.pointer = ACPI_ALLOCATE(length); | ||
356 | if (!table_desc.pointer) { | ||
357 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
358 | } | ||
359 | |||
360 | ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer, | ||
361 | length); | ||
362 | table_desc.length = length; | ||
363 | table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED; | ||
321 | break; | 364 | break; |
322 | 365 | ||
323 | default: | 366 | default: |
@@ -333,7 +376,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
333 | } | 376 | } |
334 | 377 | ||
335 | status = | 378 | status = |
336 | acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle); | 379 | acpi_ex_add_table(table_index, walk_state->scope_info->scope.node, |
380 | &ddb_handle); | ||
337 | if (ACPI_FAILURE(status)) { | 381 | if (ACPI_FAILURE(status)) { |
338 | 382 | ||
339 | /* On error, table_ptr was deallocated above */ | 383 | /* On error, table_ptr was deallocated above */ |
@@ -349,11 +393,23 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
349 | 393 | ||
350 | /* table_ptr was deallocated above */ | 394 | /* table_ptr was deallocated above */ |
351 | 395 | ||
396 | acpi_ut_remove_reference(ddb_handle); | ||
352 | return_ACPI_STATUS(status); | 397 | return_ACPI_STATUS(status); |
353 | } | 398 | } |
354 | 399 | ||
400 | /* Invoke table handler if present */ | ||
401 | |||
402 | if (acpi_gbl_table_handler) { | ||
403 | (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, | ||
404 | table_desc.pointer, | ||
405 | acpi_gbl_table_handler_context); | ||
406 | } | ||
407 | |||
355 | cleanup: | 408 | cleanup: |
356 | if (ACPI_FAILURE(status)) { | 409 | if (ACPI_FAILURE(status)) { |
410 | |||
411 | /* Delete allocated buffer or mapping */ | ||
412 | |||
357 | acpi_tb_delete_table(&table_desc); | 413 | acpi_tb_delete_table(&table_desc); |
358 | } | 414 | } |
359 | return_ACPI_STATUS(status); | 415 | return_ACPI_STATUS(status); |
@@ -376,6 +432,7 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) | |||
376 | acpi_status status = AE_OK; | 432 | acpi_status status = AE_OK; |
377 | union acpi_operand_object *table_desc = ddb_handle; | 433 | union acpi_operand_object *table_desc = ddb_handle; |
378 | acpi_native_uint table_index; | 434 | acpi_native_uint table_index; |
435 | struct acpi_table_header *table; | ||
379 | 436 | ||
380 | ACPI_FUNCTION_TRACE(ex_unload_table); | 437 | ACPI_FUNCTION_TRACE(ex_unload_table); |
381 | 438 | ||
@@ -395,17 +452,25 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle) | |||
395 | 452 | ||
396 | table_index = (acpi_native_uint) table_desc->reference.object; | 453 | table_index = (acpi_native_uint) table_desc->reference.object; |
397 | 454 | ||
455 | /* Invoke table handler if present */ | ||
456 | |||
457 | if (acpi_gbl_table_handler) { | ||
458 | status = acpi_get_table_by_index(table_index, &table); | ||
459 | if (ACPI_SUCCESS(status)) { | ||
460 | (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, | ||
461 | table, | ||
462 | acpi_gbl_table_handler_context); | ||
463 | } | ||
464 | } | ||
465 | |||
398 | /* | 466 | /* |
399 | * Delete the entire namespace under this table Node | 467 | * Delete the entire namespace under this table Node |
400 | * (Offset contains the table_id) | 468 | * (Offset contains the table_id) |
401 | */ | 469 | */ |
402 | acpi_tb_delete_namespace_by_owner(table_index); | 470 | acpi_tb_delete_namespace_by_owner(table_index); |
403 | acpi_tb_release_owner_id(table_index); | 471 | (void)acpi_tb_release_owner_id(table_index); |
404 | 472 | ||
405 | acpi_tb_set_table_loaded_flag(table_index, FALSE); | 473 | acpi_tb_set_table_loaded_flag(table_index, FALSE); |
406 | 474 | ||
407 | /* Delete the table descriptor (ddb_handle) */ | 475 | return_ACPI_STATUS(AE_OK); |
408 | |||
409 | acpi_ut_remove_reference(table_desc); | ||
410 | return_ACPI_STATUS(status); | ||
411 | } | 476 | } |
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c index 79f2c0d42c06..fd954b4ed83d 100644 --- a/drivers/acpi/executer/exconvrt.c +++ b/drivers/acpi/executer/exconvrt.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c index 6e9a23e47fef..60e62c4f0577 100644 --- a/drivers/acpi/executer/excreate.c +++ b/drivers/acpi/executer/excreate.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -96,6 +96,9 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) | |||
96 | * to the original Node. | 96 | * to the original Node. |
97 | */ | 97 | */ |
98 | switch (target_node->type) { | 98 | switch (target_node->type) { |
99 | |||
100 | /* For these types, the sub-object can change dynamically via a Store */ | ||
101 | |||
99 | case ACPI_TYPE_INTEGER: | 102 | case ACPI_TYPE_INTEGER: |
100 | case ACPI_TYPE_STRING: | 103 | case ACPI_TYPE_STRING: |
101 | case ACPI_TYPE_BUFFER: | 104 | case ACPI_TYPE_BUFFER: |
@@ -103,9 +106,18 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) | |||
103 | case ACPI_TYPE_BUFFER_FIELD: | 106 | case ACPI_TYPE_BUFFER_FIELD: |
104 | 107 | ||
105 | /* | 108 | /* |
109 | * These types open a new scope, so we need the NS node in order to access | ||
110 | * any children. | ||
111 | */ | ||
112 | case ACPI_TYPE_DEVICE: | ||
113 | case ACPI_TYPE_POWER: | ||
114 | case ACPI_TYPE_PROCESSOR: | ||
115 | case ACPI_TYPE_THERMAL: | ||
116 | case ACPI_TYPE_LOCAL_SCOPE: | ||
117 | |||
118 | /* | ||
106 | * The new alias has the type ALIAS and points to the original | 119 | * The new alias has the type ALIAS and points to the original |
107 | * NS node, not the object itself. This is because for these | 120 | * NS node, not the object itself. |
108 | * types, the object can change dynamically via a Store. | ||
109 | */ | 121 | */ |
110 | alias_node->type = ACPI_TYPE_LOCAL_ALIAS; | 122 | alias_node->type = ACPI_TYPE_LOCAL_ALIAS; |
111 | alias_node->object = | 123 | alias_node->object = |
@@ -115,9 +127,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) | |||
115 | case ACPI_TYPE_METHOD: | 127 | case ACPI_TYPE_METHOD: |
116 | 128 | ||
117 | /* | 129 | /* |
118 | * The new alias has the type ALIAS and points to the original | 130 | * Control method aliases need to be differentiated |
119 | * NS node, not the object itself. This is because for these | ||
120 | * types, the object can change dynamically via a Store. | ||
121 | */ | 131 | */ |
122 | alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; | 132 | alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; |
123 | alias_node->object = | 133 | alias_node->object = |
@@ -342,101 +352,6 @@ acpi_ex_create_region(u8 * aml_start, | |||
342 | 352 | ||
343 | /******************************************************************************* | 353 | /******************************************************************************* |
344 | * | 354 | * |
345 | * FUNCTION: acpi_ex_create_table_region | ||
346 | * | ||
347 | * PARAMETERS: walk_state - Current state | ||
348 | * | ||
349 | * RETURN: Status | ||
350 | * | ||
351 | * DESCRIPTION: Create a new data_table_region object | ||
352 | * | ||
353 | ******************************************************************************/ | ||
354 | |||
355 | acpi_status acpi_ex_create_table_region(struct acpi_walk_state *walk_state) | ||
356 | { | ||
357 | acpi_status status; | ||
358 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
359 | union acpi_operand_object *obj_desc; | ||
360 | struct acpi_namespace_node *node; | ||
361 | union acpi_operand_object *region_obj2; | ||
362 | acpi_native_uint table_index; | ||
363 | struct acpi_table_header *table; | ||
364 | |||
365 | ACPI_FUNCTION_TRACE(ex_create_table_region); | ||
366 | |||
367 | /* Get the Node from the object stack */ | ||
368 | |||
369 | node = walk_state->op->common.node; | ||
370 | |||
371 | /* | ||
372 | * If the region object is already attached to this node, | ||
373 | * just return | ||
374 | */ | ||
375 | if (acpi_ns_get_attached_object(node)) { | ||
376 | return_ACPI_STATUS(AE_OK); | ||
377 | } | ||
378 | |||
379 | /* Find the ACPI table */ | ||
380 | |||
381 | status = acpi_tb_find_table(operand[1]->string.pointer, | ||
382 | operand[2]->string.pointer, | ||
383 | operand[3]->string.pointer, &table_index); | ||
384 | if (ACPI_FAILURE(status)) { | ||
385 | return_ACPI_STATUS(status); | ||
386 | } | ||
387 | |||
388 | /* Create the region descriptor */ | ||
389 | |||
390 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION); | ||
391 | if (!obj_desc) { | ||
392 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
393 | } | ||
394 | |||
395 | region_obj2 = obj_desc->common.next_object; | ||
396 | region_obj2->extra.region_context = NULL; | ||
397 | |||
398 | status = acpi_get_table_by_index(table_index, &table); | ||
399 | if (ACPI_FAILURE(status)) { | ||
400 | return_ACPI_STATUS(status); | ||
401 | } | ||
402 | |||
403 | /* Init the region from the operands */ | ||
404 | |||
405 | obj_desc->region.space_id = REGION_DATA_TABLE; | ||
406 | obj_desc->region.address = | ||
407 | (acpi_physical_address) ACPI_TO_INTEGER(table); | ||
408 | obj_desc->region.length = table->length; | ||
409 | obj_desc->region.node = node; | ||
410 | obj_desc->region.flags = AOPOBJ_DATA_VALID; | ||
411 | |||
412 | /* Install the new region object in the parent Node */ | ||
413 | |||
414 | status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION); | ||
415 | if (ACPI_FAILURE(status)) { | ||
416 | goto cleanup; | ||
417 | } | ||
418 | |||
419 | status = acpi_ev_initialize_region(obj_desc, FALSE); | ||
420 | if (ACPI_FAILURE(status)) { | ||
421 | if (status == AE_NOT_EXIST) { | ||
422 | status = AE_OK; | ||
423 | } else { | ||
424 | goto cleanup; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE; | ||
429 | |||
430 | cleanup: | ||
431 | |||
432 | /* Remove local reference to the object */ | ||
433 | |||
434 | acpi_ut_remove_reference(obj_desc); | ||
435 | return_ACPI_STATUS(status); | ||
436 | } | ||
437 | |||
438 | /******************************************************************************* | ||
439 | * | ||
440 | * FUNCTION: acpi_ex_create_processor | 355 | * FUNCTION: acpi_ex_create_processor |
441 | * | 356 | * |
442 | * PARAMETERS: walk_state - Current state | 357 | * PARAMETERS: walk_state - Current state |
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c index 51c9c29987c3..74f1b22601b3 100644 --- a/drivers/acpi/executer/exdump.c +++ b/drivers/acpi/executer/exdump.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -500,25 +500,28 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) | |||
500 | acpi_os_printf("Reference: Debug\n"); | 500 | acpi_os_printf("Reference: Debug\n"); |
501 | break; | 501 | break; |
502 | 502 | ||
503 | case AML_NAME_OP: | 503 | case AML_INDEX_OP: |
504 | 504 | ||
505 | ACPI_DUMP_PATHNAME(obj_desc->reference.object, | 505 | acpi_os_printf("Reference: Index %p\n", |
506 | "Reference: Name: ", ACPI_LV_INFO, | 506 | obj_desc->reference.object); |
507 | _COMPONENT); | ||
508 | ACPI_DUMP_ENTRY(obj_desc->reference.object, | ||
509 | ACPI_LV_INFO); | ||
510 | break; | 507 | break; |
511 | 508 | ||
512 | case AML_INDEX_OP: | 509 | case AML_LOAD_OP: |
513 | 510 | ||
514 | acpi_os_printf("Reference: Index %p\n", | 511 | acpi_os_printf("Reference: [DdbHandle] TableIndex %p\n", |
515 | obj_desc->reference.object); | 512 | obj_desc->reference.object); |
516 | break; | 513 | break; |
517 | 514 | ||
518 | case AML_REF_OF_OP: | 515 | case AML_REF_OF_OP: |
519 | 516 | ||
520 | acpi_os_printf("Reference: (RefOf) %p\n", | 517 | acpi_os_printf("Reference: (RefOf) %p [%s]\n", |
521 | obj_desc->reference.object); | 518 | obj_desc->reference.object, |
519 | acpi_ut_get_type_name(((union | ||
520 | acpi_operand_object | ||
521 | *)obj_desc-> | ||
522 | reference. | ||
523 | object)->common. | ||
524 | type)); | ||
522 | break; | 525 | break; |
523 | 526 | ||
524 | case AML_ARG_OP: | 527 | case AML_ARG_OP: |
@@ -559,8 +562,9 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) | |||
559 | 562 | ||
560 | case AML_INT_NAMEPATH_OP: | 563 | case AML_INT_NAMEPATH_OP: |
561 | 564 | ||
562 | acpi_os_printf("Reference.Node->Name %X\n", | 565 | acpi_os_printf("Reference: Namepath %X [%4.4s]\n", |
563 | obj_desc->reference.node->name.integer); | 566 | obj_desc->reference.node->name.integer, |
567 | obj_desc->reference.node->name.ascii); | ||
564 | break; | 568 | break; |
565 | 569 | ||
566 | default: | 570 | default: |
@@ -640,8 +644,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) | |||
640 | acpi_os_printf("\n"); | 644 | acpi_os_printf("\n"); |
641 | } else { | 645 | } else { |
642 | acpi_os_printf(" base %8.8X%8.8X Length %X\n", | 646 | acpi_os_printf(" base %8.8X%8.8X Length %X\n", |
643 | ACPI_FORMAT_UINT64(obj_desc->region. | 647 | ACPI_FORMAT_NATIVE_UINT(obj_desc->region. |
644 | address), | 648 | address), |
645 | obj_desc->region.length); | 649 | obj_desc->region.length); |
646 | } | 650 | } |
647 | break; | 651 | break; |
@@ -877,20 +881,43 @@ static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc) | |||
877 | ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; | 881 | ret_buf.length = ACPI_ALLOCATE_LOCAL_BUFFER; |
878 | 882 | ||
879 | if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) { | 883 | if (obj_desc->reference.opcode == AML_INT_NAMEPATH_OP) { |
880 | acpi_os_printf("Named Object %p ", obj_desc->reference.node); | 884 | acpi_os_printf(" Named Object %p ", obj_desc->reference.node); |
881 | 885 | ||
882 | status = | 886 | status = |
883 | acpi_ns_handle_to_pathname(obj_desc->reference.node, | 887 | acpi_ns_handle_to_pathname(obj_desc->reference.node, |
884 | &ret_buf); | 888 | &ret_buf); |
885 | if (ACPI_FAILURE(status)) { | 889 | if (ACPI_FAILURE(status)) { |
886 | acpi_os_printf("Could not convert name to pathname\n"); | 890 | acpi_os_printf(" Could not convert name to pathname\n"); |
887 | } else { | 891 | } else { |
888 | acpi_os_printf("%s\n", (char *)ret_buf.pointer); | 892 | acpi_os_printf("%s\n", (char *)ret_buf.pointer); |
889 | ACPI_FREE(ret_buf.pointer); | 893 | ACPI_FREE(ret_buf.pointer); |
890 | } | 894 | } |
891 | } else if (obj_desc->reference.object) { | 895 | } else if (obj_desc->reference.object) { |
892 | acpi_os_printf("\nReferenced Object: %p\n", | 896 | if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == |
893 | obj_desc->reference.object); | 897 | ACPI_DESC_TYPE_OPERAND) { |
898 | acpi_os_printf(" Target: %p", | ||
899 | obj_desc->reference.object); | ||
900 | if (obj_desc->reference.opcode == AML_LOAD_OP) { | ||
901 | /* | ||
902 | * For DDBHandle reference, | ||
903 | * obj_desc->Reference.Object is the table index | ||
904 | */ | ||
905 | acpi_os_printf(" [DDBHandle]\n"); | ||
906 | } else { | ||
907 | acpi_os_printf(" [%s]\n", | ||
908 | acpi_ut_get_type_name(((union | ||
909 | acpi_operand_object | ||
910 | *) | ||
911 | obj_desc-> | ||
912 | reference. | ||
913 | object)-> | ||
914 | common. | ||
915 | type)); | ||
916 | } | ||
917 | } else { | ||
918 | acpi_os_printf(" Target: %p\n", | ||
919 | obj_desc->reference.object); | ||
920 | } | ||
894 | } | 921 | } |
895 | } | 922 | } |
896 | 923 | ||
@@ -976,7 +1003,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc, | |||
976 | 1003 | ||
977 | case ACPI_TYPE_LOCAL_REFERENCE: | 1004 | case ACPI_TYPE_LOCAL_REFERENCE: |
978 | 1005 | ||
979 | acpi_os_printf("[Object Reference] "); | 1006 | acpi_os_printf("[Object Reference] %s", |
1007 | (acpi_ps_get_opcode_info | ||
1008 | (obj_desc->reference.opcode))->name); | ||
980 | acpi_ex_dump_reference_obj(obj_desc); | 1009 | acpi_ex_dump_reference_obj(obj_desc); |
981 | break; | 1010 | break; |
982 | 1011 | ||
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index 2d88a3d8d1ad..3e440d84226a 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -71,7 +71,6 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, | |||
71 | union acpi_operand_object *buffer_desc; | 71 | union acpi_operand_object *buffer_desc; |
72 | acpi_size length; | 72 | acpi_size length; |
73 | void *buffer; | 73 | void *buffer; |
74 | u8 locked; | ||
75 | 74 | ||
76 | ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); | 75 | ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); |
77 | 76 | ||
@@ -111,9 +110,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, | |||
111 | 110 | ||
112 | /* Lock entire transaction if requested */ | 111 | /* Lock entire transaction if requested */ |
113 | 112 | ||
114 | locked = | 113 | acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); |
115 | acpi_ex_acquire_global_lock(obj_desc->common_field. | ||
116 | field_flags); | ||
117 | 114 | ||
118 | /* | 115 | /* |
119 | * Perform the read. | 116 | * Perform the read. |
@@ -125,7 +122,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, | |||
125 | buffer.pointer), | 122 | buffer.pointer), |
126 | ACPI_READ | (obj_desc->field. | 123 | ACPI_READ | (obj_desc->field. |
127 | attribute << 16)); | 124 | attribute << 16)); |
128 | acpi_ex_release_global_lock(locked); | 125 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); |
129 | goto exit; | 126 | goto exit; |
130 | } | 127 | } |
131 | 128 | ||
@@ -175,13 +172,12 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, | |||
175 | 172 | ||
176 | /* Lock entire transaction if requested */ | 173 | /* Lock entire transaction if requested */ |
177 | 174 | ||
178 | locked = | 175 | acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); |
179 | acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); | ||
180 | 176 | ||
181 | /* Read from the field */ | 177 | /* Read from the field */ |
182 | 178 | ||
183 | status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); | 179 | status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length); |
184 | acpi_ex_release_global_lock(locked); | 180 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); |
185 | 181 | ||
186 | exit: | 182 | exit: |
187 | if (ACPI_FAILURE(status)) { | 183 | if (ACPI_FAILURE(status)) { |
@@ -214,10 +210,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
214 | { | 210 | { |
215 | acpi_status status; | 211 | acpi_status status; |
216 | u32 length; | 212 | u32 length; |
217 | u32 required_length; | ||
218 | void *buffer; | 213 | void *buffer; |
219 | void *new_buffer; | ||
220 | u8 locked; | ||
221 | union acpi_operand_object *buffer_desc; | 214 | union acpi_operand_object *buffer_desc; |
222 | 215 | ||
223 | ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); | 216 | ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); |
@@ -278,9 +271,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
278 | 271 | ||
279 | /* Lock entire transaction if requested */ | 272 | /* Lock entire transaction if requested */ |
280 | 273 | ||
281 | locked = | 274 | acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); |
282 | acpi_ex_acquire_global_lock(obj_desc->common_field. | ||
283 | field_flags); | ||
284 | 275 | ||
285 | /* | 276 | /* |
286 | * Perform the write (returns status and perhaps data in the | 277 | * Perform the write (returns status and perhaps data in the |
@@ -291,7 +282,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
291 | (acpi_integer *) buffer, | 282 | (acpi_integer *) buffer, |
292 | ACPI_WRITE | (obj_desc->field. | 283 | ACPI_WRITE | (obj_desc->field. |
293 | attribute << 16)); | 284 | attribute << 16)); |
294 | acpi_ex_release_global_lock(locked); | 285 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); |
295 | 286 | ||
296 | *result_desc = buffer_desc; | 287 | *result_desc = buffer_desc; |
297 | return_ACPI_STATUS(status); | 288 | return_ACPI_STATUS(status); |
@@ -319,35 +310,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
319 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 310 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
320 | } | 311 | } |
321 | 312 | ||
322 | /* | ||
323 | * We must have a buffer that is at least as long as the field | ||
324 | * we are writing to. This is because individual fields are | ||
325 | * indivisible and partial writes are not supported -- as per | ||
326 | * the ACPI specification. | ||
327 | */ | ||
328 | new_buffer = NULL; | ||
329 | required_length = | ||
330 | ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); | ||
331 | |||
332 | if (length < required_length) { | ||
333 | |||
334 | /* We need to create a new buffer */ | ||
335 | |||
336 | new_buffer = ACPI_ALLOCATE_ZEROED(required_length); | ||
337 | if (!new_buffer) { | ||
338 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
339 | } | ||
340 | |||
341 | /* | ||
342 | * Copy the original data to the new buffer, starting | ||
343 | * at Byte zero. All unused (upper) bytes of the | ||
344 | * buffer will be 0. | ||
345 | */ | ||
346 | ACPI_MEMCPY((char *)new_buffer, (char *)buffer, length); | ||
347 | buffer = new_buffer; | ||
348 | length = required_length; | ||
349 | } | ||
350 | |||
351 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, | 313 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
352 | "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", | 314 | "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", |
353 | source_desc, | 315 | source_desc, |
@@ -366,19 +328,12 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
366 | 328 | ||
367 | /* Lock entire transaction if requested */ | 329 | /* Lock entire transaction if requested */ |
368 | 330 | ||
369 | locked = | 331 | acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); |
370 | acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); | ||
371 | 332 | ||
372 | /* Write to the field */ | 333 | /* Write to the field */ |
373 | 334 | ||
374 | status = acpi_ex_insert_into_field(obj_desc, buffer, length); | 335 | status = acpi_ex_insert_into_field(obj_desc, buffer, length); |
375 | acpi_ex_release_global_lock(locked); | 336 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); |
376 | |||
377 | /* Free temporary buffer if we used one */ | ||
378 | |||
379 | if (new_buffer) { | ||
380 | ACPI_FREE(new_buffer); | ||
381 | } | ||
382 | 337 | ||
383 | return_ACPI_STATUS(status); | 338 | return_ACPI_STATUS(status); |
384 | } | 339 | } |
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 65a48b6170ee..e336b5dc7a50 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -263,7 +263,8 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, | |||
263 | rgn_desc->region.space_id, | 263 | rgn_desc->region.space_id, |
264 | obj_desc->common_field.access_byte_width, | 264 | obj_desc->common_field.access_byte_width, |
265 | obj_desc->common_field.base_byte_offset, | 265 | obj_desc->common_field.base_byte_offset, |
266 | field_datum_byte_offset, (void *)address)); | 266 | field_datum_byte_offset, ACPI_CAST_PTR(void, |
267 | address))); | ||
267 | 268 | ||
268 | /* Invoke the appropriate address_space/op_region handler */ | 269 | /* Invoke the appropriate address_space/op_region handler */ |
269 | 270 | ||
@@ -805,18 +806,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
805 | u32 datum_count; | 806 | u32 datum_count; |
806 | u32 field_datum_count; | 807 | u32 field_datum_count; |
807 | u32 i; | 808 | u32 i; |
809 | u32 required_length; | ||
810 | void *new_buffer; | ||
808 | 811 | ||
809 | ACPI_FUNCTION_TRACE(ex_insert_into_field); | 812 | ACPI_FUNCTION_TRACE(ex_insert_into_field); |
810 | 813 | ||
811 | /* Validate input buffer */ | 814 | /* Validate input buffer */ |
812 | 815 | ||
813 | if (buffer_length < | 816 | new_buffer = NULL; |
814 | ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { | 817 | required_length = |
815 | ACPI_ERROR((AE_INFO, | 818 | ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); |
816 | "Field size %X (bits) is too large for buffer (%X)", | 819 | /* |
817 | obj_desc->common_field.bit_length, buffer_length)); | 820 | * We must have a buffer that is at least as long as the field |
821 | * we are writing to. This is because individual fields are | ||
822 | * indivisible and partial writes are not supported -- as per | ||
823 | * the ACPI specification. | ||
824 | */ | ||
825 | if (buffer_length < required_length) { | ||
818 | 826 | ||
819 | return_ACPI_STATUS(AE_BUFFER_OVERFLOW); | 827 | /* We need to create a new buffer */ |
828 | |||
829 | new_buffer = ACPI_ALLOCATE_ZEROED(required_length); | ||
830 | if (!new_buffer) { | ||
831 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
832 | } | ||
833 | |||
834 | /* | ||
835 | * Copy the original data to the new buffer, starting | ||
836 | * at Byte zero. All unused (upper) bytes of the | ||
837 | * buffer will be 0. | ||
838 | */ | ||
839 | ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); | ||
840 | buffer = new_buffer; | ||
841 | buffer_length = required_length; | ||
820 | } | 842 | } |
821 | 843 | ||
822 | /* | 844 | /* |
@@ -866,7 +888,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
866 | merged_datum, | 888 | merged_datum, |
867 | field_offset); | 889 | field_offset); |
868 | if (ACPI_FAILURE(status)) { | 890 | if (ACPI_FAILURE(status)) { |
869 | return_ACPI_STATUS(status); | 891 | goto exit; |
870 | } | 892 | } |
871 | 893 | ||
872 | field_offset += obj_desc->common_field.access_byte_width; | 894 | field_offset += obj_desc->common_field.access_byte_width; |
@@ -924,5 +946,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
924 | mask, merged_datum, | 946 | mask, merged_datum, |
925 | field_offset); | 947 | field_offset); |
926 | 948 | ||
949 | exit: | ||
950 | /* Free temporary buffer if we used one */ | ||
951 | |||
952 | if (new_buffer) { | ||
953 | ACPI_FREE(new_buffer); | ||
954 | } | ||
927 | return_ACPI_STATUS(status); | 955 | return_ACPI_STATUS(status); |
928 | } | 956 | } |
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c index f13d1cec2d6d..cc956a5b5267 100644 --- a/drivers/acpi/executer/exmisc.c +++ b/drivers/acpi/executer/exmisc.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index 6748e3ef0997..c873ab40cd0e 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -126,6 +126,79 @@ acpi_ex_link_mutex(union acpi_operand_object *obj_desc, | |||
126 | 126 | ||
127 | /******************************************************************************* | 127 | /******************************************************************************* |
128 | * | 128 | * |
129 | * FUNCTION: acpi_ex_acquire_mutex_object | ||
130 | * | ||
131 | * PARAMETERS: time_desc - Timeout in milliseconds | ||
132 | * obj_desc - Mutex object | ||
133 | * Thread - Current thread state | ||
134 | * | ||
135 | * RETURN: Status | ||
136 | * | ||
137 | * DESCRIPTION: Acquire an AML mutex, low-level interface. Provides a common | ||
138 | * path that supports multiple acquires by the same thread. | ||
139 | * | ||
140 | * MUTEX: Interpreter must be locked | ||
141 | * | ||
142 | * NOTE: This interface is called from three places: | ||
143 | * 1) From acpi_ex_acquire_mutex, via an AML Acquire() operator | ||
144 | * 2) From acpi_ex_acquire_global_lock when an AML Field access requires the | ||
145 | * global lock | ||
146 | * 3) From the external interface, acpi_acquire_global_lock | ||
147 | * | ||
148 | ******************************************************************************/ | ||
149 | |||
150 | acpi_status | ||
151 | acpi_ex_acquire_mutex_object(u16 timeout, | ||
152 | union acpi_operand_object *obj_desc, | ||
153 | acpi_thread_id thread_id) | ||
154 | { | ||
155 | acpi_status status; | ||
156 | |||
157 | ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex_object, obj_desc); | ||
158 | |||
159 | if (!obj_desc) { | ||
160 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
161 | } | ||
162 | |||
163 | /* Support for multiple acquires by the owning thread */ | ||
164 | |||
165 | if (obj_desc->mutex.thread_id == thread_id) { | ||
166 | /* | ||
167 | * The mutex is already owned by this thread, just increment the | ||
168 | * acquisition depth | ||
169 | */ | ||
170 | obj_desc->mutex.acquisition_depth++; | ||
171 | return_ACPI_STATUS(AE_OK); | ||
172 | } | ||
173 | |||
174 | /* Acquire the mutex, wait if necessary. Special case for Global Lock */ | ||
175 | |||
176 | if (obj_desc == acpi_gbl_global_lock_mutex) { | ||
177 | status = acpi_ev_acquire_global_lock(timeout); | ||
178 | } else { | ||
179 | status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, | ||
180 | timeout); | ||
181 | } | ||
182 | |||
183 | if (ACPI_FAILURE(status)) { | ||
184 | |||
185 | /* Includes failure from a timeout on time_desc */ | ||
186 | |||
187 | return_ACPI_STATUS(status); | ||
188 | } | ||
189 | |||
190 | /* Acquired the mutex: update mutex object */ | ||
191 | |||
192 | obj_desc->mutex.thread_id = thread_id; | ||
193 | obj_desc->mutex.acquisition_depth = 1; | ||
194 | obj_desc->mutex.original_sync_level = 0; | ||
195 | obj_desc->mutex.owner_thread = NULL; /* Used only for AML Acquire() */ | ||
196 | |||
197 | return_ACPI_STATUS(AE_OK); | ||
198 | } | ||
199 | |||
200 | /******************************************************************************* | ||
201 | * | ||
129 | * FUNCTION: acpi_ex_acquire_mutex | 202 | * FUNCTION: acpi_ex_acquire_mutex |
130 | * | 203 | * |
131 | * PARAMETERS: time_desc - Timeout integer | 204 | * PARAMETERS: time_desc - Timeout integer |
@@ -151,7 +224,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, | |||
151 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 224 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
152 | } | 225 | } |
153 | 226 | ||
154 | /* Sanity check: we must have a valid thread ID */ | 227 | /* Must have a valid thread ID */ |
155 | 228 | ||
156 | if (!walk_state->thread) { | 229 | if (!walk_state->thread) { |
157 | ACPI_ERROR((AE_INFO, | 230 | ACPI_ERROR((AE_INFO, |
@@ -161,7 +234,7 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, | |||
161 | } | 234 | } |
162 | 235 | ||
163 | /* | 236 | /* |
164 | * Current Sync must be less than or equal to the sync level of the | 237 | * Current sync level must be less than or equal to the sync level of the |
165 | * mutex. This mechanism provides some deadlock prevention | 238 | * mutex. This mechanism provides some deadlock prevention |
166 | */ | 239 | */ |
167 | if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { | 240 | if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) { |
@@ -172,51 +245,89 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, | |||
172 | return_ACPI_STATUS(AE_AML_MUTEX_ORDER); | 245 | return_ACPI_STATUS(AE_AML_MUTEX_ORDER); |
173 | } | 246 | } |
174 | 247 | ||
175 | /* Support for multiple acquires by the owning thread */ | 248 | status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value, |
249 | obj_desc, | ||
250 | walk_state->thread->thread_id); | ||
251 | if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) { | ||
176 | 252 | ||
177 | if (obj_desc->mutex.owner_thread) { | 253 | /* Save Thread object, original/current sync levels */ |
178 | if (obj_desc->mutex.owner_thread->thread_id == | 254 | |
179 | walk_state->thread->thread_id) { | 255 | obj_desc->mutex.owner_thread = walk_state->thread; |
180 | /* | 256 | obj_desc->mutex.original_sync_level = |
181 | * The mutex is already owned by this thread, just increment the | 257 | walk_state->thread->current_sync_level; |
182 | * acquisition depth | 258 | walk_state->thread->current_sync_level = |
183 | */ | 259 | obj_desc->mutex.sync_level; |
184 | obj_desc->mutex.acquisition_depth++; | 260 | |
185 | return_ACPI_STATUS(AE_OK); | 261 | /* Link the mutex to the current thread for force-unlock at method exit */ |
186 | } | 262 | |
263 | acpi_ex_link_mutex(obj_desc, walk_state->thread); | ||
187 | } | 264 | } |
188 | 265 | ||
189 | /* Acquire the mutex, wait if necessary. Special case for Global Lock */ | 266 | return_ACPI_STATUS(status); |
267 | } | ||
190 | 268 | ||
191 | if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { | 269 | /******************************************************************************* |
192 | status = | 270 | * |
193 | acpi_ev_acquire_global_lock((u16) time_desc->integer.value); | 271 | * FUNCTION: acpi_ex_release_mutex_object |
194 | } else { | 272 | * |
195 | status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex, | 273 | * PARAMETERS: obj_desc - The object descriptor for this op |
196 | (u16) time_desc->integer. | 274 | * |
197 | value); | 275 | * RETURN: Status |
276 | * | ||
277 | * DESCRIPTION: Release a previously acquired Mutex, low level interface. | ||
278 | * Provides a common path that supports multiple releases (after | ||
279 | * previous multiple acquires) by the same thread. | ||
280 | * | ||
281 | * MUTEX: Interpreter must be locked | ||
282 | * | ||
283 | * NOTE: This interface is called from three places: | ||
284 | * 1) From acpi_ex_release_mutex, via an AML Acquire() operator | ||
285 | * 2) From acpi_ex_release_global_lock when an AML Field access requires the | ||
286 | * global lock | ||
287 | * 3) From the external interface, acpi_release_global_lock | ||
288 | * | ||
289 | ******************************************************************************/ | ||
290 | |||
291 | acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) | ||
292 | { | ||
293 | acpi_status status = AE_OK; | ||
294 | |||
295 | ACPI_FUNCTION_TRACE(ex_release_mutex_object); | ||
296 | |||
297 | if (obj_desc->mutex.acquisition_depth == 0) { | ||
298 | return (AE_NOT_ACQUIRED); | ||
198 | } | 299 | } |
199 | 300 | ||
200 | if (ACPI_FAILURE(status)) { | 301 | /* Match multiple Acquires with multiple Releases */ |
201 | 302 | ||
202 | /* Includes failure from a timeout on time_desc */ | 303 | obj_desc->mutex.acquisition_depth--; |
304 | if (obj_desc->mutex.acquisition_depth != 0) { | ||
203 | 305 | ||
204 | return_ACPI_STATUS(status); | 306 | /* Just decrement the depth and return */ |
307 | |||
308 | return_ACPI_STATUS(AE_OK); | ||
205 | } | 309 | } |
206 | 310 | ||
207 | /* Have the mutex: update mutex and walk info and save the sync_level */ | 311 | if (obj_desc->mutex.owner_thread) { |
208 | 312 | ||
209 | obj_desc->mutex.owner_thread = walk_state->thread; | 313 | /* Unlink the mutex from the owner's list */ |
210 | obj_desc->mutex.acquisition_depth = 1; | ||
211 | obj_desc->mutex.original_sync_level = | ||
212 | walk_state->thread->current_sync_level; | ||
213 | 314 | ||
214 | walk_state->thread->current_sync_level = obj_desc->mutex.sync_level; | 315 | acpi_ex_unlink_mutex(obj_desc); |
316 | obj_desc->mutex.owner_thread = NULL; | ||
317 | } | ||
215 | 318 | ||
216 | /* Link the mutex to the current thread for force-unlock at method exit */ | 319 | /* Release the mutex, special case for Global Lock */ |
217 | 320 | ||
218 | acpi_ex_link_mutex(obj_desc, walk_state->thread); | 321 | if (obj_desc == acpi_gbl_global_lock_mutex) { |
219 | return_ACPI_STATUS(AE_OK); | 322 | status = acpi_ev_release_global_lock(); |
323 | } else { | ||
324 | acpi_os_release_mutex(obj_desc->mutex.os_mutex); | ||
325 | } | ||
326 | |||
327 | /* Clear mutex info */ | ||
328 | |||
329 | obj_desc->mutex.thread_id = 0; | ||
330 | return_ACPI_STATUS(status); | ||
220 | } | 331 | } |
221 | 332 | ||
222 | /******************************************************************************* | 333 | /******************************************************************************* |
@@ -253,22 +364,13 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
253 | return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); | 364 | return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); |
254 | } | 365 | } |
255 | 366 | ||
256 | /* Sanity check: we must have a valid thread ID */ | ||
257 | |||
258 | if (!walk_state->thread) { | ||
259 | ACPI_ERROR((AE_INFO, | ||
260 | "Cannot release Mutex [%4.4s], null thread info", | ||
261 | acpi_ut_get_node_name(obj_desc->mutex.node))); | ||
262 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
263 | } | ||
264 | |||
265 | /* | 367 | /* |
266 | * The Mutex is owned, but this thread must be the owner. | 368 | * The Mutex is owned, but this thread must be the owner. |
267 | * Special case for Global Lock, any thread can release | 369 | * Special case for Global Lock, any thread can release |
268 | */ | 370 | */ |
269 | if ((obj_desc->mutex.owner_thread->thread_id != | 371 | if ((obj_desc->mutex.owner_thread->thread_id != |
270 | walk_state->thread->thread_id) | 372 | walk_state->thread->thread_id) |
271 | && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) { | 373 | && (obj_desc != acpi_gbl_global_lock_mutex)) { |
272 | ACPI_ERROR((AE_INFO, | 374 | ACPI_ERROR((AE_INFO, |
273 | "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", | 375 | "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX", |
274 | (unsigned long)walk_state->thread->thread_id, | 376 | (unsigned long)walk_state->thread->thread_id, |
@@ -278,45 +380,37 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, | |||
278 | return_ACPI_STATUS(AE_AML_NOT_OWNER); | 380 | return_ACPI_STATUS(AE_AML_NOT_OWNER); |
279 | } | 381 | } |
280 | 382 | ||
383 | /* Must have a valid thread ID */ | ||
384 | |||
385 | if (!walk_state->thread) { | ||
386 | ACPI_ERROR((AE_INFO, | ||
387 | "Cannot release Mutex [%4.4s], null thread info", | ||
388 | acpi_ut_get_node_name(obj_desc->mutex.node))); | ||
389 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
390 | } | ||
391 | |||
281 | /* | 392 | /* |
282 | * The sync level of the mutex must be less than or equal to the current | 393 | * The sync level of the mutex must be less than or equal to the current |
283 | * sync level | 394 | * sync level |
284 | */ | 395 | */ |
285 | if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { | 396 | if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) { |
286 | ACPI_ERROR((AE_INFO, | 397 | ACPI_ERROR((AE_INFO, |
287 | "Cannot release Mutex [%4.4s], incorrect SyncLevel", | 398 | "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %d current %d", |
288 | acpi_ut_get_node_name(obj_desc->mutex.node))); | 399 | acpi_ut_get_node_name(obj_desc->mutex.node), |
400 | obj_desc->mutex.sync_level, | ||
401 | walk_state->thread->current_sync_level)); | ||
289 | return_ACPI_STATUS(AE_AML_MUTEX_ORDER); | 402 | return_ACPI_STATUS(AE_AML_MUTEX_ORDER); |
290 | } | 403 | } |
291 | 404 | ||
292 | /* Match multiple Acquires with multiple Releases */ | 405 | status = acpi_ex_release_mutex_object(obj_desc); |
293 | |||
294 | obj_desc->mutex.acquisition_depth--; | ||
295 | if (obj_desc->mutex.acquisition_depth != 0) { | ||
296 | |||
297 | /* Just decrement the depth and return */ | ||
298 | |||
299 | return_ACPI_STATUS(AE_OK); | ||
300 | } | ||
301 | |||
302 | /* Unlink the mutex from the owner's list */ | ||
303 | 406 | ||
304 | acpi_ex_unlink_mutex(obj_desc); | 407 | if (obj_desc->mutex.acquisition_depth == 0) { |
305 | 408 | ||
306 | /* Release the mutex, special case for Global Lock */ | 409 | /* Restore the original sync_level */ |
307 | 410 | ||
308 | if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { | 411 | walk_state->thread->current_sync_level = |
309 | status = acpi_ev_release_global_lock(); | 412 | obj_desc->mutex.original_sync_level; |
310 | } else { | ||
311 | acpi_os_release_mutex(obj_desc->mutex.os_mutex); | ||
312 | } | 413 | } |
313 | |||
314 | /* Update the mutex and restore sync_level */ | ||
315 | |||
316 | obj_desc->mutex.owner_thread = NULL; | ||
317 | walk_state->thread->current_sync_level = | ||
318 | obj_desc->mutex.original_sync_level; | ||
319 | |||
320 | return_ACPI_STATUS(status); | 414 | return_ACPI_STATUS(status); |
321 | } | 415 | } |
322 | 416 | ||
@@ -357,7 +451,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) | |||
357 | 451 | ||
358 | /* Release the mutex, special case for Global Lock */ | 452 | /* Release the mutex, special case for Global Lock */ |
359 | 453 | ||
360 | if (obj_desc->mutex.os_mutex == acpi_gbl_global_lock_mutex) { | 454 | if (obj_desc == acpi_gbl_global_lock_mutex) { |
361 | 455 | ||
362 | /* Ignore errors */ | 456 | /* Ignore errors */ |
363 | 457 | ||
@@ -369,6 +463,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) | |||
369 | /* Mark mutex unowned */ | 463 | /* Mark mutex unowned */ |
370 | 464 | ||
371 | obj_desc->mutex.owner_thread = NULL; | 465 | obj_desc->mutex.owner_thread = NULL; |
466 | obj_desc->mutex.thread_id = 0; | ||
372 | 467 | ||
373 | /* Update Thread sync_level (Last mutex is the important one) */ | 468 | /* Update Thread sync_level (Last mutex is the important one) */ |
374 | 469 | ||
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c index 308eae52dc05..817e67be3697 100644 --- a/drivers/acpi/executer/exnames.c +++ b/drivers/acpi/executer/exnames.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c index 252f10acbbcc..7c3bea575e02 100644 --- a/drivers/acpi/executer/exoparg1.c +++ b/drivers/acpi/executer/exoparg1.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -121,6 +121,7 @@ acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state) | |||
121 | 121 | ||
122 | if ((ACPI_FAILURE(status)) || walk_state->result_obj) { | 122 | if ((ACPI_FAILURE(status)) || walk_state->result_obj) { |
123 | acpi_ut_remove_reference(return_desc); | 123 | acpi_ut_remove_reference(return_desc); |
124 | walk_state->result_obj = NULL; | ||
124 | } else { | 125 | } else { |
125 | /* Save the return value */ | 126 | /* Save the return value */ |
126 | 127 | ||
@@ -739,26 +740,38 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) | |||
739 | value = acpi_gbl_integer_byte_width; | 740 | value = acpi_gbl_integer_byte_width; |
740 | break; | 741 | break; |
741 | 742 | ||
742 | case ACPI_TYPE_BUFFER: | ||
743 | value = temp_desc->buffer.length; | ||
744 | break; | ||
745 | |||
746 | case ACPI_TYPE_STRING: | 743 | case ACPI_TYPE_STRING: |
747 | value = temp_desc->string.length; | 744 | value = temp_desc->string.length; |
748 | break; | 745 | break; |
749 | 746 | ||
747 | case ACPI_TYPE_BUFFER: | ||
748 | |||
749 | /* Buffer arguments may not be evaluated at this point */ | ||
750 | |||
751 | status = acpi_ds_get_buffer_arguments(temp_desc); | ||
752 | value = temp_desc->buffer.length; | ||
753 | break; | ||
754 | |||
750 | case ACPI_TYPE_PACKAGE: | 755 | case ACPI_TYPE_PACKAGE: |
756 | |||
757 | /* Package arguments may not be evaluated at this point */ | ||
758 | |||
759 | status = acpi_ds_get_package_arguments(temp_desc); | ||
751 | value = temp_desc->package.count; | 760 | value = temp_desc->package.count; |
752 | break; | 761 | break; |
753 | 762 | ||
754 | default: | 763 | default: |
755 | ACPI_ERROR((AE_INFO, | 764 | ACPI_ERROR((AE_INFO, |
756 | "Operand is not Buf/Int/Str/Pkg - found type %s", | 765 | "Operand must be Buffer/Integer/String/Package - found type %s", |
757 | acpi_ut_get_type_name(type))); | 766 | acpi_ut_get_type_name(type))); |
758 | status = AE_AML_OPERAND_TYPE; | 767 | status = AE_AML_OPERAND_TYPE; |
759 | goto cleanup; | 768 | goto cleanup; |
760 | } | 769 | } |
761 | 770 | ||
771 | if (ACPI_FAILURE(status)) { | ||
772 | goto cleanup; | ||
773 | } | ||
774 | |||
762 | /* | 775 | /* |
763 | * Now that we have the size of the object, create a result | 776 | * Now that we have the size of the object, create a result |
764 | * object to hold the value | 777 | * object to hold the value |
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c index 17e652e65379..8e8bbb6ccebd 100644 --- a/drivers/acpi/executer/exoparg2.c +++ b/drivers/acpi/executer/exoparg2.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -241,10 +241,6 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) | |||
241 | goto cleanup; | 241 | goto cleanup; |
242 | } | 242 | } |
243 | 243 | ||
244 | /* Return the remainder */ | ||
245 | |||
246 | walk_state->result_obj = return_desc1; | ||
247 | |||
248 | cleanup: | 244 | cleanup: |
249 | /* | 245 | /* |
250 | * Since the remainder is not returned indirectly, remove a reference to | 246 | * Since the remainder is not returned indirectly, remove a reference to |
@@ -259,6 +255,12 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) | |||
259 | acpi_ut_remove_reference(return_desc1); | 255 | acpi_ut_remove_reference(return_desc1); |
260 | } | 256 | } |
261 | 257 | ||
258 | /* Save return object (the remainder) on success */ | ||
259 | |||
260 | else { | ||
261 | walk_state->result_obj = return_desc1; | ||
262 | } | ||
263 | |||
262 | return_ACPI_STATUS(status); | 264 | return_ACPI_STATUS(status); |
263 | } | 265 | } |
264 | 266 | ||
@@ -490,6 +492,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) | |||
490 | 492 | ||
491 | if (ACPI_FAILURE(status)) { | 493 | if (ACPI_FAILURE(status)) { |
492 | acpi_ut_remove_reference(return_desc); | 494 | acpi_ut_remove_reference(return_desc); |
495 | walk_state->result_obj = NULL; | ||
493 | } | 496 | } |
494 | 497 | ||
495 | return_ACPI_STATUS(status); | 498 | return_ACPI_STATUS(status); |
@@ -583,8 +586,6 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) | |||
583 | return_desc->integer.value = ACPI_INTEGER_MAX; | 586 | return_desc->integer.value = ACPI_INTEGER_MAX; |
584 | } | 587 | } |
585 | 588 | ||
586 | walk_state->result_obj = return_desc; | ||
587 | |||
588 | cleanup: | 589 | cleanup: |
589 | 590 | ||
590 | /* Delete return object on error */ | 591 | /* Delete return object on error */ |
@@ -593,5 +594,11 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) | |||
593 | acpi_ut_remove_reference(return_desc); | 594 | acpi_ut_remove_reference(return_desc); |
594 | } | 595 | } |
595 | 596 | ||
597 | /* Save return object on success */ | ||
598 | |||
599 | else { | ||
600 | walk_state->result_obj = return_desc; | ||
601 | } | ||
602 | |||
596 | return_ACPI_STATUS(status); | 603 | return_ACPI_STATUS(status); |
597 | } | 604 | } |
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c index 7fe67cf82cee..9cb4197681af 100644 --- a/drivers/acpi/executer/exoparg3.c +++ b/drivers/acpi/executer/exoparg3.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -260,6 +260,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) | |||
260 | 260 | ||
261 | if (ACPI_FAILURE(status) || walk_state->result_obj) { | 261 | if (ACPI_FAILURE(status) || walk_state->result_obj) { |
262 | acpi_ut_remove_reference(return_desc); | 262 | acpi_ut_remove_reference(return_desc); |
263 | walk_state->result_obj = NULL; | ||
263 | } | 264 | } |
264 | 265 | ||
265 | /* Set the return object and exit */ | 266 | /* Set the return object and exit */ |
diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c index bd80a9cb3d65..67d48737af53 100644 --- a/drivers/acpi/executer/exoparg6.c +++ b/drivers/acpi/executer/exoparg6.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -322,8 +322,6 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) | |||
322 | goto cleanup; | 322 | goto cleanup; |
323 | } | 323 | } |
324 | 324 | ||
325 | walk_state->result_obj = return_desc; | ||
326 | |||
327 | cleanup: | 325 | cleanup: |
328 | 326 | ||
329 | /* Delete return object on error */ | 327 | /* Delete return object on error */ |
@@ -332,5 +330,11 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) | |||
332 | acpi_ut_remove_reference(return_desc); | 330 | acpi_ut_remove_reference(return_desc); |
333 | } | 331 | } |
334 | 332 | ||
333 | /* Save return object on success */ | ||
334 | |||
335 | else { | ||
336 | walk_state->result_obj = return_desc; | ||
337 | } | ||
338 | |||
335 | return_ACPI_STATUS(status); | 339 | return_ACPI_STATUS(status); |
336 | } | 340 | } |
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c index efe5d4b461a4..3a2f8cd4c62a 100644 --- a/drivers/acpi/executer/exprep.c +++ b/drivers/acpi/executer/exprep.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -412,6 +412,7 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, | |||
412 | acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) | 412 | acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) |
413 | { | 413 | { |
414 | union acpi_operand_object *obj_desc; | 414 | union acpi_operand_object *obj_desc; |
415 | union acpi_operand_object *second_desc = NULL; | ||
415 | u32 type; | 416 | u32 type; |
416 | acpi_status status; | 417 | acpi_status status; |
417 | 418 | ||
@@ -494,6 +495,20 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) | |||
494 | obj_desc->field.access_byte_width, | 495 | obj_desc->field.access_byte_width, |
495 | obj_desc->bank_field.region_obj, | 496 | obj_desc->bank_field.region_obj, |
496 | obj_desc->bank_field.bank_obj)); | 497 | obj_desc->bank_field.bank_obj)); |
498 | |||
499 | /* | ||
500 | * Remember location in AML stream of the field unit | ||
501 | * opcode and operands -- since the bank_value | ||
502 | * operands must be evaluated. | ||
503 | */ | ||
504 | second_desc = obj_desc->common.next_object; | ||
505 | second_desc->extra.aml_start = | ||
506 | ((union acpi_parse_object *)(info->data_register_node))-> | ||
507 | named.data; | ||
508 | second_desc->extra.aml_length = | ||
509 | ((union acpi_parse_object *)(info->data_register_node))-> | ||
510 | named.length; | ||
511 | |||
497 | break; | 512 | break; |
498 | 513 | ||
499 | case ACPI_TYPE_LOCAL_INDEX_FIELD: | 514 | case ACPI_TYPE_LOCAL_INDEX_FIELD: |
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c index 3f51b7e84a17..7cd8bb54fa01 100644 --- a/drivers/acpi/executer/exregion.c +++ b/drivers/acpi/executer/exregion.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -160,7 +160,7 @@ acpi_ex_system_memory_space_handler(u32 function, | |||
160 | if (!mem_info->mapped_logical_address) { | 160 | if (!mem_info->mapped_logical_address) { |
161 | ACPI_ERROR((AE_INFO, | 161 | ACPI_ERROR((AE_INFO, |
162 | "Could not map memory at %8.8X%8.8X, size %X", | 162 | "Could not map memory at %8.8X%8.8X, size %X", |
163 | ACPI_FORMAT_UINT64(address), | 163 | ACPI_FORMAT_NATIVE_UINT(address), |
164 | (u32) window_size)); | 164 | (u32) window_size)); |
165 | mem_info->mapped_length = 0; | 165 | mem_info->mapped_length = 0; |
166 | return_ACPI_STATUS(AE_NO_MEMORY); | 166 | return_ACPI_STATUS(AE_NO_MEMORY); |
@@ -182,7 +182,8 @@ acpi_ex_system_memory_space_handler(u32 function, | |||
182 | 182 | ||
183 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 183 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
184 | "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", | 184 | "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n", |
185 | bit_width, function, ACPI_FORMAT_UINT64(address))); | 185 | bit_width, function, |
186 | ACPI_FORMAT_NATIVE_UINT(address))); | ||
186 | 187 | ||
187 | /* | 188 | /* |
188 | * Perform the memory read or write | 189 | * Perform the memory read or write |
@@ -284,7 +285,8 @@ acpi_ex_system_io_space_handler(u32 function, | |||
284 | 285 | ||
285 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 286 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
286 | "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", | 287 | "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n", |
287 | bit_width, function, ACPI_FORMAT_UINT64(address))); | 288 | bit_width, function, |
289 | ACPI_FORMAT_NATIVE_UINT(address))); | ||
288 | 290 | ||
289 | /* Decode the function parameter */ | 291 | /* Decode the function parameter */ |
290 | 292 | ||
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c index 2b3a01cc4929..5596f42c9676 100644 --- a/drivers/acpi/executer/exresnte.c +++ b/drivers/acpi/executer/exresnte.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -116,9 +116,11 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, | |||
116 | * Several object types require no further processing: | 116 | * Several object types require no further processing: |
117 | * 1) Device/Thermal objects don't have a "real" subobject, return the Node | 117 | * 1) Device/Thermal objects don't have a "real" subobject, return the Node |
118 | * 2) Method locals and arguments have a pseudo-Node | 118 | * 2) Method locals and arguments have a pseudo-Node |
119 | * 3) 10/2007: Added method type to assist with Package construction. | ||
119 | */ | 120 | */ |
120 | if ((entry_type == ACPI_TYPE_DEVICE) || | 121 | if ((entry_type == ACPI_TYPE_DEVICE) || |
121 | (entry_type == ACPI_TYPE_THERMAL) || | 122 | (entry_type == ACPI_TYPE_THERMAL) || |
123 | (entry_type == ACPI_TYPE_METHOD) || | ||
122 | (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { | 124 | (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { |
123 | return_ACPI_STATUS(AE_OK); | 125 | return_ACPI_STATUS(AE_OK); |
124 | } | 126 | } |
@@ -214,7 +216,6 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, | |||
214 | /* For these objects, just return the object attached to the Node */ | 216 | /* For these objects, just return the object attached to the Node */ |
215 | 217 | ||
216 | case ACPI_TYPE_MUTEX: | 218 | case ACPI_TYPE_MUTEX: |
217 | case ACPI_TYPE_METHOD: | ||
218 | case ACPI_TYPE_POWER: | 219 | case ACPI_TYPE_POWER: |
219 | case ACPI_TYPE_PROCESSOR: | 220 | case ACPI_TYPE_PROCESSOR: |
220 | case ACPI_TYPE_EVENT: | 221 | case ACPI_TYPE_EVENT: |
@@ -238,13 +239,12 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, | |||
238 | case ACPI_TYPE_LOCAL_REFERENCE: | 239 | case ACPI_TYPE_LOCAL_REFERENCE: |
239 | 240 | ||
240 | switch (source_desc->reference.opcode) { | 241 | switch (source_desc->reference.opcode) { |
241 | case AML_LOAD_OP: | 242 | case AML_LOAD_OP: /* This is a ddb_handle */ |
243 | case AML_REF_OF_OP: | ||
244 | case AML_INDEX_OP: | ||
242 | 245 | ||
243 | /* This is a ddb_handle */ | ||
244 | /* Return an additional reference to the object */ | 246 | /* Return an additional reference to the object */ |
245 | 247 | ||
246 | case AML_REF_OF_OP: | ||
247 | |||
248 | obj_desc = source_desc; | 248 | obj_desc = source_desc; |
249 | acpi_ut_add_reference(obj_desc); | 249 | acpi_ut_add_reference(obj_desc); |
250 | break; | 250 | break; |
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c index 6c64e55dab0e..b35f7c817acf 100644 --- a/drivers/acpi/executer/exresolv.c +++ b/drivers/acpi/executer/exresolv.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -140,7 +140,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, | |||
140 | { | 140 | { |
141 | acpi_status status = AE_OK; | 141 | acpi_status status = AE_OK; |
142 | union acpi_operand_object *stack_desc; | 142 | union acpi_operand_object *stack_desc; |
143 | void *temp_node; | ||
144 | union acpi_operand_object *obj_desc = NULL; | 143 | union acpi_operand_object *obj_desc = NULL; |
145 | u16 opcode; | 144 | u16 opcode; |
146 | 145 | ||
@@ -156,23 +155,6 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, | |||
156 | opcode = stack_desc->reference.opcode; | 155 | opcode = stack_desc->reference.opcode; |
157 | 156 | ||
158 | switch (opcode) { | 157 | switch (opcode) { |
159 | case AML_NAME_OP: | ||
160 | |||
161 | /* | ||
162 | * Convert name reference to a namespace node | ||
163 | * Then, acpi_ex_resolve_node_to_value can be used to get the value | ||
164 | */ | ||
165 | temp_node = stack_desc->reference.object; | ||
166 | |||
167 | /* Delete the Reference Object */ | ||
168 | |||
169 | acpi_ut_remove_reference(stack_desc); | ||
170 | |||
171 | /* Return the namespace node */ | ||
172 | |||
173 | (*stack_ptr) = temp_node; | ||
174 | break; | ||
175 | |||
176 | case AML_LOCAL_OP: | 158 | case AML_LOCAL_OP: |
177 | case AML_ARG_OP: | 159 | case AML_ARG_OP: |
178 | 160 | ||
@@ -207,15 +189,25 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, | |||
207 | switch (stack_desc->reference.target_type) { | 189 | switch (stack_desc->reference.target_type) { |
208 | case ACPI_TYPE_BUFFER_FIELD: | 190 | case ACPI_TYPE_BUFFER_FIELD: |
209 | 191 | ||
210 | /* Just return - leave the Reference on the stack */ | 192 | /* Just return - do not dereference */ |
211 | break; | 193 | break; |
212 | 194 | ||
213 | case ACPI_TYPE_PACKAGE: | 195 | case ACPI_TYPE_PACKAGE: |
214 | 196 | ||
197 | /* If method call or copy_object - do not dereference */ | ||
198 | |||
199 | if ((walk_state->opcode == | ||
200 | AML_INT_METHODCALL_OP) | ||
201 | || (walk_state->opcode == AML_COPY_OP)) { | ||
202 | break; | ||
203 | } | ||
204 | |||
205 | /* Otherwise, dereference the package_index to a package element */ | ||
206 | |||
215 | obj_desc = *stack_desc->reference.where; | 207 | obj_desc = *stack_desc->reference.where; |
216 | if (obj_desc) { | 208 | if (obj_desc) { |
217 | /* | 209 | /* |
218 | * Valid obj descriptor, copy pointer to return value | 210 | * Valid object descriptor, copy pointer to return value |
219 | * (i.e., dereference the package index) | 211 | * (i.e., dereference the package index) |
220 | * Delete the ref object, increment the returned object | 212 | * Delete the ref object, increment the returned object |
221 | */ | 213 | */ |
@@ -224,11 +216,11 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, | |||
224 | *stack_ptr = obj_desc; | 216 | *stack_ptr = obj_desc; |
225 | } else { | 217 | } else { |
226 | /* | 218 | /* |
227 | * A NULL object descriptor means an unitialized element of | 219 | * A NULL object descriptor means an uninitialized element of |
228 | * the package, can't dereference it | 220 | * the package, can't dereference it |
229 | */ | 221 | */ |
230 | ACPI_ERROR((AE_INFO, | 222 | ACPI_ERROR((AE_INFO, |
231 | "Attempt to deref an Index to NULL pkg element Idx=%p", | 223 | "Attempt to dereference an Index to NULL package element Idx=%p", |
232 | stack_desc)); | 224 | stack_desc)); |
233 | status = AE_AML_UNINITIALIZED_ELEMENT; | 225 | status = AE_AML_UNINITIALIZED_ELEMENT; |
234 | } | 226 | } |
@@ -239,7 +231,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, | |||
239 | /* Invalid reference object */ | 231 | /* Invalid reference object */ |
240 | 232 | ||
241 | ACPI_ERROR((AE_INFO, | 233 | ACPI_ERROR((AE_INFO, |
242 | "Unknown TargetType %X in Index/Reference obj %p", | 234 | "Unknown TargetType %X in Index/Reference object %p", |
243 | stack_desc->reference.target_type, | 235 | stack_desc->reference.target_type, |
244 | stack_desc)); | 236 | stack_desc)); |
245 | status = AE_AML_INTERNAL; | 237 | status = AE_AML_INTERNAL; |
@@ -251,7 +243,7 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, | |||
251 | case AML_DEBUG_OP: | 243 | case AML_DEBUG_OP: |
252 | case AML_LOAD_OP: | 244 | case AML_LOAD_OP: |
253 | 245 | ||
254 | /* Just leave the object as-is */ | 246 | /* Just leave the object as-is, do not dereference */ |
255 | 247 | ||
256 | break; | 248 | break; |
257 | 249 | ||
@@ -390,10 +382,10 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, | |||
390 | } | 382 | } |
391 | 383 | ||
392 | /* | 384 | /* |
393 | * For reference objects created via the ref_of or Index operators, | 385 | * For reference objects created via the ref_of, Index, or Load/load_table |
394 | * we need to get to the base object (as per the ACPI specification | 386 | * operators, we need to get to the base object (as per the ACPI |
395 | * of the object_type and size_of operators). This means traversing | 387 | * specification of the object_type and size_of operators). This means |
396 | * the list of possibly many nested references. | 388 | * traversing the list of possibly many nested references. |
397 | */ | 389 | */ |
398 | while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { | 390 | while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) { |
399 | switch (obj_desc->reference.opcode) { | 391 | switch (obj_desc->reference.opcode) { |
@@ -463,6 +455,11 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, | |||
463 | } | 455 | } |
464 | break; | 456 | break; |
465 | 457 | ||
458 | case AML_LOAD_OP: | ||
459 | |||
460 | type = ACPI_TYPE_DDB_HANDLE; | ||
461 | goto exit; | ||
462 | |||
466 | case AML_LOCAL_OP: | 463 | case AML_LOCAL_OP: |
467 | case AML_ARG_OP: | 464 | case AML_ARG_OP: |
468 | 465 | ||
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c index 09d897b3f6d5..73e29e566a70 100644 --- a/drivers/acpi/executer/exresop.c +++ b/drivers/acpi/executer/exresop.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -137,7 +137,6 @@ acpi_ex_resolve_operands(u16 opcode, | |||
137 | union acpi_operand_object *obj_desc; | 137 | union acpi_operand_object *obj_desc; |
138 | acpi_status status = AE_OK; | 138 | acpi_status status = AE_OK; |
139 | u8 object_type; | 139 | u8 object_type; |
140 | void *temp_node; | ||
141 | u32 arg_types; | 140 | u32 arg_types; |
142 | const struct acpi_opcode_info *op_info; | 141 | const struct acpi_opcode_info *op_info; |
143 | u32 this_arg_type; | 142 | u32 this_arg_type; |
@@ -239,7 +238,6 @@ acpi_ex_resolve_operands(u16 opcode, | |||
239 | 238 | ||
240 | /*lint -fallthrough */ | 239 | /*lint -fallthrough */ |
241 | 240 | ||
242 | case AML_NAME_OP: | ||
243 | case AML_INDEX_OP: | 241 | case AML_INDEX_OP: |
244 | case AML_REF_OF_OP: | 242 | case AML_REF_OF_OP: |
245 | case AML_ARG_OP: | 243 | case AML_ARG_OP: |
@@ -332,15 +330,6 @@ acpi_ex_resolve_operands(u16 opcode, | |||
332 | if (ACPI_FAILURE(status)) { | 330 | if (ACPI_FAILURE(status)) { |
333 | return_ACPI_STATUS(status); | 331 | return_ACPI_STATUS(status); |
334 | } | 332 | } |
335 | |||
336 | if (obj_desc->reference.opcode == AML_NAME_OP) { | ||
337 | |||
338 | /* Convert a named reference to the actual named object */ | ||
339 | |||
340 | temp_node = obj_desc->reference.object; | ||
341 | acpi_ut_remove_reference(obj_desc); | ||
342 | (*stack_ptr) = temp_node; | ||
343 | } | ||
344 | goto next_operand; | 333 | goto next_operand; |
345 | 334 | ||
346 | case ARGI_DATAREFOBJ: /* Store operator only */ | 335 | case ARGI_DATAREFOBJ: /* Store operator only */ |
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c index f4b69a637820..76c875bc3154 100644 --- a/drivers/acpi/executer/exstore.c +++ b/drivers/acpi/executer/exstore.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -84,8 +84,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, | |||
84 | 84 | ||
85 | ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); | 85 | ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); |
86 | 86 | ||
87 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", | 87 | /* Print line header as long as we are not in the middle of an object display */ |
88 | level, " ")); | 88 | |
89 | if (!((level > 0) && index == 0)) { | ||
90 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", | ||
91 | level, " ")); | ||
92 | } | ||
89 | 93 | ||
90 | /* Display index for package output only */ | 94 | /* Display index for package output only */ |
91 | 95 | ||
@@ -95,12 +99,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, | |||
95 | } | 99 | } |
96 | 100 | ||
97 | if (!source_desc) { | 101 | if (!source_desc) { |
98 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "<Null Object>\n")); | 102 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n")); |
99 | return_VOID; | 103 | return_VOID; |
100 | } | 104 | } |
101 | 105 | ||
102 | if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { | 106 | if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { |
103 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: ", | 107 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ", |
104 | acpi_ut_get_object_type_name | 108 | acpi_ut_get_object_type_name |
105 | (source_desc))); | 109 | (source_desc))); |
106 | 110 | ||
@@ -123,6 +127,8 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, | |||
123 | return_VOID; | 127 | return_VOID; |
124 | } | 128 | } |
125 | 129 | ||
130 | /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ | ||
131 | |||
126 | switch (ACPI_GET_OBJECT_TYPE(source_desc)) { | 132 | switch (ACPI_GET_OBJECT_TYPE(source_desc)) { |
127 | case ACPI_TYPE_INTEGER: | 133 | case ACPI_TYPE_INTEGER: |
128 | 134 | ||
@@ -147,7 +153,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, | |||
147 | (u32) source_desc->buffer.length)); | 153 | (u32) source_desc->buffer.length)); |
148 | ACPI_DUMP_BUFFER(source_desc->buffer.pointer, | 154 | ACPI_DUMP_BUFFER(source_desc->buffer.pointer, |
149 | (source_desc->buffer.length < | 155 | (source_desc->buffer.length < |
150 | 32) ? source_desc->buffer.length : 32); | 156 | 256) ? source_desc->buffer.length : 256); |
151 | break; | 157 | break; |
152 | 158 | ||
153 | case ACPI_TYPE_STRING: | 159 | case ACPI_TYPE_STRING: |
@@ -160,7 +166,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, | |||
160 | case ACPI_TYPE_PACKAGE: | 166 | case ACPI_TYPE_PACKAGE: |
161 | 167 | ||
162 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, | 168 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, |
163 | "[0x%.2X Elements]\n", | 169 | "[Contains 0x%.2X Elements]\n", |
164 | source_desc->package.count)); | 170 | source_desc->package.count)); |
165 | 171 | ||
166 | /* Output the entire contents of the package */ | 172 | /* Output the entire contents of the package */ |
@@ -180,12 +186,59 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, | |||
180 | (source_desc->reference.opcode), | 186 | (source_desc->reference.opcode), |
181 | source_desc->reference.offset)); | 187 | source_desc->reference.offset)); |
182 | } else { | 188 | } else { |
183 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]\n", | 189 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]", |
184 | acpi_ps_get_opcode_name | 190 | acpi_ps_get_opcode_name |
185 | (source_desc->reference.opcode))); | 191 | (source_desc->reference.opcode))); |
186 | } | 192 | } |
187 | 193 | ||
188 | if (source_desc->reference.object) { | 194 | if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */ |
195 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, | ||
196 | " Table OwnerId %p\n", | ||
197 | source_desc->reference.object)); | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " ")); | ||
202 | |||
203 | /* Check for valid node first, then valid object */ | ||
204 | |||
205 | if (source_desc->reference.node) { | ||
206 | if (ACPI_GET_DESCRIPTOR_TYPE | ||
207 | (source_desc->reference.node) != | ||
208 | ACPI_DESC_TYPE_NAMED) { | ||
209 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, | ||
210 | " %p - Not a valid namespace node\n", | ||
211 | source_desc->reference. | ||
212 | node)); | ||
213 | } else { | ||
214 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, | ||
215 | "Node %p [%4.4s] ", | ||
216 | source_desc->reference. | ||
217 | node, | ||
218 | (source_desc->reference. | ||
219 | node)->name.ascii)); | ||
220 | |||
221 | switch ((source_desc->reference.node)->type) { | ||
222 | |||
223 | /* These types have no attached object */ | ||
224 | |||
225 | case ACPI_TYPE_DEVICE: | ||
226 | acpi_os_printf("Device\n"); | ||
227 | break; | ||
228 | |||
229 | case ACPI_TYPE_THERMAL: | ||
230 | acpi_os_printf("Thermal Zone\n"); | ||
231 | break; | ||
232 | |||
233 | default: | ||
234 | acpi_ex_do_debug_object((source_desc-> | ||
235 | reference. | ||
236 | node)->object, | ||
237 | level + 4, 0); | ||
238 | break; | ||
239 | } | ||
240 | } | ||
241 | } else if (source_desc->reference.object) { | ||
189 | if (ACPI_GET_DESCRIPTOR_TYPE | 242 | if (ACPI_GET_DESCRIPTOR_TYPE |
190 | (source_desc->reference.object) == | 243 | (source_desc->reference.object) == |
191 | ACPI_DESC_TYPE_NAMED) { | 244 | ACPI_DESC_TYPE_NAMED) { |
@@ -198,18 +251,13 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, | |||
198 | acpi_ex_do_debug_object(source_desc->reference. | 251 | acpi_ex_do_debug_object(source_desc->reference. |
199 | object, level + 4, 0); | 252 | object, level + 4, 0); |
200 | } | 253 | } |
201 | } else if (source_desc->reference.node) { | ||
202 | acpi_ex_do_debug_object((source_desc->reference.node)-> | ||
203 | object, level + 4, 0); | ||
204 | } | 254 | } |
205 | break; | 255 | break; |
206 | 256 | ||
207 | default: | 257 | default: |
208 | 258 | ||
209 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p %s\n", | 259 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n", |
210 | source_desc, | 260 | source_desc)); |
211 | acpi_ut_get_object_type_name | ||
212 | (source_desc))); | ||
213 | break; | 261 | break; |
214 | } | 262 | } |
215 | 263 | ||
@@ -313,7 +361,6 @@ acpi_ex_store(union acpi_operand_object *source_desc, | |||
313 | * 4) Store to the debug object | 361 | * 4) Store to the debug object |
314 | */ | 362 | */ |
315 | switch (ref_desc->reference.opcode) { | 363 | switch (ref_desc->reference.opcode) { |
316 | case AML_NAME_OP: | ||
317 | case AML_REF_OF_OP: | 364 | case AML_REF_OF_OP: |
318 | 365 | ||
319 | /* Storing an object into a Name "container" */ | 366 | /* Storing an object into a Name "container" */ |
@@ -415,11 +462,24 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, | |||
415 | */ | 462 | */ |
416 | obj_desc = *(index_desc->reference.where); | 463 | obj_desc = *(index_desc->reference.where); |
417 | 464 | ||
418 | status = | 465 | if (ACPI_GET_OBJECT_TYPE(source_desc) == |
419 | acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, | 466 | ACPI_TYPE_LOCAL_REFERENCE |
420 | walk_state); | 467 | && source_desc->reference.opcode == AML_LOAD_OP) { |
421 | if (ACPI_FAILURE(status)) { | 468 | |
422 | return_ACPI_STATUS(status); | 469 | /* This is a DDBHandle, just add a reference to it */ |
470 | |||
471 | acpi_ut_add_reference(source_desc); | ||
472 | new_desc = source_desc; | ||
473 | } else { | ||
474 | /* Normal object, copy it */ | ||
475 | |||
476 | status = | ||
477 | acpi_ut_copy_iobject_to_iobject(source_desc, | ||
478 | &new_desc, | ||
479 | walk_state); | ||
480 | if (ACPI_FAILURE(status)) { | ||
481 | return_ACPI_STATUS(status); | ||
482 | } | ||
423 | } | 483 | } |
424 | 484 | ||
425 | if (obj_desc) { | 485 | if (obj_desc) { |
@@ -571,10 +631,17 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, | |||
571 | 631 | ||
572 | /* If no implicit conversion, drop into the default case below */ | 632 | /* If no implicit conversion, drop into the default case below */ |
573 | 633 | ||
574 | if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) { | 634 | if ((!implicit_conversion) || |
575 | 635 | ((walk_state->opcode == AML_COPY_OP) && | |
576 | /* Force execution of default (no implicit conversion) */ | 636 | (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && |
577 | 637 | (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && | |
638 | (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { | ||
639 | /* | ||
640 | * Force execution of default (no implicit conversion). Note: | ||
641 | * copy_object does not perform an implicit conversion, as per the ACPI | ||
642 | * spec -- except in case of region/bank/index fields -- because these | ||
643 | * objects must retain their original type permanently. | ||
644 | */ | ||
578 | target_type = ACPI_TYPE_ANY; | 645 | target_type = ACPI_TYPE_ANY; |
579 | } | 646 | } |
580 | 647 | ||
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c index 1d622c625c64..a6d2168b81f9 100644 --- a/drivers/acpi/executer/exstoren.c +++ b/drivers/acpi/executer/exstoren.c | |||
@@ -7,7 +7,7 @@ | |||
7 | *****************************************************************************/ | 7 | *****************************************************************************/ |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * Copyright (C) 2000 - 2007, R. Byron Moore | 10 | * Copyright (C) 2000 - 2008, Intel Corp. |
11 | * All rights reserved. | 11 | * All rights reserved. |
12 | * | 12 | * |
13 | * Redistribution and use in source and binary forms, with or without | 13 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c index 8233d40178ee..9a75ff09fb0c 100644 --- a/drivers/acpi/executer/exstorob.c +++ b/drivers/acpi/executer/exstorob.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c index 9460baff3032..68990f1df371 100644 --- a/drivers/acpi/executer/exsystem.c +++ b/drivers/acpi/executer/exsystem.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -44,7 +44,6 @@ | |||
44 | 44 | ||
45 | #include <acpi/acpi.h> | 45 | #include <acpi/acpi.h> |
46 | #include <acpi/acinterp.h> | 46 | #include <acpi/acinterp.h> |
47 | #include <acpi/acevents.h> | ||
48 | 47 | ||
49 | #define _COMPONENT ACPI_EXECUTER | 48 | #define _COMPONENT ACPI_EXECUTER |
50 | ACPI_MODULE_NAME("exsystem") | 49 | ACPI_MODULE_NAME("exsystem") |
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c index 6b0aeccbb69b..86c03880b523 100644 --- a/drivers/acpi/executer/exutils.c +++ b/drivers/acpi/executer/exutils.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -61,7 +61,6 @@ | |||
61 | #include <acpi/acpi.h> | 61 | #include <acpi/acpi.h> |
62 | #include <acpi/acinterp.h> | 62 | #include <acpi/acinterp.h> |
63 | #include <acpi/amlcode.h> | 63 | #include <acpi/amlcode.h> |
64 | #include <acpi/acevents.h> | ||
65 | 64 | ||
66 | #define _COMPONENT ACPI_EXECUTER | 65 | #define _COMPONENT ACPI_EXECUTER |
67 | ACPI_MODULE_NAME("exutils") | 66 | ACPI_MODULE_NAME("exutils") |
@@ -217,9 +216,10 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) | |||
217 | 216 | ||
218 | /* | 217 | /* |
219 | * Object must be a valid number and we must be executing | 218 | * Object must be a valid number and we must be executing |
220 | * a control method | 219 | * a control method. NS node could be there for AML_INT_NAMEPATH_OP. |
221 | */ | 220 | */ |
222 | if ((!obj_desc) || | 221 | if ((!obj_desc) || |
222 | (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) || | ||
223 | (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { | 223 | (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { |
224 | return; | 224 | return; |
225 | } | 225 | } |
@@ -240,72 +240,73 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) | |||
240 | * PARAMETERS: field_flags - Flags with Lock rule: | 240 | * PARAMETERS: field_flags - Flags with Lock rule: |
241 | * always_lock or never_lock | 241 | * always_lock or never_lock |
242 | * | 242 | * |
243 | * RETURN: TRUE/FALSE indicating whether the lock was actually acquired | 243 | * RETURN: None |
244 | * | 244 | * |
245 | * DESCRIPTION: Obtain the global lock and keep track of this fact via two | 245 | * DESCRIPTION: Obtain the ACPI hardware Global Lock, only if the field |
246 | * methods. A global variable keeps the state of the lock, and | 246 | * flags specifiy that it is to be obtained before field access. |
247 | * the state is returned to the caller. | ||
248 | * | 247 | * |
249 | ******************************************************************************/ | 248 | ******************************************************************************/ |
250 | 249 | ||
251 | u8 acpi_ex_acquire_global_lock(u32 field_flags) | 250 | void acpi_ex_acquire_global_lock(u32 field_flags) |
252 | { | 251 | { |
253 | u8 locked = FALSE; | ||
254 | acpi_status status; | 252 | acpi_status status; |
255 | 253 | ||
256 | ACPI_FUNCTION_TRACE(ex_acquire_global_lock); | 254 | ACPI_FUNCTION_TRACE(ex_acquire_global_lock); |
257 | 255 | ||
258 | /* Only attempt lock if the always_lock bit is set */ | 256 | /* Only use the lock if the always_lock bit is set */ |
257 | |||
258 | if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { | ||
259 | return_VOID; | ||
260 | } | ||
259 | 261 | ||
260 | if (field_flags & AML_FIELD_LOCK_RULE_MASK) { | 262 | /* Attempt to get the global lock, wait forever */ |
261 | 263 | ||
262 | /* We should attempt to get the lock, wait forever */ | 264 | status = acpi_ex_acquire_mutex_object(ACPI_WAIT_FOREVER, |
265 | acpi_gbl_global_lock_mutex, | ||
266 | acpi_os_get_thread_id()); | ||
263 | 267 | ||
264 | status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER); | 268 | if (ACPI_FAILURE(status)) { |
265 | if (ACPI_SUCCESS(status)) { | 269 | ACPI_EXCEPTION((AE_INFO, status, |
266 | locked = TRUE; | 270 | "Could not acquire Global Lock")); |
267 | } else { | ||
268 | ACPI_EXCEPTION((AE_INFO, status, | ||
269 | "Could not acquire Global Lock")); | ||
270 | } | ||
271 | } | 271 | } |
272 | 272 | ||
273 | return_UINT8(locked); | 273 | return_VOID; |
274 | } | 274 | } |
275 | 275 | ||
276 | /******************************************************************************* | 276 | /******************************************************************************* |
277 | * | 277 | * |
278 | * FUNCTION: acpi_ex_release_global_lock | 278 | * FUNCTION: acpi_ex_release_global_lock |
279 | * | 279 | * |
280 | * PARAMETERS: locked_by_me - Return value from corresponding call to | 280 | * PARAMETERS: field_flags - Flags with Lock rule: |
281 | * acquire_global_lock. | 281 | * always_lock or never_lock |
282 | * | 282 | * |
283 | * RETURN: None | 283 | * RETURN: None |
284 | * | 284 | * |
285 | * DESCRIPTION: Release the global lock if it is locked. | 285 | * DESCRIPTION: Release the ACPI hardware Global Lock |
286 | * | 286 | * |
287 | ******************************************************************************/ | 287 | ******************************************************************************/ |
288 | 288 | ||
289 | void acpi_ex_release_global_lock(u8 locked_by_me) | 289 | void acpi_ex_release_global_lock(u32 field_flags) |
290 | { | 290 | { |
291 | acpi_status status; | 291 | acpi_status status; |
292 | 292 | ||
293 | ACPI_FUNCTION_TRACE(ex_release_global_lock); | 293 | ACPI_FUNCTION_TRACE(ex_release_global_lock); |
294 | 294 | ||
295 | /* Only attempt unlock if the caller locked it */ | 295 | /* Only use the lock if the always_lock bit is set */ |
296 | 296 | ||
297 | if (locked_by_me) { | 297 | if (!(field_flags & AML_FIELD_LOCK_RULE_MASK)) { |
298 | return_VOID; | ||
299 | } | ||
298 | 300 | ||
299 | /* OK, now release the lock */ | 301 | /* Release the global lock */ |
300 | 302 | ||
301 | status = acpi_ev_release_global_lock(); | 303 | status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex); |
302 | if (ACPI_FAILURE(status)) { | 304 | if (ACPI_FAILURE(status)) { |
303 | 305 | ||
304 | /* Report the error, but there isn't much else we can do */ | 306 | /* Report the error, but there isn't much else we can do */ |
305 | 307 | ||
306 | ACPI_EXCEPTION((AE_INFO, status, | 308 | ACPI_EXCEPTION((AE_INFO, status, |
307 | "Could not release ACPI Global Lock")); | 309 | "Could not release Global Lock")); |
308 | } | ||
309 | } | 310 | } |
310 | 311 | ||
311 | return_VOID; | 312 | return_VOID; |
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 194077ab9b85..6cf10cbc1eee 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c | |||
@@ -256,24 +256,23 @@ static int acpi_fan_add(struct acpi_device *device) | |||
256 | result = PTR_ERR(cdev); | 256 | result = PTR_ERR(cdev); |
257 | goto end; | 257 | goto end; |
258 | } | 258 | } |
259 | if (cdev) { | 259 | |
260 | printk(KERN_INFO PREFIX | 260 | printk(KERN_INFO PREFIX |
261 | "%s is registered as cooling_device%d\n", | 261 | "%s is registered as cooling_device%d\n", |
262 | device->dev.bus_id, cdev->id); | 262 | device->dev.bus_id, cdev->id); |
263 | 263 | ||
264 | acpi_driver_data(device) = cdev; | 264 | acpi_driver_data(device) = cdev; |
265 | result = sysfs_create_link(&device->dev.kobj, | 265 | result = sysfs_create_link(&device->dev.kobj, |
266 | &cdev->device.kobj, | 266 | &cdev->device.kobj, |
267 | "thermal_cooling"); | 267 | "thermal_cooling"); |
268 | if (result) | 268 | if (result) |
269 | return result; | 269 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
270 | 270 | ||
271 | result = sysfs_create_link(&cdev->device.kobj, | 271 | result = sysfs_create_link(&cdev->device.kobj, |
272 | &device->dev.kobj, | 272 | &device->dev.kobj, |
273 | "device"); | 273 | "device"); |
274 | if (result) | 274 | if (result) |
275 | return result; | 275 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
276 | } | ||
277 | 276 | ||
278 | result = acpi_fan_add_fs(device); | 277 | result = acpi_fan_add_fs(device); |
279 | if (result) | 278 | if (result) |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index eda0978b57c6..06f8634fe58b 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -142,6 +142,7 @@ EXPORT_SYMBOL(acpi_get_physical_device); | |||
142 | 142 | ||
143 | static int acpi_bind_one(struct device *dev, acpi_handle handle) | 143 | static int acpi_bind_one(struct device *dev, acpi_handle handle) |
144 | { | 144 | { |
145 | struct acpi_device *acpi_dev; | ||
145 | acpi_status status; | 146 | acpi_status status; |
146 | 147 | ||
147 | if (dev->archdata.acpi_handle) { | 148 | if (dev->archdata.acpi_handle) { |
@@ -157,6 +158,16 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) | |||
157 | } | 158 | } |
158 | dev->archdata.acpi_handle = handle; | 159 | dev->archdata.acpi_handle = handle; |
159 | 160 | ||
161 | status = acpi_bus_get_device(handle, &acpi_dev); | ||
162 | if (!ACPI_FAILURE(status)) { | ||
163 | int ret; | ||
164 | |||
165 | ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj, | ||
166 | "firmware_node"); | ||
167 | ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj, | ||
168 | "physical_node"); | ||
169 | } | ||
170 | |||
160 | return 0; | 171 | return 0; |
161 | } | 172 | } |
162 | 173 | ||
@@ -165,8 +176,17 @@ static int acpi_unbind_one(struct device *dev) | |||
165 | if (!dev->archdata.acpi_handle) | 176 | if (!dev->archdata.acpi_handle) |
166 | return 0; | 177 | return 0; |
167 | if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { | 178 | if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { |
179 | struct acpi_device *acpi_dev; | ||
180 | |||
168 | /* acpi_get_physical_device increase refcnt by one */ | 181 | /* acpi_get_physical_device increase refcnt by one */ |
169 | put_device(dev); | 182 | put_device(dev); |
183 | |||
184 | if (!acpi_bus_get_device(dev->archdata.acpi_handle, | ||
185 | &acpi_dev)) { | ||
186 | sysfs_remove_link(&dev->kobj, "firmware_node"); | ||
187 | sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node"); | ||
188 | } | ||
189 | |||
170 | acpi_detach_data(dev->archdata.acpi_handle, | 190 | acpi_detach_data(dev->archdata.acpi_handle, |
171 | acpi_glue_data_handler); | 191 | acpi_glue_data_handler); |
172 | dev->archdata.acpi_handle = NULL; | 192 | dev->archdata.acpi_handle = NULL; |
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c index 6031ca13dd2f..816894ea839e 100644 --- a/drivers/acpi/hardware/hwacpi.c +++ b/drivers/acpi/hardware/hwacpi.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c index 117a05cadaaa..14bc4f456ae8 100644 --- a/drivers/acpi/hardware/hwgpe.c +++ b/drivers/acpi/hardware/hwgpe.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c index 73f9c5fb1ba7..ddf792adcf96 100644 --- a/drivers/acpi/hardware/hwregs.c +++ b/drivers/acpi/hardware/hwregs.c | |||
@@ -7,7 +7,7 @@ | |||
7 | ******************************************************************************/ | 7 | ******************************************************************************/ |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * Copyright (C) 2000 - 2007, R. Byron Moore | 10 | * Copyright (C) 2000 - 2008, Intel Corp. |
11 | * All rights reserved. | 11 | * All rights reserved. |
12 | * | 12 | * |
13 | * Redistribution and use in source and binary forms, with or without | 13 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c index 4290e0193097..d9937e05ec6a 100644 --- a/drivers/acpi/hardware/hwsleep.c +++ b/drivers/acpi/hardware/hwsleep.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -70,9 +70,10 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address) | |||
70 | 70 | ||
71 | /* Get the FACS */ | 71 | /* Get the FACS */ |
72 | 72 | ||
73 | status = | 73 | status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, |
74 | acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, | 74 | ACPI_CAST_INDIRECT_PTR(struct |
75 | (struct acpi_table_header **)&facs); | 75 | acpi_table_header, |
76 | &facs)); | ||
76 | if (ACPI_FAILURE(status)) { | 77 | if (ACPI_FAILURE(status)) { |
77 | return_ACPI_STATUS(status); | 78 | return_ACPI_STATUS(status); |
78 | } | 79 | } |
@@ -124,9 +125,10 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) | |||
124 | 125 | ||
125 | /* Get the FACS */ | 126 | /* Get the FACS */ |
126 | 127 | ||
127 | status = | 128 | status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, |
128 | acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS, | 129 | ACPI_CAST_INDIRECT_PTR(struct |
129 | (struct acpi_table_header **)&facs); | 130 | acpi_table_header, |
131 | &facs)); | ||
130 | if (ACPI_FAILURE(status)) { | 132 | if (ACPI_FAILURE(status)) { |
131 | return_ACPI_STATUS(status); | 133 | return_ACPI_STATUS(status); |
132 | } | 134 | } |
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c index c32eab696acd..b53d575491b9 100644 --- a/drivers/acpi/hardware/hwtimer.c +++ b/drivers/acpi/hardware/hwtimer.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c index 57faf598bad8..c39a7f68b889 100644 --- a/drivers/acpi/namespace/nsaccess.c +++ b/drivers/acpi/namespace/nsaccess.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -208,8 +208,7 @@ acpi_status acpi_ns_root_initialize(void) | |||
208 | /* Special case for ACPI Global Lock */ | 208 | /* Special case for ACPI Global Lock */ |
209 | 209 | ||
210 | if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { | 210 | if (ACPI_STRCMP(init_val->name, "_GL_") == 0) { |
211 | acpi_gbl_global_lock_mutex = | 211 | acpi_gbl_global_lock_mutex = obj_desc; |
212 | obj_desc->mutex.os_mutex; | ||
213 | 212 | ||
214 | /* Create additional counting semaphore for global lock */ | 213 | /* Create additional counting semaphore for global lock */ |
215 | 214 | ||
@@ -582,44 +581,68 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, | |||
582 | return_ACPI_STATUS(status); | 581 | return_ACPI_STATUS(status); |
583 | } | 582 | } |
584 | 583 | ||
585 | /* | 584 | /* More segments to follow? */ |
586 | * Sanity typecheck of the target object: | 585 | |
587 | * | 586 | if (num_segments > 0) { |
588 | * If 1) This is the last segment (num_segments == 0) | 587 | /* |
589 | * 2) And we are looking for a specific type | 588 | * If we have an alias to an object that opens a scope (such as a |
590 | * (Not checking for TYPE_ANY) | 589 | * device or processor), we need to dereference the alias here so that |
591 | * 3) Which is not an alias | 590 | * we can access any children of the original node (via the remaining |
592 | * 4) Which is not a local type (TYPE_SCOPE) | 591 | * segments). |
593 | * 5) And the type of target object is known (not TYPE_ANY) | 592 | */ |
594 | * 6) And target object does not match what we are looking for | 593 | if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) { |
595 | * | 594 | if (acpi_ns_opens_scope |
596 | * Then we have a type mismatch. Just warn and ignore it. | 595 | (((struct acpi_namespace_node *)this_node-> |
597 | */ | 596 | object)->type)) { |
598 | if ((num_segments == 0) && | 597 | this_node = |
599 | (type_to_check_for != ACPI_TYPE_ANY) && | 598 | (struct acpi_namespace_node *) |
600 | (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && | 599 | this_node->object; |
601 | (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) && | 600 | } |
602 | (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) && | 601 | } |
603 | (this_node->type != ACPI_TYPE_ANY) && | ||
604 | (this_node->type != type_to_check_for)) { | ||
605 | |||
606 | /* Complain about a type mismatch */ | ||
607 | |||
608 | ACPI_WARNING((AE_INFO, | ||
609 | "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", | ||
610 | ACPI_CAST_PTR(char, &simple_name), | ||
611 | acpi_ut_get_type_name(this_node->type), | ||
612 | acpi_ut_get_type_name | ||
613 | (type_to_check_for))); | ||
614 | } | 602 | } |
615 | 603 | ||
616 | /* | 604 | /* Special handling for the last segment (num_segments == 0) */ |
617 | * If this is the last name segment and we are not looking for a | 605 | |
618 | * specific type, but the type of found object is known, use that type | 606 | else { |
619 | * to see if it opens a scope. | 607 | /* |
620 | */ | 608 | * Sanity typecheck of the target object: |
621 | if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) { | 609 | * |
622 | type = this_node->type; | 610 | * If 1) This is the last segment (num_segments == 0) |
611 | * 2) And we are looking for a specific type | ||
612 | * (Not checking for TYPE_ANY) | ||
613 | * 3) Which is not an alias | ||
614 | * 4) Which is not a local type (TYPE_SCOPE) | ||
615 | * 5) And the type of target object is known (not TYPE_ANY) | ||
616 | * 6) And target object does not match what we are looking for | ||
617 | * | ||
618 | * Then we have a type mismatch. Just warn and ignore it. | ||
619 | */ | ||
620 | if ((type_to_check_for != ACPI_TYPE_ANY) && | ||
621 | (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && | ||
622 | (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) | ||
623 | && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) | ||
624 | && (this_node->type != ACPI_TYPE_ANY) | ||
625 | && (this_node->type != type_to_check_for)) { | ||
626 | |||
627 | /* Complain about a type mismatch */ | ||
628 | |||
629 | ACPI_WARNING((AE_INFO, | ||
630 | "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", | ||
631 | ACPI_CAST_PTR(char, &simple_name), | ||
632 | acpi_ut_get_type_name(this_node-> | ||
633 | type), | ||
634 | acpi_ut_get_type_name | ||
635 | (type_to_check_for))); | ||
636 | } | ||
637 | |||
638 | /* | ||
639 | * If this is the last name segment and we are not looking for a | ||
640 | * specific type, but the type of found object is known, use that type | ||
641 | * to (later) see if it opens a scope. | ||
642 | */ | ||
643 | if (type == ACPI_TYPE_ANY) { | ||
644 | type = this_node->type; | ||
645 | } | ||
623 | } | 646 | } |
624 | 647 | ||
625 | /* Point to next name segment and make this node current */ | 648 | /* Point to next name segment and make this node current */ |
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c index 1d693d8ad2d8..3a1740ac2edc 100644 --- a/drivers/acpi/namespace/nsalloc.c +++ b/drivers/acpi/namespace/nsalloc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c index 1fc4f86676e1..5445751b8a3e 100644 --- a/drivers/acpi/namespace/nsdump.c +++ b/drivers/acpi/namespace/nsdump.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -249,7 +249,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, | |||
249 | acpi_os_printf("ID %X Len %.4X Addr %p\n", | 249 | acpi_os_printf("ID %X Len %.4X Addr %p\n", |
250 | obj_desc->processor.proc_id, | 250 | obj_desc->processor.proc_id, |
251 | obj_desc->processor.length, | 251 | obj_desc->processor.length, |
252 | (char *)obj_desc->processor.address); | 252 | ACPI_CAST_PTR(void, |
253 | obj_desc->processor. | ||
254 | address)); | ||
253 | break; | 255 | break; |
254 | 256 | ||
255 | case ACPI_TYPE_DEVICE: | 257 | case ACPI_TYPE_DEVICE: |
@@ -320,9 +322,8 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, | |||
320 | space_id)); | 322 | space_id)); |
321 | if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { | 323 | if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { |
322 | acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n", | 324 | acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n", |
323 | ACPI_FORMAT_UINT64(obj_desc-> | 325 | ACPI_FORMAT_NATIVE_UINT |
324 | region. | 326 | (obj_desc->region.address), |
325 | address), | ||
326 | obj_desc->region.length); | 327 | obj_desc->region.length); |
327 | } else { | 328 | } else { |
328 | acpi_os_printf | 329 | acpi_os_printf |
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c index 5097e167939e..428f50fde11a 100644 --- a/drivers/acpi/namespace/nsdumpdv.c +++ b/drivers/acpi/namespace/nsdumpdv.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c index 97b2ac57c16b..14bdfa92bea0 100644 --- a/drivers/acpi/namespace/nseval.c +++ b/drivers/acpi/namespace/nseval.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c index 33db2241044e..6d6d930c8e18 100644 --- a/drivers/acpi/namespace/nsinit.c +++ b/drivers/acpi/namespace/nsinit.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -244,6 +244,10 @@ acpi_ns_init_one_object(acpi_handle obj_handle, | |||
244 | info->field_count++; | 244 | info->field_count++; |
245 | break; | 245 | break; |
246 | 246 | ||
247 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
248 | info->field_count++; | ||
249 | break; | ||
250 | |||
247 | case ACPI_TYPE_BUFFER: | 251 | case ACPI_TYPE_BUFFER: |
248 | info->buffer_count++; | 252 | info->buffer_count++; |
249 | break; | 253 | break; |
@@ -287,6 +291,12 @@ acpi_ns_init_one_object(acpi_handle obj_handle, | |||
287 | status = acpi_ds_get_buffer_field_arguments(obj_desc); | 291 | status = acpi_ds_get_buffer_field_arguments(obj_desc); |
288 | break; | 292 | break; |
289 | 293 | ||
294 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
295 | |||
296 | info->field_init++; | ||
297 | status = acpi_ds_get_bank_field_arguments(obj_desc); | ||
298 | break; | ||
299 | |||
290 | case ACPI_TYPE_BUFFER: | 300 | case ACPI_TYPE_BUFFER: |
291 | 301 | ||
292 | info->buffer_init++; | 302 | info->buffer_init++; |
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c index d4f9654fd20f..2c92f6cf5ce1 100644 --- a/drivers/acpi/namespace/nsload.c +++ b/drivers/acpi/namespace/nsload.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -107,11 +107,11 @@ acpi_ns_load_table(acpi_native_uint table_index, | |||
107 | goto unlock; | 107 | goto unlock; |
108 | } | 108 | } |
109 | 109 | ||
110 | status = acpi_ns_parse_table(table_index, node->child); | 110 | status = acpi_ns_parse_table(table_index, node); |
111 | if (ACPI_SUCCESS(status)) { | 111 | if (ACPI_SUCCESS(status)) { |
112 | acpi_tb_set_table_loaded_flag(table_index, TRUE); | 112 | acpi_tb_set_table_loaded_flag(table_index, TRUE); |
113 | } else { | 113 | } else { |
114 | acpi_tb_release_owner_id(table_index); | 114 | (void)acpi_tb_release_owner_id(table_index); |
115 | } | 115 | } |
116 | 116 | ||
117 | unlock: | 117 | unlock: |
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c index cbd94af08cc5..cffef1bcbdbc 100644 --- a/drivers/acpi/namespace/nsnames.c +++ b/drivers/acpi/namespace/nsnames.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -180,6 +180,12 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) | |||
180 | next_node = node; | 180 | next_node = node; |
181 | 181 | ||
182 | while (next_node && (next_node != acpi_gbl_root_node)) { | 182 | while (next_node && (next_node != acpi_gbl_root_node)) { |
183 | if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { | ||
184 | ACPI_ERROR((AE_INFO, | ||
185 | "Invalid NS Node (%p) while traversing path", | ||
186 | next_node)); | ||
187 | return 0; | ||
188 | } | ||
183 | size += ACPI_PATH_SEGMENT_LENGTH; | 189 | size += ACPI_PATH_SEGMENT_LENGTH; |
184 | next_node = acpi_ns_get_parent_node(next_node); | 190 | next_node = acpi_ns_get_parent_node(next_node); |
185 | } | 191 | } |
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c index d9d7377bc6e6..15fe09e24f71 100644 --- a/drivers/acpi/namespace/nsobject.c +++ b/drivers/acpi/namespace/nsobject.c | |||
@@ -6,7 +6,7 @@ | |||
6 | ******************************************************************************/ | 6 | ******************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c index e696aa847990..46a79b0103b6 100644 --- a/drivers/acpi/namespace/nsparse.c +++ b/drivers/acpi/namespace/nsparse.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -64,7 +64,8 @@ ACPI_MODULE_NAME("nsparse") | |||
64 | ******************************************************************************/ | 64 | ******************************************************************************/ |
65 | acpi_status | 65 | acpi_status |
66 | acpi_ns_one_complete_parse(acpi_native_uint pass_number, | 66 | acpi_ns_one_complete_parse(acpi_native_uint pass_number, |
67 | acpi_native_uint table_index) | 67 | acpi_native_uint table_index, |
68 | struct acpi_namespace_node * start_node) | ||
68 | { | 69 | { |
69 | union acpi_parse_object *parse_root; | 70 | union acpi_parse_object *parse_root; |
70 | acpi_status status; | 71 | acpi_status status; |
@@ -111,14 +112,25 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number, | |||
111 | aml_start = (u8 *) table + sizeof(struct acpi_table_header); | 112 | aml_start = (u8 *) table + sizeof(struct acpi_table_header); |
112 | aml_length = table->length - sizeof(struct acpi_table_header); | 113 | aml_length = table->length - sizeof(struct acpi_table_header); |
113 | status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, | 114 | status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, |
114 | aml_start, aml_length, NULL, | 115 | aml_start, (u32) aml_length, |
115 | (u8) pass_number); | 116 | NULL, (u8) pass_number); |
116 | } | 117 | } |
117 | 118 | ||
118 | if (ACPI_FAILURE(status)) { | 119 | if (ACPI_FAILURE(status)) { |
119 | acpi_ds_delete_walk_state(walk_state); | 120 | acpi_ds_delete_walk_state(walk_state); |
120 | acpi_ps_delete_parse_tree(parse_root); | 121 | goto cleanup; |
121 | return_ACPI_STATUS(status); | 122 | } |
123 | |||
124 | /* start_node is the default location to load the table */ | ||
125 | |||
126 | if (start_node && start_node != acpi_gbl_root_node) { | ||
127 | status = | ||
128 | acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD, | ||
129 | walk_state); | ||
130 | if (ACPI_FAILURE(status)) { | ||
131 | acpi_ds_delete_walk_state(walk_state); | ||
132 | goto cleanup; | ||
133 | } | ||
122 | } | 134 | } |
123 | 135 | ||
124 | /* Parse the AML */ | 136 | /* Parse the AML */ |
@@ -127,6 +139,7 @@ acpi_ns_one_complete_parse(acpi_native_uint pass_number, | |||
127 | (unsigned)pass_number)); | 139 | (unsigned)pass_number)); |
128 | status = acpi_ps_parse_aml(walk_state); | 140 | status = acpi_ps_parse_aml(walk_state); |
129 | 141 | ||
142 | cleanup: | ||
130 | acpi_ps_delete_parse_tree(parse_root); | 143 | acpi_ps_delete_parse_tree(parse_root); |
131 | return_ACPI_STATUS(status); | 144 | return_ACPI_STATUS(status); |
132 | } | 145 | } |
@@ -163,7 +176,9 @@ acpi_ns_parse_table(acpi_native_uint table_index, | |||
163 | * performs another complete parse of the AML. | 176 | * performs another complete parse of the AML. |
164 | */ | 177 | */ |
165 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); | 178 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n")); |
166 | status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index); | 179 | status = |
180 | acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1, table_index, | ||
181 | start_node); | ||
167 | if (ACPI_FAILURE(status)) { | 182 | if (ACPI_FAILURE(status)) { |
168 | return_ACPI_STATUS(status); | 183 | return_ACPI_STATUS(status); |
169 | } | 184 | } |
@@ -178,7 +193,9 @@ acpi_ns_parse_table(acpi_native_uint table_index, | |||
178 | * parse objects are all cached. | 193 | * parse objects are all cached. |
179 | */ | 194 | */ |
180 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); | 195 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 2\n")); |
181 | status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index); | 196 | status = |
197 | acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS2, table_index, | ||
198 | start_node); | ||
182 | if (ACPI_FAILURE(status)) { | 199 | if (ACPI_FAILURE(status)) { |
183 | return_ACPI_STATUS(status); | 200 | return_ACPI_STATUS(status); |
184 | } | 201 | } |
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c index e863be665ce8..8399276cba1e 100644 --- a/drivers/acpi/namespace/nssearch.c +++ b/drivers/acpi/namespace/nssearch.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c index 90fd059615ff..64c039843ed2 100644 --- a/drivers/acpi/namespace/nsutils.c +++ b/drivers/acpi/namespace/nsutils.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c index 280b8357c46c..3c905ce26d7d 100644 --- a/drivers/acpi/namespace/nswalk.c +++ b/drivers/acpi/namespace/nswalk.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -77,9 +77,7 @@ struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct | |||
77 | 77 | ||
78 | /* It's really the parent's _scope_ that we want */ | 78 | /* It's really the parent's _scope_ that we want */ |
79 | 79 | ||
80 | if (parent_node->child) { | 80 | next_node = parent_node->child; |
81 | next_node = parent_node->child; | ||
82 | } | ||
83 | } | 81 | } |
84 | 82 | ||
85 | else { | 83 | else { |
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c index b92133faf5b7..a8d549187c84 100644 --- a/drivers/acpi/namespace/nsxfeval.c +++ b/drivers/acpi/namespace/nsxfeval.c | |||
@@ -6,7 +6,7 @@ | |||
6 | ******************************************************************************/ | 6 | ******************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -467,10 +467,13 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, | |||
467 | return (AE_CTRL_DEPTH); | 467 | return (AE_CTRL_DEPTH); |
468 | } | 468 | } |
469 | 469 | ||
470 | if (!(flags & ACPI_STA_DEVICE_PRESENT)) { | 470 | if (!(flags & ACPI_STA_DEVICE_PRESENT) && |
471 | 471 | !(flags & ACPI_STA_DEVICE_FUNCTIONING)) { | |
472 | /* Don't examine children of the device if not present */ | 472 | /* |
473 | 473 | * Don't examine the children of the device only when the | |
474 | * device is neither present nor functional. See ACPI spec, | ||
475 | * description of _STA for more information. | ||
476 | */ | ||
474 | return (AE_CTRL_DEPTH); | 477 | return (AE_CTRL_DEPTH); |
475 | } | 478 | } |
476 | 479 | ||
@@ -539,7 +542,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, | |||
539 | * value is returned to the caller. | 542 | * value is returned to the caller. |
540 | * | 543 | * |
541 | * This is a wrapper for walk_namespace, but the callback performs | 544 | * This is a wrapper for walk_namespace, but the callback performs |
542 | * additional filtering. Please see acpi_get_device_callback. | 545 | * additional filtering. Please see acpi_ns_get_device_callback. |
543 | * | 546 | * |
544 | ******************************************************************************/ | 547 | ******************************************************************************/ |
545 | 548 | ||
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c index b489781b22a8..a287ed550f54 100644 --- a/drivers/acpi/namespace/nsxfname.c +++ b/drivers/acpi/namespace/nsxfname.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c index faa375887201..2b375ee80cef 100644 --- a/drivers/acpi/namespace/nsxfobj.c +++ b/drivers/acpi/namespace/nsxfobj.c | |||
@@ -6,7 +6,7 @@ | |||
6 | ******************************************************************************/ | 6 | ******************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index a498a6cc68fe..235a1386888a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -742,6 +742,7 @@ EXPORT_SYMBOL(acpi_os_execute); | |||
742 | void acpi_os_wait_events_complete(void *context) | 742 | void acpi_os_wait_events_complete(void *context) |
743 | { | 743 | { |
744 | flush_workqueue(kacpid_wq); | 744 | flush_workqueue(kacpid_wq); |
745 | flush_workqueue(kacpi_notify_wq); | ||
745 | } | 746 | } |
746 | 747 | ||
747 | EXPORT_SYMBOL(acpi_os_wait_events_complete); | 748 | EXPORT_SYMBOL(acpi_os_wait_events_complete); |
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c index c2b9835c890b..f1e8bf65e24e 100644 --- a/drivers/acpi/parser/psargs.c +++ b/drivers/acpi/parser/psargs.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -230,12 +230,12 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, | |||
230 | struct acpi_parse_state *parser_state, | 230 | struct acpi_parse_state *parser_state, |
231 | union acpi_parse_object *arg, u8 possible_method_call) | 231 | union acpi_parse_object *arg, u8 possible_method_call) |
232 | { | 232 | { |
233 | acpi_status status; | ||
233 | char *path; | 234 | char *path; |
234 | union acpi_parse_object *name_op; | 235 | union acpi_parse_object *name_op; |
235 | acpi_status status; | ||
236 | union acpi_operand_object *method_desc; | 236 | union acpi_operand_object *method_desc; |
237 | struct acpi_namespace_node *node; | 237 | struct acpi_namespace_node *node; |
238 | union acpi_generic_state scope_info; | 238 | u8 *start = parser_state->aml; |
239 | 239 | ||
240 | ACPI_FUNCTION_TRACE(ps_get_next_namepath); | 240 | ACPI_FUNCTION_TRACE(ps_get_next_namepath); |
241 | 241 | ||
@@ -249,25 +249,18 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, | |||
249 | return_ACPI_STATUS(AE_OK); | 249 | return_ACPI_STATUS(AE_OK); |
250 | } | 250 | } |
251 | 251 | ||
252 | /* Setup search scope info */ | ||
253 | |||
254 | scope_info.scope.node = NULL; | ||
255 | node = parser_state->start_node; | ||
256 | if (node) { | ||
257 | scope_info.scope.node = node; | ||
258 | } | ||
259 | |||
260 | /* | 252 | /* |
261 | * Lookup the name in the internal namespace. We don't want to add | 253 | * Lookup the name in the internal namespace, starting with the current |
262 | * anything new to the namespace here, however, so we use MODE_EXECUTE. | 254 | * scope. We don't want to add anything new to the namespace here, |
255 | * however, so we use MODE_EXECUTE. | ||
263 | * Allow searching of the parent tree, but don't open a new scope - | 256 | * Allow searching of the parent tree, but don't open a new scope - |
264 | * we just want to lookup the object (must be mode EXECUTE to perform | 257 | * we just want to lookup the object (must be mode EXECUTE to perform |
265 | * the upsearch) | 258 | * the upsearch) |
266 | */ | 259 | */ |
267 | status = | 260 | status = acpi_ns_lookup(walk_state->scope_info, path, |
268 | acpi_ns_lookup(&scope_info, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | 261 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, |
269 | ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, | 262 | ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, |
270 | NULL, &node); | 263 | NULL, &node); |
271 | 264 | ||
272 | /* | 265 | /* |
273 | * If this name is a control method invocation, we must | 266 | * If this name is a control method invocation, we must |
@@ -275,6 +268,16 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, | |||
275 | */ | 268 | */ |
276 | if (ACPI_SUCCESS(status) && | 269 | if (ACPI_SUCCESS(status) && |
277 | possible_method_call && (node->type == ACPI_TYPE_METHOD)) { | 270 | possible_method_call && (node->type == ACPI_TYPE_METHOD)) { |
271 | if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { | ||
272 | /* | ||
273 | * acpi_ps_get_next_namestring has increased the AML pointer, | ||
274 | * so we need to restore the saved AML pointer for method call. | ||
275 | */ | ||
276 | walk_state->parser_state.aml = start; | ||
277 | walk_state->arg_count = 1; | ||
278 | acpi_ps_init_op(arg, AML_INT_METHODCALL_OP); | ||
279 | return_ACPI_STATUS(AE_OK); | ||
280 | } | ||
278 | 281 | ||
279 | /* This name is actually a control method invocation */ | 282 | /* This name is actually a control method invocation */ |
280 | 283 | ||
@@ -686,9 +689,29 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, | |||
686 | return_ACPI_STATUS(AE_NO_MEMORY); | 689 | return_ACPI_STATUS(AE_NO_MEMORY); |
687 | } | 690 | } |
688 | 691 | ||
689 | status = | 692 | /* To support super_name arg of Unload */ |
690 | acpi_ps_get_next_namepath(walk_state, parser_state, | 693 | |
691 | arg, 0); | 694 | if (walk_state->op->common.aml_opcode == AML_UNLOAD_OP) { |
695 | status = | ||
696 | acpi_ps_get_next_namepath(walk_state, | ||
697 | parser_state, arg, | ||
698 | 1); | ||
699 | |||
700 | /* | ||
701 | * If the super_name arg of Unload is a method call, | ||
702 | * we have restored the AML pointer, just free this Arg | ||
703 | */ | ||
704 | if (arg->common.aml_opcode == | ||
705 | AML_INT_METHODCALL_OP) { | ||
706 | acpi_ps_free_op(arg); | ||
707 | arg = NULL; | ||
708 | } | ||
709 | } else { | ||
710 | status = | ||
711 | acpi_ps_get_next_namepath(walk_state, | ||
712 | parser_state, arg, | ||
713 | 0); | ||
714 | } | ||
692 | } else { | 715 | } else { |
693 | /* Single complex argument, nothing returned */ | 716 | /* Single complex argument, nothing returned */ |
694 | 717 | ||
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c index 773aee82fbb8..c06238e55d98 100644 --- a/drivers/acpi/parser/psloop.c +++ b/drivers/acpi/parser/psloop.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -182,6 +182,7 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state, | |||
182 | ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); | 182 | ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); |
183 | 183 | ||
184 | unnamed_op->common.value.arg = NULL; | 184 | unnamed_op->common.value.arg = NULL; |
185 | unnamed_op->common.arg_list_length = 0; | ||
185 | unnamed_op->common.aml_opcode = walk_state->opcode; | 186 | unnamed_op->common.aml_opcode = walk_state->opcode; |
186 | 187 | ||
187 | /* | 188 | /* |
@@ -241,7 +242,8 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state, | |||
241 | acpi_ps_append_arg(*op, unnamed_op->common.value.arg); | 242 | acpi_ps_append_arg(*op, unnamed_op->common.value.arg); |
242 | acpi_gbl_depth++; | 243 | acpi_gbl_depth++; |
243 | 244 | ||
244 | if ((*op)->common.aml_opcode == AML_REGION_OP) { | 245 | if ((*op)->common.aml_opcode == AML_REGION_OP || |
246 | (*op)->common.aml_opcode == AML_DATA_REGION_OP) { | ||
245 | /* | 247 | /* |
246 | * Defer final parsing of an operation_region body, because we don't | 248 | * Defer final parsing of an operation_region body, because we don't |
247 | * have enough info in the first pass to parse it correctly (i.e., | 249 | * have enough info in the first pass to parse it correctly (i.e., |
@@ -280,6 +282,9 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, | |||
280 | acpi_status status = AE_OK; | 282 | acpi_status status = AE_OK; |
281 | union acpi_parse_object *op; | 283 | union acpi_parse_object *op; |
282 | union acpi_parse_object *named_op = NULL; | 284 | union acpi_parse_object *named_op = NULL; |
285 | union acpi_parse_object *parent_scope; | ||
286 | u8 argument_count; | ||
287 | const struct acpi_opcode_info *op_info; | ||
283 | 288 | ||
284 | ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); | 289 | ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); |
285 | 290 | ||
@@ -320,8 +325,32 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, | |||
320 | op->named.length = 0; | 325 | op->named.length = 0; |
321 | } | 326 | } |
322 | 327 | ||
323 | acpi_ps_append_arg(acpi_ps_get_parent_scope | 328 | if (walk_state->opcode == AML_BANK_FIELD_OP) { |
324 | (&(walk_state->parser_state)), op); | 329 | /* |
330 | * Backup to beginning of bank_field declaration | ||
331 | * body_length is unknown until we parse the body | ||
332 | */ | ||
333 | op->named.data = aml_op_start; | ||
334 | op->named.length = 0; | ||
335 | } | ||
336 | |||
337 | parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); | ||
338 | acpi_ps_append_arg(parent_scope, op); | ||
339 | |||
340 | if (parent_scope) { | ||
341 | op_info = | ||
342 | acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); | ||
343 | if (op_info->flags & AML_HAS_TARGET) { | ||
344 | argument_count = | ||
345 | acpi_ps_get_argument_count(op_info->type); | ||
346 | if (parent_scope->common.arg_list_length > | ||
347 | argument_count) { | ||
348 | op->common.flags |= ACPI_PARSEOP_TARGET; | ||
349 | } | ||
350 | } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { | ||
351 | op->common.flags |= ACPI_PARSEOP_TARGET; | ||
352 | } | ||
353 | } | ||
325 | 354 | ||
326 | if (walk_state->descending_callback != NULL) { | 355 | if (walk_state->descending_callback != NULL) { |
327 | /* | 356 | /* |
@@ -603,13 +632,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state, | |||
603 | acpi_ps_pop_scope(&(walk_state->parser_state), op, | 632 | acpi_ps_pop_scope(&(walk_state->parser_state), op, |
604 | &walk_state->arg_types, | 633 | &walk_state->arg_types, |
605 | &walk_state->arg_count); | 634 | &walk_state->arg_count); |
606 | |||
607 | if ((*op)->common.aml_opcode != AML_WHILE_OP) { | ||
608 | status2 = acpi_ds_result_stack_pop(walk_state); | ||
609 | if (ACPI_FAILURE(status2)) { | ||
610 | return_ACPI_STATUS(status2); | ||
611 | } | ||
612 | } | ||
613 | } | 635 | } |
614 | 636 | ||
615 | /* Close this iteration of the While loop */ | 637 | /* Close this iteration of the While loop */ |
@@ -640,10 +662,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state, | |||
640 | if (ACPI_FAILURE(status2)) { | 662 | if (ACPI_FAILURE(status2)) { |
641 | return_ACPI_STATUS(status2); | 663 | return_ACPI_STATUS(status2); |
642 | } | 664 | } |
643 | status2 = acpi_ds_result_stack_pop(walk_state); | ||
644 | if (ACPI_FAILURE(status2)) { | ||
645 | return_ACPI_STATUS(status2); | ||
646 | } | ||
647 | 665 | ||
648 | acpi_ut_delete_generic_state | 666 | acpi_ut_delete_generic_state |
649 | (acpi_ut_pop_generic_state | 667 | (acpi_ut_pop_generic_state |
@@ -1005,7 +1023,8 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) | |||
1005 | acpi_gbl_depth--; | 1023 | acpi_gbl_depth--; |
1006 | } | 1024 | } |
1007 | 1025 | ||
1008 | if (op->common.aml_opcode == AML_REGION_OP) { | 1026 | if (op->common.aml_opcode == AML_REGION_OP || |
1027 | op->common.aml_opcode == AML_DATA_REGION_OP) { | ||
1009 | /* | 1028 | /* |
1010 | * Skip parsing of control method or opregion body, | 1029 | * Skip parsing of control method or opregion body, |
1011 | * because we don't have enough info in the first pass | 1030 | * because we don't have enough info in the first pass |
@@ -1030,6 +1049,16 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) | |||
1030 | (u32) (parser_state->aml - op->named.data); | 1049 | (u32) (parser_state->aml - op->named.data); |
1031 | } | 1050 | } |
1032 | 1051 | ||
1052 | if (op->common.aml_opcode == AML_BANK_FIELD_OP) { | ||
1053 | /* | ||
1054 | * Backup to beginning of bank_field declaration | ||
1055 | * | ||
1056 | * body_length is unknown until we parse the body | ||
1057 | */ | ||
1058 | op->named.length = | ||
1059 | (u32) (parser_state->aml - op->named.data); | ||
1060 | } | ||
1061 | |||
1033 | /* This op complete, notify the dispatcher */ | 1062 | /* This op complete, notify the dispatcher */ |
1034 | 1063 | ||
1035 | if (walk_state->ascending_callback != NULL) { | 1064 | if (walk_state->ascending_callback != NULL) { |
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c index 9296e86761d7..f425ab30eae8 100644 --- a/drivers/acpi/parser/psopcode.c +++ b/drivers/acpi/parser/psopcode.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -49,6 +49,9 @@ | |||
49 | #define _COMPONENT ACPI_PARSER | 49 | #define _COMPONENT ACPI_PARSER |
50 | ACPI_MODULE_NAME("psopcode") | 50 | ACPI_MODULE_NAME("psopcode") |
51 | 51 | ||
52 | static const u8 acpi_gbl_argument_count[] = | ||
53 | { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 }; | ||
54 | |||
52 | /******************************************************************************* | 55 | /******************************************************************************* |
53 | * | 56 | * |
54 | * NAME: acpi_gbl_aml_op_info | 57 | * NAME: acpi_gbl_aml_op_info |
@@ -59,6 +62,7 @@ ACPI_MODULE_NAME("psopcode") | |||
59 | * the operand type. | 62 | * the operand type. |
60 | * | 63 | * |
61 | ******************************************************************************/ | 64 | ******************************************************************************/ |
65 | |||
62 | /* | 66 | /* |
63 | * Summary of opcode types/flags | 67 | * Summary of opcode types/flags |
64 | * | 68 | * |
@@ -176,6 +180,7 @@ ACPI_MODULE_NAME("psopcode") | |||
176 | AML_CREATE_QWORD_FIELD_OP | 180 | AML_CREATE_QWORD_FIELD_OP |
177 | 181 | ||
178 | ******************************************************************************/ | 182 | ******************************************************************************/ |
183 | |||
179 | /* | 184 | /* |
180 | * Master Opcode information table. A summary of everything we know about each | 185 | * Master Opcode information table. A summary of everything we know about each |
181 | * opcode, all in one place. | 186 | * opcode, all in one place. |
@@ -515,9 +520,10 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { | |||
515 | AML_TYPE_NAMED_FIELD, | 520 | AML_TYPE_NAMED_FIELD, |
516 | AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), | 521 | AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), |
517 | /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, | 522 | /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP, |
518 | ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, | 523 | ACPI_TYPE_LOCAL_BANK_FIELD, AML_CLASS_NAMED_OBJECT, |
519 | AML_TYPE_NAMED_FIELD, | 524 | AML_TYPE_NAMED_FIELD, |
520 | AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD), | 525 | AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD | |
526 | AML_DEFER), | ||
521 | 527 | ||
522 | /* Internal opcodes that map to invalid AML opcodes */ | 528 | /* Internal opcodes that map to invalid AML opcodes */ |
523 | 529 | ||
@@ -619,9 +625,9 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { | |||
619 | AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), | 625 | AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R), |
620 | /* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP, | 626 | /* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP, |
621 | ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, | 627 | ARGI_DATA_REGION_OP, ACPI_TYPE_REGION, |
622 | AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, | 628 | AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX, |
623 | AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | | 629 | AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | |
624 | AML_NSNODE | AML_NAMED), | 630 | AML_NSNODE | AML_NAMED | AML_DEFER), |
625 | /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, | 631 | /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP, |
626 | ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, | 632 | ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, |
627 | AML_TYPE_NAMED_NO_OBJ, | 633 | AML_TYPE_NAMED_NO_OBJ, |
@@ -779,3 +785,25 @@ char *acpi_ps_get_opcode_name(u16 opcode) | |||
779 | 785 | ||
780 | #endif | 786 | #endif |
781 | } | 787 | } |
788 | |||
789 | /******************************************************************************* | ||
790 | * | ||
791 | * FUNCTION: acpi_ps_get_argument_count | ||
792 | * | ||
793 | * PARAMETERS: op_type - Type associated with the AML opcode | ||
794 | * | ||
795 | * RETURN: Argument count | ||
796 | * | ||
797 | * DESCRIPTION: Obtain the number of expected arguments for an AML opcode | ||
798 | * | ||
799 | ******************************************************************************/ | ||
800 | |||
801 | u8 acpi_ps_get_argument_count(u32 op_type) | ||
802 | { | ||
803 | |||
804 | if (op_type <= AML_TYPE_EXEC_6A_0T_1R) { | ||
805 | return (acpi_gbl_argument_count[op_type]); | ||
806 | } | ||
807 | |||
808 | return (0); | ||
809 | } | ||
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c index 5d63f48e56b5..15e1702e48d6 100644 --- a/drivers/acpi/parser/psparse.c +++ b/drivers/acpi/parser/psparse.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -205,6 +205,8 @@ acpi_ps_complete_this_op(struct acpi_walk_state * walk_state, | |||
205 | || (op->common.parent->common.aml_opcode == | 205 | || (op->common.parent->common.aml_opcode == |
206 | AML_PACKAGE_OP) | 206 | AML_PACKAGE_OP) |
207 | || (op->common.parent->common.aml_opcode == | 207 | || (op->common.parent->common.aml_opcode == |
208 | AML_BANK_FIELD_OP) | ||
209 | || (op->common.parent->common.aml_opcode == | ||
208 | AML_VAR_PACKAGE_OP)) { | 210 | AML_VAR_PACKAGE_OP)) { |
209 | replacement_op = | 211 | replacement_op = |
210 | acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); | 212 | acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP); |
@@ -349,19 +351,13 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, | |||
349 | 351 | ||
350 | parser_state->aml = walk_state->aml_last_while; | 352 | parser_state->aml = walk_state->aml_last_while; |
351 | walk_state->control_state->common.value = FALSE; | 353 | walk_state->control_state->common.value = FALSE; |
352 | status = acpi_ds_result_stack_pop(walk_state); | 354 | status = AE_CTRL_BREAK; |
353 | if (ACPI_SUCCESS(status)) { | ||
354 | status = AE_CTRL_BREAK; | ||
355 | } | ||
356 | break; | 355 | break; |
357 | 356 | ||
358 | case AE_CTRL_CONTINUE: | 357 | case AE_CTRL_CONTINUE: |
359 | 358 | ||
360 | parser_state->aml = walk_state->aml_last_while; | 359 | parser_state->aml = walk_state->aml_last_while; |
361 | status = acpi_ds_result_stack_pop(walk_state); | 360 | status = AE_CTRL_CONTINUE; |
362 | if (ACPI_SUCCESS(status)) { | ||
363 | status = AE_CTRL_CONTINUE; | ||
364 | } | ||
365 | break; | 361 | break; |
366 | 362 | ||
367 | case AE_CTRL_PENDING: | 363 | case AE_CTRL_PENDING: |
@@ -383,10 +379,7 @@ acpi_ps_next_parse_state(struct acpi_walk_state *walk_state, | |||
383 | * Just close out this package | 379 | * Just close out this package |
384 | */ | 380 | */ |
385 | parser_state->aml = acpi_ps_get_next_package_end(parser_state); | 381 | parser_state->aml = acpi_ps_get_next_package_end(parser_state); |
386 | status = acpi_ds_result_stack_pop(walk_state); | 382 | status = AE_CTRL_PENDING; |
387 | if (ACPI_SUCCESS(status)) { | ||
388 | status = AE_CTRL_PENDING; | ||
389 | } | ||
390 | break; | 383 | break; |
391 | 384 | ||
392 | case AE_CTRL_FALSE: | 385 | case AE_CTRL_FALSE: |
@@ -541,7 +534,7 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) | |||
541 | if ((status == AE_ALREADY_EXISTS) && | 534 | if ((status == AE_ALREADY_EXISTS) && |
542 | (!walk_state->method_desc->method.mutex)) { | 535 | (!walk_state->method_desc->method.mutex)) { |
543 | ACPI_INFO((AE_INFO, | 536 | ACPI_INFO((AE_INFO, |
544 | "Marking method %4.4s as Serialized", | 537 | "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", |
545 | walk_state->method_node->name. | 538 | walk_state->method_node->name. |
546 | ascii)); | 539 | ascii)); |
547 | 540 | ||
@@ -601,6 +594,30 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) | |||
601 | * The object is deleted | 594 | * The object is deleted |
602 | */ | 595 | */ |
603 | if (!previous_walk_state->return_desc) { | 596 | if (!previous_walk_state->return_desc) { |
597 | /* | ||
598 | * In slack mode execution, if there is no return value | ||
599 | * we should implicitly return zero (0) as a default value. | ||
600 | */ | ||
601 | if (acpi_gbl_enable_interpreter_slack && | ||
602 | !previous_walk_state-> | ||
603 | implicit_return_obj) { | ||
604 | previous_walk_state-> | ||
605 | implicit_return_obj = | ||
606 | acpi_ut_create_internal_object | ||
607 | (ACPI_TYPE_INTEGER); | ||
608 | if (!previous_walk_state-> | ||
609 | implicit_return_obj) { | ||
610 | return_ACPI_STATUS | ||
611 | (AE_NO_MEMORY); | ||
612 | } | ||
613 | |||
614 | previous_walk_state-> | ||
615 | implicit_return_obj-> | ||
616 | integer.value = 0; | ||
617 | } | ||
618 | |||
619 | /* Restart the calling control method */ | ||
620 | |||
604 | status = | 621 | status = |
605 | acpi_ds_restart_control_method | 622 | acpi_ds_restart_control_method |
606 | (walk_state, | 623 | (walk_state, |
diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c index 77cfa4ed0cfe..ee50e67c9443 100644 --- a/drivers/acpi/parser/psscope.c +++ b/drivers/acpi/parser/psscope.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c index 966e7ea2a0c4..1dd355ddd182 100644 --- a/drivers/acpi/parser/pstree.c +++ b/drivers/acpi/parser/pstree.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -171,6 +171,8 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) | |||
171 | while (arg) { | 171 | while (arg) { |
172 | arg->common.parent = op; | 172 | arg->common.parent = op; |
173 | arg = arg->common.next; | 173 | arg = arg->common.next; |
174 | |||
175 | op->common.arg_list_length++; | ||
174 | } | 176 | } |
175 | } | 177 | } |
176 | 178 | ||
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c index 8ca52002db55..7cf1f65cd5bb 100644 --- a/drivers/acpi/parser/psutils.c +++ b/drivers/acpi/parser/psutils.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c index 49f9757434e4..8b86ad5a3201 100644 --- a/drivers/acpi/parser/pswalk.c +++ b/drivers/acpi/parser/pswalk.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c index 94103bced75e..52581454c47c 100644 --- a/drivers/acpi/parser/psxface.c +++ b/drivers/acpi/parser/psxface.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 21fc8bf0d31f..81e4f081a4ae 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c | |||
@@ -122,7 +122,7 @@ acpi_power_get_context(acpi_handle handle, | |||
122 | } | 122 | } |
123 | 123 | ||
124 | *resource = acpi_driver_data(device); | 124 | *resource = acpi_driver_data(device); |
125 | if (!resource) | 125 | if (!*resource) |
126 | return -ENODEV; | 126 | return -ENODEV; |
127 | 127 | ||
128 | return 0; | 128 | return 0; |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 5241e3ff5080..386e5aa48834 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -674,22 +674,21 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) | |||
674 | result = PTR_ERR(pr->cdev); | 674 | result = PTR_ERR(pr->cdev); |
675 | goto end; | 675 | goto end; |
676 | } | 676 | } |
677 | if (pr->cdev) { | 677 | |
678 | printk(KERN_INFO PREFIX | 678 | printk(KERN_INFO PREFIX |
679 | "%s is registered as cooling_device%d\n", | 679 | "%s is registered as cooling_device%d\n", |
680 | device->dev.bus_id, pr->cdev->id); | 680 | device->dev.bus_id, pr->cdev->id); |
681 | 681 | ||
682 | result = sysfs_create_link(&device->dev.kobj, | 682 | result = sysfs_create_link(&device->dev.kobj, |
683 | &pr->cdev->device.kobj, | 683 | &pr->cdev->device.kobj, |
684 | "thermal_cooling"); | 684 | "thermal_cooling"); |
685 | if (result) | 685 | if (result) |
686 | return result; | 686 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
687 | result = sysfs_create_link(&pr->cdev->device.kobj, | 687 | result = sysfs_create_link(&pr->cdev->device.kobj, |
688 | &device->dev.kobj, | 688 | &device->dev.kobj, |
689 | "device"); | 689 | "device"); |
690 | if (result) | 690 | if (result) |
691 | return result; | 691 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
692 | } | ||
693 | 692 | ||
694 | if (pr->flags.throttling) { | 693 | if (pr->flags.throttling) { |
695 | printk(KERN_INFO PREFIX "%s [%s] (supports", | 694 | printk(KERN_INFO PREFIX "%s [%s] (supports", |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 789d4947ed31..2dd2c1f3a01c 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -847,6 +847,7 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) | |||
847 | /* all processors need to support C1 */ | 847 | /* all processors need to support C1 */ |
848 | pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; | 848 | pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; |
849 | pr->power.states[ACPI_STATE_C1].valid = 1; | 849 | pr->power.states[ACPI_STATE_C1].valid = 1; |
850 | pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT; | ||
850 | } | 851 | } |
851 | /* the C0 state only exists as a filler in our array */ | 852 | /* the C0 state only exists as a filler in our array */ |
852 | pr->power.states[ACPI_STATE_C0].valid = 1; | 853 | pr->power.states[ACPI_STATE_C0].valid = 1; |
@@ -959,6 +960,9 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) | |||
959 | cx.address); | 960 | cx.address); |
960 | } | 961 | } |
961 | 962 | ||
963 | if (cx.type == ACPI_STATE_C1) { | ||
964 | cx.valid = 1; | ||
965 | } | ||
962 | 966 | ||
963 | obj = &(element->package.elements[2]); | 967 | obj = &(element->package.elements[2]); |
964 | if (obj->type != ACPI_TYPE_INTEGER) | 968 | if (obj->type != ACPI_TYPE_INTEGER) |
@@ -1295,6 +1299,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1295 | { | 1299 | { |
1296 | int result = 0; | 1300 | int result = 0; |
1297 | 1301 | ||
1302 | if (boot_option_idle_override) | ||
1303 | return 0; | ||
1298 | 1304 | ||
1299 | if (!pr) | 1305 | if (!pr) |
1300 | return -EINVAL; | 1306 | return -EINVAL; |
@@ -1734,6 +1740,9 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1734 | { | 1740 | { |
1735 | int ret; | 1741 | int ret; |
1736 | 1742 | ||
1743 | if (boot_option_idle_override) | ||
1744 | return 0; | ||
1745 | |||
1737 | if (!pr) | 1746 | if (!pr) |
1738 | return -EINVAL; | 1747 | return -EINVAL; |
1739 | 1748 | ||
@@ -1764,6 +1773,8 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1764 | struct proc_dir_entry *entry = NULL; | 1773 | struct proc_dir_entry *entry = NULL; |
1765 | unsigned int i; | 1774 | unsigned int i; |
1766 | 1775 | ||
1776 | if (boot_option_idle_override) | ||
1777 | return 0; | ||
1767 | 1778 | ||
1768 | if (!first_run) { | 1779 | if (!first_run) { |
1769 | dmi_check_system(processor_power_dmi_table); | 1780 | dmi_check_system(processor_power_dmi_table); |
@@ -1799,7 +1810,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1799 | * Note that we use previously set idle handler will be used on | 1810 | * Note that we use previously set idle handler will be used on |
1800 | * platforms that only support C1. | 1811 | * platforms that only support C1. |
1801 | */ | 1812 | */ |
1802 | if ((pr->flags.power) && (!boot_option_idle_override)) { | 1813 | if (pr->flags.power) { |
1803 | #ifdef CONFIG_CPU_IDLE | 1814 | #ifdef CONFIG_CPU_IDLE |
1804 | acpi_processor_setup_cpuidle(pr); | 1815 | acpi_processor_setup_cpuidle(pr); |
1805 | pr->power.dev.cpu = pr->id; | 1816 | pr->power.dev.cpu = pr->id; |
@@ -1835,8 +1846,11 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, | |||
1835 | int acpi_processor_power_exit(struct acpi_processor *pr, | 1846 | int acpi_processor_power_exit(struct acpi_processor *pr, |
1836 | struct acpi_device *device) | 1847 | struct acpi_device *device) |
1837 | { | 1848 | { |
1849 | if (boot_option_idle_override) | ||
1850 | return 0; | ||
1851 | |||
1838 | #ifdef CONFIG_CPU_IDLE | 1852 | #ifdef CONFIG_CPU_IDLE |
1839 | if ((pr->flags.power) && (!boot_option_idle_override)) | 1853 | if (pr->flags.power) |
1840 | cpuidle_unregister_device(&pr->power.dev); | 1854 | cpuidle_unregister_device(&pr->power.dev); |
1841 | #endif | 1855 | #endif |
1842 | pr->flags.power_setup_done = 0; | 1856 | pr->flags.power_setup_done = 0; |
diff --git a/drivers/acpi/resources/rsaddr.c b/drivers/acpi/resources/rsaddr.c index 271e61509eeb..7f96332822bf 100644 --- a/drivers/acpi/resources/rsaddr.c +++ b/drivers/acpi/resources/rsaddr.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c index 0dd2ce8a3475..8a112d11d491 100644 --- a/drivers/acpi/resources/rscalc.c +++ b/drivers/acpi/resources/rscalc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -73,7 +73,7 @@ acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length); | |||
73 | 73 | ||
74 | static u8 acpi_rs_count_set_bits(u16 bit_field) | 74 | static u8 acpi_rs_count_set_bits(u16 bit_field) |
75 | { | 75 | { |
76 | u8 bits_set; | 76 | acpi_native_uint bits_set; |
77 | 77 | ||
78 | ACPI_FUNCTION_ENTRY(); | 78 | ACPI_FUNCTION_ENTRY(); |
79 | 79 | ||
@@ -81,10 +81,10 @@ static u8 acpi_rs_count_set_bits(u16 bit_field) | |||
81 | 81 | ||
82 | /* Zero the least significant bit that is set */ | 82 | /* Zero the least significant bit that is set */ |
83 | 83 | ||
84 | bit_field &= (bit_field - 1); | 84 | bit_field &= (u16) (bit_field - 1); |
85 | } | 85 | } |
86 | 86 | ||
87 | return (bits_set); | 87 | return ((u8) bits_set); |
88 | } | 88 | } |
89 | 89 | ||
90 | /******************************************************************************* | 90 | /******************************************************************************* |
@@ -211,6 +211,24 @@ acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed) | |||
211 | * variable-length fields | 211 | * variable-length fields |
212 | */ | 212 | */ |
213 | switch (resource->type) { | 213 | switch (resource->type) { |
214 | case ACPI_RESOURCE_TYPE_IRQ: | ||
215 | |||
216 | /* Length can be 3 or 2 */ | ||
217 | |||
218 | if (resource->data.irq.descriptor_length == 2) { | ||
219 | total_size--; | ||
220 | } | ||
221 | break; | ||
222 | |||
223 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: | ||
224 | |||
225 | /* Length can be 1 or 0 */ | ||
226 | |||
227 | if (resource->data.irq.descriptor_length == 0) { | ||
228 | total_size--; | ||
229 | } | ||
230 | break; | ||
231 | |||
214 | case ACPI_RESOURCE_TYPE_VENDOR: | 232 | case ACPI_RESOURCE_TYPE_VENDOR: |
215 | /* | 233 | /* |
216 | * Vendor Defined Resource: | 234 | * Vendor Defined Resource: |
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c index 50da494c3ee2..faddaee1bc07 100644 --- a/drivers/acpi/resources/rscreate.c +++ b/drivers/acpi/resources/rscreate.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c index 46da116a4030..6bbbb7b8941a 100644 --- a/drivers/acpi/resources/rsdump.c +++ b/drivers/acpi/resources/rsdump.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -87,8 +87,10 @@ acpi_rs_dump_descriptor(void *resource, struct acpi_rsdump_info *table); | |||
87 | * | 87 | * |
88 | ******************************************************************************/ | 88 | ******************************************************************************/ |
89 | 89 | ||
90 | struct acpi_rsdump_info acpi_rs_dump_irq[6] = { | 90 | struct acpi_rsdump_info acpi_rs_dump_irq[7] = { |
91 | {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, | 91 | {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL}, |
92 | {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.descriptor_length), | ||
93 | "Descriptor Length", NULL}, | ||
92 | {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", | 94 | {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering", |
93 | acpi_gbl_he_decode}, | 95 | acpi_gbl_he_decode}, |
94 | {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", | 96 | {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity", |
@@ -115,9 +117,11 @@ struct acpi_rsdump_info acpi_rs_dump_dma[6] = { | |||
115 | NULL} | 117 | NULL} |
116 | }; | 118 | }; |
117 | 119 | ||
118 | struct acpi_rsdump_info acpi_rs_dump_start_dpf[3] = { | 120 | struct acpi_rsdump_info acpi_rs_dump_start_dpf[4] = { |
119 | {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), | 121 | {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_start_dpf), |
120 | "Start-Dependent-Functions", NULL}, | 122 | "Start-Dependent-Functions", NULL}, |
123 | {ACPI_RSD_UINT8, ACPI_RSD_OFFSET(start_dpf.descriptor_length), | ||
124 | "Descriptor Length", NULL}, | ||
121 | {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), | 125 | {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.compatibility_priority), |
122 | "Compatibility Priority", acpi_gbl_config_decode}, | 126 | "Compatibility Priority", acpi_gbl_config_decode}, |
123 | {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), | 127 | {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(start_dpf.performance_robustness), |
diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c index 2c2adb6292c1..3f0a1fedbe0e 100644 --- a/drivers/acpi/resources/rsinfo.c +++ b/drivers/acpi/resources/rsinfo.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/resources/rsio.c b/drivers/acpi/resources/rsio.c index b297bc3e4419..b66d42e7402e 100644 --- a/drivers/acpi/resources/rsio.c +++ b/drivers/acpi/resources/rsio.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -185,7 +185,7 @@ struct acpi_rsconvert_info acpi_rs_convert_end_tag[2] = { | |||
185 | * | 185 | * |
186 | ******************************************************************************/ | 186 | ******************************************************************************/ |
187 | 187 | ||
188 | struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = { | 188 | struct acpi_rsconvert_info acpi_rs_get_start_dpf[6] = { |
189 | {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT, | 189 | {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_START_DEPENDENT, |
190 | ACPI_RS_SIZE(struct acpi_resource_start_dependent), | 190 | ACPI_RS_SIZE(struct acpi_resource_start_dependent), |
191 | ACPI_RSC_TABLE_SIZE(acpi_rs_get_start_dpf)}, | 191 | ACPI_RSC_TABLE_SIZE(acpi_rs_get_start_dpf)}, |
@@ -196,6 +196,12 @@ struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = { | |||
196 | ACPI_ACCEPTABLE_CONFIGURATION, | 196 | ACPI_ACCEPTABLE_CONFIGURATION, |
197 | 2}, | 197 | 2}, |
198 | 198 | ||
199 | /* Get the descriptor length (0 or 1 for Start Dpf descriptor) */ | ||
200 | |||
201 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.start_dpf.descriptor_length), | ||
202 | AML_OFFSET(start_dpf.descriptor_type), | ||
203 | 0}, | ||
204 | |||
199 | /* All done if there is no flag byte present in the descriptor */ | 205 | /* All done if there is no flag byte present in the descriptor */ |
200 | 206 | ||
201 | {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1}, | 207 | {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 1}, |
@@ -219,7 +225,9 @@ struct acpi_rsconvert_info acpi_rs_get_start_dpf[5] = { | |||
219 | * | 225 | * |
220 | ******************************************************************************/ | 226 | ******************************************************************************/ |
221 | 227 | ||
222 | struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = { | 228 | struct acpi_rsconvert_info acpi_rs_set_start_dpf[10] = { |
229 | /* Start with a default descriptor of length 1 */ | ||
230 | |||
223 | {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT, | 231 | {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_START_DEPENDENT, |
224 | sizeof(struct aml_resource_start_dependent), | 232 | sizeof(struct aml_resource_start_dependent), |
225 | ACPI_RSC_TABLE_SIZE(acpi_rs_set_start_dpf)}, | 233 | ACPI_RSC_TABLE_SIZE(acpi_rs_set_start_dpf)}, |
@@ -236,6 +244,33 @@ struct acpi_rsconvert_info acpi_rs_set_start_dpf[6] = { | |||
236 | AML_OFFSET(start_dpf.flags), | 244 | AML_OFFSET(start_dpf.flags), |
237 | 2}, | 245 | 2}, |
238 | /* | 246 | /* |
247 | * All done if the output descriptor length is required to be 1 | ||
248 | * (i.e., optimization to 0 bytes cannot be attempted) | ||
249 | */ | ||
250 | {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, | ||
251 | ACPI_RS_OFFSET(data.start_dpf.descriptor_length), | ||
252 | 1}, | ||
253 | |||
254 | /* Set length to 0 bytes (no flags byte) */ | ||
255 | |||
256 | {ACPI_RSC_LENGTH, 0, 0, | ||
257 | sizeof(struct aml_resource_start_dependent_noprio)}, | ||
258 | |||
259 | /* | ||
260 | * All done if the output descriptor length is required to be 0. | ||
261 | * | ||
262 | * TBD: Perhaps we should check for error if input flags are not | ||
263 | * compatible with a 0-byte descriptor. | ||
264 | */ | ||
265 | {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, | ||
266 | ACPI_RS_OFFSET(data.start_dpf.descriptor_length), | ||
267 | 0}, | ||
268 | |||
269 | /* Reset length to 1 byte (descriptor with flags byte) */ | ||
270 | |||
271 | {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_start_dependent)}, | ||
272 | |||
273 | /* | ||
239 | * All done if flags byte is necessary -- if either priority value | 274 | * All done if flags byte is necessary -- if either priority value |
240 | * is not ACPI_ACCEPTABLE_CONFIGURATION | 275 | * is not ACPI_ACCEPTABLE_CONFIGURATION |
241 | */ | 276 | */ |
diff --git a/drivers/acpi/resources/rsirq.c b/drivers/acpi/resources/rsirq.c index 5657f7b95039..a8805efc0366 100644 --- a/drivers/acpi/resources/rsirq.c +++ b/drivers/acpi/resources/rsirq.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -52,7 +52,7 @@ ACPI_MODULE_NAME("rsirq") | |||
52 | * acpi_rs_get_irq | 52 | * acpi_rs_get_irq |
53 | * | 53 | * |
54 | ******************************************************************************/ | 54 | ******************************************************************************/ |
55 | struct acpi_rsconvert_info acpi_rs_get_irq[7] = { | 55 | struct acpi_rsconvert_info acpi_rs_get_irq[8] = { |
56 | {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, | 56 | {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_IRQ, |
57 | ACPI_RS_SIZE(struct acpi_resource_irq), | 57 | ACPI_RS_SIZE(struct acpi_resource_irq), |
58 | ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, | 58 | ACPI_RSC_TABLE_SIZE(acpi_rs_get_irq)}, |
@@ -69,6 +69,12 @@ struct acpi_rsconvert_info acpi_rs_get_irq[7] = { | |||
69 | ACPI_EDGE_SENSITIVE, | 69 | ACPI_EDGE_SENSITIVE, |
70 | 1}, | 70 | 1}, |
71 | 71 | ||
72 | /* Get the descriptor length (2 or 3 for IRQ descriptor) */ | ||
73 | |||
74 | {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.irq.descriptor_length), | ||
75 | AML_OFFSET(irq.descriptor_type), | ||
76 | 0}, | ||
77 | |||
72 | /* All done if no flag byte present in descriptor */ | 78 | /* All done if no flag byte present in descriptor */ |
73 | 79 | ||
74 | {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, | 80 | {ACPI_RSC_EXIT_NE, ACPI_RSC_COMPARE_AML_LENGTH, 0, 3}, |
@@ -94,7 +100,9 @@ struct acpi_rsconvert_info acpi_rs_get_irq[7] = { | |||
94 | * | 100 | * |
95 | ******************************************************************************/ | 101 | ******************************************************************************/ |
96 | 102 | ||
97 | struct acpi_rsconvert_info acpi_rs_set_irq[9] = { | 103 | struct acpi_rsconvert_info acpi_rs_set_irq[13] = { |
104 | /* Start with a default descriptor of length 3 */ | ||
105 | |||
98 | {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, | 106 | {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_IRQ, |
99 | sizeof(struct aml_resource_irq), | 107 | sizeof(struct aml_resource_irq), |
100 | ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)}, | 108 | ACPI_RSC_TABLE_SIZE(acpi_rs_set_irq)}, |
@@ -105,7 +113,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = { | |||
105 | AML_OFFSET(irq.irq_mask), | 113 | AML_OFFSET(irq.irq_mask), |
106 | ACPI_RS_OFFSET(data.irq.interrupt_count)}, | 114 | ACPI_RS_OFFSET(data.irq.interrupt_count)}, |
107 | 115 | ||
108 | /* Set the flags byte by default */ | 116 | /* Set the flags byte */ |
109 | 117 | ||
110 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), | 118 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.triggering), |
111 | AML_OFFSET(irq.flags), | 119 | AML_OFFSET(irq.flags), |
@@ -118,6 +126,33 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = { | |||
118 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), | 126 | {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.irq.sharable), |
119 | AML_OFFSET(irq.flags), | 127 | AML_OFFSET(irq.flags), |
120 | 4}, | 128 | 4}, |
129 | |||
130 | /* | ||
131 | * All done if the output descriptor length is required to be 3 | ||
132 | * (i.e., optimization to 2 bytes cannot be attempted) | ||
133 | */ | ||
134 | {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, | ||
135 | ACPI_RS_OFFSET(data.irq.descriptor_length), | ||
136 | 3}, | ||
137 | |||
138 | /* Set length to 2 bytes (no flags byte) */ | ||
139 | |||
140 | {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)}, | ||
141 | |||
142 | /* | ||
143 | * All done if the output descriptor length is required to be 2. | ||
144 | * | ||
145 | * TBD: Perhaps we should check for error if input flags are not | ||
146 | * compatible with a 2-byte descriptor. | ||
147 | */ | ||
148 | {ACPI_RSC_EXIT_EQ, ACPI_RSC_COMPARE_VALUE, | ||
149 | ACPI_RS_OFFSET(data.irq.descriptor_length), | ||
150 | 2}, | ||
151 | |||
152 | /* Reset length to 3 bytes (descriptor with flags byte) */ | ||
153 | |||
154 | {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq)}, | ||
155 | |||
121 | /* | 156 | /* |
122 | * Check if the flags byte is necessary. Not needed if the flags are: | 157 | * Check if the flags byte is necessary. Not needed if the flags are: |
123 | * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE | 158 | * ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_HIGH, ACPI_EXCLUSIVE |
@@ -134,7 +169,7 @@ struct acpi_rsconvert_info acpi_rs_set_irq[9] = { | |||
134 | ACPI_RS_OFFSET(data.irq.sharable), | 169 | ACPI_RS_OFFSET(data.irq.sharable), |
135 | ACPI_EXCLUSIVE}, | 170 | ACPI_EXCLUSIVE}, |
136 | 171 | ||
137 | /* irq_no_flags() descriptor can be used */ | 172 | /* We can optimize to a 2-byte irq_no_flags() descriptor */ |
138 | 173 | ||
139 | {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)} | 174 | {ACPI_RSC_LENGTH, 0, 0, sizeof(struct aml_resource_irq_noflags)} |
140 | }; | 175 | }; |
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c index ca21e4660c79..b78c7e797a19 100644 --- a/drivers/acpi/resources/rslist.c +++ b/drivers/acpi/resources/rslist.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/resources/rsmemory.c b/drivers/acpi/resources/rsmemory.c index 521eab7dd8df..63b21abd90bb 100644 --- a/drivers/acpi/resources/rsmemory.c +++ b/drivers/acpi/resources/rsmemory.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c index c7081afa893a..de1ac3881b22 100644 --- a/drivers/acpi/resources/rsmisc.c +++ b/drivers/acpi/resources/rsmisc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -497,6 +497,17 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, | |||
497 | } | 497 | } |
498 | break; | 498 | break; |
499 | 499 | ||
500 | case ACPI_RSC_EXIT_EQ: | ||
501 | /* | ||
502 | * Control - Exit conversion if equal | ||
503 | */ | ||
504 | if (*ACPI_ADD_PTR(u8, resource, | ||
505 | COMPARE_TARGET(info)) == | ||
506 | COMPARE_VALUE(info)) { | ||
507 | goto exit; | ||
508 | } | ||
509 | break; | ||
510 | |||
500 | default: | 511 | default: |
501 | 512 | ||
502 | ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); | 513 | ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); |
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index 11c0bd7b9cfd..befe2302f41b 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -97,17 +97,17 @@ u8 acpi_rs_decode_bitmask(u16 mask, u8 * list) | |||
97 | u16 acpi_rs_encode_bitmask(u8 * list, u8 count) | 97 | u16 acpi_rs_encode_bitmask(u8 * list, u8 count) |
98 | { | 98 | { |
99 | acpi_native_uint i; | 99 | acpi_native_uint i; |
100 | u16 mask; | 100 | acpi_native_uint mask; |
101 | 101 | ||
102 | ACPI_FUNCTION_ENTRY(); | 102 | ACPI_FUNCTION_ENTRY(); |
103 | 103 | ||
104 | /* Encode the list into a single bitmask */ | 104 | /* Encode the list into a single bitmask */ |
105 | 105 | ||
106 | for (i = 0, mask = 0; i < count; i++) { | 106 | for (i = 0, mask = 0; i < count; i++) { |
107 | mask |= (0x0001 << list[i]); | 107 | mask |= (0x1 << list[i]); |
108 | } | 108 | } |
109 | 109 | ||
110 | return (mask); | 110 | return ((u16) mask); |
111 | } | 111 | } |
112 | 112 | ||
113 | /******************************************************************************* | 113 | /******************************************************************************* |
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c index 4c3fd4cdaf73..f59f4c4e034c 100644 --- a/drivers/acpi/resources/rsxface.c +++ b/drivers/acpi/resources/rsxface.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e6ce262b5d44..6d85289f1c12 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -677,9 +677,8 @@ acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, | |||
677 | device->wakeup.resources.count = package->package.count - 2; | 677 | device->wakeup.resources.count = package->package.count - 2; |
678 | for (i = 0; i < device->wakeup.resources.count; i++) { | 678 | for (i = 0; i < device->wakeup.resources.count; i++) { |
679 | element = &(package->package.elements[i + 2]); | 679 | element = &(package->package.elements[i + 2]); |
680 | if (element->type != ACPI_TYPE_ANY) { | 680 | if (element->type != ACPI_TYPE_LOCAL_REFERENCE) |
681 | return AE_BAD_DATA; | 681 | return AE_BAD_DATA; |
682 | } | ||
683 | 682 | ||
684 | device->wakeup.resources.handles[i] = element->reference.handle; | 683 | device->wakeup.resources.handles[i] = element->reference.handle; |
685 | } | 684 | } |
@@ -692,6 +691,9 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
692 | acpi_status status = 0; | 691 | acpi_status status = 0; |
693 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 692 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
694 | union acpi_object *package = NULL; | 693 | union acpi_object *package = NULL; |
694 | union acpi_object in_arg[3]; | ||
695 | struct acpi_object_list arg_list = { 3, in_arg }; | ||
696 | acpi_status psw_status = AE_OK; | ||
695 | 697 | ||
696 | struct acpi_device_id button_device_ids[] = { | 698 | struct acpi_device_id button_device_ids[] = { |
697 | {"PNP0C0D", 0}, | 699 | {"PNP0C0D", 0}, |
@@ -700,7 +702,6 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
700 | {"", 0}, | 702 | {"", 0}, |
701 | }; | 703 | }; |
702 | 704 | ||
703 | |||
704 | /* _PRW */ | 705 | /* _PRW */ |
705 | status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); | 706 | status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); |
706 | if (ACPI_FAILURE(status)) { | 707 | if (ACPI_FAILURE(status)) { |
@@ -718,6 +719,45 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | |||
718 | kfree(buffer.pointer); | 719 | kfree(buffer.pointer); |
719 | 720 | ||
720 | device->wakeup.flags.valid = 1; | 721 | device->wakeup.flags.valid = 1; |
722 | /* Call _PSW/_DSW object to disable its ability to wake the sleeping | ||
723 | * system for the ACPI device with the _PRW object. | ||
724 | * The _PSW object is depreciated in ACPI 3.0 and is replaced by _DSW. | ||
725 | * So it is necessary to call _DSW object first. Only when it is not | ||
726 | * present will the _PSW object used. | ||
727 | */ | ||
728 | /* | ||
729 | * Three agruments are needed for the _DSW object. | ||
730 | * Argument 0: enable/disable the wake capabilities | ||
731 | * When _DSW object is called to disable the wake capabilities, maybe | ||
732 | * the first argument is filled. The value of the other two agruments | ||
733 | * is meaningless. | ||
734 | */ | ||
735 | in_arg[0].type = ACPI_TYPE_INTEGER; | ||
736 | in_arg[0].integer.value = 0; | ||
737 | in_arg[1].type = ACPI_TYPE_INTEGER; | ||
738 | in_arg[1].integer.value = 0; | ||
739 | in_arg[2].type = ACPI_TYPE_INTEGER; | ||
740 | in_arg[2].integer.value = 0; | ||
741 | psw_status = acpi_evaluate_object(device->handle, "_DSW", | ||
742 | &arg_list, NULL); | ||
743 | if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) | ||
744 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in evaluate _DSW\n")); | ||
745 | /* | ||
746 | * When the _DSW object is not present, OSPM will call _PSW object. | ||
747 | */ | ||
748 | if (psw_status == AE_NOT_FOUND) { | ||
749 | /* | ||
750 | * Only one agruments is required for the _PSW object. | ||
751 | * agrument 0: enable/disable the wake capabilities | ||
752 | */ | ||
753 | arg_list.count = 1; | ||
754 | in_arg[0].integer.value = 0; | ||
755 | psw_status = acpi_evaluate_object(device->handle, "_PSW", | ||
756 | &arg_list, NULL); | ||
757 | if (ACPI_FAILURE(psw_status) && (psw_status != AE_NOT_FOUND)) | ||
758 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "error in " | ||
759 | "evaluate _PSW\n")); | ||
760 | } | ||
721 | /* Power button, Lid switch always enable wakeup */ | 761 | /* Power button, Lid switch always enable wakeup */ |
722 | if (!acpi_match_device_ids(device, button_device_ids)) | 762 | if (!acpi_match_device_ids(device, button_device_ids)) |
723 | device->wakeup.flags.run_wake = 1; | 763 | device->wakeup.flags.run_wake = 1; |
@@ -882,10 +922,7 @@ static void acpi_device_get_busid(struct acpi_device *device, | |||
882 | static int | 922 | static int |
883 | acpi_video_bus_match(struct acpi_device *device) | 923 | acpi_video_bus_match(struct acpi_device *device) |
884 | { | 924 | { |
885 | acpi_handle h_dummy1; | 925 | acpi_handle h_dummy; |
886 | acpi_handle h_dummy2; | ||
887 | acpi_handle h_dummy3; | ||
888 | |||
889 | 926 | ||
890 | if (!device) | 927 | if (!device) |
891 | return -EINVAL; | 928 | return -EINVAL; |
@@ -895,18 +932,18 @@ acpi_video_bus_match(struct acpi_device *device) | |||
895 | */ | 932 | */ |
896 | 933 | ||
897 | /* Does this device able to support video switching ? */ | 934 | /* Does this device able to support video switching ? */ |
898 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy1)) && | 935 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) && |
899 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy2))) | 936 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) |
900 | return 0; | 937 | return 0; |
901 | 938 | ||
902 | /* Does this device able to retrieve a video ROM ? */ | 939 | /* Does this device able to retrieve a video ROM ? */ |
903 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy1))) | 940 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) |
904 | return 0; | 941 | return 0; |
905 | 942 | ||
906 | /* Does this device able to configure which video head to be POSTed ? */ | 943 | /* Does this device able to configure which video head to be POSTed ? */ |
907 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy1)) && | 944 | if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_VPO", &h_dummy)) && |
908 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy2)) && | 945 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_GPD", &h_dummy)) && |
909 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy3))) | 946 | ACPI_SUCCESS(acpi_get_handle(device->handle, "_SPD", &h_dummy))) |
910 | return 0; | 947 | return 0; |
911 | 948 | ||
912 | return -ENODEV; | 949 | return -ENODEV; |
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 71183eea7906..c3b0cd88d09f 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
@@ -51,7 +51,7 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
51 | } | 51 | } |
52 | 52 | ||
53 | #ifdef CONFIG_SUSPEND | 53 | #ifdef CONFIG_SUSPEND |
54 | static struct platform_suspend_ops acpi_pm_ops; | 54 | static struct platform_suspend_ops acpi_suspend_ops; |
55 | 55 | ||
56 | extern void do_suspend_lowlevel(void); | 56 | extern void do_suspend_lowlevel(void); |
57 | 57 | ||
@@ -65,11 +65,11 @@ static u32 acpi_suspend_states[] = { | |||
65 | static int init_8259A_after_S1; | 65 | static int init_8259A_after_S1; |
66 | 66 | ||
67 | /** | 67 | /** |
68 | * acpi_pm_begin - Set the target system sleep state to the state | 68 | * acpi_suspend_begin - Set the target system sleep state to the state |
69 | * associated with given @pm_state, if supported. | 69 | * associated with given @pm_state, if supported. |
70 | */ | 70 | */ |
71 | 71 | ||
72 | static int acpi_pm_begin(suspend_state_t pm_state) | 72 | static int acpi_suspend_begin(suspend_state_t pm_state) |
73 | { | 73 | { |
74 | u32 acpi_state = acpi_suspend_states[pm_state]; | 74 | u32 acpi_state = acpi_suspend_states[pm_state]; |
75 | int error = 0; | 75 | int error = 0; |
@@ -85,13 +85,13 @@ static int acpi_pm_begin(suspend_state_t pm_state) | |||
85 | } | 85 | } |
86 | 86 | ||
87 | /** | 87 | /** |
88 | * acpi_pm_prepare - Do preliminary suspend work. | 88 | * acpi_suspend_prepare - Do preliminary suspend work. |
89 | * | 89 | * |
90 | * If necessary, set the firmware waking vector and do arch-specific | 90 | * If necessary, set the firmware waking vector and do arch-specific |
91 | * nastiness to get the wakeup code to the waking vector. | 91 | * nastiness to get the wakeup code to the waking vector. |
92 | */ | 92 | */ |
93 | 93 | ||
94 | static int acpi_pm_prepare(void) | 94 | static int acpi_suspend_prepare(void) |
95 | { | 95 | { |
96 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | 96 | int error = acpi_sleep_prepare(acpi_target_sleep_state); |
97 | 97 | ||
@@ -104,7 +104,7 @@ static int acpi_pm_prepare(void) | |||
104 | } | 104 | } |
105 | 105 | ||
106 | /** | 106 | /** |
107 | * acpi_pm_enter - Actually enter a sleep state. | 107 | * acpi_suspend_enter - Actually enter a sleep state. |
108 | * @pm_state: ignored | 108 | * @pm_state: ignored |
109 | * | 109 | * |
110 | * Flush caches and go to sleep. For STR we have to call arch-specific | 110 | * Flush caches and go to sleep. For STR we have to call arch-specific |
@@ -112,7 +112,7 @@ static int acpi_pm_prepare(void) | |||
112 | * It's unfortunate, but it works. Please fix if you're feeling frisky. | 112 | * It's unfortunate, but it works. Please fix if you're feeling frisky. |
113 | */ | 113 | */ |
114 | 114 | ||
115 | static int acpi_pm_enter(suspend_state_t pm_state) | 115 | static int acpi_suspend_enter(suspend_state_t pm_state) |
116 | { | 116 | { |
117 | acpi_status status = AE_OK; | 117 | acpi_status status = AE_OK; |
118 | unsigned long flags = 0; | 118 | unsigned long flags = 0; |
@@ -169,13 +169,13 @@ static int acpi_pm_enter(suspend_state_t pm_state) | |||
169 | } | 169 | } |
170 | 170 | ||
171 | /** | 171 | /** |
172 | * acpi_pm_finish - Instruct the platform to leave a sleep state. | 172 | * acpi_suspend_finish - Instruct the platform to leave a sleep state. |
173 | * | 173 | * |
174 | * This is called after we wake back up (or if entering the sleep state | 174 | * This is called after we wake back up (or if entering the sleep state |
175 | * failed). | 175 | * failed). |
176 | */ | 176 | */ |
177 | 177 | ||
178 | static void acpi_pm_finish(void) | 178 | static void acpi_suspend_finish(void) |
179 | { | 179 | { |
180 | u32 acpi_state = acpi_target_sleep_state; | 180 | u32 acpi_state = acpi_target_sleep_state; |
181 | 181 | ||
@@ -196,19 +196,19 @@ static void acpi_pm_finish(void) | |||
196 | } | 196 | } |
197 | 197 | ||
198 | /** | 198 | /** |
199 | * acpi_pm_end - Finish up suspend sequence. | 199 | * acpi_suspend_end - Finish up suspend sequence. |
200 | */ | 200 | */ |
201 | 201 | ||
202 | static void acpi_pm_end(void) | 202 | static void acpi_suspend_end(void) |
203 | { | 203 | { |
204 | /* | 204 | /* |
205 | * This is necessary in case acpi_pm_finish() is not called during a | 205 | * This is necessary in case acpi_suspend_finish() is not called during a |
206 | * failing transition to a sleep state. | 206 | * failing transition to a sleep state. |
207 | */ | 207 | */ |
208 | acpi_target_sleep_state = ACPI_STATE_S0; | 208 | acpi_target_sleep_state = ACPI_STATE_S0; |
209 | } | 209 | } |
210 | 210 | ||
211 | static int acpi_pm_state_valid(suspend_state_t pm_state) | 211 | static int acpi_suspend_state_valid(suspend_state_t pm_state) |
212 | { | 212 | { |
213 | u32 acpi_state; | 213 | u32 acpi_state; |
214 | 214 | ||
@@ -224,13 +224,13 @@ static int acpi_pm_state_valid(suspend_state_t pm_state) | |||
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
227 | static struct platform_suspend_ops acpi_pm_ops = { | 227 | static struct platform_suspend_ops acpi_suspend_ops = { |
228 | .valid = acpi_pm_state_valid, | 228 | .valid = acpi_suspend_state_valid, |
229 | .begin = acpi_pm_begin, | 229 | .begin = acpi_suspend_begin, |
230 | .prepare = acpi_pm_prepare, | 230 | .prepare = acpi_suspend_prepare, |
231 | .enter = acpi_pm_enter, | 231 | .enter = acpi_suspend_enter, |
232 | .finish = acpi_pm_finish, | 232 | .finish = acpi_suspend_finish, |
233 | .end = acpi_pm_end, | 233 | .end = acpi_suspend_end, |
234 | }; | 234 | }; |
235 | 235 | ||
236 | /* | 236 | /* |
@@ -492,7 +492,7 @@ int __init acpi_sleep_init(void) | |||
492 | } | 492 | } |
493 | } | 493 | } |
494 | 494 | ||
495 | suspend_set_ops(&acpi_pm_ops); | 495 | suspend_set_ops(&acpi_suspend_ops); |
496 | #endif | 496 | #endif |
497 | 497 | ||
498 | #ifdef CONFIG_HIBERNATION | 498 | #ifdef CONFIG_HIBERNATION |
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 002bb33003af..949d4114eb9f 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/tables/tbfind.c b/drivers/acpi/tables/tbfind.c index 058c064948e1..9ca3afc98c80 100644 --- a/drivers/acpi/tables/tbfind.c +++ b/drivers/acpi/tables/tbfind.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -70,12 +70,22 @@ acpi_tb_find_table(char *signature, | |||
70 | { | 70 | { |
71 | acpi_native_uint i; | 71 | acpi_native_uint i; |
72 | acpi_status status; | 72 | acpi_status status; |
73 | struct acpi_table_header header; | ||
73 | 74 | ||
74 | ACPI_FUNCTION_TRACE(tb_find_table); | 75 | ACPI_FUNCTION_TRACE(tb_find_table); |
75 | 76 | ||
77 | /* Normalize the input strings */ | ||
78 | |||
79 | ACPI_MEMSET(&header, 0, sizeof(struct acpi_table_header)); | ||
80 | ACPI_STRNCPY(header.signature, signature, ACPI_NAME_SIZE); | ||
81 | ACPI_STRNCPY(header.oem_id, oem_id, ACPI_OEM_ID_SIZE); | ||
82 | ACPI_STRNCPY(header.oem_table_id, oem_table_id, ACPI_OEM_TABLE_ID_SIZE); | ||
83 | |||
84 | /* Search for the table */ | ||
85 | |||
76 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { | 86 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { |
77 | if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature), | 87 | if (ACPI_MEMCMP(&(acpi_gbl_root_table_list.tables[i].signature), |
78 | signature, ACPI_NAME_SIZE)) { | 88 | header.signature, ACPI_NAME_SIZE)) { |
79 | 89 | ||
80 | /* Not the requested table */ | 90 | /* Not the requested table */ |
81 | 91 | ||
@@ -104,20 +114,24 @@ acpi_tb_find_table(char *signature, | |||
104 | 114 | ||
105 | if (!ACPI_MEMCMP | 115 | if (!ACPI_MEMCMP |
106 | (acpi_gbl_root_table_list.tables[i].pointer->signature, | 116 | (acpi_gbl_root_table_list.tables[i].pointer->signature, |
107 | signature, ACPI_NAME_SIZE) && (!oem_id[0] | 117 | header.signature, ACPI_NAME_SIZE) && (!oem_id[0] |
108 | || | 118 | || |
109 | !ACPI_MEMCMP | 119 | !ACPI_MEMCMP |
110 | (acpi_gbl_root_table_list. | 120 | (acpi_gbl_root_table_list. |
111 | tables[i].pointer->oem_id, | 121 | tables[i].pointer-> |
112 | oem_id, ACPI_OEM_ID_SIZE)) | 122 | oem_id, |
123 | header.oem_id, | ||
124 | ACPI_OEM_ID_SIZE)) | ||
113 | && (!oem_table_id[0] | 125 | && (!oem_table_id[0] |
114 | || !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i]. | 126 | || !ACPI_MEMCMP(acpi_gbl_root_table_list.tables[i]. |
115 | pointer->oem_table_id, oem_table_id, | 127 | pointer->oem_table_id, |
128 | header.oem_table_id, | ||
116 | ACPI_OEM_TABLE_ID_SIZE))) { | 129 | ACPI_OEM_TABLE_ID_SIZE))) { |
117 | *table_index = i; | 130 | *table_index = i; |
118 | 131 | ||
119 | ACPI_DEBUG_PRINT((ACPI_DB_TABLES, | 132 | ACPI_DEBUG_PRINT((ACPI_DB_TABLES, |
120 | "Found table [%4.4s]\n", signature)); | 133 | "Found table [%4.4s]\n", |
134 | header.signature)); | ||
121 | return_ACPI_STATUS(AE_OK); | 135 | return_ACPI_STATUS(AE_OK); |
122 | } | 136 | } |
123 | } | 137 | } |
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index 3bc0c67a9283..402f93e1ff20 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -125,13 +125,20 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, | |||
125 | 125 | ||
126 | /* The table must be either an SSDT or a PSDT or an OEMx */ | 126 | /* The table must be either an SSDT or a PSDT or an OEMx */ |
127 | 127 | ||
128 | if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)) | 128 | if (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)&& |
129 | && | 129 | !ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)&& |
130 | (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) | 130 | strncmp(table_desc->pointer->signature, "OEM", 3)) { |
131 | && (strncmp(table_desc->pointer->signature, "OEM", 3))) { | 131 | /* Check for a printable name */ |
132 | ACPI_ERROR((AE_INFO, | 132 | if (acpi_ut_valid_acpi_name( |
133 | "Table has invalid signature [%4.4s], must be SSDT, PSDT or OEMx", | 133 | *(u32 *) table_desc->pointer->signature)) { |
134 | table_desc->pointer->signature)); | 134 | ACPI_ERROR((AE_INFO, "Table has invalid signature " |
135 | "[%4.4s], must be SSDT or PSDT", | ||
136 | table_desc->pointer->signature)); | ||
137 | } else { | ||
138 | ACPI_ERROR((AE_INFO, "Table has invalid signature " | ||
139 | "(0x%8.8X), must be SSDT or PSDT", | ||
140 | *(u32 *) table_desc->pointer->signature)); | ||
141 | } | ||
135 | return_ACPI_STATUS(AE_BAD_SIGNATURE); | 142 | return_ACPI_STATUS(AE_BAD_SIGNATURE); |
136 | } | 143 | } |
137 | 144 | ||
@@ -162,6 +169,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, | |||
162 | 169 | ||
163 | acpi_tb_delete_table(table_desc); | 170 | acpi_tb_delete_table(table_desc); |
164 | *table_index = i; | 171 | *table_index = i; |
172 | status = AE_ALREADY_EXISTS; | ||
165 | goto release; | 173 | goto release; |
166 | } | 174 | } |
167 | 175 | ||
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c index 010f19652f80..bc019b9b6a68 100644 --- a/drivers/acpi/tables/tbutils.c +++ b/drivers/acpi/tables/tbutils.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -212,7 +212,7 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) | |||
212 | 212 | ||
213 | if (checksum) { | 213 | if (checksum) { |
214 | ACPI_WARNING((AE_INFO, | 214 | ACPI_WARNING((AE_INFO, |
215 | "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", | 215 | "Incorrect checksum in table [%4.4s] - %2.2X, should be %2.2X", |
216 | table->signature, table->checksum, | 216 | table->signature, table->checksum, |
217 | (u8) (table->checksum - checksum))); | 217 | (u8) (table->checksum - checksum))); |
218 | 218 | ||
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index a9e3331fee5d..fb57b93c2495 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c | |||
@@ -6,7 +6,7 @@ | |||
6 | *****************************************************************************/ | 6 | *****************************************************************************/ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * Copyright (C) 2000 - 2007, R. Byron Moore | 9 | * Copyright (C) 2000 - 2008, Intel Corp. |
10 | * All rights reserved. | 10 | * All rights reserved. |
11 | * | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without |
@@ -635,6 +635,95 @@ acpi_status acpi_load_tables(void) | |||
635 | ACPI_EXPORT_SYMBOL(acpi_load_tables) | 635 | ACPI_EXPORT_SYMBOL(acpi_load_tables) |
636 | 636 | ||
637 | 637 | ||
638 | /******************************************************************************* | ||
639 | * | ||
640 | * FUNCTION: acpi_install_table_handler | ||
641 | * | ||
642 | * PARAMETERS: Handler - Table event handler | ||
643 | * Context - Value passed to the handler on each event | ||
644 | * | ||
645 | * RETURN: Status | ||
646 | * | ||
647 | * DESCRIPTION: Install table event handler | ||
648 | * | ||
649 | ******************************************************************************/ | ||
650 | acpi_status | ||
651 | acpi_install_table_handler(acpi_tbl_handler handler, void *context) | ||
652 | { | ||
653 | acpi_status status; | ||
654 | |||
655 | ACPI_FUNCTION_TRACE(acpi_install_table_handler); | ||
656 | |||
657 | if (!handler) { | ||
658 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
659 | } | ||
660 | |||
661 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
662 | if (ACPI_FAILURE(status)) { | ||
663 | return_ACPI_STATUS(status); | ||
664 | } | ||
665 | |||
666 | /* Don't allow more than one handler */ | ||
667 | |||
668 | if (acpi_gbl_table_handler) { | ||
669 | status = AE_ALREADY_EXISTS; | ||
670 | goto cleanup; | ||
671 | } | ||
672 | |||
673 | /* Install the handler */ | ||
674 | |||
675 | acpi_gbl_table_handler = handler; | ||
676 | acpi_gbl_table_handler_context = context; | ||
677 | |||
678 | cleanup: | ||
679 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
680 | return_ACPI_STATUS(status); | ||
681 | } | ||
682 | |||
683 | ACPI_EXPORT_SYMBOL(acpi_install_table_handler) | ||
684 | |||
685 | /******************************************************************************* | ||
686 | * | ||
687 | * FUNCTION: acpi_remove_table_handler | ||
688 | * | ||
689 | * PARAMETERS: Handler - Table event handler that was installed | ||
690 | * previously. | ||
691 | * | ||
692 | * RETURN: Status | ||
693 | * | ||
694 | * DESCRIPTION: Remove table event handler | ||
695 | * | ||
696 | ******************************************************************************/ | ||
697 | acpi_status acpi_remove_table_handler(acpi_tbl_handler handler) | ||
698 | { | ||
699 | acpi_status status; | ||
700 | |||
701 | ACPI_FUNCTION_TRACE(acpi_remove_table_handler); | ||
702 | |||
703 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
704 | if (ACPI_FAILURE(status)) { | ||
705 | return_ACPI_STATUS(status); | ||
706 | } | ||
707 | |||
708 | /* Make sure that the installed handler is the same */ | ||
709 | |||
710 | if (!handler || handler != acpi_gbl_table_handler) { | ||
711 | status = AE_BAD_PARAMETER; | ||
712 | goto cleanup; | ||
713 | } | ||
714 | |||
715 | /* Remove the handler */ | ||
716 | |||
717 | acpi_gbl_table_handler = NULL; | ||
718 | |||
719 | cleanup: | ||
720 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
721 | return_ACPI_STATUS(status); | ||
722 | } | ||
723 | |||
724 | ACPI_EXPORT_SYMBOL(acpi_remove_table_handler) | ||
725 | |||
726 | |||
638 | static int __init acpi_no_auto_ssdt_setup(char *s) { | 727 | static int __init acpi_no_auto_ssdt_setup(char *s) { |
639 | 728 | ||
640 | printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); | 729 | printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n"); |
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c index 9ecb4b6c1e7d..b8c0dfa084f6 100644 --- a/drivers/acpi/tables/tbxfroot.c +++ b/drivers/acpi/tables/tbxfroot.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 0815ac3ae3d6..504385b1f211 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -889,10 +889,15 @@ static void acpi_thermal_check(void *data) | |||
889 | static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf) | 889 | static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf) |
890 | { | 890 | { |
891 | struct acpi_thermal *tz = thermal->devdata; | 891 | struct acpi_thermal *tz = thermal->devdata; |
892 | int result; | ||
892 | 893 | ||
893 | if (!tz) | 894 | if (!tz) |
894 | return -EINVAL; | 895 | return -EINVAL; |
895 | 896 | ||
897 | result = acpi_thermal_get_temperature(tz); | ||
898 | if (result) | ||
899 | return result; | ||
900 | |||
896 | return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature)); | 901 | return sprintf(buf, "%ld\n", KELVIN_TO_MILLICELSIUS(tz->temperature)); |
897 | } | 902 | } |
898 | 903 | ||
@@ -1017,6 +1022,18 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal, | |||
1017 | return -EINVAL; | 1022 | return -EINVAL; |
1018 | } | 1023 | } |
1019 | 1024 | ||
1025 | static int thermal_get_crit_temp(struct thermal_zone_device *thermal, | ||
1026 | unsigned long *temperature) { | ||
1027 | struct acpi_thermal *tz = thermal->devdata; | ||
1028 | |||
1029 | if (tz->trips.critical.flags.valid) { | ||
1030 | *temperature = KELVIN_TO_MILLICELSIUS( | ||
1031 | tz->trips.critical.temperature); | ||
1032 | return 0; | ||
1033 | } else | ||
1034 | return -EINVAL; | ||
1035 | } | ||
1036 | |||
1020 | typedef int (*cb)(struct thermal_zone_device *, int, | 1037 | typedef int (*cb)(struct thermal_zone_device *, int, |
1021 | struct thermal_cooling_device *); | 1038 | struct thermal_cooling_device *); |
1022 | static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, | 1039 | static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, |
@@ -1108,6 +1125,7 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = { | |||
1108 | .set_mode = thermal_set_mode, | 1125 | .set_mode = thermal_set_mode, |
1109 | .get_trip_type = thermal_get_trip_type, | 1126 | .get_trip_type = thermal_get_trip_type, |
1110 | .get_trip_temp = thermal_get_trip_temp, | 1127 | .get_trip_temp = thermal_get_trip_temp, |
1128 | .get_crit_temp = thermal_get_crit_temp, | ||
1111 | }; | 1129 | }; |
1112 | 1130 | ||
1113 | static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) | 1131 | static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) |
@@ -1128,7 +1146,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) | |||
1128 | 1146 | ||
1129 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && | 1147 | for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && |
1130 | tz->trips.active[i].flags.valid; i++, trips++); | 1148 | tz->trips.active[i].flags.valid; i++, trips++); |
1131 | tz->thermal_zone = thermal_zone_device_register("ACPI thermal zone", | 1149 | tz->thermal_zone = thermal_zone_device_register("acpitz", |
1132 | trips, tz, &acpi_thermal_zone_ops); | 1150 | trips, tz, &acpi_thermal_zone_ops); |
1133 | if (IS_ERR(tz->thermal_zone)) | 1151 | if (IS_ERR(tz->thermal_zone)) |
1134 | return -ENODEV; | 1152 | return -ENODEV; |
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c index 6e56d5f7c43a..ede084829a70 100644 --- a/drivers/acpi/utilities/utalloc.c +++ b/drivers/acpi/utilities/utalloc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -147,7 +147,7 @@ acpi_status acpi_ut_delete_caches(void) | |||
147 | 147 | ||
148 | if (acpi_gbl_display_final_mem_stats) { | 148 | if (acpi_gbl_display_final_mem_stats) { |
149 | ACPI_STRCPY(buffer, "MEMORY"); | 149 | ACPI_STRCPY(buffer, "MEMORY"); |
150 | acpi_db_display_statistics(buffer); | 150 | (void)acpi_db_display_statistics(buffer); |
151 | } | 151 | } |
152 | #endif | 152 | #endif |
153 | 153 | ||
diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c index 285a0f531760..245fa80cf600 100644 --- a/drivers/acpi/utilities/utcache.c +++ b/drivers/acpi/utilities/utcache.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c index 879eaa10d3ae..655c290aca7b 100644 --- a/drivers/acpi/utilities/utcopy.c +++ b/drivers/acpi/utilities/utcopy.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -43,6 +43,8 @@ | |||
43 | 43 | ||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include <acpi/amlcode.h> | 45 | #include <acpi/amlcode.h> |
46 | #include <acpi/acnamesp.h> | ||
47 | |||
46 | 48 | ||
47 | #define _COMPONENT ACPI_UTILITIES | 49 | #define _COMPONENT ACPI_UTILITIES |
48 | ACPI_MODULE_NAME("utcopy") | 50 | ACPI_MODULE_NAME("utcopy") |
@@ -172,22 +174,21 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, | |||
172 | 174 | ||
173 | case ACPI_TYPE_LOCAL_REFERENCE: | 175 | case ACPI_TYPE_LOCAL_REFERENCE: |
174 | 176 | ||
175 | /* | 177 | /* This is an object reference. */ |
176 | * This is an object reference. Attempt to dereference it. | 178 | |
177 | */ | ||
178 | switch (internal_object->reference.opcode) { | 179 | switch (internal_object->reference.opcode) { |
179 | case AML_INT_NAMEPATH_OP: | 180 | case AML_INT_NAMEPATH_OP: |
180 | 181 | ||
181 | /* For namepath, return the object handle ("reference") */ | 182 | /* For namepath, return the object handle ("reference") */ |
182 | 183 | ||
183 | default: | 184 | default: |
184 | /* | 185 | |
185 | * Use the object type of "Any" to indicate a reference | 186 | /* We are referring to the namespace node */ |
186 | * to object containing a handle to an ACPI named object. | 187 | |
187 | */ | ||
188 | external_object->type = ACPI_TYPE_ANY; | ||
189 | external_object->reference.handle = | 188 | external_object->reference.handle = |
190 | internal_object->reference.node; | 189 | internal_object->reference.node; |
190 | external_object->reference.actual_type = | ||
191 | acpi_ns_get_type(internal_object->reference.node); | ||
191 | break; | 192 | break; |
192 | } | 193 | } |
193 | break; | 194 | break; |
@@ -215,6 +216,11 @@ acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, | |||
215 | /* | 216 | /* |
216 | * There is no corresponding external object type | 217 | * There is no corresponding external object type |
217 | */ | 218 | */ |
219 | ACPI_ERROR((AE_INFO, | ||
220 | "Unsupported object type, cannot convert to external object: %s", | ||
221 | acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE | ||
222 | (internal_object)))); | ||
223 | |||
218 | return_ACPI_STATUS(AE_SUPPORT); | 224 | return_ACPI_STATUS(AE_SUPPORT); |
219 | } | 225 | } |
220 | 226 | ||
@@ -455,6 +461,7 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, | |||
455 | case ACPI_TYPE_STRING: | 461 | case ACPI_TYPE_STRING: |
456 | case ACPI_TYPE_BUFFER: | 462 | case ACPI_TYPE_BUFFER: |
457 | case ACPI_TYPE_INTEGER: | 463 | case ACPI_TYPE_INTEGER: |
464 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
458 | 465 | ||
459 | internal_object = acpi_ut_create_internal_object((u8) | 466 | internal_object = acpi_ut_create_internal_object((u8) |
460 | external_object-> | 467 | external_object-> |
@@ -464,9 +471,18 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, | |||
464 | } | 471 | } |
465 | break; | 472 | break; |
466 | 473 | ||
474 | case ACPI_TYPE_ANY: /* This is the case for a NULL object */ | ||
475 | |||
476 | *ret_internal_object = NULL; | ||
477 | return_ACPI_STATUS(AE_OK); | ||
478 | |||
467 | default: | 479 | default: |
468 | /* All other types are not supported */ | 480 | /* All other types are not supported */ |
469 | 481 | ||
482 | ACPI_ERROR((AE_INFO, | ||
483 | "Unsupported object type, cannot convert to internal object: %s", | ||
484 | acpi_ut_get_type_name(external_object->type))); | ||
485 | |||
470 | return_ACPI_STATUS(AE_SUPPORT); | 486 | return_ACPI_STATUS(AE_SUPPORT); |
471 | } | 487 | } |
472 | 488 | ||
@@ -502,6 +518,10 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, | |||
502 | external_object->buffer.length); | 518 | external_object->buffer.length); |
503 | 519 | ||
504 | internal_object->buffer.length = external_object->buffer.length; | 520 | internal_object->buffer.length = external_object->buffer.length; |
521 | |||
522 | /* Mark buffer data valid */ | ||
523 | |||
524 | internal_object->buffer.flags |= AOPOBJ_DATA_VALID; | ||
505 | break; | 525 | break; |
506 | 526 | ||
507 | case ACPI_TYPE_INTEGER: | 527 | case ACPI_TYPE_INTEGER: |
@@ -509,6 +529,15 @@ acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, | |||
509 | internal_object->integer.value = external_object->integer.value; | 529 | internal_object->integer.value = external_object->integer.value; |
510 | break; | 530 | break; |
511 | 531 | ||
532 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
533 | |||
534 | /* TBD: should validate incoming handle */ | ||
535 | |||
536 | internal_object->reference.opcode = AML_INT_NAMEPATH_OP; | ||
537 | internal_object->reference.node = | ||
538 | external_object->reference.handle; | ||
539 | break; | ||
540 | |||
512 | default: | 541 | default: |
513 | /* Other types can't get here */ | 542 | /* Other types can't get here */ |
514 | break; | 543 | break; |
@@ -570,13 +599,17 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, | |||
570 | 599 | ||
571 | /* Truncate package and delete it */ | 600 | /* Truncate package and delete it */ |
572 | 601 | ||
573 | package_object->package.count = i; | 602 | package_object->package.count = (u32) i; |
574 | package_elements[i] = NULL; | 603 | package_elements[i] = NULL; |
575 | acpi_ut_remove_reference(package_object); | 604 | acpi_ut_remove_reference(package_object); |
576 | return_ACPI_STATUS(status); | 605 | return_ACPI_STATUS(status); |
577 | } | 606 | } |
578 | } | 607 | } |
579 | 608 | ||
609 | /* Mark package data valid */ | ||
610 | |||
611 | package_object->package.flags |= AOPOBJ_DATA_VALID; | ||
612 | |||
580 | *internal_object = package_object; | 613 | *internal_object = package_object; |
581 | return_ACPI_STATUS(status); | 614 | return_ACPI_STATUS(status); |
582 | } | 615 | } |
@@ -709,7 +742,15 @@ acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, | |||
709 | /* | 742 | /* |
710 | * We copied the reference object, so we now must add a reference | 743 | * We copied the reference object, so we now must add a reference |
711 | * to the object pointed to by the reference | 744 | * to the object pointed to by the reference |
745 | * | ||
746 | * DDBHandle reference (from Load/load_table is a special reference, | ||
747 | * it's Reference.Object is the table index, so does not need to | ||
748 | * increase the reference count | ||
712 | */ | 749 | */ |
750 | if (source_desc->reference.opcode == AML_LOAD_OP) { | ||
751 | break; | ||
752 | } | ||
753 | |||
713 | acpi_ut_add_reference(source_desc->reference.object); | 754 | acpi_ut_add_reference(source_desc->reference.object); |
714 | break; | 755 | break; |
715 | 756 | ||
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c index 7361204b1eef..f938f465efa4 100644 --- a/drivers/acpi/utilities/utdebug.c +++ b/drivers/acpi/utilities/utdebug.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -68,9 +68,9 @@ static const char *acpi_ut_trim_function_name(const char *function_name); | |||
68 | 68 | ||
69 | void acpi_ut_init_stack_ptr_trace(void) | 69 | void acpi_ut_init_stack_ptr_trace(void) |
70 | { | 70 | { |
71 | u32 current_sp; | 71 | acpi_size current_sp; |
72 | 72 | ||
73 | acpi_gbl_entry_stack_pointer = ACPI_PTR_DIFF(¤t_sp, NULL); | 73 | acpi_gbl_entry_stack_pointer = ¤t_sp; |
74 | } | 74 | } |
75 | 75 | ||
76 | /******************************************************************************* | 76 | /******************************************************************************* |
@@ -89,10 +89,8 @@ void acpi_ut_track_stack_ptr(void) | |||
89 | { | 89 | { |
90 | acpi_size current_sp; | 90 | acpi_size current_sp; |
91 | 91 | ||
92 | current_sp = ACPI_PTR_DIFF(¤t_sp, NULL); | 92 | if (¤t_sp < acpi_gbl_lowest_stack_pointer) { |
93 | 93 | acpi_gbl_lowest_stack_pointer = ¤t_sp; | |
94 | if (current_sp < acpi_gbl_lowest_stack_pointer) { | ||
95 | acpi_gbl_lowest_stack_pointer = current_sp; | ||
96 | } | 94 | } |
97 | 95 | ||
98 | if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) { | 96 | if (acpi_gbl_nesting_level > acpi_gbl_deepest_nesting) { |
@@ -203,6 +201,7 @@ acpi_ut_debug_print(u32 requested_debug_level, | |||
203 | 201 | ||
204 | va_start(args, format); | 202 | va_start(args, format); |
205 | acpi_os_vprintf(format, args); | 203 | acpi_os_vprintf(format, args); |
204 | va_end(args); | ||
206 | } | 205 | } |
207 | 206 | ||
208 | ACPI_EXPORT_SYMBOL(acpi_ut_debug_print) | 207 | ACPI_EXPORT_SYMBOL(acpi_ut_debug_print) |
@@ -240,6 +239,7 @@ acpi_ut_debug_print_raw(u32 requested_debug_level, | |||
240 | 239 | ||
241 | va_start(args, format); | 240 | va_start(args, format); |
242 | acpi_os_vprintf(format, args); | 241 | acpi_os_vprintf(format, args); |
242 | va_end(args); | ||
243 | } | 243 | } |
244 | 244 | ||
245 | ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw) | 245 | ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw) |
@@ -524,6 +524,11 @@ void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) | |||
524 | u32 temp32; | 524 | u32 temp32; |
525 | u8 buf_char; | 525 | u8 buf_char; |
526 | 526 | ||
527 | if (!buffer) { | ||
528 | acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n"); | ||
529 | return; | ||
530 | } | ||
531 | |||
527 | if ((count < 4) || (count & 0x01)) { | 532 | if ((count < 4) || (count & 0x01)) { |
528 | display = DB_BYTE_DISPLAY; | 533 | display = DB_BYTE_DISPLAY; |
529 | } | 534 | } |
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c index f777cebdc46d..1fbc35139e84 100644 --- a/drivers/acpi/utilities/utdelete.c +++ b/drivers/acpi/utilities/utdelete.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -158,7 +158,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) | |||
158 | "***** Mutex %p, OS Mutex %p\n", | 158 | "***** Mutex %p, OS Mutex %p\n", |
159 | object, object->mutex.os_mutex)); | 159 | object, object->mutex.os_mutex)); |
160 | 160 | ||
161 | if (object->mutex.os_mutex == acpi_gbl_global_lock_mutex) { | 161 | if (object == acpi_gbl_global_lock_mutex) { |
162 | 162 | ||
163 | /* Global Lock has extra semaphore */ | 163 | /* Global Lock has extra semaphore */ |
164 | 164 | ||
@@ -252,6 +252,17 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) | |||
252 | } | 252 | } |
253 | break; | 253 | break; |
254 | 254 | ||
255 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
256 | |||
257 | ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, | ||
258 | "***** Bank Field %p\n", object)); | ||
259 | |||
260 | second_desc = acpi_ns_get_secondary_object(object); | ||
261 | if (second_desc) { | ||
262 | acpi_ut_delete_object_desc(second_desc); | ||
263 | } | ||
264 | break; | ||
265 | |||
255 | default: | 266 | default: |
256 | break; | 267 | break; |
257 | } | 268 | } |
@@ -524,10 +535,12 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) | |||
524 | 535 | ||
525 | case ACPI_TYPE_LOCAL_REFERENCE: | 536 | case ACPI_TYPE_LOCAL_REFERENCE: |
526 | /* | 537 | /* |
527 | * The target of an Index (a package, string, or buffer) must track | 538 | * The target of an Index (a package, string, or buffer) or a named |
528 | * changes to the ref count of the index. | 539 | * reference must track changes to the ref count of the index or |
540 | * target object. | ||
529 | */ | 541 | */ |
530 | if (object->reference.opcode == AML_INDEX_OP) { | 542 | if ((object->reference.opcode == AML_INDEX_OP) || |
543 | (object->reference.opcode == AML_INT_NAMEPATH_OP)) { | ||
531 | next_object = object->reference.object; | 544 | next_object = object->reference.object; |
532 | } | 545 | } |
533 | break; | 546 | break; |
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 0042b7e78b26..05e61be267d5 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 630c9a2c5b7b..a6e71b801d2d 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -602,6 +602,48 @@ char *acpi_ut_get_mutex_name(u32 mutex_id) | |||
602 | 602 | ||
603 | return (acpi_gbl_mutex_names[mutex_id]); | 603 | return (acpi_gbl_mutex_names[mutex_id]); |
604 | } | 604 | } |
605 | |||
606 | /******************************************************************************* | ||
607 | * | ||
608 | * FUNCTION: acpi_ut_get_notify_name | ||
609 | * | ||
610 | * PARAMETERS: notify_value - Value from the Notify() request | ||
611 | * | ||
612 | * RETURN: String corresponding to the Notify Value. | ||
613 | * | ||
614 | * DESCRIPTION: Translate a Notify Value to a notify namestring. | ||
615 | * | ||
616 | ******************************************************************************/ | ||
617 | |||
618 | /* Names for Notify() values, used for debug output */ | ||
619 | |||
620 | static const char *acpi_gbl_notify_value_names[] = { | ||
621 | "Bus Check", | ||
622 | "Device Check", | ||
623 | "Device Wake", | ||
624 | "Eject Request", | ||
625 | "Device Check Light", | ||
626 | "Frequency Mismatch", | ||
627 | "Bus Mode Mismatch", | ||
628 | "Power Fault", | ||
629 | "Capabilities Check", | ||
630 | "Device PLD Check", | ||
631 | "Reserved", | ||
632 | "System Locality Update" | ||
633 | }; | ||
634 | |||
635 | const char *acpi_ut_get_notify_name(u32 notify_value) | ||
636 | { | ||
637 | |||
638 | if (notify_value <= ACPI_NOTIFY_MAX) { | ||
639 | return (acpi_gbl_notify_value_names[notify_value]); | ||
640 | } else if (notify_value <= ACPI_MAX_SYS_NOTIFY) { | ||
641 | return ("Reserved"); | ||
642 | } else { /* Greater or equal to 0x80 */ | ||
643 | |||
644 | return ("**Device Specific**"); | ||
645 | } | ||
646 | } | ||
605 | #endif | 647 | #endif |
606 | 648 | ||
607 | /******************************************************************************* | 649 | /******************************************************************************* |
@@ -675,12 +717,13 @@ void acpi_ut_init_globals(void) | |||
675 | acpi_gbl_gpe_fadt_blocks[0] = NULL; | 717 | acpi_gbl_gpe_fadt_blocks[0] = NULL; |
676 | acpi_gbl_gpe_fadt_blocks[1] = NULL; | 718 | acpi_gbl_gpe_fadt_blocks[1] = NULL; |
677 | 719 | ||
678 | /* Global notify handlers */ | 720 | /* Global handlers */ |
679 | 721 | ||
680 | acpi_gbl_system_notify.handler = NULL; | 722 | acpi_gbl_system_notify.handler = NULL; |
681 | acpi_gbl_device_notify.handler = NULL; | 723 | acpi_gbl_device_notify.handler = NULL; |
682 | acpi_gbl_exception_handler = NULL; | 724 | acpi_gbl_exception_handler = NULL; |
683 | acpi_gbl_init_handler = NULL; | 725 | acpi_gbl_init_handler = NULL; |
726 | acpi_gbl_table_handler = NULL; | ||
684 | 727 | ||
685 | /* Global Lock support */ | 728 | /* Global Lock support */ |
686 | 729 | ||
@@ -722,7 +765,7 @@ void acpi_ut_init_globals(void) | |||
722 | acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST; | 765 | acpi_gbl_root_node_struct.flags = ANOBJ_END_OF_PEER_LIST; |
723 | 766 | ||
724 | #ifdef ACPI_DEBUG_OUTPUT | 767 | #ifdef ACPI_DEBUG_OUTPUT |
725 | acpi_gbl_lowest_stack_pointer = ACPI_SIZE_MAX; | 768 | acpi_gbl_lowest_stack_pointer = ACPI_CAST_PTR(acpi_size, ACPI_SIZE_MAX); |
726 | #endif | 769 | #endif |
727 | 770 | ||
728 | #ifdef ACPI_DBG_TRACK_ALLOCATIONS | 771 | #ifdef ACPI_DBG_TRACK_ALLOCATIONS |
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c index ad3c0d0a5cf8..cae515fc02d3 100644 --- a/drivers/acpi/utilities/utinit.c +++ b/drivers/acpi/utilities/utinit.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -125,9 +125,12 @@ void acpi_ut_subsystem_shutdown(void) | |||
125 | acpi_gbl_startup_flags = 0; | 125 | acpi_gbl_startup_flags = 0; |
126 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); | 126 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); |
127 | 127 | ||
128 | #ifndef ACPI_ASL_COMPILER | ||
129 | |||
128 | /* Close the acpi_event Handling */ | 130 | /* Close the acpi_event Handling */ |
129 | 131 | ||
130 | acpi_ev_terminate(); | 132 | acpi_ev_terminate(); |
133 | #endif | ||
131 | 134 | ||
132 | /* Close the Namespace */ | 135 | /* Close the Namespace */ |
133 | 136 | ||
diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c index 0c56a0d20b29..c927324fdd26 100644 --- a/drivers/acpi/utilities/utmath.c +++ b/drivers/acpi/utilities/utmath.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -276,7 +276,7 @@ acpi_ut_short_divide(acpi_integer in_dividend, | |||
276 | *out_quotient = in_dividend / divisor; | 276 | *out_quotient = in_dividend / divisor; |
277 | } | 277 | } |
278 | if (out_remainder) { | 278 | if (out_remainder) { |
279 | *out_remainder = (u32) in_dividend % divisor; | 279 | *out_remainder = (u32) (in_dividend % divisor); |
280 | } | 280 | } |
281 | 281 | ||
282 | return_ACPI_STATUS(AE_OK); | 282 | return_ACPI_STATUS(AE_OK); |
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c index 2d19f71e9cfa..e4ba7192cd15 100644 --- a/drivers/acpi/utilities/utmisc.c +++ b/drivers/acpi/utilities/utmisc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -1033,6 +1033,7 @@ acpi_ut_error(char *module_name, u32 line_number, char *format, ...) | |||
1033 | va_start(args, format); | 1033 | va_start(args, format); |
1034 | acpi_os_vprintf(format, args); | 1034 | acpi_os_vprintf(format, args); |
1035 | acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); | 1035 | acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); |
1036 | va_end(args); | ||
1036 | } | 1037 | } |
1037 | 1038 | ||
1038 | void ACPI_INTERNAL_VAR_XFACE | 1039 | void ACPI_INTERNAL_VAR_XFACE |
@@ -1061,6 +1062,8 @@ acpi_ut_warning(char *module_name, u32 line_number, char *format, ...) | |||
1061 | va_start(args, format); | 1062 | va_start(args, format); |
1062 | acpi_os_vprintf(format, args); | 1063 | acpi_os_vprintf(format, args); |
1063 | acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); | 1064 | acpi_os_printf(" [%X]\n", ACPI_CA_VERSION); |
1065 | va_end(args); | ||
1066 | va_end(args); | ||
1064 | } | 1067 | } |
1065 | 1068 | ||
1066 | void ACPI_INTERNAL_VAR_XFACE | 1069 | void ACPI_INTERNAL_VAR_XFACE |
@@ -1077,4 +1080,5 @@ acpi_ut_info(char *module_name, u32 line_number, char *format, ...) | |||
1077 | va_start(args, format); | 1080 | va_start(args, format); |
1078 | acpi_os_vprintf(format, args); | 1081 | acpi_os_vprintf(format, args); |
1079 | acpi_os_printf("\n"); | 1082 | acpi_os_printf("\n"); |
1083 | va_end(args); | ||
1080 | } | 1084 | } |
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c index 4820bc86d1f5..f7d602b1a894 100644 --- a/drivers/acpi/utilities/utmutex.c +++ b/drivers/acpi/utilities/utmutex.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c index e08b3fa6639f..e68466de8044 100644 --- a/drivers/acpi/utilities/utobject.c +++ b/drivers/acpi/utilities/utobject.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -107,6 +107,7 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name, | |||
107 | switch (type) { | 107 | switch (type) { |
108 | case ACPI_TYPE_REGION: | 108 | case ACPI_TYPE_REGION: |
109 | case ACPI_TYPE_BUFFER_FIELD: | 109 | case ACPI_TYPE_BUFFER_FIELD: |
110 | case ACPI_TYPE_LOCAL_BANK_FIELD: | ||
110 | 111 | ||
111 | /* These types require a secondary object */ | 112 | /* These types require a secondary object */ |
112 | 113 | ||
@@ -469,9 +470,8 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, | |||
469 | case ACPI_TYPE_PROCESSOR: | 470 | case ACPI_TYPE_PROCESSOR: |
470 | case ACPI_TYPE_POWER: | 471 | case ACPI_TYPE_POWER: |
471 | 472 | ||
472 | /* | 473 | /* No extra data for these types */ |
473 | * No extra data for these types | 474 | |
474 | */ | ||
475 | break; | 475 | break; |
476 | 476 | ||
477 | case ACPI_TYPE_LOCAL_REFERENCE: | 477 | case ACPI_TYPE_LOCAL_REFERENCE: |
diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c index b630ee137ee1..c3e3e1308edc 100644 --- a/drivers/acpi/utilities/utresrc.c +++ b/drivers/acpi/utilities/utresrc.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c index edcaafad0a31..63a6d3d77d88 100644 --- a/drivers/acpi/utilities/utstate.c +++ b/drivers/acpi/utilities/utstate.c | |||
@@ -5,7 +5,7 @@ | |||
5 | ******************************************************************************/ | 5 | ******************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c index 2d496918b3cd..f8bdadf3c32f 100644 --- a/drivers/acpi/utilities/utxface.c +++ b/drivers/acpi/utilities/utxface.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -49,6 +49,7 @@ | |||
49 | #define _COMPONENT ACPI_UTILITIES | 49 | #define _COMPONENT ACPI_UTILITIES |
50 | ACPI_MODULE_NAME("utxface") | 50 | ACPI_MODULE_NAME("utxface") |
51 | 51 | ||
52 | #ifndef ACPI_ASL_COMPILER | ||
52 | /******************************************************************************* | 53 | /******************************************************************************* |
53 | * | 54 | * |
54 | * FUNCTION: acpi_initialize_subsystem | 55 | * FUNCTION: acpi_initialize_subsystem |
@@ -192,24 +193,6 @@ acpi_status acpi_enable_subsystem(u32 flags) | |||
192 | } | 193 | } |
193 | } | 194 | } |
194 | 195 | ||
195 | /* | ||
196 | * Complete the GPE initialization for the GPE blocks defined in the FADT | ||
197 | * (GPE block 0 and 1). | ||
198 | * | ||
199 | * Note1: This is where the _PRW methods are executed for the GPEs. These | ||
200 | * methods can only be executed after the SCI and Global Lock handlers are | ||
201 | * installed and initialized. | ||
202 | * | ||
203 | * Note2: Currently, there seems to be no need to run the _REG methods | ||
204 | * before execution of the _PRW methods and enabling of the GPEs. | ||
205 | */ | ||
206 | if (!(flags & ACPI_NO_EVENT_INIT)) { | ||
207 | status = acpi_ev_install_fadt_gpes(); | ||
208 | if (ACPI_FAILURE(status)) { | ||
209 | return (status); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | return_ACPI_STATUS(status); | 196 | return_ACPI_STATUS(status); |
214 | } | 197 | } |
215 | 198 | ||
@@ -280,6 +263,23 @@ acpi_status acpi_initialize_objects(u32 flags) | |||
280 | } | 263 | } |
281 | 264 | ||
282 | /* | 265 | /* |
266 | * Complete the GPE initialization for the GPE blocks defined in the FADT | ||
267 | * (GPE block 0 and 1). | ||
268 | * | ||
269 | * Note1: This is where the _PRW methods are executed for the GPEs. These | ||
270 | * methods can only be executed after the SCI and Global Lock handlers are | ||
271 | * installed and initialized. | ||
272 | * | ||
273 | * Note2: Currently, there seems to be no need to run the _REG methods | ||
274 | * before execution of the _PRW methods and enabling of the GPEs. | ||
275 | */ | ||
276 | if (!(flags & ACPI_NO_EVENT_INIT)) { | ||
277 | status = acpi_ev_install_fadt_gpes(); | ||
278 | if (ACPI_FAILURE(status)) | ||
279 | return (status); | ||
280 | } | ||
281 | |||
282 | /* | ||
283 | * Empty the caches (delete the cached objects) on the assumption that | 283 | * Empty the caches (delete the cached objects) on the assumption that |
284 | * the table load filled them up more than they will be at runtime -- | 284 | * the table load filled them up more than they will be at runtime -- |
285 | * thus wasting non-paged memory. | 285 | * thus wasting non-paged memory. |
@@ -292,6 +292,7 @@ acpi_status acpi_initialize_objects(u32 flags) | |||
292 | 292 | ||
293 | ACPI_EXPORT_SYMBOL(acpi_initialize_objects) | 293 | ACPI_EXPORT_SYMBOL(acpi_initialize_objects) |
294 | 294 | ||
295 | #endif | ||
295 | /******************************************************************************* | 296 | /******************************************************************************* |
296 | * | 297 | * |
297 | * FUNCTION: acpi_terminate | 298 | * FUNCTION: acpi_terminate |
@@ -335,6 +336,7 @@ acpi_status acpi_terminate(void) | |||
335 | } | 336 | } |
336 | 337 | ||
337 | ACPI_EXPORT_SYMBOL(acpi_terminate) | 338 | ACPI_EXPORT_SYMBOL(acpi_terminate) |
339 | #ifndef ACPI_ASL_COMPILER | ||
338 | #ifdef ACPI_FUTURE_USAGE | 340 | #ifdef ACPI_FUTURE_USAGE |
339 | /******************************************************************************* | 341 | /******************************************************************************* |
340 | * | 342 | * |
@@ -490,3 +492,4 @@ acpi_status acpi_purge_cached_objects(void) | |||
490 | } | 492 | } |
491 | 493 | ||
492 | ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) | 494 | ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects) |
495 | #endif | ||
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 44ea60cf21c0..100926143818 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c | |||
@@ -398,7 +398,7 @@ acpi_evaluate_reference(acpi_handle handle, | |||
398 | 398 | ||
399 | element = &(package->package.elements[i]); | 399 | element = &(package->package.elements[i]); |
400 | 400 | ||
401 | if (element->type != ACPI_TYPE_ANY) { | 401 | if (element->type != ACPI_TYPE_LOCAL_REFERENCE) { |
402 | status = AE_BAD_DATA; | 402 | status = AE_BAD_DATA; |
403 | printk(KERN_ERR PREFIX | 403 | printk(KERN_ERR PREFIX |
404 | "Expecting a [Reference] package element, found type %X\n", | 404 | "Expecting a [Reference] package element, found type %X\n", |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 43b228314a86..f7eb12e55602 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -57,8 +57,6 @@ | |||
57 | #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 | 57 | #define ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS 0x88 |
58 | #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 | 58 | #define ACPI_VIDEO_NOTIFY_DISPLAY_OFF 0x89 |
59 | 59 | ||
60 | #define ACPI_VIDEO_HEAD_INVALID (~0u - 1) | ||
61 | #define ACPI_VIDEO_HEAD_END (~0u) | ||
62 | #define MAX_NAME_LEN 20 | 60 | #define MAX_NAME_LEN 20 |
63 | 61 | ||
64 | #define ACPI_VIDEO_DISPLAY_CRT 1 | 62 | #define ACPI_VIDEO_DISPLAY_CRT 1 |
@@ -743,21 +741,19 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
743 | if (IS_ERR(device->cdev)) | 741 | if (IS_ERR(device->cdev)) |
744 | return; | 742 | return; |
745 | 743 | ||
746 | if (device->cdev) { | 744 | printk(KERN_INFO PREFIX |
747 | printk(KERN_INFO PREFIX | 745 | "%s is registered as cooling_device%d\n", |
748 | "%s is registered as cooling_device%d\n", | 746 | device->dev->dev.bus_id, device->cdev->id); |
749 | device->dev->dev.bus_id, device->cdev->id); | 747 | result = sysfs_create_link(&device->dev->dev.kobj, |
750 | result = sysfs_create_link(&device->dev->dev.kobj, | 748 | &device->cdev->device.kobj, |
751 | &device->cdev->device.kobj, | 749 | "thermal_cooling"); |
752 | "thermal_cooling"); | 750 | if (result) |
753 | if (result) | 751 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
754 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | 752 | result = sysfs_create_link(&device->cdev->device.kobj, |
755 | result = sysfs_create_link(&device->cdev->device.kobj, | 753 | &device->dev->dev.kobj, "device"); |
756 | &device->dev->dev.kobj, | 754 | if (result) |
757 | "device"); | 755 | printk(KERN_ERR PREFIX "Create sysfs link\n"); |
758 | if (result) | 756 | |
759 | printk(KERN_ERR PREFIX "Create sysfs link\n"); | ||
760 | } | ||
761 | } | 757 | } |
762 | if (device->cap._DCS && device->cap._DSS){ | 758 | if (device->cap._DCS && device->cap._DSS){ |
763 | static int count = 0; | 759 | static int count = 0; |
@@ -1059,30 +1055,25 @@ acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file) | |||
1059 | 1055 | ||
1060 | static int acpi_video_device_add_fs(struct acpi_device *device) | 1056 | static int acpi_video_device_add_fs(struct acpi_device *device) |
1061 | { | 1057 | { |
1062 | struct proc_dir_entry *entry = NULL; | 1058 | struct proc_dir_entry *entry, *device_dir; |
1063 | struct acpi_video_device *vid_dev; | 1059 | struct acpi_video_device *vid_dev; |
1064 | 1060 | ||
1065 | |||
1066 | if (!device) | ||
1067 | return -ENODEV; | ||
1068 | |||
1069 | vid_dev = acpi_driver_data(device); | 1061 | vid_dev = acpi_driver_data(device); |
1070 | if (!vid_dev) | 1062 | if (!vid_dev) |
1071 | return -ENODEV; | 1063 | return -ENODEV; |
1072 | 1064 | ||
1073 | if (!acpi_device_dir(device)) { | 1065 | device_dir = proc_mkdir(acpi_device_bid(device), |
1074 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | 1066 | vid_dev->video->dir); |
1075 | vid_dev->video->dir); | 1067 | if (!device_dir) |
1076 | if (!acpi_device_dir(device)) | 1068 | return -ENOMEM; |
1077 | return -ENODEV; | 1069 | |
1078 | acpi_device_dir(device)->owner = THIS_MODULE; | 1070 | device_dir->owner = THIS_MODULE; |
1079 | } | ||
1080 | 1071 | ||
1081 | /* 'info' [R] */ | 1072 | /* 'info' [R] */ |
1082 | entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device), | 1073 | entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device), |
1083 | &acpi_video_device_info_fops, acpi_driver_data(device)); | 1074 | &acpi_video_device_info_fops, acpi_driver_data(device)); |
1084 | if (!entry) | 1075 | if (!entry) |
1085 | return -ENODEV; | 1076 | goto err_remove_dir; |
1086 | 1077 | ||
1087 | /* 'state' [R/W] */ | 1078 | /* 'state' [R/W] */ |
1088 | acpi_video_device_state_fops.write = acpi_video_device_write_state; | 1079 | acpi_video_device_state_fops.write = acpi_video_device_write_state; |
@@ -1091,7 +1082,7 @@ static int acpi_video_device_add_fs(struct acpi_device *device) | |||
1091 | &acpi_video_device_state_fops, | 1082 | &acpi_video_device_state_fops, |
1092 | acpi_driver_data(device)); | 1083 | acpi_driver_data(device)); |
1093 | if (!entry) | 1084 | if (!entry) |
1094 | return -ENODEV; | 1085 | goto err_remove_info; |
1095 | 1086 | ||
1096 | /* 'brightness' [R/W] */ | 1087 | /* 'brightness' [R/W] */ |
1097 | acpi_video_device_brightness_fops.write = | 1088 | acpi_video_device_brightness_fops.write = |
@@ -1101,30 +1092,43 @@ static int acpi_video_device_add_fs(struct acpi_device *device) | |||
1101 | &acpi_video_device_brightness_fops, | 1092 | &acpi_video_device_brightness_fops, |
1102 | acpi_driver_data(device)); | 1093 | acpi_driver_data(device)); |
1103 | if (!entry) | 1094 | if (!entry) |
1104 | return -ENODEV; | 1095 | goto err_remove_state; |
1105 | 1096 | ||
1106 | /* 'EDID' [R] */ | 1097 | /* 'EDID' [R] */ |
1107 | entry = proc_create_data("EDID", S_IRUGO, acpi_device_dir(device), | 1098 | entry = proc_create_data("EDID", S_IRUGO, acpi_device_dir(device), |
1108 | &acpi_video_device_EDID_fops, | 1099 | &acpi_video_device_EDID_fops, |
1109 | acpi_driver_data(device)); | 1100 | acpi_driver_data(device)); |
1110 | if (!entry) | 1101 | if (!entry) |
1111 | return -ENODEV; | 1102 | goto err_remove_brightness; |
1103 | |||
1112 | return 0; | 1104 | return 0; |
1105 | |||
1106 | err_remove_brightness: | ||
1107 | remove_proc_entry("brightness", device_dir); | ||
1108 | err_remove_state: | ||
1109 | remove_proc_entry("state", device_dir); | ||
1110 | err_remove_info: | ||
1111 | remove_proc_entry("info", device_dir); | ||
1112 | err_remove_dir: | ||
1113 | remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); | ||
1114 | return -ENOMEM; | ||
1113 | } | 1115 | } |
1114 | 1116 | ||
1115 | static int acpi_video_device_remove_fs(struct acpi_device *device) | 1117 | static int acpi_video_device_remove_fs(struct acpi_device *device) |
1116 | { | 1118 | { |
1117 | struct acpi_video_device *vid_dev; | 1119 | struct acpi_video_device *vid_dev; |
1120 | struct proc_dir_entry *device_dir; | ||
1118 | 1121 | ||
1119 | vid_dev = acpi_driver_data(device); | 1122 | vid_dev = acpi_driver_data(device); |
1120 | if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) | 1123 | if (!vid_dev || !vid_dev->video || !vid_dev->video->dir) |
1121 | return -ENODEV; | 1124 | return -ENODEV; |
1122 | 1125 | ||
1123 | if (acpi_device_dir(device)) { | 1126 | device_dir = acpi_device_dir(device); |
1124 | remove_proc_entry("info", acpi_device_dir(device)); | 1127 | if (device_dir) { |
1125 | remove_proc_entry("state", acpi_device_dir(device)); | 1128 | remove_proc_entry("info", device_dir); |
1126 | remove_proc_entry("brightness", acpi_device_dir(device)); | 1129 | remove_proc_entry("state", device_dir); |
1127 | remove_proc_entry("EDID", acpi_device_dir(device)); | 1130 | remove_proc_entry("brightness", device_dir); |
1131 | remove_proc_entry("EDID", device_dir); | ||
1128 | remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); | 1132 | remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir); |
1129 | acpi_device_dir(device) = NULL; | 1133 | acpi_device_dir(device) = NULL; |
1130 | } | 1134 | } |
@@ -1331,76 +1335,81 @@ acpi_video_bus_write_DOS(struct file *file, | |||
1331 | 1335 | ||
1332 | static int acpi_video_bus_add_fs(struct acpi_device *device) | 1336 | static int acpi_video_bus_add_fs(struct acpi_device *device) |
1333 | { | 1337 | { |
1334 | struct proc_dir_entry *entry = NULL; | 1338 | struct acpi_video_bus *video = acpi_driver_data(device); |
1335 | struct acpi_video_bus *video; | 1339 | struct proc_dir_entry *device_dir; |
1340 | struct proc_dir_entry *entry; | ||
1336 | 1341 | ||
1342 | device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir); | ||
1343 | if (!device_dir) | ||
1344 | return -ENOMEM; | ||
1337 | 1345 | ||
1338 | video = acpi_driver_data(device); | 1346 | device_dir->owner = THIS_MODULE; |
1339 | |||
1340 | if (!acpi_device_dir(device)) { | ||
1341 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | ||
1342 | acpi_video_dir); | ||
1343 | if (!acpi_device_dir(device)) | ||
1344 | return -ENODEV; | ||
1345 | video->dir = acpi_device_dir(device); | ||
1346 | acpi_device_dir(device)->owner = THIS_MODULE; | ||
1347 | } | ||
1348 | 1347 | ||
1349 | /* 'info' [R] */ | 1348 | /* 'info' [R] */ |
1350 | entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device), | 1349 | entry = proc_create_data("info", S_IRUGO, acpi_device_dir(device), |
1351 | &acpi_video_bus_info_fops, | 1350 | &acpi_video_bus_info_fops, |
1352 | acpi_driver_data(device)); | 1351 | acpi_driver_data(device)); |
1353 | if (!entry) | 1352 | if (!entry) |
1354 | return -ENODEV; | 1353 | goto err_remove_dir; |
1355 | 1354 | ||
1356 | /* 'ROM' [R] */ | 1355 | /* 'ROM' [R] */ |
1357 | entry = proc_create_data("ROM", S_IRUGO, acpi_device_dir(device), | 1356 | entry = proc_create_data("ROM", S_IRUGO, acpi_device_dir(device), |
1358 | &acpi_video_bus_ROM_fops, | 1357 | &acpi_video_bus_ROM_fops, |
1359 | acpi_driver_data(device)); | 1358 | acpi_driver_data(device)); |
1360 | if (!entry) | 1359 | if (!entry) |
1361 | return -ENODEV; | 1360 | goto err_remove_info; |
1362 | 1361 | ||
1363 | /* 'POST_info' [R] */ | 1362 | /* 'POST_info' [R] */ |
1364 | entry = proc_create_data("POST_info", S_IRUGO, acpi_device_dir(device), | 1363 | entry = proc_create_data("POST_info", S_IRUGO, acpi_device_dir(device), |
1365 | &acpi_video_bus_POST_info_fops, | 1364 | &acpi_video_bus_POST_info_fops, |
1366 | acpi_driver_data(device)); | 1365 | acpi_driver_data(device)); |
1367 | if (!entry) | 1366 | if (!entry) |
1368 | return -ENODEV; | 1367 | goto err_remove_rom; |
1369 | 1368 | ||
1370 | /* 'POST' [R/W] */ | 1369 | /* 'POST' [R/W] */ |
1371 | acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; | 1370 | acpi_video_bus_POST_fops.write = acpi_video_bus_write_POST; |
1372 | entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IRUSR, | 1371 | entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR, |
1373 | acpi_device_dir(device), | 1372 | acpi_device_dir(device), |
1374 | &acpi_video_bus_POST_fops, | 1373 | &acpi_video_bus_POST_fops, |
1375 | acpi_driver_data(device)); | 1374 | acpi_driver_data(device)); |
1376 | if (!entry) | 1375 | if (!entry) |
1377 | return -ENODEV; | 1376 | goto err_remove_post_info; |
1378 | 1377 | ||
1379 | /* 'DOS' [R/W] */ | 1378 | /* 'DOS' [R/W] */ |
1380 | acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; | 1379 | acpi_video_bus_DOS_fops.write = acpi_video_bus_write_DOS; |
1381 | entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IRUSR, | 1380 | entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR, |
1382 | acpi_device_dir(device), | 1381 | acpi_device_dir(device), |
1383 | &acpi_video_bus_DOS_fops, | 1382 | &acpi_video_bus_DOS_fops, |
1384 | acpi_driver_data(device)); | 1383 | acpi_driver_data(device)); |
1385 | if (!entry) | 1384 | if (!entry) |
1386 | return -ENODEV; | 1385 | goto err_remove_post; |
1387 | 1386 | ||
1387 | video->dir = acpi_device_dir(device) = device_dir; | ||
1388 | return 0; | 1388 | return 0; |
1389 | |||
1390 | err_remove_post: | ||
1391 | remove_proc_entry("POST", device_dir); | ||
1392 | err_remove_post_info: | ||
1393 | remove_proc_entry("POST_info", device_dir); | ||
1394 | err_remove_rom: | ||
1395 | remove_proc_entry("ROM", device_dir); | ||
1396 | err_remove_info: | ||
1397 | remove_proc_entry("info", device_dir); | ||
1398 | err_remove_dir: | ||
1399 | remove_proc_entry(acpi_device_bid(device), acpi_video_dir); | ||
1400 | return -ENOMEM; | ||
1389 | } | 1401 | } |
1390 | 1402 | ||
1391 | static int acpi_video_bus_remove_fs(struct acpi_device *device) | 1403 | static int acpi_video_bus_remove_fs(struct acpi_device *device) |
1392 | { | 1404 | { |
1393 | struct acpi_video_bus *video; | 1405 | struct proc_dir_entry *device_dir = acpi_device_dir(device); |
1394 | |||
1395 | 1406 | ||
1396 | video = acpi_driver_data(device); | 1407 | if (device_dir) { |
1397 | 1408 | remove_proc_entry("info", device_dir); | |
1398 | if (acpi_device_dir(device)) { | 1409 | remove_proc_entry("ROM", device_dir); |
1399 | remove_proc_entry("info", acpi_device_dir(device)); | 1410 | remove_proc_entry("POST_info", device_dir); |
1400 | remove_proc_entry("ROM", acpi_device_dir(device)); | 1411 | remove_proc_entry("POST", device_dir); |
1401 | remove_proc_entry("POST_info", acpi_device_dir(device)); | 1412 | remove_proc_entry("DOS", device_dir); |
1402 | remove_proc_entry("POST", acpi_device_dir(device)); | ||
1403 | remove_proc_entry("DOS", acpi_device_dir(device)); | ||
1404 | remove_proc_entry(acpi_device_bid(device), acpi_video_dir); | 1413 | remove_proc_entry(acpi_device_bid(device), acpi_video_dir); |
1405 | acpi_device_dir(device) = NULL; | 1414 | acpi_device_dir(device) = NULL; |
1406 | } | 1415 | } |
@@ -1416,11 +1425,15 @@ static int acpi_video_bus_remove_fs(struct acpi_device *device) | |||
1416 | static struct acpi_video_device_attrib* | 1425 | static struct acpi_video_device_attrib* |
1417 | acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) | 1426 | acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id) |
1418 | { | 1427 | { |
1419 | int count; | 1428 | struct acpi_video_enumerated_device *ids; |
1429 | int i; | ||
1430 | |||
1431 | for (i = 0; i < video->attached_count; i++) { | ||
1432 | ids = &video->attached_array[i]; | ||
1433 | if ((ids->value.int_val & 0xffff) == device_id) | ||
1434 | return &ids->value.attrib; | ||
1435 | } | ||
1420 | 1436 | ||
1421 | for(count = 0; count < video->attached_count; count++) | ||
1422 | if((video->attached_array[count].value.int_val & 0xffff) == device_id) | ||
1423 | return &(video->attached_array[count].value.attrib); | ||
1424 | return NULL; | 1437 | return NULL; |
1425 | } | 1438 | } |
1426 | 1439 | ||
@@ -1547,20 +1560,16 @@ static void | |||
1547 | acpi_video_device_bind(struct acpi_video_bus *video, | 1560 | acpi_video_device_bind(struct acpi_video_bus *video, |
1548 | struct acpi_video_device *device) | 1561 | struct acpi_video_device *device) |
1549 | { | 1562 | { |
1563 | struct acpi_video_enumerated_device *ids; | ||
1550 | int i; | 1564 | int i; |
1551 | 1565 | ||
1552 | #define IDS_VAL(i) video->attached_array[i].value.int_val | 1566 | for (i = 0; i < video->attached_count; i++) { |
1553 | #define IDS_BIND(i) video->attached_array[i].bind_info | 1567 | ids = &video->attached_array[i]; |
1554 | 1568 | if (device->device_id == (ids->value.int_val & 0xffff)) { | |
1555 | for (i = 0; IDS_VAL(i) != ACPI_VIDEO_HEAD_INVALID && | 1569 | ids->bind_info = device; |
1556 | i < video->attached_count; i++) { | ||
1557 | if (device->device_id == (IDS_VAL(i) & 0xffff)) { | ||
1558 | IDS_BIND(i) = device; | ||
1559 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i)); | 1570 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "device_bind %d\n", i)); |
1560 | } | 1571 | } |
1561 | } | 1572 | } |
1562 | #undef IDS_VAL | ||
1563 | #undef IDS_BIND | ||
1564 | } | 1573 | } |
1565 | 1574 | ||
1566 | /* | 1575 | /* |
@@ -1579,7 +1588,7 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1579 | int status; | 1588 | int status; |
1580 | int count; | 1589 | int count; |
1581 | int i; | 1590 | int i; |
1582 | struct acpi_video_enumerated_device *active_device_list; | 1591 | struct acpi_video_enumerated_device *active_list; |
1583 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 1592 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
1584 | union acpi_object *dod = NULL; | 1593 | union acpi_object *dod = NULL; |
1585 | union acpi_object *obj; | 1594 | union acpi_object *obj; |
@@ -1600,13 +1609,10 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1600 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n", | 1609 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d video heads in _DOD\n", |
1601 | dod->package.count)); | 1610 | dod->package.count)); |
1602 | 1611 | ||
1603 | active_device_list = kmalloc((1 + | 1612 | active_list = kcalloc(1 + dod->package.count, |
1604 | dod->package.count) * | 1613 | sizeof(struct acpi_video_enumerated_device), |
1605 | sizeof(struct | 1614 | GFP_KERNEL); |
1606 | acpi_video_enumerated_device), | 1615 | if (!active_list) { |
1607 | GFP_KERNEL); | ||
1608 | |||
1609 | if (!active_device_list) { | ||
1610 | status = -ENOMEM; | 1616 | status = -ENOMEM; |
1611 | goto out; | 1617 | goto out; |
1612 | } | 1618 | } |
@@ -1616,23 +1622,24 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) | |||
1616 | obj = &dod->package.elements[i]; | 1622 | obj = &dod->package.elements[i]; |
1617 | 1623 | ||
1618 | if (obj->type != ACPI_TYPE_INTEGER) { | 1624 | if (obj->type != ACPI_TYPE_INTEGER) { |
1619 | printk(KERN_ERR PREFIX "Invalid _DOD data\n"); | 1625 | printk(KERN_ERR PREFIX |
1620 | active_device_list[i].value.int_val = | 1626 | "Invalid _DOD data in element %d\n", i); |
1621 | ACPI_VIDEO_HEAD_INVALID; | 1627 | continue; |
1622 | } | 1628 | } |
1623 | active_device_list[i].value.int_val = obj->integer.value; | 1629 | |
1624 | active_device_list[i].bind_info = NULL; | 1630 | active_list[count].value.int_val = obj->integer.value; |
1631 | active_list[count].bind_info = NULL; | ||
1625 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, | 1632 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "dod element[%d] = %d\n", i, |
1626 | (int)obj->integer.value)); | 1633 | (int)obj->integer.value)); |
1627 | count++; | 1634 | count++; |
1628 | } | 1635 | } |
1629 | active_device_list[count].value.int_val = ACPI_VIDEO_HEAD_END; | ||
1630 | 1636 | ||
1631 | kfree(video->attached_array); | 1637 | kfree(video->attached_array); |
1632 | 1638 | ||
1633 | video->attached_array = active_device_list; | 1639 | video->attached_array = active_list; |
1634 | video->attached_count = count; | 1640 | video->attached_count = count; |
1635 | out: | 1641 | |
1642 | out: | ||
1636 | kfree(buffer.pointer); | 1643 | kfree(buffer.pointer); |
1637 | return status; | 1644 | return status; |
1638 | } | 1645 | } |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 297a48f85446..636af2862308 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -140,6 +140,7 @@ config ACER_WMI | |||
140 | depends on EXPERIMENTAL | 140 | depends on EXPERIMENTAL |
141 | depends on ACPI | 141 | depends on ACPI |
142 | depends on LEDS_CLASS | 142 | depends on LEDS_CLASS |
143 | depends on NEW_LEDS | ||
143 | depends on BACKLIGHT_CLASS_DEVICE | 144 | depends on BACKLIGHT_CLASS_DEVICE |
144 | depends on SERIO_I8042 | 145 | depends on SERIO_I8042 |
145 | select ACPI_WMI | 146 | select ACPI_WMI |
@@ -160,6 +161,7 @@ config ASUS_LAPTOP | |||
160 | depends on ACPI | 161 | depends on ACPI |
161 | depends on EXPERIMENTAL && !ACPI_ASUS | 162 | depends on EXPERIMENTAL && !ACPI_ASUS |
162 | depends on LEDS_CLASS | 163 | depends on LEDS_CLASS |
164 | depends on NEW_LEDS | ||
163 | depends on BACKLIGHT_CLASS_DEVICE | 165 | depends on BACKLIGHT_CLASS_DEVICE |
164 | ---help--- | 166 | ---help--- |
165 | This is the new Linux driver for Asus laptops. It may also support some | 167 | This is the new Linux driver for Asus laptops. It may also support some |
@@ -241,10 +243,13 @@ config SONYPI_COMPAT | |||
241 | config THINKPAD_ACPI | 243 | config THINKPAD_ACPI |
242 | tristate "ThinkPad ACPI Laptop Extras" | 244 | tristate "ThinkPad ACPI Laptop Extras" |
243 | depends on X86 && ACPI | 245 | depends on X86 && ACPI |
246 | select BACKLIGHT_LCD_SUPPORT | ||
244 | select BACKLIGHT_CLASS_DEVICE | 247 | select BACKLIGHT_CLASS_DEVICE |
245 | select HWMON | 248 | select HWMON |
246 | select NVRAM | 249 | select NVRAM |
247 | depends on INPUT | 250 | select INPUT |
251 | select NEW_LEDS | ||
252 | select LEDS_CLASS | ||
248 | ---help--- | 253 | ---help--- |
249 | This is a driver for the IBM and Lenovo ThinkPad laptops. It adds | 254 | This is a driver for the IBM and Lenovo ThinkPad laptops. It adds |
250 | support for Fn-Fx key combinations, Bluetooth control, video | 255 | support for Fn-Fx key combinations, Bluetooth control, video |
@@ -344,6 +349,7 @@ config ATMEL_SSC | |||
344 | config INTEL_MENLOW | 349 | config INTEL_MENLOW |
345 | tristate "Thermal Management driver for Intel menlow platform" | 350 | tristate "Thermal Management driver for Intel menlow platform" |
346 | depends on ACPI_THERMAL | 351 | depends on ACPI_THERMAL |
352 | select THERMAL | ||
347 | depends on X86 | 353 | depends on X86 |
348 | ---help--- | 354 | ---help--- |
349 | ACPI thermal management enhancement driver on | 355 | ACPI thermal management enhancement driver on |
@@ -351,6 +357,19 @@ config INTEL_MENLOW | |||
351 | 357 | ||
352 | If unsure, say N. | 358 | If unsure, say N. |
353 | 359 | ||
360 | config EEEPC_LAPTOP | ||
361 | tristate "Eee PC Hotkey Driver (EXPERIMENTAL)" | ||
362 | depends on X86 | ||
363 | depends on ACPI | ||
364 | depends on BACKLIGHT_CLASS_DEVICE | ||
365 | depends on HWMON | ||
366 | depends on EXPERIMENTAL | ||
367 | ---help--- | ||
368 | This driver supports the Fn-Fx keys on Eee PC laptops. | ||
369 | It also adds the ability to switch camera/wlan on/off. | ||
370 | |||
371 | If you have an Eee PC laptop, say Y or M here. | ||
372 | |||
354 | config ENCLOSURE_SERVICES | 373 | config ENCLOSURE_SERVICES |
355 | tristate "Enclosure Services" | 374 | tristate "Enclosure Services" |
356 | default n | 375 | default n |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 5914da434854..1952875a272e 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -7,7 +7,8 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/ | |||
7 | obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ | 7 | obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ |
8 | obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o | 8 | obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o |
9 | obj-$(CONFIG_ACER_WMI) += acer-wmi.o | 9 | obj-$(CONFIG_ACER_WMI) += acer-wmi.o |
10 | obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o | 10 | obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o |
11 | obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o | ||
11 | obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o | 12 | obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o |
12 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o | 13 | obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o |
13 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o | 14 | obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o |
diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c new file mode 100644 index 000000000000..6d727609097f --- /dev/null +++ b/drivers/misc/eeepc-laptop.c | |||
@@ -0,0 +1,666 @@ | |||
1 | /* | ||
2 | * eepc-laptop.c - Asus Eee PC extras | ||
3 | * | ||
4 | * Based on asus_acpi.c as patched for the Eee PC by Asus: | ||
5 | * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar | ||
6 | * Based on eee.c from eeepc-linux | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/backlight.h> | ||
25 | #include <linux/fb.h> | ||
26 | #include <linux/hwmon.h> | ||
27 | #include <linux/hwmon-sysfs.h> | ||
28 | #include <acpi/acpi_drivers.h> | ||
29 | #include <acpi/acpi_bus.h> | ||
30 | #include <linux/uaccess.h> | ||
31 | |||
32 | #define EEEPC_LAPTOP_VERSION "0.1" | ||
33 | |||
34 | #define EEEPC_HOTK_NAME "Eee PC Hotkey Driver" | ||
35 | #define EEEPC_HOTK_FILE "eeepc" | ||
36 | #define EEEPC_HOTK_CLASS "hotkey" | ||
37 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" | ||
38 | #define EEEPC_HOTK_HID "ASUS010" | ||
39 | |||
40 | #define EEEPC_LOG EEEPC_HOTK_FILE ": " | ||
41 | #define EEEPC_ERR KERN_ERR EEEPC_LOG | ||
42 | #define EEEPC_WARNING KERN_WARNING EEEPC_LOG | ||
43 | #define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG | ||
44 | #define EEEPC_INFO KERN_INFO EEEPC_LOG | ||
45 | |||
46 | /* | ||
47 | * Definitions for Asus EeePC | ||
48 | */ | ||
49 | #define NOTIFY_WLAN_ON 0x10 | ||
50 | #define NOTIFY_BRN_MIN 0x20 | ||
51 | #define NOTIFY_BRN_MAX 0x2f | ||
52 | |||
53 | enum { | ||
54 | DISABLE_ASL_WLAN = 0x0001, | ||
55 | DISABLE_ASL_BLUETOOTH = 0x0002, | ||
56 | DISABLE_ASL_IRDA = 0x0004, | ||
57 | DISABLE_ASL_CAMERA = 0x0008, | ||
58 | DISABLE_ASL_TV = 0x0010, | ||
59 | DISABLE_ASL_GPS = 0x0020, | ||
60 | DISABLE_ASL_DISPLAYSWITCH = 0x0040, | ||
61 | DISABLE_ASL_MODEM = 0x0080, | ||
62 | DISABLE_ASL_CARDREADER = 0x0100 | ||
63 | }; | ||
64 | |||
65 | enum { | ||
66 | CM_ASL_WLAN = 0, | ||
67 | CM_ASL_BLUETOOTH, | ||
68 | CM_ASL_IRDA, | ||
69 | CM_ASL_1394, | ||
70 | CM_ASL_CAMERA, | ||
71 | CM_ASL_TV, | ||
72 | CM_ASL_GPS, | ||
73 | CM_ASL_DVDROM, | ||
74 | CM_ASL_DISPLAYSWITCH, | ||
75 | CM_ASL_PANELBRIGHT, | ||
76 | CM_ASL_BIOSFLASH, | ||
77 | CM_ASL_ACPIFLASH, | ||
78 | CM_ASL_CPUFV, | ||
79 | CM_ASL_CPUTEMPERATURE, | ||
80 | CM_ASL_FANCPU, | ||
81 | CM_ASL_FANCHASSIS, | ||
82 | CM_ASL_USBPORT1, | ||
83 | CM_ASL_USBPORT2, | ||
84 | CM_ASL_USBPORT3, | ||
85 | CM_ASL_MODEM, | ||
86 | CM_ASL_CARDREADER, | ||
87 | CM_ASL_LID | ||
88 | }; | ||
89 | |||
90 | const char *cm_getv[] = { | ||
91 | "WLDG", NULL, NULL, NULL, | ||
92 | "CAMG", NULL, NULL, NULL, | ||
93 | NULL, "PBLG", NULL, NULL, | ||
94 | "CFVG", NULL, NULL, NULL, | ||
95 | "USBG", NULL, NULL, "MODG", | ||
96 | "CRDG", "LIDG" | ||
97 | }; | ||
98 | |||
99 | const char *cm_setv[] = { | ||
100 | "WLDS", NULL, NULL, NULL, | ||
101 | "CAMS", NULL, NULL, NULL, | ||
102 | "SDSP", "PBLS", "HDPS", NULL, | ||
103 | "CFVS", NULL, NULL, NULL, | ||
104 | "USBG", NULL, NULL, "MODS", | ||
105 | "CRDS", NULL | ||
106 | }; | ||
107 | |||
108 | #define EEEPC_EC "\\_SB.PCI0.SBRG.EC0." | ||
109 | |||
110 | #define EEEPC_EC_FAN_PWM EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */ | ||
111 | #define EEEPC_EC_SC02 0x63 | ||
112 | #define EEEPC_EC_FAN_HRPM EEEPC_EC "SC05" /* High byte, fan speed (RPM) */ | ||
113 | #define EEEPC_EC_FAN_LRPM EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */ | ||
114 | #define EEEPC_EC_FAN_CTRL EEEPC_EC "SFB3" /* Byte containing SF25 */ | ||
115 | #define EEEPC_EC_SFB3 0xD3 | ||
116 | |||
117 | /* | ||
118 | * This is the main structure, we can use it to store useful information | ||
119 | * about the hotk device | ||
120 | */ | ||
121 | struct eeepc_hotk { | ||
122 | struct acpi_device *device; /* the device we are in */ | ||
123 | acpi_handle handle; /* the handle of the hotk device */ | ||
124 | u32 cm_supported; /* the control methods supported | ||
125 | by this BIOS */ | ||
126 | uint init_flag; /* Init flags */ | ||
127 | u16 event_count[128]; /* count for each event */ | ||
128 | }; | ||
129 | |||
130 | /* The actual device the driver binds to */ | ||
131 | static struct eeepc_hotk *ehotk; | ||
132 | |||
133 | /* Platform device/driver */ | ||
134 | static struct platform_driver platform_driver = { | ||
135 | .driver = { | ||
136 | .name = EEEPC_HOTK_FILE, | ||
137 | .owner = THIS_MODULE, | ||
138 | } | ||
139 | }; | ||
140 | |||
141 | static struct platform_device *platform_device; | ||
142 | |||
143 | /* | ||
144 | * The hotkey driver declaration | ||
145 | */ | ||
146 | static int eeepc_hotk_add(struct acpi_device *device); | ||
147 | static int eeepc_hotk_remove(struct acpi_device *device, int type); | ||
148 | |||
149 | static const struct acpi_device_id eeepc_device_ids[] = { | ||
150 | {EEEPC_HOTK_HID, 0}, | ||
151 | {"", 0}, | ||
152 | }; | ||
153 | MODULE_DEVICE_TABLE(acpi, eeepc_device_ids); | ||
154 | |||
155 | static struct acpi_driver eeepc_hotk_driver = { | ||
156 | .name = EEEPC_HOTK_NAME, | ||
157 | .class = EEEPC_HOTK_CLASS, | ||
158 | .ids = eeepc_device_ids, | ||
159 | .ops = { | ||
160 | .add = eeepc_hotk_add, | ||
161 | .remove = eeepc_hotk_remove, | ||
162 | }, | ||
163 | }; | ||
164 | |||
165 | /* The backlight device /sys/class/backlight */ | ||
166 | static struct backlight_device *eeepc_backlight_device; | ||
167 | |||
168 | /* The hwmon device */ | ||
169 | static struct device *eeepc_hwmon_device; | ||
170 | |||
171 | /* | ||
172 | * The backlight class declaration | ||
173 | */ | ||
174 | static int read_brightness(struct backlight_device *bd); | ||
175 | static int update_bl_status(struct backlight_device *bd); | ||
176 | static struct backlight_ops eeepcbl_ops = { | ||
177 | .get_brightness = read_brightness, | ||
178 | .update_status = update_bl_status, | ||
179 | }; | ||
180 | |||
181 | MODULE_AUTHOR("Corentin Chary, Eric Cooper"); | ||
182 | MODULE_DESCRIPTION(EEEPC_HOTK_NAME); | ||
183 | MODULE_LICENSE("GPL"); | ||
184 | |||
185 | /* | ||
186 | * ACPI Helpers | ||
187 | */ | ||
188 | static int write_acpi_int(acpi_handle handle, const char *method, int val, | ||
189 | struct acpi_buffer *output) | ||
190 | { | ||
191 | struct acpi_object_list params; | ||
192 | union acpi_object in_obj; | ||
193 | acpi_status status; | ||
194 | |||
195 | params.count = 1; | ||
196 | params.pointer = &in_obj; | ||
197 | in_obj.type = ACPI_TYPE_INTEGER; | ||
198 | in_obj.integer.value = val; | ||
199 | |||
200 | status = acpi_evaluate_object(handle, (char *)method, ¶ms, output); | ||
201 | return (status == AE_OK ? 0 : -1); | ||
202 | } | ||
203 | |||
204 | static int read_acpi_int(acpi_handle handle, const char *method, int *val) | ||
205 | { | ||
206 | acpi_status status; | ||
207 | ulong result; | ||
208 | |||
209 | status = acpi_evaluate_integer(handle, (char *)method, NULL, &result); | ||
210 | if (ACPI_FAILURE(status)) { | ||
211 | *val = -1; | ||
212 | return -1; | ||
213 | } else { | ||
214 | *val = result; | ||
215 | return 0; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | static int set_acpi(int cm, int value) | ||
220 | { | ||
221 | if (ehotk->cm_supported & (0x1 << cm)) { | ||
222 | const char *method = cm_setv[cm]; | ||
223 | if (method == NULL) | ||
224 | return -ENODEV; | ||
225 | if (write_acpi_int(ehotk->handle, method, value, NULL)) | ||
226 | printk(EEEPC_WARNING "Error writing %s\n", method); | ||
227 | } | ||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | static int get_acpi(int cm) | ||
232 | { | ||
233 | int value = -1; | ||
234 | if ((ehotk->cm_supported & (0x1 << cm))) { | ||
235 | const char *method = cm_getv[cm]; | ||
236 | if (method == NULL) | ||
237 | return -ENODEV; | ||
238 | if (read_acpi_int(ehotk->handle, method, &value)) | ||
239 | printk(EEEPC_WARNING "Error reading %s\n", method); | ||
240 | } | ||
241 | return value; | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * Backlight | ||
246 | */ | ||
247 | static int read_brightness(struct backlight_device *bd) | ||
248 | { | ||
249 | return get_acpi(CM_ASL_PANELBRIGHT); | ||
250 | } | ||
251 | |||
252 | static int set_brightness(struct backlight_device *bd, int value) | ||
253 | { | ||
254 | value = max(0, min(15, value)); | ||
255 | return set_acpi(CM_ASL_PANELBRIGHT, value); | ||
256 | } | ||
257 | |||
258 | static int update_bl_status(struct backlight_device *bd) | ||
259 | { | ||
260 | return set_brightness(bd, bd->props.brightness); | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * Sys helpers | ||
265 | */ | ||
266 | static int parse_arg(const char *buf, unsigned long count, int *val) | ||
267 | { | ||
268 | if (!count) | ||
269 | return 0; | ||
270 | if (sscanf(buf, "%i", val) != 1) | ||
271 | return -EINVAL; | ||
272 | return count; | ||
273 | } | ||
274 | |||
275 | static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) | ||
276 | { | ||
277 | int rv, value; | ||
278 | |||
279 | rv = parse_arg(buf, count, &value); | ||
280 | if (rv > 0) | ||
281 | set_acpi(cm, value); | ||
282 | return rv; | ||
283 | } | ||
284 | |||
285 | static ssize_t show_sys_acpi(int cm, char *buf) | ||
286 | { | ||
287 | return sprintf(buf, "%d\n", get_acpi(cm)); | ||
288 | } | ||
289 | |||
290 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ | ||
291 | static ssize_t show_##_name(struct device *dev, \ | ||
292 | struct device_attribute *attr, \ | ||
293 | char *buf) \ | ||
294 | { \ | ||
295 | return show_sys_acpi(_cm, buf); \ | ||
296 | } \ | ||
297 | static ssize_t store_##_name(struct device *dev, \ | ||
298 | struct device_attribute *attr, \ | ||
299 | const char *buf, size_t count) \ | ||
300 | { \ | ||
301 | return store_sys_acpi(_cm, buf, count); \ | ||
302 | } \ | ||
303 | static struct device_attribute dev_attr_##_name = { \ | ||
304 | .attr = { \ | ||
305 | .name = __stringify(_name), \ | ||
306 | .mode = 0644 }, \ | ||
307 | .show = show_##_name, \ | ||
308 | .store = store_##_name, \ | ||
309 | } | ||
310 | |||
311 | EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); | ||
312 | EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); | ||
313 | EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); | ||
314 | EEEPC_CREATE_DEVICE_ATTR(wlan, CM_ASL_WLAN); | ||
315 | |||
316 | static struct attribute *platform_attributes[] = { | ||
317 | &dev_attr_camera.attr, | ||
318 | &dev_attr_cardr.attr, | ||
319 | &dev_attr_disp.attr, | ||
320 | &dev_attr_wlan.attr, | ||
321 | NULL | ||
322 | }; | ||
323 | |||
324 | static struct attribute_group platform_attribute_group = { | ||
325 | .attrs = platform_attributes | ||
326 | }; | ||
327 | |||
328 | /* | ||
329 | * Hotkey functions | ||
330 | */ | ||
331 | static int eeepc_hotk_check(void) | ||
332 | { | ||
333 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
334 | int result; | ||
335 | |||
336 | result = acpi_bus_get_status(ehotk->device); | ||
337 | if (result) | ||
338 | return result; | ||
339 | if (ehotk->device->status.present) { | ||
340 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, | ||
341 | &buffer)) { | ||
342 | printk(EEEPC_ERR "Hotkey initialization failed\n"); | ||
343 | return -ENODEV; | ||
344 | } else { | ||
345 | printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n", | ||
346 | ehotk->init_flag); | ||
347 | } | ||
348 | /* get control methods supported */ | ||
349 | if (read_acpi_int(ehotk->handle, "CMSG" | ||
350 | , &ehotk->cm_supported)) { | ||
351 | printk(EEEPC_ERR | ||
352 | "Get control methods supported failed\n"); | ||
353 | return -ENODEV; | ||
354 | } else { | ||
355 | printk(EEEPC_INFO | ||
356 | "Get control methods supported: 0x%x\n", | ||
357 | ehotk->cm_supported); | ||
358 | } | ||
359 | } else { | ||
360 | printk(EEEPC_ERR "Hotkey device not present, aborting\n"); | ||
361 | return -EINVAL; | ||
362 | } | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static void notify_wlan(u32 *event) | ||
367 | { | ||
368 | /* if DISABLE_ASL_WLAN is set, the notify code for fn+f2 | ||
369 | will always be 0x10 */ | ||
370 | if (ehotk->cm_supported & (0x1 << CM_ASL_WLAN)) { | ||
371 | const char *method = cm_getv[CM_ASL_WLAN]; | ||
372 | int value; | ||
373 | if (read_acpi_int(ehotk->handle, method, &value)) | ||
374 | printk(EEEPC_WARNING "Error reading %s\n", | ||
375 | method); | ||
376 | else if (value == 1) | ||
377 | *event = 0x11; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | static void notify_brn(void) | ||
382 | { | ||
383 | struct backlight_device *bd = eeepc_backlight_device; | ||
384 | bd->props.brightness = read_brightness(bd); | ||
385 | } | ||
386 | |||
387 | static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) | ||
388 | { | ||
389 | if (!ehotk) | ||
390 | return; | ||
391 | if (event == NOTIFY_WLAN_ON && (DISABLE_ASL_WLAN & ehotk->init_flag)) | ||
392 | notify_wlan(&event); | ||
393 | if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) | ||
394 | notify_brn(); | ||
395 | acpi_bus_generate_proc_event(ehotk->device, event, | ||
396 | ehotk->event_count[event % 128]++); | ||
397 | } | ||
398 | |||
399 | static int eeepc_hotk_add(struct acpi_device *device) | ||
400 | { | ||
401 | acpi_status status = AE_OK; | ||
402 | int result; | ||
403 | |||
404 | if (!device) | ||
405 | return -EINVAL; | ||
406 | printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n"); | ||
407 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | ||
408 | if (!ehotk) | ||
409 | return -ENOMEM; | ||
410 | ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; | ||
411 | ehotk->handle = device->handle; | ||
412 | strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); | ||
413 | strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); | ||
414 | acpi_driver_data(device) = ehotk; | ||
415 | ehotk->device = device; | ||
416 | result = eeepc_hotk_check(); | ||
417 | if (result) | ||
418 | goto end; | ||
419 | status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, | ||
420 | eeepc_hotk_notify, ehotk); | ||
421 | if (ACPI_FAILURE(status)) | ||
422 | printk(EEEPC_ERR "Error installing notify handler\n"); | ||
423 | end: | ||
424 | if (result) { | ||
425 | kfree(ehotk); | ||
426 | ehotk = NULL; | ||
427 | } | ||
428 | return result; | ||
429 | } | ||
430 | |||
431 | static int eeepc_hotk_remove(struct acpi_device *device, int type) | ||
432 | { | ||
433 | acpi_status status = 0; | ||
434 | |||
435 | if (!device || !acpi_driver_data(device)) | ||
436 | return -EINVAL; | ||
437 | status = acpi_remove_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, | ||
438 | eeepc_hotk_notify); | ||
439 | if (ACPI_FAILURE(status)) | ||
440 | printk(EEEPC_ERR "Error removing notify handler\n"); | ||
441 | kfree(ehotk); | ||
442 | return 0; | ||
443 | } | ||
444 | |||
445 | /* | ||
446 | * Hwmon | ||
447 | */ | ||
448 | static int eeepc_get_fan_pwm(void) | ||
449 | { | ||
450 | int value = 0; | ||
451 | |||
452 | read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value); | ||
453 | return (value); | ||
454 | } | ||
455 | |||
456 | static void eeepc_set_fan_pwm(int value) | ||
457 | { | ||
458 | value = SENSORS_LIMIT(value, 0, 100); | ||
459 | ec_write(EEEPC_EC_SC02, value); | ||
460 | } | ||
461 | |||
462 | static int eeepc_get_fan_rpm(void) | ||
463 | { | ||
464 | int high = 0; | ||
465 | int low = 0; | ||
466 | |||
467 | read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high); | ||
468 | read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low); | ||
469 | return (high << 8 | low); | ||
470 | } | ||
471 | |||
472 | static int eeepc_get_fan_ctrl(void) | ||
473 | { | ||
474 | int value = 0; | ||
475 | |||
476 | read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); | ||
477 | return ((value & 0x02 ? 1 : 0)); | ||
478 | } | ||
479 | |||
480 | static void eeepc_set_fan_ctrl(int manual) | ||
481 | { | ||
482 | int value = 0; | ||
483 | |||
484 | read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); | ||
485 | if (manual) | ||
486 | value |= 0x02; | ||
487 | else | ||
488 | value &= ~0x02; | ||
489 | ec_write(EEEPC_EC_SFB3, value); | ||
490 | } | ||
491 | |||
492 | static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count) | ||
493 | { | ||
494 | int rv, value; | ||
495 | |||
496 | rv = parse_arg(buf, count, &value); | ||
497 | if (rv > 0) | ||
498 | set(value); | ||
499 | return rv; | ||
500 | } | ||
501 | |||
502 | static ssize_t show_sys_hwmon(int (*get)(void), char *buf) | ||
503 | { | ||
504 | return sprintf(buf, "%d\n", get()); | ||
505 | } | ||
506 | |||
507 | #define EEEPC_CREATE_SENSOR_ATTR(_name, _mode, _set, _get) \ | ||
508 | static ssize_t show_##_name(struct device *dev, \ | ||
509 | struct device_attribute *attr, \ | ||
510 | char *buf) \ | ||
511 | { \ | ||
512 | return show_sys_hwmon(_set, buf); \ | ||
513 | } \ | ||
514 | static ssize_t store_##_name(struct device *dev, \ | ||
515 | struct device_attribute *attr, \ | ||
516 | const char *buf, size_t count) \ | ||
517 | { \ | ||
518 | return store_sys_hwmon(_get, buf, count); \ | ||
519 | } \ | ||
520 | static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0); | ||
521 | |||
522 | EEEPC_CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, eeepc_get_fan_rpm, NULL); | ||
523 | EEEPC_CREATE_SENSOR_ATTR(fan1_pwm, S_IRUGO | S_IWUSR, | ||
524 | eeepc_get_fan_pwm, eeepc_set_fan_pwm); | ||
525 | EEEPC_CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, | ||
526 | eeepc_get_fan_ctrl, eeepc_set_fan_ctrl); | ||
527 | |||
528 | static struct attribute *hwmon_attributes[] = { | ||
529 | &sensor_dev_attr_fan1_pwm.dev_attr.attr, | ||
530 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
531 | &sensor_dev_attr_pwm1_enable.dev_attr.attr, | ||
532 | NULL | ||
533 | }; | ||
534 | |||
535 | static struct attribute_group hwmon_attribute_group = { | ||
536 | .attrs = hwmon_attributes | ||
537 | }; | ||
538 | |||
539 | /* | ||
540 | * exit/init | ||
541 | */ | ||
542 | static void eeepc_backlight_exit(void) | ||
543 | { | ||
544 | if (eeepc_backlight_device) | ||
545 | backlight_device_unregister(eeepc_backlight_device); | ||
546 | eeepc_backlight_device = NULL; | ||
547 | } | ||
548 | |||
549 | static void eeepc_hwmon_exit(void) | ||
550 | { | ||
551 | struct device *hwmon; | ||
552 | |||
553 | hwmon = eeepc_hwmon_device; | ||
554 | if (!hwmon) | ||
555 | return ; | ||
556 | hwmon_device_unregister(hwmon); | ||
557 | sysfs_remove_group(&hwmon->kobj, | ||
558 | &hwmon_attribute_group); | ||
559 | eeepc_hwmon_device = NULL; | ||
560 | } | ||
561 | |||
562 | static void __exit eeepc_laptop_exit(void) | ||
563 | { | ||
564 | eeepc_backlight_exit(); | ||
565 | eeepc_hwmon_exit(); | ||
566 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
567 | sysfs_remove_group(&platform_device->dev.kobj, | ||
568 | &platform_attribute_group); | ||
569 | platform_device_unregister(platform_device); | ||
570 | platform_driver_unregister(&platform_driver); | ||
571 | } | ||
572 | |||
573 | static int eeepc_backlight_init(struct device *dev) | ||
574 | { | ||
575 | struct backlight_device *bd; | ||
576 | |||
577 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, | ||
578 | NULL, &eeepcbl_ops); | ||
579 | if (IS_ERR(bd)) { | ||
580 | printk(EEEPC_ERR | ||
581 | "Could not register eeepc backlight device\n"); | ||
582 | eeepc_backlight_device = NULL; | ||
583 | return PTR_ERR(bd); | ||
584 | } | ||
585 | eeepc_backlight_device = bd; | ||
586 | bd->props.max_brightness = 15; | ||
587 | bd->props.brightness = read_brightness(NULL); | ||
588 | bd->props.power = FB_BLANK_UNBLANK; | ||
589 | backlight_update_status(bd); | ||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | static int eeepc_hwmon_init(struct device *dev) | ||
594 | { | ||
595 | struct device *hwmon; | ||
596 | int result; | ||
597 | |||
598 | hwmon = hwmon_device_register(dev); | ||
599 | if (IS_ERR(hwmon)) { | ||
600 | printk(EEEPC_ERR | ||
601 | "Could not register eeepc hwmon device\n"); | ||
602 | eeepc_hwmon_device = NULL; | ||
603 | return PTR_ERR(hwmon); | ||
604 | } | ||
605 | eeepc_hwmon_device = hwmon; | ||
606 | result = sysfs_create_group(&hwmon->kobj, | ||
607 | &hwmon_attribute_group); | ||
608 | if (result) | ||
609 | eeepc_hwmon_exit(); | ||
610 | return result; | ||
611 | } | ||
612 | |||
613 | static int __init eeepc_laptop_init(void) | ||
614 | { | ||
615 | struct device *dev; | ||
616 | int result; | ||
617 | |||
618 | if (acpi_disabled) | ||
619 | return -ENODEV; | ||
620 | result = acpi_bus_register_driver(&eeepc_hotk_driver); | ||
621 | if (result < 0) | ||
622 | return result; | ||
623 | if (!ehotk) { | ||
624 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | ||
625 | return -ENODEV; | ||
626 | } | ||
627 | dev = acpi_get_physical_device(ehotk->device->handle); | ||
628 | result = eeepc_backlight_init(dev); | ||
629 | if (result) | ||
630 | goto fail_backlight; | ||
631 | result = eeepc_hwmon_init(dev); | ||
632 | if (result) | ||
633 | goto fail_hwmon; | ||
634 | /* Register platform stuff */ | ||
635 | result = platform_driver_register(&platform_driver); | ||
636 | if (result) | ||
637 | goto fail_platform_driver; | ||
638 | platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1); | ||
639 | if (!platform_device) { | ||
640 | result = -ENOMEM; | ||
641 | goto fail_platform_device1; | ||
642 | } | ||
643 | result = platform_device_add(platform_device); | ||
644 | if (result) | ||
645 | goto fail_platform_device2; | ||
646 | result = sysfs_create_group(&platform_device->dev.kobj, | ||
647 | &platform_attribute_group); | ||
648 | if (result) | ||
649 | goto fail_sysfs; | ||
650 | return 0; | ||
651 | fail_sysfs: | ||
652 | platform_device_del(platform_device); | ||
653 | fail_platform_device2: | ||
654 | platform_device_put(platform_device); | ||
655 | fail_platform_device1: | ||
656 | platform_driver_unregister(&platform_driver); | ||
657 | fail_platform_driver: | ||
658 | eeepc_hwmon_exit(); | ||
659 | fail_hwmon: | ||
660 | eeepc_backlight_exit(); | ||
661 | fail_backlight: | ||
662 | return result; | ||
663 | } | ||
664 | |||
665 | module_init(eeepc_laptop_init); | ||
666 | module_exit(eeepc_laptop_exit); | ||
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 6cb781262f94..3f28f6eabdbf 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * 02110-1301, USA. | 21 | * 02110-1301, USA. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #define TPACPI_VERSION "0.19" | 24 | #define TPACPI_VERSION "0.20" |
25 | #define TPACPI_SYSFS_VERSION 0x020200 | 25 | #define TPACPI_SYSFS_VERSION 0x020200 |
26 | 26 | ||
27 | /* | 27 | /* |
@@ -67,6 +67,7 @@ | |||
67 | #include <linux/hwmon.h> | 67 | #include <linux/hwmon.h> |
68 | #include <linux/hwmon-sysfs.h> | 68 | #include <linux/hwmon-sysfs.h> |
69 | #include <linux/input.h> | 69 | #include <linux/input.h> |
70 | #include <linux/leds.h> | ||
70 | #include <asm/uaccess.h> | 71 | #include <asm/uaccess.h> |
71 | 72 | ||
72 | #include <linux/dmi.h> | 73 | #include <linux/dmi.h> |
@@ -85,6 +86,8 @@ | |||
85 | #define TP_CMOS_VOLUME_MUTE 2 | 86 | #define TP_CMOS_VOLUME_MUTE 2 |
86 | #define TP_CMOS_BRIGHTNESS_UP 4 | 87 | #define TP_CMOS_BRIGHTNESS_UP 4 |
87 | #define TP_CMOS_BRIGHTNESS_DOWN 5 | 88 | #define TP_CMOS_BRIGHTNESS_DOWN 5 |
89 | #define TP_CMOS_THINKLIGHT_ON 12 | ||
90 | #define TP_CMOS_THINKLIGHT_OFF 13 | ||
88 | 91 | ||
89 | /* NVRAM Addresses */ | 92 | /* NVRAM Addresses */ |
90 | enum tp_nvram_addr { | 93 | enum tp_nvram_addr { |
@@ -133,8 +136,12 @@ enum { | |||
133 | #define TPACPI_PROC_DIR "ibm" | 136 | #define TPACPI_PROC_DIR "ibm" |
134 | #define TPACPI_ACPI_EVENT_PREFIX "ibm" | 137 | #define TPACPI_ACPI_EVENT_PREFIX "ibm" |
135 | #define TPACPI_DRVR_NAME TPACPI_FILE | 138 | #define TPACPI_DRVR_NAME TPACPI_FILE |
139 | #define TPACPI_DRVR_SHORTNAME "tpacpi" | ||
136 | #define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon" | 140 | #define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon" |
137 | 141 | ||
142 | #define TPACPI_NVRAM_KTHREAD_NAME "ktpacpi_nvramd" | ||
143 | #define TPACPI_WORKQUEUE_NAME "ktpacpid" | ||
144 | |||
138 | #define TPACPI_MAX_ACPI_ARGS 3 | 145 | #define TPACPI_MAX_ACPI_ARGS 3 |
139 | 146 | ||
140 | /* Debugging */ | 147 | /* Debugging */ |
@@ -225,6 +232,7 @@ static struct { | |||
225 | u32 light:1; | 232 | u32 light:1; |
226 | u32 light_status:1; | 233 | u32 light_status:1; |
227 | u32 bright_16levels:1; | 234 | u32 bright_16levels:1; |
235 | u32 bright_acpimode:1; | ||
228 | u32 wan:1; | 236 | u32 wan:1; |
229 | u32 fan_ctrl_status_undef:1; | 237 | u32 fan_ctrl_status_undef:1; |
230 | u32 input_device_registered:1; | 238 | u32 input_device_registered:1; |
@@ -236,6 +244,11 @@ static struct { | |||
236 | u32 hotkey_poll_active:1; | 244 | u32 hotkey_poll_active:1; |
237 | } tp_features; | 245 | } tp_features; |
238 | 246 | ||
247 | static struct { | ||
248 | u16 hotkey_mask_ff:1; | ||
249 | u16 bright_cmos_ec_unsync:1; | ||
250 | } tp_warned; | ||
251 | |||
239 | struct thinkpad_id_data { | 252 | struct thinkpad_id_data { |
240 | unsigned int vendor; /* ThinkPad vendor: | 253 | unsigned int vendor; /* ThinkPad vendor: |
241 | * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */ | 254 | * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */ |
@@ -246,7 +259,8 @@ struct thinkpad_id_data { | |||
246 | u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ | 259 | u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ |
247 | u16 ec_model; | 260 | u16 ec_model; |
248 | 261 | ||
249 | char *model_str; | 262 | char *model_str; /* ThinkPad T43 */ |
263 | char *nummodel_str; /* 9384A9C for a 9384-A9C model */ | ||
250 | }; | 264 | }; |
251 | static struct thinkpad_id_data thinkpad_id; | 265 | static struct thinkpad_id_data thinkpad_id; |
252 | 266 | ||
@@ -259,6 +273,16 @@ static enum { | |||
259 | static int experimental; | 273 | static int experimental; |
260 | static u32 dbg_level; | 274 | static u32 dbg_level; |
261 | 275 | ||
276 | static struct workqueue_struct *tpacpi_wq; | ||
277 | |||
278 | /* Special LED class that can defer work */ | ||
279 | struct tpacpi_led_classdev { | ||
280 | struct led_classdev led_classdev; | ||
281 | struct work_struct work; | ||
282 | enum led_brightness new_brightness; | ||
283 | unsigned int led; | ||
284 | }; | ||
285 | |||
262 | /**************************************************************************** | 286 | /**************************************************************************** |
263 | **************************************************************************** | 287 | **************************************************************************** |
264 | * | 288 | * |
@@ -807,6 +831,80 @@ static int parse_strtoul(const char *buf, | |||
807 | return 0; | 831 | return 0; |
808 | } | 832 | } |
809 | 833 | ||
834 | static int __init tpacpi_query_bcl_levels(acpi_handle handle) | ||
835 | { | ||
836 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
837 | union acpi_object *obj; | ||
838 | int rc; | ||
839 | |||
840 | if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { | ||
841 | obj = (union acpi_object *)buffer.pointer; | ||
842 | if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { | ||
843 | printk(TPACPI_ERR "Unknown _BCL data, " | ||
844 | "please report this to %s\n", TPACPI_MAIL); | ||
845 | rc = 0; | ||
846 | } else { | ||
847 | rc = obj->package.count; | ||
848 | } | ||
849 | } else { | ||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | kfree(buffer.pointer); | ||
854 | return rc; | ||
855 | } | ||
856 | |||
857 | static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle, | ||
858 | u32 lvl, void *context, void **rv) | ||
859 | { | ||
860 | char name[ACPI_PATH_SEGMENT_LENGTH]; | ||
861 | struct acpi_buffer buffer = { sizeof(name), &name }; | ||
862 | |||
863 | if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && | ||
864 | !strncmp("_BCL", name, sizeof(name) - 1)) { | ||
865 | BUG_ON(!rv || !*rv); | ||
866 | **(int **)rv = tpacpi_query_bcl_levels(handle); | ||
867 | return AE_CTRL_TERMINATE; | ||
868 | } else { | ||
869 | return AE_OK; | ||
870 | } | ||
871 | } | ||
872 | |||
873 | /* | ||
874 | * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map | ||
875 | */ | ||
876 | static int __init tpacpi_check_std_acpi_brightness_support(void) | ||
877 | { | ||
878 | int status; | ||
879 | int bcl_levels = 0; | ||
880 | void *bcl_ptr = &bcl_levels; | ||
881 | |||
882 | if (!vid_handle) { | ||
883 | TPACPI_ACPIHANDLE_INIT(vid); | ||
884 | } | ||
885 | if (!vid_handle) | ||
886 | return 0; | ||
887 | |||
888 | /* | ||
889 | * Search for a _BCL method, and execute it. This is safe on all | ||
890 | * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista | ||
891 | * BIOS in ACPI backlight control mode. We do NOT have to care | ||
892 | * about calling the _BCL method in an enabled video device, any | ||
893 | * will do for our purposes. | ||
894 | */ | ||
895 | |||
896 | status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, | ||
897 | tpacpi_acpi_walk_find_bcl, NULL, | ||
898 | &bcl_ptr); | ||
899 | |||
900 | if (ACPI_SUCCESS(status) && bcl_levels > 2) { | ||
901 | tp_features.bright_acpimode = 1; | ||
902 | return (bcl_levels - 2); | ||
903 | } | ||
904 | |||
905 | return 0; | ||
906 | } | ||
907 | |||
810 | /************************************************************************* | 908 | /************************************************************************* |
811 | * thinkpad-acpi driver attributes | 909 | * thinkpad-acpi driver attributes |
812 | */ | 910 | */ |
@@ -909,12 +1007,14 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) | |||
909 | thinkpad_id.ec_version_str : "unknown"); | 1007 | thinkpad_id.ec_version_str : "unknown"); |
910 | 1008 | ||
911 | if (thinkpad_id.vendor && thinkpad_id.model_str) | 1009 | if (thinkpad_id.vendor && thinkpad_id.model_str) |
912 | printk(TPACPI_INFO "%s %s\n", | 1010 | printk(TPACPI_INFO "%s %s, model %s\n", |
913 | (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? | 1011 | (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? |
914 | "IBM" : ((thinkpad_id.vendor == | 1012 | "IBM" : ((thinkpad_id.vendor == |
915 | PCI_VENDOR_ID_LENOVO) ? | 1013 | PCI_VENDOR_ID_LENOVO) ? |
916 | "Lenovo" : "Unknown vendor"), | 1014 | "Lenovo" : "Unknown vendor"), |
917 | thinkpad_id.model_str); | 1015 | thinkpad_id.model_str, |
1016 | (thinkpad_id.nummodel_str) ? | ||
1017 | thinkpad_id.nummodel_str : "unknown"); | ||
918 | 1018 | ||
919 | return 0; | 1019 | return 0; |
920 | } | 1020 | } |
@@ -1107,6 +1207,19 @@ static int hotkey_mask_set(u32 mask) | |||
1107 | int rc = 0; | 1207 | int rc = 0; |
1108 | 1208 | ||
1109 | if (tp_features.hotkey_mask) { | 1209 | if (tp_features.hotkey_mask) { |
1210 | if (!tp_warned.hotkey_mask_ff && | ||
1211 | (mask == 0xffff || mask == 0xffffff || | ||
1212 | mask == 0xffffffff)) { | ||
1213 | tp_warned.hotkey_mask_ff = 1; | ||
1214 | printk(TPACPI_NOTICE | ||
1215 | "setting the hotkey mask to 0x%08x is likely " | ||
1216 | "not the best way to go about it\n", mask); | ||
1217 | printk(TPACPI_NOTICE | ||
1218 | "please consider using the driver defaults, " | ||
1219 | "and refer to up-to-date thinkpad-acpi " | ||
1220 | "documentation\n"); | ||
1221 | } | ||
1222 | |||
1110 | HOTKEY_CONFIG_CRITICAL_START | 1223 | HOTKEY_CONFIG_CRITICAL_START |
1111 | for (i = 0; i < 32; i++) { | 1224 | for (i = 0; i < 32; i++) { |
1112 | u32 m = 1 << i; | 1225 | u32 m = 1 << i; |
@@ -1427,8 +1540,7 @@ static void hotkey_poll_setup(int may_warn) | |||
1427 | (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { | 1540 | (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { |
1428 | if (!tpacpi_hotkey_task) { | 1541 | if (!tpacpi_hotkey_task) { |
1429 | tpacpi_hotkey_task = kthread_run(hotkey_kthread, | 1542 | tpacpi_hotkey_task = kthread_run(hotkey_kthread, |
1430 | NULL, | 1543 | NULL, TPACPI_NVRAM_KTHREAD_NAME); |
1431 | TPACPI_FILE "d"); | ||
1432 | if (IS_ERR(tpacpi_hotkey_task)) { | 1544 | if (IS_ERR(tpacpi_hotkey_task)) { |
1433 | tpacpi_hotkey_task = NULL; | 1545 | tpacpi_hotkey_task = NULL; |
1434 | printk(TPACPI_ERR | 1546 | printk(TPACPI_ERR |
@@ -1887,6 +1999,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
1887 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ | 1999 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ |
1888 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ | 2000 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ |
1889 | 2001 | ||
2002 | /* These either have to go through ACPI video, or | ||
2003 | * act like in the IBM ThinkPads, so don't ever | ||
2004 | * enable them by default */ | ||
1890 | KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ | 2005 | KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ |
1891 | KEY_RESERVED, /* 0x10: FN+END (brightness down) */ | 2006 | KEY_RESERVED, /* 0x10: FN+END (brightness down) */ |
1892 | 2007 | ||
@@ -2091,6 +2206,32 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
2091 | set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); | 2206 | set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); |
2092 | } | 2207 | } |
2093 | 2208 | ||
2209 | /* Do not issue duplicate brightness change events to | ||
2210 | * userspace */ | ||
2211 | if (!tp_features.bright_acpimode) | ||
2212 | /* update bright_acpimode... */ | ||
2213 | tpacpi_check_std_acpi_brightness_support(); | ||
2214 | |||
2215 | if (tp_features.bright_acpimode) { | ||
2216 | printk(TPACPI_INFO | ||
2217 | "This ThinkPad has standard ACPI backlight " | ||
2218 | "brightness control, supported by the ACPI " | ||
2219 | "video driver\n"); | ||
2220 | printk(TPACPI_NOTICE | ||
2221 | "Disabling thinkpad-acpi brightness events " | ||
2222 | "by default...\n"); | ||
2223 | |||
2224 | /* The hotkey_reserved_mask change below is not | ||
2225 | * necessary while the keys are at KEY_RESERVED in the | ||
2226 | * default map, but better safe than sorry, leave it | ||
2227 | * here as a marker of what we have to do, especially | ||
2228 | * when we finally become able to set this at runtime | ||
2229 | * on response to X.org requests */ | ||
2230 | hotkey_reserved_mask |= | ||
2231 | (1 << TP_ACPI_HOTKEYSCAN_FNHOME) | ||
2232 | | (1 << TP_ACPI_HOTKEYSCAN_FNEND); | ||
2233 | } | ||
2234 | |||
2094 | dbg_printk(TPACPI_DBG_INIT, | 2235 | dbg_printk(TPACPI_DBG_INIT, |
2095 | "enabling hot key handling\n"); | 2236 | "enabling hot key handling\n"); |
2096 | res = hotkey_status_set(1); | 2237 | res = hotkey_status_set(1); |
@@ -3110,13 +3251,82 @@ static struct ibm_struct video_driver_data = { | |||
3110 | TPACPI_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */ | 3251 | TPACPI_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */ |
3111 | TPACPI_HANDLE(ledb, ec, "LEDB"); /* G4x */ | 3252 | TPACPI_HANDLE(ledb, ec, "LEDB"); /* G4x */ |
3112 | 3253 | ||
3254 | static int light_get_status(void) | ||
3255 | { | ||
3256 | int status = 0; | ||
3257 | |||
3258 | if (tp_features.light_status) { | ||
3259 | if (!acpi_evalf(ec_handle, &status, "KBLT", "d")) | ||
3260 | return -EIO; | ||
3261 | return (!!status); | ||
3262 | } | ||
3263 | |||
3264 | return -ENXIO; | ||
3265 | } | ||
3266 | |||
3267 | static int light_set_status(int status) | ||
3268 | { | ||
3269 | int rc; | ||
3270 | |||
3271 | if (tp_features.light) { | ||
3272 | if (cmos_handle) { | ||
3273 | rc = acpi_evalf(cmos_handle, NULL, NULL, "vd", | ||
3274 | (status)? | ||
3275 | TP_CMOS_THINKLIGHT_ON : | ||
3276 | TP_CMOS_THINKLIGHT_OFF); | ||
3277 | } else { | ||
3278 | rc = acpi_evalf(lght_handle, NULL, NULL, "vd", | ||
3279 | (status)? 1 : 0); | ||
3280 | } | ||
3281 | return (rc)? 0 : -EIO; | ||
3282 | } | ||
3283 | |||
3284 | return -ENXIO; | ||
3285 | } | ||
3286 | |||
3287 | static void light_set_status_worker(struct work_struct *work) | ||
3288 | { | ||
3289 | struct tpacpi_led_classdev *data = | ||
3290 | container_of(work, struct tpacpi_led_classdev, work); | ||
3291 | |||
3292 | if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) | ||
3293 | light_set_status((data->new_brightness != LED_OFF)); | ||
3294 | } | ||
3295 | |||
3296 | static void light_sysfs_set(struct led_classdev *led_cdev, | ||
3297 | enum led_brightness brightness) | ||
3298 | { | ||
3299 | struct tpacpi_led_classdev *data = | ||
3300 | container_of(led_cdev, | ||
3301 | struct tpacpi_led_classdev, | ||
3302 | led_classdev); | ||
3303 | data->new_brightness = brightness; | ||
3304 | queue_work(tpacpi_wq, &data->work); | ||
3305 | } | ||
3306 | |||
3307 | static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) | ||
3308 | { | ||
3309 | return (light_get_status() == 1)? LED_FULL : LED_OFF; | ||
3310 | } | ||
3311 | |||
3312 | static struct tpacpi_led_classdev tpacpi_led_thinklight = { | ||
3313 | .led_classdev = { | ||
3314 | .name = "tpacpi::thinklight", | ||
3315 | .brightness_set = &light_sysfs_set, | ||
3316 | .brightness_get = &light_sysfs_get, | ||
3317 | } | ||
3318 | }; | ||
3319 | |||
3113 | static int __init light_init(struct ibm_init_struct *iibm) | 3320 | static int __init light_init(struct ibm_init_struct *iibm) |
3114 | { | 3321 | { |
3322 | int rc = 0; | ||
3323 | |||
3115 | vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); | 3324 | vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); |
3116 | 3325 | ||
3117 | TPACPI_ACPIHANDLE_INIT(ledb); | 3326 | TPACPI_ACPIHANDLE_INIT(ledb); |
3118 | TPACPI_ACPIHANDLE_INIT(lght); | 3327 | TPACPI_ACPIHANDLE_INIT(lght); |
3119 | TPACPI_ACPIHANDLE_INIT(cmos); | 3328 | TPACPI_ACPIHANDLE_INIT(cmos); |
3329 | INIT_WORK(&tpacpi_led_thinklight.work, light_set_status_worker); | ||
3120 | 3330 | ||
3121 | /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */ | 3331 | /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */ |
3122 | tp_features.light = (cmos_handle || lght_handle) && !ledb_handle; | 3332 | tp_features.light = (cmos_handle || lght_handle) && !ledb_handle; |
@@ -3130,13 +3340,31 @@ static int __init light_init(struct ibm_init_struct *iibm) | |||
3130 | vdbg_printk(TPACPI_DBG_INIT, "light is %s\n", | 3340 | vdbg_printk(TPACPI_DBG_INIT, "light is %s\n", |
3131 | str_supported(tp_features.light)); | 3341 | str_supported(tp_features.light)); |
3132 | 3342 | ||
3133 | return (tp_features.light)? 0 : 1; | 3343 | if (tp_features.light) { |
3344 | rc = led_classdev_register(&tpacpi_pdev->dev, | ||
3345 | &tpacpi_led_thinklight.led_classdev); | ||
3346 | } | ||
3347 | |||
3348 | if (rc < 0) { | ||
3349 | tp_features.light = 0; | ||
3350 | tp_features.light_status = 0; | ||
3351 | } else { | ||
3352 | rc = (tp_features.light)? 0 : 1; | ||
3353 | } | ||
3354 | return rc; | ||
3355 | } | ||
3356 | |||
3357 | static void light_exit(void) | ||
3358 | { | ||
3359 | led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); | ||
3360 | if (work_pending(&tpacpi_led_thinklight.work)) | ||
3361 | flush_workqueue(tpacpi_wq); | ||
3134 | } | 3362 | } |
3135 | 3363 | ||
3136 | static int light_read(char *p) | 3364 | static int light_read(char *p) |
3137 | { | 3365 | { |
3138 | int len = 0; | 3366 | int len = 0; |
3139 | int status = 0; | 3367 | int status; |
3140 | 3368 | ||
3141 | if (!tp_features.light) { | 3369 | if (!tp_features.light) { |
3142 | len += sprintf(p + len, "status:\t\tnot supported\n"); | 3370 | len += sprintf(p + len, "status:\t\tnot supported\n"); |
@@ -3144,8 +3372,9 @@ static int light_read(char *p) | |||
3144 | len += sprintf(p + len, "status:\t\tunknown\n"); | 3372 | len += sprintf(p + len, "status:\t\tunknown\n"); |
3145 | len += sprintf(p + len, "commands:\ton, off\n"); | 3373 | len += sprintf(p + len, "commands:\ton, off\n"); |
3146 | } else { | 3374 | } else { |
3147 | if (!acpi_evalf(ec_handle, &status, "KBLT", "d")) | 3375 | status = light_get_status(); |
3148 | return -EIO; | 3376 | if (status < 0) |
3377 | return status; | ||
3149 | len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0)); | 3378 | len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0)); |
3150 | len += sprintf(p + len, "commands:\ton, off\n"); | 3379 | len += sprintf(p + len, "commands:\ton, off\n"); |
3151 | } | 3380 | } |
@@ -3155,37 +3384,29 @@ static int light_read(char *p) | |||
3155 | 3384 | ||
3156 | static int light_write(char *buf) | 3385 | static int light_write(char *buf) |
3157 | { | 3386 | { |
3158 | int cmos_cmd, lght_cmd; | ||
3159 | char *cmd; | 3387 | char *cmd; |
3160 | int success; | 3388 | int newstatus = 0; |
3161 | 3389 | ||
3162 | if (!tp_features.light) | 3390 | if (!tp_features.light) |
3163 | return -ENODEV; | 3391 | return -ENODEV; |
3164 | 3392 | ||
3165 | while ((cmd = next_cmd(&buf))) { | 3393 | while ((cmd = next_cmd(&buf))) { |
3166 | if (strlencmp(cmd, "on") == 0) { | 3394 | if (strlencmp(cmd, "on") == 0) { |
3167 | cmos_cmd = 0x0c; | 3395 | newstatus = 1; |
3168 | lght_cmd = 1; | ||
3169 | } else if (strlencmp(cmd, "off") == 0) { | 3396 | } else if (strlencmp(cmd, "off") == 0) { |
3170 | cmos_cmd = 0x0d; | 3397 | newstatus = 0; |
3171 | lght_cmd = 0; | ||
3172 | } else | 3398 | } else |
3173 | return -EINVAL; | 3399 | return -EINVAL; |
3174 | |||
3175 | success = cmos_handle ? | ||
3176 | acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) : | ||
3177 | acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd); | ||
3178 | if (!success) | ||
3179 | return -EIO; | ||
3180 | } | 3400 | } |
3181 | 3401 | ||
3182 | return 0; | 3402 | return light_set_status(newstatus); |
3183 | } | 3403 | } |
3184 | 3404 | ||
3185 | static struct ibm_struct light_driver_data = { | 3405 | static struct ibm_struct light_driver_data = { |
3186 | .name = "light", | 3406 | .name = "light", |
3187 | .read = light_read, | 3407 | .read = light_read, |
3188 | .write = light_write, | 3408 | .write = light_write, |
3409 | .exit = light_exit, | ||
3189 | }; | 3410 | }; |
3190 | 3411 | ||
3191 | /************************************************************************* | 3412 | /************************************************************************* |
@@ -3583,6 +3804,12 @@ enum { /* For TPACPI_LED_OLD */ | |||
3583 | TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */ | 3804 | TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */ |
3584 | }; | 3805 | }; |
3585 | 3806 | ||
3807 | enum led_status_t { | ||
3808 | TPACPI_LED_OFF = 0, | ||
3809 | TPACPI_LED_ON, | ||
3810 | TPACPI_LED_BLINK, | ||
3811 | }; | ||
3812 | |||
3586 | static enum led_access_mode led_supported; | 3813 | static enum led_access_mode led_supported; |
3587 | 3814 | ||
3588 | TPACPI_HANDLE(led, ec, "SLED", /* 570 */ | 3815 | TPACPI_HANDLE(led, ec, "SLED", /* 570 */ |
@@ -3591,8 +3818,174 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */ | |||
3591 | "LED", /* all others */ | 3818 | "LED", /* all others */ |
3592 | ); /* R30, R31 */ | 3819 | ); /* R30, R31 */ |
3593 | 3820 | ||
3821 | #define TPACPI_LED_NUMLEDS 8 | ||
3822 | static struct tpacpi_led_classdev *tpacpi_leds; | ||
3823 | static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS]; | ||
3824 | static const char const *tpacpi_led_names[TPACPI_LED_NUMLEDS] = { | ||
3825 | /* there's a limit of 19 chars + NULL before 2.6.26 */ | ||
3826 | "tpacpi::power", | ||
3827 | "tpacpi:orange:batt", | ||
3828 | "tpacpi:green:batt", | ||
3829 | "tpacpi::dock_active", | ||
3830 | "tpacpi::bay_active", | ||
3831 | "tpacpi::dock_batt", | ||
3832 | "tpacpi::unknown_led", | ||
3833 | "tpacpi::standby", | ||
3834 | }; | ||
3835 | |||
3836 | static int led_get_status(unsigned int led) | ||
3837 | { | ||
3838 | int status; | ||
3839 | enum led_status_t led_s; | ||
3840 | |||
3841 | switch (led_supported) { | ||
3842 | case TPACPI_LED_570: | ||
3843 | if (!acpi_evalf(ec_handle, | ||
3844 | &status, "GLED", "dd", 1 << led)) | ||
3845 | return -EIO; | ||
3846 | led_s = (status == 0)? | ||
3847 | TPACPI_LED_OFF : | ||
3848 | ((status == 1)? | ||
3849 | TPACPI_LED_ON : | ||
3850 | TPACPI_LED_BLINK); | ||
3851 | tpacpi_led_state_cache[led] = led_s; | ||
3852 | return led_s; | ||
3853 | default: | ||
3854 | return -ENXIO; | ||
3855 | } | ||
3856 | |||
3857 | /* not reached */ | ||
3858 | } | ||
3859 | |||
3860 | static int led_set_status(unsigned int led, enum led_status_t ledstatus) | ||
3861 | { | ||
3862 | /* off, on, blink. Index is led_status_t */ | ||
3863 | static const int const led_sled_arg1[] = { 0, 1, 3 }; | ||
3864 | static const int const led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ | ||
3865 | static const int const led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ | ||
3866 | static const int const led_led_arg1[] = { 0, 0x80, 0xc0 }; | ||
3867 | |||
3868 | int rc = 0; | ||
3869 | |||
3870 | switch (led_supported) { | ||
3871 | case TPACPI_LED_570: | ||
3872 | /* 570 */ | ||
3873 | led = 1 << led; | ||
3874 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", | ||
3875 | led, led_sled_arg1[ledstatus])) | ||
3876 | rc = -EIO; | ||
3877 | break; | ||
3878 | case TPACPI_LED_OLD: | ||
3879 | /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ | ||
3880 | led = 1 << led; | ||
3881 | rc = ec_write(TPACPI_LED_EC_HLMS, led); | ||
3882 | if (rc >= 0) | ||
3883 | rc = ec_write(TPACPI_LED_EC_HLBL, | ||
3884 | led * led_exp_hlbl[ledstatus]); | ||
3885 | if (rc >= 0) | ||
3886 | rc = ec_write(TPACPI_LED_EC_HLCL, | ||
3887 | led * led_exp_hlcl[ledstatus]); | ||
3888 | break; | ||
3889 | case TPACPI_LED_NEW: | ||
3890 | /* all others */ | ||
3891 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", | ||
3892 | led, led_led_arg1[ledstatus])) | ||
3893 | rc = -EIO; | ||
3894 | break; | ||
3895 | default: | ||
3896 | rc = -ENXIO; | ||
3897 | } | ||
3898 | |||
3899 | if (!rc) | ||
3900 | tpacpi_led_state_cache[led] = ledstatus; | ||
3901 | |||
3902 | return rc; | ||
3903 | } | ||
3904 | |||
3905 | static void led_sysfs_set_status(unsigned int led, | ||
3906 | enum led_brightness brightness) | ||
3907 | { | ||
3908 | led_set_status(led, | ||
3909 | (brightness == LED_OFF) ? | ||
3910 | TPACPI_LED_OFF : | ||
3911 | (tpacpi_led_state_cache[led] == TPACPI_LED_BLINK) ? | ||
3912 | TPACPI_LED_BLINK : TPACPI_LED_ON); | ||
3913 | } | ||
3914 | |||
3915 | static void led_set_status_worker(struct work_struct *work) | ||
3916 | { | ||
3917 | struct tpacpi_led_classdev *data = | ||
3918 | container_of(work, struct tpacpi_led_classdev, work); | ||
3919 | |||
3920 | if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) | ||
3921 | led_sysfs_set_status(data->led, data->new_brightness); | ||
3922 | } | ||
3923 | |||
3924 | static void led_sysfs_set(struct led_classdev *led_cdev, | ||
3925 | enum led_brightness brightness) | ||
3926 | { | ||
3927 | struct tpacpi_led_classdev *data = container_of(led_cdev, | ||
3928 | struct tpacpi_led_classdev, led_classdev); | ||
3929 | |||
3930 | data->new_brightness = brightness; | ||
3931 | queue_work(tpacpi_wq, &data->work); | ||
3932 | } | ||
3933 | |||
3934 | static int led_sysfs_blink_set(struct led_classdev *led_cdev, | ||
3935 | unsigned long *delay_on, unsigned long *delay_off) | ||
3936 | { | ||
3937 | struct tpacpi_led_classdev *data = container_of(led_cdev, | ||
3938 | struct tpacpi_led_classdev, led_classdev); | ||
3939 | |||
3940 | /* Can we choose the flash rate? */ | ||
3941 | if (*delay_on == 0 && *delay_off == 0) { | ||
3942 | /* yes. set them to the hardware blink rate (1 Hz) */ | ||
3943 | *delay_on = 500; /* ms */ | ||
3944 | *delay_off = 500; /* ms */ | ||
3945 | } else if ((*delay_on != 500) || (*delay_off != 500)) | ||
3946 | return -EINVAL; | ||
3947 | |||
3948 | data->new_brightness = TPACPI_LED_BLINK; | ||
3949 | queue_work(tpacpi_wq, &data->work); | ||
3950 | |||
3951 | return 0; | ||
3952 | } | ||
3953 | |||
3954 | static enum led_brightness led_sysfs_get(struct led_classdev *led_cdev) | ||
3955 | { | ||
3956 | int rc; | ||
3957 | |||
3958 | struct tpacpi_led_classdev *data = container_of(led_cdev, | ||
3959 | struct tpacpi_led_classdev, led_classdev); | ||
3960 | |||
3961 | rc = led_get_status(data->led); | ||
3962 | |||
3963 | if (rc == TPACPI_LED_OFF || rc < 0) | ||
3964 | rc = LED_OFF; /* no error handling in led class :( */ | ||
3965 | else | ||
3966 | rc = LED_FULL; | ||
3967 | |||
3968 | return rc; | ||
3969 | } | ||
3970 | |||
3971 | static void led_exit(void) | ||
3972 | { | ||
3973 | unsigned int i; | ||
3974 | |||
3975 | for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { | ||
3976 | if (tpacpi_leds[i].led_classdev.name) | ||
3977 | led_classdev_unregister(&tpacpi_leds[i].led_classdev); | ||
3978 | } | ||
3979 | |||
3980 | kfree(tpacpi_leds); | ||
3981 | tpacpi_leds = NULL; | ||
3982 | } | ||
3983 | |||
3594 | static int __init led_init(struct ibm_init_struct *iibm) | 3984 | static int __init led_init(struct ibm_init_struct *iibm) |
3595 | { | 3985 | { |
3986 | unsigned int i; | ||
3987 | int rc; | ||
3988 | |||
3596 | vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); | 3989 | vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); |
3597 | 3990 | ||
3598 | TPACPI_ACPIHANDLE_INIT(led); | 3991 | TPACPI_ACPIHANDLE_INIT(led); |
@@ -3613,10 +4006,41 @@ static int __init led_init(struct ibm_init_struct *iibm) | |||
3613 | vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", | 4006 | vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", |
3614 | str_supported(led_supported), led_supported); | 4007 | str_supported(led_supported), led_supported); |
3615 | 4008 | ||
4009 | tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, | ||
4010 | GFP_KERNEL); | ||
4011 | if (!tpacpi_leds) { | ||
4012 | printk(TPACPI_ERR "Out of memory for LED data\n"); | ||
4013 | return -ENOMEM; | ||
4014 | } | ||
4015 | |||
4016 | for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { | ||
4017 | tpacpi_leds[i].led = i; | ||
4018 | |||
4019 | tpacpi_leds[i].led_classdev.brightness_set = &led_sysfs_set; | ||
4020 | tpacpi_leds[i].led_classdev.blink_set = &led_sysfs_blink_set; | ||
4021 | if (led_supported == TPACPI_LED_570) | ||
4022 | tpacpi_leds[i].led_classdev.brightness_get = | ||
4023 | &led_sysfs_get; | ||
4024 | |||
4025 | tpacpi_leds[i].led_classdev.name = tpacpi_led_names[i]; | ||
4026 | |||
4027 | INIT_WORK(&tpacpi_leds[i].work, led_set_status_worker); | ||
4028 | |||
4029 | rc = led_classdev_register(&tpacpi_pdev->dev, | ||
4030 | &tpacpi_leds[i].led_classdev); | ||
4031 | if (rc < 0) { | ||
4032 | tpacpi_leds[i].led_classdev.name = NULL; | ||
4033 | led_exit(); | ||
4034 | return rc; | ||
4035 | } | ||
4036 | } | ||
4037 | |||
3616 | return (led_supported != TPACPI_LED_NONE)? 0 : 1; | 4038 | return (led_supported != TPACPI_LED_NONE)? 0 : 1; |
3617 | } | 4039 | } |
3618 | 4040 | ||
3619 | #define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking")) | 4041 | #define str_led_status(s) \ |
4042 | ((s) == TPACPI_LED_OFF ? "off" : \ | ||
4043 | ((s) == TPACPI_LED_ON ? "on" : "blinking")) | ||
3620 | 4044 | ||
3621 | static int led_read(char *p) | 4045 | static int led_read(char *p) |
3622 | { | 4046 | { |
@@ -3632,11 +4056,11 @@ static int led_read(char *p) | |||
3632 | /* 570 */ | 4056 | /* 570 */ |
3633 | int i, status; | 4057 | int i, status; |
3634 | for (i = 0; i < 8; i++) { | 4058 | for (i = 0; i < 8; i++) { |
3635 | if (!acpi_evalf(ec_handle, | 4059 | status = led_get_status(i); |
3636 | &status, "GLED", "dd", 1 << i)) | 4060 | if (status < 0) |
3637 | return -EIO; | 4061 | return -EIO; |
3638 | len += sprintf(p + len, "%d:\t\t%s\n", | 4062 | len += sprintf(p + len, "%d:\t\t%s\n", |
3639 | i, led_status(status)); | 4063 | i, str_led_status(status)); |
3640 | } | 4064 | } |
3641 | } | 4065 | } |
3642 | 4066 | ||
@@ -3646,16 +4070,11 @@ static int led_read(char *p) | |||
3646 | return len; | 4070 | return len; |
3647 | } | 4071 | } |
3648 | 4072 | ||
3649 | /* off, on, blink */ | ||
3650 | static const int led_sled_arg1[] = { 0, 1, 3 }; | ||
3651 | static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */ | ||
3652 | static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */ | ||
3653 | static const int led_led_arg1[] = { 0, 0x80, 0xc0 }; | ||
3654 | |||
3655 | static int led_write(char *buf) | 4073 | static int led_write(char *buf) |
3656 | { | 4074 | { |
3657 | char *cmd; | 4075 | char *cmd; |
3658 | int led, ind, ret; | 4076 | int led, rc; |
4077 | enum led_status_t s; | ||
3659 | 4078 | ||
3660 | if (!led_supported) | 4079 | if (!led_supported) |
3661 | return -ENODEV; | 4080 | return -ENODEV; |
@@ -3665,38 +4084,18 @@ static int led_write(char *buf) | |||
3665 | return -EINVAL; | 4084 | return -EINVAL; |
3666 | 4085 | ||
3667 | if (strstr(cmd, "off")) { | 4086 | if (strstr(cmd, "off")) { |
3668 | ind = 0; | 4087 | s = TPACPI_LED_OFF; |
3669 | } else if (strstr(cmd, "on")) { | 4088 | } else if (strstr(cmd, "on")) { |
3670 | ind = 1; | 4089 | s = TPACPI_LED_ON; |
3671 | } else if (strstr(cmd, "blink")) { | 4090 | } else if (strstr(cmd, "blink")) { |
3672 | ind = 2; | 4091 | s = TPACPI_LED_BLINK; |
3673 | } else | ||
3674 | return -EINVAL; | ||
3675 | |||
3676 | if (led_supported == TPACPI_LED_570) { | ||
3677 | /* 570 */ | ||
3678 | led = 1 << led; | ||
3679 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", | ||
3680 | led, led_sled_arg1[ind])) | ||
3681 | return -EIO; | ||
3682 | } else if (led_supported == TPACPI_LED_OLD) { | ||
3683 | /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20 */ | ||
3684 | led = 1 << led; | ||
3685 | ret = ec_write(TPACPI_LED_EC_HLMS, led); | ||
3686 | if (ret >= 0) | ||
3687 | ret = ec_write(TPACPI_LED_EC_HLBL, | ||
3688 | led * led_exp_hlbl[ind]); | ||
3689 | if (ret >= 0) | ||
3690 | ret = ec_write(TPACPI_LED_EC_HLCL, | ||
3691 | led * led_exp_hlcl[ind]); | ||
3692 | if (ret < 0) | ||
3693 | return ret; | ||
3694 | } else { | 4092 | } else { |
3695 | /* all others */ | 4093 | return -EINVAL; |
3696 | if (!acpi_evalf(led_handle, NULL, NULL, "vdd", | ||
3697 | led, led_led_arg1[ind])) | ||
3698 | return -EIO; | ||
3699 | } | 4094 | } |
4095 | |||
4096 | rc = led_set_status(led, s); | ||
4097 | if (rc < 0) | ||
4098 | return rc; | ||
3700 | } | 4099 | } |
3701 | 4100 | ||
3702 | return 0; | 4101 | return 0; |
@@ -3706,6 +4105,7 @@ static struct ibm_struct led_driver_data = { | |||
3706 | .name = "led", | 4105 | .name = "led", |
3707 | .read = led_read, | 4106 | .read = led_read, |
3708 | .write = led_write, | 4107 | .write = led_write, |
4108 | .exit = led_exit, | ||
3709 | }; | 4109 | }; |
3710 | 4110 | ||
3711 | /************************************************************************* | 4111 | /************************************************************************* |
@@ -4170,8 +4570,16 @@ static struct ibm_struct ecdump_driver_data = { | |||
4170 | 4570 | ||
4171 | #define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen" | 4571 | #define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen" |
4172 | 4572 | ||
4573 | enum { | ||
4574 | TP_EC_BACKLIGHT = 0x31, | ||
4575 | |||
4576 | /* TP_EC_BACKLIGHT bitmasks */ | ||
4577 | TP_EC_BACKLIGHT_LVLMSK = 0x1F, | ||
4578 | TP_EC_BACKLIGHT_CMDMSK = 0xE0, | ||
4579 | TP_EC_BACKLIGHT_MAPSW = 0x20, | ||
4580 | }; | ||
4581 | |||
4173 | static struct backlight_device *ibm_backlight_device; | 4582 | static struct backlight_device *ibm_backlight_device; |
4174 | static int brightness_offset = 0x31; | ||
4175 | static int brightness_mode; | 4583 | static int brightness_mode; |
4176 | static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ | 4584 | static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ |
4177 | 4585 | ||
@@ -4180,16 +4588,24 @@ static struct mutex brightness_mutex; | |||
4180 | /* | 4588 | /* |
4181 | * ThinkPads can read brightness from two places: EC 0x31, or | 4589 | * ThinkPads can read brightness from two places: EC 0x31, or |
4182 | * CMOS NVRAM byte 0x5E, bits 0-3. | 4590 | * CMOS NVRAM byte 0x5E, bits 0-3. |
4591 | * | ||
4592 | * EC 0x31 has the following layout | ||
4593 | * Bit 7: unknown function | ||
4594 | * Bit 6: unknown function | ||
4595 | * Bit 5: Z: honour scale changes, NZ: ignore scale changes | ||
4596 | * Bit 4: must be set to zero to avoid problems | ||
4597 | * Bit 3-0: backlight brightness level | ||
4598 | * | ||
4599 | * brightness_get_raw returns status data in the EC 0x31 layout | ||
4183 | */ | 4600 | */ |
4184 | static int brightness_get(struct backlight_device *bd) | 4601 | static int brightness_get_raw(int *status) |
4185 | { | 4602 | { |
4186 | u8 lec = 0, lcmos = 0, level = 0; | 4603 | u8 lec = 0, lcmos = 0, level = 0; |
4187 | 4604 | ||
4188 | if (brightness_mode & 1) { | 4605 | if (brightness_mode & 1) { |
4189 | if (!acpi_ec_read(brightness_offset, &lec)) | 4606 | if (!acpi_ec_read(TP_EC_BACKLIGHT, &lec)) |
4190 | return -EIO; | 4607 | return -EIO; |
4191 | lec &= (tp_features.bright_16levels)? 0x0f : 0x07; | 4608 | level = lec & TP_EC_BACKLIGHT_LVLMSK; |
4192 | level = lec; | ||
4193 | }; | 4609 | }; |
4194 | if (brightness_mode & 2) { | 4610 | if (brightness_mode & 2) { |
4195 | lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) | 4611 | lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) |
@@ -4199,16 +4615,27 @@ static int brightness_get(struct backlight_device *bd) | |||
4199 | level = lcmos; | 4615 | level = lcmos; |
4200 | } | 4616 | } |
4201 | 4617 | ||
4202 | if (brightness_mode == 3 && lec != lcmos) { | 4618 | if (brightness_mode == 3) { |
4203 | printk(TPACPI_ERR | 4619 | *status = lec; /* Prefer EC, CMOS is just a backing store */ |
4204 | "CMOS NVRAM (%u) and EC (%u) do not agree " | 4620 | lec &= TP_EC_BACKLIGHT_LVLMSK; |
4205 | "on display brightness level\n", | 4621 | if (lec == lcmos) |
4206 | (unsigned int) lcmos, | 4622 | tp_warned.bright_cmos_ec_unsync = 0; |
4207 | (unsigned int) lec); | 4623 | else { |
4208 | return -EIO; | 4624 | if (!tp_warned.bright_cmos_ec_unsync) { |
4625 | printk(TPACPI_ERR | ||
4626 | "CMOS NVRAM (%u) and EC (%u) do not " | ||
4627 | "agree on display brightness level\n", | ||
4628 | (unsigned int) lcmos, | ||
4629 | (unsigned int) lec); | ||
4630 | tp_warned.bright_cmos_ec_unsync = 1; | ||
4631 | } | ||
4632 | return -EIO; | ||
4633 | } | ||
4634 | } else { | ||
4635 | *status = level; | ||
4209 | } | 4636 | } |
4210 | 4637 | ||
4211 | return level; | 4638 | return 0; |
4212 | } | 4639 | } |
4213 | 4640 | ||
4214 | /* May return EINTR which can always be mapped to ERESTARTSYS */ | 4641 | /* May return EINTR which can always be mapped to ERESTARTSYS */ |
@@ -4216,19 +4643,22 @@ static int brightness_set(int value) | |||
4216 | { | 4643 | { |
4217 | int cmos_cmd, inc, i, res; | 4644 | int cmos_cmd, inc, i, res; |
4218 | int current_value; | 4645 | int current_value; |
4646 | int command_bits; | ||
4219 | 4647 | ||
4220 | if (value > ((tp_features.bright_16levels)? 15 : 7)) | 4648 | if (value > ((tp_features.bright_16levels)? 15 : 7) || |
4649 | value < 0) | ||
4221 | return -EINVAL; | 4650 | return -EINVAL; |
4222 | 4651 | ||
4223 | res = mutex_lock_interruptible(&brightness_mutex); | 4652 | res = mutex_lock_interruptible(&brightness_mutex); |
4224 | if (res < 0) | 4653 | if (res < 0) |
4225 | return res; | 4654 | return res; |
4226 | 4655 | ||
4227 | current_value = brightness_get(NULL); | 4656 | res = brightness_get_raw(¤t_value); |
4228 | if (current_value < 0) { | 4657 | if (res < 0) |
4229 | res = current_value; | ||
4230 | goto errout; | 4658 | goto errout; |
4231 | } | 4659 | |
4660 | command_bits = current_value & TP_EC_BACKLIGHT_CMDMSK; | ||
4661 | current_value &= TP_EC_BACKLIGHT_LVLMSK; | ||
4232 | 4662 | ||
4233 | cmos_cmd = value > current_value ? | 4663 | cmos_cmd = value > current_value ? |
4234 | TP_CMOS_BRIGHTNESS_UP : | 4664 | TP_CMOS_BRIGHTNESS_UP : |
@@ -4243,7 +4673,8 @@ static int brightness_set(int value) | |||
4243 | goto errout; | 4673 | goto errout; |
4244 | } | 4674 | } |
4245 | if ((brightness_mode & 1) && | 4675 | if ((brightness_mode & 1) && |
4246 | !acpi_ec_write(brightness_offset, i + inc)) { | 4676 | !acpi_ec_write(TP_EC_BACKLIGHT, |
4677 | (i + inc) | command_bits)) { | ||
4247 | res = -EIO; | 4678 | res = -EIO; |
4248 | goto errout;; | 4679 | goto errout;; |
4249 | } | 4680 | } |
@@ -4266,106 +4697,23 @@ static int brightness_update_status(struct backlight_device *bd) | |||
4266 | bd->props.brightness : 0); | 4697 | bd->props.brightness : 0); |
4267 | } | 4698 | } |
4268 | 4699 | ||
4269 | static struct backlight_ops ibm_backlight_data = { | 4700 | static int brightness_get(struct backlight_device *bd) |
4270 | .get_brightness = brightness_get, | ||
4271 | .update_status = brightness_update_status, | ||
4272 | }; | ||
4273 | |||
4274 | /* --------------------------------------------------------------------- */ | ||
4275 | |||
4276 | static int __init tpacpi_query_bcll_levels(acpi_handle handle) | ||
4277 | { | ||
4278 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
4279 | union acpi_object *obj; | ||
4280 | int rc; | ||
4281 | |||
4282 | if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { | ||
4283 | obj = (union acpi_object *)buffer.pointer; | ||
4284 | if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { | ||
4285 | printk(TPACPI_ERR "Unknown BCLL data, " | ||
4286 | "please report this to %s\n", TPACPI_MAIL); | ||
4287 | rc = 0; | ||
4288 | } else { | ||
4289 | rc = obj->package.count; | ||
4290 | } | ||
4291 | } else { | ||
4292 | return 0; | ||
4293 | } | ||
4294 | |||
4295 | kfree(buffer.pointer); | ||
4296 | return rc; | ||
4297 | } | ||
4298 | |||
4299 | static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl, | ||
4300 | void *context, void **rv) | ||
4301 | { | ||
4302 | char name[ACPI_PATH_SEGMENT_LENGTH]; | ||
4303 | struct acpi_buffer buffer = { sizeof(name), &name }; | ||
4304 | |||
4305 | if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && | ||
4306 | !strncmp("BCLL", name, sizeof(name) - 1)) { | ||
4307 | if (tpacpi_query_bcll_levels(handle) == 16) { | ||
4308 | *rv = handle; | ||
4309 | return AE_CTRL_TERMINATE; | ||
4310 | } else { | ||
4311 | return AE_OK; | ||
4312 | } | ||
4313 | } else { | ||
4314 | return AE_OK; | ||
4315 | } | ||
4316 | } | ||
4317 | |||
4318 | static int __init brightness_check_levels(void) | ||
4319 | { | 4701 | { |
4320 | int status; | 4702 | int status, res; |
4321 | void *found_node = NULL; | ||
4322 | 4703 | ||
4323 | if (!vid_handle) { | 4704 | res = brightness_get_raw(&status); |
4324 | TPACPI_ACPIHANDLE_INIT(vid); | 4705 | if (res < 0) |
4325 | } | 4706 | return 0; /* FIXME: teach backlight about error handling */ |
4326 | if (!vid_handle) | ||
4327 | return 0; | ||
4328 | |||
4329 | /* Search for a BCLL package with 16 levels */ | ||
4330 | status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3, | ||
4331 | brightness_find_bcll, NULL, | ||
4332 | &found_node); | ||
4333 | |||
4334 | return (ACPI_SUCCESS(status) && found_node != NULL); | ||
4335 | } | ||
4336 | |||
4337 | static acpi_status __init brightness_find_bcl(acpi_handle handle, u32 lvl, | ||
4338 | void *context, void **rv) | ||
4339 | { | ||
4340 | char name[ACPI_PATH_SEGMENT_LENGTH]; | ||
4341 | struct acpi_buffer buffer = { sizeof(name), &name }; | ||
4342 | 4707 | ||
4343 | if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && | 4708 | return status & TP_EC_BACKLIGHT_LVLMSK; |
4344 | !strncmp("_BCL", name, sizeof(name) - 1)) { | ||
4345 | *rv = handle; | ||
4346 | return AE_CTRL_TERMINATE; | ||
4347 | } else { | ||
4348 | return AE_OK; | ||
4349 | } | ||
4350 | } | 4709 | } |
4351 | 4710 | ||
4352 | static int __init brightness_check_std_acpi_support(void) | 4711 | static struct backlight_ops ibm_backlight_data = { |
4353 | { | 4712 | .get_brightness = brightness_get, |
4354 | int status; | 4713 | .update_status = brightness_update_status, |
4355 | void *found_node = NULL; | 4714 | }; |
4356 | |||
4357 | if (!vid_handle) { | ||
4358 | TPACPI_ACPIHANDLE_INIT(vid); | ||
4359 | } | ||
4360 | if (!vid_handle) | ||
4361 | return 0; | ||
4362 | |||
4363 | /* Search for a _BCL method, but don't execute it */ | ||
4364 | status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, | ||
4365 | brightness_find_bcl, NULL, &found_node); | ||
4366 | 4715 | ||
4367 | return (ACPI_SUCCESS(status) && found_node != NULL); | 4716 | /* --------------------------------------------------------------------- */ |
4368 | } | ||
4369 | 4717 | ||
4370 | static int __init brightness_init(struct ibm_init_struct *iibm) | 4718 | static int __init brightness_init(struct ibm_init_struct *iibm) |
4371 | { | 4719 | { |
@@ -4375,13 +4723,19 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
4375 | 4723 | ||
4376 | mutex_init(&brightness_mutex); | 4724 | mutex_init(&brightness_mutex); |
4377 | 4725 | ||
4378 | if (!brightness_enable) { | 4726 | /* |
4379 | dbg_printk(TPACPI_DBG_INIT, | 4727 | * We always attempt to detect acpi support, so as to switch |
4380 | "brightness support disabled by " | 4728 | * Lenovo Vista BIOS to ACPI brightness mode even if we are not |
4381 | "module parameter\n"); | 4729 | * going to publish a backlight interface |
4382 | return 1; | 4730 | */ |
4383 | } else if (brightness_enable > 1) { | 4731 | b = tpacpi_check_std_acpi_brightness_support(); |
4384 | if (brightness_check_std_acpi_support()) { | 4732 | if (b > 0) { |
4733 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { | ||
4734 | printk(TPACPI_NOTICE | ||
4735 | "Lenovo BIOS switched to ACPI backlight " | ||
4736 | "control mode\n"); | ||
4737 | } | ||
4738 | if (brightness_enable > 1) { | ||
4385 | printk(TPACPI_NOTICE | 4739 | printk(TPACPI_NOTICE |
4386 | "standard ACPI backlight interface " | 4740 | "standard ACPI backlight interface " |
4387 | "available, not loading native one...\n"); | 4741 | "available, not loading native one...\n"); |
@@ -4389,6 +4743,22 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
4389 | } | 4743 | } |
4390 | } | 4744 | } |
4391 | 4745 | ||
4746 | if (!brightness_enable) { | ||
4747 | dbg_printk(TPACPI_DBG_INIT, | ||
4748 | "brightness support disabled by " | ||
4749 | "module parameter\n"); | ||
4750 | return 1; | ||
4751 | } | ||
4752 | |||
4753 | if (b > 16) { | ||
4754 | printk(TPACPI_ERR | ||
4755 | "Unsupported brightness interface, " | ||
4756 | "please contact %s\n", TPACPI_MAIL); | ||
4757 | return 1; | ||
4758 | } | ||
4759 | if (b == 16) | ||
4760 | tp_features.bright_16levels = 1; | ||
4761 | |||
4392 | if (!brightness_mode) { | 4762 | if (!brightness_mode) { |
4393 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) | 4763 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) |
4394 | brightness_mode = 2; | 4764 | brightness_mode = 2; |
@@ -4402,12 +4772,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
4402 | if (brightness_mode > 3) | 4772 | if (brightness_mode > 3) |
4403 | return -EINVAL; | 4773 | return -EINVAL; |
4404 | 4774 | ||
4405 | tp_features.bright_16levels = | 4775 | if (brightness_get_raw(&b) < 0) |
4406 | thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO && | ||
4407 | brightness_check_levels(); | ||
4408 | |||
4409 | b = brightness_get(NULL); | ||
4410 | if (b < 0) | ||
4411 | return 1; | 4776 | return 1; |
4412 | 4777 | ||
4413 | if (tp_features.bright_16levels) | 4778 | if (tp_features.bright_16levels) |
@@ -4425,7 +4790,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm) | |||
4425 | 4790 | ||
4426 | ibm_backlight_device->props.max_brightness = | 4791 | ibm_backlight_device->props.max_brightness = |
4427 | (tp_features.bright_16levels)? 15 : 7; | 4792 | (tp_features.bright_16levels)? 15 : 7; |
4428 | ibm_backlight_device->props.brightness = b; | 4793 | ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; |
4429 | backlight_update_status(ibm_backlight_device); | 4794 | backlight_update_status(ibm_backlight_device); |
4430 | 4795 | ||
4431 | return 0; | 4796 | return 0; |
@@ -5046,11 +5411,11 @@ static void fan_watchdog_reset(void) | |||
5046 | if (fan_watchdog_maxinterval > 0 && | 5411 | if (fan_watchdog_maxinterval > 0 && |
5047 | tpacpi_lifecycle != TPACPI_LIFE_EXITING) { | 5412 | tpacpi_lifecycle != TPACPI_LIFE_EXITING) { |
5048 | fan_watchdog_active = 1; | 5413 | fan_watchdog_active = 1; |
5049 | if (!schedule_delayed_work(&fan_watchdog_task, | 5414 | if (!queue_delayed_work(tpacpi_wq, &fan_watchdog_task, |
5050 | msecs_to_jiffies(fan_watchdog_maxinterval | 5415 | msecs_to_jiffies(fan_watchdog_maxinterval |
5051 | * 1000))) { | 5416 | * 1000))) { |
5052 | printk(TPACPI_ERR | 5417 | printk(TPACPI_ERR |
5053 | "failed to schedule the fan watchdog, " | 5418 | "failed to queue the fan watchdog, " |
5054 | "watchdog will not trigger\n"); | 5419 | "watchdog will not trigger\n"); |
5055 | } | 5420 | } |
5056 | } else | 5421 | } else |
@@ -5420,7 +5785,7 @@ static void fan_exit(void) | |||
5420 | &driver_attr_fan_watchdog); | 5785 | &driver_attr_fan_watchdog); |
5421 | 5786 | ||
5422 | cancel_delayed_work(&fan_watchdog_task); | 5787 | cancel_delayed_work(&fan_watchdog_task); |
5423 | flush_scheduled_work(); | 5788 | flush_workqueue(tpacpi_wq); |
5424 | } | 5789 | } |
5425 | 5790 | ||
5426 | static int fan_read(char *p) | 5791 | static int fan_read(char *p) |
@@ -5826,10 +6191,13 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) | |||
5826 | 6191 | ||
5827 | tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), | 6192 | tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), |
5828 | GFP_KERNEL); | 6193 | GFP_KERNEL); |
5829 | if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) { | 6194 | if (tp->model_str && strnicmp(tp->model_str, "ThinkPad", 8) != 0) { |
5830 | kfree(tp->model_str); | 6195 | kfree(tp->model_str); |
5831 | tp->model_str = NULL; | 6196 | tp->model_str = NULL; |
5832 | } | 6197 | } |
6198 | |||
6199 | tp->nummodel_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_NAME), | ||
6200 | GFP_KERNEL); | ||
5833 | } | 6201 | } |
5834 | 6202 | ||
5835 | static int __init probe_for_thinkpad(void) | 6203 | static int __init probe_for_thinkpad(void) |
@@ -6071,6 +6439,9 @@ static void thinkpad_acpi_module_exit(void) | |||
6071 | if (proc_dir) | 6439 | if (proc_dir) |
6072 | remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir); | 6440 | remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir); |
6073 | 6441 | ||
6442 | if (tpacpi_wq) | ||
6443 | destroy_workqueue(tpacpi_wq); | ||
6444 | |||
6074 | kfree(thinkpad_id.bios_version_str); | 6445 | kfree(thinkpad_id.bios_version_str); |
6075 | kfree(thinkpad_id.ec_version_str); | 6446 | kfree(thinkpad_id.ec_version_str); |
6076 | kfree(thinkpad_id.model_str); | 6447 | kfree(thinkpad_id.model_str); |
@@ -6101,6 +6472,12 @@ static int __init thinkpad_acpi_module_init(void) | |||
6101 | TPACPI_ACPIHANDLE_INIT(ecrd); | 6472 | TPACPI_ACPIHANDLE_INIT(ecrd); |
6102 | TPACPI_ACPIHANDLE_INIT(ecwr); | 6473 | TPACPI_ACPIHANDLE_INIT(ecwr); |
6103 | 6474 | ||
6475 | tpacpi_wq = create_singlethread_workqueue(TPACPI_WORKQUEUE_NAME); | ||
6476 | if (!tpacpi_wq) { | ||
6477 | thinkpad_acpi_module_exit(); | ||
6478 | return -ENOMEM; | ||
6479 | } | ||
6480 | |||
6104 | proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir); | 6481 | proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir); |
6105 | if (!proc_dir) { | 6482 | if (!proc_dir) { |
6106 | printk(TPACPI_ERR | 6483 | printk(TPACPI_ERR |
@@ -6223,6 +6600,8 @@ static int __init thinkpad_acpi_module_init(void) | |||
6223 | /* Please remove this in year 2009 */ | 6600 | /* Please remove this in year 2009 */ |
6224 | MODULE_ALIAS("ibm_acpi"); | 6601 | MODULE_ALIAS("ibm_acpi"); |
6225 | 6602 | ||
6603 | MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); | ||
6604 | |||
6226 | /* | 6605 | /* |
6227 | * DMI matching for module autoloading | 6606 | * DMI matching for module autoloading |
6228 | * | 6607 | * |
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 31a633f65547..4fe7c58f57e9 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h | |||
@@ -1,12 +1,78 @@ | |||
1 | extern spinlock_t pnp_lock; | 1 | extern spinlock_t pnp_lock; |
2 | void *pnp_alloc(long size); | 2 | void *pnp_alloc(long size); |
3 | |||
4 | int pnp_register_protocol(struct pnp_protocol *protocol); | ||
5 | void pnp_unregister_protocol(struct pnp_protocol *protocol); | ||
6 | |||
7 | #define PNP_EISA_ID_MASK 0x7fffffff | ||
8 | void pnp_eisa_id_to_string(u32 id, char *str); | ||
9 | struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid); | ||
10 | struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid); | ||
11 | |||
12 | int pnp_add_device(struct pnp_dev *dev); | ||
13 | struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id); | ||
3 | int pnp_interface_attach_device(struct pnp_dev *dev); | 14 | int pnp_interface_attach_device(struct pnp_dev *dev); |
15 | |||
16 | int pnp_add_card(struct pnp_card *card); | ||
17 | struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id); | ||
18 | void pnp_remove_card(struct pnp_card *card); | ||
19 | int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); | ||
20 | void pnp_remove_card_device(struct pnp_dev *dev); | ||
21 | |||
22 | struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev); | ||
23 | struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, | ||
24 | int priority); | ||
25 | int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, | ||
26 | struct pnp_irq *data); | ||
27 | int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, | ||
28 | struct pnp_dma *data); | ||
29 | int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, | ||
30 | struct pnp_port *data); | ||
31 | int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, | ||
32 | struct pnp_mem *data); | ||
33 | void pnp_init_resources(struct pnp_dev *dev); | ||
34 | |||
4 | void pnp_fixup_device(struct pnp_dev *dev); | 35 | void pnp_fixup_device(struct pnp_dev *dev); |
5 | void pnp_free_option(struct pnp_option *option); | 36 | void pnp_free_option(struct pnp_option *option); |
6 | int __pnp_add_device(struct pnp_dev *dev); | 37 | int __pnp_add_device(struct pnp_dev *dev); |
7 | void __pnp_remove_device(struct pnp_dev *dev); | 38 | void __pnp_remove_device(struct pnp_dev *dev); |
8 | 39 | ||
9 | int pnp_check_port(struct pnp_dev * dev, int idx); | 40 | int pnp_check_port(struct pnp_dev *dev, struct resource *res); |
10 | int pnp_check_mem(struct pnp_dev * dev, int idx); | 41 | int pnp_check_mem(struct pnp_dev *dev, struct resource *res); |
11 | int pnp_check_irq(struct pnp_dev * dev, int idx); | 42 | int pnp_check_irq(struct pnp_dev *dev, struct resource *res); |
12 | int pnp_check_dma(struct pnp_dev * dev, int idx); | 43 | int pnp_check_dma(struct pnp_dev *dev, struct resource *res); |
44 | |||
45 | void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc); | ||
46 | |||
47 | void pnp_init_resource(struct resource *res); | ||
48 | |||
49 | struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev, | ||
50 | unsigned int type, unsigned int num); | ||
51 | |||
52 | #define PNP_MAX_PORT 40 | ||
53 | #define PNP_MAX_MEM 24 | ||
54 | #define PNP_MAX_IRQ 2 | ||
55 | #define PNP_MAX_DMA 2 | ||
56 | |||
57 | struct pnp_resource { | ||
58 | struct resource res; | ||
59 | unsigned int index; /* ISAPNP config register index */ | ||
60 | }; | ||
61 | |||
62 | struct pnp_resource_table { | ||
63 | struct pnp_resource port[PNP_MAX_PORT]; | ||
64 | struct pnp_resource mem[PNP_MAX_MEM]; | ||
65 | struct pnp_resource dma[PNP_MAX_DMA]; | ||
66 | struct pnp_resource irq[PNP_MAX_IRQ]; | ||
67 | }; | ||
68 | |||
69 | struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, | ||
70 | int flags); | ||
71 | struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, | ||
72 | int flags); | ||
73 | struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, | ||
74 | resource_size_t start, | ||
75 | resource_size_t end, int flags); | ||
76 | struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, | ||
77 | resource_size_t start, | ||
78 | resource_size_t end, int flags); | ||
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index da1c9909eb44..a762a4176736 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c | |||
@@ -5,6 +5,7 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/ctype.h> | ||
8 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
9 | #include <linux/pnp.h> | 10 | #include <linux/pnp.h> |
10 | #include "base.h" | 11 | #include "base.h" |
@@ -100,19 +101,33 @@ static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv) | |||
100 | * @id: pointer to a pnp_id structure | 101 | * @id: pointer to a pnp_id structure |
101 | * @card: pointer to the desired card | 102 | * @card: pointer to the desired card |
102 | */ | 103 | */ |
103 | int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) | 104 | struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id) |
104 | { | 105 | { |
105 | struct pnp_id *ptr; | 106 | struct pnp_id *dev_id, *ptr; |
106 | 107 | ||
107 | id->next = NULL; | 108 | dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); |
109 | if (!dev_id) | ||
110 | return NULL; | ||
111 | |||
112 | dev_id->id[0] = id[0]; | ||
113 | dev_id->id[1] = id[1]; | ||
114 | dev_id->id[2] = id[2]; | ||
115 | dev_id->id[3] = tolower(id[3]); | ||
116 | dev_id->id[4] = tolower(id[4]); | ||
117 | dev_id->id[5] = tolower(id[5]); | ||
118 | dev_id->id[6] = tolower(id[6]); | ||
119 | dev_id->id[7] = '\0'; | ||
120 | |||
121 | dev_id->next = NULL; | ||
108 | ptr = card->id; | 122 | ptr = card->id; |
109 | while (ptr && ptr->next) | 123 | while (ptr && ptr->next) |
110 | ptr = ptr->next; | 124 | ptr = ptr->next; |
111 | if (ptr) | 125 | if (ptr) |
112 | ptr->next = id; | 126 | ptr->next = dev_id; |
113 | else | 127 | else |
114 | card->id = id; | 128 | card->id = dev_id; |
115 | return 0; | 129 | |
130 | return dev_id; | ||
116 | } | 131 | } |
117 | 132 | ||
118 | static void pnp_free_card_ids(struct pnp_card *card) | 133 | static void pnp_free_card_ids(struct pnp_card *card) |
@@ -136,6 +151,31 @@ static void pnp_release_card(struct device *dmdev) | |||
136 | kfree(card); | 151 | kfree(card); |
137 | } | 152 | } |
138 | 153 | ||
154 | struct pnp_card *pnp_alloc_card(struct pnp_protocol *protocol, int id, char *pnpid) | ||
155 | { | ||
156 | struct pnp_card *card; | ||
157 | struct pnp_id *dev_id; | ||
158 | |||
159 | card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL); | ||
160 | if (!card) | ||
161 | return NULL; | ||
162 | |||
163 | card->protocol = protocol; | ||
164 | card->number = id; | ||
165 | |||
166 | card->dev.parent = &card->protocol->dev; | ||
167 | sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, | ||
168 | card->number); | ||
169 | |||
170 | dev_id = pnp_add_card_id(card, pnpid); | ||
171 | if (!dev_id) { | ||
172 | kfree(card); | ||
173 | return NULL; | ||
174 | } | ||
175 | |||
176 | return card; | ||
177 | } | ||
178 | |||
139 | static ssize_t pnp_show_card_name(struct device *dmdev, | 179 | static ssize_t pnp_show_card_name(struct device *dmdev, |
140 | struct device_attribute *attr, char *buf) | 180 | struct device_attribute *attr, char *buf) |
141 | { | 181 | { |
@@ -191,9 +231,6 @@ int pnp_add_card(struct pnp_card *card) | |||
191 | int error; | 231 | int error; |
192 | struct list_head *pos, *temp; | 232 | struct list_head *pos, *temp; |
193 | 233 | ||
194 | sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, | ||
195 | card->number); | ||
196 | card->dev.parent = &card->protocol->dev; | ||
197 | card->dev.bus = NULL; | 234 | card->dev.bus = NULL; |
198 | card->dev.release = &pnp_release_card; | 235 | card->dev.release = &pnp_release_card; |
199 | error = device_register(&card->dev); | 236 | error = device_register(&card->dev); |
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index 7d366ca672d3..20771b7d4482 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c | |||
@@ -106,18 +106,53 @@ static void pnp_release_device(struct device *dmdev) | |||
106 | pnp_free_option(dev->independent); | 106 | pnp_free_option(dev->independent); |
107 | pnp_free_option(dev->dependent); | 107 | pnp_free_option(dev->dependent); |
108 | pnp_free_ids(dev); | 108 | pnp_free_ids(dev); |
109 | kfree(dev->res); | ||
109 | kfree(dev); | 110 | kfree(dev); |
110 | } | 111 | } |
111 | 112 | ||
112 | int __pnp_add_device(struct pnp_dev *dev) | 113 | struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid) |
113 | { | 114 | { |
114 | int ret; | 115 | struct pnp_dev *dev; |
116 | struct pnp_id *dev_id; | ||
115 | 117 | ||
116 | pnp_fixup_device(dev); | 118 | dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); |
119 | if (!dev) | ||
120 | return NULL; | ||
121 | |||
122 | dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); | ||
123 | if (!dev->res) { | ||
124 | kfree(dev); | ||
125 | return NULL; | ||
126 | } | ||
127 | |||
128 | dev->protocol = protocol; | ||
129 | dev->number = id; | ||
130 | dev->dma_mask = DMA_24BIT_MASK; | ||
131 | |||
132 | dev->dev.parent = &dev->protocol->dev; | ||
117 | dev->dev.bus = &pnp_bus_type; | 133 | dev->dev.bus = &pnp_bus_type; |
118 | dev->dev.dma_mask = &dev->dma_mask; | 134 | dev->dev.dma_mask = &dev->dma_mask; |
119 | dev->dma_mask = dev->dev.coherent_dma_mask = DMA_24BIT_MASK; | 135 | dev->dev.coherent_dma_mask = dev->dma_mask; |
120 | dev->dev.release = &pnp_release_device; | 136 | dev->dev.release = &pnp_release_device; |
137 | |||
138 | sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number, | ||
139 | dev->number); | ||
140 | |||
141 | dev_id = pnp_add_id(dev, pnpid); | ||
142 | if (!dev_id) { | ||
143 | kfree(dev->res); | ||
144 | kfree(dev); | ||
145 | return NULL; | ||
146 | } | ||
147 | |||
148 | return dev; | ||
149 | } | ||
150 | |||
151 | int __pnp_add_device(struct pnp_dev *dev) | ||
152 | { | ||
153 | int ret; | ||
154 | |||
155 | pnp_fixup_device(dev); | ||
121 | dev->status = PNP_READY; | 156 | dev->status = PNP_READY; |
122 | spin_lock(&pnp_lock); | 157 | spin_lock(&pnp_lock); |
123 | list_add_tail(&dev->global_list, &pnp_global); | 158 | list_add_tail(&dev->global_list, &pnp_global); |
@@ -145,9 +180,6 @@ int pnp_add_device(struct pnp_dev *dev) | |||
145 | if (dev->card) | 180 | if (dev->card) |
146 | return -EINVAL; | 181 | return -EINVAL; |
147 | 182 | ||
148 | dev->dev.parent = &dev->protocol->dev; | ||
149 | sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number, | ||
150 | dev->number); | ||
151 | ret = __pnp_add_device(dev); | 183 | ret = __pnp_add_device(dev); |
152 | if (ret) | 184 | if (ret) |
153 | return ret; | 185 | return ret; |
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index e85cbf116db1..d3f869ee1d92 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c | |||
@@ -226,22 +226,36 @@ void pnp_unregister_driver(struct pnp_driver *drv) | |||
226 | 226 | ||
227 | /** | 227 | /** |
228 | * pnp_add_id - adds an EISA id to the specified device | 228 | * pnp_add_id - adds an EISA id to the specified device |
229 | * @id: pointer to a pnp_id structure | ||
230 | * @dev: pointer to the desired device | 229 | * @dev: pointer to the desired device |
230 | * @id: pointer to an EISA id string | ||
231 | */ | 231 | */ |
232 | int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) | 232 | struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id) |
233 | { | 233 | { |
234 | struct pnp_id *ptr; | 234 | struct pnp_id *dev_id, *ptr; |
235 | 235 | ||
236 | id->next = NULL; | 236 | dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); |
237 | if (!dev_id) | ||
238 | return NULL; | ||
239 | |||
240 | dev_id->id[0] = id[0]; | ||
241 | dev_id->id[1] = id[1]; | ||
242 | dev_id->id[2] = id[2]; | ||
243 | dev_id->id[3] = tolower(id[3]); | ||
244 | dev_id->id[4] = tolower(id[4]); | ||
245 | dev_id->id[5] = tolower(id[5]); | ||
246 | dev_id->id[6] = tolower(id[6]); | ||
247 | dev_id->id[7] = '\0'; | ||
248 | |||
249 | dev_id->next = NULL; | ||
237 | ptr = dev->id; | 250 | ptr = dev->id; |
238 | while (ptr && ptr->next) | 251 | while (ptr && ptr->next) |
239 | ptr = ptr->next; | 252 | ptr = ptr->next; |
240 | if (ptr) | 253 | if (ptr) |
241 | ptr->next = id; | 254 | ptr->next = dev_id; |
242 | else | 255 | else |
243 | dev->id = id; | 256 | dev->id = dev_id; |
244 | return 0; | 257 | |
258 | return dev_id; | ||
245 | } | 259 | } |
246 | 260 | ||
247 | EXPORT_SYMBOL(pnp_register_driver); | 261 | EXPORT_SYMBOL(pnp_register_driver); |
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 982658477a58..5d9301de1778 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c | |||
@@ -248,6 +248,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, | |||
248 | char *buf) | 248 | char *buf) |
249 | { | 249 | { |
250 | struct pnp_dev *dev = to_pnp_dev(dmdev); | 250 | struct pnp_dev *dev = to_pnp_dev(dmdev); |
251 | struct resource *res; | ||
251 | int i, ret; | 252 | int i, ret; |
252 | pnp_info_buffer_t *buffer; | 253 | pnp_info_buffer_t *buffer; |
253 | 254 | ||
@@ -267,50 +268,46 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, | |||
267 | else | 268 | else |
268 | pnp_printf(buffer, "disabled\n"); | 269 | pnp_printf(buffer, "disabled\n"); |
269 | 270 | ||
270 | for (i = 0; i < PNP_MAX_PORT; i++) { | 271 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { |
271 | if (pnp_port_valid(dev, i)) { | 272 | if (pnp_resource_valid(res)) { |
272 | pnp_printf(buffer, "io"); | 273 | pnp_printf(buffer, "io"); |
273 | if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED) | 274 | if (res->flags & IORESOURCE_DISABLED) |
274 | pnp_printf(buffer, " disabled\n"); | 275 | pnp_printf(buffer, " disabled\n"); |
275 | else | 276 | else |
276 | pnp_printf(buffer, " 0x%llx-0x%llx\n", | 277 | pnp_printf(buffer, " 0x%llx-0x%llx\n", |
277 | (unsigned long long) | 278 | (unsigned long long) res->start, |
278 | pnp_port_start(dev, i), | 279 | (unsigned long long) res->end); |
279 | (unsigned long long)pnp_port_end(dev, | ||
280 | i)); | ||
281 | } | 280 | } |
282 | } | 281 | } |
283 | for (i = 0; i < PNP_MAX_MEM; i++) { | 282 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { |
284 | if (pnp_mem_valid(dev, i)) { | 283 | if (pnp_resource_valid(res)) { |
285 | pnp_printf(buffer, "mem"); | 284 | pnp_printf(buffer, "mem"); |
286 | if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED) | 285 | if (res->flags & IORESOURCE_DISABLED) |
287 | pnp_printf(buffer, " disabled\n"); | 286 | pnp_printf(buffer, " disabled\n"); |
288 | else | 287 | else |
289 | pnp_printf(buffer, " 0x%llx-0x%llx\n", | 288 | pnp_printf(buffer, " 0x%llx-0x%llx\n", |
290 | (unsigned long long) | 289 | (unsigned long long) res->start, |
291 | pnp_mem_start(dev, i), | 290 | (unsigned long long) res->end); |
292 | (unsigned long long)pnp_mem_end(dev, | ||
293 | i)); | ||
294 | } | 291 | } |
295 | } | 292 | } |
296 | for (i = 0; i < PNP_MAX_IRQ; i++) { | 293 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) { |
297 | if (pnp_irq_valid(dev, i)) { | 294 | if (pnp_resource_valid(res)) { |
298 | pnp_printf(buffer, "irq"); | 295 | pnp_printf(buffer, "irq"); |
299 | if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED) | 296 | if (res->flags & IORESOURCE_DISABLED) |
300 | pnp_printf(buffer, " disabled\n"); | 297 | pnp_printf(buffer, " disabled\n"); |
301 | else | 298 | else |
302 | pnp_printf(buffer, " %lld\n", | 299 | pnp_printf(buffer, " %lld\n", |
303 | (unsigned long long)pnp_irq(dev, i)); | 300 | (unsigned long long) res->start); |
304 | } | 301 | } |
305 | } | 302 | } |
306 | for (i = 0; i < PNP_MAX_DMA; i++) { | 303 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) { |
307 | if (pnp_dma_valid(dev, i)) { | 304 | if (pnp_resource_valid(res)) { |
308 | pnp_printf(buffer, "dma"); | 305 | pnp_printf(buffer, "dma"); |
309 | if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED) | 306 | if (res->flags & IORESOURCE_DISABLED) |
310 | pnp_printf(buffer, " disabled\n"); | 307 | pnp_printf(buffer, " disabled\n"); |
311 | else | 308 | else |
312 | pnp_printf(buffer, " %lld\n", | 309 | pnp_printf(buffer, " %lld\n", |
313 | (unsigned long long)pnp_dma(dev, i)); | 310 | (unsigned long long) res->start); |
314 | } | 311 | } |
315 | } | 312 | } |
316 | ret = (buffer->curr - buf); | 313 | ret = (buffer->curr - buf); |
@@ -323,8 +320,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
323 | const char *ubuf, size_t count) | 320 | const char *ubuf, size_t count) |
324 | { | 321 | { |
325 | struct pnp_dev *dev = to_pnp_dev(dmdev); | 322 | struct pnp_dev *dev = to_pnp_dev(dmdev); |
323 | struct pnp_resource *pnp_res; | ||
326 | char *buf = (void *)ubuf; | 324 | char *buf = (void *)ubuf; |
327 | int retval = 0; | 325 | int retval = 0; |
326 | resource_size_t start, end; | ||
328 | 327 | ||
329 | if (dev->status & PNP_ATTACHED) { | 328 | if (dev->status & PNP_ATTACHED) { |
330 | retval = -EBUSY; | 329 | retval = -EBUSY; |
@@ -351,20 +350,20 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
351 | if (!strnicmp(buf, "auto", 4)) { | 350 | if (!strnicmp(buf, "auto", 4)) { |
352 | if (dev->active) | 351 | if (dev->active) |
353 | goto done; | 352 | goto done; |
354 | pnp_init_resource_table(&dev->res); | 353 | pnp_init_resources(dev); |
355 | retval = pnp_auto_config_dev(dev); | 354 | retval = pnp_auto_config_dev(dev); |
356 | goto done; | 355 | goto done; |
357 | } | 356 | } |
358 | if (!strnicmp(buf, "clear", 5)) { | 357 | if (!strnicmp(buf, "clear", 5)) { |
359 | if (dev->active) | 358 | if (dev->active) |
360 | goto done; | 359 | goto done; |
361 | pnp_init_resource_table(&dev->res); | 360 | pnp_init_resources(dev); |
362 | goto done; | 361 | goto done; |
363 | } | 362 | } |
364 | if (!strnicmp(buf, "get", 3)) { | 363 | if (!strnicmp(buf, "get", 3)) { |
365 | mutex_lock(&pnp_res_mutex); | 364 | mutex_lock(&pnp_res_mutex); |
366 | if (pnp_can_read(dev)) | 365 | if (pnp_can_read(dev)) |
367 | dev->protocol->get(dev, &dev->res); | 366 | dev->protocol->get(dev); |
368 | mutex_unlock(&pnp_res_mutex); | 367 | mutex_unlock(&pnp_res_mutex); |
369 | goto done; | 368 | goto done; |
370 | } | 369 | } |
@@ -373,7 +372,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
373 | if (dev->active) | 372 | if (dev->active) |
374 | goto done; | 373 | goto done; |
375 | buf += 3; | 374 | buf += 3; |
376 | pnp_init_resource_table(&dev->res); | 375 | pnp_init_resources(dev); |
377 | mutex_lock(&pnp_res_mutex); | 376 | mutex_lock(&pnp_res_mutex); |
378 | while (1) { | 377 | while (1) { |
379 | while (isspace(*buf)) | 378 | while (isspace(*buf)) |
@@ -382,76 +381,60 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
382 | buf += 2; | 381 | buf += 2; |
383 | while (isspace(*buf)) | 382 | while (isspace(*buf)) |
384 | ++buf; | 383 | ++buf; |
385 | dev->res.port_resource[nport].start = | 384 | start = simple_strtoul(buf, &buf, 0); |
386 | simple_strtoul(buf, &buf, 0); | ||
387 | while (isspace(*buf)) | 385 | while (isspace(*buf)) |
388 | ++buf; | 386 | ++buf; |
389 | if (*buf == '-') { | 387 | if (*buf == '-') { |
390 | buf += 1; | 388 | buf += 1; |
391 | while (isspace(*buf)) | 389 | while (isspace(*buf)) |
392 | ++buf; | 390 | ++buf; |
393 | dev->res.port_resource[nport].end = | 391 | end = simple_strtoul(buf, &buf, 0); |
394 | simple_strtoul(buf, &buf, 0); | ||
395 | } else | 392 | } else |
396 | dev->res.port_resource[nport].end = | 393 | end = start; |
397 | dev->res.port_resource[nport].start; | 394 | pnp_res = pnp_add_io_resource(dev, start, end, |
398 | dev->res.port_resource[nport].flags = | 395 | 0); |
399 | IORESOURCE_IO; | 396 | if (pnp_res) |
400 | nport++; | 397 | pnp_res->index = nport++; |
401 | if (nport >= PNP_MAX_PORT) | ||
402 | break; | ||
403 | continue; | 398 | continue; |
404 | } | 399 | } |
405 | if (!strnicmp(buf, "mem", 3)) { | 400 | if (!strnicmp(buf, "mem", 3)) { |
406 | buf += 3; | 401 | buf += 3; |
407 | while (isspace(*buf)) | 402 | while (isspace(*buf)) |
408 | ++buf; | 403 | ++buf; |
409 | dev->res.mem_resource[nmem].start = | 404 | start = simple_strtoul(buf, &buf, 0); |
410 | simple_strtoul(buf, &buf, 0); | ||
411 | while (isspace(*buf)) | 405 | while (isspace(*buf)) |
412 | ++buf; | 406 | ++buf; |
413 | if (*buf == '-') { | 407 | if (*buf == '-') { |
414 | buf += 1; | 408 | buf += 1; |
415 | while (isspace(*buf)) | 409 | while (isspace(*buf)) |
416 | ++buf; | 410 | ++buf; |
417 | dev->res.mem_resource[nmem].end = | 411 | end = simple_strtoul(buf, &buf, 0); |
418 | simple_strtoul(buf, &buf, 0); | ||
419 | } else | 412 | } else |
420 | dev->res.mem_resource[nmem].end = | 413 | end = start; |
421 | dev->res.mem_resource[nmem].start; | 414 | pnp_res = pnp_add_mem_resource(dev, start, end, |
422 | dev->res.mem_resource[nmem].flags = | 415 | 0); |
423 | IORESOURCE_MEM; | 416 | if (pnp_res) |
424 | nmem++; | 417 | pnp_res->index = nmem++; |
425 | if (nmem >= PNP_MAX_MEM) | ||
426 | break; | ||
427 | continue; | 418 | continue; |
428 | } | 419 | } |
429 | if (!strnicmp(buf, "irq", 3)) { | 420 | if (!strnicmp(buf, "irq", 3)) { |
430 | buf += 3; | 421 | buf += 3; |
431 | while (isspace(*buf)) | 422 | while (isspace(*buf)) |
432 | ++buf; | 423 | ++buf; |
433 | dev->res.irq_resource[nirq].start = | 424 | start = simple_strtoul(buf, &buf, 0); |
434 | dev->res.irq_resource[nirq].end = | 425 | pnp_res = pnp_add_irq_resource(dev, start, 0); |
435 | simple_strtoul(buf, &buf, 0); | 426 | if (pnp_res) |
436 | dev->res.irq_resource[nirq].flags = | 427 | nirq++; |
437 | IORESOURCE_IRQ; | ||
438 | nirq++; | ||
439 | if (nirq >= PNP_MAX_IRQ) | ||
440 | break; | ||
441 | continue; | 428 | continue; |
442 | } | 429 | } |
443 | if (!strnicmp(buf, "dma", 3)) { | 430 | if (!strnicmp(buf, "dma", 3)) { |
444 | buf += 3; | 431 | buf += 3; |
445 | while (isspace(*buf)) | 432 | while (isspace(*buf)) |
446 | ++buf; | 433 | ++buf; |
447 | dev->res.dma_resource[ndma].start = | 434 | start = simple_strtoul(buf, &buf, 0); |
448 | dev->res.dma_resource[ndma].end = | 435 | pnp_res = pnp_add_dma_resource(dev, start, 0); |
449 | simple_strtoul(buf, &buf, 0); | 436 | if (pnp_res) |
450 | dev->res.dma_resource[ndma].flags = | 437 | pnp_res->index = ndma++; |
451 | IORESOURCE_DMA; | ||
452 | ndma++; | ||
453 | if (ndma >= PNP_MAX_DMA) | ||
454 | break; | ||
455 | continue; | 438 | continue; |
456 | } | 439 | } |
457 | break; | 440 | break; |
diff --git a/drivers/pnp/isapnp/Makefile b/drivers/pnp/isapnp/Makefile index cac18bbfb817..3e38f06f8d78 100644 --- a/drivers/pnp/isapnp/Makefile +++ b/drivers/pnp/isapnp/Makefile | |||
@@ -5,3 +5,7 @@ | |||
5 | isapnp-proc-$(CONFIG_PROC_FS) = proc.o | 5 | isapnp-proc-$(CONFIG_PROC_FS) = proc.o |
6 | 6 | ||
7 | obj-y := core.o compat.o $(isapnp-proc-y) | 7 | obj-y := core.o compat.o $(isapnp-proc-y) |
8 | |||
9 | ifeq ($(CONFIG_PNP_DEBUG),y) | ||
10 | EXTRA_CFLAGS += -DDEBUG | ||
11 | endif | ||
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index 257f5d827d83..f1bccdbdeb08 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c | |||
@@ -44,6 +44,8 @@ | |||
44 | #include <linux/mutex.h> | 44 | #include <linux/mutex.h> |
45 | #include <asm/io.h> | 45 | #include <asm/io.h> |
46 | 46 | ||
47 | #include "../base.h" | ||
48 | |||
47 | #if 0 | 49 | #if 0 |
48 | #define ISAPNP_REGION_OK | 50 | #define ISAPNP_REGION_OK |
49 | #endif | 51 | #endif |
@@ -88,6 +90,14 @@ MODULE_LICENSE("GPL"); | |||
88 | #define _LTAG_MEM32RANGE 0x85 | 90 | #define _LTAG_MEM32RANGE 0x85 |
89 | #define _LTAG_FIXEDMEM32RANGE 0x86 | 91 | #define _LTAG_FIXEDMEM32RANGE 0x86 |
90 | 92 | ||
93 | /* Logical device control and configuration registers */ | ||
94 | |||
95 | #define ISAPNP_CFG_ACTIVATE 0x30 /* byte */ | ||
96 | #define ISAPNP_CFG_MEM 0x40 /* 4 * dword */ | ||
97 | #define ISAPNP_CFG_PORT 0x60 /* 8 * word */ | ||
98 | #define ISAPNP_CFG_IRQ 0x70 /* 2 * word */ | ||
99 | #define ISAPNP_CFG_DMA 0x74 /* 2 * byte */ | ||
100 | |||
91 | /* | 101 | /* |
92 | * Sizes of ISAPNP logical device configuration register sets. | 102 | * Sizes of ISAPNP logical device configuration register sets. |
93 | * See PNP-ISA-v1.0a.pdf, Appendix A. | 103 | * See PNP-ISA-v1.0a.pdf, Appendix A. |
@@ -388,28 +398,6 @@ static void __init isapnp_skip_bytes(int count) | |||
388 | } | 398 | } |
389 | 399 | ||
390 | /* | 400 | /* |
391 | * Parse EISA id. | ||
392 | */ | ||
393 | static void isapnp_parse_id(struct pnp_dev *dev, unsigned short vendor, | ||
394 | unsigned short device) | ||
395 | { | ||
396 | struct pnp_id *id; | ||
397 | |||
398 | if (!dev) | ||
399 | return; | ||
400 | id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); | ||
401 | if (!id) | ||
402 | return; | ||
403 | sprintf(id->id, "%c%c%c%x%x%x%x", | ||
404 | 'A' + ((vendor >> 2) & 0x3f) - 1, | ||
405 | 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, | ||
406 | 'A' + ((vendor >> 8) & 0x1f) - 1, | ||
407 | (device >> 4) & 0x0f, | ||
408 | device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f); | ||
409 | pnp_add_id(id, dev); | ||
410 | } | ||
411 | |||
412 | /* | ||
413 | * Parse logical device tag. | 401 | * Parse logical device tag. |
414 | */ | 402 | */ |
415 | static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, | 403 | static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, |
@@ -417,30 +405,31 @@ static struct pnp_dev *__init isapnp_parse_device(struct pnp_card *card, | |||
417 | { | 405 | { |
418 | unsigned char tmp[6]; | 406 | unsigned char tmp[6]; |
419 | struct pnp_dev *dev; | 407 | struct pnp_dev *dev; |
408 | u32 eisa_id; | ||
409 | char id[8]; | ||
420 | 410 | ||
421 | isapnp_peek(tmp, size); | 411 | isapnp_peek(tmp, size); |
422 | dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); | 412 | eisa_id = tmp[0] | tmp[1] << 8 | tmp[2] << 16 | tmp[3] << 24; |
413 | pnp_eisa_id_to_string(eisa_id, id); | ||
414 | |||
415 | dev = pnp_alloc_dev(&isapnp_protocol, number, id); | ||
423 | if (!dev) | 416 | if (!dev) |
424 | return NULL; | 417 | return NULL; |
425 | dev->number = number; | 418 | |
426 | isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0], (tmp[3] << 8) | tmp[2]); | ||
427 | dev->regs = tmp[4]; | ||
428 | dev->card = card; | 419 | dev->card = card; |
429 | if (size > 5) | ||
430 | dev->regs |= tmp[5] << 8; | ||
431 | dev->protocol = &isapnp_protocol; | ||
432 | dev->capabilities |= PNP_CONFIGURABLE; | 420 | dev->capabilities |= PNP_CONFIGURABLE; |
433 | dev->capabilities |= PNP_READ; | 421 | dev->capabilities |= PNP_READ; |
434 | dev->capabilities |= PNP_WRITE; | 422 | dev->capabilities |= PNP_WRITE; |
435 | dev->capabilities |= PNP_DISABLE; | 423 | dev->capabilities |= PNP_DISABLE; |
436 | pnp_init_resource_table(&dev->res); | 424 | pnp_init_resources(dev); |
437 | return dev; | 425 | return dev; |
438 | } | 426 | } |
439 | 427 | ||
440 | /* | 428 | /* |
441 | * Add IRQ resource to resources list. | 429 | * Add IRQ resource to resources list. |
442 | */ | 430 | */ |
443 | static void __init isapnp_parse_irq_resource(struct pnp_option *option, | 431 | static void __init isapnp_parse_irq_resource(struct pnp_dev *dev, |
432 | struct pnp_option *option, | ||
444 | int size) | 433 | int size) |
445 | { | 434 | { |
446 | unsigned char tmp[3]; | 435 | unsigned char tmp[3]; |
@@ -457,13 +446,14 @@ static void __init isapnp_parse_irq_resource(struct pnp_option *option, | |||
457 | irq->flags = tmp[2]; | 446 | irq->flags = tmp[2]; |
458 | else | 447 | else |
459 | irq->flags = IORESOURCE_IRQ_HIGHEDGE; | 448 | irq->flags = IORESOURCE_IRQ_HIGHEDGE; |
460 | pnp_register_irq_resource(option, irq); | 449 | pnp_register_irq_resource(dev, option, irq); |
461 | } | 450 | } |
462 | 451 | ||
463 | /* | 452 | /* |
464 | * Add DMA resource to resources list. | 453 | * Add DMA resource to resources list. |
465 | */ | 454 | */ |
466 | static void __init isapnp_parse_dma_resource(struct pnp_option *option, | 455 | static void __init isapnp_parse_dma_resource(struct pnp_dev *dev, |
456 | struct pnp_option *option, | ||
467 | int size) | 457 | int size) |
468 | { | 458 | { |
469 | unsigned char tmp[2]; | 459 | unsigned char tmp[2]; |
@@ -475,13 +465,14 @@ static void __init isapnp_parse_dma_resource(struct pnp_option *option, | |||
475 | return; | 465 | return; |
476 | dma->map = tmp[0]; | 466 | dma->map = tmp[0]; |
477 | dma->flags = tmp[1]; | 467 | dma->flags = tmp[1]; |
478 | pnp_register_dma_resource(option, dma); | 468 | pnp_register_dma_resource(dev, option, dma); |
479 | } | 469 | } |
480 | 470 | ||
481 | /* | 471 | /* |
482 | * Add port resource to resources list. | 472 | * Add port resource to resources list. |
483 | */ | 473 | */ |
484 | static void __init isapnp_parse_port_resource(struct pnp_option *option, | 474 | static void __init isapnp_parse_port_resource(struct pnp_dev *dev, |
475 | struct pnp_option *option, | ||
485 | int size) | 476 | int size) |
486 | { | 477 | { |
487 | unsigned char tmp[7]; | 478 | unsigned char tmp[7]; |
@@ -496,13 +487,14 @@ static void __init isapnp_parse_port_resource(struct pnp_option *option, | |||
496 | port->align = tmp[5]; | 487 | port->align = tmp[5]; |
497 | port->size = tmp[6]; | 488 | port->size = tmp[6]; |
498 | port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0; | 489 | port->flags = tmp[0] ? PNP_PORT_FLAG_16BITADDR : 0; |
499 | pnp_register_port_resource(option, port); | 490 | pnp_register_port_resource(dev, option, port); |
500 | } | 491 | } |
501 | 492 | ||
502 | /* | 493 | /* |
503 | * Add fixed port resource to resources list. | 494 | * Add fixed port resource to resources list. |
504 | */ | 495 | */ |
505 | static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, | 496 | static void __init isapnp_parse_fixed_port_resource(struct pnp_dev *dev, |
497 | struct pnp_option *option, | ||
506 | int size) | 498 | int size) |
507 | { | 499 | { |
508 | unsigned char tmp[3]; | 500 | unsigned char tmp[3]; |
@@ -516,13 +508,14 @@ static void __init isapnp_parse_fixed_port_resource(struct pnp_option *option, | |||
516 | port->size = tmp[2]; | 508 | port->size = tmp[2]; |
517 | port->align = 0; | 509 | port->align = 0; |
518 | port->flags = PNP_PORT_FLAG_FIXED; | 510 | port->flags = PNP_PORT_FLAG_FIXED; |
519 | pnp_register_port_resource(option, port); | 511 | pnp_register_port_resource(dev, option, port); |
520 | } | 512 | } |
521 | 513 | ||
522 | /* | 514 | /* |
523 | * Add memory resource to resources list. | 515 | * Add memory resource to resources list. |
524 | */ | 516 | */ |
525 | static void __init isapnp_parse_mem_resource(struct pnp_option *option, | 517 | static void __init isapnp_parse_mem_resource(struct pnp_dev *dev, |
518 | struct pnp_option *option, | ||
526 | int size) | 519 | int size) |
527 | { | 520 | { |
528 | unsigned char tmp[9]; | 521 | unsigned char tmp[9]; |
@@ -537,13 +530,14 @@ static void __init isapnp_parse_mem_resource(struct pnp_option *option, | |||
537 | mem->align = (tmp[6] << 8) | tmp[5]; | 530 | mem->align = (tmp[6] << 8) | tmp[5]; |
538 | mem->size = ((tmp[8] << 8) | tmp[7]) << 8; | 531 | mem->size = ((tmp[8] << 8) | tmp[7]) << 8; |
539 | mem->flags = tmp[0]; | 532 | mem->flags = tmp[0]; |
540 | pnp_register_mem_resource(option, mem); | 533 | pnp_register_mem_resource(dev, option, mem); |
541 | } | 534 | } |
542 | 535 | ||
543 | /* | 536 | /* |
544 | * Add 32-bit memory resource to resources list. | 537 | * Add 32-bit memory resource to resources list. |
545 | */ | 538 | */ |
546 | static void __init isapnp_parse_mem32_resource(struct pnp_option *option, | 539 | static void __init isapnp_parse_mem32_resource(struct pnp_dev *dev, |
540 | struct pnp_option *option, | ||
547 | int size) | 541 | int size) |
548 | { | 542 | { |
549 | unsigned char tmp[17]; | 543 | unsigned char tmp[17]; |
@@ -560,13 +554,14 @@ static void __init isapnp_parse_mem32_resource(struct pnp_option *option, | |||
560 | mem->size = | 554 | mem->size = |
561 | (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; | 555 | (tmp[16] << 24) | (tmp[15] << 16) | (tmp[14] << 8) | tmp[13]; |
562 | mem->flags = tmp[0]; | 556 | mem->flags = tmp[0]; |
563 | pnp_register_mem_resource(option, mem); | 557 | pnp_register_mem_resource(dev, option, mem); |
564 | } | 558 | } |
565 | 559 | ||
566 | /* | 560 | /* |
567 | * Add 32-bit fixed memory resource to resources list. | 561 | * Add 32-bit fixed memory resource to resources list. |
568 | */ | 562 | */ |
569 | static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, | 563 | static void __init isapnp_parse_fixed_mem32_resource(struct pnp_dev *dev, |
564 | struct pnp_option *option, | ||
570 | int size) | 565 | int size) |
571 | { | 566 | { |
572 | unsigned char tmp[9]; | 567 | unsigned char tmp[9]; |
@@ -581,7 +576,7 @@ static void __init isapnp_parse_fixed_mem32_resource(struct pnp_option *option, | |||
581 | mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; | 576 | mem->size = (tmp[8] << 24) | (tmp[7] << 16) | (tmp[6] << 8) | tmp[5]; |
582 | mem->align = 0; | 577 | mem->align = 0; |
583 | mem->flags = tmp[0]; | 578 | mem->flags = tmp[0]; |
584 | pnp_register_mem_resource(option, mem); | 579 | pnp_register_mem_resource(dev, option, mem); |
585 | } | 580 | } |
586 | 581 | ||
587 | /* | 582 | /* |
@@ -613,6 +608,8 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
613 | unsigned char type, tmp[17]; | 608 | unsigned char type, tmp[17]; |
614 | struct pnp_option *option; | 609 | struct pnp_option *option; |
615 | struct pnp_dev *dev; | 610 | struct pnp_dev *dev; |
611 | u32 eisa_id; | ||
612 | char id[8]; | ||
616 | 613 | ||
617 | if ((dev = isapnp_parse_device(card, size, number++)) == NULL) | 614 | if ((dev = isapnp_parse_device(card, size, number++)) == NULL) |
618 | return 1; | 615 | return 1; |
@@ -652,8 +649,10 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
652 | case _STAG_COMPATDEVID: | 649 | case _STAG_COMPATDEVID: |
653 | if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) { | 650 | if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) { |
654 | isapnp_peek(tmp, 4); | 651 | isapnp_peek(tmp, 4); |
655 | isapnp_parse_id(dev, (tmp[1] << 8) | tmp[0], | 652 | eisa_id = tmp[0] | tmp[1] << 8 | |
656 | (tmp[3] << 8) | tmp[2]); | 653 | tmp[2] << 16 | tmp[3] << 24; |
654 | pnp_eisa_id_to_string(eisa_id, id); | ||
655 | pnp_add_id(dev, id); | ||
657 | compat++; | 656 | compat++; |
658 | size = 0; | 657 | size = 0; |
659 | } | 658 | } |
@@ -661,13 +660,13 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
661 | case _STAG_IRQ: | 660 | case _STAG_IRQ: |
662 | if (size < 2 || size > 3) | 661 | if (size < 2 || size > 3) |
663 | goto __skip; | 662 | goto __skip; |
664 | isapnp_parse_irq_resource(option, size); | 663 | isapnp_parse_irq_resource(dev, option, size); |
665 | size = 0; | 664 | size = 0; |
666 | break; | 665 | break; |
667 | case _STAG_DMA: | 666 | case _STAG_DMA: |
668 | if (size != 2) | 667 | if (size != 2) |
669 | goto __skip; | 668 | goto __skip; |
670 | isapnp_parse_dma_resource(option, size); | 669 | isapnp_parse_dma_resource(dev, option, size); |
671 | size = 0; | 670 | size = 0; |
672 | break; | 671 | break; |
673 | case _STAG_STARTDEP: | 672 | case _STAG_STARTDEP: |
@@ -687,17 +686,18 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
687 | if (size != 0) | 686 | if (size != 0) |
688 | goto __skip; | 687 | goto __skip; |
689 | priority = 0; | 688 | priority = 0; |
689 | dev_dbg(&dev->dev, "end dependent options\n"); | ||
690 | break; | 690 | break; |
691 | case _STAG_IOPORT: | 691 | case _STAG_IOPORT: |
692 | if (size != 7) | 692 | if (size != 7) |
693 | goto __skip; | 693 | goto __skip; |
694 | isapnp_parse_port_resource(option, size); | 694 | isapnp_parse_port_resource(dev, option, size); |
695 | size = 0; | 695 | size = 0; |
696 | break; | 696 | break; |
697 | case _STAG_FIXEDIO: | 697 | case _STAG_FIXEDIO: |
698 | if (size != 3) | 698 | if (size != 3) |
699 | goto __skip; | 699 | goto __skip; |
700 | isapnp_parse_fixed_port_resource(option, size); | 700 | isapnp_parse_fixed_port_resource(dev, option, size); |
701 | size = 0; | 701 | size = 0; |
702 | break; | 702 | break; |
703 | case _STAG_VENDOR: | 703 | case _STAG_VENDOR: |
@@ -705,7 +705,7 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
705 | case _LTAG_MEMRANGE: | 705 | case _LTAG_MEMRANGE: |
706 | if (size != 9) | 706 | if (size != 9) |
707 | goto __skip; | 707 | goto __skip; |
708 | isapnp_parse_mem_resource(option, size); | 708 | isapnp_parse_mem_resource(dev, option, size); |
709 | size = 0; | 709 | size = 0; |
710 | break; | 710 | break; |
711 | case _LTAG_ANSISTR: | 711 | case _LTAG_ANSISTR: |
@@ -720,13 +720,13 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
720 | case _LTAG_MEM32RANGE: | 720 | case _LTAG_MEM32RANGE: |
721 | if (size != 17) | 721 | if (size != 17) |
722 | goto __skip; | 722 | goto __skip; |
723 | isapnp_parse_mem32_resource(option, size); | 723 | isapnp_parse_mem32_resource(dev, option, size); |
724 | size = 0; | 724 | size = 0; |
725 | break; | 725 | break; |
726 | case _LTAG_FIXEDMEM32RANGE: | 726 | case _LTAG_FIXEDMEM32RANGE: |
727 | if (size != 9) | 727 | if (size != 9) |
728 | goto __skip; | 728 | goto __skip; |
729 | isapnp_parse_fixed_mem32_resource(option, size); | 729 | isapnp_parse_fixed_mem32_resource(dev, option, size); |
730 | size = 0; | 730 | size = 0; |
731 | break; | 731 | break; |
732 | case _STAG_END: | 732 | case _STAG_END: |
@@ -734,9 +734,8 @@ static int __init isapnp_create_device(struct pnp_card *card, | |||
734 | isapnp_skip_bytes(size); | 734 | isapnp_skip_bytes(size); |
735 | return 1; | 735 | return 1; |
736 | default: | 736 | default: |
737 | printk(KERN_ERR | 737 | dev_err(&dev->dev, "unknown tag %#x (card %i), " |
738 | "isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", | 738 | "ignored\n", type, card->number); |
739 | type, dev->number, card->number); | ||
740 | } | 739 | } |
741 | __skip: | 740 | __skip: |
742 | if (size > 0) | 741 | if (size > 0) |
@@ -789,9 +788,8 @@ static void __init isapnp_parse_resource_map(struct pnp_card *card) | |||
789 | isapnp_skip_bytes(size); | 788 | isapnp_skip_bytes(size); |
790 | return; | 789 | return; |
791 | default: | 790 | default: |
792 | printk(KERN_ERR | 791 | dev_err(&card->dev, "unknown tag %#x, ignored\n", |
793 | "isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", | 792 | type); |
794 | type, card->number); | ||
795 | } | 793 | } |
796 | __skip: | 794 | __skip: |
797 | if (size > 0) | 795 | if (size > 0) |
@@ -822,25 +820,6 @@ static unsigned char __init isapnp_checksum(unsigned char *data) | |||
822 | } | 820 | } |
823 | 821 | ||
824 | /* | 822 | /* |
825 | * Parse EISA id for ISA PnP card. | ||
826 | */ | ||
827 | static void isapnp_parse_card_id(struct pnp_card *card, unsigned short vendor, | ||
828 | unsigned short device) | ||
829 | { | ||
830 | struct pnp_id *id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); | ||
831 | |||
832 | if (!id) | ||
833 | return; | ||
834 | sprintf(id->id, "%c%c%c%x%x%x%x", | ||
835 | 'A' + ((vendor >> 2) & 0x3f) - 1, | ||
836 | 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, | ||
837 | 'A' + ((vendor >> 8) & 0x1f) - 1, | ||
838 | (device >> 4) & 0x0f, | ||
839 | device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f); | ||
840 | pnp_add_card_id(id, card); | ||
841 | } | ||
842 | |||
843 | /* | ||
844 | * Build device list for all present ISA PnP devices. | 823 | * Build device list for all present ISA PnP devices. |
845 | */ | 824 | */ |
846 | static int __init isapnp_build_device_list(void) | 825 | static int __init isapnp_build_device_list(void) |
@@ -848,6 +827,8 @@ static int __init isapnp_build_device_list(void) | |||
848 | int csn; | 827 | int csn; |
849 | unsigned char header[9], checksum; | 828 | unsigned char header[9], checksum; |
850 | struct pnp_card *card; | 829 | struct pnp_card *card; |
830 | u32 eisa_id; | ||
831 | char id[8]; | ||
851 | 832 | ||
852 | isapnp_wait(); | 833 | isapnp_wait(); |
853 | isapnp_key(); | 834 | isapnp_key(); |
@@ -855,32 +836,30 @@ static int __init isapnp_build_device_list(void) | |||
855 | isapnp_wake(csn); | 836 | isapnp_wake(csn); |
856 | isapnp_peek(header, 9); | 837 | isapnp_peek(header, 9); |
857 | checksum = isapnp_checksum(header); | 838 | checksum = isapnp_checksum(header); |
839 | eisa_id = header[0] | header[1] << 8 | | ||
840 | header[2] << 16 | header[3] << 24; | ||
841 | pnp_eisa_id_to_string(eisa_id, id); | ||
842 | card = pnp_alloc_card(&isapnp_protocol, csn, id); | ||
843 | if (!card) | ||
844 | continue; | ||
845 | |||
858 | #if 0 | 846 | #if 0 |
859 | printk(KERN_DEBUG | 847 | dev_info(&card->dev, |
860 | "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", | 848 | "vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", |
861 | header[0], header[1], header[2], header[3], header[4], | 849 | header[0], header[1], header[2], header[3], header[4], |
862 | header[5], header[6], header[7], header[8]); | 850 | header[5], header[6], header[7], header[8]); |
863 | printk(KERN_DEBUG "checksum = 0x%x\n", checksum); | 851 | dev_info(&card->dev, "checksum = %#x\n", checksum); |
864 | #endif | 852 | #endif |
865 | if ((card = | ||
866 | kzalloc(sizeof(struct pnp_card), GFP_KERNEL)) == NULL) | ||
867 | continue; | ||
868 | |||
869 | card->number = csn; | ||
870 | INIT_LIST_HEAD(&card->devices); | 853 | INIT_LIST_HEAD(&card->devices); |
871 | isapnp_parse_card_id(card, (header[1] << 8) | header[0], | ||
872 | (header[3] << 8) | header[2]); | ||
873 | card->serial = | 854 | card->serial = |
874 | (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | | 855 | (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | |
875 | header[4]; | 856 | header[4]; |
876 | isapnp_checksum_value = 0x00; | 857 | isapnp_checksum_value = 0x00; |
877 | isapnp_parse_resource_map(card); | 858 | isapnp_parse_resource_map(card); |
878 | if (isapnp_checksum_value != 0x00) | 859 | if (isapnp_checksum_value != 0x00) |
879 | printk(KERN_ERR | 860 | dev_err(&card->dev, "invalid checksum %#x\n", |
880 | "isapnp: checksum for device %i is not valid (0x%x)\n", | 861 | isapnp_checksum_value); |
881 | csn, isapnp_checksum_value); | ||
882 | card->checksum = isapnp_checksum_value; | 862 | card->checksum = isapnp_checksum_value; |
883 | card->protocol = &isapnp_protocol; | ||
884 | 863 | ||
885 | pnp_add_card(card); | 864 | pnp_add_card(card); |
886 | } | 865 | } |
@@ -947,100 +926,117 @@ EXPORT_SYMBOL(isapnp_cfg_begin); | |||
947 | EXPORT_SYMBOL(isapnp_cfg_end); | 926 | EXPORT_SYMBOL(isapnp_cfg_end); |
948 | EXPORT_SYMBOL(isapnp_write_byte); | 927 | EXPORT_SYMBOL(isapnp_write_byte); |
949 | 928 | ||
950 | static int isapnp_read_resources(struct pnp_dev *dev, | 929 | static int isapnp_get_resources(struct pnp_dev *dev) |
951 | struct pnp_resource_table *res) | ||
952 | { | 930 | { |
953 | int tmp, ret; | 931 | struct pnp_resource *pnp_res; |
932 | int i, ret; | ||
954 | 933 | ||
934 | dev_dbg(&dev->dev, "get resources\n"); | ||
935 | pnp_init_resources(dev); | ||
936 | isapnp_cfg_begin(dev->card->number, dev->number); | ||
955 | dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); | 937 | dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); |
956 | if (dev->active) { | 938 | if (!dev->active) |
957 | for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { | 939 | goto __end; |
958 | ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1)); | 940 | |
959 | if (!ret) | 941 | for (i = 0; i < ISAPNP_MAX_PORT; i++) { |
960 | continue; | 942 | ret = isapnp_read_word(ISAPNP_CFG_PORT + (i << 1)); |
961 | res->port_resource[tmp].start = ret; | 943 | if (ret) { |
962 | res->port_resource[tmp].flags = IORESOURCE_IO; | 944 | pnp_res = pnp_add_io_resource(dev, ret, ret, 0); |
945 | if (pnp_res) | ||
946 | pnp_res->index = i; | ||
963 | } | 947 | } |
964 | for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { | 948 | } |
965 | ret = | 949 | for (i = 0; i < ISAPNP_MAX_MEM; i++) { |
966 | isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8; | 950 | ret = isapnp_read_word(ISAPNP_CFG_MEM + (i << 3)) << 8; |
967 | if (!ret) | 951 | if (ret) { |
968 | continue; | 952 | pnp_res = pnp_add_mem_resource(dev, ret, ret, 0); |
969 | res->mem_resource[tmp].start = ret; | 953 | if (pnp_res) |
970 | res->mem_resource[tmp].flags = IORESOURCE_MEM; | 954 | pnp_res->index = i; |
971 | } | 955 | } |
972 | for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { | 956 | } |
973 | ret = | 957 | for (i = 0; i < ISAPNP_MAX_IRQ; i++) { |
974 | (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> | 958 | ret = isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)) >> 8; |
975 | 8); | 959 | if (ret) { |
976 | if (!ret) | 960 | pnp_res = pnp_add_irq_resource(dev, ret, 0); |
977 | continue; | 961 | if (pnp_res) |
978 | res->irq_resource[tmp].start = | 962 | pnp_res->index = i; |
979 | res->irq_resource[tmp].end = ret; | ||
980 | res->irq_resource[tmp].flags = IORESOURCE_IRQ; | ||
981 | } | 963 | } |
982 | for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { | 964 | } |
983 | ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); | 965 | for (i = 0; i < ISAPNP_MAX_DMA; i++) { |
984 | if (ret == 4) | 966 | ret = isapnp_read_byte(ISAPNP_CFG_DMA + i); |
985 | continue; | 967 | if (ret != 4) { |
986 | res->dma_resource[tmp].start = | 968 | pnp_res = pnp_add_dma_resource(dev, ret, 0); |
987 | res->dma_resource[tmp].end = ret; | 969 | if (pnp_res) |
988 | res->dma_resource[tmp].flags = IORESOURCE_DMA; | 970 | pnp_res->index = i; |
989 | } | 971 | } |
990 | } | 972 | } |
991 | return 0; | ||
992 | } | ||
993 | |||
994 | static int isapnp_get_resources(struct pnp_dev *dev, | ||
995 | struct pnp_resource_table *res) | ||
996 | { | ||
997 | int ret; | ||
998 | 973 | ||
999 | pnp_init_resource_table(res); | 974 | __end: |
1000 | isapnp_cfg_begin(dev->card->number, dev->number); | ||
1001 | ret = isapnp_read_resources(dev, res); | ||
1002 | isapnp_cfg_end(); | 975 | isapnp_cfg_end(); |
1003 | return ret; | 976 | return 0; |
1004 | } | 977 | } |
1005 | 978 | ||
1006 | static int isapnp_set_resources(struct pnp_dev *dev, | 979 | static int isapnp_set_resources(struct pnp_dev *dev) |
1007 | struct pnp_resource_table *res) | ||
1008 | { | 980 | { |
1009 | int tmp; | 981 | struct pnp_resource *pnp_res; |
982 | struct resource *res; | ||
983 | int tmp, index; | ||
1010 | 984 | ||
985 | dev_dbg(&dev->dev, "set resources\n"); | ||
1011 | isapnp_cfg_begin(dev->card->number, dev->number); | 986 | isapnp_cfg_begin(dev->card->number, dev->number); |
1012 | dev->active = 1; | 987 | dev->active = 1; |
1013 | for (tmp = 0; | 988 | for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) { |
1014 | tmp < ISAPNP_MAX_PORT | 989 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, tmp); |
1015 | && (res->port_resource[tmp]. | 990 | if (!pnp_res) |
1016 | flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; | 991 | continue; |
1017 | tmp++) | 992 | res = &pnp_res->res; |
1018 | isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), | 993 | if (pnp_resource_valid(res)) { |
1019 | res->port_resource[tmp].start); | 994 | index = pnp_res->index; |
1020 | for (tmp = 0; | 995 | dev_dbg(&dev->dev, " set io %d to %#llx\n", |
1021 | tmp < ISAPNP_MAX_IRQ | 996 | index, (unsigned long long) res->start); |
1022 | && (res->irq_resource[tmp]. | 997 | isapnp_write_word(ISAPNP_CFG_PORT + (index << 1), |
1023 | flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; | 998 | res->start); |
1024 | tmp++) { | 999 | } |
1025 | int irq = res->irq_resource[tmp].start; | 1000 | } |
1026 | if (irq == 2) | 1001 | for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) { |
1027 | irq = 9; | 1002 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, tmp); |
1028 | isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); | 1003 | if (!pnp_res) |
1004 | continue; | ||
1005 | res = &pnp_res->res; | ||
1006 | if (pnp_resource_valid(res)) { | ||
1007 | int irq = res->start; | ||
1008 | if (irq == 2) | ||
1009 | irq = 9; | ||
1010 | index = pnp_res->index; | ||
1011 | dev_dbg(&dev->dev, " set irq %d to %d\n", index, irq); | ||
1012 | isapnp_write_byte(ISAPNP_CFG_IRQ + (index << 1), irq); | ||
1013 | } | ||
1014 | } | ||
1015 | for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) { | ||
1016 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, tmp); | ||
1017 | if (!pnp_res) | ||
1018 | continue; | ||
1019 | res = &pnp_res->res; | ||
1020 | if (pnp_resource_valid(res)) { | ||
1021 | index = pnp_res->index; | ||
1022 | dev_dbg(&dev->dev, " set dma %d to %lld\n", | ||
1023 | index, (unsigned long long) res->start); | ||
1024 | isapnp_write_byte(ISAPNP_CFG_DMA + index, res->start); | ||
1025 | } | ||
1026 | } | ||
1027 | for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) { | ||
1028 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, tmp); | ||
1029 | if (!pnp_res) | ||
1030 | continue; | ||
1031 | res = &pnp_res->res; | ||
1032 | if (pnp_resource_valid(res)) { | ||
1033 | index = pnp_res->index; | ||
1034 | dev_dbg(&dev->dev, " set mem %d to %#llx\n", | ||
1035 | index, (unsigned long long) res->start); | ||
1036 | isapnp_write_word(ISAPNP_CFG_MEM + (index << 3), | ||
1037 | (res->start >> 8) & 0xffff); | ||
1038 | } | ||
1029 | } | 1039 | } |
1030 | for (tmp = 0; | ||
1031 | tmp < ISAPNP_MAX_DMA | ||
1032 | && (res->dma_resource[tmp]. | ||
1033 | flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA; | ||
1034 | tmp++) | ||
1035 | isapnp_write_byte(ISAPNP_CFG_DMA + tmp, | ||
1036 | res->dma_resource[tmp].start); | ||
1037 | for (tmp = 0; | ||
1038 | tmp < ISAPNP_MAX_MEM | ||
1039 | && (res->mem_resource[tmp]. | ||
1040 | flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM; | ||
1041 | tmp++) | ||
1042 | isapnp_write_word(ISAPNP_CFG_MEM + (tmp << 3), | ||
1043 | (res->mem_resource[tmp].start >> 8) & 0xffff); | ||
1044 | /* FIXME: We aren't handling 32bit mems properly here */ | 1040 | /* FIXME: We aren't handling 32bit mems properly here */ |
1045 | isapnp_activate(dev->number); | 1041 | isapnp_activate(dev->number); |
1046 | isapnp_cfg_end(); | 1042 | isapnp_cfg_end(); |
@@ -1138,13 +1134,13 @@ static int __init isapnp_init(void) | |||
1138 | protocol_for_each_card(&isapnp_protocol, card) { | 1134 | protocol_for_each_card(&isapnp_protocol, card) { |
1139 | cards++; | 1135 | cards++; |
1140 | if (isapnp_verbose) { | 1136 | if (isapnp_verbose) { |
1141 | printk(KERN_INFO "isapnp: Card '%s'\n", | 1137 | dev_info(&card->dev, "card '%s'\n", |
1142 | card->name[0] ? card->name : "Unknown"); | 1138 | card->name[0] ? card->name : "unknown"); |
1143 | if (isapnp_verbose < 2) | 1139 | if (isapnp_verbose < 2) |
1144 | continue; | 1140 | continue; |
1145 | card_for_each_dev(card, dev) { | 1141 | card_for_each_dev(card, dev) { |
1146 | printk(KERN_INFO "isapnp: Device '%s'\n", | 1142 | dev_info(&card->dev, "device '%s'\n", |
1147 | dev->name[0] ? dev->name : "Unknown"); | 1143 | dev->name[0] ? dev->name : "unknown"); |
1148 | } | 1144 | } |
1149 | } | 1145 | } |
1150 | } | 1146 | } |
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index c28caf272c11..bea0914ff947 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c | |||
@@ -19,100 +19,118 @@ DEFINE_MUTEX(pnp_res_mutex); | |||
19 | 19 | ||
20 | static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) | 20 | static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) |
21 | { | 21 | { |
22 | resource_size_t *start, *end; | 22 | struct pnp_resource *pnp_res; |
23 | unsigned long *flags; | 23 | struct resource *res; |
24 | 24 | ||
25 | if (idx >= PNP_MAX_PORT) { | 25 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx); |
26 | if (!pnp_res) { | ||
26 | dev_err(&dev->dev, "too many I/O port resources\n"); | 27 | dev_err(&dev->dev, "too many I/O port resources\n"); |
27 | /* pretend we were successful so at least the manager won't try again */ | 28 | /* pretend we were successful so at least the manager won't try again */ |
28 | return 1; | 29 | return 1; |
29 | } | 30 | } |
30 | 31 | ||
32 | res = &pnp_res->res; | ||
33 | |||
31 | /* check if this resource has been manually set, if so skip */ | 34 | /* check if this resource has been manually set, if so skip */ |
32 | if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) | 35 | if (!(res->flags & IORESOURCE_AUTO)) { |
36 | dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " | ||
37 | "flags %#lx\n", idx, (unsigned long long) res->start, | ||
38 | (unsigned long long) res->end, res->flags); | ||
33 | return 1; | 39 | return 1; |
34 | 40 | } | |
35 | start = &dev->res.port_resource[idx].start; | ||
36 | end = &dev->res.port_resource[idx].end; | ||
37 | flags = &dev->res.port_resource[idx].flags; | ||
38 | 41 | ||
39 | /* set the initial values */ | 42 | /* set the initial values */ |
40 | *flags |= rule->flags | IORESOURCE_IO; | 43 | pnp_res->index = idx; |
41 | *flags &= ~IORESOURCE_UNSET; | 44 | res->flags |= rule->flags | IORESOURCE_IO; |
45 | res->flags &= ~IORESOURCE_UNSET; | ||
42 | 46 | ||
43 | if (!rule->size) { | 47 | if (!rule->size) { |
44 | *flags |= IORESOURCE_DISABLED; | 48 | res->flags |= IORESOURCE_DISABLED; |
49 | dev_dbg(&dev->dev, " io %d disabled\n", idx); | ||
45 | return 1; /* skip disabled resource requests */ | 50 | return 1; /* skip disabled resource requests */ |
46 | } | 51 | } |
47 | 52 | ||
48 | *start = rule->min; | 53 | res->start = rule->min; |
49 | *end = *start + rule->size - 1; | 54 | res->end = res->start + rule->size - 1; |
50 | 55 | ||
51 | /* run through until pnp_check_port is happy */ | 56 | /* run through until pnp_check_port is happy */ |
52 | while (!pnp_check_port(dev, idx)) { | 57 | while (!pnp_check_port(dev, res)) { |
53 | *start += rule->align; | 58 | res->start += rule->align; |
54 | *end = *start + rule->size - 1; | 59 | res->end = res->start + rule->size - 1; |
55 | if (*start > rule->max || !rule->align) | 60 | if (res->start > rule->max || !rule->align) { |
61 | dev_dbg(&dev->dev, " couldn't assign io %d\n", idx); | ||
56 | return 0; | 62 | return 0; |
63 | } | ||
57 | } | 64 | } |
65 | dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx, | ||
66 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
58 | return 1; | 67 | return 1; |
59 | } | 68 | } |
60 | 69 | ||
61 | static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) | 70 | static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) |
62 | { | 71 | { |
63 | resource_size_t *start, *end; | 72 | struct pnp_resource *pnp_res; |
64 | unsigned long *flags; | 73 | struct resource *res; |
65 | 74 | ||
66 | if (idx >= PNP_MAX_MEM) { | 75 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx); |
76 | if (!pnp_res) { | ||
67 | dev_err(&dev->dev, "too many memory resources\n"); | 77 | dev_err(&dev->dev, "too many memory resources\n"); |
68 | /* pretend we were successful so at least the manager won't try again */ | 78 | /* pretend we were successful so at least the manager won't try again */ |
69 | return 1; | 79 | return 1; |
70 | } | 80 | } |
71 | 81 | ||
82 | res = &pnp_res->res; | ||
83 | |||
72 | /* check if this resource has been manually set, if so skip */ | 84 | /* check if this resource has been manually set, if so skip */ |
73 | if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) | 85 | if (!(res->flags & IORESOURCE_AUTO)) { |
86 | dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " | ||
87 | "flags %#lx\n", idx, (unsigned long long) res->start, | ||
88 | (unsigned long long) res->end, res->flags); | ||
74 | return 1; | 89 | return 1; |
75 | 90 | } | |
76 | start = &dev->res.mem_resource[idx].start; | ||
77 | end = &dev->res.mem_resource[idx].end; | ||
78 | flags = &dev->res.mem_resource[idx].flags; | ||
79 | 91 | ||
80 | /* set the initial values */ | 92 | /* set the initial values */ |
81 | *flags |= rule->flags | IORESOURCE_MEM; | 93 | pnp_res->index = idx; |
82 | *flags &= ~IORESOURCE_UNSET; | 94 | res->flags |= rule->flags | IORESOURCE_MEM; |
95 | res->flags &= ~IORESOURCE_UNSET; | ||
83 | 96 | ||
84 | /* convert pnp flags to standard Linux flags */ | 97 | /* convert pnp flags to standard Linux flags */ |
85 | if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) | 98 | if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) |
86 | *flags |= IORESOURCE_READONLY; | 99 | res->flags |= IORESOURCE_READONLY; |
87 | if (rule->flags & IORESOURCE_MEM_CACHEABLE) | 100 | if (rule->flags & IORESOURCE_MEM_CACHEABLE) |
88 | *flags |= IORESOURCE_CACHEABLE; | 101 | res->flags |= IORESOURCE_CACHEABLE; |
89 | if (rule->flags & IORESOURCE_MEM_RANGELENGTH) | 102 | if (rule->flags & IORESOURCE_MEM_RANGELENGTH) |
90 | *flags |= IORESOURCE_RANGELENGTH; | 103 | res->flags |= IORESOURCE_RANGELENGTH; |
91 | if (rule->flags & IORESOURCE_MEM_SHADOWABLE) | 104 | if (rule->flags & IORESOURCE_MEM_SHADOWABLE) |
92 | *flags |= IORESOURCE_SHADOWABLE; | 105 | res->flags |= IORESOURCE_SHADOWABLE; |
93 | 106 | ||
94 | if (!rule->size) { | 107 | if (!rule->size) { |
95 | *flags |= IORESOURCE_DISABLED; | 108 | res->flags |= IORESOURCE_DISABLED; |
109 | dev_dbg(&dev->dev, " mem %d disabled\n", idx); | ||
96 | return 1; /* skip disabled resource requests */ | 110 | return 1; /* skip disabled resource requests */ |
97 | } | 111 | } |
98 | 112 | ||
99 | *start = rule->min; | 113 | res->start = rule->min; |
100 | *end = *start + rule->size - 1; | 114 | res->end = res->start + rule->size - 1; |
101 | 115 | ||
102 | /* run through until pnp_check_mem is happy */ | 116 | /* run through until pnp_check_mem is happy */ |
103 | while (!pnp_check_mem(dev, idx)) { | 117 | while (!pnp_check_mem(dev, res)) { |
104 | *start += rule->align; | 118 | res->start += rule->align; |
105 | *end = *start + rule->size - 1; | 119 | res->end = res->start + rule->size - 1; |
106 | if (*start > rule->max || !rule->align) | 120 | if (res->start > rule->max || !rule->align) { |
121 | dev_dbg(&dev->dev, " couldn't assign mem %d\n", idx); | ||
107 | return 0; | 122 | return 0; |
123 | } | ||
108 | } | 124 | } |
125 | dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx, | ||
126 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
109 | return 1; | 127 | return 1; |
110 | } | 128 | } |
111 | 129 | ||
112 | static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) | 130 | static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) |
113 | { | 131 | { |
114 | resource_size_t *start, *end; | 132 | struct pnp_resource *pnp_res; |
115 | unsigned long *flags; | 133 | struct resource *res; |
116 | int i; | 134 | int i; |
117 | 135 | ||
118 | /* IRQ priority: this table is good for i386 */ | 136 | /* IRQ priority: this table is good for i386 */ |
@@ -120,49 +138,59 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) | |||
120 | 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 | 138 | 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 |
121 | }; | 139 | }; |
122 | 140 | ||
123 | if (idx >= PNP_MAX_IRQ) { | 141 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx); |
142 | if (!pnp_res) { | ||
124 | dev_err(&dev->dev, "too many IRQ resources\n"); | 143 | dev_err(&dev->dev, "too many IRQ resources\n"); |
125 | /* pretend we were successful so at least the manager won't try again */ | 144 | /* pretend we were successful so at least the manager won't try again */ |
126 | return 1; | 145 | return 1; |
127 | } | 146 | } |
128 | 147 | ||
148 | res = &pnp_res->res; | ||
149 | |||
129 | /* check if this resource has been manually set, if so skip */ | 150 | /* check if this resource has been manually set, if so skip */ |
130 | if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) | 151 | if (!(res->flags & IORESOURCE_AUTO)) { |
152 | dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", | ||
153 | idx, (int) res->start, res->flags); | ||
131 | return 1; | 154 | return 1; |
132 | 155 | } | |
133 | start = &dev->res.irq_resource[idx].start; | ||
134 | end = &dev->res.irq_resource[idx].end; | ||
135 | flags = &dev->res.irq_resource[idx].flags; | ||
136 | 156 | ||
137 | /* set the initial values */ | 157 | /* set the initial values */ |
138 | *flags |= rule->flags | IORESOURCE_IRQ; | 158 | pnp_res->index = idx; |
139 | *flags &= ~IORESOURCE_UNSET; | 159 | res->flags |= rule->flags | IORESOURCE_IRQ; |
160 | res->flags &= ~IORESOURCE_UNSET; | ||
140 | 161 | ||
141 | if (bitmap_empty(rule->map, PNP_IRQ_NR)) { | 162 | if (bitmap_empty(rule->map, PNP_IRQ_NR)) { |
142 | *flags |= IORESOURCE_DISABLED; | 163 | res->flags |= IORESOURCE_DISABLED; |
164 | dev_dbg(&dev->dev, " irq %d disabled\n", idx); | ||
143 | return 1; /* skip disabled resource requests */ | 165 | return 1; /* skip disabled resource requests */ |
144 | } | 166 | } |
145 | 167 | ||
146 | /* TBD: need check for >16 IRQ */ | 168 | /* TBD: need check for >16 IRQ */ |
147 | *start = find_next_bit(rule->map, PNP_IRQ_NR, 16); | 169 | res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16); |
148 | if (*start < PNP_IRQ_NR) { | 170 | if (res->start < PNP_IRQ_NR) { |
149 | *end = *start; | 171 | res->end = res->start; |
172 | dev_dbg(&dev->dev, " assign irq %d %d\n", idx, | ||
173 | (int) res->start); | ||
150 | return 1; | 174 | return 1; |
151 | } | 175 | } |
152 | for (i = 0; i < 16; i++) { | 176 | for (i = 0; i < 16; i++) { |
153 | if (test_bit(xtab[i], rule->map)) { | 177 | if (test_bit(xtab[i], rule->map)) { |
154 | *start = *end = xtab[i]; | 178 | res->start = res->end = xtab[i]; |
155 | if (pnp_check_irq(dev, idx)) | 179 | if (pnp_check_irq(dev, res)) { |
180 | dev_dbg(&dev->dev, " assign irq %d %d\n", idx, | ||
181 | (int) res->start); | ||
156 | return 1; | 182 | return 1; |
183 | } | ||
157 | } | 184 | } |
158 | } | 185 | } |
186 | dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); | ||
159 | return 0; | 187 | return 0; |
160 | } | 188 | } |
161 | 189 | ||
162 | static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) | 190 | static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) |
163 | { | 191 | { |
164 | resource_size_t *start, *end; | 192 | struct pnp_resource *pnp_res; |
165 | unsigned long *flags; | 193 | struct resource *res; |
166 | int i; | 194 | int i; |
167 | 195 | ||
168 | /* DMA priority: this table is good for i386 */ | 196 | /* DMA priority: this table is good for i386 */ |
@@ -170,71 +198,89 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) | |||
170 | 1, 3, 5, 6, 7, 0, 2, 4 | 198 | 1, 3, 5, 6, 7, 0, 2, 4 |
171 | }; | 199 | }; |
172 | 200 | ||
173 | if (idx >= PNP_MAX_DMA) { | 201 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx); |
202 | if (!pnp_res) { | ||
174 | dev_err(&dev->dev, "too many DMA resources\n"); | 203 | dev_err(&dev->dev, "too many DMA resources\n"); |
175 | return; | 204 | return; |
176 | } | 205 | } |
177 | 206 | ||
207 | res = &pnp_res->res; | ||
208 | |||
178 | /* check if this resource has been manually set, if so skip */ | 209 | /* check if this resource has been manually set, if so skip */ |
179 | if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) | 210 | if (!(res->flags & IORESOURCE_AUTO)) { |
211 | dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", | ||
212 | idx, (int) res->start, res->flags); | ||
180 | return; | 213 | return; |
181 | 214 | } | |
182 | start = &dev->res.dma_resource[idx].start; | ||
183 | end = &dev->res.dma_resource[idx].end; | ||
184 | flags = &dev->res.dma_resource[idx].flags; | ||
185 | 215 | ||
186 | /* set the initial values */ | 216 | /* set the initial values */ |
187 | *flags |= rule->flags | IORESOURCE_DMA; | 217 | pnp_res->index = idx; |
188 | *flags &= ~IORESOURCE_UNSET; | 218 | res->flags |= rule->flags | IORESOURCE_DMA; |
219 | res->flags &= ~IORESOURCE_UNSET; | ||
189 | 220 | ||
190 | for (i = 0; i < 8; i++) { | 221 | for (i = 0; i < 8; i++) { |
191 | if (rule->map & (1 << xtab[i])) { | 222 | if (rule->map & (1 << xtab[i])) { |
192 | *start = *end = xtab[i]; | 223 | res->start = res->end = xtab[i]; |
193 | if (pnp_check_dma(dev, idx)) | 224 | if (pnp_check_dma(dev, res)) { |
225 | dev_dbg(&dev->dev, " assign dma %d %d\n", idx, | ||
226 | (int) res->start); | ||
194 | return; | 227 | return; |
228 | } | ||
195 | } | 229 | } |
196 | } | 230 | } |
197 | #ifdef MAX_DMA_CHANNELS | 231 | #ifdef MAX_DMA_CHANNELS |
198 | *start = *end = MAX_DMA_CHANNELS; | 232 | res->start = res->end = MAX_DMA_CHANNELS; |
199 | #endif | 233 | #endif |
200 | *flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; | 234 | res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; |
235 | dev_dbg(&dev->dev, " disable dma %d\n", idx); | ||
236 | } | ||
237 | |||
238 | void pnp_init_resource(struct resource *res) | ||
239 | { | ||
240 | unsigned long type; | ||
241 | |||
242 | type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM | | ||
243 | IORESOURCE_IRQ | IORESOURCE_DMA); | ||
244 | |||
245 | res->name = NULL; | ||
246 | res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
247 | if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) { | ||
248 | res->start = -1; | ||
249 | res->end = -1; | ||
250 | } else { | ||
251 | res->start = 0; | ||
252 | res->end = 0; | ||
253 | } | ||
201 | } | 254 | } |
202 | 255 | ||
203 | /** | 256 | /** |
204 | * pnp_init_resources - Resets a resource table to default values. | 257 | * pnp_init_resources - Resets a resource table to default values. |
205 | * @table: pointer to the desired resource table | 258 | * @table: pointer to the desired resource table |
206 | */ | 259 | */ |
207 | void pnp_init_resource_table(struct pnp_resource_table *table) | 260 | void pnp_init_resources(struct pnp_dev *dev) |
208 | { | 261 | { |
262 | struct resource *res; | ||
209 | int idx; | 263 | int idx; |
210 | 264 | ||
211 | for (idx = 0; idx < PNP_MAX_IRQ; idx++) { | 265 | for (idx = 0; idx < PNP_MAX_IRQ; idx++) { |
212 | table->irq_resource[idx].name = NULL; | 266 | res = &dev->res->irq[idx].res; |
213 | table->irq_resource[idx].start = -1; | 267 | res->flags = IORESOURCE_IRQ; |
214 | table->irq_resource[idx].end = -1; | 268 | pnp_init_resource(res); |
215 | table->irq_resource[idx].flags = | ||
216 | IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
217 | } | 269 | } |
218 | for (idx = 0; idx < PNP_MAX_DMA; idx++) { | 270 | for (idx = 0; idx < PNP_MAX_DMA; idx++) { |
219 | table->dma_resource[idx].name = NULL; | 271 | res = &dev->res->dma[idx].res; |
220 | table->dma_resource[idx].start = -1; | 272 | res->flags = IORESOURCE_DMA; |
221 | table->dma_resource[idx].end = -1; | 273 | pnp_init_resource(res); |
222 | table->dma_resource[idx].flags = | ||
223 | IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
224 | } | 274 | } |
225 | for (idx = 0; idx < PNP_MAX_PORT; idx++) { | 275 | for (idx = 0; idx < PNP_MAX_PORT; idx++) { |
226 | table->port_resource[idx].name = NULL; | 276 | res = &dev->res->port[idx].res; |
227 | table->port_resource[idx].start = 0; | 277 | res->flags = IORESOURCE_IO; |
228 | table->port_resource[idx].end = 0; | 278 | pnp_init_resource(res); |
229 | table->port_resource[idx].flags = | ||
230 | IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
231 | } | 279 | } |
232 | for (idx = 0; idx < PNP_MAX_MEM; idx++) { | 280 | for (idx = 0; idx < PNP_MAX_MEM; idx++) { |
233 | table->mem_resource[idx].name = NULL; | 281 | res = &dev->res->mem[idx].res; |
234 | table->mem_resource[idx].start = 0; | 282 | res->flags = IORESOURCE_MEM; |
235 | table->mem_resource[idx].end = 0; | 283 | pnp_init_resource(res); |
236 | table->mem_resource[idx].flags = | ||
237 | IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
238 | } | 284 | } |
239 | } | 285 | } |
240 | 286 | ||
@@ -242,41 +288,38 @@ void pnp_init_resource_table(struct pnp_resource_table *table) | |||
242 | * pnp_clean_resources - clears resources that were not manually set | 288 | * pnp_clean_resources - clears resources that were not manually set |
243 | * @res: the resources to clean | 289 | * @res: the resources to clean |
244 | */ | 290 | */ |
245 | static void pnp_clean_resource_table(struct pnp_resource_table *res) | 291 | static void pnp_clean_resource_table(struct pnp_dev *dev) |
246 | { | 292 | { |
293 | struct resource *res; | ||
247 | int idx; | 294 | int idx; |
248 | 295 | ||
249 | for (idx = 0; idx < PNP_MAX_IRQ; idx++) { | 296 | for (idx = 0; idx < PNP_MAX_IRQ; idx++) { |
250 | if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO)) | 297 | res = &dev->res->irq[idx].res; |
251 | continue; | 298 | if (res->flags & IORESOURCE_AUTO) { |
252 | res->irq_resource[idx].start = -1; | 299 | res->flags = IORESOURCE_IRQ; |
253 | res->irq_resource[idx].end = -1; | 300 | pnp_init_resource(res); |
254 | res->irq_resource[idx].flags = | 301 | } |
255 | IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
256 | } | 302 | } |
257 | for (idx = 0; idx < PNP_MAX_DMA; idx++) { | 303 | for (idx = 0; idx < PNP_MAX_DMA; idx++) { |
258 | if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO)) | 304 | res = &dev->res->dma[idx].res; |
259 | continue; | 305 | if (res->flags & IORESOURCE_AUTO) { |
260 | res->dma_resource[idx].start = -1; | 306 | res->flags = IORESOURCE_DMA; |
261 | res->dma_resource[idx].end = -1; | 307 | pnp_init_resource(res); |
262 | res->dma_resource[idx].flags = | 308 | } |
263 | IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
264 | } | 309 | } |
265 | for (idx = 0; idx < PNP_MAX_PORT; idx++) { | 310 | for (idx = 0; idx < PNP_MAX_PORT; idx++) { |
266 | if (!(res->port_resource[idx].flags & IORESOURCE_AUTO)) | 311 | res = &dev->res->port[idx].res; |
267 | continue; | 312 | if (res->flags & IORESOURCE_AUTO) { |
268 | res->port_resource[idx].start = 0; | 313 | res->flags = IORESOURCE_IO; |
269 | res->port_resource[idx].end = 0; | 314 | pnp_init_resource(res); |
270 | res->port_resource[idx].flags = | 315 | } |
271 | IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
272 | } | 316 | } |
273 | for (idx = 0; idx < PNP_MAX_MEM; idx++) { | 317 | for (idx = 0; idx < PNP_MAX_MEM; idx++) { |
274 | if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO)) | 318 | res = &dev->res->mem[idx].res; |
275 | continue; | 319 | if (res->flags & IORESOURCE_AUTO) { |
276 | res->mem_resource[idx].start = 0; | 320 | res->flags = IORESOURCE_MEM; |
277 | res->mem_resource[idx].end = 0; | 321 | pnp_init_resource(res); |
278 | res->mem_resource[idx].flags = | 322 | } |
279 | IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
280 | } | 323 | } |
281 | } | 324 | } |
282 | 325 | ||
@@ -298,9 +341,11 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | |||
298 | if (!pnp_can_configure(dev)) | 341 | if (!pnp_can_configure(dev)) |
299 | return -ENODEV; | 342 | return -ENODEV; |
300 | 343 | ||
344 | dbg_pnp_show_resources(dev, "before pnp_assign_resources"); | ||
301 | mutex_lock(&pnp_res_mutex); | 345 | mutex_lock(&pnp_res_mutex); |
302 | pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ | 346 | pnp_clean_resource_table(dev); |
303 | if (dev->independent) { | 347 | if (dev->independent) { |
348 | dev_dbg(&dev->dev, "assigning independent options\n"); | ||
304 | port = dev->independent->port; | 349 | port = dev->independent->port; |
305 | mem = dev->independent->mem; | 350 | mem = dev->independent->mem; |
306 | irq = dev->independent->irq; | 351 | irq = dev->independent->irq; |
@@ -333,6 +378,8 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | |||
333 | if (depnum) { | 378 | if (depnum) { |
334 | struct pnp_option *dep; | 379 | struct pnp_option *dep; |
335 | int i; | 380 | int i; |
381 | |||
382 | dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum); | ||
336 | for (i = 1, dep = dev->dependent; i < depnum; | 383 | for (i = 1, dep = dev->dependent; i < depnum; |
337 | i++, dep = dep->next) | 384 | i++, dep = dep->next) |
338 | if (!dep) | 385 | if (!dep) |
@@ -368,68 +415,17 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | |||
368 | goto fail; | 415 | goto fail; |
369 | 416 | ||
370 | mutex_unlock(&pnp_res_mutex); | 417 | mutex_unlock(&pnp_res_mutex); |
418 | dbg_pnp_show_resources(dev, "after pnp_assign_resources"); | ||
371 | return 1; | 419 | return 1; |
372 | 420 | ||
373 | fail: | 421 | fail: |
374 | pnp_clean_resource_table(&dev->res); | 422 | pnp_clean_resource_table(dev); |
375 | mutex_unlock(&pnp_res_mutex); | 423 | mutex_unlock(&pnp_res_mutex); |
424 | dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)"); | ||
376 | return 0; | 425 | return 0; |
377 | } | 426 | } |
378 | 427 | ||
379 | /** | 428 | /** |
380 | * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table | ||
381 | * @dev: pointer to the desired device | ||
382 | * @res: pointer to the new resource config | ||
383 | * @mode: 0 or PNP_CONFIG_FORCE | ||
384 | * | ||
385 | * This function can be used by drivers that want to manually set thier resources. | ||
386 | */ | ||
387 | int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, | ||
388 | int mode) | ||
389 | { | ||
390 | int i; | ||
391 | struct pnp_resource_table *bak; | ||
392 | |||
393 | if (!pnp_can_configure(dev)) | ||
394 | return -ENODEV; | ||
395 | bak = pnp_alloc(sizeof(struct pnp_resource_table)); | ||
396 | if (!bak) | ||
397 | return -ENOMEM; | ||
398 | *bak = dev->res; | ||
399 | |||
400 | mutex_lock(&pnp_res_mutex); | ||
401 | dev->res = *res; | ||
402 | if (!(mode & PNP_CONFIG_FORCE)) { | ||
403 | for (i = 0; i < PNP_MAX_PORT; i++) { | ||
404 | if (!pnp_check_port(dev, i)) | ||
405 | goto fail; | ||
406 | } | ||
407 | for (i = 0; i < PNP_MAX_MEM; i++) { | ||
408 | if (!pnp_check_mem(dev, i)) | ||
409 | goto fail; | ||
410 | } | ||
411 | for (i = 0; i < PNP_MAX_IRQ; i++) { | ||
412 | if (!pnp_check_irq(dev, i)) | ||
413 | goto fail; | ||
414 | } | ||
415 | for (i = 0; i < PNP_MAX_DMA; i++) { | ||
416 | if (!pnp_check_dma(dev, i)) | ||
417 | goto fail; | ||
418 | } | ||
419 | } | ||
420 | mutex_unlock(&pnp_res_mutex); | ||
421 | |||
422 | kfree(bak); | ||
423 | return 0; | ||
424 | |||
425 | fail: | ||
426 | dev->res = *bak; | ||
427 | mutex_unlock(&pnp_res_mutex); | ||
428 | kfree(bak); | ||
429 | return -EINVAL; | ||
430 | } | ||
431 | |||
432 | /** | ||
433 | * pnp_auto_config_dev - automatically assigns resources to a device | 429 | * pnp_auto_config_dev - automatically assigns resources to a device |
434 | * @dev: pointer to the desired device | 430 | * @dev: pointer to the desired device |
435 | */ | 431 | */ |
@@ -473,7 +469,8 @@ int pnp_start_dev(struct pnp_dev *dev) | |||
473 | return -EINVAL; | 469 | return -EINVAL; |
474 | } | 470 | } |
475 | 471 | ||
476 | if (dev->protocol->set(dev, &dev->res) < 0) { | 472 | dbg_pnp_show_resources(dev, "pnp_start_dev"); |
473 | if (dev->protocol->set(dev) < 0) { | ||
477 | dev_err(&dev->dev, "activation failed\n"); | 474 | dev_err(&dev->dev, "activation failed\n"); |
478 | return -EIO; | 475 | return -EIO; |
479 | } | 476 | } |
@@ -549,30 +546,13 @@ int pnp_disable_dev(struct pnp_dev *dev) | |||
549 | 546 | ||
550 | /* release the resources so that other devices can use them */ | 547 | /* release the resources so that other devices can use them */ |
551 | mutex_lock(&pnp_res_mutex); | 548 | mutex_lock(&pnp_res_mutex); |
552 | pnp_clean_resource_table(&dev->res); | 549 | pnp_clean_resource_table(dev); |
553 | mutex_unlock(&pnp_res_mutex); | 550 | mutex_unlock(&pnp_res_mutex); |
554 | 551 | ||
555 | return 0; | 552 | return 0; |
556 | } | 553 | } |
557 | 554 | ||
558 | /** | ||
559 | * pnp_resource_change - change one resource | ||
560 | * @resource: pointer to resource to be changed | ||
561 | * @start: start of region | ||
562 | * @size: size of region | ||
563 | */ | ||
564 | void pnp_resource_change(struct resource *resource, resource_size_t start, | ||
565 | resource_size_t size) | ||
566 | { | ||
567 | resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET); | ||
568 | resource->start = start; | ||
569 | resource->end = start + size - 1; | ||
570 | } | ||
571 | |||
572 | EXPORT_SYMBOL(pnp_manual_config_dev); | ||
573 | EXPORT_SYMBOL(pnp_start_dev); | 555 | EXPORT_SYMBOL(pnp_start_dev); |
574 | EXPORT_SYMBOL(pnp_stop_dev); | 556 | EXPORT_SYMBOL(pnp_stop_dev); |
575 | EXPORT_SYMBOL(pnp_activate_dev); | 557 | EXPORT_SYMBOL(pnp_activate_dev); |
576 | EXPORT_SYMBOL(pnp_disable_dev); | 558 | EXPORT_SYMBOL(pnp_disable_dev); |
577 | EXPORT_SYMBOL(pnp_resource_change); | ||
578 | EXPORT_SYMBOL(pnp_init_resource_table); | ||
diff --git a/drivers/pnp/pnpacpi/Makefile b/drivers/pnp/pnpacpi/Makefile index 905326fcca85..2d7a1e6908be 100644 --- a/drivers/pnp/pnpacpi/Makefile +++ b/drivers/pnp/pnpacpi/Makefile | |||
@@ -3,3 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := core.o rsparser.o | 5 | obj-y := core.o rsparser.o |
6 | |||
7 | ifeq ($(CONFIG_PNP_DEBUG),y) | ||
8 | EXTRA_CFLAGS += -DDEBUG | ||
9 | endif | ||
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index c283a9a70d83..50902773beaf 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <acpi/acpi_bus.h> | 25 | #include <acpi/acpi_bus.h> |
26 | #include <acpi/actypes.h> | 26 | #include <acpi/actypes.h> |
27 | 27 | ||
28 | #include "../base.h" | ||
28 | #include "pnpacpi.h" | 29 | #include "pnpacpi.h" |
29 | 30 | ||
30 | static int num = 0; | 31 | static int num = 0; |
@@ -44,7 +45,7 @@ static struct acpi_device_id excluded_id_list[] __initdata = { | |||
44 | {"", 0}, | 45 | {"", 0}, |
45 | }; | 46 | }; |
46 | 47 | ||
47 | static inline int is_exclusive_device(struct acpi_device *dev) | 48 | static inline int __init is_exclusive_device(struct acpi_device *dev) |
48 | { | 49 | { |
49 | return (!acpi_match_device_ids(dev, excluded_id_list)); | 50 | return (!acpi_match_device_ids(dev, excluded_id_list)); |
50 | } | 51 | } |
@@ -72,40 +73,24 @@ static int __init ispnpidacpi(char *id) | |||
72 | return 1; | 73 | return 1; |
73 | } | 74 | } |
74 | 75 | ||
75 | static void __init pnpidacpi_to_pnpid(char *id, char *str) | 76 | static int pnpacpi_get_resources(struct pnp_dev *dev) |
76 | { | 77 | { |
77 | str[0] = id[0]; | 78 | dev_dbg(&dev->dev, "get resources\n"); |
78 | str[1] = id[1]; | 79 | return pnpacpi_parse_allocated_resource(dev); |
79 | str[2] = id[2]; | ||
80 | str[3] = tolower(id[3]); | ||
81 | str[4] = tolower(id[4]); | ||
82 | str[5] = tolower(id[5]); | ||
83 | str[6] = tolower(id[6]); | ||
84 | str[7] = '\0'; | ||
85 | } | 80 | } |
86 | 81 | ||
87 | static int pnpacpi_get_resources(struct pnp_dev *dev, | 82 | static int pnpacpi_set_resources(struct pnp_dev *dev) |
88 | struct pnp_resource_table *res) | ||
89 | { | ||
90 | acpi_status status; | ||
91 | |||
92 | status = pnpacpi_parse_allocated_resource((acpi_handle) dev->data, | ||
93 | &dev->res); | ||
94 | return ACPI_FAILURE(status) ? -ENODEV : 0; | ||
95 | } | ||
96 | |||
97 | static int pnpacpi_set_resources(struct pnp_dev *dev, | ||
98 | struct pnp_resource_table *res) | ||
99 | { | 83 | { |
100 | acpi_handle handle = dev->data; | 84 | acpi_handle handle = dev->data; |
101 | struct acpi_buffer buffer; | 85 | struct acpi_buffer buffer; |
102 | int ret = 0; | 86 | int ret; |
103 | acpi_status status; | 87 | acpi_status status; |
104 | 88 | ||
105 | ret = pnpacpi_build_resource_template(handle, &buffer); | 89 | dev_dbg(&dev->dev, "set resources\n"); |
90 | ret = pnpacpi_build_resource_template(dev, &buffer); | ||
106 | if (ret) | 91 | if (ret) |
107 | return ret; | 92 | return ret; |
108 | ret = pnpacpi_encode_resources(res, &buffer); | 93 | ret = pnpacpi_encode_resources(dev, &buffer); |
109 | if (ret) { | 94 | if (ret) { |
110 | kfree(buffer.pointer); | 95 | kfree(buffer.pointer); |
111 | return ret; | 96 | return ret; |
@@ -163,7 +148,6 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
163 | { | 148 | { |
164 | acpi_handle temp = NULL; | 149 | acpi_handle temp = NULL; |
165 | acpi_status status; | 150 | acpi_status status; |
166 | struct pnp_id *dev_id; | ||
167 | struct pnp_dev *dev; | 151 | struct pnp_dev *dev; |
168 | 152 | ||
169 | status = acpi_get_handle(device->handle, "_CRS", &temp); | 153 | status = acpi_get_handle(device->handle, "_CRS", &temp); |
@@ -171,11 +155,10 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
171 | is_exclusive_device(device)) | 155 | is_exclusive_device(device)) |
172 | return 0; | 156 | return 0; |
173 | 157 | ||
174 | dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); | 158 | dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device)); |
175 | if (!dev) { | 159 | if (!dev) |
176 | pnp_err("Out of memory"); | ||
177 | return -ENOMEM; | 160 | return -ENOMEM; |
178 | } | 161 | |
179 | dev->data = device->handle; | 162 | dev->data = device->handle; |
180 | /* .enabled means the device can decode the resources */ | 163 | /* .enabled means the device can decode the resources */ |
181 | dev->active = device->status.enabled; | 164 | dev->active = device->status.enabled; |
@@ -191,44 +174,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
191 | if (ACPI_SUCCESS(status)) | 174 | if (ACPI_SUCCESS(status)) |
192 | dev->capabilities |= PNP_DISABLE; | 175 | dev->capabilities |= PNP_DISABLE; |
193 | 176 | ||
194 | dev->protocol = &pnpacpi_protocol; | ||
195 | |||
196 | if (strlen(acpi_device_name(device))) | 177 | if (strlen(acpi_device_name(device))) |
197 | strncpy(dev->name, acpi_device_name(device), sizeof(dev->name)); | 178 | strncpy(dev->name, acpi_device_name(device), sizeof(dev->name)); |
198 | else | 179 | else |
199 | strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); | 180 | strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); |
200 | 181 | ||
201 | dev->number = num; | 182 | if (dev->active) |
202 | 183 | pnpacpi_parse_allocated_resource(dev); | |
203 | /* set the initial values for the PnP device */ | ||
204 | dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); | ||
205 | if (!dev_id) | ||
206 | goto err; | ||
207 | pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id); | ||
208 | pnp_add_id(dev_id, dev); | ||
209 | |||
210 | if (dev->active) { | ||
211 | /* parse allocated resource */ | ||
212 | status = pnpacpi_parse_allocated_resource(device->handle, | ||
213 | &dev->res); | ||
214 | if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { | ||
215 | pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s", | ||
216 | dev_id->id); | ||
217 | goto err1; | ||
218 | } | ||
219 | } | ||
220 | 184 | ||
221 | if (dev->capabilities & PNP_CONFIGURABLE) { | 185 | if (dev->capabilities & PNP_CONFIGURABLE) |
222 | status = pnpacpi_parse_resource_option_data(device->handle, | 186 | pnpacpi_parse_resource_option_data(dev); |
223 | dev); | ||
224 | if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { | ||
225 | pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s", | ||
226 | dev_id->id); | ||
227 | goto err1; | ||
228 | } | ||
229 | } | ||
230 | 187 | ||
231 | /* parse compatible ids */ | ||
232 | if (device->flags.compatible_ids) { | 188 | if (device->flags.compatible_ids) { |
233 | struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; | 189 | struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; |
234 | int i; | 190 | int i; |
@@ -236,27 +192,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device) | |||
236 | for (i = 0; i < cid_list->count; i++) { | 192 | for (i = 0; i < cid_list->count; i++) { |
237 | if (!ispnpidacpi(cid_list->id[i].value)) | 193 | if (!ispnpidacpi(cid_list->id[i].value)) |
238 | continue; | 194 | continue; |
239 | dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); | 195 | pnp_add_id(dev, cid_list->id[i].value); |
240 | if (!dev_id) | ||
241 | continue; | ||
242 | |||
243 | pnpidacpi_to_pnpid(cid_list->id[i].value, dev_id->id); | ||
244 | pnp_add_id(dev_id, dev); | ||
245 | } | 196 | } |
246 | } | 197 | } |
247 | 198 | ||
248 | /* clear out the damaged flags */ | 199 | /* clear out the damaged flags */ |
249 | if (!dev->active) | 200 | if (!dev->active) |
250 | pnp_init_resource_table(&dev->res); | 201 | pnp_init_resources(dev); |
251 | pnp_add_device(dev); | 202 | pnp_add_device(dev); |
252 | num++; | 203 | num++; |
253 | 204 | ||
254 | return AE_OK; | 205 | return AE_OK; |
255 | err1: | ||
256 | kfree(dev_id); | ||
257 | err: | ||
258 | kfree(dev); | ||
259 | return -EINVAL; | ||
260 | } | 206 | } |
261 | 207 | ||
262 | static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, | 208 | static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, |
diff --git a/drivers/pnp/pnpacpi/pnpacpi.h b/drivers/pnp/pnpacpi/pnpacpi.h index f28e2ed66fa3..3e60225b0227 100644 --- a/drivers/pnp/pnpacpi/pnpacpi.h +++ b/drivers/pnp/pnpacpi/pnpacpi.h | |||
@@ -5,8 +5,8 @@ | |||
5 | #include <linux/acpi.h> | 5 | #include <linux/acpi.h> |
6 | #include <linux/pnp.h> | 6 | #include <linux/pnp.h> |
7 | 7 | ||
8 | acpi_status pnpacpi_parse_allocated_resource(acpi_handle, struct pnp_resource_table*); | 8 | int pnpacpi_parse_allocated_resource(struct pnp_dev *); |
9 | acpi_status pnpacpi_parse_resource_option_data(acpi_handle, struct pnp_dev*); | 9 | int pnpacpi_parse_resource_option_data(struct pnp_dev *); |
10 | int pnpacpi_encode_resources(struct pnp_resource_table *, struct acpi_buffer *); | 10 | int pnpacpi_encode_resources(struct pnp_dev *, struct acpi_buffer *); |
11 | int pnpacpi_build_resource_template(acpi_handle, struct acpi_buffer*); | 11 | int pnpacpi_build_resource_template(struct pnp_dev *, struct acpi_buffer *); |
12 | #endif | 12 | #endif |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 98cbc9f18eed..0201c8adfda7 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/acpi.h> | 22 | #include <linux/acpi.h> |
23 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/pnp.h> | ||
25 | #include "../base.h" | ||
24 | #include "pnpacpi.h" | 26 | #include "pnpacpi.h" |
25 | 27 | ||
26 | #ifdef CONFIG_IA64 | 28 | #ifdef CONFIG_IA64 |
@@ -32,19 +34,26 @@ | |||
32 | /* | 34 | /* |
33 | * Allocated Resources | 35 | * Allocated Resources |
34 | */ | 36 | */ |
35 | static int irq_flags(int triggering, int polarity) | 37 | static int irq_flags(int triggering, int polarity, int shareable) |
36 | { | 38 | { |
39 | int flags; | ||
40 | |||
37 | if (triggering == ACPI_LEVEL_SENSITIVE) { | 41 | if (triggering == ACPI_LEVEL_SENSITIVE) { |
38 | if (polarity == ACPI_ACTIVE_LOW) | 42 | if (polarity == ACPI_ACTIVE_LOW) |
39 | return IORESOURCE_IRQ_LOWLEVEL; | 43 | flags = IORESOURCE_IRQ_LOWLEVEL; |
40 | else | 44 | else |
41 | return IORESOURCE_IRQ_HIGHLEVEL; | 45 | flags = IORESOURCE_IRQ_HIGHLEVEL; |
42 | } else { | 46 | } else { |
43 | if (polarity == ACPI_ACTIVE_LOW) | 47 | if (polarity == ACPI_ACTIVE_LOW) |
44 | return IORESOURCE_IRQ_LOWEDGE; | 48 | flags = IORESOURCE_IRQ_LOWEDGE; |
45 | else | 49 | else |
46 | return IORESOURCE_IRQ_HIGHEDGE; | 50 | flags = IORESOURCE_IRQ_HIGHEDGE; |
47 | } | 51 | } |
52 | |||
53 | if (shareable) | ||
54 | flags |= IORESOURCE_IRQ_SHAREABLE; | ||
55 | |||
56 | return flags; | ||
48 | } | 57 | } |
49 | 58 | ||
50 | static void decode_irq_flags(int flag, int *triggering, int *polarity) | 59 | static void decode_irq_flags(int flag, int *triggering, int *polarity) |
@@ -69,29 +78,16 @@ static void decode_irq_flags(int flag, int *triggering, int *polarity) | |||
69 | } | 78 | } |
70 | } | 79 | } |
71 | 80 | ||
72 | static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, | 81 | static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, |
73 | u32 gsi, int triggering, | 82 | u32 gsi, int triggering, |
74 | int polarity, int shareable) | 83 | int polarity, int shareable) |
75 | { | 84 | { |
76 | int i = 0; | 85 | int irq, flags; |
77 | int irq; | ||
78 | int p, t; | 86 | int p, t; |
79 | static unsigned char warned; | ||
80 | 87 | ||
81 | if (!valid_IRQ(gsi)) | 88 | if (!valid_IRQ(gsi)) |
82 | return; | 89 | return; |
83 | 90 | ||
84 | while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) && | ||
85 | i < PNP_MAX_IRQ) | ||
86 | i++; | ||
87 | if (i >= PNP_MAX_IRQ) { | ||
88 | if (!warned) { | ||
89 | printk(KERN_WARNING "pnpacpi: exceeded the max number" | ||
90 | " of IRQ resources: %d\n", PNP_MAX_IRQ); | ||
91 | warned = 1; | ||
92 | } | ||
93 | return; | ||
94 | } | ||
95 | /* | 91 | /* |
96 | * in IO-APIC mode, use overrided attribute. Two reasons: | 92 | * in IO-APIC mode, use overrided attribute. Two reasons: |
97 | * 1. BIOS bug in DSDT | 93 | * 1. BIOS bug in DSDT |
@@ -102,27 +98,21 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, | |||
102 | p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; | 98 | p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH; |
103 | 99 | ||
104 | if (triggering != t || polarity != p) { | 100 | if (triggering != t || polarity != p) { |
105 | pnp_warn("IRQ %d override to %s, %s", | 101 | dev_warn(&dev->dev, "IRQ %d override to %s, %s\n", |
106 | gsi, t ? "edge":"level", p ? "low":"high"); | 102 | gsi, t ? "edge":"level", p ? "low":"high"); |
107 | triggering = t; | 103 | triggering = t; |
108 | polarity = p; | 104 | polarity = p; |
109 | } | 105 | } |
110 | } | 106 | } |
111 | 107 | ||
112 | res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag | 108 | flags = irq_flags(triggering, polarity, shareable); |
113 | res->irq_resource[i].flags |= irq_flags(triggering, polarity); | ||
114 | irq = acpi_register_gsi(gsi, triggering, polarity); | 109 | irq = acpi_register_gsi(gsi, triggering, polarity); |
115 | if (irq < 0) { | 110 | if (irq >= 0) |
116 | res->irq_resource[i].flags |= IORESOURCE_DISABLED; | 111 | pcibios_penalize_isa_irq(irq, 1); |
117 | return; | 112 | else |
118 | } | 113 | flags |= IORESOURCE_DISABLED; |
119 | |||
120 | if (shareable) | ||
121 | res->irq_resource[i].flags |= IORESOURCE_IRQ_SHAREABLE; | ||
122 | 114 | ||
123 | res->irq_resource[i].start = irq; | 115 | pnp_add_irq_resource(dev, irq, flags); |
124 | res->irq_resource[i].end = irq; | ||
125 | pcibios_penalize_isa_irq(irq, 1); | ||
126 | } | 116 | } |
127 | 117 | ||
128 | static int dma_flags(int type, int bus_master, int transfer) | 118 | static int dma_flags(int type, int bus_master, int transfer) |
@@ -168,88 +158,36 @@ static int dma_flags(int type, int bus_master, int transfer) | |||
168 | return flags; | 158 | return flags; |
169 | } | 159 | } |
170 | 160 | ||
171 | static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, | 161 | static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, |
172 | u32 dma, int type, | 162 | u64 len, int io_decode) |
173 | int bus_master, int transfer) | ||
174 | { | 163 | { |
175 | int i = 0; | 164 | int flags = 0; |
176 | static unsigned char warned; | 165 | u64 end = start + len - 1; |
177 | |||
178 | while (i < PNP_MAX_DMA && | ||
179 | !(res->dma_resource[i].flags & IORESOURCE_UNSET)) | ||
180 | i++; | ||
181 | if (i < PNP_MAX_DMA) { | ||
182 | res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag | ||
183 | res->dma_resource[i].flags |= | ||
184 | dma_flags(type, bus_master, transfer); | ||
185 | if (dma == -1) { | ||
186 | res->dma_resource[i].flags |= IORESOURCE_DISABLED; | ||
187 | return; | ||
188 | } | ||
189 | res->dma_resource[i].start = dma; | ||
190 | res->dma_resource[i].end = dma; | ||
191 | } else if (!warned) { | ||
192 | printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA " | ||
193 | "resources: %d \n", PNP_MAX_DMA); | ||
194 | warned = 1; | ||
195 | } | ||
196 | } | ||
197 | 166 | ||
198 | static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res, | 167 | if (io_decode == ACPI_DECODE_16) |
199 | u64 io, u64 len, int io_decode) | 168 | flags |= PNP_PORT_FLAG_16BITADDR; |
200 | { | 169 | if (len == 0 || end >= 0x10003) |
201 | int i = 0; | 170 | flags |= IORESOURCE_DISABLED; |
202 | static unsigned char warned; | ||
203 | 171 | ||
204 | while (!(res->port_resource[i].flags & IORESOURCE_UNSET) && | 172 | pnp_add_io_resource(dev, start, end, flags); |
205 | i < PNP_MAX_PORT) | ||
206 | i++; | ||
207 | if (i < PNP_MAX_PORT) { | ||
208 | res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag | ||
209 | if (io_decode == ACPI_DECODE_16) | ||
210 | res->port_resource[i].flags |= PNP_PORT_FLAG_16BITADDR; | ||
211 | if (len <= 0 || (io + len - 1) >= 0x10003) { | ||
212 | res->port_resource[i].flags |= IORESOURCE_DISABLED; | ||
213 | return; | ||
214 | } | ||
215 | res->port_resource[i].start = io; | ||
216 | res->port_resource[i].end = io + len - 1; | ||
217 | } else if (!warned) { | ||
218 | printk(KERN_WARNING "pnpacpi: exceeded the max number of IO " | ||
219 | "resources: %d \n", PNP_MAX_PORT); | ||
220 | warned = 1; | ||
221 | } | ||
222 | } | 173 | } |
223 | 174 | ||
224 | static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res, | 175 | static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, |
225 | u64 mem, u64 len, | 176 | u64 start, u64 len, |
226 | int write_protect) | 177 | int write_protect) |
227 | { | 178 | { |
228 | int i = 0; | 179 | int flags = 0; |
229 | static unsigned char warned; | 180 | u64 end = start + len - 1; |
230 | 181 | ||
231 | while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) && | 182 | if (len == 0) |
232 | (i < PNP_MAX_MEM)) | 183 | flags |= IORESOURCE_DISABLED; |
233 | i++; | 184 | if (write_protect == ACPI_READ_WRITE_MEMORY) |
234 | if (i < PNP_MAX_MEM) { | 185 | flags |= IORESOURCE_MEM_WRITEABLE; |
235 | res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag | 186 | |
236 | if (len <= 0) { | 187 | pnp_add_mem_resource(dev, start, end, flags); |
237 | res->mem_resource[i].flags |= IORESOURCE_DISABLED; | ||
238 | return; | ||
239 | } | ||
240 | if (write_protect == ACPI_READ_WRITE_MEMORY) | ||
241 | res->mem_resource[i].flags |= IORESOURCE_MEM_WRITEABLE; | ||
242 | |||
243 | res->mem_resource[i].start = mem; | ||
244 | res->mem_resource[i].end = mem + len - 1; | ||
245 | } else if (!warned) { | ||
246 | printk(KERN_WARNING "pnpacpi: exceeded the max number of mem " | ||
247 | "resources: %d\n", PNP_MAX_MEM); | ||
248 | warned = 1; | ||
249 | } | ||
250 | } | 188 | } |
251 | 189 | ||
252 | static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, | 190 | static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, |
253 | struct acpi_resource *res) | 191 | struct acpi_resource *res) |
254 | { | 192 | { |
255 | struct acpi_resource_address64 addr, *p = &addr; | 193 | struct acpi_resource_address64 addr, *p = &addr; |
@@ -257,7 +195,7 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res | |||
257 | 195 | ||
258 | status = acpi_resource_to_address64(res, p); | 196 | status = acpi_resource_to_address64(res, p); |
259 | if (!ACPI_SUCCESS(status)) { | 197 | if (!ACPI_SUCCESS(status)) { |
260 | pnp_warn("PnPACPI: failed to convert resource type %d", | 198 | dev_warn(&dev->dev, "failed to convert resource type %d\n", |
261 | res->type); | 199 | res->type); |
262 | return; | 200 | return; |
263 | } | 201 | } |
@@ -266,11 +204,11 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res | |||
266 | return; | 204 | return; |
267 | 205 | ||
268 | if (p->resource_type == ACPI_MEMORY_RANGE) | 206 | if (p->resource_type == ACPI_MEMORY_RANGE) |
269 | pnpacpi_parse_allocated_memresource(res_table, | 207 | pnpacpi_parse_allocated_memresource(dev, |
270 | p->minimum, p->address_length, | 208 | p->minimum, p->address_length, |
271 | p->info.mem.write_protect); | 209 | p->info.mem.write_protect); |
272 | else if (p->resource_type == ACPI_IO_RANGE) | 210 | else if (p->resource_type == ACPI_IO_RANGE) |
273 | pnpacpi_parse_allocated_ioresource(res_table, | 211 | pnpacpi_parse_allocated_ioresource(dev, |
274 | p->minimum, p->address_length, | 212 | p->minimum, p->address_length, |
275 | p->granularity == 0xfff ? ACPI_DECODE_10 : | 213 | p->granularity == 0xfff ? ACPI_DECODE_10 : |
276 | ACPI_DECODE_16); | 214 | ACPI_DECODE_16); |
@@ -279,8 +217,16 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res | |||
279 | static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | 217 | static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, |
280 | void *data) | 218 | void *data) |
281 | { | 219 | { |
282 | struct pnp_resource_table *res_table = data; | 220 | struct pnp_dev *dev = data; |
283 | int i; | 221 | struct acpi_resource_irq *irq; |
222 | struct acpi_resource_dma *dma; | ||
223 | struct acpi_resource_io *io; | ||
224 | struct acpi_resource_fixed_io *fixed_io; | ||
225 | struct acpi_resource_memory24 *memory24; | ||
226 | struct acpi_resource_memory32 *memory32; | ||
227 | struct acpi_resource_fixed_memory32 *fixed_memory32; | ||
228 | struct acpi_resource_extended_irq *extended_irq; | ||
229 | int i, flags; | ||
284 | 230 | ||
285 | switch (res->type) { | 231 | switch (res->type) { |
286 | case ACPI_RESOURCE_TYPE_IRQ: | 232 | case ACPI_RESOURCE_TYPE_IRQ: |
@@ -288,29 +234,33 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
288 | * Per spec, only one interrupt per descriptor is allowed in | 234 | * Per spec, only one interrupt per descriptor is allowed in |
289 | * _CRS, but some firmware violates this, so parse them all. | 235 | * _CRS, but some firmware violates this, so parse them all. |
290 | */ | 236 | */ |
291 | for (i = 0; i < res->data.irq.interrupt_count; i++) { | 237 | irq = &res->data.irq; |
292 | pnpacpi_parse_allocated_irqresource(res_table, | 238 | for (i = 0; i < irq->interrupt_count; i++) { |
293 | res->data.irq.interrupts[i], | 239 | pnpacpi_parse_allocated_irqresource(dev, |
294 | res->data.irq.triggering, | 240 | irq->interrupts[i], |
295 | res->data.irq.polarity, | 241 | irq->triggering, |
296 | res->data.irq.sharable); | 242 | irq->polarity, |
243 | irq->sharable); | ||
297 | } | 244 | } |
298 | break; | 245 | break; |
299 | 246 | ||
300 | case ACPI_RESOURCE_TYPE_DMA: | 247 | case ACPI_RESOURCE_TYPE_DMA: |
301 | if (res->data.dma.channel_count > 0) | 248 | dma = &res->data.dma; |
302 | pnpacpi_parse_allocated_dmaresource(res_table, | 249 | if (dma->channel_count > 0) { |
303 | res->data.dma.channels[0], | 250 | flags = dma_flags(dma->type, dma->bus_master, |
304 | res->data.dma.type, | 251 | dma->transfer); |
305 | res->data.dma.bus_master, | 252 | if (dma->channels[0] == (u8) -1) |
306 | res->data.dma.transfer); | 253 | flags |= IORESOURCE_DISABLED; |
254 | pnp_add_dma_resource(dev, dma->channels[0], flags); | ||
255 | } | ||
307 | break; | 256 | break; |
308 | 257 | ||
309 | case ACPI_RESOURCE_TYPE_IO: | 258 | case ACPI_RESOURCE_TYPE_IO: |
310 | pnpacpi_parse_allocated_ioresource(res_table, | 259 | io = &res->data.io; |
311 | res->data.io.minimum, | 260 | pnpacpi_parse_allocated_ioresource(dev, |
312 | res->data.io.address_length, | 261 | io->minimum, |
313 | res->data.io.io_decode); | 262 | io->address_length, |
263 | io->io_decode); | ||
314 | break; | 264 | break; |
315 | 265 | ||
316 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: | 266 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: |
@@ -318,9 +268,10 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
318 | break; | 268 | break; |
319 | 269 | ||
320 | case ACPI_RESOURCE_TYPE_FIXED_IO: | 270 | case ACPI_RESOURCE_TYPE_FIXED_IO: |
321 | pnpacpi_parse_allocated_ioresource(res_table, | 271 | fixed_io = &res->data.fixed_io; |
322 | res->data.fixed_io.address, | 272 | pnpacpi_parse_allocated_ioresource(dev, |
323 | res->data.fixed_io.address_length, | 273 | fixed_io->address, |
274 | fixed_io->address_length, | ||
324 | ACPI_DECODE_10); | 275 | ACPI_DECODE_10); |
325 | break; | 276 | break; |
326 | 277 | ||
@@ -331,27 +282,30 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
331 | break; | 282 | break; |
332 | 283 | ||
333 | case ACPI_RESOURCE_TYPE_MEMORY24: | 284 | case ACPI_RESOURCE_TYPE_MEMORY24: |
334 | pnpacpi_parse_allocated_memresource(res_table, | 285 | memory24 = &res->data.memory24; |
335 | res->data.memory24.minimum, | 286 | pnpacpi_parse_allocated_memresource(dev, |
336 | res->data.memory24.address_length, | 287 | memory24->minimum, |
337 | res->data.memory24.write_protect); | 288 | memory24->address_length, |
289 | memory24->write_protect); | ||
338 | break; | 290 | break; |
339 | case ACPI_RESOURCE_TYPE_MEMORY32: | 291 | case ACPI_RESOURCE_TYPE_MEMORY32: |
340 | pnpacpi_parse_allocated_memresource(res_table, | 292 | memory32 = &res->data.memory32; |
341 | res->data.memory32.minimum, | 293 | pnpacpi_parse_allocated_memresource(dev, |
342 | res->data.memory32.address_length, | 294 | memory32->minimum, |
343 | res->data.memory32.write_protect); | 295 | memory32->address_length, |
296 | memory32->write_protect); | ||
344 | break; | 297 | break; |
345 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: | 298 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: |
346 | pnpacpi_parse_allocated_memresource(res_table, | 299 | fixed_memory32 = &res->data.fixed_memory32; |
347 | res->data.fixed_memory32.address, | 300 | pnpacpi_parse_allocated_memresource(dev, |
348 | res->data.fixed_memory32.address_length, | 301 | fixed_memory32->address, |
349 | res->data.fixed_memory32.write_protect); | 302 | fixed_memory32->address_length, |
303 | fixed_memory32->write_protect); | ||
350 | break; | 304 | break; |
351 | case ACPI_RESOURCE_TYPE_ADDRESS16: | 305 | case ACPI_RESOURCE_TYPE_ADDRESS16: |
352 | case ACPI_RESOURCE_TYPE_ADDRESS32: | 306 | case ACPI_RESOURCE_TYPE_ADDRESS32: |
353 | case ACPI_RESOURCE_TYPE_ADDRESS64: | 307 | case ACPI_RESOURCE_TYPE_ADDRESS64: |
354 | pnpacpi_parse_allocated_address_space(res_table, res); | 308 | pnpacpi_parse_allocated_address_space(dev, res); |
355 | break; | 309 | break; |
356 | 310 | ||
357 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | 311 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: |
@@ -360,15 +314,16 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
360 | break; | 314 | break; |
361 | 315 | ||
362 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 316 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
363 | if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER) | 317 | extended_irq = &res->data.extended_irq; |
318 | if (extended_irq->producer_consumer == ACPI_PRODUCER) | ||
364 | return AE_OK; | 319 | return AE_OK; |
365 | 320 | ||
366 | for (i = 0; i < res->data.extended_irq.interrupt_count; i++) { | 321 | for (i = 0; i < extended_irq->interrupt_count; i++) { |
367 | pnpacpi_parse_allocated_irqresource(res_table, | 322 | pnpacpi_parse_allocated_irqresource(dev, |
368 | res->data.extended_irq.interrupts[i], | 323 | extended_irq->interrupts[i], |
369 | res->data.extended_irq.triggering, | 324 | extended_irq->triggering, |
370 | res->data.extended_irq.polarity, | 325 | extended_irq->polarity, |
371 | res->data.extended_irq.sharable); | 326 | extended_irq->sharable); |
372 | } | 327 | } |
373 | break; | 328 | break; |
374 | 329 | ||
@@ -376,24 +331,36 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, | |||
376 | break; | 331 | break; |
377 | 332 | ||
378 | default: | 333 | default: |
379 | pnp_warn("PnPACPI: unknown resource type %d", res->type); | 334 | dev_warn(&dev->dev, "unknown resource type %d in _CRS\n", |
335 | res->type); | ||
380 | return AE_ERROR; | 336 | return AE_ERROR; |
381 | } | 337 | } |
382 | 338 | ||
383 | return AE_OK; | 339 | return AE_OK; |
384 | } | 340 | } |
385 | 341 | ||
386 | acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, | 342 | int pnpacpi_parse_allocated_resource(struct pnp_dev *dev) |
387 | struct pnp_resource_table * res) | ||
388 | { | 343 | { |
389 | /* Blank the resource table values */ | 344 | acpi_handle handle = dev->data; |
390 | pnp_init_resource_table(res); | 345 | acpi_status status; |
346 | |||
347 | dev_dbg(&dev->dev, "parse allocated resources\n"); | ||
391 | 348 | ||
392 | return acpi_walk_resources(handle, METHOD_NAME__CRS, | 349 | pnp_init_resources(dev); |
393 | pnpacpi_allocated_resource, res); | 350 | |
351 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | ||
352 | pnpacpi_allocated_resource, dev); | ||
353 | |||
354 | if (ACPI_FAILURE(status)) { | ||
355 | if (status != AE_NOT_FOUND) | ||
356 | dev_err(&dev->dev, "can't evaluate _CRS: %d", status); | ||
357 | return -EPERM; | ||
358 | } | ||
359 | return 0; | ||
394 | } | 360 | } |
395 | 361 | ||
396 | static __init void pnpacpi_parse_dma_option(struct pnp_option *option, | 362 | static __init void pnpacpi_parse_dma_option(struct pnp_dev *dev, |
363 | struct pnp_option *option, | ||
397 | struct acpi_resource_dma *p) | 364 | struct acpi_resource_dma *p) |
398 | { | 365 | { |
399 | int i; | 366 | int i; |
@@ -410,10 +377,11 @@ static __init void pnpacpi_parse_dma_option(struct pnp_option *option, | |||
410 | 377 | ||
411 | dma->flags = dma_flags(p->type, p->bus_master, p->transfer); | 378 | dma->flags = dma_flags(p->type, p->bus_master, p->transfer); |
412 | 379 | ||
413 | pnp_register_dma_resource(option, dma); | 380 | pnp_register_dma_resource(dev, option, dma); |
414 | } | 381 | } |
415 | 382 | ||
416 | static __init void pnpacpi_parse_irq_option(struct pnp_option *option, | 383 | static __init void pnpacpi_parse_irq_option(struct pnp_dev *dev, |
384 | struct pnp_option *option, | ||
417 | struct acpi_resource_irq *p) | 385 | struct acpi_resource_irq *p) |
418 | { | 386 | { |
419 | int i; | 387 | int i; |
@@ -428,12 +396,13 @@ static __init void pnpacpi_parse_irq_option(struct pnp_option *option, | |||
428 | for (i = 0; i < p->interrupt_count; i++) | 396 | for (i = 0; i < p->interrupt_count; i++) |
429 | if (p->interrupts[i]) | 397 | if (p->interrupts[i]) |
430 | __set_bit(p->interrupts[i], irq->map); | 398 | __set_bit(p->interrupts[i], irq->map); |
431 | irq->flags = irq_flags(p->triggering, p->polarity); | 399 | irq->flags = irq_flags(p->triggering, p->polarity, p->sharable); |
432 | 400 | ||
433 | pnp_register_irq_resource(option, irq); | 401 | pnp_register_irq_resource(dev, option, irq); |
434 | } | 402 | } |
435 | 403 | ||
436 | static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option, | 404 | static __init void pnpacpi_parse_ext_irq_option(struct pnp_dev *dev, |
405 | struct pnp_option *option, | ||
437 | struct acpi_resource_extended_irq *p) | 406 | struct acpi_resource_extended_irq *p) |
438 | { | 407 | { |
439 | int i; | 408 | int i; |
@@ -448,12 +417,13 @@ static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option, | |||
448 | for (i = 0; i < p->interrupt_count; i++) | 417 | for (i = 0; i < p->interrupt_count; i++) |
449 | if (p->interrupts[i]) | 418 | if (p->interrupts[i]) |
450 | __set_bit(p->interrupts[i], irq->map); | 419 | __set_bit(p->interrupts[i], irq->map); |
451 | irq->flags = irq_flags(p->triggering, p->polarity); | 420 | irq->flags = irq_flags(p->triggering, p->polarity, p->sharable); |
452 | 421 | ||
453 | pnp_register_irq_resource(option, irq); | 422 | pnp_register_irq_resource(dev, option, irq); |
454 | } | 423 | } |
455 | 424 | ||
456 | static __init void pnpacpi_parse_port_option(struct pnp_option *option, | 425 | static __init void pnpacpi_parse_port_option(struct pnp_dev *dev, |
426 | struct pnp_option *option, | ||
457 | struct acpi_resource_io *io) | 427 | struct acpi_resource_io *io) |
458 | { | 428 | { |
459 | struct pnp_port *port; | 429 | struct pnp_port *port; |
@@ -469,10 +439,11 @@ static __init void pnpacpi_parse_port_option(struct pnp_option *option, | |||
469 | port->size = io->address_length; | 439 | port->size = io->address_length; |
470 | port->flags = ACPI_DECODE_16 == io->io_decode ? | 440 | port->flags = ACPI_DECODE_16 == io->io_decode ? |
471 | PNP_PORT_FLAG_16BITADDR : 0; | 441 | PNP_PORT_FLAG_16BITADDR : 0; |
472 | pnp_register_port_resource(option, port); | 442 | pnp_register_port_resource(dev, option, port); |
473 | } | 443 | } |
474 | 444 | ||
475 | static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option, | 445 | static __init void pnpacpi_parse_fixed_port_option(struct pnp_dev *dev, |
446 | struct pnp_option *option, | ||
476 | struct acpi_resource_fixed_io *io) | 447 | struct acpi_resource_fixed_io *io) |
477 | { | 448 | { |
478 | struct pnp_port *port; | 449 | struct pnp_port *port; |
@@ -486,10 +457,11 @@ static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option, | |||
486 | port->size = io->address_length; | 457 | port->size = io->address_length; |
487 | port->align = 0; | 458 | port->align = 0; |
488 | port->flags = PNP_PORT_FLAG_FIXED; | 459 | port->flags = PNP_PORT_FLAG_FIXED; |
489 | pnp_register_port_resource(option, port); | 460 | pnp_register_port_resource(dev, option, port); |
490 | } | 461 | } |
491 | 462 | ||
492 | static __init void pnpacpi_parse_mem24_option(struct pnp_option *option, | 463 | static __init void pnpacpi_parse_mem24_option(struct pnp_dev *dev, |
464 | struct pnp_option *option, | ||
493 | struct acpi_resource_memory24 *p) | 465 | struct acpi_resource_memory24 *p) |
494 | { | 466 | { |
495 | struct pnp_mem *mem; | 467 | struct pnp_mem *mem; |
@@ -507,10 +479,11 @@ static __init void pnpacpi_parse_mem24_option(struct pnp_option *option, | |||
507 | mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? | 479 | mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? |
508 | IORESOURCE_MEM_WRITEABLE : 0; | 480 | IORESOURCE_MEM_WRITEABLE : 0; |
509 | 481 | ||
510 | pnp_register_mem_resource(option, mem); | 482 | pnp_register_mem_resource(dev, option, mem); |
511 | } | 483 | } |
512 | 484 | ||
513 | static __init void pnpacpi_parse_mem32_option(struct pnp_option *option, | 485 | static __init void pnpacpi_parse_mem32_option(struct pnp_dev *dev, |
486 | struct pnp_option *option, | ||
514 | struct acpi_resource_memory32 *p) | 487 | struct acpi_resource_memory32 *p) |
515 | { | 488 | { |
516 | struct pnp_mem *mem; | 489 | struct pnp_mem *mem; |
@@ -528,10 +501,11 @@ static __init void pnpacpi_parse_mem32_option(struct pnp_option *option, | |||
528 | mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? | 501 | mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? |
529 | IORESOURCE_MEM_WRITEABLE : 0; | 502 | IORESOURCE_MEM_WRITEABLE : 0; |
530 | 503 | ||
531 | pnp_register_mem_resource(option, mem); | 504 | pnp_register_mem_resource(dev, option, mem); |
532 | } | 505 | } |
533 | 506 | ||
534 | static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, | 507 | static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_dev *dev, |
508 | struct pnp_option *option, | ||
535 | struct acpi_resource_fixed_memory32 *p) | 509 | struct acpi_resource_fixed_memory32 *p) |
536 | { | 510 | { |
537 | struct pnp_mem *mem; | 511 | struct pnp_mem *mem; |
@@ -548,10 +522,11 @@ static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, | |||
548 | mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? | 522 | mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ? |
549 | IORESOURCE_MEM_WRITEABLE : 0; | 523 | IORESOURCE_MEM_WRITEABLE : 0; |
550 | 524 | ||
551 | pnp_register_mem_resource(option, mem); | 525 | pnp_register_mem_resource(dev, option, mem); |
552 | } | 526 | } |
553 | 527 | ||
554 | static __init void pnpacpi_parse_address_option(struct pnp_option *option, | 528 | static __init void pnpacpi_parse_address_option(struct pnp_dev *dev, |
529 | struct pnp_option *option, | ||
555 | struct acpi_resource *r) | 530 | struct acpi_resource *r) |
556 | { | 531 | { |
557 | struct acpi_resource_address64 addr, *p = &addr; | 532 | struct acpi_resource_address64 addr, *p = &addr; |
@@ -579,7 +554,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option, | |||
579 | mem->flags = (p->info.mem.write_protect == | 554 | mem->flags = (p->info.mem.write_protect == |
580 | ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE | 555 | ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE |
581 | : 0; | 556 | : 0; |
582 | pnp_register_mem_resource(option, mem); | 557 | pnp_register_mem_resource(dev, option, mem); |
583 | } else if (p->resource_type == ACPI_IO_RANGE) { | 558 | } else if (p->resource_type == ACPI_IO_RANGE) { |
584 | port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); | 559 | port = kzalloc(sizeof(struct pnp_port), GFP_KERNEL); |
585 | if (!port) | 560 | if (!port) |
@@ -588,7 +563,7 @@ static __init void pnpacpi_parse_address_option(struct pnp_option *option, | |||
588 | port->size = p->address_length; | 563 | port->size = p->address_length; |
589 | port->align = 0; | 564 | port->align = 0; |
590 | port->flags = PNP_PORT_FLAG_FIXED; | 565 | port->flags = PNP_PORT_FLAG_FIXED; |
591 | pnp_register_port_resource(option, port); | 566 | pnp_register_port_resource(dev, option, port); |
592 | } | 567 | } |
593 | } | 568 | } |
594 | 569 | ||
@@ -608,11 +583,11 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, | |||
608 | 583 | ||
609 | switch (res->type) { | 584 | switch (res->type) { |
610 | case ACPI_RESOURCE_TYPE_IRQ: | 585 | case ACPI_RESOURCE_TYPE_IRQ: |
611 | pnpacpi_parse_irq_option(option, &res->data.irq); | 586 | pnpacpi_parse_irq_option(dev, option, &res->data.irq); |
612 | break; | 587 | break; |
613 | 588 | ||
614 | case ACPI_RESOURCE_TYPE_DMA: | 589 | case ACPI_RESOURCE_TYPE_DMA: |
615 | pnpacpi_parse_dma_option(option, &res->data.dma); | 590 | pnpacpi_parse_dma_option(dev, option, &res->data.dma); |
616 | break; | 591 | break; |
617 | 592 | ||
618 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: | 593 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: |
@@ -642,19 +617,22 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, | |||
642 | case ACPI_RESOURCE_TYPE_END_DEPENDENT: | 617 | case ACPI_RESOURCE_TYPE_END_DEPENDENT: |
643 | /*only one EndDependentFn is allowed */ | 618 | /*only one EndDependentFn is allowed */ |
644 | if (!parse_data->option_independent) { | 619 | if (!parse_data->option_independent) { |
645 | pnp_warn("PnPACPI: more than one EndDependentFn"); | 620 | dev_warn(&dev->dev, "more than one EndDependentFn " |
621 | "in _PRS\n"); | ||
646 | return AE_ERROR; | 622 | return AE_ERROR; |
647 | } | 623 | } |
648 | parse_data->option = parse_data->option_independent; | 624 | parse_data->option = parse_data->option_independent; |
649 | parse_data->option_independent = NULL; | 625 | parse_data->option_independent = NULL; |
626 | dev_dbg(&dev->dev, "end dependent options\n"); | ||
650 | break; | 627 | break; |
651 | 628 | ||
652 | case ACPI_RESOURCE_TYPE_IO: | 629 | case ACPI_RESOURCE_TYPE_IO: |
653 | pnpacpi_parse_port_option(option, &res->data.io); | 630 | pnpacpi_parse_port_option(dev, option, &res->data.io); |
654 | break; | 631 | break; |
655 | 632 | ||
656 | case ACPI_RESOURCE_TYPE_FIXED_IO: | 633 | case ACPI_RESOURCE_TYPE_FIXED_IO: |
657 | pnpacpi_parse_fixed_port_option(option, &res->data.fixed_io); | 634 | pnpacpi_parse_fixed_port_option(dev, option, |
635 | &res->data.fixed_io); | ||
658 | break; | 636 | break; |
659 | 637 | ||
660 | case ACPI_RESOURCE_TYPE_VENDOR: | 638 | case ACPI_RESOURCE_TYPE_VENDOR: |
@@ -662,57 +640,67 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, | |||
662 | break; | 640 | break; |
663 | 641 | ||
664 | case ACPI_RESOURCE_TYPE_MEMORY24: | 642 | case ACPI_RESOURCE_TYPE_MEMORY24: |
665 | pnpacpi_parse_mem24_option(option, &res->data.memory24); | 643 | pnpacpi_parse_mem24_option(dev, option, &res->data.memory24); |
666 | break; | 644 | break; |
667 | 645 | ||
668 | case ACPI_RESOURCE_TYPE_MEMORY32: | 646 | case ACPI_RESOURCE_TYPE_MEMORY32: |
669 | pnpacpi_parse_mem32_option(option, &res->data.memory32); | 647 | pnpacpi_parse_mem32_option(dev, option, &res->data.memory32); |
670 | break; | 648 | break; |
671 | 649 | ||
672 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: | 650 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: |
673 | pnpacpi_parse_fixed_mem32_option(option, | 651 | pnpacpi_parse_fixed_mem32_option(dev, option, |
674 | &res->data.fixed_memory32); | 652 | &res->data.fixed_memory32); |
675 | break; | 653 | break; |
676 | 654 | ||
677 | case ACPI_RESOURCE_TYPE_ADDRESS16: | 655 | case ACPI_RESOURCE_TYPE_ADDRESS16: |
678 | case ACPI_RESOURCE_TYPE_ADDRESS32: | 656 | case ACPI_RESOURCE_TYPE_ADDRESS32: |
679 | case ACPI_RESOURCE_TYPE_ADDRESS64: | 657 | case ACPI_RESOURCE_TYPE_ADDRESS64: |
680 | pnpacpi_parse_address_option(option, res); | 658 | pnpacpi_parse_address_option(dev, option, res); |
681 | break; | 659 | break; |
682 | 660 | ||
683 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | 661 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: |
684 | break; | 662 | break; |
685 | 663 | ||
686 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 664 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
687 | pnpacpi_parse_ext_irq_option(option, &res->data.extended_irq); | 665 | pnpacpi_parse_ext_irq_option(dev, option, |
666 | &res->data.extended_irq); | ||
688 | break; | 667 | break; |
689 | 668 | ||
690 | case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: | 669 | case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: |
691 | break; | 670 | break; |
692 | 671 | ||
693 | default: | 672 | default: |
694 | pnp_warn("PnPACPI: unknown resource type %d", res->type); | 673 | dev_warn(&dev->dev, "unknown resource type %d in _PRS\n", |
674 | res->type); | ||
695 | return AE_ERROR; | 675 | return AE_ERROR; |
696 | } | 676 | } |
697 | 677 | ||
698 | return AE_OK; | 678 | return AE_OK; |
699 | } | 679 | } |
700 | 680 | ||
701 | acpi_status __init pnpacpi_parse_resource_option_data(acpi_handle handle, | 681 | int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) |
702 | struct pnp_dev *dev) | ||
703 | { | 682 | { |
683 | acpi_handle handle = dev->data; | ||
704 | acpi_status status; | 684 | acpi_status status; |
705 | struct acpipnp_parse_option_s parse_data; | 685 | struct acpipnp_parse_option_s parse_data; |
706 | 686 | ||
687 | dev_dbg(&dev->dev, "parse resource options\n"); | ||
688 | |||
707 | parse_data.option = pnp_register_independent_option(dev); | 689 | parse_data.option = pnp_register_independent_option(dev); |
708 | if (!parse_data.option) | 690 | if (!parse_data.option) |
709 | return AE_ERROR; | 691 | return -ENOMEM; |
692 | |||
710 | parse_data.option_independent = parse_data.option; | 693 | parse_data.option_independent = parse_data.option; |
711 | parse_data.dev = dev; | 694 | parse_data.dev = dev; |
712 | status = acpi_walk_resources(handle, METHOD_NAME__PRS, | 695 | status = acpi_walk_resources(handle, METHOD_NAME__PRS, |
713 | pnpacpi_option_resource, &parse_data); | 696 | pnpacpi_option_resource, &parse_data); |
714 | 697 | ||
715 | return status; | 698 | if (ACPI_FAILURE(status)) { |
699 | if (status != AE_NOT_FOUND) | ||
700 | dev_err(&dev->dev, "can't evaluate _PRS: %d", status); | ||
701 | return -EPERM; | ||
702 | } | ||
703 | return 0; | ||
716 | } | 704 | } |
717 | 705 | ||
718 | static int pnpacpi_supported_resource(struct acpi_resource *res) | 706 | static int pnpacpi_supported_resource(struct acpi_resource *res) |
@@ -760,9 +748,10 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data) | |||
760 | return AE_OK; | 748 | return AE_OK; |
761 | } | 749 | } |
762 | 750 | ||
763 | int pnpacpi_build_resource_template(acpi_handle handle, | 751 | int pnpacpi_build_resource_template(struct pnp_dev *dev, |
764 | struct acpi_buffer *buffer) | 752 | struct acpi_buffer *buffer) |
765 | { | 753 | { |
754 | acpi_handle handle = dev->data; | ||
766 | struct acpi_resource *resource; | 755 | struct acpi_resource *resource; |
767 | int res_cnt = 0; | 756 | int res_cnt = 0; |
768 | acpi_status status; | 757 | acpi_status status; |
@@ -770,7 +759,7 @@ int pnpacpi_build_resource_template(acpi_handle handle, | |||
770 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | 759 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, |
771 | pnpacpi_count_resources, &res_cnt); | 760 | pnpacpi_count_resources, &res_cnt); |
772 | if (ACPI_FAILURE(status)) { | 761 | if (ACPI_FAILURE(status)) { |
773 | pnp_err("Evaluate _CRS failed"); | 762 | dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status); |
774 | return -EINVAL; | 763 | return -EINVAL; |
775 | } | 764 | } |
776 | if (!res_cnt) | 765 | if (!res_cnt) |
@@ -779,13 +768,13 @@ int pnpacpi_build_resource_template(acpi_handle handle, | |||
779 | buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL); | 768 | buffer->pointer = kzalloc(buffer->length - 1, GFP_KERNEL); |
780 | if (!buffer->pointer) | 769 | if (!buffer->pointer) |
781 | return -ENOMEM; | 770 | return -ENOMEM; |
782 | pnp_dbg("Res cnt %d", res_cnt); | 771 | |
783 | resource = (struct acpi_resource *)buffer->pointer; | 772 | resource = (struct acpi_resource *)buffer->pointer; |
784 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | 773 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, |
785 | pnpacpi_type_resources, &resource); | 774 | pnpacpi_type_resources, &resource); |
786 | if (ACPI_FAILURE(status)) { | 775 | if (ACPI_FAILURE(status)) { |
787 | kfree(buffer->pointer); | 776 | kfree(buffer->pointer); |
788 | pnp_err("Evaluate _CRS failed"); | 777 | dev_err(&dev->dev, "can't evaluate _CRS: %d\n", status); |
789 | return -EINVAL; | 778 | return -EINVAL; |
790 | } | 779 | } |
791 | /* resource will pointer the end resource now */ | 780 | /* resource will pointer the end resource now */ |
@@ -794,129 +783,184 @@ int pnpacpi_build_resource_template(acpi_handle handle, | |||
794 | return 0; | 783 | return 0; |
795 | } | 784 | } |
796 | 785 | ||
797 | static void pnpacpi_encode_irq(struct acpi_resource *resource, | 786 | static void pnpacpi_encode_irq(struct pnp_dev *dev, |
787 | struct acpi_resource *resource, | ||
798 | struct resource *p) | 788 | struct resource *p) |
799 | { | 789 | { |
790 | struct acpi_resource_irq *irq = &resource->data.irq; | ||
800 | int triggering, polarity; | 791 | int triggering, polarity; |
801 | 792 | ||
802 | decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); | 793 | decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); |
803 | resource->data.irq.triggering = triggering; | 794 | irq->triggering = triggering; |
804 | resource->data.irq.polarity = polarity; | 795 | irq->polarity = polarity; |
805 | if (triggering == ACPI_EDGE_SENSITIVE) | 796 | if (triggering == ACPI_EDGE_SENSITIVE) |
806 | resource->data.irq.sharable = ACPI_EXCLUSIVE; | 797 | irq->sharable = ACPI_EXCLUSIVE; |
807 | else | 798 | else |
808 | resource->data.irq.sharable = ACPI_SHARED; | 799 | irq->sharable = ACPI_SHARED; |
809 | resource->data.irq.interrupt_count = 1; | 800 | irq->interrupt_count = 1; |
810 | resource->data.irq.interrupts[0] = p->start; | 801 | irq->interrupts[0] = p->start; |
802 | |||
803 | dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start, | ||
804 | triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge", | ||
805 | polarity == ACPI_ACTIVE_LOW ? "low" : "high", | ||
806 | irq->sharable == ACPI_SHARED ? "shared" : "exclusive"); | ||
811 | } | 807 | } |
812 | 808 | ||
813 | static void pnpacpi_encode_ext_irq(struct acpi_resource *resource, | 809 | static void pnpacpi_encode_ext_irq(struct pnp_dev *dev, |
810 | struct acpi_resource *resource, | ||
814 | struct resource *p) | 811 | struct resource *p) |
815 | { | 812 | { |
813 | struct acpi_resource_extended_irq *extended_irq = &resource->data.extended_irq; | ||
816 | int triggering, polarity; | 814 | int triggering, polarity; |
817 | 815 | ||
818 | decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); | 816 | decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity); |
819 | resource->data.extended_irq.producer_consumer = ACPI_CONSUMER; | 817 | extended_irq->producer_consumer = ACPI_CONSUMER; |
820 | resource->data.extended_irq.triggering = triggering; | 818 | extended_irq->triggering = triggering; |
821 | resource->data.extended_irq.polarity = polarity; | 819 | extended_irq->polarity = polarity; |
822 | if (triggering == ACPI_EDGE_SENSITIVE) | 820 | if (triggering == ACPI_EDGE_SENSITIVE) |
823 | resource->data.irq.sharable = ACPI_EXCLUSIVE; | 821 | extended_irq->sharable = ACPI_EXCLUSIVE; |
824 | else | 822 | else |
825 | resource->data.irq.sharable = ACPI_SHARED; | 823 | extended_irq->sharable = ACPI_SHARED; |
826 | resource->data.extended_irq.interrupt_count = 1; | 824 | extended_irq->interrupt_count = 1; |
827 | resource->data.extended_irq.interrupts[0] = p->start; | 825 | extended_irq->interrupts[0] = p->start; |
826 | |||
827 | dev_dbg(&dev->dev, " encode irq %d %s %s %s\n", (int) p->start, | ||
828 | triggering == ACPI_LEVEL_SENSITIVE ? "level" : "edge", | ||
829 | polarity == ACPI_ACTIVE_LOW ? "low" : "high", | ||
830 | extended_irq->sharable == ACPI_SHARED ? "shared" : "exclusive"); | ||
828 | } | 831 | } |
829 | 832 | ||
830 | static void pnpacpi_encode_dma(struct acpi_resource *resource, | 833 | static void pnpacpi_encode_dma(struct pnp_dev *dev, |
834 | struct acpi_resource *resource, | ||
831 | struct resource *p) | 835 | struct resource *p) |
832 | { | 836 | { |
837 | struct acpi_resource_dma *dma = &resource->data.dma; | ||
838 | |||
833 | /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ | 839 | /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ |
834 | switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { | 840 | switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { |
835 | case IORESOURCE_DMA_TYPEA: | 841 | case IORESOURCE_DMA_TYPEA: |
836 | resource->data.dma.type = ACPI_TYPE_A; | 842 | dma->type = ACPI_TYPE_A; |
837 | break; | 843 | break; |
838 | case IORESOURCE_DMA_TYPEB: | 844 | case IORESOURCE_DMA_TYPEB: |
839 | resource->data.dma.type = ACPI_TYPE_B; | 845 | dma->type = ACPI_TYPE_B; |
840 | break; | 846 | break; |
841 | case IORESOURCE_DMA_TYPEF: | 847 | case IORESOURCE_DMA_TYPEF: |
842 | resource->data.dma.type = ACPI_TYPE_F; | 848 | dma->type = ACPI_TYPE_F; |
843 | break; | 849 | break; |
844 | default: | 850 | default: |
845 | resource->data.dma.type = ACPI_COMPATIBILITY; | 851 | dma->type = ACPI_COMPATIBILITY; |
846 | } | 852 | } |
847 | 853 | ||
848 | switch (p->flags & IORESOURCE_DMA_TYPE_MASK) { | 854 | switch (p->flags & IORESOURCE_DMA_TYPE_MASK) { |
849 | case IORESOURCE_DMA_8BIT: | 855 | case IORESOURCE_DMA_8BIT: |
850 | resource->data.dma.transfer = ACPI_TRANSFER_8; | 856 | dma->transfer = ACPI_TRANSFER_8; |
851 | break; | 857 | break; |
852 | case IORESOURCE_DMA_8AND16BIT: | 858 | case IORESOURCE_DMA_8AND16BIT: |
853 | resource->data.dma.transfer = ACPI_TRANSFER_8_16; | 859 | dma->transfer = ACPI_TRANSFER_8_16; |
854 | break; | 860 | break; |
855 | default: | 861 | default: |
856 | resource->data.dma.transfer = ACPI_TRANSFER_16; | 862 | dma->transfer = ACPI_TRANSFER_16; |
857 | } | 863 | } |
858 | 864 | ||
859 | resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); | 865 | dma->bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); |
860 | resource->data.dma.channel_count = 1; | 866 | dma->channel_count = 1; |
861 | resource->data.dma.channels[0] = p->start; | 867 | dma->channels[0] = p->start; |
868 | |||
869 | dev_dbg(&dev->dev, " encode dma %d " | ||
870 | "type %#x transfer %#x master %d\n", | ||
871 | (int) p->start, dma->type, dma->transfer, dma->bus_master); | ||
862 | } | 872 | } |
863 | 873 | ||
864 | static void pnpacpi_encode_io(struct acpi_resource *resource, | 874 | static void pnpacpi_encode_io(struct pnp_dev *dev, |
875 | struct acpi_resource *resource, | ||
865 | struct resource *p) | 876 | struct resource *p) |
866 | { | 877 | { |
878 | struct acpi_resource_io *io = &resource->data.io; | ||
879 | |||
867 | /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ | 880 | /* Note: pnp_assign_port will copy pnp_port->flags into p->flags */ |
868 | resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ? | 881 | io->io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR) ? |
869 | ACPI_DECODE_16 : ACPI_DECODE_10; | 882 | ACPI_DECODE_16 : ACPI_DECODE_10; |
870 | resource->data.io.minimum = p->start; | 883 | io->minimum = p->start; |
871 | resource->data.io.maximum = p->end; | 884 | io->maximum = p->end; |
872 | resource->data.io.alignment = 0; /* Correct? */ | 885 | io->alignment = 0; /* Correct? */ |
873 | resource->data.io.address_length = p->end - p->start + 1; | 886 | io->address_length = p->end - p->start + 1; |
887 | |||
888 | dev_dbg(&dev->dev, " encode io %#llx-%#llx decode %#x\n", | ||
889 | (unsigned long long) p->start, (unsigned long long) p->end, | ||
890 | io->io_decode); | ||
874 | } | 891 | } |
875 | 892 | ||
876 | static void pnpacpi_encode_fixed_io(struct acpi_resource *resource, | 893 | static void pnpacpi_encode_fixed_io(struct pnp_dev *dev, |
894 | struct acpi_resource *resource, | ||
877 | struct resource *p) | 895 | struct resource *p) |
878 | { | 896 | { |
879 | resource->data.fixed_io.address = p->start; | 897 | struct acpi_resource_fixed_io *fixed_io = &resource->data.fixed_io; |
880 | resource->data.fixed_io.address_length = p->end - p->start + 1; | 898 | |
899 | fixed_io->address = p->start; | ||
900 | fixed_io->address_length = p->end - p->start + 1; | ||
901 | |||
902 | dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", | ||
903 | (unsigned long long) p->start, (unsigned long long) p->end); | ||
881 | } | 904 | } |
882 | 905 | ||
883 | static void pnpacpi_encode_mem24(struct acpi_resource *resource, | 906 | static void pnpacpi_encode_mem24(struct pnp_dev *dev, |
907 | struct acpi_resource *resource, | ||
884 | struct resource *p) | 908 | struct resource *p) |
885 | { | 909 | { |
910 | struct acpi_resource_memory24 *memory24 = &resource->data.memory24; | ||
911 | |||
886 | /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ | 912 | /* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */ |
887 | resource->data.memory24.write_protect = | 913 | memory24->write_protect = |
888 | (p->flags & IORESOURCE_MEM_WRITEABLE) ? | 914 | (p->flags & IORESOURCE_MEM_WRITEABLE) ? |
889 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; | 915 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; |
890 | resource->data.memory24.minimum = p->start; | 916 | memory24->minimum = p->start; |
891 | resource->data.memory24.maximum = p->end; | 917 | memory24->maximum = p->end; |
892 | resource->data.memory24.alignment = 0; | 918 | memory24->alignment = 0; |
893 | resource->data.memory24.address_length = p->end - p->start + 1; | 919 | memory24->address_length = p->end - p->start + 1; |
920 | |||
921 | dev_dbg(&dev->dev, " encode mem24 %#llx-%#llx write_protect %#x\n", | ||
922 | (unsigned long long) p->start, (unsigned long long) p->end, | ||
923 | memory24->write_protect); | ||
894 | } | 924 | } |
895 | 925 | ||
896 | static void pnpacpi_encode_mem32(struct acpi_resource *resource, | 926 | static void pnpacpi_encode_mem32(struct pnp_dev *dev, |
927 | struct acpi_resource *resource, | ||
897 | struct resource *p) | 928 | struct resource *p) |
898 | { | 929 | { |
899 | resource->data.memory32.write_protect = | 930 | struct acpi_resource_memory32 *memory32 = &resource->data.memory32; |
931 | |||
932 | memory32->write_protect = | ||
900 | (p->flags & IORESOURCE_MEM_WRITEABLE) ? | 933 | (p->flags & IORESOURCE_MEM_WRITEABLE) ? |
901 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; | 934 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; |
902 | resource->data.memory32.minimum = p->start; | 935 | memory32->minimum = p->start; |
903 | resource->data.memory32.maximum = p->end; | 936 | memory32->maximum = p->end; |
904 | resource->data.memory32.alignment = 0; | 937 | memory32->alignment = 0; |
905 | resource->data.memory32.address_length = p->end - p->start + 1; | 938 | memory32->address_length = p->end - p->start + 1; |
939 | |||
940 | dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx write_protect %#x\n", | ||
941 | (unsigned long long) p->start, (unsigned long long) p->end, | ||
942 | memory32->write_protect); | ||
906 | } | 943 | } |
907 | 944 | ||
908 | static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource, | 945 | static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev, |
946 | struct acpi_resource *resource, | ||
909 | struct resource *p) | 947 | struct resource *p) |
910 | { | 948 | { |
911 | resource->data.fixed_memory32.write_protect = | 949 | struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32; |
950 | |||
951 | fixed_memory32->write_protect = | ||
912 | (p->flags & IORESOURCE_MEM_WRITEABLE) ? | 952 | (p->flags & IORESOURCE_MEM_WRITEABLE) ? |
913 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; | 953 | ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; |
914 | resource->data.fixed_memory32.address = p->start; | 954 | fixed_memory32->address = p->start; |
915 | resource->data.fixed_memory32.address_length = p->end - p->start + 1; | 955 | fixed_memory32->address_length = p->end - p->start + 1; |
956 | |||
957 | dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx " | ||
958 | "write_protect %#x\n", | ||
959 | (unsigned long long) p->start, (unsigned long long) p->end, | ||
960 | fixed_memory32->write_protect); | ||
916 | } | 961 | } |
917 | 962 | ||
918 | int pnpacpi_encode_resources(struct pnp_resource_table *res_table, | 963 | int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer) |
919 | struct acpi_buffer *buffer) | ||
920 | { | 964 | { |
921 | int i = 0; | 965 | int i = 0; |
922 | /* pnpacpi_build_resource_template allocates extra mem */ | 966 | /* pnpacpi_build_resource_template allocates extra mem */ |
@@ -924,58 +968,48 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table, | |||
924 | struct acpi_resource *resource = buffer->pointer; | 968 | struct acpi_resource *resource = buffer->pointer; |
925 | int port = 0, irq = 0, dma = 0, mem = 0; | 969 | int port = 0, irq = 0, dma = 0, mem = 0; |
926 | 970 | ||
927 | pnp_dbg("res cnt %d", res_cnt); | 971 | dev_dbg(&dev->dev, "encode %d resources\n", res_cnt); |
928 | while (i < res_cnt) { | 972 | while (i < res_cnt) { |
929 | switch (resource->type) { | 973 | switch (resource->type) { |
930 | case ACPI_RESOURCE_TYPE_IRQ: | 974 | case ACPI_RESOURCE_TYPE_IRQ: |
931 | pnp_dbg("Encode irq"); | 975 | pnpacpi_encode_irq(dev, resource, |
932 | pnpacpi_encode_irq(resource, | 976 | pnp_get_resource(dev, IORESOURCE_IRQ, irq)); |
933 | &res_table->irq_resource[irq]); | ||
934 | irq++; | 977 | irq++; |
935 | break; | 978 | break; |
936 | 979 | ||
937 | case ACPI_RESOURCE_TYPE_DMA: | 980 | case ACPI_RESOURCE_TYPE_DMA: |
938 | pnp_dbg("Encode dma"); | 981 | pnpacpi_encode_dma(dev, resource, |
939 | pnpacpi_encode_dma(resource, | 982 | pnp_get_resource(dev, IORESOURCE_DMA, dma)); |
940 | &res_table->dma_resource[dma]); | ||
941 | dma++; | 983 | dma++; |
942 | break; | 984 | break; |
943 | case ACPI_RESOURCE_TYPE_IO: | 985 | case ACPI_RESOURCE_TYPE_IO: |
944 | pnp_dbg("Encode io"); | 986 | pnpacpi_encode_io(dev, resource, |
945 | pnpacpi_encode_io(resource, | 987 | pnp_get_resource(dev, IORESOURCE_IO, port)); |
946 | &res_table->port_resource[port]); | ||
947 | port++; | 988 | port++; |
948 | break; | 989 | break; |
949 | case ACPI_RESOURCE_TYPE_FIXED_IO: | 990 | case ACPI_RESOURCE_TYPE_FIXED_IO: |
950 | pnp_dbg("Encode fixed io"); | 991 | pnpacpi_encode_fixed_io(dev, resource, |
951 | pnpacpi_encode_fixed_io(resource, | 992 | pnp_get_resource(dev, IORESOURCE_IO, port)); |
952 | &res_table-> | ||
953 | port_resource[port]); | ||
954 | port++; | 993 | port++; |
955 | break; | 994 | break; |
956 | case ACPI_RESOURCE_TYPE_MEMORY24: | 995 | case ACPI_RESOURCE_TYPE_MEMORY24: |
957 | pnp_dbg("Encode mem24"); | 996 | pnpacpi_encode_mem24(dev, resource, |
958 | pnpacpi_encode_mem24(resource, | 997 | pnp_get_resource(dev, IORESOURCE_MEM, mem)); |
959 | &res_table->mem_resource[mem]); | ||
960 | mem++; | 998 | mem++; |
961 | break; | 999 | break; |
962 | case ACPI_RESOURCE_TYPE_MEMORY32: | 1000 | case ACPI_RESOURCE_TYPE_MEMORY32: |
963 | pnp_dbg("Encode mem32"); | 1001 | pnpacpi_encode_mem32(dev, resource, |
964 | pnpacpi_encode_mem32(resource, | 1002 | pnp_get_resource(dev, IORESOURCE_MEM, mem)); |
965 | &res_table->mem_resource[mem]); | ||
966 | mem++; | 1003 | mem++; |
967 | break; | 1004 | break; |
968 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: | 1005 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: |
969 | pnp_dbg("Encode fixed mem32"); | 1006 | pnpacpi_encode_fixed_mem32(dev, resource, |
970 | pnpacpi_encode_fixed_mem32(resource, | 1007 | pnp_get_resource(dev, IORESOURCE_MEM, mem)); |
971 | &res_table-> | ||
972 | mem_resource[mem]); | ||
973 | mem++; | 1008 | mem++; |
974 | break; | 1009 | break; |
975 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | 1010 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
976 | pnp_dbg("Encode ext irq"); | 1011 | pnpacpi_encode_ext_irq(dev, resource, |
977 | pnpacpi_encode_ext_irq(resource, | 1012 | pnp_get_resource(dev, IORESOURCE_IRQ, irq)); |
978 | &res_table->irq_resource[irq]); | ||
979 | irq++; | 1013 | irq++; |
980 | break; | 1014 | break; |
981 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: | 1015 | case ACPI_RESOURCE_TYPE_START_DEPENDENT: |
@@ -988,7 +1022,8 @@ int pnpacpi_encode_resources(struct pnp_resource_table *res_table, | |||
988 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | 1022 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: |
989 | case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: | 1023 | case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: |
990 | default: /* other type */ | 1024 | default: /* other type */ |
991 | pnp_warn("unknown resource type %d", resource->type); | 1025 | dev_warn(&dev->dev, "can't encode unknown resource " |
1026 | "type %d\n", resource->type); | ||
992 | return -EINVAL; | 1027 | return -EINVAL; |
993 | } | 1028 | } |
994 | resource++; | 1029 | resource++; |
diff --git a/drivers/pnp/pnpbios/Makefile b/drivers/pnp/pnpbios/Makefile index 3cd3ed760605..310e2b3a7710 100644 --- a/drivers/pnp/pnpbios/Makefile +++ b/drivers/pnp/pnpbios/Makefile | |||
@@ -5,3 +5,7 @@ | |||
5 | pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o | 5 | pnpbios-proc-$(CONFIG_PNPBIOS_PROC_FS) = proc.o |
6 | 6 | ||
7 | obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y) | 7 | obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y) |
8 | |||
9 | ifeq ($(CONFIG_PNP_DEBUG),y) | ||
10 | EXTRA_CFLAGS += -DDEBUG | ||
11 | endif | ||
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index a8364d815222..7ff824496b39 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/linkage.h> | 8 | #include <linux/linkage.h> |
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/pnpbios.h> | ||
11 | #include <linux/device.h> | 10 | #include <linux/device.h> |
12 | #include <linux/pnp.h> | 11 | #include <linux/pnp.h> |
13 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index a8a51500e1e9..19a4be1a9a31 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include <linux/init.h> | 50 | #include <linux/init.h> |
51 | #include <linux/linkage.h> | 51 | #include <linux/linkage.h> |
52 | #include <linux/kernel.h> | 52 | #include <linux/kernel.h> |
53 | #include <linux/pnpbios.h> | ||
54 | #include <linux/device.h> | 53 | #include <linux/device.h> |
55 | #include <linux/pnp.h> | 54 | #include <linux/pnp.h> |
56 | #include <linux/mm.h> | 55 | #include <linux/mm.h> |
@@ -69,6 +68,7 @@ | |||
69 | #include <asm/system.h> | 68 | #include <asm/system.h> |
70 | #include <asm/byteorder.h> | 69 | #include <asm/byteorder.h> |
71 | 70 | ||
71 | #include "../base.h" | ||
72 | #include "pnpbios.h" | 72 | #include "pnpbios.h" |
73 | 73 | ||
74 | /* | 74 | /* |
@@ -203,8 +203,7 @@ static int pnp_dock_thread(void *unused) | |||
203 | 203 | ||
204 | #endif /* CONFIG_HOTPLUG */ | 204 | #endif /* CONFIG_HOTPLUG */ |
205 | 205 | ||
206 | static int pnpbios_get_resources(struct pnp_dev *dev, | 206 | static int pnpbios_get_resources(struct pnp_dev *dev) |
207 | struct pnp_resource_table *res) | ||
208 | { | 207 | { |
209 | u8 nodenum = dev->number; | 208 | u8 nodenum = dev->number; |
210 | struct pnp_bios_node *node; | 209 | struct pnp_bios_node *node; |
@@ -212,6 +211,7 @@ static int pnpbios_get_resources(struct pnp_dev *dev, | |||
212 | if (!pnpbios_is_dynamic(dev)) | 211 | if (!pnpbios_is_dynamic(dev)) |
213 | return -EPERM; | 212 | return -EPERM; |
214 | 213 | ||
214 | dev_dbg(&dev->dev, "get resources\n"); | ||
215 | node = kzalloc(node_info.max_node_size, GFP_KERNEL); | 215 | node = kzalloc(node_info.max_node_size, GFP_KERNEL); |
216 | if (!node) | 216 | if (!node) |
217 | return -1; | 217 | return -1; |
@@ -219,14 +219,13 @@ static int pnpbios_get_resources(struct pnp_dev *dev, | |||
219 | kfree(node); | 219 | kfree(node); |
220 | return -ENODEV; | 220 | return -ENODEV; |
221 | } | 221 | } |
222 | pnpbios_read_resources_from_node(res, node); | 222 | pnpbios_read_resources_from_node(dev, node); |
223 | dev->active = pnp_is_active(dev); | 223 | dev->active = pnp_is_active(dev); |
224 | kfree(node); | 224 | kfree(node); |
225 | return 0; | 225 | return 0; |
226 | } | 226 | } |
227 | 227 | ||
228 | static int pnpbios_set_resources(struct pnp_dev *dev, | 228 | static int pnpbios_set_resources(struct pnp_dev *dev) |
229 | struct pnp_resource_table *res) | ||
230 | { | 229 | { |
231 | u8 nodenum = dev->number; | 230 | u8 nodenum = dev->number; |
232 | struct pnp_bios_node *node; | 231 | struct pnp_bios_node *node; |
@@ -235,6 +234,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev, | |||
235 | if (!pnpbios_is_dynamic(dev)) | 234 | if (!pnpbios_is_dynamic(dev)) |
236 | return -EPERM; | 235 | return -EPERM; |
237 | 236 | ||
237 | dev_dbg(&dev->dev, "set resources\n"); | ||
238 | node = kzalloc(node_info.max_node_size, GFP_KERNEL); | 238 | node = kzalloc(node_info.max_node_size, GFP_KERNEL); |
239 | if (!node) | 239 | if (!node) |
240 | return -1; | 240 | return -1; |
@@ -242,7 +242,7 @@ static int pnpbios_set_resources(struct pnp_dev *dev, | |||
242 | kfree(node); | 242 | kfree(node); |
243 | return -ENODEV; | 243 | return -ENODEV; |
244 | } | 244 | } |
245 | if (pnpbios_write_resources_to_node(res, node) < 0) { | 245 | if (pnpbios_write_resources_to_node(dev, node) < 0) { |
246 | kfree(node); | 246 | kfree(node); |
247 | return -1; | 247 | return -1; |
248 | } | 248 | } |
@@ -317,7 +317,6 @@ static int __init insert_device(struct pnp_bios_node *node) | |||
317 | { | 317 | { |
318 | struct list_head *pos; | 318 | struct list_head *pos; |
319 | struct pnp_dev *dev; | 319 | struct pnp_dev *dev; |
320 | struct pnp_id *dev_id; | ||
321 | char id[8]; | 320 | char id[8]; |
322 | 321 | ||
323 | /* check if the device is already added */ | 322 | /* check if the device is already added */ |
@@ -327,20 +326,11 @@ static int __init insert_device(struct pnp_bios_node *node) | |||
327 | return -1; | 326 | return -1; |
328 | } | 327 | } |
329 | 328 | ||
330 | dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL); | 329 | pnp_eisa_id_to_string(node->eisa_id & PNP_EISA_ID_MASK, id); |
330 | dev = pnp_alloc_dev(&pnpbios_protocol, node->handle, id); | ||
331 | if (!dev) | 331 | if (!dev) |
332 | return -1; | 332 | return -1; |
333 | 333 | ||
334 | dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); | ||
335 | if (!dev_id) { | ||
336 | kfree(dev); | ||
337 | return -1; | ||
338 | } | ||
339 | |||
340 | dev->number = node->handle; | ||
341 | pnpid32_to_pnpid(node->eisa_id, id); | ||
342 | memcpy(dev_id->id, id, 7); | ||
343 | pnp_add_id(dev_id, dev); | ||
344 | pnpbios_parse_data_stream(dev, node); | 334 | pnpbios_parse_data_stream(dev, node); |
345 | dev->active = pnp_is_active(dev); | 335 | dev->active = pnp_is_active(dev); |
346 | dev->flags = node->flags; | 336 | dev->flags = node->flags; |
@@ -353,11 +343,10 @@ static int __init insert_device(struct pnp_bios_node *node) | |||
353 | dev->capabilities |= PNP_WRITE; | 343 | dev->capabilities |= PNP_WRITE; |
354 | if (dev->flags & PNPBIOS_REMOVABLE) | 344 | if (dev->flags & PNPBIOS_REMOVABLE) |
355 | dev->capabilities |= PNP_REMOVABLE; | 345 | dev->capabilities |= PNP_REMOVABLE; |
356 | dev->protocol = &pnpbios_protocol; | ||
357 | 346 | ||
358 | /* clear out the damaged flags */ | 347 | /* clear out the damaged flags */ |
359 | if (!dev->active) | 348 | if (!dev->active) |
360 | pnp_init_resource_table(&dev->res); | 349 | pnp_init_resources(dev); |
361 | 350 | ||
362 | pnp_add_device(dev); | 351 | pnp_add_device(dev); |
363 | pnpbios_interface_attach_device(node); | 352 | pnpbios_interface_attach_device(node); |
diff --git a/drivers/pnp/pnpbios/pnpbios.h b/drivers/pnp/pnpbios/pnpbios.h index d8cb2fd1f127..b09cf6dc2075 100644 --- a/drivers/pnp/pnpbios/pnpbios.h +++ b/drivers/pnp/pnpbios/pnpbios.h | |||
@@ -2,6 +2,142 @@ | |||
2 | * pnpbios.h - contains local definitions | 2 | * pnpbios.h - contains local definitions |
3 | */ | 3 | */ |
4 | 4 | ||
5 | /* | ||
6 | * Include file for the interface to a PnP BIOS | ||
7 | * | ||
8 | * Original BIOS code (C) 1998 Christian Schmidt (chr.schmidt@tu-bs.de) | ||
9 | * PnP handler parts (c) 1998 Tom Lees <tom@lpsg.demon.co.uk> | ||
10 | * Minor reorganizations by David Hinds <dahinds@users.sourceforge.net> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2, or (at your option) any | ||
15 | * later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, but | ||
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
20 | * General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | * Return codes | ||
29 | */ | ||
30 | #define PNP_SUCCESS 0x00 | ||
31 | #define PNP_NOT_SET_STATICALLY 0x7f | ||
32 | #define PNP_UNKNOWN_FUNCTION 0x81 | ||
33 | #define PNP_FUNCTION_NOT_SUPPORTED 0x82 | ||
34 | #define PNP_INVALID_HANDLE 0x83 | ||
35 | #define PNP_BAD_PARAMETER 0x84 | ||
36 | #define PNP_SET_FAILED 0x85 | ||
37 | #define PNP_EVENTS_NOT_PENDING 0x86 | ||
38 | #define PNP_SYSTEM_NOT_DOCKED 0x87 | ||
39 | #define PNP_NO_ISA_PNP_CARDS 0x88 | ||
40 | #define PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES 0x89 | ||
41 | #define PNP_CONFIG_CHANGE_FAILED_NO_BATTERY 0x8a | ||
42 | #define PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT 0x8b | ||
43 | #define PNP_BUFFER_TOO_SMALL 0x8c | ||
44 | #define PNP_USE_ESCD_SUPPORT 0x8d | ||
45 | #define PNP_MESSAGE_NOT_SUPPORTED 0x8e | ||
46 | #define PNP_HARDWARE_ERROR 0x8f | ||
47 | |||
48 | #define ESCD_SUCCESS 0x00 | ||
49 | #define ESCD_IO_ERROR_READING 0x55 | ||
50 | #define ESCD_INVALID 0x56 | ||
51 | #define ESCD_BUFFER_TOO_SMALL 0x59 | ||
52 | #define ESCD_NVRAM_TOO_SMALL 0x5a | ||
53 | #define ESCD_FUNCTION_NOT_SUPPORTED 0x81 | ||
54 | |||
55 | /* | ||
56 | * Events that can be received by "get event" | ||
57 | */ | ||
58 | #define PNPEV_ABOUT_TO_CHANGE_CONFIG 0x0001 | ||
59 | #define PNPEV_DOCK_CHANGED 0x0002 | ||
60 | #define PNPEV_SYSTEM_DEVICE_CHANGED 0x0003 | ||
61 | #define PNPEV_CONFIG_CHANGED_FAILED 0x0004 | ||
62 | #define PNPEV_UNKNOWN_SYSTEM_EVENT 0xffff | ||
63 | /* 0x8000 through 0xfffe are OEM defined */ | ||
64 | |||
65 | /* | ||
66 | * Messages that should be sent through "send message" | ||
67 | */ | ||
68 | #define PNPMSG_OK 0x00 | ||
69 | #define PNPMSG_ABORT 0x01 | ||
70 | #define PNPMSG_UNDOCK_DEFAULT_ACTION 0x40 | ||
71 | #define PNPMSG_POWER_OFF 0x41 | ||
72 | #define PNPMSG_PNP_OS_ACTIVE 0x42 | ||
73 | #define PNPMSG_PNP_OS_INACTIVE 0x43 | ||
74 | |||
75 | /* | ||
76 | * Plug and Play BIOS flags | ||
77 | */ | ||
78 | #define PNPBIOS_NO_DISABLE 0x0001 | ||
79 | #define PNPBIOS_NO_CONFIG 0x0002 | ||
80 | #define PNPBIOS_OUTPUT 0x0004 | ||
81 | #define PNPBIOS_INPUT 0x0008 | ||
82 | #define PNPBIOS_BOOTABLE 0x0010 | ||
83 | #define PNPBIOS_DOCK 0x0020 | ||
84 | #define PNPBIOS_REMOVABLE 0x0040 | ||
85 | #define pnpbios_is_static(x) (((x)->flags & 0x0100) == 0x0000) | ||
86 | #define pnpbios_is_dynamic(x) ((x)->flags & 0x0080) | ||
87 | |||
88 | /* | ||
89 | * Function Parameters | ||
90 | */ | ||
91 | #define PNPMODE_STATIC 1 | ||
92 | #define PNPMODE_DYNAMIC 0 | ||
93 | |||
94 | /* 0x8000 through 0xffff are OEM defined */ | ||
95 | |||
96 | #pragma pack(1) | ||
97 | struct pnp_dev_node_info { | ||
98 | __u16 no_nodes; | ||
99 | __u16 max_node_size; | ||
100 | }; | ||
101 | struct pnp_docking_station_info { | ||
102 | __u32 location_id; | ||
103 | __u32 serial; | ||
104 | __u16 capabilities; | ||
105 | }; | ||
106 | struct pnp_isa_config_struc { | ||
107 | __u8 revision; | ||
108 | __u8 no_csns; | ||
109 | __u16 isa_rd_data_port; | ||
110 | __u16 reserved; | ||
111 | }; | ||
112 | struct escd_info_struc { | ||
113 | __u16 min_escd_write_size; | ||
114 | __u16 escd_size; | ||
115 | __u32 nv_storage_base; | ||
116 | }; | ||
117 | struct pnp_bios_node { | ||
118 | __u16 size; | ||
119 | __u8 handle; | ||
120 | __u32 eisa_id; | ||
121 | __u8 type_code[3]; | ||
122 | __u16 flags; | ||
123 | __u8 data[0]; | ||
124 | }; | ||
125 | #pragma pack() | ||
126 | |||
127 | /* non-exported */ | ||
128 | extern struct pnp_dev_node_info node_info; | ||
129 | |||
130 | extern int pnp_bios_dev_node_info(struct pnp_dev_node_info *data); | ||
131 | extern int pnp_bios_get_dev_node(u8 *nodenum, char config, | ||
132 | struct pnp_bios_node *data); | ||
133 | extern int pnp_bios_set_dev_node(u8 nodenum, char config, | ||
134 | struct pnp_bios_node *data); | ||
135 | extern int pnp_bios_get_stat_res(char *info); | ||
136 | extern int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data); | ||
137 | extern int pnp_bios_escd_info(struct escd_info_struc *data); | ||
138 | extern int pnp_bios_read_escd(char *data, u32 nvram_base); | ||
139 | extern int pnp_bios_dock_station_info(struct pnp_docking_station_info *data); | ||
140 | |||
5 | #pragma pack(1) | 141 | #pragma pack(1) |
6 | union pnp_bios_install_struct { | 142 | union pnp_bios_install_struct { |
7 | struct { | 143 | struct { |
@@ -28,8 +164,8 @@ extern int pnp_bios_present(void); | |||
28 | extern int pnpbios_dont_use_current_config; | 164 | extern int pnpbios_dont_use_current_config; |
29 | 165 | ||
30 | extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node); | 166 | extern int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node * node); |
31 | extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node); | 167 | extern int pnpbios_read_resources_from_node(struct pnp_dev *dev, struct pnp_bios_node *node); |
32 | extern int pnpbios_write_resources_to_node(struct pnp_resource_table *res, struct pnp_bios_node * node); | 168 | extern int pnpbios_write_resources_to_node(struct pnp_dev *dev, struct pnp_bios_node *node); |
33 | extern void pnpid32_to_pnpid(u32 id, char *str); | 169 | extern void pnpid32_to_pnpid(u32 id, char *str); |
34 | 170 | ||
35 | extern void pnpbios_print_status(const char * module, u16 status); | 171 | extern void pnpbios_print_status(const char * module, u16 status); |
diff --git a/drivers/pnp/pnpbios/proc.c b/drivers/pnp/pnpbios/proc.c index 46d506f66259..b35d921bac6e 100644 --- a/drivers/pnp/pnpbios/proc.c +++ b/drivers/pnp/pnpbios/proc.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/proc_fs.h> | 25 | #include <linux/proc_fs.h> |
26 | #include <linux/pnpbios.h> | 26 | #include <linux/pnp.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | 28 | ||
29 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index caade3531416..2e2c457a0fea 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c | |||
@@ -4,7 +4,6 @@ | |||
4 | 4 | ||
5 | #include <linux/ctype.h> | 5 | #include <linux/ctype.h> |
6 | #include <linux/pnp.h> | 6 | #include <linux/pnp.h> |
7 | #include <linux/pnpbios.h> | ||
8 | #include <linux/string.h> | 7 | #include <linux/string.h> |
9 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
10 | 9 | ||
@@ -16,6 +15,7 @@ inline void pcibios_penalize_isa_irq(int irq, int active) | |||
16 | } | 15 | } |
17 | #endif /* CONFIG_PCI */ | 16 | #endif /* CONFIG_PCI */ |
18 | 17 | ||
18 | #include "../base.h" | ||
19 | #include "pnpbios.h" | 19 | #include "pnpbios.h" |
20 | 20 | ||
21 | /* standard resource tags */ | 21 | /* standard resource tags */ |
@@ -53,97 +53,43 @@ inline void pcibios_penalize_isa_irq(int irq, int active) | |||
53 | * Allocated Resources | 53 | * Allocated Resources |
54 | */ | 54 | */ |
55 | 55 | ||
56 | static void pnpbios_parse_allocated_irqresource(struct pnp_resource_table *res, | 56 | static void pnpbios_parse_allocated_ioresource(struct pnp_dev *dev, |
57 | int irq) | 57 | int start, int len) |
58 | { | 58 | { |
59 | int i = 0; | 59 | int flags = 0; |
60 | 60 | int end = start + len - 1; | |
61 | while (!(res->irq_resource[i].flags & IORESOURCE_UNSET) | ||
62 | && i < PNP_MAX_IRQ) | ||
63 | i++; | ||
64 | if (i < PNP_MAX_IRQ) { | ||
65 | res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag | ||
66 | if (irq == -1) { | ||
67 | res->irq_resource[i].flags |= IORESOURCE_DISABLED; | ||
68 | return; | ||
69 | } | ||
70 | res->irq_resource[i].start = | ||
71 | res->irq_resource[i].end = (unsigned long)irq; | ||
72 | pcibios_penalize_isa_irq(irq, 1); | ||
73 | } | ||
74 | } | ||
75 | 61 | ||
76 | static void pnpbios_parse_allocated_dmaresource(struct pnp_resource_table *res, | 62 | if (len <= 0 || end >= 0x10003) |
77 | int dma) | 63 | flags |= IORESOURCE_DISABLED; |
78 | { | ||
79 | int i = 0; | ||
80 | |||
81 | while (i < PNP_MAX_DMA && | ||
82 | !(res->dma_resource[i].flags & IORESOURCE_UNSET)) | ||
83 | i++; | ||
84 | if (i < PNP_MAX_DMA) { | ||
85 | res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag | ||
86 | if (dma == -1) { | ||
87 | res->dma_resource[i].flags |= IORESOURCE_DISABLED; | ||
88 | return; | ||
89 | } | ||
90 | res->dma_resource[i].start = | ||
91 | res->dma_resource[i].end = (unsigned long)dma; | ||
92 | } | ||
93 | } | ||
94 | 64 | ||
95 | static void pnpbios_parse_allocated_ioresource(struct pnp_resource_table *res, | 65 | pnp_add_io_resource(dev, start, end, flags); |
96 | int io, int len) | ||
97 | { | ||
98 | int i = 0; | ||
99 | |||
100 | while (!(res->port_resource[i].flags & IORESOURCE_UNSET) | ||
101 | && i < PNP_MAX_PORT) | ||
102 | i++; | ||
103 | if (i < PNP_MAX_PORT) { | ||
104 | res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag | ||
105 | if (len <= 0 || (io + len - 1) >= 0x10003) { | ||
106 | res->port_resource[i].flags |= IORESOURCE_DISABLED; | ||
107 | return; | ||
108 | } | ||
109 | res->port_resource[i].start = (unsigned long)io; | ||
110 | res->port_resource[i].end = (unsigned long)(io + len - 1); | ||
111 | } | ||
112 | } | 66 | } |
113 | 67 | ||
114 | static void pnpbios_parse_allocated_memresource(struct pnp_resource_table *res, | 68 | static void pnpbios_parse_allocated_memresource(struct pnp_dev *dev, |
115 | int mem, int len) | 69 | int start, int len) |
116 | { | 70 | { |
117 | int i = 0; | 71 | int flags = 0; |
118 | 72 | int end = start + len - 1; | |
119 | while (!(res->mem_resource[i].flags & IORESOURCE_UNSET) | 73 | |
120 | && i < PNP_MAX_MEM) | 74 | if (len <= 0) |
121 | i++; | 75 | flags |= IORESOURCE_DISABLED; |
122 | if (i < PNP_MAX_MEM) { | 76 | |
123 | res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag | 77 | pnp_add_mem_resource(dev, start, end, flags); |
124 | if (len <= 0) { | ||
125 | res->mem_resource[i].flags |= IORESOURCE_DISABLED; | ||
126 | return; | ||
127 | } | ||
128 | res->mem_resource[i].start = (unsigned long)mem; | ||
129 | res->mem_resource[i].end = (unsigned long)(mem + len - 1); | ||
130 | } | ||
131 | } | 78 | } |
132 | 79 | ||
133 | static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, | 80 | static unsigned char *pnpbios_parse_allocated_resource_data(struct pnp_dev *dev, |
134 | unsigned char *end, | 81 | unsigned char *p, |
135 | struct | 82 | unsigned char *end) |
136 | pnp_resource_table | ||
137 | *res) | ||
138 | { | 83 | { |
139 | unsigned int len, tag; | 84 | unsigned int len, tag; |
140 | int io, size, mask, i; | 85 | int io, size, mask, i, flags; |
141 | 86 | ||
142 | if (!p) | 87 | if (!p) |
143 | return NULL; | 88 | return NULL; |
144 | 89 | ||
145 | /* Blank the resource table values */ | 90 | dev_dbg(&dev->dev, "parse allocated resources\n"); |
146 | pnp_init_resource_table(res); | 91 | |
92 | pnp_init_resources(dev); | ||
147 | 93 | ||
148 | while ((char *)p < (char *)end) { | 94 | while ((char *)p < (char *)end) { |
149 | 95 | ||
@@ -163,7 +109,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, | |||
163 | goto len_err; | 109 | goto len_err; |
164 | io = *(short *)&p[4]; | 110 | io = *(short *)&p[4]; |
165 | size = *(short *)&p[10]; | 111 | size = *(short *)&p[10]; |
166 | pnpbios_parse_allocated_memresource(res, io, size); | 112 | pnpbios_parse_allocated_memresource(dev, io, size); |
167 | break; | 113 | break; |
168 | 114 | ||
169 | case LARGE_TAG_ANSISTR: | 115 | case LARGE_TAG_ANSISTR: |
@@ -179,7 +125,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, | |||
179 | goto len_err; | 125 | goto len_err; |
180 | io = *(int *)&p[4]; | 126 | io = *(int *)&p[4]; |
181 | size = *(int *)&p[16]; | 127 | size = *(int *)&p[16]; |
182 | pnpbios_parse_allocated_memresource(res, io, size); | 128 | pnpbios_parse_allocated_memresource(dev, io, size); |
183 | break; | 129 | break; |
184 | 130 | ||
185 | case LARGE_TAG_FIXEDMEM32: | 131 | case LARGE_TAG_FIXEDMEM32: |
@@ -187,29 +133,37 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, | |||
187 | goto len_err; | 133 | goto len_err; |
188 | io = *(int *)&p[4]; | 134 | io = *(int *)&p[4]; |
189 | size = *(int *)&p[8]; | 135 | size = *(int *)&p[8]; |
190 | pnpbios_parse_allocated_memresource(res, io, size); | 136 | pnpbios_parse_allocated_memresource(dev, io, size); |
191 | break; | 137 | break; |
192 | 138 | ||
193 | case SMALL_TAG_IRQ: | 139 | case SMALL_TAG_IRQ: |
194 | if (len < 2 || len > 3) | 140 | if (len < 2 || len > 3) |
195 | goto len_err; | 141 | goto len_err; |
142 | flags = 0; | ||
196 | io = -1; | 143 | io = -1; |
197 | mask = p[1] + p[2] * 256; | 144 | mask = p[1] + p[2] * 256; |
198 | for (i = 0; i < 16; i++, mask = mask >> 1) | 145 | for (i = 0; i < 16; i++, mask = mask >> 1) |
199 | if (mask & 0x01) | 146 | if (mask & 0x01) |
200 | io = i; | 147 | io = i; |
201 | pnpbios_parse_allocated_irqresource(res, io); | 148 | if (io != -1) |
149 | pcibios_penalize_isa_irq(io, 1); | ||
150 | else | ||
151 | flags = IORESOURCE_DISABLED; | ||
152 | pnp_add_irq_resource(dev, io, flags); | ||
202 | break; | 153 | break; |
203 | 154 | ||
204 | case SMALL_TAG_DMA: | 155 | case SMALL_TAG_DMA: |
205 | if (len != 2) | 156 | if (len != 2) |
206 | goto len_err; | 157 | goto len_err; |
158 | flags = 0; | ||
207 | io = -1; | 159 | io = -1; |
208 | mask = p[1]; | 160 | mask = p[1]; |
209 | for (i = 0; i < 8; i++, mask = mask >> 1) | 161 | for (i = 0; i < 8; i++, mask = mask >> 1) |
210 | if (mask & 0x01) | 162 | if (mask & 0x01) |
211 | io = i; | 163 | io = i; |
212 | pnpbios_parse_allocated_dmaresource(res, io); | 164 | if (io == -1) |
165 | flags = IORESOURCE_DISABLED; | ||
166 | pnp_add_dma_resource(dev, io, flags); | ||
213 | break; | 167 | break; |
214 | 168 | ||
215 | case SMALL_TAG_PORT: | 169 | case SMALL_TAG_PORT: |
@@ -217,7 +171,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, | |||
217 | goto len_err; | 171 | goto len_err; |
218 | io = p[2] + p[3] * 256; | 172 | io = p[2] + p[3] * 256; |
219 | size = p[7]; | 173 | size = p[7]; |
220 | pnpbios_parse_allocated_ioresource(res, io, size); | 174 | pnpbios_parse_allocated_ioresource(dev, io, size); |
221 | break; | 175 | break; |
222 | 176 | ||
223 | case SMALL_TAG_VENDOR: | 177 | case SMALL_TAG_VENDOR: |
@@ -229,7 +183,7 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, | |||
229 | goto len_err; | 183 | goto len_err; |
230 | io = p[1] + p[2] * 256; | 184 | io = p[1] + p[2] * 256; |
231 | size = p[3]; | 185 | size = p[3]; |
232 | pnpbios_parse_allocated_ioresource(res, io, size); | 186 | pnpbios_parse_allocated_ioresource(dev, io, size); |
233 | break; | 187 | break; |
234 | 188 | ||
235 | case SMALL_TAG_END: | 189 | case SMALL_TAG_END: |
@@ -239,9 +193,8 @@ static unsigned char *pnpbios_parse_allocated_resource_data(unsigned char *p, | |||
239 | 193 | ||
240 | default: /* an unkown tag */ | 194 | default: /* an unkown tag */ |
241 | len_err: | 195 | len_err: |
242 | printk(KERN_ERR | 196 | dev_err(&dev->dev, "unknown tag %#x length %d\n", |
243 | "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", | 197 | tag, len); |
244 | tag, len); | ||
245 | break; | 198 | break; |
246 | } | 199 | } |
247 | 200 | ||
@@ -252,8 +205,7 @@ len_err: | |||
252 | p += len + 1; | 205 | p += len + 1; |
253 | } | 206 | } |
254 | 207 | ||
255 | printk(KERN_ERR | 208 | dev_err(&dev->dev, "no end tag in resource structure\n"); |
256 | "PnPBIOS: Resource structure does not contain an end tag.\n"); | ||
257 | 209 | ||
258 | return NULL; | 210 | return NULL; |
259 | } | 211 | } |
@@ -262,7 +214,8 @@ len_err: | |||
262 | * Resource Configuration Options | 214 | * Resource Configuration Options |
263 | */ | 215 | */ |
264 | 216 | ||
265 | static __init void pnpbios_parse_mem_option(unsigned char *p, int size, | 217 | static __init void pnpbios_parse_mem_option(struct pnp_dev *dev, |
218 | unsigned char *p, int size, | ||
266 | struct pnp_option *option) | 219 | struct pnp_option *option) |
267 | { | 220 | { |
268 | struct pnp_mem *mem; | 221 | struct pnp_mem *mem; |
@@ -275,10 +228,11 @@ static __init void pnpbios_parse_mem_option(unsigned char *p, int size, | |||
275 | mem->align = (p[9] << 8) | p[8]; | 228 | mem->align = (p[9] << 8) | p[8]; |
276 | mem->size = ((p[11] << 8) | p[10]) << 8; | 229 | mem->size = ((p[11] << 8) | p[10]) << 8; |
277 | mem->flags = p[3]; | 230 | mem->flags = p[3]; |
278 | pnp_register_mem_resource(option, mem); | 231 | pnp_register_mem_resource(dev, option, mem); |
279 | } | 232 | } |
280 | 233 | ||
281 | static __init void pnpbios_parse_mem32_option(unsigned char *p, int size, | 234 | static __init void pnpbios_parse_mem32_option(struct pnp_dev *dev, |
235 | unsigned char *p, int size, | ||
282 | struct pnp_option *option) | 236 | struct pnp_option *option) |
283 | { | 237 | { |
284 | struct pnp_mem *mem; | 238 | struct pnp_mem *mem; |
@@ -291,10 +245,11 @@ static __init void pnpbios_parse_mem32_option(unsigned char *p, int size, | |||
291 | mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12]; | 245 | mem->align = (p[15] << 24) | (p[14] << 16) | (p[13] << 8) | p[12]; |
292 | mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16]; | 246 | mem->size = (p[19] << 24) | (p[18] << 16) | (p[17] << 8) | p[16]; |
293 | mem->flags = p[3]; | 247 | mem->flags = p[3]; |
294 | pnp_register_mem_resource(option, mem); | 248 | pnp_register_mem_resource(dev, option, mem); |
295 | } | 249 | } |
296 | 250 | ||
297 | static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, | 251 | static __init void pnpbios_parse_fixed_mem32_option(struct pnp_dev *dev, |
252 | unsigned char *p, int size, | ||
298 | struct pnp_option *option) | 253 | struct pnp_option *option) |
299 | { | 254 | { |
300 | struct pnp_mem *mem; | 255 | struct pnp_mem *mem; |
@@ -306,11 +261,12 @@ static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, | |||
306 | mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; | 261 | mem->size = (p[11] << 24) | (p[10] << 16) | (p[9] << 8) | p[8]; |
307 | mem->align = 0; | 262 | mem->align = 0; |
308 | mem->flags = p[3]; | 263 | mem->flags = p[3]; |
309 | pnp_register_mem_resource(option, mem); | 264 | pnp_register_mem_resource(dev, option, mem); |
310 | } | 265 | } |
311 | 266 | ||
312 | static __init void pnpbios_parse_irq_option(unsigned char *p, int size, | 267 | static __init void pnpbios_parse_irq_option(struct pnp_dev *dev, |
313 | struct pnp_option *option) | 268 | unsigned char *p, int size, |
269 | struct pnp_option *option) | ||
314 | { | 270 | { |
315 | struct pnp_irq *irq; | 271 | struct pnp_irq *irq; |
316 | unsigned long bits; | 272 | unsigned long bits; |
@@ -324,11 +280,12 @@ static __init void pnpbios_parse_irq_option(unsigned char *p, int size, | |||
324 | irq->flags = p[3]; | 280 | irq->flags = p[3]; |
325 | else | 281 | else |
326 | irq->flags = IORESOURCE_IRQ_HIGHEDGE; | 282 | irq->flags = IORESOURCE_IRQ_HIGHEDGE; |
327 | pnp_register_irq_resource(option, irq); | 283 | pnp_register_irq_resource(dev, option, irq); |
328 | } | 284 | } |
329 | 285 | ||
330 | static __init void pnpbios_parse_dma_option(unsigned char *p, int size, | 286 | static __init void pnpbios_parse_dma_option(struct pnp_dev *dev, |
331 | struct pnp_option *option) | 287 | unsigned char *p, int size, |
288 | struct pnp_option *option) | ||
332 | { | 289 | { |
333 | struct pnp_dma *dma; | 290 | struct pnp_dma *dma; |
334 | 291 | ||
@@ -337,10 +294,11 @@ static __init void pnpbios_parse_dma_option(unsigned char *p, int size, | |||
337 | return; | 294 | return; |
338 | dma->map = p[1]; | 295 | dma->map = p[1]; |
339 | dma->flags = p[2]; | 296 | dma->flags = p[2]; |
340 | pnp_register_dma_resource(option, dma); | 297 | pnp_register_dma_resource(dev, option, dma); |
341 | } | 298 | } |
342 | 299 | ||
343 | static __init void pnpbios_parse_port_option(unsigned char *p, int size, | 300 | static __init void pnpbios_parse_port_option(struct pnp_dev *dev, |
301 | unsigned char *p, int size, | ||
344 | struct pnp_option *option) | 302 | struct pnp_option *option) |
345 | { | 303 | { |
346 | struct pnp_port *port; | 304 | struct pnp_port *port; |
@@ -353,10 +311,11 @@ static __init void pnpbios_parse_port_option(unsigned char *p, int size, | |||
353 | port->align = p[6]; | 311 | port->align = p[6]; |
354 | port->size = p[7]; | 312 | port->size = p[7]; |
355 | port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0; | 313 | port->flags = p[1] ? PNP_PORT_FLAG_16BITADDR : 0; |
356 | pnp_register_port_resource(option, port); | 314 | pnp_register_port_resource(dev, option, port); |
357 | } | 315 | } |
358 | 316 | ||
359 | static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size, | 317 | static __init void pnpbios_parse_fixed_port_option(struct pnp_dev *dev, |
318 | unsigned char *p, int size, | ||
360 | struct pnp_option *option) | 319 | struct pnp_option *option) |
361 | { | 320 | { |
362 | struct pnp_port *port; | 321 | struct pnp_port *port; |
@@ -368,7 +327,7 @@ static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size, | |||
368 | port->size = p[3]; | 327 | port->size = p[3]; |
369 | port->align = 0; | 328 | port->align = 0; |
370 | port->flags = PNP_PORT_FLAG_FIXED; | 329 | port->flags = PNP_PORT_FLAG_FIXED; |
371 | pnp_register_port_resource(option, port); | 330 | pnp_register_port_resource(dev, option, port); |
372 | } | 331 | } |
373 | 332 | ||
374 | static __init unsigned char * | 333 | static __init unsigned char * |
@@ -382,6 +341,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, | |||
382 | if (!p) | 341 | if (!p) |
383 | return NULL; | 342 | return NULL; |
384 | 343 | ||
344 | dev_dbg(&dev->dev, "parse resource options\n"); | ||
345 | |||
385 | option_independent = option = pnp_register_independent_option(dev); | 346 | option_independent = option = pnp_register_independent_option(dev); |
386 | if (!option) | 347 | if (!option) |
387 | return NULL; | 348 | return NULL; |
@@ -402,37 +363,37 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, | |||
402 | case LARGE_TAG_MEM: | 363 | case LARGE_TAG_MEM: |
403 | if (len != 9) | 364 | if (len != 9) |
404 | goto len_err; | 365 | goto len_err; |
405 | pnpbios_parse_mem_option(p, len, option); | 366 | pnpbios_parse_mem_option(dev, p, len, option); |
406 | break; | 367 | break; |
407 | 368 | ||
408 | case LARGE_TAG_MEM32: | 369 | case LARGE_TAG_MEM32: |
409 | if (len != 17) | 370 | if (len != 17) |
410 | goto len_err; | 371 | goto len_err; |
411 | pnpbios_parse_mem32_option(p, len, option); | 372 | pnpbios_parse_mem32_option(dev, p, len, option); |
412 | break; | 373 | break; |
413 | 374 | ||
414 | case LARGE_TAG_FIXEDMEM32: | 375 | case LARGE_TAG_FIXEDMEM32: |
415 | if (len != 9) | 376 | if (len != 9) |
416 | goto len_err; | 377 | goto len_err; |
417 | pnpbios_parse_fixed_mem32_option(p, len, option); | 378 | pnpbios_parse_fixed_mem32_option(dev, p, len, option); |
418 | break; | 379 | break; |
419 | 380 | ||
420 | case SMALL_TAG_IRQ: | 381 | case SMALL_TAG_IRQ: |
421 | if (len < 2 || len > 3) | 382 | if (len < 2 || len > 3) |
422 | goto len_err; | 383 | goto len_err; |
423 | pnpbios_parse_irq_option(p, len, option); | 384 | pnpbios_parse_irq_option(dev, p, len, option); |
424 | break; | 385 | break; |
425 | 386 | ||
426 | case SMALL_TAG_DMA: | 387 | case SMALL_TAG_DMA: |
427 | if (len != 2) | 388 | if (len != 2) |
428 | goto len_err; | 389 | goto len_err; |
429 | pnpbios_parse_dma_option(p, len, option); | 390 | pnpbios_parse_dma_option(dev, p, len, option); |
430 | break; | 391 | break; |
431 | 392 | ||
432 | case SMALL_TAG_PORT: | 393 | case SMALL_TAG_PORT: |
433 | if (len != 7) | 394 | if (len != 7) |
434 | goto len_err; | 395 | goto len_err; |
435 | pnpbios_parse_port_option(p, len, option); | 396 | pnpbios_parse_port_option(dev, p, len, option); |
436 | break; | 397 | break; |
437 | 398 | ||
438 | case SMALL_TAG_VENDOR: | 399 | case SMALL_TAG_VENDOR: |
@@ -442,7 +403,7 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, | |||
442 | case SMALL_TAG_FIXEDPORT: | 403 | case SMALL_TAG_FIXEDPORT: |
443 | if (len != 3) | 404 | if (len != 3) |
444 | goto len_err; | 405 | goto len_err; |
445 | pnpbios_parse_fixed_port_option(p, len, option); | 406 | pnpbios_parse_fixed_port_option(dev, p, len, option); |
446 | break; | 407 | break; |
447 | 408 | ||
448 | case SMALL_TAG_STARTDEP: | 409 | case SMALL_TAG_STARTDEP: |
@@ -460,9 +421,10 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, | |||
460 | if (len != 0) | 421 | if (len != 0) |
461 | goto len_err; | 422 | goto len_err; |
462 | if (option_independent == option) | 423 | if (option_independent == option) |
463 | printk(KERN_WARNING | 424 | dev_warn(&dev->dev, "missing " |
464 | "PnPBIOS: Missing SMALL_TAG_STARTDEP tag\n"); | 425 | "SMALL_TAG_STARTDEP tag\n"); |
465 | option = option_independent; | 426 | option = option_independent; |
427 | dev_dbg(&dev->dev, "end dependent options\n"); | ||
466 | break; | 428 | break; |
467 | 429 | ||
468 | case SMALL_TAG_END: | 430 | case SMALL_TAG_END: |
@@ -470,9 +432,8 @@ pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, | |||
470 | 432 | ||
471 | default: /* an unkown tag */ | 433 | default: /* an unkown tag */ |
472 | len_err: | 434 | len_err: |
473 | printk(KERN_ERR | 435 | dev_err(&dev->dev, "unknown tag %#x length %d\n", |
474 | "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", | 436 | tag, len); |
475 | tag, len); | ||
476 | break; | 437 | break; |
477 | } | 438 | } |
478 | 439 | ||
@@ -483,8 +444,7 @@ len_err: | |||
483 | p += len + 1; | 444 | p += len + 1; |
484 | } | 445 | } |
485 | 446 | ||
486 | printk(KERN_ERR | 447 | dev_err(&dev->dev, "no end tag in resource structure\n"); |
487 | "PnPBIOS: Resource structure does not contain an end tag.\n"); | ||
488 | 448 | ||
489 | return NULL; | 449 | return NULL; |
490 | } | 450 | } |
@@ -493,32 +453,12 @@ len_err: | |||
493 | * Compatible Device IDs | 453 | * Compatible Device IDs |
494 | */ | 454 | */ |
495 | 455 | ||
496 | #define HEX(id,a) hex[((id)>>a) & 15] | ||
497 | #define CHAR(id,a) (0x40 + (((id)>>a) & 31)) | ||
498 | |||
499 | void pnpid32_to_pnpid(u32 id, char *str) | ||
500 | { | ||
501 | const char *hex = "0123456789abcdef"; | ||
502 | |||
503 | id = be32_to_cpu(id); | ||
504 | str[0] = CHAR(id, 26); | ||
505 | str[1] = CHAR(id, 21); | ||
506 | str[2] = CHAR(id, 16); | ||
507 | str[3] = HEX(id, 12); | ||
508 | str[4] = HEX(id, 8); | ||
509 | str[5] = HEX(id, 4); | ||
510 | str[6] = HEX(id, 0); | ||
511 | str[7] = '\0'; | ||
512 | } | ||
513 | |||
514 | #undef CHAR | ||
515 | #undef HEX | ||
516 | |||
517 | static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, | 456 | static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, |
518 | unsigned char *end, | 457 | unsigned char *end, |
519 | struct pnp_dev *dev) | 458 | struct pnp_dev *dev) |
520 | { | 459 | { |
521 | int len, tag; | 460 | int len, tag; |
461 | u32 eisa_id; | ||
522 | char id[8]; | 462 | char id[8]; |
523 | struct pnp_id *dev_id; | 463 | struct pnp_id *dev_id; |
524 | 464 | ||
@@ -548,13 +488,11 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, | |||
548 | case SMALL_TAG_COMPATDEVID: /* compatible ID */ | 488 | case SMALL_TAG_COMPATDEVID: /* compatible ID */ |
549 | if (len != 4) | 489 | if (len != 4) |
550 | goto len_err; | 490 | goto len_err; |
551 | dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL); | 491 | eisa_id = p[1] | p[2] << 8 | p[3] << 16 | p[4] << 24; |
492 | pnp_eisa_id_to_string(eisa_id & PNP_EISA_ID_MASK, id); | ||
493 | dev_id = pnp_add_id(dev, id); | ||
552 | if (!dev_id) | 494 | if (!dev_id) |
553 | return NULL; | 495 | return NULL; |
554 | pnpid32_to_pnpid(p[1] | p[2] << 8 | p[3] << 16 | p[4] << | ||
555 | 24, id); | ||
556 | memcpy(&dev_id->id, id, 7); | ||
557 | pnp_add_id(dev_id, dev); | ||
558 | break; | 496 | break; |
559 | 497 | ||
560 | case SMALL_TAG_END: | 498 | case SMALL_TAG_END: |
@@ -564,9 +502,8 @@ static unsigned char *pnpbios_parse_compatible_ids(unsigned char *p, | |||
564 | 502 | ||
565 | default: /* an unkown tag */ | 503 | default: /* an unkown tag */ |
566 | len_err: | 504 | len_err: |
567 | printk(KERN_ERR | 505 | dev_err(&dev->dev, "unknown tag %#x length %d\n", |
568 | "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", | 506 | tag, len); |
569 | tag, len); | ||
570 | break; | 507 | break; |
571 | } | 508 | } |
572 | 509 | ||
@@ -577,8 +514,7 @@ len_err: | |||
577 | p += len + 1; | 514 | p += len + 1; |
578 | } | 515 | } |
579 | 516 | ||
580 | printk(KERN_ERR | 517 | dev_err(&dev->dev, "no end tag in resource structure\n"); |
581 | "PnPBIOS: Resource structure does not contain an end tag.\n"); | ||
582 | 518 | ||
583 | return NULL; | 519 | return NULL; |
584 | } | 520 | } |
@@ -587,7 +523,8 @@ len_err: | |||
587 | * Allocated Resource Encoding | 523 | * Allocated Resource Encoding |
588 | */ | 524 | */ |
589 | 525 | ||
590 | static void pnpbios_encode_mem(unsigned char *p, struct resource *res) | 526 | static void pnpbios_encode_mem(struct pnp_dev *dev, unsigned char *p, |
527 | struct resource *res) | ||
591 | { | 528 | { |
592 | unsigned long base = res->start; | 529 | unsigned long base = res->start; |
593 | unsigned long len = res->end - res->start + 1; | 530 | unsigned long len = res->end - res->start + 1; |
@@ -598,9 +535,13 @@ static void pnpbios_encode_mem(unsigned char *p, struct resource *res) | |||
598 | p[7] = ((base >> 8) >> 8) & 0xff; | 535 | p[7] = ((base >> 8) >> 8) & 0xff; |
599 | p[10] = (len >> 8) & 0xff; | 536 | p[10] = (len >> 8) & 0xff; |
600 | p[11] = ((len >> 8) >> 8) & 0xff; | 537 | p[11] = ((len >> 8) >> 8) & 0xff; |
538 | |||
539 | dev_dbg(&dev->dev, " encode mem %#llx-%#llx\n", | ||
540 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
601 | } | 541 | } |
602 | 542 | ||
603 | static void pnpbios_encode_mem32(unsigned char *p, struct resource *res) | 543 | static void pnpbios_encode_mem32(struct pnp_dev *dev, unsigned char *p, |
544 | struct resource *res) | ||
604 | { | 545 | { |
605 | unsigned long base = res->start; | 546 | unsigned long base = res->start; |
606 | unsigned long len = res->end - res->start + 1; | 547 | unsigned long len = res->end - res->start + 1; |
@@ -617,9 +558,13 @@ static void pnpbios_encode_mem32(unsigned char *p, struct resource *res) | |||
617 | p[17] = (len >> 8) & 0xff; | 558 | p[17] = (len >> 8) & 0xff; |
618 | p[18] = (len >> 16) & 0xff; | 559 | p[18] = (len >> 16) & 0xff; |
619 | p[19] = (len >> 24) & 0xff; | 560 | p[19] = (len >> 24) & 0xff; |
561 | |||
562 | dev_dbg(&dev->dev, " encode mem32 %#llx-%#llx\n", | ||
563 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
620 | } | 564 | } |
621 | 565 | ||
622 | static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res) | 566 | static void pnpbios_encode_fixed_mem32(struct pnp_dev *dev, unsigned char *p, |
567 | struct resource *res) | ||
623 | { | 568 | { |
624 | unsigned long base = res->start; | 569 | unsigned long base = res->start; |
625 | unsigned long len = res->end - res->start + 1; | 570 | unsigned long len = res->end - res->start + 1; |
@@ -632,26 +577,36 @@ static void pnpbios_encode_fixed_mem32(unsigned char *p, struct resource *res) | |||
632 | p[9] = (len >> 8) & 0xff; | 577 | p[9] = (len >> 8) & 0xff; |
633 | p[10] = (len >> 16) & 0xff; | 578 | p[10] = (len >> 16) & 0xff; |
634 | p[11] = (len >> 24) & 0xff; | 579 | p[11] = (len >> 24) & 0xff; |
580 | |||
581 | dev_dbg(&dev->dev, " encode fixed_mem32 %#llx-%#llx\n", | ||
582 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
635 | } | 583 | } |
636 | 584 | ||
637 | static void pnpbios_encode_irq(unsigned char *p, struct resource *res) | 585 | static void pnpbios_encode_irq(struct pnp_dev *dev, unsigned char *p, |
586 | struct resource *res) | ||
638 | { | 587 | { |
639 | unsigned long map = 0; | 588 | unsigned long map = 0; |
640 | 589 | ||
641 | map = 1 << res->start; | 590 | map = 1 << res->start; |
642 | p[1] = map & 0xff; | 591 | p[1] = map & 0xff; |
643 | p[2] = (map >> 8) & 0xff; | 592 | p[2] = (map >> 8) & 0xff; |
593 | |||
594 | dev_dbg(&dev->dev, " encode irq %d\n", res->start); | ||
644 | } | 595 | } |
645 | 596 | ||
646 | static void pnpbios_encode_dma(unsigned char *p, struct resource *res) | 597 | static void pnpbios_encode_dma(struct pnp_dev *dev, unsigned char *p, |
598 | struct resource *res) | ||
647 | { | 599 | { |
648 | unsigned long map = 0; | 600 | unsigned long map = 0; |
649 | 601 | ||
650 | map = 1 << res->start; | 602 | map = 1 << res->start; |
651 | p[1] = map & 0xff; | 603 | p[1] = map & 0xff; |
604 | |||
605 | dev_dbg(&dev->dev, " encode dma %d\n", res->start); | ||
652 | } | 606 | } |
653 | 607 | ||
654 | static void pnpbios_encode_port(unsigned char *p, struct resource *res) | 608 | static void pnpbios_encode_port(struct pnp_dev *dev, unsigned char *p, |
609 | struct resource *res) | ||
655 | { | 610 | { |
656 | unsigned long base = res->start; | 611 | unsigned long base = res->start; |
657 | unsigned long len = res->end - res->start + 1; | 612 | unsigned long len = res->end - res->start + 1; |
@@ -661,9 +616,13 @@ static void pnpbios_encode_port(unsigned char *p, struct resource *res) | |||
661 | p[4] = base & 0xff; | 616 | p[4] = base & 0xff; |
662 | p[5] = (base >> 8) & 0xff; | 617 | p[5] = (base >> 8) & 0xff; |
663 | p[7] = len & 0xff; | 618 | p[7] = len & 0xff; |
619 | |||
620 | dev_dbg(&dev->dev, " encode io %#llx-%#llx\n", | ||
621 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
664 | } | 622 | } |
665 | 623 | ||
666 | static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res) | 624 | static void pnpbios_encode_fixed_port(struct pnp_dev *dev, unsigned char *p, |
625 | struct resource *res) | ||
667 | { | 626 | { |
668 | unsigned long base = res->start; | 627 | unsigned long base = res->start; |
669 | unsigned long len = res->end - res->start + 1; | 628 | unsigned long len = res->end - res->start + 1; |
@@ -671,13 +630,15 @@ static void pnpbios_encode_fixed_port(unsigned char *p, struct resource *res) | |||
671 | p[1] = base & 0xff; | 630 | p[1] = base & 0xff; |
672 | p[2] = (base >> 8) & 0xff; | 631 | p[2] = (base >> 8) & 0xff; |
673 | p[3] = len & 0xff; | 632 | p[3] = len & 0xff; |
633 | |||
634 | dev_dbg(&dev->dev, " encode fixed_io %#llx-%#llx\n", | ||
635 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
674 | } | 636 | } |
675 | 637 | ||
676 | static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, | 638 | static unsigned char *pnpbios_encode_allocated_resource_data(struct pnp_dev |
677 | unsigned char *end, | 639 | *dev, |
678 | struct | 640 | unsigned char *p, |
679 | pnp_resource_table | 641 | unsigned char *end) |
680 | *res) | ||
681 | { | 642 | { |
682 | unsigned int len, tag; | 643 | unsigned int len, tag; |
683 | int port = 0, irq = 0, dma = 0, mem = 0; | 644 | int port = 0, irq = 0, dma = 0, mem = 0; |
@@ -701,42 +662,48 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, | |||
701 | case LARGE_TAG_MEM: | 662 | case LARGE_TAG_MEM: |
702 | if (len != 9) | 663 | if (len != 9) |
703 | goto len_err; | 664 | goto len_err; |
704 | pnpbios_encode_mem(p, &res->mem_resource[mem]); | 665 | pnpbios_encode_mem(dev, p, |
666 | pnp_get_resource(dev, IORESOURCE_MEM, mem)); | ||
705 | mem++; | 667 | mem++; |
706 | break; | 668 | break; |
707 | 669 | ||
708 | case LARGE_TAG_MEM32: | 670 | case LARGE_TAG_MEM32: |
709 | if (len != 17) | 671 | if (len != 17) |
710 | goto len_err; | 672 | goto len_err; |
711 | pnpbios_encode_mem32(p, &res->mem_resource[mem]); | 673 | pnpbios_encode_mem32(dev, p, |
674 | pnp_get_resource(dev, IORESOURCE_MEM, mem)); | ||
712 | mem++; | 675 | mem++; |
713 | break; | 676 | break; |
714 | 677 | ||
715 | case LARGE_TAG_FIXEDMEM32: | 678 | case LARGE_TAG_FIXEDMEM32: |
716 | if (len != 9) | 679 | if (len != 9) |
717 | goto len_err; | 680 | goto len_err; |
718 | pnpbios_encode_fixed_mem32(p, &res->mem_resource[mem]); | 681 | pnpbios_encode_fixed_mem32(dev, p, |
682 | pnp_get_resource(dev, IORESOURCE_MEM, mem)); | ||
719 | mem++; | 683 | mem++; |
720 | break; | 684 | break; |
721 | 685 | ||
722 | case SMALL_TAG_IRQ: | 686 | case SMALL_TAG_IRQ: |
723 | if (len < 2 || len > 3) | 687 | if (len < 2 || len > 3) |
724 | goto len_err; | 688 | goto len_err; |
725 | pnpbios_encode_irq(p, &res->irq_resource[irq]); | 689 | pnpbios_encode_irq(dev, p, |
690 | pnp_get_resource(dev, IORESOURCE_IRQ, irq)); | ||
726 | irq++; | 691 | irq++; |
727 | break; | 692 | break; |
728 | 693 | ||
729 | case SMALL_TAG_DMA: | 694 | case SMALL_TAG_DMA: |
730 | if (len != 2) | 695 | if (len != 2) |
731 | goto len_err; | 696 | goto len_err; |
732 | pnpbios_encode_dma(p, &res->dma_resource[dma]); | 697 | pnpbios_encode_dma(dev, p, |
698 | pnp_get_resource(dev, IORESOURCE_DMA, dma)); | ||
733 | dma++; | 699 | dma++; |
734 | break; | 700 | break; |
735 | 701 | ||
736 | case SMALL_TAG_PORT: | 702 | case SMALL_TAG_PORT: |
737 | if (len != 7) | 703 | if (len != 7) |
738 | goto len_err; | 704 | goto len_err; |
739 | pnpbios_encode_port(p, &res->port_resource[port]); | 705 | pnpbios_encode_port(dev, p, |
706 | pnp_get_resource(dev, IORESOURCE_IO, port)); | ||
740 | port++; | 707 | port++; |
741 | break; | 708 | break; |
742 | 709 | ||
@@ -747,7 +714,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, | |||
747 | case SMALL_TAG_FIXEDPORT: | 714 | case SMALL_TAG_FIXEDPORT: |
748 | if (len != 3) | 715 | if (len != 3) |
749 | goto len_err; | 716 | goto len_err; |
750 | pnpbios_encode_fixed_port(p, &res->port_resource[port]); | 717 | pnpbios_encode_fixed_port(dev, p, |
718 | pnp_get_resource(dev, IORESOURCE_IO, port)); | ||
751 | port++; | 719 | port++; |
752 | break; | 720 | break; |
753 | 721 | ||
@@ -758,9 +726,8 @@ static unsigned char *pnpbios_encode_allocated_resource_data(unsigned char *p, | |||
758 | 726 | ||
759 | default: /* an unkown tag */ | 727 | default: /* an unkown tag */ |
760 | len_err: | 728 | len_err: |
761 | printk(KERN_ERR | 729 | dev_err(&dev->dev, "unknown tag %#x length %d\n", |
762 | "PnPBIOS: Unknown tag '0x%x', length '%d'.\n", | 730 | tag, len); |
763 | tag, len); | ||
764 | break; | 731 | break; |
765 | } | 732 | } |
766 | 733 | ||
@@ -771,8 +738,7 @@ len_err: | |||
771 | p += len + 1; | 738 | p += len + 1; |
772 | } | 739 | } |
773 | 740 | ||
774 | printk(KERN_ERR | 741 | dev_err(&dev->dev, "no end tag in resource structure\n"); |
775 | "PnPBIOS: Resource structure does not contain an end tag.\n"); | ||
776 | 742 | ||
777 | return NULL; | 743 | return NULL; |
778 | } | 744 | } |
@@ -787,7 +753,7 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev, | |||
787 | unsigned char *p = (char *)node->data; | 753 | unsigned char *p = (char *)node->data; |
788 | unsigned char *end = (char *)(node->data + node->size); | 754 | unsigned char *end = (char *)(node->data + node->size); |
789 | 755 | ||
790 | p = pnpbios_parse_allocated_resource_data(p, end, &dev->res); | 756 | p = pnpbios_parse_allocated_resource_data(dev, p, end); |
791 | if (!p) | 757 | if (!p) |
792 | return -EIO; | 758 | return -EIO; |
793 | p = pnpbios_parse_resource_option_data(p, end, dev); | 759 | p = pnpbios_parse_resource_option_data(p, end, dev); |
@@ -799,25 +765,25 @@ int __init pnpbios_parse_data_stream(struct pnp_dev *dev, | |||
799 | return 0; | 765 | return 0; |
800 | } | 766 | } |
801 | 767 | ||
802 | int pnpbios_read_resources_from_node(struct pnp_resource_table *res, | 768 | int pnpbios_read_resources_from_node(struct pnp_dev *dev, |
803 | struct pnp_bios_node *node) | 769 | struct pnp_bios_node *node) |
804 | { | 770 | { |
805 | unsigned char *p = (char *)node->data; | 771 | unsigned char *p = (char *)node->data; |
806 | unsigned char *end = (char *)(node->data + node->size); | 772 | unsigned char *end = (char *)(node->data + node->size); |
807 | 773 | ||
808 | p = pnpbios_parse_allocated_resource_data(p, end, res); | 774 | p = pnpbios_parse_allocated_resource_data(dev, p, end); |
809 | if (!p) | 775 | if (!p) |
810 | return -EIO; | 776 | return -EIO; |
811 | return 0; | 777 | return 0; |
812 | } | 778 | } |
813 | 779 | ||
814 | int pnpbios_write_resources_to_node(struct pnp_resource_table *res, | 780 | int pnpbios_write_resources_to_node(struct pnp_dev *dev, |
815 | struct pnp_bios_node *node) | 781 | struct pnp_bios_node *node) |
816 | { | 782 | { |
817 | unsigned char *p = (char *)node->data; | 783 | unsigned char *p = (char *)node->data; |
818 | unsigned char *end = (char *)(node->data + node->size); | 784 | unsigned char *end = (char *)(node->data + node->size); |
819 | 785 | ||
820 | p = pnpbios_encode_allocated_resource_data(p, end, res); | 786 | p = pnpbios_encode_allocated_resource_data(dev, p, end); |
821 | if (!p) | 787 | if (!p) |
822 | return -EIO; | 788 | return -EIO; |
823 | return 0; | 789 | return 0; |
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index e4daf4635c48..d049a2279fea 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c | |||
@@ -117,6 +117,7 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) | |||
117 | static void quirk_system_pci_resources(struct pnp_dev *dev) | 117 | static void quirk_system_pci_resources(struct pnp_dev *dev) |
118 | { | 118 | { |
119 | struct pci_dev *pdev = NULL; | 119 | struct pci_dev *pdev = NULL; |
120 | struct resource *res; | ||
120 | resource_size_t pnp_start, pnp_end, pci_start, pci_end; | 121 | resource_size_t pnp_start, pnp_end, pci_start, pci_end; |
121 | int i, j; | 122 | int i, j; |
122 | 123 | ||
@@ -137,13 +138,15 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) | |||
137 | 138 | ||
138 | pci_start = pci_resource_start(pdev, i); | 139 | pci_start = pci_resource_start(pdev, i); |
139 | pci_end = pci_resource_end(pdev, i); | 140 | pci_end = pci_resource_end(pdev, i); |
140 | for (j = 0; j < PNP_MAX_MEM; j++) { | 141 | for (j = 0; |
141 | if (!pnp_mem_valid(dev, j) || | 142 | (res = pnp_get_resource(dev, IORESOURCE_MEM, j)); |
142 | pnp_mem_len(dev, j) == 0) | 143 | j++) { |
144 | if (res->flags & IORESOURCE_UNSET || | ||
145 | (res->start == 0 && res->end == 0)) | ||
143 | continue; | 146 | continue; |
144 | 147 | ||
145 | pnp_start = pnp_mem_start(dev, j); | 148 | pnp_start = res->start; |
146 | pnp_end = pnp_mem_end(dev, j); | 149 | pnp_end = res->end; |
147 | 150 | ||
148 | /* | 151 | /* |
149 | * If the PNP region doesn't overlap the PCI | 152 | * If the PNP region doesn't overlap the PCI |
@@ -176,7 +179,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) | |||
176 | pci_name(pdev), i, | 179 | pci_name(pdev), i, |
177 | (unsigned long long) pci_start, | 180 | (unsigned long long) pci_start, |
178 | (unsigned long long) pci_end); | 181 | (unsigned long long) pci_end); |
179 | pnp_mem_flags(dev, j) = 0; | 182 | res->flags = 0; |
180 | } | 183 | } |
181 | } | 184 | } |
182 | } | 185 | } |
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index e50ebcffb962..2041620d5682 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c | |||
@@ -53,6 +53,8 @@ struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev) | |||
53 | if (dev->independent) | 53 | if (dev->independent) |
54 | dev_err(&dev->dev, "independent resource already registered\n"); | 54 | dev_err(&dev->dev, "independent resource already registered\n"); |
55 | dev->independent = option; | 55 | dev->independent = option; |
56 | |||
57 | dev_dbg(&dev->dev, "new independent option\n"); | ||
56 | return option; | 58 | return option; |
57 | } | 59 | } |
58 | 60 | ||
@@ -70,12 +72,18 @@ struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, | |||
70 | parent->next = option; | 72 | parent->next = option; |
71 | } else | 73 | } else |
72 | dev->dependent = option; | 74 | dev->dependent = option; |
75 | |||
76 | dev_dbg(&dev->dev, "new dependent option (priority %#x)\n", priority); | ||
73 | return option; | 77 | return option; |
74 | } | 78 | } |
75 | 79 | ||
76 | int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) | 80 | int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option, |
81 | struct pnp_irq *data) | ||
77 | { | 82 | { |
78 | struct pnp_irq *ptr; | 83 | struct pnp_irq *ptr; |
84 | #ifdef DEBUG | ||
85 | char buf[PNP_IRQ_NR]; /* hex-encoded, so this is overkill but safe */ | ||
86 | #endif | ||
79 | 87 | ||
80 | ptr = option->irq; | 88 | ptr = option->irq; |
81 | while (ptr && ptr->next) | 89 | while (ptr && ptr->next) |
@@ -94,10 +102,17 @@ int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) | |||
94 | pcibios_penalize_isa_irq(i, 0); | 102 | pcibios_penalize_isa_irq(i, 0); |
95 | } | 103 | } |
96 | #endif | 104 | #endif |
105 | |||
106 | #ifdef DEBUG | ||
107 | bitmap_scnprintf(buf, sizeof(buf), data->map, PNP_IRQ_NR); | ||
108 | dev_dbg(&dev->dev, " irq bitmask %s flags %#x\n", buf, | ||
109 | data->flags); | ||
110 | #endif | ||
97 | return 0; | 111 | return 0; |
98 | } | 112 | } |
99 | 113 | ||
100 | int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) | 114 | int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option, |
115 | struct pnp_dma *data) | ||
101 | { | 116 | { |
102 | struct pnp_dma *ptr; | 117 | struct pnp_dma *ptr; |
103 | 118 | ||
@@ -109,10 +124,13 @@ int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) | |||
109 | else | 124 | else |
110 | option->dma = data; | 125 | option->dma = data; |
111 | 126 | ||
127 | dev_dbg(&dev->dev, " dma bitmask %#x flags %#x\n", data->map, | ||
128 | data->flags); | ||
112 | return 0; | 129 | return 0; |
113 | } | 130 | } |
114 | 131 | ||
115 | int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) | 132 | int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option, |
133 | struct pnp_port *data) | ||
116 | { | 134 | { |
117 | struct pnp_port *ptr; | 135 | struct pnp_port *ptr; |
118 | 136 | ||
@@ -124,10 +142,14 @@ int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) | |||
124 | else | 142 | else |
125 | option->port = data; | 143 | option->port = data; |
126 | 144 | ||
145 | dev_dbg(&dev->dev, " io " | ||
146 | "min %#x max %#x align %d size %d flags %#x\n", | ||
147 | data->min, data->max, data->align, data->size, data->flags); | ||
127 | return 0; | 148 | return 0; |
128 | } | 149 | } |
129 | 150 | ||
130 | int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) | 151 | int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option, |
152 | struct pnp_mem *data) | ||
131 | { | 153 | { |
132 | struct pnp_mem *ptr; | 154 | struct pnp_mem *ptr; |
133 | 155 | ||
@@ -138,6 +160,10 @@ int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) | |||
138 | ptr->next = data; | 160 | ptr->next = data; |
139 | else | 161 | else |
140 | option->mem = data; | 162 | option->mem = data; |
163 | |||
164 | dev_dbg(&dev->dev, " mem " | ||
165 | "min %#x max %#x align %d size %d flags %#x\n", | ||
166 | data->min, data->max, data->align, data->size, data->flags); | ||
141 | return 0; | 167 | return 0; |
142 | } | 168 | } |
143 | 169 | ||
@@ -213,17 +239,18 @@ void pnp_free_option(struct pnp_option *option) | |||
213 | #define cannot_compare(flags) \ | 239 | #define cannot_compare(flags) \ |
214 | ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) | 240 | ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) |
215 | 241 | ||
216 | int pnp_check_port(struct pnp_dev *dev, int idx) | 242 | int pnp_check_port(struct pnp_dev *dev, struct resource *res) |
217 | { | 243 | { |
218 | int tmp; | 244 | int i; |
219 | struct pnp_dev *tdev; | 245 | struct pnp_dev *tdev; |
246 | struct resource *tres; | ||
220 | resource_size_t *port, *end, *tport, *tend; | 247 | resource_size_t *port, *end, *tport, *tend; |
221 | 248 | ||
222 | port = &dev->res.port_resource[idx].start; | 249 | port = &res->start; |
223 | end = &dev->res.port_resource[idx].end; | 250 | end = &res->end; |
224 | 251 | ||
225 | /* if the resource doesn't exist, don't complain about it */ | 252 | /* if the resource doesn't exist, don't complain about it */ |
226 | if (cannot_compare(dev->res.port_resource[idx].flags)) | 253 | if (cannot_compare(res->flags)) |
227 | return 1; | 254 | return 1; |
228 | 255 | ||
229 | /* check if the resource is already in use, skip if the | 256 | /* check if the resource is already in use, skip if the |
@@ -234,18 +261,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx) | |||
234 | } | 261 | } |
235 | 262 | ||
236 | /* check if the resource is reserved */ | 263 | /* check if the resource is reserved */ |
237 | for (tmp = 0; tmp < 8; tmp++) { | 264 | for (i = 0; i < 8; i++) { |
238 | int rport = pnp_reserve_io[tmp << 1]; | 265 | int rport = pnp_reserve_io[i << 1]; |
239 | int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1; | 266 | int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1; |
240 | if (ranged_conflict(port, end, &rport, &rend)) | 267 | if (ranged_conflict(port, end, &rport, &rend)) |
241 | return 0; | 268 | return 0; |
242 | } | 269 | } |
243 | 270 | ||
244 | /* check for internal conflicts */ | 271 | /* check for internal conflicts */ |
245 | for (tmp = 0; tmp < PNP_MAX_PORT && tmp != idx; tmp++) { | 272 | for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { |
246 | if (dev->res.port_resource[tmp].flags & IORESOURCE_IO) { | 273 | if (tres != res && tres->flags & IORESOURCE_IO) { |
247 | tport = &dev->res.port_resource[tmp].start; | 274 | tport = &tres->start; |
248 | tend = &dev->res.port_resource[tmp].end; | 275 | tend = &tres->end; |
249 | if (ranged_conflict(port, end, tport, tend)) | 276 | if (ranged_conflict(port, end, tport, tend)) |
250 | return 0; | 277 | return 0; |
251 | } | 278 | } |
@@ -255,13 +282,14 @@ int pnp_check_port(struct pnp_dev *dev, int idx) | |||
255 | pnp_for_each_dev(tdev) { | 282 | pnp_for_each_dev(tdev) { |
256 | if (tdev == dev) | 283 | if (tdev == dev) |
257 | continue; | 284 | continue; |
258 | for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { | 285 | for (i = 0; |
259 | if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) { | 286 | (tres = pnp_get_resource(tdev, IORESOURCE_IO, i)); |
260 | if (cannot_compare | 287 | i++) { |
261 | (tdev->res.port_resource[tmp].flags)) | 288 | if (tres->flags & IORESOURCE_IO) { |
289 | if (cannot_compare(tres->flags)) | ||
262 | continue; | 290 | continue; |
263 | tport = &tdev->res.port_resource[tmp].start; | 291 | tport = &tres->start; |
264 | tend = &tdev->res.port_resource[tmp].end; | 292 | tend = &tres->end; |
265 | if (ranged_conflict(port, end, tport, tend)) | 293 | if (ranged_conflict(port, end, tport, tend)) |
266 | return 0; | 294 | return 0; |
267 | } | 295 | } |
@@ -271,17 +299,18 @@ int pnp_check_port(struct pnp_dev *dev, int idx) | |||
271 | return 1; | 299 | return 1; |
272 | } | 300 | } |
273 | 301 | ||
274 | int pnp_check_mem(struct pnp_dev *dev, int idx) | 302 | int pnp_check_mem(struct pnp_dev *dev, struct resource *res) |
275 | { | 303 | { |
276 | int tmp; | 304 | int i; |
277 | struct pnp_dev *tdev; | 305 | struct pnp_dev *tdev; |
306 | struct resource *tres; | ||
278 | resource_size_t *addr, *end, *taddr, *tend; | 307 | resource_size_t *addr, *end, *taddr, *tend; |
279 | 308 | ||
280 | addr = &dev->res.mem_resource[idx].start; | 309 | addr = &res->start; |
281 | end = &dev->res.mem_resource[idx].end; | 310 | end = &res->end; |
282 | 311 | ||
283 | /* if the resource doesn't exist, don't complain about it */ | 312 | /* if the resource doesn't exist, don't complain about it */ |
284 | if (cannot_compare(dev->res.mem_resource[idx].flags)) | 313 | if (cannot_compare(res->flags)) |
285 | return 1; | 314 | return 1; |
286 | 315 | ||
287 | /* check if the resource is already in use, skip if the | 316 | /* check if the resource is already in use, skip if the |
@@ -292,18 +321,18 @@ int pnp_check_mem(struct pnp_dev *dev, int idx) | |||
292 | } | 321 | } |
293 | 322 | ||
294 | /* check if the resource is reserved */ | 323 | /* check if the resource is reserved */ |
295 | for (tmp = 0; tmp < 8; tmp++) { | 324 | for (i = 0; i < 8; i++) { |
296 | int raddr = pnp_reserve_mem[tmp << 1]; | 325 | int raddr = pnp_reserve_mem[i << 1]; |
297 | int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1; | 326 | int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1; |
298 | if (ranged_conflict(addr, end, &raddr, &rend)) | 327 | if (ranged_conflict(addr, end, &raddr, &rend)) |
299 | return 0; | 328 | return 0; |
300 | } | 329 | } |
301 | 330 | ||
302 | /* check for internal conflicts */ | 331 | /* check for internal conflicts */ |
303 | for (tmp = 0; tmp < PNP_MAX_MEM && tmp != idx; tmp++) { | 332 | for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { |
304 | if (dev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { | 333 | if (tres != res && tres->flags & IORESOURCE_MEM) { |
305 | taddr = &dev->res.mem_resource[tmp].start; | 334 | taddr = &tres->start; |
306 | tend = &dev->res.mem_resource[tmp].end; | 335 | tend = &tres->end; |
307 | if (ranged_conflict(addr, end, taddr, tend)) | 336 | if (ranged_conflict(addr, end, taddr, tend)) |
308 | return 0; | 337 | return 0; |
309 | } | 338 | } |
@@ -313,13 +342,14 @@ int pnp_check_mem(struct pnp_dev *dev, int idx) | |||
313 | pnp_for_each_dev(tdev) { | 342 | pnp_for_each_dev(tdev) { |
314 | if (tdev == dev) | 343 | if (tdev == dev) |
315 | continue; | 344 | continue; |
316 | for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { | 345 | for (i = 0; |
317 | if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { | 346 | (tres = pnp_get_resource(tdev, IORESOURCE_MEM, i)); |
318 | if (cannot_compare | 347 | i++) { |
319 | (tdev->res.mem_resource[tmp].flags)) | 348 | if (tres->flags & IORESOURCE_MEM) { |
349 | if (cannot_compare(tres->flags)) | ||
320 | continue; | 350 | continue; |
321 | taddr = &tdev->res.mem_resource[tmp].start; | 351 | taddr = &tres->start; |
322 | tend = &tdev->res.mem_resource[tmp].end; | 352 | tend = &tres->end; |
323 | if (ranged_conflict(addr, end, taddr, tend)) | 353 | if (ranged_conflict(addr, end, taddr, tend)) |
324 | return 0; | 354 | return 0; |
325 | } | 355 | } |
@@ -334,14 +364,17 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id) | |||
334 | return IRQ_HANDLED; | 364 | return IRQ_HANDLED; |
335 | } | 365 | } |
336 | 366 | ||
337 | int pnp_check_irq(struct pnp_dev *dev, int idx) | 367 | int pnp_check_irq(struct pnp_dev *dev, struct resource *res) |
338 | { | 368 | { |
339 | int tmp; | 369 | int i; |
340 | struct pnp_dev *tdev; | 370 | struct pnp_dev *tdev; |
341 | resource_size_t *irq = &dev->res.irq_resource[idx].start; | 371 | struct resource *tres; |
372 | resource_size_t *irq; | ||
373 | |||
374 | irq = &res->start; | ||
342 | 375 | ||
343 | /* if the resource doesn't exist, don't complain about it */ | 376 | /* if the resource doesn't exist, don't complain about it */ |
344 | if (cannot_compare(dev->res.irq_resource[idx].flags)) | 377 | if (cannot_compare(res->flags)) |
345 | return 1; | 378 | return 1; |
346 | 379 | ||
347 | /* check if the resource is valid */ | 380 | /* check if the resource is valid */ |
@@ -349,15 +382,15 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) | |||
349 | return 0; | 382 | return 0; |
350 | 383 | ||
351 | /* check if the resource is reserved */ | 384 | /* check if the resource is reserved */ |
352 | for (tmp = 0; tmp < 16; tmp++) { | 385 | for (i = 0; i < 16; i++) { |
353 | if (pnp_reserve_irq[tmp] == *irq) | 386 | if (pnp_reserve_irq[i] == *irq) |
354 | return 0; | 387 | return 0; |
355 | } | 388 | } |
356 | 389 | ||
357 | /* check for internal conflicts */ | 390 | /* check for internal conflicts */ |
358 | for (tmp = 0; tmp < PNP_MAX_IRQ && tmp != idx; tmp++) { | 391 | for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) { |
359 | if (dev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { | 392 | if (tres != res && tres->flags & IORESOURCE_IRQ) { |
360 | if (dev->res.irq_resource[tmp].start == *irq) | 393 | if (tres->start == *irq) |
361 | return 0; | 394 | return 0; |
362 | } | 395 | } |
363 | } | 396 | } |
@@ -388,12 +421,13 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) | |||
388 | pnp_for_each_dev(tdev) { | 421 | pnp_for_each_dev(tdev) { |
389 | if (tdev == dev) | 422 | if (tdev == dev) |
390 | continue; | 423 | continue; |
391 | for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { | 424 | for (i = 0; |
392 | if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { | 425 | (tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i)); |
393 | if (cannot_compare | 426 | i++) { |
394 | (tdev->res.irq_resource[tmp].flags)) | 427 | if (tres->flags & IORESOURCE_IRQ) { |
428 | if (cannot_compare(tres->flags)) | ||
395 | continue; | 429 | continue; |
396 | if ((tdev->res.irq_resource[tmp].start == *irq)) | 430 | if (tres->start == *irq) |
397 | return 0; | 431 | return 0; |
398 | } | 432 | } |
399 | } | 433 | } |
@@ -402,15 +436,18 @@ int pnp_check_irq(struct pnp_dev *dev, int idx) | |||
402 | return 1; | 436 | return 1; |
403 | } | 437 | } |
404 | 438 | ||
405 | int pnp_check_dma(struct pnp_dev *dev, int idx) | 439 | int pnp_check_dma(struct pnp_dev *dev, struct resource *res) |
406 | { | 440 | { |
407 | #ifndef CONFIG_IA64 | 441 | #ifndef CONFIG_IA64 |
408 | int tmp; | 442 | int i; |
409 | struct pnp_dev *tdev; | 443 | struct pnp_dev *tdev; |
410 | resource_size_t *dma = &dev->res.dma_resource[idx].start; | 444 | struct resource *tres; |
445 | resource_size_t *dma; | ||
446 | |||
447 | dma = &res->start; | ||
411 | 448 | ||
412 | /* if the resource doesn't exist, don't complain about it */ | 449 | /* if the resource doesn't exist, don't complain about it */ |
413 | if (cannot_compare(dev->res.dma_resource[idx].flags)) | 450 | if (cannot_compare(res->flags)) |
414 | return 1; | 451 | return 1; |
415 | 452 | ||
416 | /* check if the resource is valid */ | 453 | /* check if the resource is valid */ |
@@ -418,15 +455,15 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) | |||
418 | return 0; | 455 | return 0; |
419 | 456 | ||
420 | /* check if the resource is reserved */ | 457 | /* check if the resource is reserved */ |
421 | for (tmp = 0; tmp < 8; tmp++) { | 458 | for (i = 0; i < 8; i++) { |
422 | if (pnp_reserve_dma[tmp] == *dma) | 459 | if (pnp_reserve_dma[i] == *dma) |
423 | return 0; | 460 | return 0; |
424 | } | 461 | } |
425 | 462 | ||
426 | /* check for internal conflicts */ | 463 | /* check for internal conflicts */ |
427 | for (tmp = 0; tmp < PNP_MAX_DMA && tmp != idx; tmp++) { | 464 | for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) { |
428 | if (dev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { | 465 | if (tres != res && tres->flags & IORESOURCE_DMA) { |
429 | if (dev->res.dma_resource[tmp].start == *dma) | 466 | if (tres->start == *dma) |
430 | return 0; | 467 | return 0; |
431 | } | 468 | } |
432 | } | 469 | } |
@@ -443,12 +480,13 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) | |||
443 | pnp_for_each_dev(tdev) { | 480 | pnp_for_each_dev(tdev) { |
444 | if (tdev == dev) | 481 | if (tdev == dev) |
445 | continue; | 482 | continue; |
446 | for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { | 483 | for (i = 0; |
447 | if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { | 484 | (tres = pnp_get_resource(tdev, IORESOURCE_DMA, i)); |
448 | if (cannot_compare | 485 | i++) { |
449 | (tdev->res.dma_resource[tmp].flags)) | 486 | if (tres->flags & IORESOURCE_DMA) { |
487 | if (cannot_compare(tres->flags)) | ||
450 | continue; | 488 | continue; |
451 | if ((tdev->res.dma_resource[tmp].start == *dma)) | 489 | if (tres->start == *dma) |
452 | return 0; | 490 | return 0; |
453 | } | 491 | } |
454 | } | 492 | } |
@@ -461,6 +499,193 @@ int pnp_check_dma(struct pnp_dev *dev, int idx) | |||
461 | #endif | 499 | #endif |
462 | } | 500 | } |
463 | 501 | ||
502 | struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev, | ||
503 | unsigned int type, unsigned int num) | ||
504 | { | ||
505 | struct pnp_resource_table *res = dev->res; | ||
506 | |||
507 | switch (type) { | ||
508 | case IORESOURCE_IO: | ||
509 | if (num >= PNP_MAX_PORT) | ||
510 | return NULL; | ||
511 | return &res->port[num]; | ||
512 | case IORESOURCE_MEM: | ||
513 | if (num >= PNP_MAX_MEM) | ||
514 | return NULL; | ||
515 | return &res->mem[num]; | ||
516 | case IORESOURCE_IRQ: | ||
517 | if (num >= PNP_MAX_IRQ) | ||
518 | return NULL; | ||
519 | return &res->irq[num]; | ||
520 | case IORESOURCE_DMA: | ||
521 | if (num >= PNP_MAX_DMA) | ||
522 | return NULL; | ||
523 | return &res->dma[num]; | ||
524 | } | ||
525 | return NULL; | ||
526 | } | ||
527 | |||
528 | struct resource *pnp_get_resource(struct pnp_dev *dev, | ||
529 | unsigned int type, unsigned int num) | ||
530 | { | ||
531 | struct pnp_resource *pnp_res; | ||
532 | |||
533 | pnp_res = pnp_get_pnp_resource(dev, type, num); | ||
534 | if (pnp_res) | ||
535 | return &pnp_res->res; | ||
536 | |||
537 | return NULL; | ||
538 | } | ||
539 | EXPORT_SYMBOL(pnp_get_resource); | ||
540 | |||
541 | static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type) | ||
542 | { | ||
543 | struct pnp_resource *pnp_res; | ||
544 | int i; | ||
545 | |||
546 | switch (type) { | ||
547 | case IORESOURCE_IO: | ||
548 | for (i = 0; i < PNP_MAX_PORT; i++) { | ||
549 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i); | ||
550 | if (pnp_res && !pnp_resource_valid(&pnp_res->res)) | ||
551 | return pnp_res; | ||
552 | } | ||
553 | break; | ||
554 | case IORESOURCE_MEM: | ||
555 | for (i = 0; i < PNP_MAX_MEM; i++) { | ||
556 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i); | ||
557 | if (pnp_res && !pnp_resource_valid(&pnp_res->res)) | ||
558 | return pnp_res; | ||
559 | } | ||
560 | break; | ||
561 | case IORESOURCE_IRQ: | ||
562 | for (i = 0; i < PNP_MAX_IRQ; i++) { | ||
563 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i); | ||
564 | if (pnp_res && !pnp_resource_valid(&pnp_res->res)) | ||
565 | return pnp_res; | ||
566 | } | ||
567 | break; | ||
568 | case IORESOURCE_DMA: | ||
569 | for (i = 0; i < PNP_MAX_DMA; i++) { | ||
570 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i); | ||
571 | if (pnp_res && !pnp_resource_valid(&pnp_res->res)) | ||
572 | return pnp_res; | ||
573 | } | ||
574 | break; | ||
575 | } | ||
576 | return NULL; | ||
577 | } | ||
578 | |||
579 | struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq, | ||
580 | int flags) | ||
581 | { | ||
582 | struct pnp_resource *pnp_res; | ||
583 | struct resource *res; | ||
584 | static unsigned char warned; | ||
585 | |||
586 | pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ); | ||
587 | if (!pnp_res) { | ||
588 | if (!warned) { | ||
589 | dev_err(&dev->dev, "can't add resource for IRQ %d\n", | ||
590 | irq); | ||
591 | warned = 1; | ||
592 | } | ||
593 | return NULL; | ||
594 | } | ||
595 | |||
596 | res = &pnp_res->res; | ||
597 | res->flags = IORESOURCE_IRQ | flags; | ||
598 | res->start = irq; | ||
599 | res->end = irq; | ||
600 | |||
601 | dev_dbg(&dev->dev, " add irq %d flags %#x\n", irq, flags); | ||
602 | return pnp_res; | ||
603 | } | ||
604 | |||
605 | struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma, | ||
606 | int flags) | ||
607 | { | ||
608 | struct pnp_resource *pnp_res; | ||
609 | struct resource *res; | ||
610 | static unsigned char warned; | ||
611 | |||
612 | pnp_res = pnp_new_resource(dev, IORESOURCE_DMA); | ||
613 | if (!pnp_res) { | ||
614 | if (!warned) { | ||
615 | dev_err(&dev->dev, "can't add resource for DMA %d\n", | ||
616 | dma); | ||
617 | warned = 1; | ||
618 | } | ||
619 | return NULL; | ||
620 | } | ||
621 | |||
622 | res = &pnp_res->res; | ||
623 | res->flags = IORESOURCE_DMA | flags; | ||
624 | res->start = dma; | ||
625 | res->end = dma; | ||
626 | |||
627 | dev_dbg(&dev->dev, " add dma %d flags %#x\n", dma, flags); | ||
628 | return pnp_res; | ||
629 | } | ||
630 | |||
631 | struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev, | ||
632 | resource_size_t start, | ||
633 | resource_size_t end, int flags) | ||
634 | { | ||
635 | struct pnp_resource *pnp_res; | ||
636 | struct resource *res; | ||
637 | static unsigned char warned; | ||
638 | |||
639 | pnp_res = pnp_new_resource(dev, IORESOURCE_IO); | ||
640 | if (!pnp_res) { | ||
641 | if (!warned) { | ||
642 | dev_err(&dev->dev, "can't add resource for IO " | ||
643 | "%#llx-%#llx\n",(unsigned long long) start, | ||
644 | (unsigned long long) end); | ||
645 | warned = 1; | ||
646 | } | ||
647 | return NULL; | ||
648 | } | ||
649 | |||
650 | res = &pnp_res->res; | ||
651 | res->flags = IORESOURCE_IO | flags; | ||
652 | res->start = start; | ||
653 | res->end = end; | ||
654 | |||
655 | dev_dbg(&dev->dev, " add io %#llx-%#llx flags %#x\n", | ||
656 | (unsigned long long) start, (unsigned long long) end, flags); | ||
657 | return pnp_res; | ||
658 | } | ||
659 | |||
660 | struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev, | ||
661 | resource_size_t start, | ||
662 | resource_size_t end, int flags) | ||
663 | { | ||
664 | struct pnp_resource *pnp_res; | ||
665 | struct resource *res; | ||
666 | static unsigned char warned; | ||
667 | |||
668 | pnp_res = pnp_new_resource(dev, IORESOURCE_MEM); | ||
669 | if (!pnp_res) { | ||
670 | if (!warned) { | ||
671 | dev_err(&dev->dev, "can't add resource for MEM " | ||
672 | "%#llx-%#llx\n",(unsigned long long) start, | ||
673 | (unsigned long long) end); | ||
674 | warned = 1; | ||
675 | } | ||
676 | return NULL; | ||
677 | } | ||
678 | |||
679 | res = &pnp_res->res; | ||
680 | res->flags = IORESOURCE_MEM | flags; | ||
681 | res->start = start; | ||
682 | res->end = end; | ||
683 | |||
684 | dev_dbg(&dev->dev, " add mem %#llx-%#llx flags %#x\n", | ||
685 | (unsigned long long) start, (unsigned long long) end, flags); | ||
686 | return pnp_res; | ||
687 | } | ||
688 | |||
464 | /* format is: pnp_reserve_irq=irq1[,irq2] .... */ | 689 | /* format is: pnp_reserve_irq=irq1[,irq2] .... */ |
465 | static int __init pnp_setup_reserve_irq(char *str) | 690 | static int __init pnp_setup_reserve_irq(char *str) |
466 | { | 691 | { |
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index 13c608f5fb30..3eba85ed729c 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c | |||
@@ -25,3 +25,66 @@ int pnp_is_active(struct pnp_dev *dev) | |||
25 | } | 25 | } |
26 | 26 | ||
27 | EXPORT_SYMBOL(pnp_is_active); | 27 | EXPORT_SYMBOL(pnp_is_active); |
28 | |||
29 | /* | ||
30 | * Functionally similar to acpi_ex_eisa_id_to_string(), but that's | ||
31 | * buried in the ACPI CA, and we can't depend on it being present. | ||
32 | */ | ||
33 | void pnp_eisa_id_to_string(u32 id, char *str) | ||
34 | { | ||
35 | id = be32_to_cpu(id); | ||
36 | |||
37 | /* | ||
38 | * According to the specs, the first three characters are five-bit | ||
39 | * compressed ASCII, and the left-over high order bit should be zero. | ||
40 | * However, the Linux ISAPNP code historically used six bits for the | ||
41 | * first character, and there seem to be IDs that depend on that, | ||
42 | * e.g., "nEC8241" in the Linux 8250_pnp serial driver and the | ||
43 | * FreeBSD sys/pc98/cbus/sio_cbus.c driver. | ||
44 | */ | ||
45 | str[0] = 'A' + ((id >> 26) & 0x3f) - 1; | ||
46 | str[1] = 'A' + ((id >> 21) & 0x1f) - 1; | ||
47 | str[2] = 'A' + ((id >> 16) & 0x1f) - 1; | ||
48 | str[3] = hex_asc((id >> 12) & 0xf); | ||
49 | str[4] = hex_asc((id >> 8) & 0xf); | ||
50 | str[5] = hex_asc((id >> 4) & 0xf); | ||
51 | str[6] = hex_asc((id >> 0) & 0xf); | ||
52 | str[7] = '\0'; | ||
53 | } | ||
54 | |||
55 | void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc) | ||
56 | { | ||
57 | #ifdef DEBUG | ||
58 | struct resource *res; | ||
59 | int i; | ||
60 | |||
61 | dev_dbg(&dev->dev, "current resources: %s\n", desc); | ||
62 | |||
63 | for (i = 0; i < PNP_MAX_IRQ; i++) { | ||
64 | res = pnp_get_resource(dev, IORESOURCE_IRQ, i); | ||
65 | if (res && !(res->flags & IORESOURCE_UNSET)) | ||
66 | dev_dbg(&dev->dev, " irq %lld flags %#lx\n", | ||
67 | (unsigned long long) res->start, res->flags); | ||
68 | } | ||
69 | for (i = 0; i < PNP_MAX_DMA; i++) { | ||
70 | res = pnp_get_resource(dev, IORESOURCE_DMA, i); | ||
71 | if (res && !(res->flags & IORESOURCE_UNSET)) | ||
72 | dev_dbg(&dev->dev, " dma %lld flags %#lx\n", | ||
73 | (unsigned long long) res->start, res->flags); | ||
74 | } | ||
75 | for (i = 0; i < PNP_MAX_PORT; i++) { | ||
76 | res = pnp_get_resource(dev, IORESOURCE_IO, i); | ||
77 | if (res && !(res->flags & IORESOURCE_UNSET)) | ||
78 | dev_dbg(&dev->dev, " io %#llx-%#llx flags %#lx\n", | ||
79 | (unsigned long long) res->start, | ||
80 | (unsigned long long) res->end, res->flags); | ||
81 | } | ||
82 | for (i = 0; i < PNP_MAX_MEM; i++) { | ||
83 | res = pnp_get_resource(dev, IORESOURCE_MEM, i); | ||
84 | if (res && !(res->flags & IORESOURCE_UNSET)) | ||
85 | dev_dbg(&dev->dev, " mem %#llx-%#llx flags %#lx\n", | ||
86 | (unsigned long long) res->start, | ||
87 | (unsigned long long) res->end, res->flags); | ||
88 | } | ||
89 | #endif | ||
90 | } | ||
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index 55c4563986b3..9c2496dbeee4 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c | |||
@@ -56,14 +56,15 @@ static void reserve_range(struct pnp_dev *dev, resource_size_t start, | |||
56 | 56 | ||
57 | static void reserve_resources_of_dev(struct pnp_dev *dev) | 57 | static void reserve_resources_of_dev(struct pnp_dev *dev) |
58 | { | 58 | { |
59 | struct resource *res; | ||
59 | int i; | 60 | int i; |
60 | 61 | ||
61 | for (i = 0; i < PNP_MAX_PORT; i++) { | 62 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { |
62 | if (!pnp_port_valid(dev, i)) | 63 | if (res->flags & IORESOURCE_UNSET) |
63 | continue; | 64 | continue; |
64 | if (pnp_port_start(dev, i) == 0) | 65 | if (res->start == 0) |
65 | continue; /* disabled */ | 66 | continue; /* disabled */ |
66 | if (pnp_port_start(dev, i) < 0x100) | 67 | if (res->start < 0x100) |
67 | /* | 68 | /* |
68 | * Below 0x100 is only standard PC hardware | 69 | * Below 0x100 is only standard PC hardware |
69 | * (pics, kbd, timer, dma, ...) | 70 | * (pics, kbd, timer, dma, ...) |
@@ -73,19 +74,17 @@ static void reserve_resources_of_dev(struct pnp_dev *dev) | |||
73 | * So, do nothing | 74 | * So, do nothing |
74 | */ | 75 | */ |
75 | continue; | 76 | continue; |
76 | if (pnp_port_end(dev, i) < pnp_port_start(dev, i)) | 77 | if (res->end < res->start) |
77 | continue; /* invalid */ | 78 | continue; /* invalid */ |
78 | 79 | ||
79 | reserve_range(dev, pnp_port_start(dev, i), | 80 | reserve_range(dev, res->start, res->end, 1); |
80 | pnp_port_end(dev, i), 1); | ||
81 | } | 81 | } |
82 | 82 | ||
83 | for (i = 0; i < PNP_MAX_MEM; i++) { | 83 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { |
84 | if (!pnp_mem_valid(dev, i)) | 84 | if (res->flags & IORESOURCE_UNSET) |
85 | continue; | 85 | continue; |
86 | 86 | ||
87 | reserve_range(dev, pnp_mem_start(dev, i), | 87 | reserve_range(dev, res->start, res->end, 0); |
88 | pnp_mem_end(dev, i), 0); | ||
89 | } | 88 | } |
90 | } | 89 | } |
91 | 90 | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index dcdc142a3441..d060a06ce05b 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -854,11 +854,12 @@ cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) | |||
854 | * don't define the IRQ. It should always be safe to | 854 | * don't define the IRQ. It should always be safe to |
855 | * hardcode it in these cases | 855 | * hardcode it in these cases |
856 | */ | 856 | */ |
857 | return cmos_do_probe(&pnp->dev, &pnp->res.port_resource[0], 8); | 857 | return cmos_do_probe(&pnp->dev, |
858 | pnp_get_resource(pnp, IORESOURCE_IO, 0), 8); | ||
858 | else | 859 | else |
859 | return cmos_do_probe(&pnp->dev, | 860 | return cmos_do_probe(&pnp->dev, |
860 | &pnp->res.port_resource[0], | 861 | pnp_get_resource(pnp, IORESOURCE_IO, 0), |
861 | pnp->res.irq_resource[0].start); | 862 | pnp_irq(pnp, 0)); |
862 | } | 863 | } |
863 | 864 | ||
864 | static void __exit cmos_pnp_remove(struct pnp_dev *pnp) | 865 | static void __exit cmos_pnp_remove(struct pnp_dev *pnp) |
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 17e71d56f31e..4b628526df09 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menuconfig THERMAL | 5 | menuconfig THERMAL |
6 | bool "Generic Thermal sysfs driver" | 6 | tristate "Generic Thermal sysfs driver" |
7 | help | 7 | help |
8 | Generic Thermal Sysfs driver offers a generic mechanism for | 8 | Generic Thermal Sysfs driver offers a generic mechanism for |
9 | thermal management. Usually it's made up of one or more thermal | 9 | thermal management. Usually it's made up of one or more thermal |
@@ -11,4 +11,4 @@ menuconfig THERMAL | |||
11 | Each thermal zone contains its own temperature, trip points, | 11 | Each thermal zone contains its own temperature, trip points, |
12 | cooling devices. | 12 | cooling devices. |
13 | All platforms with ACPI thermal support can use this driver. | 13 | All platforms with ACPI thermal support can use this driver. |
14 | If you want this support, you should say Y here. | 14 | If you want this support, you should say Y or M here. |
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 8ef1232de376..31108a01c22e 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile | |||
@@ -2,4 +2,4 @@ | |||
2 | # Makefile for sensor chip drivers. | 2 | # Makefile for sensor chip drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_THERMAL) += thermal.o | 5 | obj-$(CONFIG_THERMAL) += thermal_sys.o |
diff --git a/drivers/thermal/thermal.c b/drivers/thermal/thermal_sys.c index 7f79bbf652d7..6098787341f3 100644 --- a/drivers/thermal/thermal.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/thermal.h> | 31 | #include <linux/thermal.h> |
32 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
33 | 33 | ||
34 | MODULE_AUTHOR("Zhang Rui") | 34 | MODULE_AUTHOR("Zhang Rui"); |
35 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); | 35 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); |
36 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
37 | 37 | ||
@@ -295,6 +295,164 @@ thermal_cooling_device_trip_point_show(struct device *dev, | |||
295 | 295 | ||
296 | /* Device management */ | 296 | /* Device management */ |
297 | 297 | ||
298 | #if defined(CONFIG_HWMON) || \ | ||
299 | (defined(CONFIG_HWMON_MODULE) && defined(CONFIG_THERMAL_MODULE)) | ||
300 | /* hwmon sys I/F */ | ||
301 | #include <linux/hwmon.h> | ||
302 | static LIST_HEAD(thermal_hwmon_list); | ||
303 | |||
304 | static ssize_t | ||
305 | name_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
306 | { | ||
307 | struct thermal_hwmon_device *hwmon = dev->driver_data; | ||
308 | return sprintf(buf, "%s\n", hwmon->type); | ||
309 | } | ||
310 | static DEVICE_ATTR(name, 0444, name_show, NULL); | ||
311 | |||
312 | static ssize_t | ||
313 | temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
314 | { | ||
315 | struct thermal_hwmon_attr *hwmon_attr | ||
316 | = container_of(attr, struct thermal_hwmon_attr, attr); | ||
317 | struct thermal_zone_device *tz | ||
318 | = container_of(hwmon_attr, struct thermal_zone_device, | ||
319 | temp_input); | ||
320 | |||
321 | return tz->ops->get_temp(tz, buf); | ||
322 | } | ||
323 | |||
324 | static ssize_t | ||
325 | temp_crit_show(struct device *dev, struct device_attribute *attr, | ||
326 | char *buf) | ||
327 | { | ||
328 | struct thermal_hwmon_attr *hwmon_attr | ||
329 | = container_of(attr, struct thermal_hwmon_attr, attr); | ||
330 | struct thermal_zone_device *tz | ||
331 | = container_of(hwmon_attr, struct thermal_zone_device, | ||
332 | temp_crit); | ||
333 | |||
334 | return tz->ops->get_trip_temp(tz, 0, buf); | ||
335 | } | ||
336 | |||
337 | |||
338 | static int | ||
339 | thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) | ||
340 | { | ||
341 | struct thermal_hwmon_device *hwmon; | ||
342 | int new_hwmon_device = 1; | ||
343 | int result; | ||
344 | |||
345 | mutex_lock(&thermal_list_lock); | ||
346 | list_for_each_entry(hwmon, &thermal_hwmon_list, node) | ||
347 | if (!strcmp(hwmon->type, tz->type)) { | ||
348 | new_hwmon_device = 0; | ||
349 | mutex_unlock(&thermal_list_lock); | ||
350 | goto register_sys_interface; | ||
351 | } | ||
352 | mutex_unlock(&thermal_list_lock); | ||
353 | |||
354 | hwmon = kzalloc(sizeof(struct thermal_hwmon_device), GFP_KERNEL); | ||
355 | if (!hwmon) | ||
356 | return -ENOMEM; | ||
357 | |||
358 | INIT_LIST_HEAD(&hwmon->tz_list); | ||
359 | strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); | ||
360 | hwmon->device = hwmon_device_register(NULL); | ||
361 | if (IS_ERR(hwmon->device)) { | ||
362 | result = PTR_ERR(hwmon->device); | ||
363 | goto free_mem; | ||
364 | } | ||
365 | hwmon->device->driver_data = hwmon; | ||
366 | result = device_create_file(hwmon->device, &dev_attr_name); | ||
367 | if (result) | ||
368 | goto unregister_hwmon_device; | ||
369 | |||
370 | register_sys_interface: | ||
371 | tz->hwmon = hwmon; | ||
372 | hwmon->count++; | ||
373 | |||
374 | snprintf(tz->temp_input.name, THERMAL_NAME_LENGTH, | ||
375 | "temp%d_input", hwmon->count); | ||
376 | tz->temp_input.attr.attr.name = tz->temp_input.name; | ||
377 | tz->temp_input.attr.attr.mode = 0444; | ||
378 | tz->temp_input.attr.show = temp_input_show; | ||
379 | result = device_create_file(hwmon->device, &tz->temp_input.attr); | ||
380 | if (result) | ||
381 | goto unregister_hwmon_device; | ||
382 | |||
383 | if (tz->ops->get_crit_temp) { | ||
384 | unsigned long temperature; | ||
385 | if (!tz->ops->get_crit_temp(tz, &temperature)) { | ||
386 | snprintf(tz->temp_crit.name, THERMAL_NAME_LENGTH, | ||
387 | "temp%d_crit", hwmon->count); | ||
388 | tz->temp_crit.attr.attr.name = tz->temp_crit.name; | ||
389 | tz->temp_crit.attr.attr.mode = 0444; | ||
390 | tz->temp_crit.attr.show = temp_crit_show; | ||
391 | result = device_create_file(hwmon->device, | ||
392 | &tz->temp_crit.attr); | ||
393 | if (result) | ||
394 | goto unregister_hwmon_device; | ||
395 | } | ||
396 | } | ||
397 | |||
398 | mutex_lock(&thermal_list_lock); | ||
399 | if (new_hwmon_device) | ||
400 | list_add_tail(&hwmon->node, &thermal_hwmon_list); | ||
401 | list_add_tail(&tz->hwmon_node, &hwmon->tz_list); | ||
402 | mutex_unlock(&thermal_list_lock); | ||
403 | |||
404 | return 0; | ||
405 | |||
406 | unregister_hwmon_device: | ||
407 | device_remove_file(hwmon->device, &tz->temp_crit.attr); | ||
408 | device_remove_file(hwmon->device, &tz->temp_input.attr); | ||
409 | if (new_hwmon_device) { | ||
410 | device_remove_file(hwmon->device, &dev_attr_name); | ||
411 | hwmon_device_unregister(hwmon->device); | ||
412 | } | ||
413 | free_mem: | ||
414 | if (new_hwmon_device) | ||
415 | kfree(hwmon); | ||
416 | |||
417 | return result; | ||
418 | } | ||
419 | |||
420 | static void | ||
421 | thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) | ||
422 | { | ||
423 | struct thermal_hwmon_device *hwmon = tz->hwmon; | ||
424 | |||
425 | tz->hwmon = NULL; | ||
426 | device_remove_file(hwmon->device, &tz->temp_input.attr); | ||
427 | device_remove_file(hwmon->device, &tz->temp_crit.attr); | ||
428 | |||
429 | mutex_lock(&thermal_list_lock); | ||
430 | list_del(&tz->hwmon_node); | ||
431 | if (!list_empty(&hwmon->tz_list)) { | ||
432 | mutex_unlock(&thermal_list_lock); | ||
433 | return; | ||
434 | } | ||
435 | list_del(&hwmon->node); | ||
436 | mutex_unlock(&thermal_list_lock); | ||
437 | |||
438 | device_remove_file(hwmon->device, &dev_attr_name); | ||
439 | hwmon_device_unregister(hwmon->device); | ||
440 | kfree(hwmon); | ||
441 | } | ||
442 | #else | ||
443 | static int | ||
444 | thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) | ||
445 | { | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | static void | ||
450 | thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) | ||
451 | { | ||
452 | } | ||
453 | #endif | ||
454 | |||
455 | |||
298 | /** | 456 | /** |
299 | * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone | 457 | * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone |
300 | * @tz: thermal zone device | 458 | * @tz: thermal zone device |
@@ -642,6 +800,10 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, | |||
642 | goto unregister; | 800 | goto unregister; |
643 | } | 801 | } |
644 | 802 | ||
803 | result = thermal_add_hwmon_sysfs(tz); | ||
804 | if (result) | ||
805 | goto unregister; | ||
806 | |||
645 | mutex_lock(&thermal_list_lock); | 807 | mutex_lock(&thermal_list_lock); |
646 | list_add_tail(&tz->node, &thermal_tz_list); | 808 | list_add_tail(&tz->node, &thermal_tz_list); |
647 | if (ops->bind) | 809 | if (ops->bind) |
@@ -700,6 +862,7 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) | |||
700 | for (count = 0; count < tz->trips; count++) | 862 | for (count = 0; count < tz->trips; count++) |
701 | TRIP_POINT_ATTR_REMOVE(&tz->device, count); | 863 | TRIP_POINT_ATTR_REMOVE(&tz->device, count); |
702 | 864 | ||
865 | thermal_remove_hwmon_sysfs(tz); | ||
703 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); | 866 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); |
704 | idr_destroy(&tz->idr); | 867 | idr_destroy(&tz->idr); |
705 | mutex_destroy(&tz->lock); | 868 | mutex_destroy(&tz->lock); |