aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/i8k.c76
1 files changed, 62 insertions, 14 deletions
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index 09ebe06764e3..24cc4ed9a780 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -43,6 +43,7 @@
43#define I8K_SMM_SET_FAN 0x01a3 43#define I8K_SMM_SET_FAN 0x01a3
44#define I8K_SMM_GET_FAN 0x00a3 44#define I8K_SMM_GET_FAN 0x00a3
45#define I8K_SMM_GET_SPEED 0x02a3 45#define I8K_SMM_GET_SPEED 0x02a3
46#define I8K_SMM_GET_FAN_TYPE 0x03a3
46#define I8K_SMM_GET_NOM_SPEED 0x04a3 47#define I8K_SMM_GET_NOM_SPEED 0x04a3
47#define I8K_SMM_GET_TEMP 0x10a3 48#define I8K_SMM_GET_TEMP 0x10a3
48#define I8K_SMM_GET_TEMP_TYPE 0x11a3 49#define I8K_SMM_GET_TEMP_TYPE 0x11a3
@@ -279,6 +280,17 @@ static int i8k_get_fan_speed(int fan)
279} 280}
280 281
281/* 282/*
283 * Read the fan type.
284 */
285static int i8k_get_fan_type(int fan)
286{
287 struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };
288
289 regs.ebx = fan & 0xff;
290 return i8k_smm(&regs) ? : regs.eax & 0xff;
291}
292
293/*
282 * Read the fan nominal rpm for specific fan speed. 294 * Read the fan nominal rpm for specific fan speed.
283 */ 295 */
284static int i8k_get_fan_nominal_speed(int fan, int speed) 296static int i8k_get_fan_nominal_speed(int fan, int speed)
@@ -553,6 +565,37 @@ static ssize_t i8k_hwmon_show_temp(struct device *dev,
553 return sprintf(buf, "%d\n", temp * 1000); 565 return sprintf(buf, "%d\n", temp * 1000);
554} 566}
555 567
568static ssize_t i8k_hwmon_show_fan_label(struct device *dev,
569 struct device_attribute *devattr,
570 char *buf)
571{
572 static const char * const labels[] = {
573 "Processor Fan",
574 "Motherboard Fan",
575 "Video Fan",
576 "Power Supply Fan",
577 "Chipset Fan",
578 "Other Fan",
579 };
580 int index = to_sensor_dev_attr(devattr)->index;
581 bool dock = false;
582 int type;
583
584 type = i8k_get_fan_type(index);
585 if (type < 0)
586 return type;
587
588 if (type & 0x10) {
589 dock = true;
590 type &= 0x0F;
591 }
592
593 if (type >= ARRAY_SIZE(labels))
594 type = (ARRAY_SIZE(labels) - 1);
595
596 return sprintf(buf, "%s%s\n", (dock ? "Docking " : ""), labels[type]);
597}
598
556static ssize_t i8k_hwmon_show_fan(struct device *dev, 599static ssize_t i8k_hwmon_show_fan(struct device *dev,
557 struct device_attribute *devattr, 600 struct device_attribute *devattr,
558 char *buf) 601 char *buf)
@@ -611,14 +654,17 @@ static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
611static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3); 654static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, i8k_hwmon_show_temp, NULL, 3);
612static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL, 655static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, i8k_hwmon_show_temp_label, NULL,
613 3); 656 3);
614static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, 657static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, i8k_hwmon_show_fan, NULL, 0);
615 I8K_FAN_LEFT); 658static SENSOR_DEVICE_ATTR(fan1_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,
659 0);
616static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, 660static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
617 i8k_hwmon_set_pwm, I8K_FAN_LEFT); 661 i8k_hwmon_set_pwm, 0);
618static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL, 662static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, i8k_hwmon_show_fan, NULL,
619 I8K_FAN_RIGHT); 663 1);
664static SENSOR_DEVICE_ATTR(fan2_label, S_IRUGO, i8k_hwmon_show_fan_label, NULL,
665 1);
620static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm, 666static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, i8k_hwmon_show_pwm,
621 i8k_hwmon_set_pwm, I8K_FAN_RIGHT); 667 i8k_hwmon_set_pwm, 1);
622 668
623static struct attribute *i8k_attrs[] = { 669static struct attribute *i8k_attrs[] = {
624 &sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */ 670 &sensor_dev_attr_temp1_input.dev_attr.attr, /* 0 */
@@ -630,9 +676,11 @@ static struct attribute *i8k_attrs[] = {
630 &sensor_dev_attr_temp4_input.dev_attr.attr, /* 6 */ 676 &sensor_dev_attr_temp4_input.dev_attr.attr, /* 6 */
631 &sensor_dev_attr_temp4_label.dev_attr.attr, /* 7 */ 677 &sensor_dev_attr_temp4_label.dev_attr.attr, /* 7 */
632 &sensor_dev_attr_fan1_input.dev_attr.attr, /* 8 */ 678 &sensor_dev_attr_fan1_input.dev_attr.attr, /* 8 */
633 &sensor_dev_attr_pwm1.dev_attr.attr, /* 9 */ 679 &sensor_dev_attr_fan1_label.dev_attr.attr, /* 9 */
634 &sensor_dev_attr_fan2_input.dev_attr.attr, /* 10 */ 680 &sensor_dev_attr_pwm1.dev_attr.attr, /* 10 */
635 &sensor_dev_attr_pwm2.dev_attr.attr, /* 11 */ 681 &sensor_dev_attr_fan2_input.dev_attr.attr, /* 11 */
682 &sensor_dev_attr_fan2_label.dev_attr.attr, /* 12 */
683 &sensor_dev_attr_pwm2.dev_attr.attr, /* 13 */
636 NULL 684 NULL
637}; 685};
638 686
@@ -651,10 +699,10 @@ static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
651 if (index >= 6 && index <= 7 && 699 if (index >= 6 && index <= 7 &&
652 !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4)) 700 !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP4))
653 return 0; 701 return 0;
654 if (index >= 8 && index <= 9 && 702 if (index >= 8 && index <= 10 &&
655 !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1)) 703 !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN1))
656 return 0; 704 return 0;
657 if (index >= 10 && index <= 11 && 705 if (index >= 11 && index <= 13 &&
658 !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2)) 706 !(i8k_hwmon_flags & I8K_HWMON_HAVE_FAN2))
659 return 0; 707 return 0;
660 708
@@ -688,13 +736,13 @@ static int __init i8k_init_hwmon(void)
688 if (err >= 0) 736 if (err >= 0)
689 i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4; 737 i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
690 738
691 /* Left fan attributes, if left fan is present */ 739 /* First fan attributes, if fan type is OK */
692 err = i8k_get_fan_status(I8K_FAN_LEFT); 740 err = i8k_get_fan_type(0);
693 if (err >= 0) 741 if (err >= 0)
694 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1; 742 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;
695 743
696 /* Right fan attributes, if right fan is present */ 744 /* Second fan attributes, if fan type is OK */
697 err = i8k_get_fan_status(I8K_FAN_RIGHT); 745 err = i8k_get_fan_type(1);
698 if (err >= 0) 746 if (err >= 0)
699 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2; 747 i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;
700 748