Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 85

kernel-2.6.18-238.el5.src.rpm

From: Matthew Garrett <mjg@redhat.com>
Date: Wed, 4 Mar 2009 11:36:49 +0000
Subject: [acpi] donot evaluate _PPC until _PSS has been evaluated
Message-id: 20090304113649.GA28600@srcf.ucam.org
O-Subject: [RHEL 5.4 PATCH] Do not evaluate _PPC until _PSS has been evaluated
Bugzilla: 469105
RH-Acked-by: Prarit Bhargava <prarit@redhat.com>

Some Thinkpads report a limited range of frequencies until the processor
init functions have been called. We therefore need to avoid calling the
_PPC method until the associated _PSS methods have been evaluated. This
prevents inappropriate limiting of the system CPU frequency.

Fixes 469105

diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 2f62eb2..473a5b7 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -61,10 +61,21 @@ static DEFINE_MUTEX(performance_mutex);
  * policy is adjusted accordingly.
  */
 
+/* ignore_ppc:
+ * -1 > cpufreq low level drivers not initialized > _PSS, etc. not called yet
+ *       ignore _PPC
+ *  0 > cpufreq low level drivers initialized > consider _PPC values
+ *  1 > ignore _PPC totally > forced by user through boot param
+ */
+static int ignore_ppc = -1;
+module_param(ignore_ppc, int, 0644);
+MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
+		 "limited by BIOS, this should help");
+
 #define PPC_REGISTERED   1
 #define PPC_IN_USE       2
 
-static int acpi_processor_ppc_status = 0;
+static int acpi_processor_ppc_status;
 
 static int acpi_processor_ppc_notifier(struct notifier_block *nb,
 				       unsigned long event, void *data)
@@ -73,6 +84,14 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb,
 	struct acpi_processor *pr;
 	unsigned int ppc = 0;
 
+	if (event == CPUFREQ_START && ignore_ppc < 0) {
+		ignore_ppc = 0;
+		return 0;
+	}
+	
+	if (ignore_ppc)
+		return 0;
+
 	mutex_lock(&performance_mutex);
 
 	if (event != CPUFREQ_INCOMPATIBLE)
@@ -131,7 +150,13 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
 
 int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
 {
-	int ret = acpi_processor_get_platform_limit(pr);
+	int ret;
+	
+	if (ignore_ppc)
+		return 0;
+
+	ret = acpi_processor_get_platform_limit(pr);
+
 	if (ret < 0)
 		return (ret);
 	else
@@ -322,10 +347,6 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
 	if (result)
 		return result;
 
-	result = acpi_processor_get_platform_limit(pr);
-	if (result)
-		return result;
-
 	return 0;
 }
 
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 3c90283..47442d4 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -736,6 +736,9 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
 		goto err_out;
 	}
 
+	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+				     CPUFREQ_START, policy);
+
 #ifdef CONFIG_SMP
 	for_each_cpu_mask(j, policy->cpus) {
 		if (cpu == j)
@@ -887,7 +890,6 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
 	}
 	cpufreq_cpu_data[cpu] = NULL;
 
-
 #ifdef CONFIG_SMP
 	/* if this isn't the CPU which is the parent of the kobj, we
 	 * only need to unlink, put and exit
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index bf9ccbf..92e06e5 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -96,6 +96,7 @@ struct cpufreq_policy {
 #define CPUFREQ_ADJUST		(0)
 #define CPUFREQ_INCOMPATIBLE	(1)
 #define CPUFREQ_NOTIFY		(2)
+#define CPUFREQ_START		(3)
 
 #define CPUFREQ_SHARED_TYPE_NONE (0) /* None */
 #define CPUFREQ_SHARED_TYPE_HW	 (1) /* HW does needed coordination */