linux/drivers/cpufreq/cpufreq_userspace.c
<<
>>
Prefs
   1
   2/*
   3 *  linux/drivers/cpufreq/cpufreq_userspace.c
   4 *
   5 *  Copyright (C)  2001 Russell King
   6 *            (C)  2002 - 2004 Dominik Brodowski <linux@brodo.de>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 *
  12 */
  13
  14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  15
  16#include <linux/cpufreq.h>
  17#include <linux/init.h>
  18#include <linux/module.h>
  19#include <linux/mutex.h>
  20
  21static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
  22static DEFINE_MUTEX(userspace_mutex);
  23
  24/**
  25 * cpufreq_set - set the CPU frequency
  26 * @policy: pointer to policy struct where freq is being set
  27 * @freq: target frequency in kHz
  28 *
  29 * Sets the CPU frequency to freq.
  30 */
  31static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
  32{
  33        int ret = -EINVAL;
  34
  35        pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
  36
  37        mutex_lock(&userspace_mutex);
  38        if (!per_cpu(cpu_is_managed, policy->cpu))
  39                goto err;
  40
  41        /*
  42         * We're safe from concurrent calls to ->target() here
  43         * as we hold the userspace_mutex lock. If we were calling
  44         * cpufreq_driver_target, a deadlock situation might occur:
  45         * A: cpufreq_set (lock userspace_mutex) ->
  46         *      cpufreq_driver_target(lock policy->lock)
  47         * B: cpufreq_set_policy(lock policy->lock) ->
  48         *      __cpufreq_governor ->
  49         *         cpufreq_governor_userspace (lock userspace_mutex)
  50         */
  51        ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
  52
  53 err:
  54        mutex_unlock(&userspace_mutex);
  55        return ret;
  56}
  57
  58static ssize_t show_speed(struct cpufreq_policy *policy, char *buf)
  59{
  60        return sprintf(buf, "%u\n", policy->cur);
  61}
  62
  63static int cpufreq_governor_userspace(struct cpufreq_policy *policy,
  64                                   unsigned int event)
  65{
  66        unsigned int cpu = policy->cpu;
  67        int rc = 0;
  68
  69        switch (event) {
  70        case CPUFREQ_GOV_START:
  71                BUG_ON(!policy->cur);
  72                pr_debug("started managing cpu %u\n", cpu);
  73
  74                mutex_lock(&userspace_mutex);
  75                per_cpu(cpu_is_managed, cpu) = 1;
  76                mutex_unlock(&userspace_mutex);
  77                break;
  78        case CPUFREQ_GOV_STOP:
  79                pr_debug("managing cpu %u stopped\n", cpu);
  80
  81                mutex_lock(&userspace_mutex);
  82                per_cpu(cpu_is_managed, cpu) = 0;
  83                mutex_unlock(&userspace_mutex);
  84                break;
  85        case CPUFREQ_GOV_LIMITS:
  86                mutex_lock(&userspace_mutex);
  87                pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz\n",
  88                        cpu, policy->min, policy->max,
  89                        policy->cur);
  90
  91                if (policy->max < policy->cur)
  92                        __cpufreq_driver_target(policy, policy->max,
  93                                                CPUFREQ_RELATION_H);
  94                else if (policy->min > policy->cur)
  95                        __cpufreq_driver_target(policy, policy->min,
  96                                                CPUFREQ_RELATION_L);
  97                mutex_unlock(&userspace_mutex);
  98                break;
  99        }
 100        return rc;
 101}
 102
 103#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
 104static
 105#endif
 106struct cpufreq_governor cpufreq_gov_userspace = {
 107        .name           = "userspace",
 108        .governor       = cpufreq_governor_userspace,
 109        .store_setspeed = cpufreq_set,
 110        .show_setspeed  = show_speed,
 111        .owner          = THIS_MODULE,
 112};
 113
 114static int __init cpufreq_gov_userspace_init(void)
 115{
 116        return cpufreq_register_governor(&cpufreq_gov_userspace);
 117}
 118
 119static void __exit cpufreq_gov_userspace_exit(void)
 120{
 121        cpufreq_unregister_governor(&cpufreq_gov_userspace);
 122}
 123
 124MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>, "
 125                "Russell King <rmk@arm.linux.org.uk>");
 126MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'");
 127MODULE_LICENSE("GPL");
 128
 129#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
 130fs_initcall(cpufreq_gov_userspace_init);
 131#else
 132module_init(cpufreq_gov_userspace_init);
 133#endif
 134module_exit(cpufreq_gov_userspace_exit);
 135
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.