0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/slab.h>
0010 #include <linux/device.h>
0011 #include <linux/devfreq.h>
0012 #include <linux/pm.h>
0013 #include <linux/mutex.h>
0014 #include <linux/module.h>
0015 #include "governor.h"
0016
0017 struct userspace_data {
0018 unsigned long user_frequency;
0019 bool valid;
0020 };
0021
0022 static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq)
0023 {
0024 struct userspace_data *data = df->data;
0025
0026 if (data->valid)
0027 *freq = data->user_frequency;
0028 else
0029 *freq = df->previous_freq;
0030
0031 return 0;
0032 }
0033
0034 static ssize_t set_freq_store(struct device *dev, struct device_attribute *attr,
0035 const char *buf, size_t count)
0036 {
0037 struct devfreq *devfreq = to_devfreq(dev);
0038 struct userspace_data *data;
0039 unsigned long wanted;
0040 int err = 0;
0041
0042 mutex_lock(&devfreq->lock);
0043 data = devfreq->data;
0044
0045 sscanf(buf, "%lu", &wanted);
0046 data->user_frequency = wanted;
0047 data->valid = true;
0048 err = update_devfreq(devfreq);
0049 if (err == 0)
0050 err = count;
0051 mutex_unlock(&devfreq->lock);
0052 return err;
0053 }
0054
0055 static ssize_t set_freq_show(struct device *dev,
0056 struct device_attribute *attr, char *buf)
0057 {
0058 struct devfreq *devfreq = to_devfreq(dev);
0059 struct userspace_data *data;
0060 int err = 0;
0061
0062 mutex_lock(&devfreq->lock);
0063 data = devfreq->data;
0064
0065 if (data->valid)
0066 err = sprintf(buf, "%lu\n", data->user_frequency);
0067 else
0068 err = sprintf(buf, "undefined\n");
0069 mutex_unlock(&devfreq->lock);
0070 return err;
0071 }
0072
0073 static DEVICE_ATTR_RW(set_freq);
0074 static struct attribute *dev_entries[] = {
0075 &dev_attr_set_freq.attr,
0076 NULL,
0077 };
0078 static const struct attribute_group dev_attr_group = {
0079 .name = DEVFREQ_GOV_USERSPACE,
0080 .attrs = dev_entries,
0081 };
0082
0083 static int userspace_init(struct devfreq *devfreq)
0084 {
0085 int err = 0;
0086 struct userspace_data *data = kzalloc(sizeof(struct userspace_data),
0087 GFP_KERNEL);
0088
0089 if (!data) {
0090 err = -ENOMEM;
0091 goto out;
0092 }
0093 data->valid = false;
0094 devfreq->data = data;
0095
0096 err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group);
0097 out:
0098 return err;
0099 }
0100
0101 static void userspace_exit(struct devfreq *devfreq)
0102 {
0103
0104
0105
0106
0107 if (devfreq->dev.kobj.sd)
0108 sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group);
0109
0110 kfree(devfreq->data);
0111 devfreq->data = NULL;
0112 }
0113
0114 static int devfreq_userspace_handler(struct devfreq *devfreq,
0115 unsigned int event, void *data)
0116 {
0117 int ret = 0;
0118
0119 switch (event) {
0120 case DEVFREQ_GOV_START:
0121 ret = userspace_init(devfreq);
0122 break;
0123 case DEVFREQ_GOV_STOP:
0124 userspace_exit(devfreq);
0125 break;
0126 default:
0127 break;
0128 }
0129
0130 return ret;
0131 }
0132
0133 static struct devfreq_governor devfreq_userspace = {
0134 .name = DEVFREQ_GOV_USERSPACE,
0135 .get_target_freq = devfreq_userspace_func,
0136 .event_handler = devfreq_userspace_handler,
0137 };
0138
0139 static int __init devfreq_userspace_init(void)
0140 {
0141 return devfreq_add_governor(&devfreq_userspace);
0142 }
0143 subsys_initcall(devfreq_userspace_init);
0144
0145 static void __exit devfreq_userspace_exit(void)
0146 {
0147 int ret;
0148
0149 ret = devfreq_remove_governor(&devfreq_userspace);
0150 if (ret)
0151 pr_err("%s: failed remove governor %d\n", __func__, ret);
0152
0153 return;
0154 }
0155 module_exit(devfreq_userspace_exit);
0156 MODULE_LICENSE("GPL");