diff options
author | Luca Tettamanti <kronos.it@gmail.com> | 2009-10-09 14:35:18 -0400 |
---|---|---|
committer | Jean Delvare <khali@linux-fr.org> | 2009-10-09 14:35:18 -0400 |
commit | 18e255558574c5663c9d72fe82c099d2115aee55 (patch) | |
tree | 395c31badbb72a7da87871512b3c16eba9f07d11 | |
parent | cb0f1a1e77e4280c3138047ad5c16d88320a1fde (diff) |
hwmon: (asus_atk0110) Refactor the code
Refactor the code of the new style interface around GGRP (enumeration) and
GITM (read) helpers to mimic ASL code. Also switch the read path to use
dynamic buffers (handled by ACPI core) since ASUS expanded the return buffer
(ASBF) in newer boards (e.g. P7P55D).
Signed-off-by: Luca Tettamanti <kronos.it@gmail.com>
Tested-by: Robert Hancock <hancockrwd@gmail.com>
Tested-by: Thomas Backlund <tmb@mandriva.org>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r-- | drivers/hwmon/asus_atk0110.c | 158 |
1 files changed, 102 insertions, 56 deletions
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index fe4fa29c9219..19f3fd32e10a 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c | |||
@@ -129,9 +129,22 @@ struct atk_sensor_data { | |||
129 | char const *acpi_name; | 129 | char const *acpi_name; |
130 | }; | 130 | }; |
131 | 131 | ||
132 | struct atk_acpi_buffer_u64 { | 132 | /* Return buffer format: |
133 | union acpi_object buf; | 133 | * [0-3] "value" is valid flag |
134 | u64 value; | 134 | * [4-7] value |
135 | * [8- ] unknown stuff on newer mobos | ||
136 | */ | ||
137 | struct atk_acpi_ret_buffer { | ||
138 | u32 flags; | ||
139 | u32 value; | ||
140 | u8 data[]; | ||
141 | }; | ||
142 | |||
143 | /* Input buffer used for GITM and SITM methods */ | ||
144 | struct atk_acpi_input_buf { | ||
145 | u32 id; | ||
146 | u32 param1; | ||
147 | u32 param2; | ||
135 | }; | 148 | }; |
136 | 149 | ||
137 | static int atk_add(struct acpi_device *device); | 150 | static int atk_add(struct acpi_device *device); |
@@ -439,52 +452,110 @@ static int atk_read_value_old(struct atk_sensor_data *sensor, u64 *value) | |||
439 | return 0; | 452 | return 0; |
440 | } | 453 | } |
441 | 454 | ||
442 | static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value) | 455 | static union acpi_object *atk_ggrp(struct atk_data *data, u16 mux) |
443 | { | 456 | { |
444 | struct atk_data *data = sensor->data; | ||
445 | struct device *dev = &data->acpi_dev->dev; | 457 | struct device *dev = &data->acpi_dev->dev; |
458 | struct acpi_buffer buf; | ||
459 | acpi_status ret; | ||
446 | struct acpi_object_list params; | 460 | struct acpi_object_list params; |
447 | struct acpi_buffer ret; | ||
448 | union acpi_object id; | 461 | union acpi_object id; |
449 | struct atk_acpi_buffer_u64 tmp; | 462 | union acpi_object *pack; |
450 | acpi_status status; | ||
451 | 463 | ||
452 | id.type = ACPI_TYPE_INTEGER; | 464 | id.type = ACPI_TYPE_INTEGER; |
453 | id.integer.value = sensor->id; | 465 | id.integer.value = mux; |
454 | |||
455 | params.count = 1; | 466 | params.count = 1; |
456 | params.pointer = &id; | 467 | params.pointer = &id; |
457 | 468 | ||
458 | tmp.buf.type = ACPI_TYPE_BUFFER; | 469 | buf.length = ACPI_ALLOCATE_BUFFER; |
459 | tmp.buf.buffer.pointer = (u8 *)&tmp.value; | 470 | ret = acpi_evaluate_object(data->enumerate_handle, NULL, ¶ms, &buf); |
460 | tmp.buf.buffer.length = sizeof(u64); | 471 | if (ret != AE_OK) { |
461 | ret.length = sizeof(tmp); | 472 | dev_err(dev, "GGRP[%#x] ACPI exception: %s\n", mux, |
462 | ret.pointer = &tmp; | 473 | acpi_format_exception(ret)); |
474 | return ERR_PTR(-EIO); | ||
475 | } | ||
476 | pack = buf.pointer; | ||
477 | if (pack->type != ACPI_TYPE_PACKAGE) { | ||
478 | /* Execution was successful, but the id was not found */ | ||
479 | ACPI_FREE(pack); | ||
480 | return ERR_PTR(-ENOENT); | ||
481 | } | ||
463 | 482 | ||
483 | if (pack->package.count < 1) { | ||
484 | dev_err(dev, "GGRP[%#x] package is too small\n", mux); | ||
485 | ACPI_FREE(pack); | ||
486 | return ERR_PTR(-EIO); | ||
487 | } | ||
488 | return pack; | ||
489 | } | ||
490 | |||
491 | static union acpi_object *atk_gitm(struct atk_data *data, u64 id) | ||
492 | { | ||
493 | struct device *dev = &data->acpi_dev->dev; | ||
494 | struct atk_acpi_input_buf buf; | ||
495 | union acpi_object tmp; | ||
496 | struct acpi_object_list params; | ||
497 | struct acpi_buffer ret; | ||
498 | union acpi_object *obj; | ||
499 | acpi_status status; | ||
500 | |||
501 | buf.id = id; | ||
502 | buf.param1 = 0; | ||
503 | buf.param2 = 0; | ||
504 | |||
505 | tmp.type = ACPI_TYPE_BUFFER; | ||
506 | tmp.buffer.pointer = (u8 *)&buf; | ||
507 | tmp.buffer.length = sizeof(buf); | ||
508 | |||
509 | params.count = 1; | ||
510 | params.pointer = (void *)&tmp; | ||
511 | |||
512 | ret.length = ACPI_ALLOCATE_BUFFER; | ||
464 | status = acpi_evaluate_object_typed(data->read_handle, NULL, ¶ms, | 513 | status = acpi_evaluate_object_typed(data->read_handle, NULL, ¶ms, |
465 | &ret, ACPI_TYPE_BUFFER); | 514 | &ret, ACPI_TYPE_BUFFER); |
466 | if (status != AE_OK) { | 515 | if (status != AE_OK) { |
467 | dev_warn(dev, "%s: ACPI exception: %s\n", __func__, | 516 | dev_warn(dev, "GITM[%#llx] ACPI exception: %s\n", id, |
468 | acpi_format_exception(status)); | 517 | acpi_format_exception(status)); |
469 | return -EIO; | 518 | return ERR_PTR(-EIO); |
519 | } | ||
520 | obj = ret.pointer; | ||
521 | |||
522 | /* Sanity check */ | ||
523 | if (obj->buffer.length < 8) { | ||
524 | dev_warn(dev, "Unexpected ASBF length: %u\n", | ||
525 | obj->buffer.length); | ||
526 | ACPI_FREE(obj); | ||
527 | return ERR_PTR(-EIO); | ||
470 | } | 528 | } |
529 | return obj; | ||
530 | } | ||
471 | 531 | ||
472 | /* Return buffer format: | 532 | static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value) |
473 | * [0-3] "value" is valid flag | 533 | { |
474 | * [4-7] value | 534 | struct atk_data *data = sensor->data; |
475 | */ | 535 | struct device *dev = &data->acpi_dev->dev; |
476 | if (!(tmp.value & 0xffffffff)) { | 536 | union acpi_object *obj; |
537 | struct atk_acpi_ret_buffer *buf; | ||
538 | int err = 0; | ||
539 | |||
540 | obj = atk_gitm(data, sensor->id); | ||
541 | if (IS_ERR(obj)) | ||
542 | return PTR_ERR(obj); | ||
543 | |||
544 | buf = (struct atk_acpi_ret_buffer *)obj->buffer.pointer; | ||
545 | if (buf->flags == 0) { | ||
477 | /* The reading is not valid, possible causes: | 546 | /* The reading is not valid, possible causes: |
478 | * - sensor failure | 547 | * - sensor failure |
479 | * - enumeration was FUBAR (and we didn't notice) | 548 | * - enumeration was FUBAR (and we didn't notice) |
480 | */ | 549 | */ |
481 | dev_info(dev, "Failure: %#llx\n", tmp.value); | 550 | dev_warn(dev, "Read failed, sensor = %#llx\n", sensor->id); |
482 | return -EIO; | 551 | err = -EIO; |
552 | goto out; | ||
483 | } | 553 | } |
484 | 554 | ||
485 | *value = (tmp.value & 0xffffffff00000000ULL) >> 32; | 555 | *value = buf->value; |
486 | 556 | out: | |
487 | return 0; | 557 | ACPI_FREE(obj); |
558 | return err; | ||
488 | } | 559 | } |
489 | 560 | ||
490 | static int atk_read_value(struct atk_sensor_data *sensor, u64 *value) | 561 | static int atk_read_value(struct atk_sensor_data *sensor, u64 *value) |
@@ -716,39 +787,15 @@ cleanup: | |||
716 | static int atk_enumerate_new_hwmon(struct atk_data *data) | 787 | static int atk_enumerate_new_hwmon(struct atk_data *data) |
717 | { | 788 | { |
718 | struct device *dev = &data->acpi_dev->dev; | 789 | struct device *dev = &data->acpi_dev->dev; |
719 | struct acpi_buffer buf; | ||
720 | acpi_status ret; | ||
721 | struct acpi_object_list params; | ||
722 | union acpi_object id; | ||
723 | union acpi_object *pack; | 790 | union acpi_object *pack; |
724 | int err; | 791 | int err; |
725 | int i; | 792 | int i; |
726 | 793 | ||
727 | dev_dbg(dev, "Enumerating hwmon sensors\n"); | 794 | dev_dbg(dev, "Enumerating hwmon sensors\n"); |
728 | 795 | ||
729 | id.type = ACPI_TYPE_INTEGER; | 796 | pack = atk_ggrp(data, ATK_MUX_HWMON); |
730 | id.integer.value = ATK_MUX_HWMON; | 797 | if (IS_ERR(pack)) |
731 | params.count = 1; | 798 | return PTR_ERR(pack); |
732 | params.pointer = &id; | ||
733 | |||
734 | buf.length = ACPI_ALLOCATE_BUFFER; | ||
735 | ret = acpi_evaluate_object_typed(data->enumerate_handle, NULL, ¶ms, | ||
736 | &buf, ACPI_TYPE_PACKAGE); | ||
737 | if (ret != AE_OK) { | ||
738 | dev_warn(dev, METHOD_ENUMERATE ": ACPI exception: %s\n", | ||
739 | acpi_format_exception(ret)); | ||
740 | return -ENODEV; | ||
741 | } | ||
742 | |||
743 | /* Result must be a package */ | ||
744 | pack = buf.pointer; | ||
745 | |||
746 | if (pack->package.count < 1) { | ||
747 | dev_dbg(dev, "%s: hwmon package is too small: %d\n", __func__, | ||
748 | pack->package.count); | ||
749 | err = -EINVAL; | ||
750 | goto out; | ||
751 | } | ||
752 | 799 | ||
753 | for (i = 0; i < pack->package.count; i++) { | 800 | for (i = 0; i < pack->package.count; i++) { |
754 | union acpi_object *obj = &pack->package.elements[i]; | 801 | union acpi_object *obj = &pack->package.elements[i]; |
@@ -758,8 +805,7 @@ static int atk_enumerate_new_hwmon(struct atk_data *data) | |||
758 | 805 | ||
759 | err = data->voltage_count + data->temperature_count + data->fan_count; | 806 | err = data->voltage_count + data->temperature_count + data->fan_count; |
760 | 807 | ||
761 | out: | 808 | ACPI_FREE(pack); |
762 | ACPI_FREE(buf.pointer); | ||
763 | return err; | 809 | return err; |
764 | } | 810 | } |
765 | 811 | ||