diff options
| -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 | ||
