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 struct userspace_policy { 19 unsigned int is_managed; 20 unsigned int setspeed; 21 struct mutex mutex; 22 }; 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 */ 31 static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq) 32 { 33 int ret = -EINVAL; 34 struct userspace_policy *userspace = policy->governor_data; 35 36 pr_debug("cpufreq_set for cpu %u, freq %u kHz\n", policy->cpu, freq); 37 38 mutex_lock(&userspace->mutex); 39 if (!userspace->is_managed) 40 goto err; 41 42 userspace->setspeed = freq; 43 44 ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); 45 err: 46 mutex_unlock(&userspace->mutex); 47 return ret; 48 } 49 50 static ssize_t show_speed(struct cpufreq_policy *policy, char *buf) 51 { 52 return sprintf(buf, "%u\n", policy->cur); 53 } 54 55 static int cpufreq_userspace_policy_init(struct cpufreq_policy *policy) 56 { 57 struct userspace_policy *userspace; 58 59 userspace = kzalloc(sizeof(*userspace), GFP_KERNEL); 60 if (!userspace) 61 return -ENOMEM; 62 63 mutex_init(&userspace->mutex); 64 65 policy->governor_data = userspace; 66 return 0; 67 } 68 69 /* 70 * Any routine that writes to the policy struct will hold the "rwsem" of 71 * policy struct that means it is free to free "governor_data" here. 72 */ 73 static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy) 74 { 75 kfree(policy->governor_data); 76 policy->governor_data = NULL; 77 } 78 79 static int cpufreq_userspace_policy_start(struct cpufreq_policy *policy) 80 { 81 struct userspace_policy *userspace = policy->governor_data; 82 83 BUG_ON(!policy->cur); 84 pr_debug("started managing cpu %u\n", policy->cpu); 85 86 mutex_lock(&userspace->mutex); 87 userspace->is_managed = 1; 88 userspace->setspeed = policy->cur; 89 mutex_unlock(&userspace->mutex); 90 return 0; 91 } 92 93 static void cpufreq_userspace_policy_stop(struct cpufreq_policy *policy) 94 { 95 struct userspace_policy *userspace = policy->governor_data; 96 97 pr_debug("managing cpu %u stopped\n", policy->cpu); 98 99 mutex_lock(&userspace->mutex); 100 userspace->is_managed = 0; 101 userspace->setspeed = 0; 102 mutex_unlock(&userspace->mutex); 103 } 104 105 static void cpufreq_userspace_policy_limits(struct cpufreq_policy *policy) 106 { 107 struct userspace_policy *userspace = policy->governor_data; 108 109 mutex_lock(&userspace->mutex); 110 111 pr_debug("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n", 112 policy->cpu, policy->min, policy->max, policy->cur, userspace->setspeed); 113 114 if (policy->max < userspace->setspeed) 115 __cpufreq_driver_target(policy, policy->max, 116 CPUFREQ_RELATION_H); 117 else if (policy->min > userspace->setspeed) 118 __cpufreq_driver_target(policy, policy->min, 119 CPUFREQ_RELATION_L); 120 else 121 __cpufreq_driver_target(policy, userspace->setspeed, 122 CPUFREQ_RELATION_L); 123 124 mutex_unlock(&userspace->mutex); 125 } 126 127 static struct cpufreq_governor cpufreq_gov_userspace = { 128 .name = "userspace", 129 .init = cpufreq_userspace_policy_init, 130 .exit = cpufreq_userspace_policy_exit, 131 .start = cpufreq_userspace_policy_start, 132 .stop = cpufreq_userspace_policy_stop, 133 .limits = cpufreq_userspace_policy_limits, 134 .store_setspeed = cpufreq_set, 135 .show_setspeed = show_speed, 136 .owner = THIS_MODULE, 137 }; 138 139 MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>, " 140 "Russell King <rmk@arm.linux.org.uk>"); 141 MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'"); 142 MODULE_LICENSE("GPL"); 143 144 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE 145 struct cpufreq_governor *cpufreq_default_governor(void) 146 { 147 return &cpufreq_gov_userspace; 148 } 149 #endif 150 151 cpufreq_governor_init(cpufreq_gov_userspace); 152 cpufreq_governor_exit(cpufreq_gov_userspace); 153