lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <201412232011.11914@pali>
Date:	Tue, 23 Dec 2014 20:11:11 +0100
From:	Pali Rohár <pali.rohar@...il.com>
To:	Guenter Roeck <linux@...ck-us.net>
Cc:	Arnd Bergmann <arnd@...db.de>,
	"Greg Kroah-Hartman" <gregkh@...uxfoundation.org>,
	linux-kernel@...r.kernel.org, Valdis.Kletnieks@...edu,
	Steven Honeyman <stevenhoneyman@...il.com>,
	Jean Delvare <jdelvare@...e.de>,
	Gabriele Mazzotta <gabriele.mzt@...il.com>,
	Jochen Eisinger <jochen@...guin-breeder.org>
Subject: Re: [PATCH v4] i8k: Autodetect maximal fan speed and fan RPM multiplier

On Tuesday 23 December 2014 14:52:10 Guenter Roeck wrote:
> On Mon, Dec 22, 2014 at 04:07:34PM +0100, Pali Rohár wrote:
> > On Sunday 21 December 2014 20:51:14 Guenter Roeck wrote:
> > > On 12/21/2014 09:23 AM, Pali Rohár wrote:
> > > > This patch adds new function i8k_get_fan_nominal_speed()
> > > > for doing SMM call which will return nominal fan RPM
> > > > for specified fan speed. It returns nominal RPM value
> > > > at which fan operate when speed (0, 1, 2, 3) is set. It
> > > > looks like RPM value is not accurate, but still
> > > > provides very useful information.
> > > > 
> > > > First it can be used to validate if certain fan speed
> > > > could be accepted by SMM for setting fan speed and we
> > > > can use this routine to detect maximal fan speed.
> > > > 
> > > > Second it returns RPM value, so we can check if value
> > > > looks correct with multiplier 30 or multiplier 1 (until
> > > > now only these two multiplier were used). If RPM value
> > > > with multiplier 30 is too high, then multiplier 1 is
> > > > used.
> > > > 
> > > > In case when SMM reports that new function is not
> > > > supported we will fallback to old hardcoded values.
> > > > Maximal fan speed would be 2 and RPM multiplier 30.
> > > > 
> > > > Signed-off-by: Pali Rohár <pali.rohar@...il.com>
> > > > Tested-by: Pali Rohár <pali.rohar@...il.com>
> > > 
> > > Auto-detection of both multiplier and maximum speed tested
> > > working on M140 (after removing its configuration entry).
> > > 
> > > On Studio 1555, multiplier auto-detection works, but
> > > fan_max auto-detection fails. A speed value of '3' is
> > > accepted, but it does not set the fan speed to its
> > > maximum. Also, after setting the speed value to '3',
> > > reading it back returns to old value. No idea what it
> > > does or is expected to do. Reading the nominal speed does
> > > return a valid value.
> > > 
> > > Given that, I think we should not try to auto-detect
> > > fan_max, but keep the current code (meaning either use 2
> > > or 3 depending on the configuration data, with 2 as
> > > default if nothing else is known).
> > > 
> > > Thanks,
> > > Guenter
> > 
> > Ok. In this case I will remove max fan speed detection code
> > and we will use config data for those some machines which
> > support TURBO speed. If multiplier detection on Studio is
> > working fine, I can send another patch which remove config
> > data for Studio (because default multiplier is 2).
> > 
> > Can you check which nominal value Studio returns for speed
> > 3? Maybe it is some special?
> 
> It was a bit higher than the value returned for speed 2.
> Nothing special as far as I could see, only that setting a
> value of 3 did not modify the fan speed.
> 

Ok. I removed detection of maximal fan speed. Patch is below.

> Note that I won't be able to test further in the next two
> weeks; I am about 6,000 miles away from my Dell laptops right
> now.
> 
> Guenter

Ok. When you will be back you can test new version:

diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index d6e8a26..f0e21a0 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -6,6 +6,7 @@
  * Hwmon integration:
  * Copyright (C) 2011  Jean Delvare <jdelvare@...e.de>
  * Copyright (C) 2013, 2014  Guenter Roeck <linux@...ck-us.net>
+ * Copyright (C) 2014  Pali Rohár <pali.rohar@...il.com>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -42,12 +43,14 @@
 #define I8K_SMM_SET_FAN		0x01a3
 #define I8K_SMM_GET_FAN		0x00a3
 #define I8K_SMM_GET_SPEED	0x02a3
+#define I8K_SMM_GET_NOM_SPEED	0x04a3
 #define I8K_SMM_GET_TEMP	0x10a3
 #define I8K_SMM_GET_TEMP_TYPE	0x11a3
 #define I8K_SMM_GET_DELL_SIG1	0xfea3
 #define I8K_SMM_GET_DELL_SIG2	0xffa3
 
 #define I8K_FAN_MULT		30
+#define I8K_FAN_MAX_RPM		30000
 #define I8K_MAX_TEMP		127
 
 #define I8K_FN_NONE		0x00
@@ -64,7 +67,7 @@ static DEFINE_MUTEX(i8k_mutex);
 static char bios_version[4];
 static struct device *i8k_hwmon_dev;
 static u32 i8k_hwmon_flags;
-static uint i8k_fan_mult;
+static uint i8k_fan_mult = I8K_FAN_MULT;
 static uint i8k_pwm_mult;
 static uint i8k_fan_max = I8K_FAN_HIGH;
 
@@ -95,13 +98,13 @@ static bool power_status;
 module_param(power_status, bool, 0600);
 MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
 
-static uint fan_mult = I8K_FAN_MULT;
+static uint fan_mult;
 module_param(fan_mult, uint, 0);
-MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with");
+MODULE_PARM_DESC(fan_mult, "Factor to multiply fan speed with (default: autodetect)");
 
-static uint fan_max = I8K_FAN_HIGH;
+static uint fan_max;
 module_param(fan_max, uint, 0);
-MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed");
+MODULE_PARM_DESC(fan_max, "Maximum configurable fan speed (default: autodetect)");
 
 static int i8k_open_fs(struct inode *inode, struct file *file);
 static long i8k_ioctl(struct file *, unsigned int, unsigned long);
@@ -276,6 +279,17 @@ static int i8k_get_fan_speed(int fan)
 }
 
 /*
+ * Read the fan nominal rpm for specific fan speed.
+ */
+static int i8k_get_fan_nominal_speed(int fan, int speed)
+{
+	struct smm_regs regs = { .eax = I8K_SMM_GET_NOM_SPEED, };
+
+	regs.ebx = (fan & 0xff) | (speed << 8);
+	return i8k_smm(&regs) ? : (regs.eax & 0xffff) * i8k_fan_mult;
+}
+
+/*
  * Set the fan speed (off, low, high). Returns the new fan status.
  */
 static int i8k_set_fan(int fan, int speed)
@@ -863,6 +877,7 @@ MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
 static int __init i8k_probe(void)
 {
 	const struct dmi_system_id *id;
+	int fan, ret;
 
 	/*
 	 * Get DMI information
@@ -891,19 +906,47 @@ static int __init i8k_probe(void)
 			return -ENODEV;
 	}
 
-	i8k_fan_mult = fan_mult;
-	i8k_fan_max = fan_max ? : I8K_FAN_HIGH;	/* Must not be 0 */
+	/*
+	 * Set fan multiplier and maximal fan speed from dmi config
+	 * Values specified in module parameters override values from dmi
+	 */
 	id = dmi_first_match(i8k_dmi_table);
 	if (id && id->driver_data) {
 		const struct i8k_config_data *conf = id->driver_data;
-
-		if (fan_mult == I8K_FAN_MULT && conf->fan_mult)
-			i8k_fan_mult = conf->fan_mult;
-		if (fan_max == I8K_FAN_HIGH && conf->fan_max)
-			i8k_fan_max = conf->fan_max;
+		if (!fan_mult && conf->fan_mult)
+			fan_mult = conf->fan_mult;
+		if (!fan_max && conf->fan_max)
+			fan_max = conf->fan_max;
 	}
+
+	i8k_fan_max = fan_max ? : I8K_FAN_HIGH;	/* Must not be 0 */
 	i8k_pwm_mult = DIV_ROUND_UP(255, i8k_fan_max);
 
+	if (!fan_mult) {
+		/*
+		 * Autodetect fan multiplier based on nominal rpm
+		 * If fan reports rpm value too high then set multiplier to 1
+		 *
+		 * Try also setting multiplier from current rpm, but this will
+		 * work only in case when fan is not turned off. It is better
+		 * then nothing for machines which does not support nominal rpm
+		 * SMM function.
+		 */
+		for (fan = 0; fan < 2; ++fan) {
+			ret = i8k_get_fan_nominal_speed(fan, i8k_fan_max);
+			if (ret < 0)
+				ret = i8k_get_fan_speed(fan);
+			if (ret < 0)
+				continue;
+			if (ret > I8K_FAN_MAX_RPM)
+				i8k_fan_mult = 1;
+			break;
+		}
+	} else {
+		/* Fan multiplier was specified in module param or in dmi */
+		i8k_fan_mult = fan_mult;
+	}
+
 	return 0;
 }
 

-- 
Pali Rohár
pali.rohar@...il.com

Download attachment "signature.asc " of type "application/pgp-signature" (199 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ