public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Dominik Brodowski <linux@brodo.de>
To: torvalds@transmeta.com
Cc: linux-kernel@vger.kernel.org, cpufreq@www.linux.org.uk
Subject: [PATCH 2.5.56-bk3] cpufreq: per-CPU initialization in x86 + ACPI drivers
Date: Mon, 13 Jan 2003 16:02:25 +0100	[thread overview]
Message-ID: <20030113150225.GA10835@brodo.de> (raw)

This patch adds per-CPU initialization to a couple of cpufreq
drivers. It's a large simplification of many code paths, but
especially in the ACPI cpufreq driver.

	 Dominik

 arch/i386/kernel/cpu/cpufreq/elanfreq.c    |  104 ++++++--------
 arch/i386/kernel/cpu/cpufreq/longrun.c     |  102 ++++++--------
 arch/i386/kernel/cpu/cpufreq/p4-clockmod.c |  136 ++++++++----------
 arch/i386/kernel/cpu/cpufreq/powernow-k6.c |  122 ++++++++--------
 arch/i386/kernel/cpu/cpufreq/speedstep.c   |  130 +++++++-----------
 drivers/acpi/processor.c                   |  209 ++++++++++-------------------
 6 files changed, 359 insertions(+), 444 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-13 15:54:11.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/elanfreq.c	2003-01-13 15:55:00.000000000 +0100
@@ -31,15 +31,11 @@
 #define REG_CSCIR 0x22 		/* Chip Setup and Control Index Register    */
 #define REG_CSCDR 0x23		/* Chip Setup and Control Data  Register    */
 
-static struct cpufreq_driver *elanfreq_driver;
+static struct cpufreq_driver elanfreq_driver;
 
 /* Module parameter */
 static int max_freq;
 
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Robert Schwebel <r.schwebel@pengutronix.de>, Sven Geggus <sven@geggus.net>");
-MODULE_DESCRIPTION("cpufreq driver for AMD's Elan CPUs");
-
 struct s_elan_multiplier {
 	int clock;		/* frequency in kHz                         */
 	int val40h;		/* PMU Force Mode register                  */
@@ -204,6 +200,37 @@
  *	Module init and exit code
  */
 
+static int elanfreq_cpu_init(struct cpufreq_policy *policy)
+{
+	struct cpuinfo_x86 *c = cpu_data;
+	unsigned int i;
+
+	/* capability check */
+	if ((c->x86_vendor != X86_VENDOR_AMD) ||
+	    (c->x86 != 4) || (c->x86_model!=10))
+		return -ENODEV;
+
+	/* max freq */
+	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;
+	}
+
+	/* cpuinfo and default policy values */
+	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+#ifdef CONFIG_CPU_FREQ_24_API
+	elanfreq_driver.cpu_cur_freq[policy->cpu] = elanfreq_get_cpu_frequency();
+#endif
+
+	return cpufreq_frequency_table_cpuinfo(policy, &elanfreq_table[0]);;
+}
+
+
 #ifndef MODULE
 /**
  * elanfreq_setup - elanfreq command line parameter parsing
@@ -238,63 +265,32 @@
                 return -ENODEV;
 	}
 	
-	driver = kmalloc(sizeof(struct cpufreq_driver) +
-			 NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
-	if (!driver)
-		return -ENOMEM;
-
-	driver->policy = (struct cpufreq_policy *) (driver + 1);
-
-	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;
-	}
+	return cpufreq_register_driver(driver);
+}
 
-#ifdef CONFIG_CPU_FREQ_24_API
-	driver->cpu_cur_freq[0] = elanfreq_get_cpu_frequency();
-#endif
 
-	driver->verify        = &elanfreq_verify;
-	driver->setpolicy     = &elanfreq_setpolicy;
-	driver->init = NULL;
-	driver->exit = NULL;
-	strncpy(driver->name, "elanfrep\0", CPUFREQ_NAME_LEN);
-
-	driver->policy[0].cpu    = 0;
-	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.transition_latency = CPUFREQ_ETERNAL;
+static void __exit elanfreq_exit(void) 
+{
+	cpufreq_unregister_driver(&elanfreq_driver);
+}
 
-	elanfreq_driver = driver;
 
-	ret = cpufreq_register(driver);
-	if (ret) {
-		elanfreq_driver = NULL;
-		kfree(driver);
-	}
+static struct cpufreq_driver elanfreq_driver = {
+	.verify 	= elanfreq_verify,
+	.setpolicy 	= elanfreq_setpolicy,
+	.init		= elanfreq_cpu_init,
+	.exit		= NULL,
+	.policy		= NULL,
+	.name		= "elanfreq",
+};
 
-	return ret;
-}
 
+MODULE_PARM (max_freq, "i");
 
-static void __exit elanfreq_exit(void) 
-{
-	if (elanfreq_driver) {
-		cpufreq_unregister();
-		kfree(elanfreq_driver);
-	}
-}
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Schwebel <r.schwebel@pengutronix.de>, Sven Geggus <sven@geggus.net>");
+MODULE_DESCRIPTION("cpufreq driver for AMD's Elan CPUs");
 
 module_init(elanfreq_init);
 module_exit(elanfreq_exit);
 
-MODULE_PARM (max_freq, "i");
-
diff -ruN linux-original/arch/i386/kernel/cpu/cpufreq/longrun.c linux/arch/i386/kernel/cpu/cpufreq/longrun.c
--- linux-original/arch/i386/kernel/cpu/cpufreq/longrun.c	2003-01-13 15:54:11.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/longrun.c	2003-01-13 15:55:00.000000000 +0100
@@ -18,7 +18,7 @@
 #include <asm/processor.h>
 #include <asm/timex.h>
 
-static struct cpufreq_driver	*longrun_driver;
+static struct cpufreq_driver	longrun_driver;
 
 /**
  * longrun_{low,high}_freq is needed for the conversion of cpufreq kHz 
@@ -39,9 +39,6 @@
 {
 	u32 msr_lo, msr_hi;
 
-	if (!longrun_driver)
-		return;
-
 	rdmsr(MSR_TMTA_LONGRUN_FLAGS, msr_lo, msr_hi);
 	if (msr_lo & 0x01)
 		policy->policy = CPUFREQ_POLICY_PERFORMANCE;
@@ -72,7 +69,7 @@
 	u32 msr_lo, msr_hi;
 	u32 pctg_lo, pctg_hi;
 
-	if (!longrun_driver || !policy)
+	if (!policy)
 		return -EINVAL;
 
 	pctg_lo = (policy->min - longrun_low_freq) / 
@@ -117,13 +114,13 @@
  */
 static int longrun_verify_policy(struct cpufreq_policy *policy)
 {
-	if (!policy || !longrun_driver)
+	if (!policy)
 		return -EINVAL;
 
 	policy->cpu = 0;
 	cpufreq_verify_within_limits(policy, 
-		longrun_driver->policy[0].cpuinfo.min_freq, 
-		longrun_driver->policy[0].cpuinfo.max_freq);
+		policy->cpuinfo.min_freq, 
+		policy->cpuinfo.max_freq);
 
 	return 0;
 }
@@ -221,58 +218,51 @@
 }
 
 
-/**
- * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver
- *
- * Initializes the LongRun support.
- */
-static int __init longrun_init(void)
+static int longrun_cpu_init(struct cpufreq_policy *policy)
 {
-	int                     result;
-	struct cpufreq_driver   *driver;
+	int                     result = 0;
 	struct cpuinfo_x86 *c = cpu_data;
 
+	/* capability check */
+	if (policy->cpu != 0)
+		return -ENODEV;
 	if (c->x86_vendor != X86_VENDOR_TRANSMETA || 
 	    !cpu_has(c, X86_FEATURE_LONGRUN))
-		return 0;
-
-	/* initialization of main "cpufreq" code*/
-	driver = kmalloc(sizeof(struct cpufreq_driver) + 
-			 NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
-	if (!driver)
-		return -ENOMEM;
-
-	driver->policy = (struct cpufreq_policy *) (driver + 1);
-
-	if (longrun_determine_freqs(&longrun_low_freq, &longrun_high_freq)) {
-		kfree(driver);
-		return -EIO;
-	}
-	driver->policy[0].cpuinfo.min_freq = longrun_low_freq;
-	driver->policy[0].cpuinfo.max_freq = longrun_high_freq;
-	driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-	driver->init = NULL;
-	driver->exit = NULL;
-	strncpy(driver->name, "longrun\0", CPUFREQ_NAME_LEN);
-
-	longrun_get_policy(&driver->policy[0]);
+		return -ENODEV;
 
+	/* detect low and high frequency */
+	result = longrun_determine_freqs(&longrun_low_freq, &longrun_high_freq);
+	if (result)
+		return result;
+
+	/* cpuinfo and default policy values */
+	policy->cpuinfo.min_freq = longrun_low_freq;
+	policy->cpuinfo.max_freq = longrun_high_freq;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	longrun_get_policy(policy);
+	
 #ifdef CONFIG_CPU_FREQ_24_API
-	driver->cpu_cur_freq[0] = longrun_high_freq; /* dummy value */
+	longrun_driver.cpu_cur_freq[policy->cpu] = longrun_low_freq; /* dummy value */
 #endif
 
-	driver->verify         = &longrun_verify_policy;
-	driver->setpolicy      = &longrun_set_policy;
+	return 0;
+}
 
-	longrun_driver = driver;
 
-	result = cpufreq_register(driver);
-	if (result) {
-		longrun_driver = NULL;
-		kfree(driver);
-	}
+/**
+ * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver
+ *
+ * Initializes the LongRun support.
+ */
+static int __init longrun_init(void)
+{
+	struct cpuinfo_x86 *c = cpu_data;
+
+	if (c->x86_vendor != X86_VENDOR_TRANSMETA || 
+	    !cpu_has(c, X86_FEATURE_LONGRUN))
+		return -ENODEV;
 
-	return result;
+	return cpufreq_register_driver(&longrun_driver);
 }
 
 
@@ -281,15 +271,23 @@
  */
 static void __exit longrun_exit(void)
 {
-	if (longrun_driver) {
-		cpufreq_unregister();
-		kfree(longrun_driver);
-	}
+	cpufreq_unregister_driver(&longrun_driver);
 }
 
 
+static struct cpufreq_driver longrun_driver = {
+	.verify 	= longrun_verify_policy,
+	.setpolicy 	= longrun_set_policy,
+	.init		= longrun_cpu_init,
+	.exit		= NULL,
+	.policy		= NULL,
+	.name		= "longrun",
+};
+
+
 MODULE_AUTHOR ("Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION ("LongRun driver for Transmeta Crusoe processors.");
 MODULE_LICENSE ("GPL");
+
 module_init(longrun_init);
 module_exit(longrun_exit);
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-13 15:54:11.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2003-01-13 15:55:00.000000000 +0100
@@ -45,11 +45,11 @@
 #define DC_ENTRIES	8
 
 
-static int has_N44_O17_errata;
+static int has_N44_O17_errata[NR_CPUS];
 static int stock_freq;
 MODULE_PARM(stock_freq, "i");
 
-static struct cpufreq_driver *cpufreq_p4_driver;
+static struct cpufreq_driver p4clockmod_driver;
 
 
 static int cpufreq_p4_setdc(unsigned int cpu, unsigned int newstate)
@@ -109,7 +109,7 @@
 	if (l & 0x01)
 		printk(KERN_DEBUG PFX "CPU#%d currently thermal throttled\n", cpu);
 
-	if (has_N44_O17_errata && (newstate == DC_25PT || newstate == DC_DFLT))
+	if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT))
 		newstate = DC_38PT;
 
 	rdmsr(MSR_IA32_THERM_CONTROL, l, h);
@@ -174,39 +174,30 @@
 }
 
 
-static int __init cpufreq_p4_init(void)
-{	
-	struct cpuinfo_x86 *c = cpu_data;
-	int cpuid;
-	int ret;
-	struct cpufreq_driver *driver;
+static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
+{
+	struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
+	int cpuid = 0;
 	unsigned int i;
 
-	/*
-	 * THERM_CONTROL is architectural for IA32 now, so 
-	 * we can rely on the capability checks
-	 */
+	/* capability check */
 	if (c->x86_vendor != X86_VENDOR_INTEL)
 		return -ENODEV;
-
 	if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) ||
-		!test_bit(X86_FEATURE_ACC, c->x86_capability))
+	    !test_bit(X86_FEATURE_ACC, c->x86_capability))
 		return -ENODEV;
-
-	/* Errata workarounds */
+	
+	/* Errata workaround */
 	cpuid = (c->x86 << 8) | (c->x86_model << 4) | c->x86_mask;
 	switch (cpuid) {
-		case 0x0f07:
-		case 0x0f0a:
-		case 0x0f11:
-		case 0x0f12:
-			has_N44_O17_errata = 1;
-		default:
-			break;
+	case 0x0f07:
+	case 0x0f0a:
+	case 0x0f11:
+	case 0x0f12:
+		has_N44_O17_errata[policy->cpu] = 1;
 	}
-
-	printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n");
-
+	
+	/* get frequency */
 	if (!stock_freq) {
 		if (cpu_khz)
 			stock_freq = cpu_khz;
@@ -216,71 +207,70 @@
 		}
 	}
 
-	driver = kmalloc(sizeof(struct cpufreq_driver) +
-			 NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
-	if (!driver)
-		return -ENOMEM;
-
-	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))
+		if ((i<2) && (has_N44_O17_errata[policy->cpu]))
 			p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID;
 		else
 			p4clockmod_table[i].frequency = (stock_freq * i)/8;
 	}
 	
-
+	/* cpuinfo and default policy values */
+	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 #ifdef CONFIG_CPU_FREQ_24_API
-	for (i=0;i<NR_CPUS;i++) {
-		driver->cpu_cur_freq[i] = stock_freq;
-	}
+	p4clockmod_driver.cpu_cur_freq[policy->cpu] = stock_freq;
 #endif
 
-	driver->verify        = &cpufreq_p4_verify;
-	driver->setpolicy     = &cpufreq_p4_setpolicy;
-	driver->init = NULL;
-	driver->exit = NULL;
-	strncpy(driver->name, "p4-clockmod\0", CPUFREQ_NAME_LEN);
-
-	for (i=0;i<NR_CPUS;i++) {
-		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.transition_latency = CPUFREQ_ETERNAL;
-	}
+	return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]);
+}
 
-	cpufreq_p4_driver = driver;
-	
-	ret = cpufreq_register(driver);
-	if (ret) {
-		cpufreq_p4_driver = NULL;
-		kfree(driver);
-	}
 
-	return ret;
+static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
+{
+	return cpufreq_p4_setdc(policy->cpu, DC_DISABLE);
+}
+
+
+static int __init cpufreq_p4_init(void)
+{	
+	struct cpuinfo_x86 *c = cpu_data;
+
+	/*
+	 * THERM_CONTROL is architectural for IA32 now, so 
+	 * we can rely on the capability checks
+	 */
+	if (c->x86_vendor != X86_VENDOR_INTEL)
+		return -ENODEV;
+
+	if (!test_bit(X86_FEATURE_ACPI, c->x86_capability) ||
+		!test_bit(X86_FEATURE_ACC, c->x86_capability))
+		return -ENODEV;
+
+	printk(KERN_INFO PFX "P4/Xeon(TM) CPU On-Demand Clock Modulation available\n");
+
+	return cpufreq_register_driver(&p4clockmod_driver);
 }
 
 
 static void __exit cpufreq_p4_exit(void)
 {
-	unsigned int i;
-
-	if (cpufreq_p4_driver) {
-		for (i=0; i<NR_CPUS; i++) {
-			if (cpu_online(i)) 
-				cpufreq_p4_setdc(i, DC_DISABLE);
-		}
-		cpufreq_unregister();
-		kfree(cpufreq_p4_driver);
-	}
+	cpufreq_unregister_driver(&p4clockmod_driver);
 }
 
+
+static struct cpufreq_driver p4clockmod_driver = {
+	.verify 	= cpufreq_p4_verify,
+	.setpolicy 	= cpufreq_p4_setpolicy,
+	.init		= cpufreq_p4_cpu_init,
+	.exit		= cpufreq_p4_cpu_exit,
+	.policy		= NULL,
+	.name		= "p4-clockmod",
+};
+
+
+MODULE_PARM(stock_freq, "i");
+
 MODULE_AUTHOR ("Zwane Mwaikambo <zwane@commfireservices.com>");
 MODULE_DESCRIPTION ("cpufreq driver for Pentium(TM) 4/Xeon(TM)");
 MODULE_LICENSE ("GPL");
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-13 15:54:11.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/powernow-k6.c	2003-01-13 15:55:00.000000000 +0100
@@ -25,7 +25,7 @@
 #define POWERNOW_IOPORT 0xfff0         /* it doesn't matter where, as long
 					  as it is unused */
 
-static struct cpufreq_driver		*powernow_driver;
+static struct cpufreq_driver		powernow_k6_driver;
 static unsigned int                     busfreq;   /* FSB, in 10 kHz */
 static unsigned int                     max_multiplier;
 
@@ -77,8 +77,8 @@
 	unsigned long           msrval;
 	struct cpufreq_freqs    freqs;
 
-	if (!powernow_driver) {
-		printk(KERN_ERR "cpufreq: initialization problem or invalid target frequency\n");
+	if (clock_ratio[best_i].index > max_multiplier) {
+		printk(KERN_ERR "cpufreq: invalid target frequency\n");
 		return;
 	}
 
@@ -139,41 +139,22 @@
 }
 
 
-/**
- * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver
- *
- *   Initializes the K6 PowerNow! support. Returns -ENODEV on unsupported
- * devices, -EINVAL or -ENOMEM on problems during initiatization, and zero
- * on success.
- */
-static int __init powernow_k6_init(void)
-{	
-	struct cpuinfo_x86      *c = cpu_data;
-	struct cpufreq_driver   *driver;
-	unsigned int            result;
-	unsigned int            i;
+static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
+{
+	struct cpuinfo_x86 *c = cpu_data;
+	unsigned int i;
 
+	/* capability check */
 	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
-		((c->x86_model != 12) && (c->x86_model != 13)))
+	    ((c->x86_model != 12) && (c->x86_model != 13)))
+		return -ENODEV;
+	if (policy->cpu != 0)
 		return -ENODEV;
 
+	/* get frequencies */
 	max_multiplier = powernow_k6_get_cpu_multiplier();
 	busfreq = cpu_khz / max_multiplier;
 
-	if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) {
-		printk("cpufreq: PowerNow IOPORT region already used.\n");
-		return -EIO;
-	}
-
-	/* initialization of main "cpufreq" code*/
-	driver = kmalloc(sizeof(struct cpufreq_driver) +
-			 NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
-	if (!driver) {
-		release_region (POWERNOW_IOPORT, 16);
-		return -ENOMEM;
-	}
-	driver->policy = (struct cpufreq_policy *) (driver + 1);
-
 	/* table init */
  	for (i=0; (clock_ratio[i].frequency != CPUFREQ_TABLE_END); i++) {
 		if (clock_ratio[i].index > max_multiplier)
@@ -182,35 +163,52 @@
 			clock_ratio[i].frequency = busfreq * clock_ratio[i].index;
 	}
 
-	driver->verify        = &powernow_k6_verify;
-	driver->setpolicy     = &powernow_k6_setpolicy;
-	driver->init = NULL;
-	driver->exit = NULL;
-	strncpy(driver->name, "powernow-k6\0", CPUFREQ_NAME_LEN);
-
 	/* cpuinfo and default policy values */
-	driver->policy[0].cpu    = 0;
-	driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-	driver->policy[0].policy = CPUFREQ_POLICY_PERFORMANCE;
+	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 #ifdef CONFIG_CPU_FREQ_24_API
-	driver->cpu_cur_freq[0]  = busfreq * max_multiplier;
+	powernow_k6_driver.cpu_cur_freq[policy->cpu] = busfreq * max_multiplier;
 #endif
-	result = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &clock_ratio[0]);
-	if (result) {
-		kfree(driver);
-		return result;
+
+	return cpufreq_frequency_table_cpuinfo(policy, &clock_ratio[0]);
+}
+
+static int powernow_k6_cpu_exit(struct cpufreq_policy *policy)
+{
+	unsigned int i;
+	for (i=0; i<8; i++) {
+		if (i==max_multiplier)
+			powernow_k6_set_state(i);
 	}
+	return 0;
+}
 
-	powernow_driver = driver;
+/**
+ * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver
+ *
+ *   Initializes the K6 PowerNow! support. Returns -ENODEV on unsupported
+ * devices, -EINVAL or -ENOMEM on problems during initiatization, and zero
+ * on success.
+ */
+static int __init powernow_k6_init(void)
+{	
+	struct cpuinfo_x86      *c = cpu_data;
+
+	if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) ||
+		((c->x86_model != 12) && (c->x86_model != 13)))
+		return -ENODEV;
 
-	result = cpufreq_register(driver);
-	if (result) {
+	if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) {
+		printk("cpufreq: PowerNow IOPORT region already used.\n");
+		return -EIO;
+	}
+
+	if (cpufreq_register_driver(&powernow_k6_driver)) {
 		release_region (POWERNOW_IOPORT, 16);
-		powernow_driver = NULL;
-		kfree(driver);
+		return -EINVAL;
 	}
 
-	return result;
+	return 0;
 }
 
 
@@ -221,20 +219,24 @@
  */
 static void __exit powernow_k6_exit(void)
 {
-	unsigned int i;
-
-	if (powernow_driver) {
-		for (i=0;i<8;i++)
-			if (clock_ratio[i].index == max_multiplier)
-				powernow_k6_set_state(i);		
-		cpufreq_unregister();
-		kfree(powernow_driver);
-	}
+	cpufreq_unregister_driver(&powernow_k6_driver);
+	release_region (POWERNOW_IOPORT, 16);
 }
 
 
+static struct cpufreq_driver powernow_k6_driver = {
+	.verify 	= powernow_k6_verify,
+	.setpolicy 	= powernow_k6_setpolicy,
+	.init		= powernow_k6_cpu_init,
+	.exit		= powernow_k6_cpu_exit,
+	.policy		= NULL,
+	.name		= "powernow-k6",
+};
+
+
 MODULE_AUTHOR ("Arjan van de Ven <arjanv@redhat.com>, Dave Jones <davej@suse.de>, Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION ("PowerNow! driver for AMD K6-2+ / K6-3+ processors.");
 MODULE_LICENSE ("GPL");
+
 module_init(powernow_k6_init);
 module_exit(powernow_k6_exit);
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-13 15:54:11.000000000 +0100
+++ linux/arch/i386/kernel/cpu/cpufreq/speedstep.c	2003-01-13 15:55:00.000000000 +0100
@@ -30,7 +30,7 @@
 #include <asm/msr.h>
 
 
-static struct cpufreq_driver		*speedstep_driver;
+static struct cpufreq_driver		speedstep_driver;
 
 /* speedstep_chipset:
  *   It is necessary to know which chipset is used. As accesses to 
@@ -599,6 +599,42 @@
 }
 
 
+static int speedstep_cpu_init(struct cpufreq_policy *policy)
+{
+	int		result = 0;
+	unsigned int	speed;
+
+	/* capability check */
+	if (policy->cpu != 0)
+		return -ENODEV;
+
+	/* detect low and high frequency */
+	result = speedstep_detect_speeds();
+	if (result)
+		return result;
+
+	/* get current speed setting */
+	result = speedstep_get_state(&speed);
+	if (result)
+		return result;
+
+	speed = (speed == SPEEDSTEP_LOW) ? speedstep_low_freq : speedstep_high_freq;
+	dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", 
+		(speed == speedstep_low_freq) ? "low" : "high",
+		(speed / 1000));
+
+	/* cpuinfo and default policy values */
+	policy->policy = (speed == speedstep_low_freq) ? 
+		CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+#ifdef CONFIG_CPU_FREQ_24_API
+	speedstep_driver.cpu_cur_freq[policy->cpu] = speed;
+#endif
+
+	return cpufreq_frequency_table_cpuinfo(policy, &speedstep_freqs[0]);
+}
+
+
 #ifndef MODULE
 /**
  * speedstep_setup  speedstep command line parameter parsing
@@ -627,11 +663,6 @@
  */
 static int __init speedstep_init(void)
 {
-	int                     result;
-	unsigned int            speed;
-	struct cpufreq_driver   *driver;
-
-
 	/* detect chipset */
 	speedstep_chipset = speedstep_detect_chipset(); 
 
@@ -640,74 +671,17 @@
 		speedstep_processor = speedstep_detect_processor();
 
 	if ((!speedstep_chipset) || (!speedstep_processor)) {
-		printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_chipset ? "processor" : "chipset");
+		dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_chipset ? "processor" : "chipset");
 		return -ENODEV;
 	}
 
 	dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.58 $\n");
-	dprintk(KERN_DEBUG "cpufreq: chipset 0x%x - processor 0x%x\n", 
-	       speedstep_chipset, speedstep_processor);
-
-	/* activate speedstep support */
-	result = speedstep_activate();
-	if (result)
-		return result;
 
-	/* detect low and high frequency */
-	result = speedstep_detect_speeds();
-	if (result)
-		return result;
-
-	/* get current speed setting */
-	result = speedstep_get_state(&speed);
-	if (result)
-		return result;
-
-	speed = (speed == SPEEDSTEP_LOW) ? speedstep_low_freq : speedstep_high_freq;
-
-	dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", 
-	       (speed == speedstep_low_freq) ? "low" : "high",
-	       (speed / 1000));
-
-	/* initialization of main "cpufreq" code*/
-	driver = kmalloc(sizeof(struct cpufreq_driver) + 
-			 NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
-	if (!driver)
-		return -ENOMEM;
-
-	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
-
-	driver->verify      = &speedstep_verify;
-	driver->setpolicy   = &speedstep_setpolicy;
-	driver->init = NULL;
-	driver->exit = NULL;
-	strncpy(driver->name, "speedstep\0", CPUFREQ_NAME_LEN);
-
-	driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-
-	driver->policy[0].policy = (speed == speedstep_low_freq) ? 
-	    CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE;
-
-	speedstep_driver = driver;
-
-	result = cpufreq_register(driver);
-	if (result) {
-		speedstep_driver = NULL;
-		kfree(driver);
-	}
+	/* activate speedstep support on chipset */
+	if (speedstep_activate())
+		return -EINVAL;
 
-	return result;
+	return cpufreq_register_driver(&speedstep_driver);
 }
 
 
@@ -718,17 +692,25 @@
  */
 static void __exit speedstep_exit(void)
 {
-	if (speedstep_driver) {
-		cpufreq_unregister();
-		kfree(speedstep_driver);
-	}
+	cpufreq_unregister_driver(&speedstep_driver);
 }
 
 
+static struct cpufreq_driver speedstep_driver = {
+	.verify 	= speedstep_verify,
+	.setpolicy 	= speedstep_setpolicy,
+	.init		= speedstep_cpu_init,
+	.exit		= NULL,
+	.policy		= NULL,
+	.name		= "speedstep",
+};
+
+
+MODULE_PARM (speedstep_coppermine, "i");
+
 MODULE_AUTHOR ("Dave Jones <davej@suse.de>, Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors.");
 MODULE_LICENSE ("GPL");
+
 module_init(speedstep_init);
 module_exit(speedstep_exit);
-
-MODULE_PARM (speedstep_coppermine, "i");
diff -ruN linux-original/drivers/acpi/processor.c linux/drivers/acpi/processor.c
--- linux-original/drivers/acpi/processor.c	2003-01-13 15:54:11.000000000 +0100
+++ linux/drivers/acpi/processor.c	2003-01-13 15:55:00.000000000 +0100
@@ -166,6 +166,9 @@
 	u16			status_register;
 	int			state_count;
 	struct acpi_processor_px states[ACPI_PROCESSOR_MAX_PERFORMANCE];
+#ifdef CONFIG_ACPI_PROCESSOR_PERF
+	struct cpufreq_frequency_table freq_table[ACPI_PROCESSOR_MAX_PERFORMANCE];
+#endif
 };
 
 
@@ -263,8 +266,8 @@
 static void (*pm_idle_save)(void) = NULL;
 
 #ifdef CONFIG_ACPI_PROCESSOR_PERF
-static unsigned int cpufreq_usage_count = 0;
-static struct cpufreq_driver *acpi_cpufreq_driver;
+static unsigned int cpufreq_usage = 0;
+static struct cpufreq_driver acpi_cpufreq_driver;
 static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file);
 static struct file_operations acpi_processor_perf_fops = {
 	.open 		= acpi_processor_perf_open_fs,
@@ -1658,7 +1661,6 @@
 acpi_cpufreq_setpolicy (
 	struct cpufreq_policy   *policy)
 {
-	unsigned int i = 0;
 	struct acpi_processor *pr = NULL;
 	unsigned int next_state = 0;
 	unsigned int result = 0;
@@ -1672,33 +1674,12 @@
 	if (!pr)
 		return_VALUE(-EINVAL);
 
-	/* select appropriate P-State */
-	if (policy->policy == CPUFREQ_POLICY_POWERSAVE)
-	{
-		for (i=(pr->performance.state_count - 1); i>= pr->limit.state.px; i--)
-		{
-			unsigned int state_freq = pr->performance.states[i].core_frequency * 1000;
-			if ((policy->min <= state_freq) &&
-			    (policy->max >= state_freq)) 
-			{
-				next_state = i;
-				break;
-			}
-		}
-	} else {
-		for (i=pr->limit.state.px; i < pr->performance.state_count; i++)
-		{
-			unsigned int state_freq = pr->performance.states[i].core_frequency * 1000;
-			if ((policy->min <= state_freq) &&
-			    (policy->max >= state_freq)) 
-			{
-				next_state = i;
-				break;
-			}
-		}
-	}
+	result = cpufreq_frequency_table_setpolicy(policy, 
+			&pr->performance.freq_table[pr->limit.state.px], 
+			&next_state);
+	if (result)
+		return_VALUE(result);
 
-	/* set one or all CPUs to the new state */
 	result = acpi_processor_set_performance (pr, next_state);
 
 	return_VALUE(result);
@@ -1709,10 +1690,8 @@
 acpi_cpufreq_verify (
 	struct cpufreq_policy   *policy)
 {
-	unsigned int i = 0;
 	struct acpi_processor *pr = NULL;
-	unsigned int number_states = 0;
-	unsigned int next_larger_state = 0;
+	unsigned int result = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_cpufreq_verify");
 
@@ -1723,55 +1702,75 @@
 	if (!pr)
 		return_VALUE(-EINVAL);
 
-	/* first check if min and max are within valid limits */
+	result = cpufreq_frequency_table_verify(policy, 
+			&pr->performance.freq_table[pr->limit.state.px]);
+
 	cpufreq_verify_within_limits(
 		policy, 
 		pr->performance.states[pr->performance.state_count - 1].core_frequency * 1000,
 		pr->performance.states[pr->limit.state.px].core_frequency * 1000);
 
-	/* now check if at least one value is within this limit */
-	for (i=pr->limit.state.px; i < pr->performance.state_count; i++)
-	{
-		unsigned int state_freq = pr->performance.states[i].core_frequency * 1000;
-		if ((policy->min <= state_freq) &&
-		    (policy->max >= state_freq))
-			number_states++;
-		if (state_freq > policy->max)
-			next_larger_state = i;
+	return_VALUE(result);
+}
+
+
+static int
+acpi_cpufreq_cpu_init (
+	struct cpufreq_policy   *policy)
+{
+	unsigned int		i;
+	struct acpi_processor  *pr = NULL;
+	unsigned int		result = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_cpufreq_cpu_init");
+
+	pr = processors[policy->cpu];
+	if (!pr)
+		return_VALUE(-EINVAL);
+
+	/* capability check */
+	if (!pr->flags.performance)
+		return_VALUE(-ENODEV);
+
+	/* detect transition latency */
+	policy->cpuinfo.transition_latency = 0;
+	for (i=0;i<pr->performance.state_count;i++) {
+		if (pr->performance.states[i].transition_latency > policy->cpuinfo.transition_latency)
+			policy->cpuinfo.transition_latency = pr->performance.states[i].transition_latency;
 	}
+	policy->policy = CPUFREQ_POLICY_PERFORMANCE;
 
-	if (!number_states) {
-		/* round up now */
-		policy->max = pr->performance.states[next_larger_state].core_frequency * 1000;
+	/* table init */
+	for (i=0; i<=pr->performance.state_count; i++)
+	{
+		pr->performance.freq_table[i].index = i;
+		if (i<pr->performance.state_count)
+			pr->performance.freq_table[i].frequency = pr->performance.states[i].core_frequency * 1000;
+		else
+			pr->performance.freq_table[i].frequency = CPUFREQ_TABLE_END;
 	}
 
-	cpufreq_verify_within_limits(
-		policy, 
-		pr->performance.states[pr->performance.state_count - 1].core_frequency * 1000,
-		pr->performance.states[pr->limit.state.px].core_frequency * 1000);
+#ifdef CONFIG_CPU_FREQ_24_API
+	acpi_cpufreq_driver.cpu_cur_freq[policy->cpu] = pr->performance.states[pr->limit.state.px].core_frequency * 1000;
+#endif
 
-	return_VALUE(0);
+	result = cpufreq_frequency_table_cpuinfo(policy, &pr->performance.freq_table[0]);
+
+	return_VALUE(result);
 }
 
+
 static int
 acpi_cpufreq_init (
 	struct acpi_processor   *pr)
 {
 	int                     result = 0;
-	int                     i = 0;
 	int                     current_state = 0;
-	struct cpufreq_driver   *driver;
 
 	ACPI_FUNCTION_TRACE("acpi_cpufreq_init");
 
-	if (!pr->flags.performance)
-		return_VALUE(0);
-
-	if (cpufreq_usage_count) {
-		if (pr->flags.performance == 1)
-			cpufreq_usage_count++;
+	if (!pr->flags.performance || cpufreq_usage)
 		return_VALUE(0);
-	}
 
 	/* test if it works */
 	current_state = pr->performance.state;
@@ -1801,97 +1800,44 @@
 		}
 	}
 
-	/* initialization of main "cpufreq" code*/
-	driver = kmalloc(sizeof(struct cpufreq_driver) + 
-			 NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
-	if (!driver)
-		return_VALUE(-ENOMEM);
-
-	driver->policy = (struct cpufreq_policy *) (driver + 1);
-
-#ifdef CONFIG_CPU_FREQ_24_API
-	for (i=0;i<NR_CPUS;i++) {
-		driver->cpu_cur_freq[0] = pr->performance.states[current_state].core_frequency * 1000;
-	}
-#endif
-
-	/* detect highest transition latency */
-	for (i=0;i<pr->performance.state_count;i++) {
-		if (pr->performance.states[i].transition_latency > driver->policy[0].cpuinfo.transition_latency)
-			driver->policy[0].cpuinfo.transition_latency = pr->performance.states[i].transition_latency;
-	}
-
-	driver->verify      = &acpi_cpufreq_verify;
-	driver->setpolicy   = &acpi_cpufreq_setpolicy;
-	driver->init        = NULL;
-	driver->exit        = NULL;
-	strncpy(driver->name, "acpi-processor\0", CPUFREQ_NAME_LEN);
-
-	for (i=0;i<NR_CPUS;i++) {
-		driver->policy[i].cpu    = pr->id;
-		driver->policy[i].min    = pr->performance.states[pr->performance.state_count - 1].core_frequency * 1000;
-		driver->policy[i].max    = pr->performance.states[pr->limit.state.px].core_frequency * 1000;
-		driver->policy[i].cpuinfo.max_freq = pr->performance.states[0].core_frequency * 1000;
-		driver->policy[i].cpuinfo.min_freq = pr->performance.states[pr->performance.state_count - 1].core_frequency * 1000;
-		driver->policy[i].cpuinfo.transition_latency = driver->policy[0].cpuinfo.transition_latency;
-		driver->policy[i].policy = ( pr->performance.states[current_state].core_frequency * 1000 == driver->policy[i].max) ? 
-			CPUFREQ_POLICY_PERFORMANCE : CPUFREQ_POLICY_POWERSAVE;
-	}
-
-	acpi_cpufreq_driver = driver;
-	result = cpufreq_register(driver);
+	/* register driver */
+	result = cpufreq_register_driver(&acpi_cpufreq_driver);
 	if (result) {
-		kfree(driver);
-		acpi_cpufreq_driver = NULL;
+		pr->flags.performance = 0;
 		return_VALUE(result);
 	}
 
-	cpufreq_usage_count++;
-
+	cpufreq_usage = 1;
 	return_VALUE(0);
 }
 
 static int
-acpi_cpufreq_exit (
-	struct acpi_processor   *pr)
+acpi_cpufreq_exit (void)
 {
 	int                     result = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_cpufreq_exit");
 
-	if (!pr)
-		return_VALUE(-EINVAL);
-
-	if (pr->flags.performance)
-		cpufreq_usage_count--;
-
-	if (!cpufreq_usage_count) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, 
-			"Removing cpufreq driver\n"));
-		result = cpufreq_unregister();
-	}
+	result = cpufreq_unregister_driver(&acpi_cpufreq_driver);
 
 	return_VALUE(result);
 }
-#else
-static int
-acpi_cpufreq_init (
-	struct acpi_processor   *pr)
-{
-	ACPI_FUNCTION_TRACE("acpi_cpufreq_init_dummy");
-	return_VALUE(0);
-}
 
+static struct cpufreq_driver acpi_cpufreq_driver = {
+	.verify 	= acpi_cpufreq_verify,
+	.setpolicy 	= acpi_cpufreq_setpolicy,
+	.init		= acpi_cpufreq_cpu_init,
+	.exit		= NULL,
+	.policy		= NULL,
+	.name		= "acpi-processor",
+};
 
-static int
-acpi_cpufreq_exit (
-	struct acpi_processor   *pr)
-{
-	ACPI_FUNCTION_TRACE("acpi_cpufreq_exit_dummy");
-	return_VALUE(0);
-}
+#else
+#define acpi_cpufreq_init(x) do {} while(0)
+#define acpi_cpufreq_exit()  do {} while(0)
 #endif
 
+
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
    -------------------------------------------------------------------------- */
@@ -2554,7 +2500,6 @@
 		return_VALUE(-ENODEV);
 	}
 
-	acpi_cpufreq_exit(pr);
 	acpi_processor_remove_fs(device);
 
 	processors[pr->id] = NULL;
@@ -2594,6 +2539,8 @@
 {
 	ACPI_FUNCTION_TRACE("acpi_processor_exit");
 
+	acpi_cpufreq_exit();
+
 	acpi_bus_unregister_driver(&acpi_processor_driver);
 
 	remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);

                 reply	other threads:[~2003-01-13 14:54 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030113150225.GA10835@brodo.de \
    --to=linux@brodo.de \
    --cc=cpufreq@www.linux.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@transmeta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox