linux/drivers/devfreq/governor_userspace.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/devfreq/governor_simpleondemand.c
   3 *
   4 *  Copyright (C) 2011 Samsung Electronics
   5 *      MyungJoo Ham <myungjoo.ham@samsung.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/slab.h>
  13#include <linux/device.h>
  14#include <linux/devfreq.h>
  15#include <linux/pm.h>
  16#include <linux/mutex.h>
  17#include "governor.h"
  18
  19struct userspace_data {
  20        unsigned long user_frequency;
  21        bool valid;
  22};
  23
  24static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq)
  25{
  26        struct userspace_data *data = df->data;
  27
  28        if (!data->valid)
  29                *freq = df->previous_freq; /* No user freq specified yet */
  30        else
  31                *freq = data->user_frequency;
  32        return 0;
  33}
  34
  35static ssize_t store_freq(struct device *dev, struct device_attribute *attr,
  36                          const char *buf, size_t count)
  37{
  38        struct devfreq *devfreq = to_devfreq(dev);
  39        struct userspace_data *data;
  40        unsigned long wanted;
  41        int err = 0;
  42
  43
  44        mutex_lock(&devfreq->lock);
  45        data = devfreq->data;
  46
  47        sscanf(buf, "%lu", &wanted);
  48        data->user_frequency = wanted;
  49        data->valid = true;
  50        err = update_devfreq(devfreq);
  51        if (err == 0)
  52                err = count;
  53        mutex_unlock(&devfreq->lock);
  54        return err;
  55}
  56
  57static ssize_t show_freq(struct device *dev, struct device_attribute *attr,
  58                         char *buf)
  59{
  60        struct devfreq *devfreq = to_devfreq(dev);
  61        struct userspace_data *data;
  62        int err = 0;
  63
  64        mutex_lock(&devfreq->lock);
  65        data = devfreq->data;
  66
  67        if (data->valid)
  68                err = sprintf(buf, "%lu\n", data->user_frequency);
  69        else
  70                err = sprintf(buf, "undefined\n");
  71        mutex_unlock(&devfreq->lock);
  72        return err;
  73}
  74
  75static DEVICE_ATTR(set_freq, 0644, show_freq, store_freq);
  76static struct attribute *dev_entries[] = {
  77        &dev_attr_set_freq.attr,
  78        NULL,
  79};
  80static struct attribute_group dev_attr_group = {
  81        .name   = "userspace",
  82        .attrs  = dev_entries,
  83};
  84
  85static int userspace_init(struct devfreq *devfreq)
  86{
  87        int err = 0;
  88        struct userspace_data *data = kzalloc(sizeof(struct userspace_data),
  89                                              GFP_KERNEL);
  90
  91        if (!data) {
  92                err = -ENOMEM;
  93                goto out;
  94        }
  95        data->valid = false;
  96        devfreq->data = data;
  97
  98        err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group);
  99out:
 100        return err;
 101}
 102
 103static void userspace_exit(struct devfreq *devfreq)
 104{
 105        sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group);
 106        kfree(devfreq->data);
 107        devfreq->data = NULL;
 108}
 109
 110const struct devfreq_governor devfreq_userspace = {
 111        .name = "userspace",
 112        .get_target_freq = devfreq_userspace_func,
 113        .init = userspace_init,
 114        .exit = userspace_exit,
 115        .no_central_polling = true,
 116};
 117