diff options
Diffstat (limited to 'drivers/hwmon/asus_atk0110.c')
-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 | ||