Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

handling of multiple fans on Lenovo P50 #58

Open
sassmann opened this issue Aug 14, 2018 · 131 comments
Open

handling of multiple fans on Lenovo P50 #58

sassmann opened this issue Aug 14, 2018 · 131 comments
Labels
enhancement Idea for an improvement or a new feature

Comments

@sassmann
Copy link

The P50 has 2 fans, lm-sensors shows:

thinkpad-isa-0000
Adapter: ISA adapter
fan1:        2316 RPM
fan2:        2332 RPM

in sysfs there is

# ls -al /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/
total 0
drwxr-xr-x 3 root root    0 Aug 14 13:39 .
drwxr-xr-x 3 root root    0 Aug 14 10:01 ..
lrwxrwxrwx 1 root root    0 Aug 14 10:01 device -> ../../../thinkpad_hwmon
-r--r--r-- 1 root root 4096 Aug 14 13:39 fan1_input
-r--r--r-- 1 root root 4096 Aug 14 10:01 fan2_input
-r--r--r-- 1 root root 4096 Aug 14 10:01 name
drwxr-xr-x 2 root root    0 Aug 14 13:39 power
-rw-r--r-- 1 root root 4096 Aug 14 13:39 pwm1
-rw-r--r-- 1 root root 4096 Aug 14 13:39 pwm1_enable
lrwxrwxrwx 1 root root    0 Aug 14 10:01 subsystem -> ../../../../../class/hwmon
-rw-r--r-- 1 root root 4096 Aug 14 10:01 uevent

It seems that thinkfan is only able to control fan1, fan2 keeps constant ~2300 RPM.
thinkfan.conf used

tp_fan /proc/acpi/ibm/fan
hwmon /sys/devices/platform/coretemp.0/hwmon/hwmon4/temp1_input
(0,     0,      65)
(1,     55,     82)
(2,     65,     88)
(6,     82,     92)
(7,     70,     32767)

Is there a way to control both fans?

@vmatare
Copy link
Owner

vmatare commented Aug 24, 2018

No, currently thinkfan is designed to control one fan only. In theory, you can use dangerous mode (the -D switch that disables all sanity checks) to allow for two instances of thinkfan to be running at the same time, one for each fan. But I've never tried that, it might work or not. However, I am currently working on multifan support, but my spare time is limited so it might take a while.

@vmatare vmatare added the enhancement Idea for an improvement or a new feature label Aug 24, 2018
@vmatare
Copy link
Owner

vmatare commented Aug 24, 2018

Oh btw, looking at your hwmon directory listing, I see that you only seem to have a pwm1 file, but not pwm2. This indicates that your hwmon driver can only control one fan, so that would be an additional issue that you'd have to resolve with the driver developer (thinkpad_acpi I guess).

@ericvhileman
Copy link

Would love to have this ability for the x1 extreme as well. Unsure why lm-sensors only detects one fan for me though...

@vmatare
Copy link
Owner

vmatare commented Jan 2, 2019

The thinkpad_acpi kernel module is probably responsible for detecting the fans. Before thinkfan can use them, they will have to be supported by thinkpad_acpi, so I guess you'll have to contact those authors/maintainers for that.

@LukeFernandes
Copy link

Hi there, just wondering if this is still in the pipeline? There are quite a few ThinkPad dual fan laptops now, especially in the P series, and without this functionality thinkfan is less useful than it could be.

@vmatare
Copy link
Owner

vmatare commented Sep 26, 2019

Well, are they supported by thinkpad_acpi or any other hwmon driver? Because if not then you have to talk to these developers first ;-)

@bssb
Copy link

bssb commented Nov 3, 2019

I also have the issue where only 1 of the 2 fans is detected by thinkpad_acpi (on my P53), so I filed a bug here: https://bugzilla.kernel.org/show_bug.cgi?id=205405

@voidworker
Copy link

There are more and more dual-fan thinkpad laptops.

I use old thinkpad_acpi patch for 2-fan thinkpads, P50 and P70. I can't adapt it to P53, because I understand almost nothing in the code. But maybe someone can help P53 owners one day...
TIP: if dmideocode | grep N1 output is non-empty, there is a chance this patch works for you.

I don't know why this patch has not been accepted into kernel, but I'm using it and it works (kernel version is 4.15):

# ls -al /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon3/
total 0
drwxr-xr-x 3 root root    0 Nov  8 22:33 .
drwxr-xr-x 3 root root    0 Oct 29 20:48 ..
lrwxrwxrwx 1 root root    0 Oct 29 20:48 device -> ../../../thinkpad_hwmon
-r--r--r-- 1 root root 4096 Oct 29 20:48 fan1_input
-r--r--r-- 1 root root 4096 Oct 29 20:48 fan2_input
-r--r--r-- 1 root root 4096 Oct 29 20:48 name
drwxr-xr-x 2 root root    0 Oct 29 20:50 power
-rw-r--r-- 1 root root 4096 Oct  8 22:33 pwm1
-rw-r--r-- 1 root root 4096 Oct  8 20:40 pwm1_enable
-rw-r--r-- 1 root root 4096 Oct  8 22:33 pwm2
-rw-r--r-- 1 root root 4096 Oct  8 20:40 pwm2_enable
lrwxrwxrwx 1 root root    0 Oct 29 20:50 subsystem -> ../../../../../class/hwmon
-rw-r--r-- 1 root root 4096 Oct 29 20:48 uevent

fancontrol now has support for (>1)-fan configurations, so I have to use it.
(Also I have to rebuild thinkpad_acpi kernel module every time I upgrade kernel)
The patch: https://pastebin.com/eVPcnvfK
History: https://sourceforge.net/p/ibm-acpi/mailman/message/35005000/
my patched thinkpad_acpi.c https://gist.github.com/voidworker/12294117db5eb0ce663159a96e965093

TIP: If you are dummy like me, you can use tools like meld to compare vanilla and patched files and merge changes into vanilla version. But not all of them! There are some minor changes in vanilla since this patch was created.

@bssb
Copy link

bssb commented Nov 9, 2019

@voidworker Wow thank you very much for this! I'll take a look and see if I can get it working with the P53.

@ghost
Copy link

ghost commented Dec 1, 2019

I merged the patch posted by @voidworker and reinstalled the thinkpad_acpi module.
The left fan (which was controlled by thinkfan) is now following the BIOS curve while the right one (which was previously unavailable) can now be set.
The problem is that sensors still only lists fan1 which is now the right fan. The left one is now hidden and cannot be controlled anymore.

sensors:

thinkpad-isa-0000
Adapter: ISA adapter
fan1:           0 RPM <-- the left fan was spinning when this measurement was taken

ls -la /sys/devices/platform/thinkpad_hwmon/hwmon/hwmon6:

lrwxrwxrwx     0 root  1 Dez  1:30  device -> ../../../thinkpad_hwmon
.r--r--r--  4.1k root  1 Dez  1:36  fan1_input
.r--r--r--  4.1k root  1 Dez  1:36  name
drwxr-xr-x     - root  1 Dez  1:36  power
.rw-r--r--  4.1k root  1 Dez  1:36  pwm1
.rw-r--r--  4.1k root  1 Dez  1:36  pwm1_enable
lrwxrwxrwx     0 root  1 Dez  1:36  subsystem -> ../../../../../class/hwmon
.r--r--r--  4.1k root  1 Dez  1:36  temp1_input
.r--r--r--  4.1k root  1 Dez  1:36  temp2_input
.r--r--r--  4.1k root  1 Dez  1:36  temp3_input
.r--r--r--  4.1k root  1 Dez  1:36  temp4_input
.r--r--r--  4.1k root  1 Dez  1:36  temp5_input
.r--r--r--  4.1k root  1 Dez  1:36  temp6_input
.r--r--r--  4.1k root  1 Dez  1:36  temp7_input
.r--r--r--  4.1k root  1 Dez  1:36  temp8_input
.r--r--r--  4.1k root  1 Dez  1:36  temp9_input
.r--r--r--  4.1k root  1 Dez  1:36  temp10_input
.r--r--r--  4.1k root  1 Dez  1:36  temp11_input
.r--r--r--  4.1k root  1 Dez  1:36  temp12_input
.r--r--r--  4.1k root  1 Dez  1:36  temp13_input
.r--r--r--  4.1k root  1 Dez  1:36  temp14_input
.r--r--r--  4.1k root  1 Dez  1:36  temp15_input
.r--r--r--  4.1k root  1 Dez  1:36  temp16_input
.rw-r--r--  4.1k root  1 Dez  1:36  uevent

I will try to understand the code which has been modified but if anyone manages to find a solution, please share.

I'm using this on an X1 Extreme Gen 2 by the way.

@voidworker
Copy link

I am sorry for my lack of expertise. Maybe it's worth asking the author of the patch?
By the way, I have correct detection on my P50:

thinkpad-isa-0000
Adapter: ISA adapter
fan1:        1940 RPM
fan2:        2207 RPM

@tobomobo
Copy link

tobomobo commented Dec 7, 2019

Hello guys. I am am a noob so please excuse me if this makes no sense.

Pop! OS supports Dual Fan Control on my Thinkpad P1 Gen 2 (X1 Extreme) but I want to use Manjaro KDE. Is it possible to extract the fan control from them?

Thanks in advance :)

@bssb
Copy link

bssb commented Dec 8, 2019

@tobomobo If I were you I would stick with what's already working. Just install KDE on your PopOS.

@tobomobo
Copy link

tobomobo commented Dec 8, 2019

@tobomobo If I were you I would stick with what's already working. Just install KDE on your PopOS.

I would love to stay on an Arch based Distro because of the AUR packages .

But thanks for the quick reply 😊

@bssb
Copy link

bssb commented Dec 8, 2019

AUR is nice and convenient but it's not worth giving up the functionality of one of your fans...

@tobomobo
Copy link

tobomobo commented Dec 8, 2019 via email

@civic9
Copy link

civic9 commented Jan 5, 2020

@voidworker Thanks for your info. After minor modifications it works for me on Arch, kernel 5.4.7, Thinkpad X1 Extreme 1st gen. If anyone is interested: https://github.com/civic9/thinkpad_acpi.2ndfan.patch

I use it with two instances of thinkfan, as @vmatare suggested. Everything works fine. Finally X1 extreme has become usable for me.

@ghost
Copy link

ghost commented Jan 5, 2020

@civic9 Thank you for this! I was able to read both fans by changing the BIOS string in the fan_quirk_table from N2E to N2O.

Could you share your thinkfan config file? I am having some issues setting the correct speed. Also, how are you running two instances automatically? Did you modify the systemd service files?

@civic9
Copy link

civic9 commented Jan 5, 2020

@niciuffo
x1 extreme speed values: 0-31 (off), 32-63 - level 1, 64-95 - level 2, 96-127 - level 3, 128-159 - level 4, 160-191 - level 5, 192 - 255 - level 6 (max). my thinkpad.conf:

hwmon /sys/class/hwmon/hwmon6/temp1_input
pwm_fan /sys/class/hwmon/hwmon5/pwm1

(0,     0,      67)
(32,    65,     75)
(64,    73,     80)
(96,    78,     85)
(128,   83,     90)
(160,   88,     95)
(255,   93,     32767)

For 2nd thinkfan instance I created /etc/thinkfan2.conf (as above, but pwm2 in pwm_fan path) and /etc/systemd/system/thinkfan2.service:

[Unit]
Description=simple and lightweight fan control program - 2nd fan
Wants=lm_sensors.service
After=lm_sensors.service

[Service]
Type=forking
ExecStart=/usr/bin/thinkfan -b0 -c /etc/thinkfan2.conf -D
ExecReload=pkill -HUP thinkfan

[Install]
WantedBy=multi-user.target
Also=thinkfan-wakeup.service

In logs it shows a warning/error about existing pid file, but works fine.

@sassmann
Copy link
Author

@civic9 Thank you for this! I was able to read both fans by changing the BIOS string in the fan_quirk_table from N2E to N2O.

@niciuffo Where exactly did you make that change?

@ghost
Copy link

ghost commented Feb 4, 2020

@sassmann sorry forgot to reply, did you manage to fix this? You shouldn't have to change anything as the the string has been added on commit 2294baf.

@sassmann
Copy link
Author

sassmann commented Feb 5, 2020

Ah, my bad. The patch isn't upstream yet.

@tobomobo
Copy link

Hello there. Noob alert.

Is someone willing to explain step by step how to do this? (Using a P1 Gen2)

Thanks in advance! :)

@lhofhansl
Copy link

lhofhansl commented Mar 28, 2020

Hey all. I looked at the Kernel code and found a better solution. Instead of creating two fan control devices I just have the one device set both fan controls. That way a single thinkfan instance it sufficient. And you rarely want different levels for the fans anyway. (and the code is simpler).

Tried on my x1 extreme gen2, and it works beautifully.

Here's the patch:

diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index da794dcfdd92..282b97f39074 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -8326,6 +8326,11 @@ static int fan_set_level(int level)
 	switch (fan_control_access_mode) {
 	case TPACPI_FAN_WR_ACPI_SFAN:
 		if (level >= 0 && level <= 7) {
+			fan_select_fan2();
+			if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
+				return -EIO;
+
+			fan_select_fan1();
 			if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
 				return -EIO;
 		} else
@@ -8346,10 +8351,18 @@ static int fan_set_level(int level)
 		else if (level & TP_EC_FAN_AUTO)
 			level |= 4;	/* safety min speed 4 */
 
+		fan_select_fan2();
 		if (!acpi_ec_write(fan_status_offset, level))
 			return -EIO;
 		else
 			tp_features.fan_ctrl_status_undef = 0;
+
+		fan_select_fan1();
+		if (!acpi_ec_write(fan_status_offset, level))
+			return -EIO;
+		else
+			tp_features.fan_ctrl_status_undef = 0;
+
 		break;
 
 	default:
@@ -8772,6 +8785,7 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
 	TPACPI_QEC_IBM('7', '0', TPACPI_FAN_Q1),
 	TPACPI_QEC_LNV('7', 'M', TPACPI_FAN_2FAN),
 	TPACPI_Q_LNV('N', '1', TPACPI_FAN_2FAN),
+	TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2FAN),	/* X1 Extreme (2nd gen) */
 };
 
 static int __init fan_init(struct ibm_init_struct *iibm)
@@ -8813,8 +8827,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 				fan_quirk1_setup();
 			if (quirks & TPACPI_FAN_2FAN) {
 				tp_features.second_fan = 1;
-				dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
-					"secondary fan support enabled\n");
+				pr_info("secondary fan support enabled\n");
 			}
 		} else {
 			pr_err("ThinkPad ACPI EC access misbehaving, fan status and control unavailable\n");

@tobomobo
Copy link

Hey all. I looked at the Kernel code and found a better solution. Instead of creating two fan control devices I just have the one device set both fan controls. That way a single thinkfan instance it sufficient. And you rarely want different levels for the fans anyway. (and the code is simpler).

Tried on my x1 extreme gen2, and it works beautifully.

Here's the patch:

diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index da794dcfdd92..282b97f39074 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -8326,6 +8326,11 @@ static int fan_set_level(int level)
 	switch (fan_control_access_mode) {
 	case TPACPI_FAN_WR_ACPI_SFAN:
 		if (level >= 0 && level <= 7) {
+			fan_select_fan2();
+			if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
+				return -EIO;
+
+			fan_select_fan1();
 			if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
 				return -EIO;
 		} else
@@ -8346,10 +8351,18 @@ static int fan_set_level(int level)
 		else if (level & TP_EC_FAN_AUTO)
 			level |= 4;	/* safety min speed 4 */
 
+		fan_select_fan2();
 		if (!acpi_ec_write(fan_status_offset, level))
 			return -EIO;
 		else
 			tp_features.fan_ctrl_status_undef = 0;
+
+		fan_select_fan1();
+		if (!acpi_ec_write(fan_status_offset, level))
+			return -EIO;
+		else
+			tp_features.fan_ctrl_status_undef = 0;
+
 		break;
 
 	default:
@@ -8772,6 +8785,7 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
 	TPACPI_QEC_IBM('7', '0', TPACPI_FAN_Q1),
 	TPACPI_QEC_LNV('7', 'M', TPACPI_FAN_2FAN),
 	TPACPI_Q_LNV('N', '1', TPACPI_FAN_2FAN),
+	TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2FAN),	/* X1 Extreme (2nd gen) */
 };
 
 static int __init fan_init(struct ibm_init_struct *iibm)
@@ -8813,8 +8827,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 				fan_quirk1_setup();
 			if (quirks & TPACPI_FAN_2FAN) {
 				tp_features.second_fan = 1;
-				dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
-					"secondary fan support enabled\n");
+				pr_info("secondary fan support enabled\n");
 			}
 		} else {
 			pr_err("ThinkPad ACPI EC access misbehaving, fan status and control unavailable\n");

Hey thanks for improving the solution but unfortunately I am still stuck.

Could you explain to me how to apply this patch or link me to the right tutorial?

Help is greatly appreciated! 😊

@lhofhansl
Copy link

You have to rebuild the thinkpad_acpi kernel module. With my change that's all you need. Thinkfan will see a single fan, any changes will apply ton both fans.

I'll add detailed instructions later. @civic9 has a patch script linked above, I got the BIOS quirks from there. Thanks @civic9 !

For the actual change I looked into tp-thinkfan (for Windows) and just added the right parts to the patch.

@lhofhansl
Copy link

Update patch:

diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index da794dcfdd92..bd24642ba0f6 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -8320,13 +8320,18 @@ static int fan2_get_speed(unsigned int *speed)
 
 static int fan_set_level(int level)
 {
+	bool result1, result2;
+
 	if (!fan_control_allowed)
 		return -EPERM;
 
 	switch (fan_control_access_mode) {
 	case TPACPI_FAN_WR_ACPI_SFAN:
 		if (level >= 0 && level <= 7) {
-			if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
+			result2 = fan_select_fan2() && acpi_evalf(sfan_handle, NULL, NULL, "vd", level);
+			result1 = fan_select_fan1() && acpi_evalf(sfan_handle, NULL, NULL, "vd", level);
+
+			if (!result1 || !result2)
 				return -EIO;
 		} else
 			return -EINVAL;
@@ -8346,7 +8351,10 @@ static int fan_set_level(int level)
 		else if (level & TP_EC_FAN_AUTO)
 			level |= 4;	/* safety min speed 4 */
 
-		if (!acpi_ec_write(fan_status_offset, level))
+		result2 = fan_select_fan2() && acpi_ec_write(fan_status_offset, level);
+		result1 = fan_select_fan1() && acpi_ec_write(fan_status_offset, level);
+
+		if (!result1 || !result2)
 			return -EIO;
 		else
 			tp_features.fan_ctrl_status_undef = 0;
@@ -8772,6 +8780,14 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
 	TPACPI_QEC_IBM('7', '0', TPACPI_FAN_Q1),
 	TPACPI_QEC_LNV('7', 'M', TPACPI_FAN_2FAN),
 	TPACPI_Q_LNV('N', '1', TPACPI_FAN_2FAN),
+	TPACPI_Q_LNV3('N', '1', 'D', TPACPI_FAN_2FAN),	/* P70 */
+	TPACPI_Q_LNV3('N', '1', 'T', TPACPI_FAN_2FAN),	/* P71 */
+	TPACPI_Q_LNV3('N', '2', 'C', TPACPI_FAN_2FAN),	/* P72 */
+	TPACPI_Q_LNV3('N', '1', 'E', TPACPI_FAN_2FAN),	/* P50 */
+	TPACPI_Q_LNV3('N', '1', 'U', TPACPI_FAN_2FAN),	/* P51 */
+	TPACPI_Q_LNV3('N', '2', 'C', TPACPI_FAN_2FAN),	/* P52 */
+	TPACPI_Q_LNV3('N', '2', 'E', TPACPI_FAN_2FAN),	/* X1 Extreme (1st gen) */
+	TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2FAN),	/* X1 Extreme (2nd gen) */
 };
 
 static int __init fan_init(struct ibm_init_struct *iibm)
@@ -8813,8 +8829,7 @@ static int __init fan_init(struct ibm_init_struct *iibm)
 				fan_quirk1_setup();
 			if (quirks & TPACPI_FAN_2FAN) {
 				tp_features.second_fan = 1;
-				dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
-					"secondary fan support enabled\n");
+				pr_info("secondary fan support enabled\n");
 			}
 		} else {
 			pr_err("ThinkPad ACPI EC access misbehaving, fan status and control unavailable\n");

Added all the known bios version (again thanks @civic9 ), and made the error handling slightly more robust.

For instructions... It's really best to look at @civic9 's build script: https://github.com/civic9/thinkpad_acpi.2ndfan.patch/blob/master/build_install.sh

All I would do here is to write out the very same instructions.
You can do all these commands manually.

Cut the patch above into some file and patch it into the kernel source (as shown the script).

@tobomobo
Copy link

tobomobo commented Mar 29, 2020

Thanks for you help.

I am new to this. So sorry if this is a head bump question haha.

My problem is, when I start the scrip and the kernel gets pulled the terminal asks me different things. The first one is, if I want to "Compile also drivers which will not load" and many others. Do I just close out now or do I have to press yes to some things in terminal?

EDIT:
after manually entering the commands from the script I get these two errors:

cp: cannot stat '/usr/lib/modules/5.5.13-1-MANJARO/build/.config': No such file or directory

cp: cannot stat '/usr/lib/modules/5.5.13-1-MANJARO/build/Module.symvers': No such file or directory

@lhofhansl
Copy link

lhofhansl commented Mar 29, 2020

No problem at all!

For all the questions... It's the first time you do make oldconfig just take all the defaults, it doesn't matter for this module.

Manjaro is based off Arch, so in theory it should mostly work the same.
(I have Fedora and building the kernel and installing kernel modules is almost the same).

I assume that happens when you do depmod -a...?
Can you tell me which directory is missing in the path (/usr/lib/modules/5.5.13-1-MANJARO/build/.config)?
What's the output of $ ls /usr/lib/modules/ ?

You might need install a package to have that. On Fedora is kernel-core, but I do not know how it work on Arch/Manjaro.

rainwoodman pushed a commit to rainwoodman/scarlett-gen2 that referenced this issue Jul 30, 2020
This adds dual fan control for the following models:
P50, P51, P52, P70, P71, P72, P1 gen1, P2 gen2, X1E gen1 and X1E gen2.

Both fans are controlled together as if they were a single fan.

Tested on an X1 Extreme Gen1, an X1 Extreme Gen2, and a P50.

The patch is defensive, it adds only specific supported machines, and falls
back to the old behavior if both fans cannot be controlled.

Background:
I tested the BIOS default behavior on my X1E gen2 and both fans are always
changed together. So rather than adding controls for each fan, this controls
both fans together as the BIOS would do.

This was inspired by a discussion on dual fan support for the thinkfan tool
(see link below). All BIOS IDs are taken from there. The X1E gen2 ID is
verified on my machine.

Thanks to GitHub users voidworker and civic9 for the earlier patches and
BIOS IDs, and to users peter-stoll and sassman for testing the patch on
their machines.

BugLink: vmatare/thinkfan#58
Signed-off-by: Lars Hofhansl <[email protected]>
[andy: massaged commit message to capitalize ID and convert to BugLink]
Signed-off-by: Andy Shevchenko <[email protected]>
rainwoodman pushed a commit to rainwoodman/scarlett-gen2 that referenced this issue Jul 31, 2020
This adds dual fan control for the following models:
P50, P51, P52, P70, P71, P72, P1 gen1, P2 gen2, X1E gen1 and X1E gen2.

Both fans are controlled together as if they were a single fan.

Tested on an X1 Extreme Gen1, an X1 Extreme Gen2, and a P50.

The patch is defensive, it adds only specific supported machines, and falls
back to the old behavior if both fans cannot be controlled.

Background:
I tested the BIOS default behavior on my X1E gen2 and both fans are always
changed together. So rather than adding controls for each fan, this controls
both fans together as the BIOS would do.

This was inspired by a discussion on dual fan support for the thinkfan tool
(see link below). All BIOS IDs are taken from there. The X1E gen2 ID is
verified on my machine.

Thanks to GitHub users voidworker and civic9 for the earlier patches and
BIOS IDs, and to users peter-stoll and sassman for testing the patch on
their machines.

BugLink: vmatare/thinkfan#58
Signed-off-by: Lars Hofhansl <[email protected]>
[andy: massaged commit message to capitalize ID and convert to BugLink]
Signed-off-by: Andy Shevchenko <[email protected]>
@akorn
Copy link

akorn commented Aug 18, 2020

FWIW, this patch is already in linux-5.8.1.

@andreaswarnaar
Copy link

I just wanted to mention that the patch 14232c6e788c platform/x86: thinkpad_acpi: Add support for dual fan control only adds support for the P52/P72/X1 extreme/x1 extreme gen2. I had to build the module patched with explicit support for the P50. I don't know if the author is watching this issue, but it would be extremely nice if this worked out of the box on the P50/P70/P51/P71 as well. It seems a bit of an odd omission given that other patches here have the code for adding support for those machines. My patch is as follows (Ubuntu 20.04, kernel 5.4.0-37):

+++ ../linux-source-5.4.0/drivers/platform/x86/thinkpad_acpi.c	2020-06-26 01:31:54.721961000 +0100
@@ -8325,11 +8325,19 @@
 
 	switch (fan_control_access_mode) {
 	case TPACPI_FAN_WR_ACPI_SFAN:
-		if (level >= 0 && level <= 7) {
-			if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
-				return -EIO;
-		} else
+		if (((level < 0) || (level > 7)))
 			return -EINVAL;
+		if (tp_features.second_fan) {
+            if (!fan_select_fan2() ||
+                !acpi_evalf(sfan_handle, NULL, NULL, "vd", level)) {
+                fan_select_fan1();
+                pr_warn("Couldn't set 2nd fan level, disabling support\n");
+                tp_features.second_fan = 0;
+            }
+            fan_select_fan1();
+        }
+        if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level))
+            return -EIO;
 		break;
 
 	case TPACPI_FAN_WR_ACPI_FANS:
@@ -8346,6 +8354,16 @@
 		else if (level & TP_EC_FAN_AUTO)
 			level |= 4;	/* safety min speed 4 */
 
+		if (tp_features.second_fan) {
+            if (!fan_select_fan2() ||
+                !acpi_ec_write(fan_status_offset, level)) {
+                fan_select_fan1();
+                pr_warn("Couldn't set 2nd fan level, disabling support\n");
+                tp_features.second_fan = 0;
+            }
+            fan_select_fan1();
+
+        }
 		if (!acpi_ec_write(fan_status_offset, level))
 			return -EIO;
 		else
@@ -8772,6 +8790,13 @@
 	TPACPI_QEC_IBM('7', '0', TPACPI_FAN_Q1),
 	TPACPI_QEC_LNV('7', 'M', TPACPI_FAN_2FAN),
 	TPACPI_Q_LNV('N', '1', TPACPI_FAN_2FAN),
+	TPACPI_Q_LNV3('N', '1', 'D', TPACPI_FAN_2FAN),	/* P70 */
+	TPACPI_Q_LNV3('N', '1', 'T', TPACPI_FAN_2FAN),	/* P71 */
+	TPACPI_Q_LNV3('N', '1', 'E', TPACPI_FAN_2FAN),	/* P50 */
+	TPACPI_Q_LNV3('N', '1', 'U', TPACPI_FAN_2FAN),	/* P51 */
+	TPACPI_Q_LNV3('N', '2', 'C', TPACPI_FAN_2FAN),    /* P52 / P72 */
+    TPACPI_Q_LNV3('N', '2', 'E', TPACPI_FAN_2FAN),    /* X1 Extreme (1st gen) */
+    TPACPI_Q_LNV3('N', '2', 'O', TPACPI_FAN_2FAN),    /* X1 Extreme (2nd gen) */
 };
 
 static int __init fan_init(struct ibm_init_struct *iibm)
@@ -8813,8 +8838,7 @@
 				fan_quirk1_setup();
 			if (quirks & TPACPI_FAN_2FAN) {
 				tp_features.second_fan = 1;
-				dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_FAN,
-					"secondary fan support enabled\n");
+				pr_info("secondary fan support enabled\n");
 			}
 		} else {
 			pr_err("ThinkPad ACPI EC access misbehaving, fan status and control unavailable\n");

Could you help me with to apply this patch on ubuntu 20.20 kernel ?

@lhofhansl
Copy link

@andreaswarnaar Please see the comments above. The comment you cite referred to an old version of the patch.
The patch included in the Kernel does support the P50.

@mudrii
Copy link

mudrii commented Nov 28, 2020

Any dual-fan support for p53?

@civic9
Copy link

civic9 commented Jan 9, 2021

@mudrii You can patch kernel for p53 on your own - civic9/thinkpad_acpi.2ndfan.patch#8 (comment)

@medwatt
Copy link

medwatt commented Jan 26, 2021

Does anyone know if it's possible to prevent spikes from activating a particular level? For example, I currently have my fan set to turn on at 55C. Sometimes, the CPU will be at 40C, then spikes to 60C when I launch a program or open a website, then drops back to 42 or so. This causes the fan to turn on. Is there a way to avoid such things?

@civic9
Copy link

civic9 commented Jan 26, 2021

@medwatt look at the -b BIAS argument to thinkfan. negative value should help.
Or/and you can also try disabling turbo (echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo) - it is not always needed, but generates a lot of heat I think.

@medwatt
Copy link

medwatt commented Jan 27, 2021

@medwatt look at the -b BIAS argument to thinkfan. negative value should help.
Or/and you can also try disabling turbo (echo 0 > /sys/devices/system/cpu/intel_pstate/no_turbo) - it is not always needed, but generates a lot of heat I think.

I just ran cat /sys/devices/system/cpu/intel_pstate/no_turbo and got back 0. I had no idea turbo boost was disabled. Any idea why this is the case ? My power profile is set to balanced.

@civic9
Copy link

civic9 commented Jan 28, 2021

I just ran cat /sys/devices/system/cpu/intel_pstate/no_turbo and got back 0. I had no idea turbo boost was disabled. Any idea why this is the case ? My power profile is set to balanced.

Ops... my fault... 0 means turbo boost is enabled. 1 means disabled.

@koutheir
Copy link
Contributor

The Thinkpad P15 Gen 1 also has two fans. It would be wonderful to have this feature integrated into thinkfan, even if the control is the same for both fans. Controlling only one fan does not make sense, especially in a laptop.

$ sensors
...
thinkpad-isa-0000
Adapter: ISA adapter
fan1:        3217 RPM
fan2:        3769 RPM
...

@vmatare
Copy link
Owner

vmatare commented Sep 11, 2021

@koutheir You may be in luck. Controlling multiple fans is in fact already implemented, there's just no formal documentation yet. Take a look at this example config. It's what I use on my desktop system.

@cgirerd
Copy link

cgirerd commented Sep 21, 2021

@koutheir You may be in luck. Controlling multiple fans is in fact already implemented, there's just no formal documentation yet. Take a look at this example config. It's what I use on my desktop system.

Excellent, thanks for all the work! Could you detail from which version of thinkfan dual / multiple fan control has been implemented? Not sure if I should compile the current sources or if there are deb files already available somwhere with this feature.

@koutheir
Copy link
Contributor

@cgirerd, for info, I built using master sources, and I'm using it daily without issues. Thank you @vmatare for this nice piece of software!

If this could be useful to anybody, I published my /etc/thinkfan.conf for my Lenovo ThinkPad P15 Gen 1 in the ArchLinux wiki.

@cgirerd
Copy link

cgirerd commented Sep 22, 2021

Thank you @koutheir for the details on the setup for your system and @vmatare for the software! I am facing an issue while trying to run it though, opening a new thread to not pollute this one :)

@jdchristensen
Copy link

I'm running Ubuntu's 5.13.0-27-generic kernel on an X1 Extreme Gen 4, and I only see one fan. The control for it only affects the right fan, not the left one. dmidecode | grep N1 shows nothing, but dmidecode | grep N4 shows

	Version: N40ET31W (1.13 )
	Version ID: N40HT30W

(That's a zero after the 4.) Can the patch be updated to handle this?

@jdchristensen
Copy link

Thanks to all of you who worked on developing this patch and getting it merged upstream! I'm using an X1 Extreme Gen 4, and support was added in the 5.16 kernel, which was recently released.

I'd like to throw in a vote for separate fan controls. When my machine has a light load, I think a single fan on level 1 should be enough to keep the temps steady, and that will be quieter than two fans on level 1.

@peter-stoll
Copy link

peter-stoll commented Jan 22, 2022

I think a single fan on level 1 should be enough to keep the temps steady, and that will be quieter than two fans on level 1.

The opposite is true, since with two fans, one can reduce their speed at level 1 with keeping the same cooling power. As the result, the total noise is significantly lower.

The physical background is that noise increases highly nonlinear with the velocity of air. When I remember right from my studies (30 years ago in fluid mechanics), it increases even with power 4.

For the same reason prefers very large, but slow fans in silent computers.

@jdchristensen
Copy link

@peter-stoll You missed my point: there is no level in between 0 and 1, so if one fan at level 1 is enough, that would be quieter than two fans at level 1. On my X1 Extreme Gen 4, level 1 is 2500 rpm, well above what is often needed when 0 rpm is not enough. Two fans at level 1 would be two fans both at around 2500 rpm...

@peter-stoll
Copy link

peter-stoll commented Jan 23, 2022

@jdchristensen , no, I understood that, but it might be I made it not clear or I have technically other assumptions. On my P1 gen 2, I can set the rpm for each level. I assume you can do as well. One can compare two options which have the same cooling power:

a) 1 Fan with with 2500 rpm, 1 Fan with 0 rpm

b) 2 Fans with reduced rpm, such that the cooling power is about the same. I'd guess that would be sqrt(1/2)*2500 ~ 1750 , so two fans with 1750 rpm.

I'd might be wrong with the exact number for the rpm in Option b), but in any case, b) will be much quiter then a), since the noise goes with power 4, but the cooling power with a much lower exponent than 4. (I'd had to check my old textbooks for the exact number).

In case that you computer can not adjust the rpms below 2500, than you proposal would indeed be an improvement, but I'd be surprised if that is not possible.

@peter-stoll
Copy link

btw, I use thinkfan to adjust the rpm. One can not set the rpms directly, but some percentage, but the result is the same.

@jdchristensen
Copy link

@peter-stoll For the thinkpad_acpi driver, only the top 3 bits of the pwm setting are used:

	/* scale down from 0-255 to 0-7 */
	newlevel = (s >> 5) & 0x07;

If you specify 0-32, you get level 0, which is off. If you specify 33, you get level 1, which is 2500 rpm. I would really love to have something in the 1000-1500 range, which would be almost silent, but it seems like the hardware doesn't support it.

@jdchristensen
Copy link

The rpm values are for my X1 Extreme Gen 4. In auto mode, it only ever uses levels 0 to 3, which give rpm values 0, 2500, 3000, 3400 (roughly). The fans can go up to 5200 rpm (level 7, regulated) or 7600 rpm (full-speed, unregulated), but I have not been able to create a workload that gets them above 3400. So we are limited to just a few fan speeds in practice. Rather than having those unneeded higher levels, a finer choice of slower speeds would be better.

@LukeFernandes
Copy link

LukeFernandes commented Jan 23, 2022 via email

@jdchristensen
Copy link

@LukeFernandes As I said in my previous message, the "finer" pwm controls from 0 to 255 are binned into 7 bins using the top three bits, so in the end they give you exactly the same speed options as the level 0 through level 7 options via /proc/acpi/ibm/fan.

@LukeFernandes
Copy link

@jdchristensen so it seems @peter-stoll is incorrect that percentages can be set.

In that case I also vote for separate fan controls. My P72 chassis gets warm even at light load and can be uncomfortable on the lap, but level 1 with both fans is overkill and can be a bit noisy. So I'd want to be able to set the right fan only to level 1.

@vmatare vmatare removed this from the 2.0 milestone Aug 9, 2022
@vmatare
Copy link
Owner

vmatare commented Aug 9, 2022

Removed this from the 2.0 milestone because most of the discussion is about the hardware support in the kernel module. Support for multiple fans has been implemented in thinkfan for a while now, but that of course requires driver support, which in this case (I think) doesn't exist, yet...

@jonashackt
Copy link

Any update on the Thinkpad hardware support in kernel module to support more fine-grained rpms like 1000rpm (which would be enough most cases for my P1 Gen 6)? Or any hint, where to look for? I also got to the conclusion like @jdchristensen that 2300rpm (level 1) is much to high...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement Idea for an improvement or a new feature
Projects
None yet
Development

No branches or pull requests