[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC PATCH v2 6/8] cpufreq: introduce cpufreq_drv_ops



This patch allows to use more than one high-level
cpufreq driver. This patch is needed for implementation
xen-based high-level cpufreq driver.

Signed-off-by: Oleksandr Dmytryshyn <oleksandr.dmytryshyn@xxxxxxxxxxxxxxx>
---
 drivers/cpufreq/Kconfig            |   4 +
 drivers/cpufreq/Makefile           |   1 +
 drivers/cpufreq/acpi-cpufreq.c     |   5 +-
 drivers/cpufreq/cpufreq.c          | 116 ++++++++++++-----------
 drivers/cpufreq/cpufreq_drv_ops.c  | 187 +++++++++++++++++++++++++++++++++++++
 drivers/cpufreq/cpufreq_drv_ops.h  |  50 ++++++++++
 drivers/cpufreq/cpufreq_governor.c |   4 +-
 include/linux/cpufreq.h            |   2 +-
 8 files changed, 312 insertions(+), 57 deletions(-)
 create mode 100644 drivers/cpufreq/cpufreq_drv_ops.c
 create mode 100644 drivers/cpufreq/cpufreq_drv_ops.h

diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index cbcb21e..42a1aed 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -1,7 +1,11 @@
 menu "CPU Frequency scaling"
 
+config CPUFREQ_DRV_OPS
+       bool
+
 config CPU_FREQ
        bool "CPU Frequency scaling"
+       select CPUFREQ_DRV_OPS
        help
          CPU Frequency scaling allows you to change the clock speed of 
          CPUs on the fly. This is a nice method to save power, because 
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index fadc4d4..f12a0d3 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -1,5 +1,6 @@
 # CPUfreq core
 obj-$(CONFIG_CPU_FREQ)                 += cpufreq.o
+obj-$(CONFIG_CPUFREQ_DRV_OPS)          += cpufreq_drv_ops.o
 # CPUfreq stats
 obj-$(CONFIG_CPU_FREQ_STAT)             += cpufreq_stats.o
 
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 7b0d49d..2c2a33f 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -950,7 +950,8 @@ static void __init acpi_cpufreq_boost_init(void)
        /* We create the boost file in any case, though for systems without
         * hardware support it will be read-only and hardwired to return 0.
         */
-       if (sysfs_create_file(cpufreq_global_kobject, &(global_boost.attr)))
+       if (sysfs_create_file(get_cpufreq_global_kobject(),
+                             &(global_boost.attr)))
                pr_warn(PFX "could not register global boost sysfs file\n");
        else
                pr_debug("registered global boost sysfs file\n");
@@ -958,7 +959,7 @@ static void __init acpi_cpufreq_boost_init(void)
 
 static void __exit acpi_cpufreq_boost_exit(void)
 {
-       sysfs_remove_file(cpufreq_global_kobject, &(global_boost.attr));
+       sysfs_remove_file(get_cpufreq_global_kobject(), &(global_boost.attr));
 
        if (msrs) {
                unregister_cpu_notifier(&boost_nb);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 6ed3c13..1b24bc3e 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -33,6 +33,7 @@
 #include <linux/syscore_ops.h>
 
 #include <trace/events/power.h>
+#include "cpufreq_drv_ops.h"
 
 /**
  * The "cpufreq driver" - the arch- or hardware-dependent low
@@ -178,11 +179,10 @@ err_out:
        return NULL;
 }
 
-struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
+struct cpufreq_policy *kern_cpufreq_cpu_get(unsigned int cpu)
 {
        return __cpufreq_cpu_get(cpu, false);
 }
-EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
 
 static struct cpufreq_policy *cpufreq_cpu_get_sysfs(unsigned int cpu)
 {
@@ -196,11 +196,10 @@ static void __cpufreq_cpu_put(struct cpufreq_policy 
*data, bool sysfs)
        module_put(cpufreq_driver->owner);
 }
 
-void cpufreq_cpu_put(struct cpufreq_policy *data)
+void kern_cpufreq_cpu_put(struct cpufreq_policy *data)
 {
        __cpufreq_cpu_put(data, false);
 }
-EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
 
 static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *data)
 {
@@ -258,7 +257,8 @@ static inline void adjust_jiffies(unsigned long val, struct 
cpufreq_freqs *ci)
  * function. It is called twice on all CPU frequency changes that have
  * external effects.
  */
-void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
+void kern_cpufreq_notify_transition(struct cpufreq_freqs *freqs,
+                                   unsigned int state)
 {
        struct cpufreq_policy *policy;
 
@@ -303,9 +303,6 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, 
unsigned int state)
                break;
        }
 }
-EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
-
-
 
 /*********************************************************************
  *                          SYSFS INTERFACE                          *
@@ -628,7 +625,10 @@ static struct attribute *default_attrs[] = {
 };
 
 struct kobject *cpufreq_global_kobject;
-EXPORT_SYMBOL(cpufreq_global_kobject);
+struct kobject *get_kern_cpufreq_global_kobject(void)
+{
+       return cpufreq_global_kobject;
+}
 
 #define to_policy(k) container_of(k, struct cpufreq_policy, kobj)
 #define to_attr(a) container_of(a, struct freq_attr, attr)
@@ -1214,7 +1214,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, 
unsigned int old_freq,
  * This is the last known freq, without actually getting it from the driver.
  * Return value will be same as what is shown in scaling_cur_freq in sysfs.
  */
-unsigned int cpufreq_quick_get(unsigned int cpu)
+unsigned int kern_cpufreq_quick_get(unsigned int cpu)
 {
        struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
        unsigned int ret_freq = 0;
@@ -1226,7 +1226,7 @@ unsigned int cpufreq_quick_get(unsigned int cpu)
 
        return ret_freq;
 }
-EXPORT_SYMBOL(cpufreq_quick_get);
+EXPORT_SYMBOL(kern_cpufreq_quick_get);
 
 /**
  * cpufreq_quick_get_max - get the max reported CPU frequency for this CPU
@@ -1234,7 +1234,7 @@ EXPORT_SYMBOL(cpufreq_quick_get);
  *
  * Just return the max possible frequency for a given CPU.
  */
-unsigned int cpufreq_quick_get_max(unsigned int cpu)
+unsigned int kern_cpufreq_quick_get_max(unsigned int cpu)
 {
        struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
        unsigned int ret_freq = 0;
@@ -1246,7 +1246,7 @@ unsigned int cpufreq_quick_get_max(unsigned int cpu)
 
        return ret_freq;
 }
-EXPORT_SYMBOL(cpufreq_quick_get_max);
+EXPORT_SYMBOL(kern_cpufreq_quick_get_max);
 
 
 static unsigned int __cpufreq_get(unsigned int cpu)
@@ -1278,7 +1278,7 @@ static unsigned int __cpufreq_get(unsigned int cpu)
  *
  * Get the CPU current (static) CPU frequency
  */
-unsigned int cpufreq_get(unsigned int cpu)
+unsigned int kern_cpufreq_get(unsigned int cpu)
 {
        unsigned int ret_freq = 0;
        struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
@@ -1298,7 +1298,7 @@ out_policy:
 out:
        return ret_freq;
 }
-EXPORT_SYMBOL(cpufreq_get);
+EXPORT_SYMBOL(kern_cpufreq_get);
 
 static struct subsys_interface cpufreq_interface = {
        .name           = "cpufreq",
@@ -1387,26 +1387,25 @@ static struct syscore_ops cpufreq_syscore_ops = {
 };
 
 /**
- *     cpufreq_get_current_driver - return current driver's name
+ *     kern_cpufreq_get_current_driver - return current driver's name
  *
  *     Return the name string of the currently loaded cpufreq driver
  *     or NULL, if none.
  */
-const char *cpufreq_get_current_driver(void)
+const char *kern_cpufreq_get_current_driver(void)
 {
        if (cpufreq_driver)
                return cpufreq_driver->name;
 
        return NULL;
 }
-EXPORT_SYMBOL_GPL(cpufreq_get_current_driver);
 
 /*********************************************************************
  *                     NOTIFIER LISTS INTERFACE                      *
  *********************************************************************/
 
 /**
- *     cpufreq_register_notifier - register a driver with cpufreq
+ *     kern_cpufreq_register_notifier - register a driver with cpufreq
  *     @nb: notifier function to register
  *      @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
  *
@@ -1418,7 +1417,7 @@ EXPORT_SYMBOL_GPL(cpufreq_get_current_driver);
  *     This function may sleep, and has the same return conditions as
  *     blocking_notifier_chain_register.
  */
-int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
+int kern_cpufreq_register_notifier(struct notifier_block *nb, unsigned int 
list)
 {
        int ret;
 
@@ -1439,11 +1438,11 @@ int cpufreq_register_notifier(struct notifier_block 
*nb, unsigned int list)
 
        return ret;
 }
-EXPORT_SYMBOL(cpufreq_register_notifier);
+EXPORT_SYMBOL(kern_cpufreq_register_notifier);
 
 
 /**
- *     cpufreq_unregister_notifier - unregister a driver with cpufreq
+ *     kern_cpufreq_unregister_notifier - unregister a driver with cpufreq
  *     @nb: notifier block to be unregistered
  *      @list: CPUFREQ_TRANSITION_NOTIFIER or CPUFREQ_POLICY_NOTIFIER
  *
@@ -1452,7 +1451,8 @@ EXPORT_SYMBOL(cpufreq_register_notifier);
  *     This function may sleep, and has the same return conditions as
  *     blocking_notifier_chain_unregister.
  */
-int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
+int kern_cpufreq_unregister_notifier(struct notifier_block *nb,
+                                    unsigned int list)
 {
        int ret;
 
@@ -1471,7 +1471,7 @@ int cpufreq_unregister_notifier(struct notifier_block 
*nb, unsigned int list)
 
        return ret;
 }
-EXPORT_SYMBOL(cpufreq_unregister_notifier);
+EXPORT_SYMBOL(kern_cpufreq_unregister_notifier);
 
 
 /*********************************************************************
@@ -1479,7 +1479,7 @@ EXPORT_SYMBOL(cpufreq_unregister_notifier);
  *********************************************************************/
 
 
-int __cpufreq_driver_target(struct cpufreq_policy *policy,
+int __kern_cpufreq_driver_target(struct cpufreq_policy *policy,
                            unsigned int target_freq,
                            unsigned int relation)
 {
@@ -1506,9 +1506,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
 
        return retval;
 }
-EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
 
-int cpufreq_driver_target(struct cpufreq_policy *policy,
+int kern_cpufreq_driver_target(struct cpufreq_policy *policy,
                          unsigned int target_freq,
                          unsigned int relation)
 {
@@ -1530,9 +1529,9 @@ fail:
 no_policy:
        return ret;
 }
-EXPORT_SYMBOL_GPL(cpufreq_driver_target);
 
-int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
+int __kern_cpufreq_driver_getavg(struct cpufreq_policy *policy,
+                                unsigned int cpu)
 {
        int ret = 0;
 
@@ -1548,7 +1547,6 @@ int __cpufreq_driver_getavg(struct cpufreq_policy 
*policy, unsigned int cpu)
        cpufreq_cpu_put(policy);
        return ret;
 }
-EXPORT_SYMBOL_GPL(__cpufreq_driver_getavg);
 
 /*
  * when "event" is CPUFREQ_GOV_LIMITS
@@ -1602,7 +1600,7 @@ static int __cpufreq_governor(struct cpufreq_policy 
*policy,
 }
 
 
-int cpufreq_register_governor(struct cpufreq_governor *governor)
+int kern_cpufreq_register_governor(struct cpufreq_governor *governor)
 {
        int err;
 
@@ -1623,10 +1621,8 @@ int cpufreq_register_governor(struct cpufreq_governor 
*governor)
        mutex_unlock(&cpufreq_governor_mutex);
        return err;
 }
-EXPORT_SYMBOL_GPL(cpufreq_register_governor);
-
 
-void cpufreq_unregister_governor(struct cpufreq_governor *governor)
+void kern_cpufreq_unregister_governor(struct cpufreq_governor *governor)
 {
 #ifdef CONFIG_HOTPLUG_CPU
        int cpu;
@@ -1652,22 +1648,19 @@ void cpufreq_unregister_governor(struct 
cpufreq_governor *governor)
        mutex_unlock(&cpufreq_governor_mutex);
        return;
 }
-EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
-
-
 
 /*********************************************************************
  *                          POLICY INTERFACE                         *
  *********************************************************************/
 
 /**
- * cpufreq_get_policy - get the current cpufreq_policy
+ * kern_cpufreq_get_policy - get the current cpufreq_policy
  * @policy: struct cpufreq_policy into which the current cpufreq_policy
  *     is written
  *
  * Reads the current cpufreq policy.
  */
-int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
+int kern_cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
 {
        struct cpufreq_policy *cpu_policy;
        if (!policy)
@@ -1682,7 +1675,7 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, 
unsigned int cpu)
        cpufreq_cpu_put(cpu_policy);
        return 0;
 }
-EXPORT_SYMBOL(cpufreq_get_policy);
+EXPORT_SYMBOL(kern_cpufreq_get_policy);
 
 
 /*
@@ -1774,13 +1767,13 @@ error_out:
 }
 
 /**
- *     cpufreq_update_policy - re-evaluate an existing cpufreq policy
+ *     kern_cpufreq_update_policy - re-evaluate an existing cpufreq policy
  *     @cpu: CPU which shall be re-evaluated
  *
  *     Useful for policy notifiers which have different necessities
  *     at different times.
  */
-int cpufreq_update_policy(unsigned int cpu)
+int kern_cpufreq_update_policy(unsigned int cpu)
 {
        struct cpufreq_policy *data = cpufreq_cpu_get(cpu);
        struct cpufreq_policy policy;
@@ -1826,7 +1819,7 @@ fail:
 no_policy:
        return ret;
 }
-EXPORT_SYMBOL(cpufreq_update_policy);
+EXPORT_SYMBOL(kern_cpufreq_update_policy);
 
 static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb,
                                        unsigned long action, void *hcpu)
@@ -1866,7 +1859,7 @@ static struct notifier_block __refdata 
cpufreq_cpu_notifier = {
  *********************************************************************/
 
 /**
- * cpufreq_register_driver - register a CPU Frequency driver
+ * kern_cpufreq_register_driver - register a CPU Frequency driver
  * @driver_data: A struct cpufreq_driver containing the values#
  * submitted by the CPU Frequency driver.
  *
@@ -1875,7 +1868,7 @@ static struct notifier_block __refdata 
cpufreq_cpu_notifier = {
  * (and isn't unregistered in the meantime).
  *
  */
-int cpufreq_register_driver(struct cpufreq_driver *driver_data)
+int kern_cpufreq_register_driver(struct cpufreq_driver *driver_data)
 {
        unsigned long flags;
        int ret;
@@ -1935,18 +1928,16 @@ err_null_driver:
        spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
        return ret;
 }
-EXPORT_SYMBOL_GPL(cpufreq_register_driver);
-
 
 /**
- * cpufreq_unregister_driver - unregister the current CPUFreq driver
+ * kern_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_driver(struct cpufreq_driver *driver)
+int kern_cpufreq_unregister_driver(struct cpufreq_driver *driver)
 {
        unsigned long flags;
 
@@ -1964,9 +1955,30 @@ int cpufreq_unregister_driver(struct cpufreq_driver 
*driver)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
 
-static int __init cpufreq_core_init(void)
+struct cpufreq_drv_ops kern_cpufreq_drv_ops = {
+       .get_global_kobject = get_kern_cpufreq_global_kobject,
+       .cpu_get = kern_cpufreq_cpu_get,
+       .cpu_put = kern_cpufreq_cpu_put,
+       .notify_transition = kern_cpufreq_notify_transition,
+       .quick_get = kern_cpufreq_quick_get,
+       .quick_get_max = kern_cpufreq_quick_get_max,
+       .get = kern_cpufreq_get,
+       .register_notifier = kern_cpufreq_register_notifier,
+       .unregister_notifier = kern_cpufreq_unregister_notifier,
+       .get_current_driver = kern_cpufreq_get_current_driver,
+       .__driver_target = __kern_cpufreq_driver_target,
+       .driver_target = kern_cpufreq_driver_target,
+       .__driver_getavg = __kern_cpufreq_driver_getavg,
+       .register_governor = kern_cpufreq_register_governor,
+       .unregister_governor = kern_cpufreq_unregister_governor,
+       .get_policy = kern_cpufreq_get_policy,
+       .update_policy = kern_cpufreq_update_policy,
+       .register_driver = kern_cpufreq_register_driver,
+       .unregister_driver = kern_cpufreq_unregister_driver,
+};
+
+static int __init kern_cpufreq_core_init(void)
 {
        int cpu;
 
@@ -1984,4 +1996,4 @@ static int __init cpufreq_core_init(void)
 
        return 0;
 }
-core_initcall(cpufreq_core_init);
+core_initcall(kern_cpufreq_core_init);
diff --git a/drivers/cpufreq/cpufreq_drv_ops.c 
b/drivers/cpufreq/cpufreq_drv_ops.c
new file mode 100644
index 0000000..c971442
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_drv_ops.c
@@ -0,0 +1,187 @@
+/*
+ *  Copyright (C) 2014 GlobalLogic Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "cpufreq_drv_ops.h"
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/export.h>
+
+static struct cpufreq_drv_ops *ops;
+
+struct kobject *get_cpufreq_global_kobject(void)
+{
+       if (ops && ops->get_global_kobject)
+               return ops->get_global_kobject();
+       return NULL;
+}
+EXPORT_SYMBOL(get_cpufreq_global_kobject);
+
+struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
+{
+       if (ops && ops->cpu_get)
+               return ops->cpu_get(cpu);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
+
+void cpufreq_cpu_put(struct cpufreq_policy *data)
+{
+       if (ops && ops->cpu_put)
+               ops->cpu_put(data);
+}
+EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
+
+void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
+{
+       if (ops && ops->notify_transition)
+               ops->notify_transition(freqs, state);
+}
+EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
+
+#ifdef CONFIG_CPU_FREQ
+unsigned int cpufreq_quick_get(unsigned int cpu)
+{
+       if (ops && ops->quick_get)
+               return ops->quick_get(cpu);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL(cpufreq_quick_get);
+
+unsigned int cpufreq_quick_get_max(unsigned int cpu)
+{
+       if (ops && ops->quick_get_max)
+               return ops->quick_get_max(cpu);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL(cpufreq_quick_get_max);
+
+unsigned int cpufreq_get(unsigned int cpu)
+{
+       if (ops && ops->get)
+               return ops->get(cpu);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL(cpufreq_get);
+
+int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list)
+{
+       if (ops && ops->register_notifier)
+               return ops->register_notifier(nb, list);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL(cpufreq_register_notifier);
+
+int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list)
+{
+       if (ops && ops->unregister_notifier)
+               return ops->unregister_notifier(nb, list);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL(cpufreq_unregister_notifier);
+#endif
+
+const char *cpufreq_get_current_driver(void)
+{
+       if (ops && ops->get_current_driver)
+               return ops->get_current_driver();
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(cpufreq_get_current_driver);
+
+int __cpufreq_driver_target(struct cpufreq_policy *policy,
+                           unsigned int target_freq,
+                           unsigned int relation)
+{
+       if (ops && ops->__driver_target)
+               return ops->__driver_target(policy, target_freq, relation);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(__cpufreq_driver_target);
+
+int cpufreq_driver_target(struct cpufreq_policy *policy,
+                         unsigned int target_freq,
+                         unsigned int relation)
+{
+       if (ops && ops->driver_target)
+               return ops->driver_target(policy, target_freq, relation);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(cpufreq_driver_target);
+
+int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu)
+{
+       if (ops && ops->__driver_getavg)
+               return ops->__driver_getavg(policy, cpu);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(__cpufreq_driver_getavg);
+
+int cpufreq_register_governor(struct cpufreq_governor *governor)
+{
+       if (ops && ops->register_governor)
+               return ops->register_governor(governor);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(cpufreq_register_governor);
+
+void cpufreq_unregister_governor(struct cpufreq_governor *governor)
+{
+       if (ops && ops->unregister_governor)
+               ops->unregister_governor(governor);
+}
+EXPORT_SYMBOL_GPL(cpufreq_unregister_governor);
+
+int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
+{
+       if (ops && ops->get_policy)
+               return ops->get_policy(policy, cpu);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL(cpufreq_get_policy);
+
+int cpufreq_update_policy(unsigned int cpu)
+{
+       if (ops && ops->update_policy)
+               return ops->update_policy(cpu);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL(cpufreq_update_policy);
+
+int cpufreq_register_driver(struct cpufreq_driver *driver_data)
+{
+       if (ops && ops->register_driver)
+               return ops->register_driver(driver_data);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(cpufreq_register_driver);
+
+int cpufreq_unregister_driver(struct cpufreq_driver *driver)
+{
+       if (ops && ops->unregister_driver)
+               return ops->unregister_driver(driver);
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(cpufreq_unregister_driver);
+
+static int __init cpufreq_drv_ops_init(void)
+{
+#ifdef CONFIG_CPU_FREQ
+       ops = &kern_cpufreq_drv_ops;
+       pr_debug("using kern_cpufreq_drv_ops\n");
+#endif
+
+       return 0;
+}
+core_initcall(cpufreq_drv_ops_init);
diff --git a/drivers/cpufreq/cpufreq_drv_ops.h 
b/drivers/cpufreq/cpufreq_drv_ops.h
new file mode 100644
index 0000000..5cc8e05
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_drv_ops.h
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (C) 2014 GlobalLogic Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#ifndef _CPUFREQ_DRV_OPS_H
+#define _CPUFREQ_DRV_OPS_H
+
+#include <linux/types.h>
+#include <linux/cpufreq.h>
+
+struct cpufreq_drv_ops {
+       struct kobject *(*get_global_kobject)(void);
+       struct cpufreq_policy *(*cpu_get)(unsigned int);
+       void (*cpu_put)(struct cpufreq_policy *);
+       void (*notify_transition)(struct cpufreq_freqs *, unsigned int);
+#ifdef CONFIG_CPU_FREQ
+       unsigned int (*quick_get)(unsigned int);
+       unsigned int (*quick_get_max)(unsigned int);
+       unsigned int (*get)(unsigned int);
+       int (*register_notifier)(struct notifier_block *, unsigned int);
+       int (*unregister_notifier)(struct notifier_block *, unsigned int);
+#endif
+       const char *(*get_current_driver)(void);
+       int (*__driver_target)(struct cpufreq_policy *,
+                              unsigned int, unsigned int);
+       int (*driver_target)(struct cpufreq_policy *,
+                            unsigned int, unsigned int);
+       int (*__driver_getavg)(struct cpufreq_policy *, unsigned int);
+       int (*register_governor)(struct cpufreq_governor *);
+       void (*unregister_governor)(struct cpufreq_governor *);
+       int (*get_policy)(struct cpufreq_policy *, unsigned int);
+       int (*update_policy)(unsigned int);
+       int (*register_driver)(struct cpufreq_driver *);
+       int (*unregister_driver)(struct cpufreq_driver *);
+};
+
+#ifdef CONFIG_CPU_FREQ
+extern struct cpufreq_drv_ops kern_cpufreq_drv_ops;
+#endif
+
+#endif /* _CPUFREQ_DRV_OPS_H */
diff --git a/drivers/cpufreq/cpufreq_governor.c 
b/drivers/cpufreq/cpufreq_governor.c
index 6c5f1d3..731fa0d 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -226,7 +226,7 @@ int cpufreq_governor_dbs(struct dbs_data *dbs_data,
                if (dbs_data->enable != 1)
                        goto second_time;
 
-               rc = sysfs_create_group(cpufreq_global_kobject,
+               rc = sysfs_create_group(get_cpufreq_global_kobject(),
                                dbs_data->attr_group);
                if (rc) {
                        mutex_unlock(&dbs_data->mutex);
@@ -291,7 +291,7 @@ second_time:
                if (!dbs_data->enable) {
                        struct cs_ops *ops = dbs_data->gov_ops;
 
-                       sysfs_remove_group(cpufreq_global_kobject,
+                       sysfs_remove_group(get_cpufreq_global_kobject(),
                                        dbs_data->attr_group);
                        if (dbs_data->governor == GOV_CONSERVATIVE)
                                cpufreq_unregister_notifier(ops->notifier_block,
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 3d919ea..2852bb23 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -70,7 +70,7 @@ static inline void disable_cpufreq(void) { }
 struct cpufreq_governor;
 
 /* /sys/devices/system/cpu/cpufreq: entry point for global variables */
-extern struct kobject *cpufreq_global_kobject;
+struct kobject *get_cpufreq_global_kobject(void);
 
 #define CPUFREQ_ETERNAL                        (-1)
 struct cpufreq_cpuinfo {
-- 
1.9.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.