static ssize_t governor_store()

in devfreq.c [1404:1481]


static ssize_t governor_store(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];
	const struct devfreq_governor *governor, *prev_governor;

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

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

	mutex_lock(&devfreq_list_lock);
	governor = try_then_request_governor(str_governor);
	if (IS_ERR(governor)) {
		ret = PTR_ERR(governor);
		goto out;
	}
	if (df->governor == governor) {
		ret = 0;
		goto out;
	} else if (IS_SUPPORTED_FLAG(df->governor->flags, IMMUTABLE)
		|| IS_SUPPORTED_FLAG(governor->flags, IMMUTABLE)) {
		ret = -EINVAL;
		goto out;
	}

	/*
	 * Stop the current governor and remove the specific sysfs files
	 * which depend on current 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;
	}
	remove_sysfs_files(df, df->governor);

	/*
	 * Start the new governor and create the specific sysfs files
	 * which depend on the new governor.
	 */
	prev_governor = df->governor;
	df->governor = governor;
	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);

		/* Restore previous governor */
		df->governor = prev_governor;
		ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
		if (ret) {
			dev_err(dev,
				"%s: reverting to Governor %s failed (%d)\n",
				__func__, prev_governor->name, ret);
			df->governor = NULL;
			goto out;
		}
	}

	/*
	 * Create the sysfs files for the new governor. But if failed to start
	 * the new governor, restore the sysfs files of previous governor.
	 */
	create_sysfs_files(df, df->governor);

out:
	mutex_unlock(&devfreq_list_lock);

	if (!ret)
		ret = count;
	return ret;
}