Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp3707127ybc; Thu, 14 Nov 2019 13:25:54 -0800 (PST) X-Google-Smtp-Source: APXvYqwGf9ert4uAo29YVO8iCyiZm0Hosx2bBpT7PLHHYK3YcLSpmqSFPPJtGpo6od94WLViWrDz X-Received: by 2002:a05:6000:12c4:: with SMTP id l4mr10448370wrx.110.1573766753942; Thu, 14 Nov 2019 13:25:53 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1573766753; cv=none; d=google.com; s=arc-20160816; b=GjvaMhYlMl63A1DRjo5QScy3tD93m1Pa0h557m/F9uDpb/0WaI3RUjGAXWBBwSCG87 cwrY7NdRAuKjbqcNQbquDL10W5hD2vUifpx9zbpoP5P4HEdG5vfuMXXyPhoR+ujBnB+p 5sDgCrM/Ka90PZjqWH3QG9aXyJX80ELAjFF4McyZFh/OjwW9ZvRQsWo7vELzUGQdq25u DxaJYy0+gvP3NAjaOEe5v3jzMVDDgc31+M9qVxCVlMqqzRAyd8ecZpiBxIsHmxwS5XOl 3okVWw8XjJGTTONvz2VnI20j6pxiAL/oO12V5+2jv2K6T1Sge7vLIujO/XzBZBm4j1fn Ef6A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=C1Zqbutor/J6VzvxyHl95+q2SjZItvdtIJskimitUQQ=; b=eo/amkwqHrhut54J0ONs2HpYkLxwVmTwXzHeIcQC3T2pQ3gVkOTRmp4YT1WiXQnvIM 73/HMZhRknWHow8GIsVbnxWMVItddHPsNU6OlooxX71IgATpg1HdRGVGJRXOok4i4Ulc MCDhpmxY2Ilhec9qtU64VlwGUFr3aAzZfcuYKtsbrgSTA0bckIG+Ui+XS53mzJg8IJJR /MQ7gVEI++uINPseQmTl7BbO2GKrlJa0ZGzK84FhwEW6SWA7i4g9LHWiYCKU+DzC8Bld nDwiAzqm5u6fDp/J4xjhCKRJIhZ6qjUlT5D7cOCEvQWYGevmACuWCrWRZrmDBuluU0x3 oNLA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id h11si5596383ede.45.2019.11.14.13.25.27; Thu, 14 Nov 2019 13:25:53 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726952AbfKNVWM (ORCPT + 99 others); Thu, 14 Nov 2019 16:22:12 -0500 Received: from pietrobattiston.it ([92.243.7.39]:57368 "EHLO jauntuale.pietrobattiston.it" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726592AbfKNVWM (ORCPT ); Thu, 14 Nov 2019 16:22:12 -0500 X-Greylist: delayed 459 seconds by postgrey-1.27 at vger.kernel.org; Thu, 14 Nov 2019 16:22:09 EST Received: from amalgama (94.105.105.79.dyn.edpnet.net [94.105.105.79]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: giovanni) by jauntuale.pietrobattiston.it (Postfix) with ESMTPSA id DF12EE1E18; Thu, 14 Nov 2019 22:14:27 +0100 (CET) Received: by amalgama (Postfix, from userid 1000) id 7025C3C01EF; Thu, 14 Nov 2019 22:14:27 +0100 (CET) From: Giovanni Mascellani To: =?UTF-8?q?Pali=20Roh=C3=A1r?= , Jean Delvare , Guenter Roeck , linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Giovanni Mascellani Subject: [PATCH] hwmon: (dell-smm-hwmon) Disable BIOS fan control on SET_FAN Date: Thu, 14 Nov 2019 22:14:08 +0100 Message-Id: <20191114211408.22123-1-gio@debian.org> X-Mailer: git-send-email 2.24.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On some Dell laptops the BIOS directly controls fan speed, ignoring SET_FAN commands. Also, the BIOS controller often happens to be buggy, failing to increase fan speed when the CPU is under heavy load and setting fan at full speed even when the CPU is idle and relatively cool. Disable BIOS fan control on such laptops as soon as a SET_FAN command is issued, and re-enable it at module unloading, so that a userspace controller like i8kmon can take control of the fan. There is a missing feature: interaction with PM; I think that when suspending on RAM the fans should be stopped (this BIOS doesn't always do this automatically, neither when fan control is enabled nor when it is disabled); when recovering from hibernation to disk, also, the command to disable BIOS fan control should be issued again, because the computer will have had a power cycle in the meantime. I don't know how to implement these two actions; can someone suggest a way? Also, I would be happy to know from more experienced people if these actions are sensible. Signed-off-by: Giovanni Mascellani --- drivers/hwmon/dell-smm-hwmon.c | 64 ++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c index 4212d022d253..6d72e207076f 100644 --- a/drivers/hwmon/dell-smm-hwmon.c +++ b/drivers/hwmon/dell-smm-hwmon.c @@ -32,6 +32,12 @@ #include +/* + * The code for enabling and disabling BIOS fan control were found by + * trial and error with the program at + * https://github.com/clopez/dellfan. + */ + #define I8K_SMM_FN_STATUS 0x0025 #define I8K_SMM_POWER_STATUS 0x0069 #define I8K_SMM_SET_FAN 0x01a3 @@ -43,6 +49,8 @@ #define I8K_SMM_GET_TEMP_TYPE 0x11a3 #define I8K_SMM_GET_DELL_SIG1 0xfea3 #define I8K_SMM_GET_DELL_SIG2 0xffa3 +#define I8K_SMM_DISABLE_BIOS 0x30a3 +#define I8K_SMM_ENABLE_BIOS 0x31a3 #define I8K_FAN_MULT 30 #define I8K_FAN_MAX_RPM 30000 @@ -68,6 +76,8 @@ static uint i8k_pwm_mult; static uint i8k_fan_max = I8K_FAN_HIGH; static bool disallow_fan_type_call; static bool disallow_fan_support; +static bool disable_bios; +static bool bios_disabled; #define I8K_HWMON_HAVE_TEMP1 (1 << 0) #define I8K_HWMON_HAVE_TEMP2 (1 << 1) @@ -419,6 +429,26 @@ static int i8k_get_power_status(void) return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY; } +/* + * Disable BIOS fan control. + */ +static int i8k_disable_bios(void) +{ + struct smm_regs regs = { .eax = I8K_SMM_DISABLE_BIOS, .ebx = 0 }; + + return i8k_smm(®s) ? : regs.eax & 0xff; +} + +/* + * Enable BIOS fan control. + */ +static int i8k_enable_bios(void) +{ + struct smm_regs regs = { .eax = I8K_SMM_ENABLE_BIOS, .ebx = 0 }; + + return i8k_smm(®s) ? : regs.eax & 0xff; +} + /* * Procfs interface */ @@ -488,6 +518,13 @@ i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg) if (copy_from_user(&speed, argp + 1, sizeof(int))) return -EFAULT; + if (disable_bios && !bios_disabled) { + val = i8k_disable_bios(); + if (val < 0) + return val; + bios_disabled = true; + } + val = i8k_set_fan(val, speed); break; @@ -1135,6 +1172,22 @@ static struct dmi_system_id i8k_blacklist_fan_support_dmi_table[] __initdata = { { } }; +/* + * On some machines the BIOS disregards all SET_FAN commands unless it + * is explicitly disabled. + * See bug: https://bugzilla.kernel.org/show_bug.cgi?id=200949 + */ +static struct dmi_system_id i8k_disable_bios_dmi_table[] __initdata = { + { + .ident = "Dell Precision 5530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Precision 5530"), + }, + }, + { } +}; + /* * Probe for the presence of a supported laptop. */ @@ -1169,6 +1222,11 @@ static int __init i8k_probe(void) disallow_fan_type_call = true; } + if (dmi_check_system(i8k_disable_bios_dmi_table)) { + pr_warn("broken Dell BIOS detected, will disable BIOS fan control\n"); + disable_bios = true; + } + strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION), sizeof(bios_version)); strlcpy(bios_machineid, i8k_get_dmi_data(DMI_PRODUCT_SERIAL), @@ -1241,6 +1299,12 @@ static void __exit i8k_exit(void) { hwmon_device_unregister(i8k_hwmon_dev); i8k_exit_procfs(); + + if (bios_disabled) { + pr_warn("re-enabling BIOS fan control\n"); + if (i8k_enable_bios()) + pr_warn("could not re-enable BIOS fan control\n"); + } } module_init(i8k_init); -- 2.24.0