Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

platform/x86: thinkpad_acpi: Fix for ThinkPad's with ECFW showing incorrect fan speed

Fix for Thinkpad's with ECFW showing incorrect fan speed. Some models use
decimal instead of hexadecimal for the speed stored in the EC registers.
For example the rpm register will have 0x4200 instead of 0x1068, here
the actual RPM is "4200" in decimal.

Add a quirk to handle this.

Signed-off-by: Vishnu Sankar <vishnuocv@gmail.com>
Suggested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Link: https://lore.kernel.org/r/20241105235505.8493-1-vishnuocv@gmail.com
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>

authored by

Vishnu Sankar and committed by
Hans de Goede
1be765b2 36e66be8

+25 -3
+25 -3
drivers/platform/x86/thinkpad_acpi.c
··· 7936 7936 static int fan_watchdog_maxinterval; 7937 7937 7938 7938 static bool fan_with_ns_addr; 7939 + static bool ecfw_with_fan_dec_rpm; 7939 7940 7940 7941 static struct mutex fan_mutex; 7941 7942 ··· 8683 8682 if (res < 0) 8684 8683 return res; 8685 8684 8686 - return sysfs_emit(buf, "%u\n", speed); 8685 + /* Check for fan speeds displayed in hexadecimal */ 8686 + if (!ecfw_with_fan_dec_rpm) 8687 + return sysfs_emit(buf, "%u\n", speed); 8688 + else 8689 + return sysfs_emit(buf, "%x\n", speed); 8687 8690 } 8688 8691 8689 8692 static DEVICE_ATTR(fan1_input, S_IRUGO, fan_fan1_input_show, NULL); ··· 8704 8699 if (res < 0) 8705 8700 return res; 8706 8701 8707 - return sysfs_emit(buf, "%u\n", speed); 8702 + /* Check for fan speeds displayed in hexadecimal */ 8703 + if (!ecfw_with_fan_dec_rpm) 8704 + return sysfs_emit(buf, "%u\n", speed); 8705 + else 8706 + return sysfs_emit(buf, "%x\n", speed); 8708 8707 } 8709 8708 8710 8709 static DEVICE_ATTR(fan2_input, S_IRUGO, fan_fan2_input_show, NULL); ··· 8784 8775 #define TPACPI_FAN_2CTL 0x0004 /* selects fan2 control */ 8785 8776 #define TPACPI_FAN_NOFAN 0x0008 /* no fan available */ 8786 8777 #define TPACPI_FAN_NS 0x0010 /* For EC with non-Standard register addresses */ 8778 + #define TPACPI_FAN_DECRPM 0x0020 /* For ECFW's with RPM in register as decimal */ 8787 8779 8788 8780 static const struct tpacpi_quirk fan_quirk_table[] __initconst = { 8789 8781 TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1), ··· 8813 8803 TPACPI_Q_LNV3('R', '1', 'D', TPACPI_FAN_NS), /* 11e Gen5 GL-R */ 8814 8804 TPACPI_Q_LNV3('R', '0', 'V', TPACPI_FAN_NS), /* 11e Gen5 KL-Y */ 8815 8805 TPACPI_Q_LNV3('N', '1', 'O', TPACPI_FAN_NOFAN), /* X1 Tablet (2nd gen) */ 8806 + TPACPI_Q_LNV3('R', '0', 'Q', TPACPI_FAN_DECRPM),/* L480 */ 8816 8807 }; 8817 8808 8818 8809 static int __init fan_init(struct ibm_init_struct *iibm) ··· 8855 8844 pr_info("ECFW with non-standard fan reg control found\n"); 8856 8845 fan_with_ns_addr = 1; 8857 8846 /* Fan ctrl support from host is undefined for now */ 8847 + tp_features.fan_ctrl_status_undef = 1; 8848 + } 8849 + 8850 + /* Check for the EC/BIOS with RPM reported in decimal*/ 8851 + if (quirks & TPACPI_FAN_DECRPM) { 8852 + pr_info("ECFW with fan RPM as decimal in EC register\n"); 8853 + ecfw_with_fan_dec_rpm = 1; 8858 8854 tp_features.fan_ctrl_status_undef = 1; 8859 8855 } 8860 8856 ··· 9085 9067 if (rc < 0) 9086 9068 return rc; 9087 9069 9088 - seq_printf(m, "speed:\t\t%d\n", speed); 9070 + /* Check for fan speeds displayed in hexadecimal */ 9071 + if (!ecfw_with_fan_dec_rpm) 9072 + seq_printf(m, "speed:\t\t%d\n", speed); 9073 + else 9074 + seq_printf(m, "speed:\t\t%x\n", speed); 9089 9075 9090 9076 if (fan_status_access_mode == TPACPI_FAN_RD_TPEC_NS) { 9091 9077 /*