1 // SPDX-License-Identifier: GPL-2.0-only 2 3 /* 4 * linux/drivers/cpufreq/cpufreq_userspace.c 5 * 6 * Copyright (C) 2001 Russell King 7 * (C) 2002 - 2004 Dominik Brodowski <linux@brodo.de> 8 */ 9 10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 12 #include <linux/cpufreq.h> 13 #include <linux/init.h> 14 #include <linux/module.h> 15 #include <linux/mutex.h> 16 #include <linux/slab.h> 17 18 static DEFINE_PER_CPU(unsigned int, cpu_is_managed); 19 static DEFINE_MUTEX(userspace_mutex); 20 21 /** 22 * cpufreq_set - set the CPU frequency 23 * @policy: pointer to policy struct where freq is being set 24 * @freq: target frequency in kHz 25 * 26 * Sets the CPU frequency to freq. 27 */ 28 static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq) 29 { 30 int ret = -EINVAL; 31 unsigned int *setspeed = policy->governor_data; 32 33 pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq); 34 35 mutex_lock(&userspace_mutex); 36 if (!per_cpu(cpu_is_managed, policy->cpu)) 37 goto err; 38 39 *setspeed = freq; 40 41 ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); 42 err: 43 mutex_unlock(&userspace_mutex); 44 return ret; 45 } 46 47 static ssize_t show_speed(struct cpufreq_policy *policy, char *buf) 48 { 49 return sprintf(buf, "%u\n", policy->cur); 50 } 51 52 static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy) 53 { 54 unsigned int *setspeed; 55 56 setspeed = kzalloc(sizeof(*setspeed), GFP_KERNEL); 57 if (!setspeed) 58 return -ENOMEM; 59 60 policy->governor_data = setspeed; 61 return 0; 62 } 63 64 static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy) 65 { 66 mutex_lock(&userspace_mutex); 67 kfree(policy->governor_data); 68 policy->governor_data = NULL; 69 mutex_unlock(&userspace_mutex); 70 } 71 72 static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy) 73 { 74 unsigned int *setspeed = policy->governor_data; 75 76 BUG_ON(!policy->cur); 77 pr_debug("started managing cpu %u\n", policy->cpu); 78 79 mutex_lock(&userspace_mutex); 80 per_cpu(cpu_is_managed, policy->cpu) = 1; 81 *setspeed = policy->cur; 82 mutex_unlock(&userspace_mutex); 83 return 0; 84 } 85 86 static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy) 87 { 88 unsigned int *setspeed = policy->governor_data; 89 90 pr_debug("managing cpu %u stopped\n", policy->cpu); 91 92 mutex_lock(&userspace_mutex); 93 per_cpu(cpu_is_managed, policy->cpu) = 0; 94 *setspeed = 0; 95 mutex_unlock(&userspace_mutex); 96 } 97 98 static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy) 99 { 100 unsigned int *setspeed = policy->governor_data; 101 102 mutex_lock(&userspace_mutex); 103 104 pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", 105 policy->cpu, policy->min, policy->max, policy->cur, *setspeed); 106 107 if (policy->max < *setspeed) 108 __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); 109 else if (policy->min > *setspeed) 110 __cpufreq_driver_target(policy, policy->min, CPUFREQ_RELATION_L); 111 else 112 __cpufreq_driver_target(policy, *setspeed, CPUFREQ_RELATION_L); 113 114 mutex_unlock(&userspace_mutex); 115 } 116 117 static struct cpufreq_governor cpufreq_gov_userspace = { 118 .name = "userspace", 119 .init = cpufreq_userspace_policy_init, 120 .exit = cpufreq_userspace_policy_exit, 121 .start = cpufreq_userspace_policy_start, 122 .stop = cpufreq_userspace_policy_stop, 123 .limits = cpufreq_userspace_policy_limits, 124 .store_setspeed = cpufreq_set, 125 .show_setspeed = show_speed, 126 .owner = THIS_MODULE, 127 }; 128 129 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>, " 130 "Russell King <rmk@arm.linux.org.uk>"); 131 MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'"); 132 MODULE_LICENSE("GPL"); 133 134 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE 135 struct cpufreq_governor *cpufreq_default_governor(void) 136 { 137 return &cpufreq_gov_userspace; 138 } 139 #endif 140 141 cpufreq_governor_init(cpufreq_gov_userspace); 142 cpufreq_governor_exit(cpufreq_gov_userspace); 143