]> git.hungrycats.org Git - linux/commitdiff
[PATCH] cpufreq: per-CPU initialization
authorDominik Brodowski <linux@brodo.de>
Mon, 13 Jan 2003 06:03:50 +0000 (22:03 -0800)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Mon, 13 Jan 2003 06:03:50 +0000 (22:03 -0800)
Allow for per-CPU initialization of CPUfreq. Therefore, it's not
necessary any longer to kmalloc the per-CPU policy struct. To use
this, cpufreq_driver->policy has to be set to NULL. Of course,
cpufreq_driver->init is needed then, which is the appropriate function
for CPU initialization. cpufreq_driver->exit is available for cleanup.

All existing drivers continue to work without any changes, just for
clarity ->init and ->exit are set to NULL, and the names accordingly.

12 files changed:
arch/arm/mach-integrator/cpu.c
arch/arm/mach-sa1100/cpu-sa1100.c
arch/arm/mach-sa1100/cpu-sa1110.c
arch/i386/kernel/cpu/cpufreq/elanfreq.c
arch/i386/kernel/cpu/cpufreq/longhaul.c
arch/i386/kernel/cpu/cpufreq/longrun.c
arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
arch/i386/kernel/cpu/cpufreq/powernow-k6.c
arch/i386/kernel/cpu/cpufreq/speedstep.c
drivers/acpi/processor.c
include/linux/cpufreq.h
kernel/cpufreq.c

index e59d1abf5f4ff685bd6399956319a7b1db82f860..2d71baa76351081a154d611830eb7767044f209e 100644 (file)
@@ -166,6 +166,7 @@ static struct cpufreq_driver integrator_driver = {
        .verify         = integrator_verify_speed,
        .setpolicy      = integrator_set_policy,
        .policy         = &integrator_policy,
+       .name           = "integrator",
 };
 #endif
 
index 31378afc1d3f9738274cba0c28b4f07164b3c652..b4226692b9021b15fb30c8df9566293c138f0c69 100644 (file)
@@ -214,6 +214,7 @@ static struct cpufreq_driver sa1100_driver = {
        .verify         = sa11x0_verify_speed,
        .setpolicy      = sa1100_setspeed,
        .policy         = &sa1100_policy,
+       .name           = "sa1100",
 };
 
 static int __init sa1100_dram_init(void)
index f46c170631822dab37f0a66aba4808df913f6dfa..2ab03f867d867475266d9da6fdcae12a9cce0f6d 100644 (file)
@@ -309,6 +309,7 @@ static struct cpufreq_driver sa1110_driver = {
        .verify          = sa11x0_verify_speed,
        .setpolicy       = sa1110_setspeed,
        .policy          = &sa1110_policy,
+       .name           = "sa1110",
 };
 
 static int __init sa1110_clk_init(void)
index 1917510f033809f3dd8db56963f6bc92107bfe01..c1c7aa0758640cd1c139aac2cd3435f3bde9c634 100644 (file)
@@ -260,6 +260,9 @@ static int __init elanfreq_init(void)
 
        driver->verify        = &elanfreq_verify;
        driver->setpolicy     = &elanfreq_setpolicy;
+       driver->init = NULL;
+       driver->exit = NULL;
+       strncpy(driver->name, "elanfreq", CPUFREQ_NAME_LEN);
 
        driver->policy[0].cpu    = 0;
        ret = cpufreq_frequency_table_cpuinfo(&driver->policy[0], &elanfreq_table[0]);
index d6f3f66d6644c9db43b7c089de5632b44ad6498a..b0af80343bedabb0c4c33fcded91444a8a6468a9 100644 (file)
@@ -771,6 +771,9 @@ static int __init longhaul_init (void)
 
        driver->verify    = &longhaul_verify;
        driver->setpolicy = &longhaul_setpolicy;
+       driver->init = NULL;
+       driver->exit = NULL;
+       strncpy(driver->name, "longhaul", CPUFREQ_NAME_LEN);
 
        driver->policy[0].cpu = 0;
        driver->policy[0].min = (unsigned int) lowest_speed;
index 69b4fdb4275182866b360266deef871b17d3f678..b8a854fb0f2f1e4dd9ffedd2da452d83d29c8ac1 100644 (file)
@@ -251,6 +251,9 @@ static int __init longrun_init(void)
        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", CPUFREQ_NAME_LEN);
 
        longrun_get_policy(&driver->policy[0]);
 
index e26c7918045e59be952a6944f8c62549327c51f6..c64aa0ac9cad15330e12f7ca94097fbc8fa462b8 100644 (file)
@@ -240,6 +240,9 @@ static int __init cpufreq_p4_init(void)
 
        driver->verify        = &cpufreq_p4_verify;
        driver->setpolicy     = &cpufreq_p4_setpolicy;
+       driver->init = NULL;
+       driver->exit = NULL;
+       strncpy(driver->name, "p4-clockmod", CPUFREQ_NAME_LEN);
 
        for (i=0;i<NR_CPUS;i++) {
                driver->policy[i].cpu    = i;
index 88085123ee3b657e09f3fa6a74461abd7ac5b518..af01528ce993f1efc86a0a27cfb97cb420970bef 100644 (file)
@@ -184,6 +184,9 @@ static int __init powernow_k6_init(void)
 
        driver->verify        = &powernow_k6_verify;
        driver->setpolicy     = &powernow_k6_setpolicy;
+       driver->init = NULL;
+       driver->exit = NULL;
+       strncpy(driver->name, "powernow-k6", CPUFREQ_NAME_LEN);
 
        /* cpuinfo and default policy values */
        driver->policy[0].cpu    = 0;
index 97212910fcff0b1425d4d70474def0e84097744c..209938dc1021a787fcb40f772953875fdecb1d8a 100644 (file)
@@ -690,6 +690,9 @@ static int __init speedstep_init(void)
 
        driver->verify      = &speedstep_verify;
        driver->setpolicy   = &speedstep_setpolicy;
+       driver->init = NULL;
+       driver->exit = NULL;
+       strncpy(driver->name, "speedstep", CPUFREQ_NAME_LEN);
 
        driver->policy[0].cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 
index 9c2bc028dce44882d0be220b3a402edfe4fe11c1..ebdd6f25a2d7fb76427059ee2a766115b1e72ab8 100644 (file)
@@ -1823,6 +1823,9 @@ acpi_cpufreq_init (
 
        driver->verify      = &acpi_cpufreq_verify;
        driver->setpolicy   = &acpi_cpufreq_setpolicy;
+       driver->init        = NULL;
+       driver->exit        = NULL;
+       strncpy(driver->name, "acpi-processor", CPUFREQ_NAME_LEN);
 
        for (i=0;i<NR_CPUS;i++) {
                driver->policy[i].cpu    = pr->id;
index 12c59ed7d6955d68f5b27e6d99e030affe6c0809..9226268ef4ef9dee91581799d480a905d02e9776 100644 (file)
@@ -109,19 +109,29 @@ static inline unsigned long cpufreq_scale(unsigned long old, u_int div, u_int mu
  *                      CPUFREQ DRIVER INTERFACE                     *
  *********************************************************************/
 
+#define CPUFREQ_NAME_LEN 16
+
 struct cpufreq_driver {
        /* needed by all drivers */
        int     (*verify)       (struct cpufreq_policy *policy);
        int     (*setpolicy)    (struct cpufreq_policy *policy);
        struct cpufreq_policy   *policy;
+       char                    name[CPUFREQ_NAME_LEN];
+       /* optional, for the moment */
+       int     (*init)        (struct cpufreq_policy *policy);
+       int     (*exit)        (struct cpufreq_policy *policy);
        /* 2.4. compatible API */
 #ifdef CONFIG_CPU_FREQ_24_API
        unsigned int            cpu_cur_freq[NR_CPUS];
 #endif
 };
 
-int cpufreq_register(struct cpufreq_driver *driver_data);
-int cpufreq_unregister(void);
+int cpufreq_register_driver(struct cpufreq_driver *driver_data);
+int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
+/* deprecated */
+#define cpufreq_register(x)   cpufreq_register_driver(x)
+#define cpufreq_unregister(x) cpufreq_unregister_driver(NULL)
+
 
 void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state);
 
index f2e15a43e39d35111ba107c8e57f7b1e82caf1dd..9f13db3b92334c3316237e1c4dcdbff2e35d2e8c 100644 (file)
@@ -57,18 +57,6 @@ static struct notifier_block    *cpufreq_transition_notifier_list;
 static DECLARE_MUTEX            (cpufreq_notifier_sem);
 
 
-/**
- * The cpufreq default policy. Can be set by a "cpufreq=..." command
- * line option.
- */
-static struct cpufreq_policy default_policy = {
-       .cpu    = CPUFREQ_ALL_CPUS,
-       .min    = 0,
-       .max    = 0,
-       .policy = 0,
-};
-
-
 #ifdef CONFIG_CPU_FREQ_24_API
 /**
  * A few values needed by the 2.4.-compatible API
@@ -234,6 +222,25 @@ store_scaling_governor (struct device *dev, const char *buf, size_t count)
 }
 
 
+/**
+ * show_scaling_governor - show the current policy for the specified CPU
+ */
+static ssize_t show_scaling_driver (struct device *dev, char *buf)
+{
+       char value[CPUFREQ_NAME_LEN];
+
+       if (!dev)
+               return 0;
+
+       down(&cpufreq_driver_sem);
+       if (cpufreq_driver)
+               strncpy(value, cpufreq_driver->name, CPUFREQ_NAME_LEN);
+       up(&cpufreq_driver_sem);
+
+       return sprintf(buf, "%s\n", value);
+}
+
+
 /**
  * cpufreq_per_cpu_attr_ro - read-only cpufreq per-CPU file
  */
@@ -258,6 +265,7 @@ cpufreq_per_cpu_attr_rw(scaling_min_freq, min);
 cpufreq_per_cpu_attr_rw(scaling_max_freq, max);
 
 static DEVICE_ATTR(scaling_governor, (S_IRUGO | S_IWUSR), show_scaling_governor, store_scaling_governor);
+static DEVICE_ATTR(scaling_driver, S_IRUGO, show_scaling_driver, NULL);
 
 
 /**
@@ -269,6 +277,7 @@ static int cpufreq_add_dev (struct device * dev)
 {
        unsigned int cpu = to_cpu_nr(dev);
        int ret = 0;
+       struct cpufreq_policy policy;
 
        down(&cpufreq_driver_sem);
        if (!cpufreq_driver) {
@@ -276,6 +285,37 @@ static int cpufreq_add_dev (struct device * dev)
                return -EINVAL;
        }
 
+       /* call driver. From then on the cpufreq must be able
+        * to accept all calls to ->verify and ->setpolicy for this CPU
+        */
+       cpufreq_driver->policy[cpu].cpu = cpu;
+       if (cpufreq_driver->init) {
+               ret = cpufreq_driver->init(&cpufreq_driver->policy[cpu]);
+               if (ret) {
+                       up(&cpufreq_driver_sem);
+                       return -ENODEV;
+               }
+       }
+
+       /* set default policy on this CPU */
+       policy.policy = cpufreq_driver->policy[cpu].policy;
+       policy.min    = cpufreq_driver->policy[cpu].min;
+       policy.max    = cpufreq_driver->policy[cpu].max;
+       policy.cpu    = cpu;
+
+       up(&cpufreq_driver_sem);
+       ret = cpufreq_set_policy(&policy);
+       if (ret)
+               return -EINVAL;
+       down(&cpufreq_driver_sem);
+
+       /* 2.4-API init for this CPU */
+#ifdef CONFIG_CPU_FREQ_24_API
+       cpu_min_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.min_freq;
+       cpu_max_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.max_freq;
+       cpu_cur_freq[cpu] = cpufreq_driver->cpu_cur_freq[cpu];
+#endif
+
        /* prepare interface data */
        cpufreq_driver->policy[cpu].intf.dev  = dev;
        cpufreq_driver->policy[cpu].intf.intf = &cpufreq_interface;
@@ -297,6 +337,7 @@ static int cpufreq_add_dev (struct device * dev)
        device_create_file (dev, &dev_attr_scaling_min_freq);
        device_create_file (dev, &dev_attr_scaling_max_freq);
        device_create_file (dev, &dev_attr_scaling_governor);
+       device_create_file (dev, &dev_attr_scaling_driver);
 
        up(&cpufreq_driver_sem);
        return ret;
@@ -312,12 +353,17 @@ static int cpufreq_add_dev (struct device * dev)
 static int cpufreq_remove_dev (struct intf_data *intf)
 {
        struct device * dev = intf->dev;
+       unsigned int cpu = to_cpu_nr(dev);
+
+       if (cpufreq_driver->exit)
+               cpufreq_driver->exit(&cpufreq_driver->policy[cpu]);
 
        device_remove_file (dev, &dev_attr_cpuinfo_min_freq);
        device_remove_file (dev, &dev_attr_cpuinfo_max_freq);
        device_remove_file (dev, &dev_attr_scaling_min_freq);
        device_remove_file (dev, &dev_attr_scaling_max_freq);
        device_remove_file (dev, &dev_attr_scaling_governor);
+       device_remove_file (dev, &dev_attr_scaling_governor);
 
        return 0;
 }
@@ -402,20 +448,6 @@ scan_policy:
 }
 
 
-/*
- * cpufreq command line parameter.  Must be hard values (kHz)
- *  cpufreq=1000000:2000000:PERFORMANCE   
- * to set the default CPUFreq policy.
- */
-static int __init cpufreq_setup(char *str)
-{
-       cpufreq_parse_policy(str, &default_policy);
-       default_policy.cpu = CPUFREQ_ALL_CPUS;
-       return 1;
-}
-__setup("cpufreq=", cpufreq_setup);
-
-
 /**
  * cpufreq_proc_read - read /proc/cpufreq
  *
@@ -1203,19 +1235,18 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
  *********************************************************************/
 
 /**
- * cpufreq_register - register a CPU Frequency driver
- * @driver_data: A struct cpufreq_driver containing the values submitted by the CPU Frequency driver.
+ * cpufreq_register_driver - register a CPU Frequency driver
+ * @driver_data: A struct cpufreq_driver containing the values#
+ * submitted by the CPU Frequency driver.
  *
  *   Registers a CPU Frequency driver to this core code. This code 
  * returns zero on success, -EBUSY when another driver got here first
  * (and isn't unregistered in the meantime). 
  *
  */
-int cpufreq_register(struct cpufreq_driver *driver_data)
+int cpufreq_register_driver(struct cpufreq_driver *driver_data)
 {
-       unsigned int            ret;
-       unsigned int            i;
-       struct cpufreq_policy   policy;
+       int ret = 0;
 
        if (cpufreq_driver)
                return -EBUSY;
@@ -1225,53 +1256,27 @@ int cpufreq_register(struct cpufreq_driver *driver_data)
                return -EINVAL;
 
        down(&cpufreq_driver_sem);
-       cpufreq_driver        = driver_data;
-       
-       /* check for a default policy - if it exists, use it on _all_ CPUs*/
-       for (i=0; i<NR_CPUS; i++)
-       {
-               if (default_policy.policy)
-                       cpufreq_driver->policy[i].policy = default_policy.policy;
-               if (default_policy.min)
-                       cpufreq_driver->policy[i].min = default_policy.min;
-               if (default_policy.max)
-                       cpufreq_driver->policy[i].max = default_policy.max;
-       }
 
-       /* set default policy on all CPUs. Must be called per-CPU and not
-        * with CPUFREQ_ALL_CPUs as there might be no common policy for all
-        * CPUs (UltraSPARC etc.)
-        */
-       for (i=0; i<NR_CPUS; i++)
-       {
-               policy.policy = cpufreq_driver->policy[i].policy;
-               policy.min    = cpufreq_driver->policy[i].min;
-               policy.max    = cpufreq_driver->policy[i].max;
-               policy.cpu    = i;
-               up(&cpufreq_driver_sem);
-               ret = cpufreq_set_policy(&policy);
-               down(&cpufreq_driver_sem);
-               if (ret) {
-                       cpufreq_driver = NULL;
+       cpufreq_driver = driver_data;
+
+       if (!cpufreq_driver->policy) {
+               /* then we need per-CPU init */
+               if (!cpufreq_driver->init) {
                        up(&cpufreq_driver_sem);
-                       return ret;
+                       return -EINVAL;
+               }
+               cpufreq_driver->policy = kmalloc(NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL);
+               if (!cpufreq_driver->policy) {
+                       up(&cpufreq_driver_sem);
+                       return -ENOMEM;
                }
        }
-
+       
        up(&cpufreq_driver_sem);
 
        cpufreq_proc_init();
 
 #ifdef CONFIG_CPU_FREQ_24_API
-       down(&cpufreq_driver_sem);
-       for (i=0; i<NR_CPUS; i++) 
-       {
-               cpu_min_freq[i] = driver_data->policy[i].cpuinfo.min_freq;
-               cpu_max_freq[i] = driver_data->policy[i].cpuinfo.max_freq;
-               cpu_cur_freq[i] = driver_data->cpu_cur_freq[i];
-       }
-       up(&cpufreq_driver_sem);
-
        cpufreq_sysctl_init();
 #endif
 
@@ -1279,40 +1284,53 @@ int cpufreq_register(struct cpufreq_driver *driver_data)
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(cpufreq_register);
+EXPORT_SYMBOL_GPL(cpufreq_register_driver);
 
 
 /**
- * cpufreq_unregister - unregister the current CPUFreq driver
+ * cpufreq_unregister_driver - unregister the current CPUFreq driver
  *
  *    Unregister the current CPUFreq driver. Only call this if you have 
  * the right to do so, i.e. if you have succeeded in initialising before!
  * Returns zero if successful, and -EINVAL if the cpufreq_driver is
  * currently not initialised.
  */
-int cpufreq_unregister(void)
+int cpufreq_unregister_driver(struct cpufreq_driver *driver)
 {
        down(&cpufreq_driver_sem);
 
-       if (!cpufreq_driver) {
+       if (!cpufreq_driver || 
+           ((driver != cpufreq_driver) && (driver != NULL))) { /* compat */
                up(&cpufreq_driver_sem);
                return -EINVAL;
        }
 
-       interface_unregister(&cpufreq_interface);
-       cpufreq_driver = NULL;
-
-       up(&cpufreq_driver_sem);
-
        cpufreq_proc_exit();
 
 #ifdef CONFIG_CPU_FREQ_24_API
        cpufreq_sysctl_exit();
 #endif
 
+       /* remove this workaround as soon as interface_add_data works */
+       {
+               unsigned int i;
+               for (i=0; i<NR_CPUS; i++) {
+                       if (cpu_online(i)) 
+                               cpufreq_remove_dev(&cpufreq_driver->policy[i].intf);
+               }
+       }
+
+       interface_unregister(&cpufreq_interface);
+
+       if (driver)
+               kfree(cpufreq_driver->policy);
+       cpufreq_driver = NULL;
+
+       up(&cpufreq_driver_sem);
+
        return 0;
 }
-EXPORT_SYMBOL_GPL(cpufreq_unregister);
+EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
 
 
 #ifdef CONFIG_PM