aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/asus_atk0110.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/asus_atk0110.c')
-rw-r--r--drivers/hwmon/asus_atk0110.c158
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
132struct 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 */
137struct atk_acpi_ret_buffer {
138 u32 flags;
139 u32 value;
140 u8 data[];
141};
142
143/* Input buffer used for GITM and SITM methods */
144struct atk_acpi_input_buf {
145 u32 id;
146 u32 param1;
147 u32 param2;
135}; 148};
136 149
137static int atk_add(struct acpi_device *device); 150static 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
442static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value) 455static 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, &params, &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
491static 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, &params, 513 status = acpi_evaluate_object_typed(data->read_handle, NULL, &params,
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: 532static 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 556out:
487 return 0; 557 ACPI_FREE(obj);
558 return err;
488} 559}
489 560
490static int atk_read_value(struct atk_sensor_data *sensor, u64 *value) 561static int atk_read_value(struct atk_sensor_data *sensor, u64 *value)
@@ -716,39 +787,15 @@ cleanup:
716static int atk_enumerate_new_hwmon(struct atk_data *data) 787static 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, &params,
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
761out: 808 ACPI_FREE(pack);
762 ACPI_FREE(buf.pointer);
763 return err; 809 return err;
764} 810}
765 811