public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2.5.55] cpufreq: frequency table helpers
@ 2003-01-10 10:05 Dominik Brodowski
  0 siblings, 0 replies; only message in thread
From: Dominik Brodowski @ 2003-01-10 10:05 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel, davej, cpufreq

This patch adds "frequency table helpers" to kernel/cpufreq.c and
updates some drivers to use them.

Most CPU frequency scaling methods only support a few static
frequencies. In these drivers a lot of duplicated code existed in the
->setpolicy and ->verify calls.

Please note that this in no way changes the behaviour of cpufreq or of
the ->setpolicy or ->verify calls. These "frequency table helpers"
aren't for drivers which either only support policies (longrun) or
really many frequency states (ARM, gx-suspmod).

       Dominik

 arch/i386/kernel/cpu/cpufreq/elanfreq.c    |   83 ++++++-------------
 arch/i386/kernel/cpu/cpufreq/p4-clockmod.c |   97 +++++++----------------
 arch/i386/kernel/cpu/cpufreq/powernow-k6.c |  122 ++++++++---------------------
 arch/i386/kernel/cpu/cpufreq/speedstep.c   |   57 +++++--------
 include/linux/cpufreq.h                    |   23 +++++
 kernel/cpufreq.c                           |  117 +++++++++++++++++++++++++++
6 files changed, 257 insertions(+), 242 deletions(-)

diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/elanfreq.c linux/arch/i386/kernel/cpu/cpufreq/elanfreq.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/elanfreq.c	2003-01-09 19:15:40.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/elanfreq.c	2003-01-10 10:15:57.000000000 +0100
@@ -61,6 +61,18 @@
 	{99000,	0x01,	0x05}
 };
 
+static struct cpufreq_frequency_table elanfreq_table[] = {
+	{0,	1000},
+	{1,	2000},
+	{2,	4000},
+	{3,	8000},
+	{4,	16000},
+	{5,	33000},
+	{6,	66000},
+	{7,	99000},
+	{0,	CPUFREQ_TABLE_END},
+};
+
 
 /**
  *	elanfreq_get_cpu_frequency: determine current cpu speed
@@ -172,63 +184,17 @@
 
 static int elanfreq_verify (struct cpufreq_policy *policy)
 {
-	unsigned int    number_states = 0;
-	unsigned int    i;
-
-	if (!policy || !max_freq)
-		return -EINVAL;
-
-	policy->cpu = 0;
-
-	cpufreq_verify_within_limits(policy, 1000, max_freq);
-
-	for (i=7; i>=0; i--)
-		if ((elan_multiplier[i].clock >= policy->min) &&
-		    (elan_multiplier[i].clock <= policy->max))
-			number_states++;
-
-	if (number_states)
-		return 0;
-
-	for (i=7; i>=0; i--)
-		if (elan_multiplier[i].clock < policy->max)
-			break;
-
-	policy->max = elan_multiplier[i+1].clock;
-
-	cpufreq_verify_within_limits(policy, 1000, max_freq);
-
-	return 0;
+	return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]);
 }
 
 static int elanfreq_setpolicy (struct cpufreq_policy *policy)
 {
-	unsigned int    i;
-	unsigned int    optimal = 8;
-
-	if (!elanfreq_driver)
-		return -EINVAL;
+	unsigned int    newstate = 0;
 
-	for (i=0; i<8; i++) {
-		if ((elan_multiplier[i].clock > policy->max) ||
-		    (elan_multiplier[i].clock < policy->min))
-			continue;
-		switch(policy->policy) {
-		case CPUFREQ_POLICY_POWERSAVE:
-			if (optimal == 8)
-				optimal = i;
-			break;
-		case CPUFREQ_POLICY_PERFORMANCE:
-			optimal = i;
-			break;
-		default:
-			return -EINVAL;
-		}
-	}
-	if ((optimal == 8) || (elan_multiplier[optimal].clock > max_freq))
+	if (cpufreq_frequency_table_setpolicy(policy, &elanfreq_table[0], &newstate))
 		return -EINVAL;
 
-	elanfreq_set_cpu_state(optimal);
+	elanfreq_set_cpu_state(newstate);
 
 	return 0;
 }
@@ -262,7 +228,7 @@
 {	
 	struct cpuinfo_x86 *c = cpu_data;
 	struct cpufreq_driver *driver;
-	int ret;
+	int ret, i;
 
 	/* Test if we have the right hardware */
 	if ((c->x86_vendor != X86_VENDOR_AMD) ||
@@ -282,6 +248,12 @@
 	if (!max_freq)
 		max_freq = elanfreq_get_cpu_frequency();
 
+	/* table init */
+ 	for (i=0; (elanfreq_table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		if (elanfreq_table[i].frequency > max_freq)
+			elanfreq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+	}
+
 #ifdef CONFIG_CPU_FREQ_24_API
 	driver->cpu_cur_freq[0] = elanfreq_get_cpu_frequency();
 #endif
@@ -290,11 +262,12 @@
 	driver->setpolicy     = &elanfreq_setpolicy;
 
 	driver->policy[0].cpu    = 0;
-	driver->policy[0].min    = 1000;
-	driver->policy[0].max    = max_freq;
+	ret = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &elanfreq_table[0]);
+	if (ret) {
+		kfree(driver);
+		return ret;
+	}
 	driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
-	driver->policy[0].cpuinfo.max_freq = max_freq;
-	driver->policy[0].cpuinfo.min_freq = 1000;
 	driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 
 	elanfreq_driver = driver;
diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c linux/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2003-01-09 19:15:40.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2003-01-10 09:56:09.000000000 +0100
@@ -141,39 +141,27 @@
 }
 
 
+static struct cpufreq_frequency_table p4clockmod_table[] = {
+	{DC_RESV, CPUFREQ_ENTRY_INVALID},
+	{DC_DFLT, 0},
+	{DC_25PT, 0},
+	{DC_38PT, 0},
+	{DC_50PT, 0},
+	{DC_64PT, 0},
+	{DC_75PT, 0},
+	{DC_88PT, 0},
+	{DC_DISABLE, 0},
+	{DC_RESV, CPUFREQ_TABLE_END},
+};
+
+
 static int cpufreq_p4_setpolicy(struct cpufreq_policy *policy)
 {
-	unsigned int    i;
-	unsigned int    newstate = 0;
-	unsigned int    number_states = 0;
-	unsigned int    minstate = 1;
+	unsigned int    newstate = DC_RESV;
 
-	if (!cpufreq_p4_driver || !stock_freq || 
-	    !policy || !cpu_online(policy->cpu))
+	if (cpufreq_frequency_table_setpolicy(policy, &p4clockmod_table[0], &newstate))
 		return -EINVAL;
 
-	if (has_N44_O17_errata)
-		minstate = 3;
-
-	if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
-	{
-		for (i=8; i>=minstate; i--)
-			if ((policy->min <= ((stock_freq / 8) * i)) &&
-			    (policy->max >= ((stock_freq / 8) * i))) 
-			{
-				newstate = i;
-				number_states++;
-			}
-	} else {
-		for (i=minstate; i<=8; i++)
-			if ((policy->min <= ((stock_freq / 8) * i)) &&
-			    (policy->max >= ((stock_freq / 8) * i))) 
-			{
-				newstate = i;
-				number_states++;
-			}
-	}
-
 	cpufreq_p4_setdc(policy->cpu, newstate);
 
 	return 0;
@@ -182,34 +170,7 @@
 
 static int cpufreq_p4_verify(struct cpufreq_policy *policy)
 {
-	unsigned int    number_states = 0;
-	unsigned int    i = 1;
-
-	if (!cpufreq_p4_driver || !stock_freq || 
-	    !policy || !cpu_online(policy->cpu))
-		return -EINVAL;
-
-	cpufreq_verify_within_limits(policy, 
-				     policy->cpuinfo.min_freq, 
-				     policy->cpuinfo.max_freq);
-
-	if (has_N44_O17_errata)
-		i = 3;
-
-	/* is there at least one state within the limit? */
-	for (; i<=8; i++)
-		if ((policy->min <= ((stock_freq / 8) * i)) &&
-		    (policy->max >= ((stock_freq / 8) * i)))
-			number_states++;
-
-	if (number_states)
-		return 0;
-
-	policy->max = (stock_freq / 8) * (((unsigned int) ((policy->max * 8) / stock_freq)) + 1);
-	cpufreq_verify_within_limits(policy, 
-				     policy->cpuinfo.min_freq, 
-				     policy->cpuinfo.max_freq);
-	return 0;
+	return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]);
 }
 
 
@@ -262,6 +223,15 @@
 
 	driver->policy = (struct cpufreq_policy *) (driver + 1);
 
+	/* table init */
+	for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		if ((i<2) && (has_N44_O17_errata))
+			p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+		else
+			p4clockmod_table[i].frequency = (stock_freq * i)/8;
+	}
+	
+
 #ifdef CONFIG_CPU_FREQ_24_API
 	for (i=0;i<NR_CPUS;i++) {
 		driver->cpu_cur_freq[i] = stock_freq;
@@ -272,17 +242,14 @@
 	driver->setpolicy     = &cpufreq_p4_setpolicy;
 
 	for (i=0;i<NR_CPUS;i++) {
-		if (has_N44_O17_errata)
-			driver->policy[i].min    = (stock_freq * 3) / 8;
-		else
-			driver->policy[i].min    = stock_freq / 8;
-		driver->policy[i].max    = stock_freq;
+		driver->policy[i].cpu    = i;
+		ret = cpufreq_frequency_table_cpuinfo(&driver->policy[i], &p4clockmod_table[0]);
+		if (ret) {
+			kfree(driver);
+			return ret;
+		}
 		driver->policy[i].policy = CPUFREQ_POLICY_PERFORMANCE;
-		driver->policy[i].cpuinfo.min_freq  = driver->policy[i].min;
-		driver->policy[i].cpuinfo.max_freq  = stock_freq;
 		driver->policy[i].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-
-		driver->policy[i].cpu    = i;
 	}
 
 	cpufreq_p4_driver = driver;
diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/powernow-k6.c linux/arch/i386/kernel/cpu/cpufreq/powernow-k6.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	2003-01-09 19:15:40.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	2003-01-10 10:08:05.000000000 +0100
@@ -31,15 +31,16 @@
 
 
 /* Clock ratio multiplied by 10 - see table 27 in AMD#23446 */
-static int clock_ratio[8] = {
-	45,  /* 000 -> 4.5x */
-	50,  /* 001 -> 5.0x */
-	40,  /* 010 -> 4.0x */
-	55,  /* 011 -> 5.5x */
-	20,  /* 100 -> 2.0x */
-	30,  /* 101 -> 3.0x */
-	60,  /* 110 -> 6.0x */
-	35   /* 111 -> 3.5x */
+static struct cpufreq_frequency_table clock_ratio[] = {
+	{45,  /* 000 -> 4.5x */ 0},
+	{50,  /* 001 -> 5.0x */ 0},
+	{40,  /* 010 -> 4.0x */ 0},
+	{55,  /* 011 -> 5.5x */ 0},
+	{20,  /* 100 -> 2.0x */ 0},
+	{30,  /* 101 -> 3.0x */ 0},
+	{60,  /* 110 -> 6.0x */ 0},
+	{35,  /* 111 -> 3.5x */ 0},
+	{0, CPUFREQ_TABLE_END}
 };
 
 
@@ -60,7 +61,7 @@
 	msrval = POWERNOW_IOPORT + 0x0;
 	wrmsr(MSR_K6_EPMR, msrval, 0); /* disable it again */
 
-	return clock_ratio[(invalue >> 5)&7];
+	return clock_ratio[(invalue >> 5)&7].index;
 }
 
 
@@ -82,7 +83,7 @@
 	}
 
 	freqs.old = busfreq * powernow_k6_get_cpu_multiplier();
-	freqs.new = busfreq * clock_ratio[best_i];
+	freqs.new = busfreq * clock_ratio[best_i].index;
 	freqs.cpu = 0; /* powernow-k6.c is UP only driver */
 	
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
@@ -115,39 +116,7 @@
  */
 static int powernow_k6_verify(struct cpufreq_policy *policy)
 {
-	unsigned int    number_states = 0;
-	unsigned int    i, j;
-
-	if (!policy || !busfreq)
-		return -EINVAL;
-
-	policy->cpu = 0;
-	cpufreq_verify_within_limits(policy, (20 * busfreq),
-				     (max_multiplier * busfreq));
-
-	for (i=0; i<8; i++)
-		if ((policy->min <= (busfreq * clock_ratio[i])) &&
-		    (policy->max >= (busfreq * clock_ratio[i])))
-			number_states++;
-
-	if (number_states)
-		return 0;
-
-	/* no state is available within range -- find next larger state */
-
-	j = 6;
-
-	for (i=0; i<8; i++)
-		if (((clock_ratio[i] * busfreq) >= policy->min) &&
-		    (clock_ratio[i] < clock_ratio[j]))
-			j = i;
-
-	policy->max = clock_ratio[j] * busfreq;
-
-	cpufreq_verify_within_limits(policy, (20 * busfreq),
-				     (max_multiplier * busfreq));
-
-	return 0;
+	return cpufreq_frequency_table_verify(policy, &clock_ratio[0]);
 }
 
 
@@ -159,43 +128,12 @@
  */
 static int powernow_k6_setpolicy (struct cpufreq_policy *policy)
 {
-	unsigned int    i;
-	unsigned int    optimal;
+	unsigned int    newstate = 0;
 
-	if (!powernow_driver || !policy || policy->cpu)
+	if (cpufreq_frequency_table_setpolicy(policy, &clock_ratio[0], &newstate))
 		return -EINVAL;
 
-	switch(policy->policy) {
-	case CPUFREQ_POLICY_POWERSAVE:
-		optimal = 6;
-		break;
-	case CPUFREQ_POLICY_PERFORMANCE:
-		optimal = max_multiplier;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	for (i=0;i<8;i++) {
-		unsigned int freq = busfreq * clock_ratio[i];
-		if (clock_ratio[i] > max_multiplier)
-			continue;
-		if ((freq > policy->max) ||
-		    (freq < policy->min))
-			continue;
-		switch(policy->policy) {
-		case CPUFREQ_POLICY_POWERSAVE:
-			if (freq < (clock_ratio[optimal] * busfreq))
-				optimal = i;
-			break;
-		case CPUFREQ_POLICY_PERFORMANCE:
-			if (freq > (clock_ratio[optimal] * busfreq))
-				optimal = i;
-			break;
-		}
-	}
-
-	powernow_k6_set_state(optimal);
+	powernow_k6_set_state(newstate);
 
 	return 0;
 }
@@ -213,6 +151,7 @@
 	struct cpuinfo_x86      *c = cpu_data;
 	struct cpufreq_driver   *driver;
 	unsigned int            result;
+	unsigned int            i;
 
 	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
 		((c->x86_model != 12) && (c->x86_model != 13)))
@@ -235,20 +174,29 @@
 	}
 	driver->policy = (struct cpufreq_policy *) (driver + 1);
 
-#ifdef CONFIG_CPU_FREQ_24_API
-	driver->cpu_cur_freq[0]  = busfreq * max_multiplier;
-#endif
+	/* table init */
+ 	for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
+		if (clock_ratio[i].index > max_multiplier)
+			clock_ratio[i].frequency = CPUFREQ_ENTRY_INVALID;
+		else
+			clock_ratio[i].frequency = busfreq * clock_ratio[i].index;
+	}
 
 	driver->verify        = &powernow_k6_verify;
 	driver->setpolicy     = &powernow_k6_setpolicy;
 
+	/* cpuinfo and default policy values */
 	driver->policy[0].cpu    = 0;
-	driver->policy[0].min    = busfreq * 20;
-	driver->policy[0].max    = busfreq * max_multiplier;
-	driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
-	driver->policy[0].cpuinfo.max_freq = busfreq * max_multiplier;
-	driver->policy[0].cpuinfo.min_freq = busfreq * 20;
 	driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
+#ifdef CONFIG_CPU_FREQ_24_API
+	driver->cpu_cur_freq[0]  = busfreq * max_multiplier;
+#endif
+	result = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &clock_ratio[0]);
+	if (result) {
+		kfree(driver);
+		return result;
+	}
 
 	powernow_driver = driver;
 
@@ -274,7 +222,7 @@
 
 	if (powernow_driver) {
 		for (i=0;i<8;i++)
-			if (clock_ratio[i] == max_multiplier)
+			if (clock_ratio[i].index == max_multiplier)
 				powernow_k6_set_state(i);		
 		cpufreq_unregister();
 		kfree(powernow_driver);
diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/speedstep.c linux/arch/i386/kernel/cpu/cpufreq/speedstep.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/speedstep.c	2003-01-09 19:32:00.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/speedstep.c	2003-01-10 10:04:22.000000000 +0100
@@ -58,12 +58,18 @@
  *   There are only two frequency states for each processor. Values
  * are in kHz for the time being.
  */
-static unsigned int                     speedstep_low_freq;
-static unsigned int                     speedstep_high_freq;
-
 #define SPEEDSTEP_HIGH                  0x00000000
 #define SPEEDSTEP_LOW                   0x00000001
 
+static struct cpufreq_frequency_table speedstep_freqs[] = {
+	{SPEEDSTEP_HIGH, 	0},
+	{SPEEDSTEP_LOW,		0},
+	{0,			CPUFREQ_TABLE_END},
+};
+
+#define speedstep_low_freq	speedstep_freqs[SPEEDSTEP_LOW].frequency
+#define speedstep_high_freq	speedstep_freqs[SPEEDSTEP_HIGH].frequency
+
 
 /* DEBUG
  *   Define it if you want verbose debug output, e.g. for bug reporting
@@ -569,22 +575,13 @@
  */
 static int speedstep_setpolicy (struct cpufreq_policy *policy)
 {
-	if (!speedstep_driver || !policy)
+	unsigned int    newstate = 0;
+
+	if (cpufreq_frequency_table_setpolicy(policy, &speedstep_freqs[0], &newstate))
 		return -EINVAL;
 
-	if (policy->min > speedstep_low_freq) 
-		speedstep_set_state(SPEEDSTEP_HIGH, 1);
-	else {
-		if (policy->max < speedstep_high_freq)
-			speedstep_set_state(SPEEDSTEP_LOW, 1);
-		else {
-			/* both frequency states are allowed */
-			if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
-				speedstep_set_state(SPEEDSTEP_LOW, 1);
-			else
-				speedstep_set_state(SPEEDSTEP_HIGH, 1);
-		}
-	}
+	speedstep_set_state(newstate, 1);
+
 	return 0;
 }
 
@@ -598,19 +595,7 @@
  */
 static int speedstep_verify (struct cpufreq_policy *policy)
 {
-	if (!policy || !speedstep_driver || 
-	    !speedstep_low_freq || !speedstep_high_freq)
-		return -EINVAL;
-
-	policy->cpu = 0; /* UP only */
-
-	cpufreq_verify_within_limits(policy, speedstep_low_freq, speedstep_high_freq);
-
-	if ((policy->min > speedstep_low_freq) && 
-	    (policy->max < speedstep_high_freq))
-		policy->max = speedstep_high_freq;
-	
-	return 0;
+	return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
 }
 
 
@@ -692,6 +677,13 @@
 
 	driver->policy = (struct cpufreq_policy *) (driver + 1);
 
+	driver->policy[0].cpu    = 0;
+	result = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &speedstep_freqs[0]);
+	if (result) {
+		kfree(driver);
+		return result;
+	}
+
 #ifdef CONFIG_CPU_FREQ_24_API
 	driver->cpu_cur_freq[0] = speed;
 #endif
@@ -699,11 +691,6 @@
 	driver->verify      = &speedstep_verify;
 	driver->setpolicy   = &speedstep_setpolicy;
 
-	driver->policy[0].cpu    = 0;
-	driver->policy[0].min    = speedstep_low_freq;
-	driver->policy[0].max    = speedstep_high_freq;
-	driver->policy[0].cpuinfo.min_freq = speedstep_low_freq;
-	driver->policy[0].cpuinfo.max_freq = speedstep_high_freq;
 	driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 
 	driver->policy[0].policy = (speed == speedstep_low_freq) ? 
diff -ruN linux-original/include/linux/cpufreq.h linux/include/linux/cpufreq.h
--- linux-original/include/linux/cpufreq.h	2003-01-09 19:15:52.000000000 +0100
+++ linux/include/linux/cpufreq.h	2003-01-09 20:09:17.000000000 +0100
@@ -241,4 +241,27 @@
 
 #endif /* CONFIG_CPU_FREQ_24_API */
 
+/*********************************************************************
+ *                     FREQUENCY TABLE HELPERS                       *
+ *********************************************************************/
+
+#define CPUFREQ_ENTRY_INVALID ~0
+#define CPUFREQ_TABLE_END     ~1
+
+struct cpufreq_frequency_table {
+	unsigned int	index;     /* any */
+	unsigned int	frequency; /* kHz - doesn't need to be in ascending
+				    * order */
+};
+
+int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
+				    struct cpufreq_frequency_table *table);
+
+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
+				   struct cpufreq_frequency_table *table);
+
+int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
+				      struct cpufreq_frequency_table *table,
+				      unsigned int *index);
+
 #endif /* _LINUX_CPUFREQ_H */
diff -ruN linux-original/kernel/cpufreq.c linux/kernel/cpufreq.c
--- linux-original/kernel/cpufreq.c	2003-01-09 19:19:58.000000000 +0100
+++ linux/kernel/cpufreq.c	2003-01-09 20:07:31.000000000 +0100
@@ -1134,3 +1134,120 @@
 #define cpufreq_restore() do {} while (0)
 #endif /* CONFIG_PM */
 
+
+/*********************************************************************
+ *                     FREQUENCY TABLE HELPERS                       *
+ *********************************************************************/
+
+int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
+				    struct cpufreq_frequency_table *table)
+{
+	unsigned int min_freq = ~0;
+	unsigned int max_freq = 0;
+	unsigned int i = 0;
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		unsigned int freq = table[i].frequency;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
+		if (freq < min_freq)
+			min_freq = freq;
+		if (freq > max_freq)
+			max_freq = freq;
+	}
+
+	policy->min = policy->cpuinfo.min_freq = min_freq;
+	policy->max = policy->cpuinfo.max_freq = max_freq;
+
+	if (policy->min == ~0)
+		return -EINVAL;
+	else
+		return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
+
+
+int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
+				   struct cpufreq_frequency_table *table)
+{
+	unsigned int next_larger = ~0;
+	unsigned int i = 0;
+	unsigned int count = 0;
+
+	if (!cpu_online(policy->cpu))
+		return -EINVAL;
+
+	cpufreq_verify_within_limits(policy, 
+				     policy->cpuinfo.min_freq, 
+				     policy->cpuinfo.max_freq);
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		unsigned int freq = table[i].frequency;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
+		if ((freq >= policy->min) && (freq <= policy->max))
+			count++;
+		else if ((next_larger > freq) && (freq > policy->max))
+			next_larger = freq;
+	}
+
+	if (!count)
+		policy->max = next_larger;
+
+	cpufreq_verify_within_limits(policy, 
+				     policy->cpuinfo.min_freq, 
+				     policy->cpuinfo.max_freq);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
+
+
+int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy,
+				      struct cpufreq_frequency_table *table,
+				      unsigned int *index)
+{
+	struct cpufreq_frequency_table optimal = { .index = ~0, };
+	unsigned int i;
+
+	switch (policy->policy) {
+	case CPUFREQ_POLICY_PERFORMANCE:
+		optimal.frequency = 0;
+		break;
+	case CPUFREQ_POLICY_POWERSAVE:
+		optimal.frequency = ~0;
+		break;
+	}
+
+	if (!cpu_online(policy->cpu))
+		return -EINVAL;
+
+	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
+		unsigned int freq = table[i].frequency;
+		if (freq == CPUFREQ_ENTRY_INVALID)
+			continue;
+		if ((freq < policy->min) || (freq > policy->max))
+			continue;
+		switch(policy->policy) {
+		case CPUFREQ_POLICY_PERFORMANCE:
+			if (optimal.frequency <= freq) {
+				optimal.frequency = freq;
+				optimal.index = i;
+			}
+			break;
+		case CPUFREQ_POLICY_POWERSAVE:
+			if (optimal.frequency >= freq) {
+				optimal.frequency = freq;
+				optimal.index = i;
+			}
+			break;
+		}
+	}
+	if (optimal.index > i)
+		return -EINVAL;
+
+	*index = optimal.index;
+	
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-01-10  9:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-01-10 10:05 [PATCH 2.5.55] cpufreq: frequency table helpers Dominik Brodowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox