brintos

brintos / linux-shallow public Read only

0
0
Text · 3.9 KiB · 2c42fee Raw
153 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 3/*4 *  linux/drivers/cpufreq/cpufreq_userspace.c5 *6 *  Copyright (C)  2001 Russell King7 *            (C)  2002 - 2004 Dominik Brodowski <linux@brodo.de>8 */9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11 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 18struct userspace_policy {19	unsigned int is_managed;20	unsigned int setspeed;21	struct mutex mutex;22};23 24/**25 * cpufreq_set - set the CPU frequency26 * @policy: pointer to policy struct where freq is being set27 * @freq: target frequency in kHz28 *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	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 50static ssize_t show_speed(struct cpufreq_policy *policy, char *buf)51{52	return sprintf(buf, "%u\n", policy->cur);53}54 55static 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" of71 * policy struct that means it is free to free "governor_data" here.72 */73static void cpufreq_userspace_policy_exit(struct cpufreq_policy *policy)74{75	kfree(policy->governor_data);76	policy->governor_data = NULL;77}78 79static 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 93static 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 105static 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	else121		__cpufreq_driver_target(policy, userspace->setspeed,122					CPUFREQ_RELATION_L);123 124	mutex_unlock(&userspace->mutex);125}126 127static 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 139MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>, "140		"Russell King <rmk@arm.linux.org.uk>");141MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'");142MODULE_LICENSE("GPL");143 144#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE145struct cpufreq_governor *cpufreq_default_governor(void)146{147	return &cpufreq_gov_userspace;148}149#endif150 151cpufreq_governor_init(cpufreq_gov_userspace);152cpufreq_governor_exit(cpufreq_gov_userspace);153