cpufreq: ia64: move cpufreq driver to drivers/cpufreq
authorViresh Kumar <viresh.kumar@linaro.org>
Thu, 4 Apr 2013 12:54:20 +0000 (12:54 +0000)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 10 Apr 2013 11:19:25 +0000 (13:19 +0200)
This patch moves cpufreq driver of IA64 architecture to drivers/cpufreq.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
arch/ia64/Kconfig
arch/ia64/kernel/Makefile
arch/ia64/kernel/cpufreq/Kconfig [deleted file]
arch/ia64/kernel/cpufreq/Makefile [deleted file]
arch/ia64/kernel/cpufreq/acpi-cpufreq.c [deleted file]
drivers/cpufreq/Kconfig
drivers/cpufreq/Makefile
drivers/cpufreq/ia64-acpi-cpufreq.c [new file with mode: 0644]

index 9a02f71c6b1f7cb5e8339e55f77bb82ad9b8d8d3..152b5f29d048641875c556987a5bef1cd9c93d9a 100644 (file)
@@ -591,9 +591,9 @@ source "kernel/power/Kconfig"
 source "drivers/acpi/Kconfig"
 
 if PM
-
-source "arch/ia64/kernel/cpufreq/Kconfig"
-
+menu "CPU Frequency scaling"
+source "drivers/cpufreq/Kconfig"
+endmenu
 endif
 
 endmenu
index d959c84904bec8bb978da5d11fc3ba0bfb54be26..20678a9ed11a83081083b2aca0ac8bd84b5b9fcb 100644 (file)
@@ -23,7 +23,6 @@ obj-$(CONFIG_SMP)             += smp.o smpboot.o
 obj-$(CONFIG_NUMA)             += numa.o
 obj-$(CONFIG_PERFMON)          += perfmon_default_smpl.o
 obj-$(CONFIG_IA64_CYCLONE)     += cyclone.o
-obj-$(CONFIG_CPU_FREQ)         += cpufreq/
 obj-$(CONFIG_IA64_MCA_RECOVERY)        += mca_recovery.o
 obj-$(CONFIG_KPROBES)          += kprobes.o jprobes.o
 obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
diff --git a/arch/ia64/kernel/cpufreq/Kconfig b/arch/ia64/kernel/cpufreq/Kconfig
deleted file mode 100644 (file)
index 2d9d527..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-
-#
-# CPU Frequency scaling
-#
-
-menu "CPU Frequency scaling"
-
-source "drivers/cpufreq/Kconfig"
-
-if CPU_FREQ
-
-comment "CPUFreq processor drivers"
-
-config IA64_ACPI_CPUFREQ
-       tristate "ACPI Processor P-States driver"
-       select CPU_FREQ_TABLE
-       depends on ACPI_PROCESSOR
-       help
-       This driver adds a CPUFreq driver which utilizes the ACPI
-       Processor Performance States.
-
-       For details, take a look at <file:Documentation/cpu-freq/>.
-
-       If in doubt, say N.
-
-endif   # CPU_FREQ
-
-endmenu
-
diff --git a/arch/ia64/kernel/cpufreq/Makefile b/arch/ia64/kernel/cpufreq/Makefile
deleted file mode 100644 (file)
index 4838f2a..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_IA64_ACPI_CPUFREQ)                += acpi-cpufreq.o
-
diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c
deleted file mode 100644 (file)
index 4700fef..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * arch/ia64/kernel/cpufreq/acpi-cpufreq.c
- * This file provides the ACPI based P-state support. This
- * module works with generic cpufreq infrastructure. Most of
- * the code is based on i386 version
- * (arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c)
- *
- * Copyright (C) 2005 Intel Corp
- *      Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pal.h>
-
-#include <linux/acpi.h>
-#include <acpi/processor.h>
-
-MODULE_AUTHOR("Venkatesh Pallipadi");
-MODULE_DESCRIPTION("ACPI Processor P-States Driver");
-MODULE_LICENSE("GPL");
-
-
-struct cpufreq_acpi_io {
-       struct acpi_processor_performance       acpi_data;
-       struct cpufreq_frequency_table          *freq_table;
-       unsigned int                            resume;
-};
-
-static struct cpufreq_acpi_io  *acpi_io_data[NR_CPUS];
-
-static struct cpufreq_driver acpi_cpufreq_driver;
-
-
-static int
-processor_set_pstate (
-       u32     value)
-{
-       s64 retval;
-
-       pr_debug("processor_set_pstate\n");
-
-       retval = ia64_pal_set_pstate((u64)value);
-
-       if (retval) {
-               pr_debug("Failed to set freq to 0x%x, with error 0x%lx\n",
-                       value, retval);
-               return -ENODEV;
-       }
-       return (int)retval;
-}
-
-
-static int
-processor_get_pstate (
-       u32     *value)
-{
-       u64     pstate_index = 0;
-       s64     retval;
-
-       pr_debug("processor_get_pstate\n");
-
-       retval = ia64_pal_get_pstate(&pstate_index,
-                                    PAL_GET_PSTATE_TYPE_INSTANT);
-       *value = (u32) pstate_index;
-
-       if (retval)
-               pr_debug("Failed to get current freq with "
-                       "error 0x%lx, idx 0x%x\n", retval, *value);
-
-       return (int)retval;
-}
-
-
-/* To be used only after data->acpi_data is initialized */
-static unsigned
-extract_clock (
-       struct cpufreq_acpi_io *data,
-       unsigned value,
-       unsigned int cpu)
-{
-       unsigned long i;
-
-       pr_debug("extract_clock\n");
-
-       for (i = 0; i < data->acpi_data.state_count; i++) {
-               if (value == data->acpi_data.states[i].status)
-                       return data->acpi_data.states[i].core_frequency;
-       }
-       return data->acpi_data.states[i-1].core_frequency;
-}
-
-
-static unsigned int
-processor_get_freq (
-       struct cpufreq_acpi_io  *data,
-       unsigned int            cpu)
-{
-       int                     ret = 0;
-       u32                     value = 0;
-       cpumask_t               saved_mask;
-       unsigned long           clock_freq;
-
-       pr_debug("processor_get_freq\n");
-
-       saved_mask = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, cpumask_of(cpu));
-       if (smp_processor_id() != cpu)
-               goto migrate_end;
-
-       /* processor_get_pstate gets the instantaneous frequency */
-       ret = processor_get_pstate(&value);
-
-       if (ret) {
-               set_cpus_allowed_ptr(current, &saved_mask);
-               printk(KERN_WARNING "get performance failed with error %d\n",
-                      ret);
-               ret = 0;
-               goto migrate_end;
-       }
-       clock_freq = extract_clock(data, value, cpu);
-       ret = (clock_freq*1000);
-
-migrate_end:
-       set_cpus_allowed_ptr(current, &saved_mask);
-       return ret;
-}
-
-
-static int
-processor_set_freq (
-       struct cpufreq_acpi_io  *data,
-       struct cpufreq_policy   *policy,
-       int                     state)
-{
-       int                     ret = 0;
-       u32                     value = 0;
-       struct cpufreq_freqs    cpufreq_freqs;
-       cpumask_t               saved_mask;
-       int                     retval;
-
-       pr_debug("processor_set_freq\n");
-
-       saved_mask = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, cpumask_of(policy->cpu));
-       if (smp_processor_id() != policy->cpu) {
-               retval = -EAGAIN;
-               goto migrate_end;
-       }
-
-       if (state == data->acpi_data.state) {
-               if (unlikely(data->resume)) {
-                       pr_debug("Called after resume, resetting to P%d\n", state);
-                       data->resume = 0;
-               } else {
-                       pr_debug("Already at target state (P%d)\n", state);
-                       retval = 0;
-                       goto migrate_end;
-               }
-       }
-
-       pr_debug("Transitioning from P%d to P%d\n",
-               data->acpi_data.state, state);
-
-       /* cpufreq frequency struct */
-       cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
-       cpufreq_freqs.new = data->freq_table[state].frequency;
-
-       /* notify cpufreq */
-       cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_PRECHANGE);
-
-       /*
-        * First we write the target state's 'control' value to the
-        * control_register.
-        */
-
-       value = (u32) data->acpi_data.states[state].control;
-
-       pr_debug("Transitioning to state: 0x%08x\n", value);
-
-       ret = processor_set_pstate(value);
-       if (ret) {
-               unsigned int tmp = cpufreq_freqs.new;
-               cpufreq_notify_transition(policy, &cpufreq_freqs,
-                               CPUFREQ_POSTCHANGE);
-               cpufreq_freqs.new = cpufreq_freqs.old;
-               cpufreq_freqs.old = tmp;
-               cpufreq_notify_transition(policy, &cpufreq_freqs,
-                               CPUFREQ_PRECHANGE);
-               cpufreq_notify_transition(policy, &cpufreq_freqs,
-                               CPUFREQ_POSTCHANGE);
-               printk(KERN_WARNING "Transition failed with error %d\n", ret);
-               retval = -ENODEV;
-               goto migrate_end;
-       }
-
-       cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_POSTCHANGE);
-
-       data->acpi_data.state = state;
-
-       retval = 0;
-
-migrate_end:
-       set_cpus_allowed_ptr(current, &saved_mask);
-       return (retval);
-}
-
-
-static unsigned int
-acpi_cpufreq_get (
-       unsigned int            cpu)
-{
-       struct cpufreq_acpi_io *data = acpi_io_data[cpu];
-
-       pr_debug("acpi_cpufreq_get\n");
-
-       return processor_get_freq(data, cpu);
-}
-
-
-static int
-acpi_cpufreq_target (
-       struct cpufreq_policy   *policy,
-       unsigned int target_freq,
-       unsigned int relation)
-{
-       struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-       unsigned int next_state = 0;
-       unsigned int result = 0;
-
-       pr_debug("acpi_cpufreq_setpolicy\n");
-
-       result = cpufreq_frequency_table_target(policy,
-                       data->freq_table, target_freq, relation, &next_state);
-       if (result)
-               return (result);
-
-       result = processor_set_freq(data, policy, next_state);
-
-       return (result);
-}
-
-
-static int
-acpi_cpufreq_verify (
-       struct cpufreq_policy   *policy)
-{
-       unsigned int result = 0;
-       struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-
-       pr_debug("acpi_cpufreq_verify\n");
-
-       result = cpufreq_frequency_table_verify(policy,
-                       data->freq_table);
-
-       return (result);
-}
-
-
-static int
-acpi_cpufreq_cpu_init (
-       struct cpufreq_policy   *policy)
-{
-       unsigned int            i;
-       unsigned int            cpu = policy->cpu;
-       struct cpufreq_acpi_io  *data;
-       unsigned int            result = 0;
-
-       pr_debug("acpi_cpufreq_cpu_init\n");
-
-       data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
-       if (!data)
-               return (-ENOMEM);
-
-       acpi_io_data[cpu] = data;
-
-       result = acpi_processor_register_performance(&data->acpi_data, cpu);
-
-       if (result)
-               goto err_free;
-
-       /* capability check */
-       if (data->acpi_data.state_count <= 1) {
-               pr_debug("No P-States\n");
-               result = -ENODEV;
-               goto err_unreg;
-       }
-
-       if ((data->acpi_data.control_register.space_id !=
-                                       ACPI_ADR_SPACE_FIXED_HARDWARE) ||
-           (data->acpi_data.status_register.space_id !=
-                                       ACPI_ADR_SPACE_FIXED_HARDWARE)) {
-               pr_debug("Unsupported address space [%d, %d]\n",
-                       (u32) (data->acpi_data.control_register.space_id),
-                       (u32) (data->acpi_data.status_register.space_id));
-               result = -ENODEV;
-               goto err_unreg;
-       }
-
-       /* alloc freq_table */
-       data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
-                                  (data->acpi_data.state_count + 1),
-                                  GFP_KERNEL);
-       if (!data->freq_table) {
-               result = -ENOMEM;
-               goto err_unreg;
-       }
-
-       /* detect transition latency */
-       policy->cpuinfo.transition_latency = 0;
-       for (i=0; i<data->acpi_data.state_count; i++) {
-               if ((data->acpi_data.states[i].transition_latency * 1000) >
-                   policy->cpuinfo.transition_latency) {
-                       policy->cpuinfo.transition_latency =
-                           data->acpi_data.states[i].transition_latency * 1000;
-               }
-       }
-       policy->cur = processor_get_freq(data, policy->cpu);
-
-       /* table init */
-       for (i = 0; i <= data->acpi_data.state_count; i++)
-       {
-               data->freq_table[i].index = i;
-               if (i < data->acpi_data.state_count) {
-                       data->freq_table[i].frequency =
-                             data->acpi_data.states[i].core_frequency * 1000;
-               } else {
-                       data->freq_table[i].frequency = CPUFREQ_TABLE_END;
-               }
-       }
-
-       result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
-       if (result) {
-               goto err_freqfree;
-       }
-
-       /* notify BIOS that we exist */
-       acpi_processor_notify_smm(THIS_MODULE);
-
-       printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management "
-              "activated.\n", cpu);
-
-       for (i = 0; i < data->acpi_data.state_count; i++)
-               pr_debug("     %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n",
-                       (i == data->acpi_data.state?'*':' '), i,
-                       (u32) data->acpi_data.states[i].core_frequency,
-                       (u32) data->acpi_data.states[i].power,
-                       (u32) data->acpi_data.states[i].transition_latency,
-                       (u32) data->acpi_data.states[i].bus_master_latency,
-                       (u32) data->acpi_data.states[i].status,
-                       (u32) data->acpi_data.states[i].control);
-
-       cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
-
-       /* the first call to ->target() should result in us actually
-        * writing something to the appropriate registers. */
-       data->resume = 1;
-
-       return (result);
-
- err_freqfree:
-       kfree(data->freq_table);
- err_unreg:
-       acpi_processor_unregister_performance(&data->acpi_data, cpu);
- err_free:
-       kfree(data);
-       acpi_io_data[cpu] = NULL;
-
-       return (result);
-}
-
-
-static int
-acpi_cpufreq_cpu_exit (
-       struct cpufreq_policy   *policy)
-{
-       struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-
-       pr_debug("acpi_cpufreq_cpu_exit\n");
-
-       if (data) {
-               cpufreq_frequency_table_put_attr(policy->cpu);
-               acpi_io_data[policy->cpu] = NULL;
-               acpi_processor_unregister_performance(&data->acpi_data,
-                                                     policy->cpu);
-               kfree(data);
-       }
-
-       return (0);
-}
-
-
-static struct freq_attr* acpi_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-
-static struct cpufreq_driver acpi_cpufreq_driver = {
-       .verify         = acpi_cpufreq_verify,
-       .target         = acpi_cpufreq_target,
-       .get            = acpi_cpufreq_get,
-       .init           = acpi_cpufreq_cpu_init,
-       .exit           = acpi_cpufreq_cpu_exit,
-       .name           = "acpi-cpufreq",
-       .owner          = THIS_MODULE,
-       .attr           = acpi_cpufreq_attr,
-};
-
-
-static int __init
-acpi_cpufreq_init (void)
-{
-       pr_debug("acpi_cpufreq_init\n");
-
-       return cpufreq_register_driver(&acpi_cpufreq_driver);
-}
-
-
-static void __exit
-acpi_cpufreq_exit (void)
-{
-       pr_debug("acpi_cpufreq_exit\n");
-
-       cpufreq_unregister_driver(&acpi_cpufreq_driver);
-       return;
-}
-
-
-late_initcall(acpi_cpufreq_init);
-module_exit(acpi_cpufreq_exit);
-
index d7ce6ccf5c9106ee94575dfe3b29bffc81e03220..a2f1600c78f8566b25a03dbb30bd133b0547330c 100644 (file)
@@ -218,6 +218,23 @@ config AVR32_AT32AP_CPUFREQ
 
 endmenu
 
+menu "CPUFreq processor drivers"
+depends on IA64
+
+config IA64_ACPI_CPUFREQ
+       tristate "ACPI Processor P-States driver"
+       select CPU_FREQ_TABLE
+       depends on ACPI_PROCESSOR
+       help
+       This driver adds a CPUFreq driver which utilizes the ACPI
+       Processor Performance States.
+
+       For details, take a look at <file:Documentation/cpu-freq/>.
+
+       If in doubt, say N.
+
+endmenu
+
 menu "PowerPC CPU frequency scaling drivers"
 depends on PPC32 || PPC64
 source "drivers/cpufreq/Kconfig.powerpc"
index 2d6dbf30862b3339ee3452c9354634ad8ceaa54c..ab681337e6d49d72d3134efc62b803e669c3c4aa 100644 (file)
@@ -81,3 +81,4 @@ obj-$(CONFIG_AVR32_AT32AP_CPUFREQ)    += at32ap-cpufreq.o
 obj-$(CONFIG_BLACKFIN)                 += blackfin-cpufreq.o
 obj-$(CONFIG_CRIS_MACH_ARTPEC3)                += cris-artpec3-cpufreq.o
 obj-$(CONFIG_ETRAXFS)                  += cris-etraxfs-cpufreq.o
+obj-$(CONFIG_IA64_ACPI_CPUFREQ)                += ia64-acpi-cpufreq.o
diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c
new file mode 100644 (file)
index 0000000..c0075db
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+ * This file provides the ACPI based P-state support. This
+ * module works with generic cpufreq infrastructure. Most of
+ * the code is based on i386 version
+ * (arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c)
+ *
+ * Copyright (C) 2005 Intel Corp
+ *      Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/cpufreq.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pal.h>
+
+#include <linux/acpi.h>
+#include <acpi/processor.h>
+
+MODULE_AUTHOR("Venkatesh Pallipadi");
+MODULE_DESCRIPTION("ACPI Processor P-States Driver");
+MODULE_LICENSE("GPL");
+
+
+struct cpufreq_acpi_io {
+       struct acpi_processor_performance       acpi_data;
+       struct cpufreq_frequency_table          *freq_table;
+       unsigned int                            resume;
+};
+
+static struct cpufreq_acpi_io  *acpi_io_data[NR_CPUS];
+
+static struct cpufreq_driver acpi_cpufreq_driver;
+
+
+static int
+processor_set_pstate (
+       u32     value)
+{
+       s64 retval;
+
+       pr_debug("processor_set_pstate\n");
+
+       retval = ia64_pal_set_pstate((u64)value);
+
+       if (retval) {
+               pr_debug("Failed to set freq to 0x%x, with error 0x%lx\n",
+                       value, retval);
+               return -ENODEV;
+       }
+       return (int)retval;
+}
+
+
+static int
+processor_get_pstate (
+       u32     *value)
+{
+       u64     pstate_index = 0;
+       s64     retval;
+
+       pr_debug("processor_get_pstate\n");
+
+       retval = ia64_pal_get_pstate(&pstate_index,
+                                    PAL_GET_PSTATE_TYPE_INSTANT);
+       *value = (u32) pstate_index;
+
+       if (retval)
+               pr_debug("Failed to get current freq with "
+                       "error 0x%lx, idx 0x%x\n", retval, *value);
+
+       return (int)retval;
+}
+
+
+/* To be used only after data->acpi_data is initialized */
+static unsigned
+extract_clock (
+       struct cpufreq_acpi_io *data,
+       unsigned value,
+       unsigned int cpu)
+{
+       unsigned long i;
+
+       pr_debug("extract_clock\n");
+
+       for (i = 0; i < data->acpi_data.state_count; i++) {
+               if (value == data->acpi_data.states[i].status)
+                       return data->acpi_data.states[i].core_frequency;
+       }
+       return data->acpi_data.states[i-1].core_frequency;
+}
+
+
+static unsigned int
+processor_get_freq (
+       struct cpufreq_acpi_io  *data,
+       unsigned int            cpu)
+{
+       int                     ret = 0;
+       u32                     value = 0;
+       cpumask_t               saved_mask;
+       unsigned long           clock_freq;
+
+       pr_debug("processor_get_freq\n");
+
+       saved_mask = current->cpus_allowed;
+       set_cpus_allowed_ptr(current, cpumask_of(cpu));
+       if (smp_processor_id() != cpu)
+               goto migrate_end;
+
+       /* processor_get_pstate gets the instantaneous frequency */
+       ret = processor_get_pstate(&value);
+
+       if (ret) {
+               set_cpus_allowed_ptr(current, &saved_mask);
+               printk(KERN_WARNING "get performance failed with error %d\n",
+                      ret);
+               ret = 0;
+               goto migrate_end;
+       }
+       clock_freq = extract_clock(data, value, cpu);
+       ret = (clock_freq*1000);
+
+migrate_end:
+       set_cpus_allowed_ptr(current, &saved_mask);
+       return ret;
+}
+
+
+static int
+processor_set_freq (
+       struct cpufreq_acpi_io  *data,
+       struct cpufreq_policy   *policy,
+       int                     state)
+{
+       int                     ret = 0;
+       u32                     value = 0;
+       struct cpufreq_freqs    cpufreq_freqs;
+       cpumask_t               saved_mask;
+       int                     retval;
+
+       pr_debug("processor_set_freq\n");
+
+       saved_mask = current->cpus_allowed;
+       set_cpus_allowed_ptr(current, cpumask_of(policy->cpu));
+       if (smp_processor_id() != policy->cpu) {
+               retval = -EAGAIN;
+               goto migrate_end;
+       }
+
+       if (state == data->acpi_data.state) {
+               if (unlikely(data->resume)) {
+                       pr_debug("Called after resume, resetting to P%d\n", state);
+                       data->resume = 0;
+               } else {
+                       pr_debug("Already at target state (P%d)\n", state);
+                       retval = 0;
+                       goto migrate_end;
+               }
+       }
+
+       pr_debug("Transitioning from P%d to P%d\n",
+               data->acpi_data.state, state);
+
+       /* cpufreq frequency struct */
+       cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
+       cpufreq_freqs.new = data->freq_table[state].frequency;
+
+       /* notify cpufreq */
+       cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_PRECHANGE);
+
+       /*
+        * First we write the target state's 'control' value to the
+        * control_register.
+        */
+
+       value = (u32) data->acpi_data.states[state].control;
+
+       pr_debug("Transitioning to state: 0x%08x\n", value);
+
+       ret = processor_set_pstate(value);
+       if (ret) {
+               unsigned int tmp = cpufreq_freqs.new;
+               cpufreq_notify_transition(policy, &cpufreq_freqs,
+                               CPUFREQ_POSTCHANGE);
+               cpufreq_freqs.new = cpufreq_freqs.old;
+               cpufreq_freqs.old = tmp;
+               cpufreq_notify_transition(policy, &cpufreq_freqs,
+                               CPUFREQ_PRECHANGE);
+               cpufreq_notify_transition(policy, &cpufreq_freqs,
+                               CPUFREQ_POSTCHANGE);
+               printk(KERN_WARNING "Transition failed with error %d\n", ret);
+               retval = -ENODEV;
+               goto migrate_end;
+       }
+
+       cpufreq_notify_transition(policy, &cpufreq_freqs, CPUFREQ_POSTCHANGE);
+
+       data->acpi_data.state = state;
+
+       retval = 0;
+
+migrate_end:
+       set_cpus_allowed_ptr(current, &saved_mask);
+       return (retval);
+}
+
+
+static unsigned int
+acpi_cpufreq_get (
+       unsigned int            cpu)
+{
+       struct cpufreq_acpi_io *data = acpi_io_data[cpu];
+
+       pr_debug("acpi_cpufreq_get\n");
+
+       return processor_get_freq(data, cpu);
+}
+
+
+static int
+acpi_cpufreq_target (
+       struct cpufreq_policy   *policy,
+       unsigned int target_freq,
+       unsigned int relation)
+{
+       struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+       unsigned int next_state = 0;
+       unsigned int result = 0;
+
+       pr_debug("acpi_cpufreq_setpolicy\n");
+
+       result = cpufreq_frequency_table_target(policy,
+                       data->freq_table, target_freq, relation, &next_state);
+       if (result)
+               return (result);
+
+       result = processor_set_freq(data, policy, next_state);
+
+       return (result);
+}
+
+
+static int
+acpi_cpufreq_verify (
+       struct cpufreq_policy   *policy)
+{
+       unsigned int result = 0;
+       struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+
+       pr_debug("acpi_cpufreq_verify\n");
+
+       result = cpufreq_frequency_table_verify(policy,
+                       data->freq_table);
+
+       return (result);
+}
+
+
+static int
+acpi_cpufreq_cpu_init (
+       struct cpufreq_policy   *policy)
+{
+       unsigned int            i;
+       unsigned int            cpu = policy->cpu;
+       struct cpufreq_acpi_io  *data;
+       unsigned int            result = 0;
+
+       pr_debug("acpi_cpufreq_cpu_init\n");
+
+       data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
+       if (!data)
+               return (-ENOMEM);
+
+       acpi_io_data[cpu] = data;
+
+       result = acpi_processor_register_performance(&data->acpi_data, cpu);
+
+       if (result)
+               goto err_free;
+
+       /* capability check */
+       if (data->acpi_data.state_count <= 1) {
+               pr_debug("No P-States\n");
+               result = -ENODEV;
+               goto err_unreg;
+       }
+
+       if ((data->acpi_data.control_register.space_id !=
+                                       ACPI_ADR_SPACE_FIXED_HARDWARE) ||
+           (data->acpi_data.status_register.space_id !=
+                                       ACPI_ADR_SPACE_FIXED_HARDWARE)) {
+               pr_debug("Unsupported address space [%d, %d]\n",
+                       (u32) (data->acpi_data.control_register.space_id),
+                       (u32) (data->acpi_data.status_register.space_id));
+               result = -ENODEV;
+               goto err_unreg;
+       }
+
+       /* alloc freq_table */
+       data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) *
+                                  (data->acpi_data.state_count + 1),
+                                  GFP_KERNEL);
+       if (!data->freq_table) {
+               result = -ENOMEM;
+               goto err_unreg;
+       }
+
+       /* detect transition latency */
+       policy->cpuinfo.transition_latency = 0;
+       for (i=0; i<data->acpi_data.state_count; i++) {
+               if ((data->acpi_data.states[i].transition_latency * 1000) >
+                   policy->cpuinfo.transition_latency) {
+                       policy->cpuinfo.transition_latency =
+                           data->acpi_data.states[i].transition_latency * 1000;
+               }
+       }
+       policy->cur = processor_get_freq(data, policy->cpu);
+
+       /* table init */
+       for (i = 0; i <= data->acpi_data.state_count; i++)
+       {
+               data->freq_table[i].index = i;
+               if (i < data->acpi_data.state_count) {
+                       data->freq_table[i].frequency =
+                             data->acpi_data.states[i].core_frequency * 1000;
+               } else {
+                       data->freq_table[i].frequency = CPUFREQ_TABLE_END;
+               }
+       }
+
+       result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
+       if (result) {
+               goto err_freqfree;
+       }
+
+       /* notify BIOS that we exist */
+       acpi_processor_notify_smm(THIS_MODULE);
+
+       printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management "
+              "activated.\n", cpu);
+
+       for (i = 0; i < data->acpi_data.state_count; i++)
+               pr_debug("     %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n",
+                       (i == data->acpi_data.state?'*':' '), i,
+                       (u32) data->acpi_data.states[i].core_frequency,
+                       (u32) data->acpi_data.states[i].power,
+                       (u32) data->acpi_data.states[i].transition_latency,
+                       (u32) data->acpi_data.states[i].bus_master_latency,
+                       (u32) data->acpi_data.states[i].status,
+                       (u32) data->acpi_data.states[i].control);
+
+       cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
+
+       /* the first call to ->target() should result in us actually
+        * writing something to the appropriate registers. */
+       data->resume = 1;
+
+       return (result);
+
+ err_freqfree:
+       kfree(data->freq_table);
+ err_unreg:
+       acpi_processor_unregister_performance(&data->acpi_data, cpu);
+ err_free:
+       kfree(data);
+       acpi_io_data[cpu] = NULL;
+
+       return (result);
+}
+
+
+static int
+acpi_cpufreq_cpu_exit (
+       struct cpufreq_policy   *policy)
+{
+       struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+
+       pr_debug("acpi_cpufreq_cpu_exit\n");
+
+       if (data) {
+               cpufreq_frequency_table_put_attr(policy->cpu);
+               acpi_io_data[policy->cpu] = NULL;
+               acpi_processor_unregister_performance(&data->acpi_data,
+                                                     policy->cpu);
+               kfree(data);
+       }
+
+       return (0);
+}
+
+
+static struct freq_attr* acpi_cpufreq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
+
+static struct cpufreq_driver acpi_cpufreq_driver = {
+       .verify         = acpi_cpufreq_verify,
+       .target         = acpi_cpufreq_target,
+       .get            = acpi_cpufreq_get,
+       .init           = acpi_cpufreq_cpu_init,
+       .exit           = acpi_cpufreq_cpu_exit,
+       .name           = "acpi-cpufreq",
+       .owner          = THIS_MODULE,
+       .attr           = acpi_cpufreq_attr,
+};
+
+
+static int __init
+acpi_cpufreq_init (void)
+{
+       pr_debug("acpi_cpufreq_init\n");
+
+       return cpufreq_register_driver(&acpi_cpufreq_driver);
+}
+
+
+static void __exit
+acpi_cpufreq_exit (void)
+{
+       pr_debug("acpi_cpufreq_exit\n");
+
+       cpufreq_unregister_driver(&acpi_cpufreq_driver);
+       return;
+}
+
+
+late_initcall(acpi_cpufreq_init);
+module_exit(acpi_cpufreq_exit);
+
This page took 0.036178 seconds and 5 git commands to generate.