diff options
author | Zhao Yakui <yakui.zhao@intel.com> | 2007-11-15 04:05:05 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-11-16 21:43:21 -0500 |
commit | 9bcb27217344c2c1389db3983a436e19484c2f50 (patch) | |
tree | 14c28cade53f8f64755f3d660149c3c7d501fd1d /drivers/acpi | |
parent | 0753f6e0a3d9568fb6b8e34753b944d9f8eed05b (diff) |
ACPI: Use _TSS for throttling control, when present. Add error checks.
_TSS was erroneously ignored, in favor of the FADT.
When TSS is used, the access width is included in the PTC control/status
register. So it is unnecessary that the access bit width is multiplied by 8.
At the same time the bit_offset should be considered for system I/O Access.
It should be checked the bit_width and bit_offset of PTC regsiter in order to
avoid the failure of system I/O access. It means that bit_width plus
bit_offset can't be greater than 32.
Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
Signed-off-by: Li Shaohua <shaohua.li@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/processor_throttling.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 5c96ef18e94c..f4b5f7d5dbe6 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
@@ -131,6 +131,7 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) | |||
131 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 131 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
132 | union acpi_object *ptc = NULL; | 132 | union acpi_object *ptc = NULL; |
133 | union acpi_object obj = { 0 }; | 133 | union acpi_object obj = { 0 }; |
134 | struct acpi_processor_throttling *throttling; | ||
134 | 135 | ||
135 | status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); | 136 | status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); |
136 | if (ACPI_FAILURE(status)) { | 137 | if (ACPI_FAILURE(status)) { |
@@ -182,6 +183,22 @@ static int acpi_processor_get_throttling_control(struct acpi_processor *pr) | |||
182 | memcpy(&pr->throttling.status_register, obj.buffer.pointer, | 183 | memcpy(&pr->throttling.status_register, obj.buffer.pointer, |
183 | sizeof(struct acpi_ptc_register)); | 184 | sizeof(struct acpi_ptc_register)); |
184 | 185 | ||
186 | throttling = &pr->throttling; | ||
187 | |||
188 | if ((throttling->control_register.bit_width + | ||
189 | throttling->control_register.bit_offset) > 32) { | ||
190 | printk(KERN_ERR PREFIX "Invalid _PTC control register\n"); | ||
191 | result = -EFAULT; | ||
192 | goto end; | ||
193 | } | ||
194 | |||
195 | if ((throttling->status_register.bit_width + | ||
196 | throttling->status_register.bit_offset) > 32) { | ||
197 | printk(KERN_ERR PREFIX "Invalid _PTC status register\n"); | ||
198 | result = -EFAULT; | ||
199 | goto end; | ||
200 | } | ||
201 | |||
185 | end: | 202 | end: |
186 | kfree(buffer.pointer); | 203 | kfree(buffer.pointer); |
187 | 204 | ||
@@ -379,7 +396,9 @@ static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) | |||
379 | static int acpi_read_throttling_status(struct acpi_processor *pr, | 396 | static int acpi_read_throttling_status(struct acpi_processor *pr, |
380 | acpi_integer *value) | 397 | acpi_integer *value) |
381 | { | 398 | { |
399 | u32 bit_width, bit_offset; | ||
382 | u64 ptc_value; | 400 | u64 ptc_value; |
401 | u64 ptc_mask; | ||
383 | struct acpi_processor_throttling *throttling; | 402 | struct acpi_processor_throttling *throttling; |
384 | int ret = -1; | 403 | int ret = -1; |
385 | 404 | ||
@@ -387,11 +406,14 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, | |||
387 | switch (throttling->status_register.space_id) { | 406 | switch (throttling->status_register.space_id) { |
388 | case ACPI_ADR_SPACE_SYSTEM_IO: | 407 | case ACPI_ADR_SPACE_SYSTEM_IO: |
389 | ptc_value = 0; | 408 | ptc_value = 0; |
409 | bit_width = throttling->status_register.bit_width; | ||
410 | bit_offset = throttling->status_register.bit_offset; | ||
411 | |||
390 | acpi_os_read_port((acpi_io_address) throttling->status_register. | 412 | acpi_os_read_port((acpi_io_address) throttling->status_register. |
391 | address, (u32 *) &ptc_value, | 413 | address, (u32 *) &ptc_value, |
392 | (u32) throttling->status_register.bit_width * | 414 | (u32) (bit_width + bit_offset)); |
393 | 8); | 415 | ptc_mask = (1 << bit_width) - 1; |
394 | *value = (acpi_integer) ptc_value; | 416 | *value = (acpi_integer) ((ptc_value >> bit_offset) & ptc_mask); |
395 | ret = 0; | 417 | ret = 0; |
396 | break; | 418 | break; |
397 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | 419 | case ACPI_ADR_SPACE_FIXED_HARDWARE: |
@@ -408,18 +430,24 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, | |||
408 | static int acpi_write_throttling_state(struct acpi_processor *pr, | 430 | static int acpi_write_throttling_state(struct acpi_processor *pr, |
409 | acpi_integer value) | 431 | acpi_integer value) |
410 | { | 432 | { |
433 | u32 bit_width, bit_offset; | ||
411 | u64 ptc_value; | 434 | u64 ptc_value; |
435 | u64 ptc_mask; | ||
412 | struct acpi_processor_throttling *throttling; | 436 | struct acpi_processor_throttling *throttling; |
413 | int ret = -1; | 437 | int ret = -1; |
414 | 438 | ||
415 | throttling = &pr->throttling; | 439 | throttling = &pr->throttling; |
416 | switch (throttling->control_register.space_id) { | 440 | switch (throttling->control_register.space_id) { |
417 | case ACPI_ADR_SPACE_SYSTEM_IO: | 441 | case ACPI_ADR_SPACE_SYSTEM_IO: |
418 | ptc_value = value; | 442 | bit_width = throttling->control_register.bit_width; |
443 | bit_offset = throttling->control_register.bit_offset; | ||
444 | ptc_mask = (1 << bit_width) - 1; | ||
445 | ptc_value = value & ptc_mask; | ||
446 | |||
419 | acpi_os_write_port((acpi_io_address) throttling-> | 447 | acpi_os_write_port((acpi_io_address) throttling-> |
420 | control_register.address, (u32) ptc_value, | 448 | control_register.address, |
421 | (u32) throttling->control_register. | 449 | (u32) (ptc_value << bit_offset), |
422 | bit_width * 8); | 450 | (u32) (bit_width + bit_offset)); |
423 | ret = 0; | 451 | ret = 0; |
424 | break; | 452 | break; |
425 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | 453 | case ACPI_ADR_SPACE_FIXED_HARDWARE: |