Commit 8a531b02 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge tag 'pull_req_20121120' of...

Merge tag 'pull_req_20121120' of git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq into pm-devfreq

Devfreq pull request for Rafael from MyungJoo
Created on 2012.11.20 based on Linux 3.7-rc5

* tag 'pull_req_20121120' of git://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq:
  PM / devfreq: exynos4_bus.c: Fixed an alignment of the func call args.
  PM / devfreq: Add sysfs node to expose available governors
  PM / devfreq: allow sysfs governor node to switch governor
  PM / devfreq: governors: add GPL module license and allow module build
  PM / devfreq: map devfreq drivers to governor using name
  PM / devfreq: register governors with devfreq framework
  PM / devfreq: provide hooks for governors to be registered
  PM / devfreq: export update_devfreq
  PM / devfreq: Add sysfs node for representing frequency transition information.
  PM / devfreq: Add sysfs node to expose available frequencies
  PM / devfreq: documentation cleanups for devfreq header
  PM / devfreq: Use devm_* functions in exynos4_bus.c
parents 1a1357ea dce9dc3a
Loading
Loading
Loading
Loading
+28 −1
Original line number Diff line number Diff line
@@ -11,7 +11,7 @@ What: /sys/class/devfreq/.../governor
Date:		September 2011
Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
Description:
		The /sys/class/devfreq/.../governor shows the name of the
		The /sys/class/devfreq/.../governor show or set the name of the
		governor used by the corresponding devfreq object.

What:		/sys/class/devfreq/.../cur_freq
@@ -44,6 +44,17 @@ Description:
		(/sys/class/devfreq/.../central_polling is 0), this value
		may be useless.

What:		/sys/class/devfreq/.../trans_stat
Date:		October 2012
Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
Descrtiption:
		This ABI shows the statistics of devfreq behavior on a
		specific device. It shows the time spent in each state and
		the number of transitions between states.
		In order to activate this ABI, the devfreq target device
		driver should provide the list of available frequencies
		with its profile.

What:		/sys/class/devfreq/.../userspace/set_freq
Date:		September 2011
Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
@@ -51,3 +62,19 @@ Description:
		The /sys/class/devfreq/.../userspace/set_freq shows and
		sets the requested frequency for the devfreq object if
		userspace governor is in effect.

What:		/sys/class/devfreq/.../available_frequencies
Date:		October 2012
Contact:	Nishanth Menon <nm@ti.com>
Description:
		The /sys/class/devfreq/.../available_frequencies shows
		the available frequencies of the corresponding devfreq object.
		This is a snapshot of available frequencies and not limited
		by the min/max frequency restrictions.

What:		/sys/class/devfreq/.../available_governors
Date:		October 2012
Contact:	Nishanth Menon <nm@ti.com>
Description:
		The /sys/class/devfreq/.../available_governors shows
		currently available governors in the system.
+4 −4
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ if PM_DEVFREQ
comment "DEVFREQ Governors"

config DEVFREQ_GOV_SIMPLE_ONDEMAND
	bool "Simple Ondemand"
	tristate "Simple Ondemand"
	help
	  Chooses frequency based on the recent load on the device. Works
	  similar as ONDEMAND governor of CPUFREQ does. A device with
@@ -39,7 +39,7 @@ config DEVFREQ_GOV_SIMPLE_ONDEMAND
	  values to the governor with data field at devfreq_add_device().

config DEVFREQ_GOV_PERFORMANCE
	bool "Performance"
	tristate "Performance"
	help
	  Sets the frequency at the maximum available frequency.
	  This governor always returns UINT_MAX as frequency so that
@@ -47,7 +47,7 @@ config DEVFREQ_GOV_PERFORMANCE
	  at any time.

config DEVFREQ_GOV_POWERSAVE
	bool "Powersave"
	tristate "Powersave"
	help
	  Sets the frequency at the minimum available frequency.
	  This governor always returns 0 as frequency so that
@@ -55,7 +55,7 @@ config DEVFREQ_GOV_POWERSAVE
	  at any time.

config DEVFREQ_GOV_USERSPACE
	bool "Userspace"
	tristate "Userspace"
	help
	  Sets the frequency at the user specified one.
	  This governor returns the user configured frequency if there
+378 −9
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ static struct class *devfreq_class;
 */
static struct workqueue_struct *devfreq_wq;

/* The list of all device-devfreq governors */
static LIST_HEAD(devfreq_governor_list);
/* The list of all device-devfreq */
static LIST_HEAD(devfreq_list);
static DEFINE_MUTEX(devfreq_list_lock);
@@ -66,6 +68,77 @@ static struct devfreq *find_device_devfreq(struct device *dev)
	return ERR_PTR(-ENODEV);
}

/**
 * devfreq_get_freq_level() - Lookup freq_table for the frequency
 * @devfreq:	the devfreq instance
 * @freq:	the target frequency
 */
static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
{
	int lev;

	for (lev = 0; lev < devfreq->profile->max_state; lev++)
		if (freq == devfreq->profile->freq_table[lev])
			return lev;

	return -EINVAL;
}

/**
 * devfreq_update_status() - Update statistics of devfreq behavior
 * @devfreq:	the devfreq instance
 * @freq:	the update target frequency
 */
static int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
{
	int lev, prev_lev;
	unsigned long cur_time;

	lev = devfreq_get_freq_level(devfreq, freq);
	if (lev < 0)
		return lev;

	cur_time = jiffies;
	devfreq->time_in_state[lev] +=
			 cur_time - devfreq->last_stat_updated;
	if (freq != devfreq->previous_freq) {
		prev_lev = devfreq_get_freq_level(devfreq,
						devfreq->previous_freq);
		devfreq->trans_table[(prev_lev *
				devfreq->profile->max_state) + lev]++;
		devfreq->total_trans++;
	}
	devfreq->last_stat_updated = cur_time;

	return 0;
}

/**
 * find_devfreq_governor() - find devfreq governor from name
 * @name:	name of the governor
 *
 * Search the list of devfreq governors and return the matched
 * governor's pointer. devfreq_list_lock should be held by the caller.
 */
static struct devfreq_governor *find_devfreq_governor(const char *name)
{
	struct devfreq_governor *tmp_governor;

	if (unlikely(IS_ERR_OR_NULL(name))) {
		pr_err("DEVFREQ: %s: Invalid parameters\n", __func__);
		return ERR_PTR(-EINVAL);
	}
	WARN(!mutex_is_locked(&devfreq_list_lock),
	     "devfreq_list_lock must be locked.");

	list_for_each_entry(tmp_governor, &devfreq_governor_list, node) {
		if (!strncmp(tmp_governor->name, name, DEVFREQ_NAME_LEN))
			return tmp_governor;
	}

	return ERR_PTR(-ENODEV);
}

/* Load monitoring helper functions for governors use */

/**
@@ -86,6 +159,9 @@ int update_devfreq(struct devfreq *devfreq)
		return -EINVAL;
	}

	if (!devfreq->governor)
		return -EINVAL;

	/* Reevaluate the proper frequency */
	err = devfreq->governor->get_target_freq(devfreq, &freq);
	if (err)
@@ -112,9 +188,15 @@ int update_devfreq(struct devfreq *devfreq)
	if (err)
		return err;

	if (devfreq->profile->freq_table)
		if (devfreq_update_status(devfreq, freq))
			dev_err(&devfreq->dev,
				"Couldn't update frequency transition information.\n");

	devfreq->previous_freq = freq;
	return err;
}
EXPORT_SYMBOL(update_devfreq);

/**
 * devfreq_monitor() - Periodically poll devfreq objects.
@@ -300,7 +382,9 @@ static void _remove_devfreq(struct devfreq *devfreq, bool skip)
	list_del(&devfreq->node);
	mutex_unlock(&devfreq_list_lock);

	devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_STOP, NULL);
	if (devfreq->governor)
		devfreq->governor->event_handler(devfreq,
						 DEVFREQ_GOV_STOP, NULL);

	if (devfreq->profile->exit)
		devfreq->profile->exit(devfreq->dev.parent);
@@ -333,19 +417,20 @@ static void devfreq_dev_release(struct device *dev)
 * devfreq_add_device() - Add devfreq feature to the device
 * @dev:	the device to add devfreq feature.
 * @profile:	device-specific profile to run devfreq.
 * @governor:	the policy to choose frequency.
 * @governor_name:	name of the policy to choose frequency.
 * @data:	private data for the governor. The devfreq framework does not
 *		touch this value.
 */
struct devfreq *devfreq_add_device(struct device *dev,
				   struct devfreq_dev_profile *profile,
				   const struct devfreq_governor *governor,
				   const char *governor_name,
				   void *data)
{
	struct devfreq *devfreq;
	struct devfreq_governor *governor;
	int err = 0;

	if (!dev || !profile || !governor) {
	if (!dev || !profile || !governor_name) {
		dev_err(dev, "%s: Invalid parameters.\n", __func__);
		return ERR_PTR(-EINVAL);
	}
@@ -373,11 +458,20 @@ struct devfreq *devfreq_add_device(struct device *dev,
	devfreq->dev.class = devfreq_class;
	devfreq->dev.release = devfreq_dev_release;
	devfreq->profile = profile;
	devfreq->governor = governor;
	strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
	devfreq->previous_freq = profile->initial_freq;
	devfreq->data = data;
	devfreq->nb.notifier_call = devfreq_notifier_call;

	devfreq->trans_table =	devm_kzalloc(dev, sizeof(unsigned int) *
						devfreq->profile->max_state *
						devfreq->profile->max_state,
						GFP_KERNEL);
	devfreq->time_in_state = devm_kzalloc(dev, sizeof(unsigned int) *
						devfreq->profile->max_state,
						GFP_KERNEL);
	devfreq->last_stat_updated = jiffies;

	dev_set_name(&devfreq->dev, dev_name(dev));
	err = device_register(&devfreq->dev);
	if (err) {
@@ -390,10 +484,14 @@ struct devfreq *devfreq_add_device(struct device *dev,

	mutex_lock(&devfreq_list_lock);
	list_add(&devfreq->node, &devfreq_list);
	mutex_unlock(&devfreq_list_lock);

	governor = find_devfreq_governor(devfreq->governor_name);
	if (!IS_ERR(governor))
		devfreq->governor = governor;
	if (devfreq->governor)
		err = devfreq->governor->event_handler(devfreq,
					DEVFREQ_GOV_START, NULL);
	mutex_unlock(&devfreq_list_lock);
	if (err) {
		dev_err(dev, "%s: Unable to start governor for the device\n",
			__func__);
@@ -436,6 +534,9 @@ int devfreq_suspend_device(struct devfreq *devfreq)
	if (!devfreq)
		return -EINVAL;

	if (!devfreq->governor)
		return 0;

	return devfreq->governor->event_handler(devfreq,
				DEVFREQ_GOV_SUSPEND, NULL);
}
@@ -450,17 +551,207 @@ int devfreq_resume_device(struct devfreq *devfreq)
	if (!devfreq)
		return -EINVAL;

	if (!devfreq->governor)
		return 0;

	return devfreq->governor->event_handler(devfreq,
				DEVFREQ_GOV_RESUME, NULL);
}
EXPORT_SYMBOL(devfreq_resume_device);

/**
 * devfreq_add_governor() - Add devfreq governor
 * @governor:	the devfreq governor to be added
 */
int devfreq_add_governor(struct devfreq_governor *governor)
{
	struct devfreq_governor *g;
	struct devfreq *devfreq;
	int err = 0;

	if (!governor) {
		pr_err("%s: Invalid parameters.\n", __func__);
		return -EINVAL;
	}

	mutex_lock(&devfreq_list_lock);
	g = find_devfreq_governor(governor->name);
	if (!IS_ERR(g)) {
		pr_err("%s: governor %s already registered\n", __func__,
		       g->name);
		err = -EINVAL;
		goto err_out;
	}

	list_add(&governor->node, &devfreq_governor_list);

	list_for_each_entry(devfreq, &devfreq_list, node) {
		int ret = 0;
		struct device *dev = devfreq->dev.parent;

		if (!strncmp(devfreq->governor_name, governor->name,
			     DEVFREQ_NAME_LEN)) {
			/* The following should never occur */
			if (devfreq->governor) {
				dev_warn(dev,
					 "%s: Governor %s already present\n",
					 __func__, devfreq->governor->name);
				ret = devfreq->governor->event_handler(devfreq,
							DEVFREQ_GOV_STOP, NULL);
				if (ret) {
					dev_warn(dev,
						 "%s: Governor %s stop = %d\n",
						 __func__,
						 devfreq->governor->name, ret);
				}
				/* Fall through */
			}
			devfreq->governor = governor;
			ret = devfreq->governor->event_handler(devfreq,
						DEVFREQ_GOV_START, NULL);
			if (ret) {
				dev_warn(dev, "%s: Governor %s start=%d\n",
					 __func__, devfreq->governor->name,
					 ret);
			}
		}
	}

err_out:
	mutex_unlock(&devfreq_list_lock);

	return err;
}
EXPORT_SYMBOL(devfreq_add_governor);

/**
 * devfreq_remove_device() - Remove devfreq feature from a device.
 * @governor:	the devfreq governor to be removed
 */
int devfreq_remove_governor(struct devfreq_governor *governor)
{
	struct devfreq_governor *g;
	struct devfreq *devfreq;
	int err = 0;

	if (!governor) {
		pr_err("%s: Invalid parameters.\n", __func__);
		return -EINVAL;
	}

	mutex_lock(&devfreq_list_lock);
	g = find_devfreq_governor(governor->name);
	if (IS_ERR(g)) {
		pr_err("%s: governor %s not registered\n", __func__,
		       g->name);
		err = -EINVAL;
		goto err_out;
	}
	list_for_each_entry(devfreq, &devfreq_list, node) {
		int ret;
		struct device *dev = devfreq->dev.parent;

		if (!strncmp(devfreq->governor_name, governor->name,
			     DEVFREQ_NAME_LEN)) {
			/* we should have a devfreq governor! */
			if (!devfreq->governor) {
				dev_warn(dev, "%s: Governor %s NOT present\n",
					 __func__, governor->name);
				continue;
				/* Fall through */
			}
			ret = devfreq->governor->event_handler(devfreq,
						DEVFREQ_GOV_STOP, NULL);
			if (ret) {
				dev_warn(dev, "%s: Governor %s stop=%d\n",
					 __func__, devfreq->governor->name,
					 ret);
			}
			devfreq->governor = NULL;
		}
	}

	list_del(&governor->node);
err_out:
	mutex_unlock(&devfreq_list_lock);

	return err;
}
EXPORT_SYMBOL(devfreq_remove_governor);

static ssize_t show_governor(struct device *dev,
			     struct device_attribute *attr, char *buf)
{
	if (!to_devfreq(dev)->governor)
		return -EINVAL;

	return sprintf(buf, "%s\n", to_devfreq(dev)->governor->name);
}

static ssize_t store_governor(struct device *dev, struct device_attribute *attr,
			      const char *buf, size_t count)
{
	struct devfreq *df = to_devfreq(dev);
	int ret;
	char str_governor[DEVFREQ_NAME_LEN + 1];
	struct devfreq_governor *governor;

	ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
	if (ret != 1)
		return -EINVAL;

	mutex_lock(&devfreq_list_lock);
	governor = find_devfreq_governor(str_governor);
	if (IS_ERR(governor)) {
		ret = PTR_ERR(governor);
		goto out;
	}
	if (df->governor == governor)
		goto out;

	if (df->governor) {
		ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
		if (ret) {
			dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
				 __func__, df->governor->name, ret);
			goto out;
		}
	}
	df->governor = governor;
	strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN);
	ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
	if (ret)
		dev_warn(dev, "%s: Governor %s not started(%d)\n",
			 __func__, df->governor->name, ret);
out:
	mutex_unlock(&devfreq_list_lock);

	if (!ret)
		ret = count;
	return ret;
}
static ssize_t show_available_governors(struct device *d,
				    struct device_attribute *attr,
				    char *buf)
{
	struct devfreq_governor *tmp_governor;
	ssize_t count = 0;

	mutex_lock(&devfreq_list_lock);
	list_for_each_entry(tmp_governor, &devfreq_governor_list, node)
		count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
				   "%s ", tmp_governor->name);
	mutex_unlock(&devfreq_list_lock);

	/* Truncate the trailing space */
	if (count)
		count--;

	count += sprintf(&buf[count], "\n");

	return count;
}

static ssize_t show_freq(struct device *dev,
			 struct device_attribute *attr, char *buf)
{
@@ -494,6 +785,9 @@ static ssize_t store_polling_interval(struct device *dev,
	unsigned int value;
	int ret;

	if (!df->governor)
		return -EINVAL;

	ret = sscanf(buf, "%u", &value);
	if (ret != 1)
		return -EINVAL;
@@ -570,14 +864,89 @@ static ssize_t show_max_freq(struct device *dev, struct device_attribute *attr,
	return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq);
}

static ssize_t show_available_freqs(struct device *d,
				    struct device_attribute *attr,
				    char *buf)
{
	struct devfreq *df = to_devfreq(d);
	struct device *dev = df->dev.parent;
	struct opp *opp;
	ssize_t count = 0;
	unsigned long freq = 0;

	rcu_read_lock();
	do {
		opp = opp_find_freq_ceil(dev, &freq);
		if (IS_ERR(opp))
			break;

		count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
				   "%lu ", freq);
		freq++;
	} while (1);
	rcu_read_unlock();

	/* Truncate the trailing space */
	if (count)
		count--;

	count += sprintf(&buf[count], "\n");

	return count;
}

static ssize_t show_trans_table(struct device *dev, struct device_attribute *attr,
				char *buf)
{
	struct devfreq *devfreq = to_devfreq(dev);
	ssize_t len;
	int i, j, err;
	unsigned int max_state = devfreq->profile->max_state;

	err = devfreq_update_status(devfreq, devfreq->previous_freq);
	if (err)
		return 0;

	len = sprintf(buf, "   From  :   To\n");
	len += sprintf(buf + len, "         :");
	for (i = 0; i < max_state; i++)
		len += sprintf(buf + len, "%8u",
				devfreq->profile->freq_table[i]);

	len += sprintf(buf + len, "   time(ms)\n");

	for (i = 0; i < max_state; i++) {
		if (devfreq->profile->freq_table[i]
					== devfreq->previous_freq) {
			len += sprintf(buf + len, "*");
		} else {
			len += sprintf(buf + len, " ");
		}
		len += sprintf(buf + len, "%8u:",
				devfreq->profile->freq_table[i]);
		for (j = 0; j < max_state; j++)
			len += sprintf(buf + len, "%8u",
				devfreq->trans_table[(i * max_state) + j]);
		len += sprintf(buf + len, "%10u\n",
			jiffies_to_msecs(devfreq->time_in_state[i]));
	}

	len += sprintf(buf + len, "Total transition : %u\n",
					devfreq->total_trans);
	return len;
}

static struct device_attribute devfreq_attrs[] = {
	__ATTR(governor, S_IRUGO, show_governor, NULL),
	__ATTR(governor, S_IRUGO | S_IWUSR, show_governor, store_governor),
	__ATTR(available_governors, S_IRUGO, show_available_governors, NULL),
	__ATTR(cur_freq, S_IRUGO, show_freq, NULL),
	__ATTR(available_frequencies, S_IRUGO, show_available_freqs, NULL),
	__ATTR(target_freq, S_IRUGO, show_target_freq, NULL),
	__ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval,
	       store_polling_interval),
	__ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq),
	__ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq),
	__ATTR(trans_stat, S_IRUGO, show_trans_table, NULL),
	{ },
};

+13 −32
Original line number Diff line number Diff line
@@ -987,7 +987,7 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	int err = 0;

	data = kzalloc(sizeof(struct busfreq_data), GFP_KERNEL);
	data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data), GFP_KERNEL);
	if (data == NULL) {
		dev_err(dev, "Cannot allocate memory.\n");
		return -ENOMEM;
@@ -1012,22 +1012,18 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
		err = -EINVAL;
	}
	if (err)
		goto err_regulator;
		return err;

	data->vdd_int = regulator_get(dev, "vdd_int");
	data->vdd_int = devm_regulator_get(dev, "vdd_int");
	if (IS_ERR(data->vdd_int)) {
		dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
		err = PTR_ERR(data->vdd_int);
		goto err_regulator;
		return PTR_ERR(data->vdd_int);
	}
	if (data->type == TYPE_BUSF_EXYNOS4x12) {
		data->vdd_mif = regulator_get(dev, "vdd_mif");
		data->vdd_mif = devm_regulator_get(dev, "vdd_mif");
		if (IS_ERR(data->vdd_mif)) {
			dev_err(dev, "Cannot get the regulator \"vdd_mif\"\n");
			err = PTR_ERR(data->vdd_mif);
			regulator_put(data->vdd_int);
			goto err_regulator;

			return PTR_ERR(data->vdd_mif);
		}
	}

@@ -1035,8 +1031,7 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
	if (IS_ERR(opp)) {
		dev_err(dev, "Invalid initial frequency %lu kHz.\n",
			exynos4_devfreq_profile.initial_freq);
		err = PTR_ERR(opp);
		goto err_opp_add;
		return PTR_ERR(opp);
	}
	data->curr_opp = opp;

@@ -1045,30 +1040,20 @@ static __devinit int exynos4_busfreq_probe(struct platform_device *pdev)
	busfreq_mon_reset(data);

	data->devfreq = devfreq_add_device(dev, &exynos4_devfreq_profile,
					   &devfreq_simple_ondemand, NULL);
	if (IS_ERR(data->devfreq)) {
		err = PTR_ERR(data->devfreq);
		goto err_opp_add;
	}
					   "simple_ondemand", NULL);
	if (IS_ERR(data->devfreq))
		return PTR_ERR(data->devfreq);

	devfreq_register_opp_notifier(dev, data->devfreq);

	err = register_pm_notifier(&data->pm_notifier);
	if (err) {
		dev_err(dev, "Failed to setup pm notifier\n");
		goto err_devfreq_add;
		devfreq_remove_device(data->devfreq);
		return err;
	}

	return 0;
err_devfreq_add:
	devfreq_remove_device(data->devfreq);
err_opp_add:
	if (data->vdd_mif)
		regulator_put(data->vdd_mif);
	regulator_put(data->vdd_int);
err_regulator:
	kfree(data);
	return err;
}

static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)
@@ -1077,10 +1062,6 @@ static __devexit int exynos4_busfreq_remove(struct platform_device *pdev)

	unregister_pm_notifier(&data->pm_notifier);
	devfreq_remove_device(data->devfreq);
	regulator_put(data->vdd_int);
	if (data->vdd_mif)
		regulator_put(data->vdd_mif);
	kfree(data);

	return 0;
}
+4 −0
Original line number Diff line number Diff line
@@ -34,4 +34,8 @@ extern void devfreq_monitor_suspend(struct devfreq *devfreq);
extern void devfreq_monitor_resume(struct devfreq *devfreq);
extern void devfreq_interval_update(struct devfreq *devfreq,
					unsigned int *delay);

extern int devfreq_add_governor(struct devfreq_governor *governor);
extern int devfreq_remove_governor(struct devfreq_governor *governor);

#endif /* _GOVERNOR_H */
Loading