Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 
0003 /*
0004  *  linux/drivers/cpufreq/cpufreq_userspace.c
0005  *
0006  *  Copyright (C)  2001 Russell King
0007  *            (C)  2002 - 2004 Dominik Brodowski <linux@brodo.de>
0008  */
0009 
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011 
0012 #include <linux/cpufreq.h>
0013 #include <linux/init.h>
0014 #include <linux/module.h>
0015 #include <linux/mutex.h>
0016 #include <linux/slab.h>
0017 
0018 static DEFINE_PER_CPU(unsigned int, cpu_is_managed);
0019 static DEFINE_MUTEX(userspace_mutex);
0020 
0021 /**
0022  * cpufreq_set - set the CPU frequency
0023  * @policy: pointer to policy struct where freq is being set
0024  * @freq: target frequency in kHz
0025  *
0026  * Sets the CPU frequency to freq.
0027  */
0028 static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq)
0029 {
0030     int ret = -EINVAL;
0031     unsigned int *setspeed = policy->governor_data;
0032 
0033     pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq);
0034 
0035     mutex_lock(&userspace_mutex);
0036     if (!per_cpu(cpu_is_managed, policy->cpu))
0037         goto err;
0038 
0039     *setspeed = freq;
0040 
0041     ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L);
0042  err:
0043     mutex_unlock(&userspace_mutex);
0044     return ret;
0045 }
0046 
0047 static ssize_t show_speed(struct cpufreq_policy *policy, char *buf)
0048 {
0049     return sprintf(buf, "%u\n", policy->cur);
0050 }
0051 
0052 static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy)
0053 {
0054     unsigned int *setspeed;
0055 
0056     setspeed = kzalloc(sizeof(*setspeed), GFP_KERNEL);
0057     if (!setspeed)
0058         return -ENOMEM;
0059 
0060     policy->governor_data = setspeed;
0061     return 0;
0062 }
0063 
0064 static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy)
0065 {
0066     mutex_lock(&userspace_mutex);
0067     kfree(policy->governor_data);
0068     policy->governor_data = NULL;
0069     mutex_unlock(&userspace_mutex);
0070 }
0071 
0072 static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy)
0073 {
0074     unsigned int *setspeed = policy->governor_data;
0075 
0076     BUG_ON(!policy->cur);
0077     pr_debug("started managing cpu %u\n", policy->cpu);
0078 
0079     mutex_lock(&userspace_mutex);
0080     per_cpu(cpu_is_managed, policy->cpu) = 1;
0081     *setspeed = policy->cur;
0082     mutex_unlock(&userspace_mutex);
0083     return 0;
0084 }
0085 
0086 static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy)
0087 {
0088     unsigned int *setspeed = policy->governor_data;
0089 
0090     pr_debug("managing cpu %u stopped\n", policy->cpu);
0091 
0092     mutex_lock(&userspace_mutex);
0093     per_cpu(cpu_is_managed, policy->cpu) = 0;
0094     *setspeed = 0;
0095     mutex_unlock(&userspace_mutex);
0096 }
0097 
0098 static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy)
0099 {
0100     unsigned int *setspeed = policy->governor_data;
0101 
0102     mutex_lock(&userspace_mutex);
0103 
0104     pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n",
0105          policy->cpu, policy->min, policy->max, policy->cur, *setspeed);
0106 
0107     if (policy->max < *setspeed)
0108         __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H);
0109     else if (policy->min > *setspeed)
0110         __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L);
0111     else
0112         __cpufreq_driver_target(policy, *setspeed, CPUFREQ_RELATION_L);
0113 
0114     mutex_unlock(&userspace_mutex);
0115 }
0116 
0117 static struct cpufreq_governor cpufreq_gov_userspace = {
0118     .name       = "userspace",
0119     .init       = cpufreq_userspace_policy_init,
0120     .exit       = cpufreq_userspace_policy_exit,
0121     .start      = cpufreq_userspace_policy_start,
0122     .stop       = cpufreq_userspace_policy_stop,
0123     .limits     = cpufreq_userspace_policy_limits,
0124     .store_setspeed = cpufreq_set,
0125     .show_setspeed  = show_speed,
0126     .owner      = THIS_MODULE,
0127 };
0128 
0129 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>, "
0130         "Russell King <rmk@arm.linux.org.uk>");
0131 MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'");
0132 MODULE_LICENSE("GPL");
0133 
0134 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE
0135 struct cpufreq_governor *cpufreq_default_governor(void)
0136 {
0137     return &cpufreq_gov_userspace;
0138 }
0139 #endif
0140 
0141 cpufreq_governor_init(cpufreq_gov_userspace);
0142 cpufreq_governor_exit(cpufreq_gov_userspace);