cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

governor_userspace.c (3339B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  linux/drivers/devfreq/governor_userspace.c
      4 *
      5 *  Copyright (C) 2011 Samsung Electronics
      6 *	MyungJoo Ham <myungjoo.ham@samsung.com>
      7 */
      8
      9#include <linux/slab.h>
     10#include <linux/device.h>
     11#include <linux/devfreq.h>
     12#include <linux/pm.h>
     13#include <linux/mutex.h>
     14#include <linux/module.h>
     15#include "governor.h"
     16
     17struct userspace_data {
     18	unsigned long user_frequency;
     19	bool valid;
     20};
     21
     22static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq)
     23{
     24	struct userspace_data *data = df->data;
     25
     26	if (data->valid)
     27		*freq = data->user_frequency;
     28	else
     29		*freq = df->previous_freq; /* No user freq specified yet */
     30
     31	return 0;
     32}
     33
     34static ssize_t set_freq_store(struct device *dev, struct device_attribute *attr,
     35			      const char *buf, size_t count)
     36{
     37	struct devfreq *devfreq = to_devfreq(dev);
     38	struct userspace_data *data;
     39	unsigned long wanted;
     40	int err = 0;
     41
     42	mutex_lock(&devfreq->lock);
     43	data = devfreq->data;
     44
     45	sscanf(buf, "%lu", &wanted);
     46	data->user_frequency = wanted;
     47	data->valid = true;
     48	err = update_devfreq(devfreq);
     49	if (err == 0)
     50		err = count;
     51	mutex_unlock(&devfreq->lock);
     52	return err;
     53}
     54
     55static ssize_t set_freq_show(struct device *dev,
     56			     struct device_attribute *attr, char *buf)
     57{
     58	struct devfreq *devfreq = to_devfreq(dev);
     59	struct userspace_data *data;
     60	int err = 0;
     61
     62	mutex_lock(&devfreq->lock);
     63	data = devfreq->data;
     64
     65	if (data->valid)
     66		err = sprintf(buf, "%lu\n", data->user_frequency);
     67	else
     68		err = sprintf(buf, "undefined\n");
     69	mutex_unlock(&devfreq->lock);
     70	return err;
     71}
     72
     73static DEVICE_ATTR_RW(set_freq);
     74static struct attribute *dev_entries[] = {
     75	&dev_attr_set_freq.attr,
     76	NULL,
     77};
     78static const struct attribute_group dev_attr_group = {
     79	.name	= DEVFREQ_GOV_USERSPACE,
     80	.attrs	= dev_entries,
     81};
     82
     83static int userspace_init(struct devfreq *devfreq)
     84{
     85	int err = 0;
     86	struct userspace_data *data = kzalloc(sizeof(struct userspace_data),
     87					      GFP_KERNEL);
     88
     89	if (!data) {
     90		err = -ENOMEM;
     91		goto out;
     92	}
     93	data->valid = false;
     94	devfreq->data = data;
     95
     96	err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group);
     97out:
     98	return err;
     99}
    100
    101static void userspace_exit(struct devfreq *devfreq)
    102{
    103	/*
    104	 * Remove the sysfs entry, unless this is being called after
    105	 * device_del(), which should have done this already via kobject_del().
    106	 */
    107	if (devfreq->dev.kobj.sd)
    108		sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group);
    109
    110	kfree(devfreq->data);
    111	devfreq->data = NULL;
    112}
    113
    114static int devfreq_userspace_handler(struct devfreq *devfreq,
    115			unsigned int event, void *data)
    116{
    117	int ret = 0;
    118
    119	switch (event) {
    120	case DEVFREQ_GOV_START:
    121		ret = userspace_init(devfreq);
    122		break;
    123	case DEVFREQ_GOV_STOP:
    124		userspace_exit(devfreq);
    125		break;
    126	default:
    127		break;
    128	}
    129
    130	return ret;
    131}
    132
    133static struct devfreq_governor devfreq_userspace = {
    134	.name = DEVFREQ_GOV_USERSPACE,
    135	.get_target_freq = devfreq_userspace_func,
    136	.event_handler = devfreq_userspace_handler,
    137};
    138
    139static int __init devfreq_userspace_init(void)
    140{
    141	return devfreq_add_governor(&devfreq_userspace);
    142}
    143subsys_initcall(devfreq_userspace_init);
    144
    145static void __exit devfreq_userspace_exit(void)
    146{
    147	int ret;
    148
    149	ret = devfreq_remove_governor(&devfreq_userspace);
    150	if (ret)
    151		pr_err("%s: failed remove governor %d\n", __func__, ret);
    152
    153	return;
    154}
    155module_exit(devfreq_userspace_exit);
    156MODULE_LICENSE("GPL");