forked from mirrors/linux
		
	PM / devfreq: Fix available_governor sysfs
The devfreq using passive governor is not able to change the governor.
So, the user can not change the governor through 'available_governor' sysfs
entry. Also, the devfreq which don't use the passive governor is not able to
change to 'passive' governor on the fly.
Fixes: 996133119f ("PM / devfreq: Add new passive governor")
Cc: stable@vger.kernel.org
Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
			
			
This commit is contained in:
		
							parent
							
								
									b0d75c0809
								
							
						
					
					
						commit
						bcf23c79c4
					
				
					 3 changed files with 31 additions and 4 deletions
				
			
		| 
						 | 
					@ -940,6 +940,9 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
 | 
				
			||||||
	if (df->governor == governor) {
 | 
						if (df->governor == governor) {
 | 
				
			||||||
		ret = 0;
 | 
							ret = 0;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
						} else if (df->governor->immutable || governor->immutable) {
 | 
				
			||||||
 | 
							ret = -EINVAL;
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (df->governor) {
 | 
						if (df->governor) {
 | 
				
			||||||
| 
						 | 
					@ -969,13 +972,33 @@ static ssize_t available_governors_show(struct device *d,
 | 
				
			||||||
					struct device_attribute *attr,
 | 
										struct device_attribute *attr,
 | 
				
			||||||
					char *buf)
 | 
										char *buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct devfreq_governor *tmp_governor;
 | 
						struct devfreq *df = to_devfreq(d);
 | 
				
			||||||
	ssize_t count = 0;
 | 
						ssize_t count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&devfreq_list_lock);
 | 
						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);
 | 
						 * The devfreq with immutable governor (e.g., passive) shows
 | 
				
			||||||
 | 
						 * only own governor.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (df->governor->immutable) {
 | 
				
			||||||
 | 
							count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
 | 
				
			||||||
 | 
									   "%s ", df->governor_name);
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * The devfreq device shows the registered governor except for
 | 
				
			||||||
 | 
						 * immutable governors such as passive governor .
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							struct devfreq_governor *governor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							list_for_each_entry(governor, &devfreq_governor_list, node) {
 | 
				
			||||||
 | 
								if (governor->immutable)
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
 | 
				
			||||||
 | 
										   "%s ", governor->name);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_unlock(&devfreq_list_lock);
 | 
						mutex_unlock(&devfreq_list_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Truncate the trailing space */
 | 
						/* Truncate the trailing space */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -179,6 +179,7 @@ static int devfreq_passive_event_handler(struct devfreq *devfreq,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct devfreq_governor devfreq_passive = {
 | 
					static struct devfreq_governor devfreq_passive = {
 | 
				
			||||||
	.name = "passive",
 | 
						.name = "passive",
 | 
				
			||||||
 | 
						.immutable = 1,
 | 
				
			||||||
	.get_target_freq = devfreq_passive_get_target_freq,
 | 
						.get_target_freq = devfreq_passive_get_target_freq,
 | 
				
			||||||
	.event_handler = devfreq_passive_event_handler,
 | 
						.event_handler = devfreq_passive_event_handler,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -104,6 +104,8 @@ struct devfreq_dev_profile {
 | 
				
			||||||
 * struct devfreq_governor - Devfreq policy governor
 | 
					 * struct devfreq_governor - Devfreq policy governor
 | 
				
			||||||
 * @node:		list node - contains registered devfreq governors
 | 
					 * @node:		list node - contains registered devfreq governors
 | 
				
			||||||
 * @name:		Governor's name
 | 
					 * @name:		Governor's name
 | 
				
			||||||
 | 
					 * @immutable:		Immutable flag for governor. If the value is 1,
 | 
				
			||||||
 | 
					 *			this govenror is never changeable to other governor.
 | 
				
			||||||
 * @get_target_freq:	Returns desired operating frequency for the device.
 | 
					 * @get_target_freq:	Returns desired operating frequency for the device.
 | 
				
			||||||
 *			Basically, get_target_freq will run
 | 
					 *			Basically, get_target_freq will run
 | 
				
			||||||
 *			devfreq_dev_profile.get_dev_status() to get the
 | 
					 *			devfreq_dev_profile.get_dev_status() to get the
 | 
				
			||||||
| 
						 | 
					@ -121,6 +123,7 @@ struct devfreq_governor {
 | 
				
			||||||
	struct list_head node;
 | 
						struct list_head node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const char name[DEVFREQ_NAME_LEN];
 | 
						const char name[DEVFREQ_NAME_LEN];
 | 
				
			||||||
 | 
						const unsigned int immutable;
 | 
				
			||||||
	int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
 | 
						int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
 | 
				
			||||||
	int (*event_handler)(struct devfreq *devfreq,
 | 
						int (*event_handler)(struct devfreq *devfreq,
 | 
				
			||||||
				unsigned int event, void *data);
 | 
									unsigned int event, void *data);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue