[RFC PATCH] powernow-k8: check for BIOS with p-state capability

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There are HP servers where the BIOS is capable of managing P-states 
inherently. On those systems the BIOS does not provide the relevant ACPI 
data (_PSS,_PCT etc.) to the OS. We don't want to print the following 
"firmware bug" error messages on those servers:

[Firmware Bug]: powernow-k8: No compatible ACPI _PSS objects found.
[Firmware Bug]: powernow-k8: Try again with latest BIOS.

I think in each of the following cases the call to 
acpi_processor_register_performance() will fail in the P-state driver: 

1) a buggy BIOS (that relinquishes control to the P-state driver, but has 
an error in the ACPI data)
2) a BIOS that doesn't intentionally expose relevant ACPI info because the 
HW is buggy
3) a BIOS that manages P-states inherently and doesn't want to provide 
the cpufreq-related ACPI data

There is no simple/clean way to distinguish between these cases.

Below is a whitelist that mentions those AMD-based HP x86 servers whose BIOS 
have the capability of managing P-states. But whitelists are ugly ...

Comments?
- naga -


--------------------
On systems where the BIOS is capable of managing P-states, no relevant ACPI 
info (_PCT,_PSS etc.) is provided to the driver/OS. Avoid printing the 
"firmware bug" error messages in those cases.

Signed-off-by: Naga Chumbalkar <nagananda.chumbalkar@xxxxxx>

---
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index a9df944..5712478 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -36,6 +36,7 @@
 #include <linux/sched.h>	/* for current / set_cpus_allowed() */
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/dmi.h>
 
 #include <asm/msr.h>
 
@@ -1239,12 +1240,88 @@ static void __cpuinit powernowk8_cpu_init_on_cpu(void *_init_on_cpu)
 	init_on_cpu->rc = 0;
 }
 
+/*
+ * Some BIOSes may not present P-state related ACPI information
+ * to the OS/driver.
+ */
+static int bios_with_pstate_cap;
+
+static int bios_capability_found(const struct dmi_system_id *d)
+{
+	bios_with_pstate_cap = 1;
+	printk(KERN_INFO PFX "driver did not load because %s BIOS"
+			" has built-in pstate transitioning"
+			" capability\n", d->ident);
+	return 0;
+}
+
+static const struct dmi_system_id bios_cap_dmi_table[] = {
+	{
+		.callback = bios_capability_found,
+		.ident = "HP ProLiant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL365"),
+		},
+	},
+	{
+		.callback = bios_capability_found,
+		.ident = "HP ProLiant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL385"),
+		},
+	},
+	{
+		.callback = bios_capability_found,
+		.ident = "HP ProLiant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL465c"),
+		},
+	},
+	{
+		.callback = bios_capability_found,
+		.ident = "HP ProLiant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL495c"),
+		},
+	},
+	{
+		.callback = bios_capability_found,
+		.ident = "HP ProLiant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585"),
+		},
+	},
+	{
+		.callback = bios_capability_found,
+		.ident = "HP ProLiant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL685c"),
+		},
+	},
+	{
+		.callback = bios_capability_found,
+		.ident = "HP ProLiant",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL785"),
+		},
+	},
+	{ }
+};
+
 /* per CPU init entry point to the driver */
 static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 {
 	static const char ACPI_PSS_BIOS_BUG_MSG[] =
 		KERN_ERR FW_BUG PFX "No compatible ACPI _PSS objects found.\n"
 		FW_BUG PFX "Try again with latest BIOS.\n";
+	static int done;
 	struct powernow_k8_data *data;
 	struct init_on_cpu init_on_cpu;
 	int rc;
@@ -1271,7 +1348,12 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 		 * an UP version, and is deprecated by AMD.
 		 */
 		if (num_online_cpus() != 1) {
-			printk_once(ACPI_PSS_BIOS_BUG_MSG);
+			if (!done) {
+				dmi_check_system(bios_cap_dmi_table);
+				done++;
+			}
+			if (!bios_with_pstate_cap)
+				printk_once(ACPI_PSS_BIOS_BUG_MSG);
 			goto err_out;
 		}
 		if (pol->cpu != 0) {
--
To unsubscribe from this list: send the line "unsubscribe cpufreq" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Devel]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Forum]     [Linux SCSI]

  Powered by Linux