diff options
| -rw-r--r-- | drivers/cpuidle/cpuidle.c | 1 | ||||
| -rw-r--r-- | drivers/cpuidle/driver.c | 29 | ||||
| -rw-r--r-- | drivers/cpuidle/governors/menu.c | 5 | ||||
| -rw-r--r-- | drivers/cpuidle/sysfs.c | 21 | ||||
| -rw-r--r-- | include/linux/cpuidle.h | 8 | 
5 files changed, 49 insertions, 15 deletions
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index d90519cec88..04e4b7674a4 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -265,7 +265,6 @@ static void poll_idle_init(struct cpuidle_driver *drv)  	state->power_usage = -1;  	state->flags = 0;  	state->enter = poll_idle; -	state->disable = 0;  }  #else  static void poll_idle_init(struct cpuidle_driver *drv) {} diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 40cd3f3024d..58bf3b1ac9c 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -16,6 +16,7 @@  static struct cpuidle_driver *cpuidle_curr_driver;  DEFINE_SPINLOCK(cpuidle_driver_lock); +int cpuidle_driver_refcount;  static void __cpuidle_register_driver(struct cpuidle_driver *drv)  { @@ -89,8 +90,34 @@ void cpuidle_unregister_driver(struct cpuidle_driver *drv)  	}  	spin_lock(&cpuidle_driver_lock); -	cpuidle_curr_driver = NULL; + +	if (!WARN_ON(cpuidle_driver_refcount > 0)) +		cpuidle_curr_driver = NULL; +  	spin_unlock(&cpuidle_driver_lock);  }  EXPORT_SYMBOL_GPL(cpuidle_unregister_driver); + +struct cpuidle_driver *cpuidle_driver_ref(void) +{ +	struct cpuidle_driver *drv; + +	spin_lock(&cpuidle_driver_lock); + +	drv = cpuidle_curr_driver; +	cpuidle_driver_refcount++; + +	spin_unlock(&cpuidle_driver_lock); +	return drv; +} + +void cpuidle_driver_unref(void) +{ +	spin_lock(&cpuidle_driver_lock); + +	if (!WARN_ON(cpuidle_driver_refcount <= 0)) +		cpuidle_driver_refcount--; + +	spin_unlock(&cpuidle_driver_lock); +} diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 06335756ea1..8391d93f57d 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -281,7 +281,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)  	 * unless the timer is happening really really soon.  	 */  	if (data->expected_us > 5 && -		drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0) +		dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0)  		data->last_state_idx = CPUIDLE_DRIVER_STATE_START;  	/* @@ -290,8 +290,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)  	 */  	for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {  		struct cpuidle_state *s = &drv->states[i]; +		struct cpuidle_state_usage *su = &dev->states_usage[i]; -		if (s->disable) +		if (su->disable)  			continue;  		if (s->target_residency > data->predicted_us)  			continue; diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 88032b4dc6d..5f809e337b8 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -217,7 +217,8 @@ struct cpuidle_state_attr {  	struct attribute attr;  	ssize_t (*show)(struct cpuidle_state *, \  					struct cpuidle_state_usage *, char *); -	ssize_t (*store)(struct cpuidle_state *, const char *, size_t); +	ssize_t (*store)(struct cpuidle_state *, \ +			struct cpuidle_state_usage *, const char *, size_t);  };  #define define_one_state_ro(_name, show) \ @@ -233,21 +234,22 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \  	return sprintf(buf, "%u\n", state->_name);\  } -#define define_store_state_function(_name) \ +#define define_store_state_ull_function(_name) \  static ssize_t store_state_##_name(struct cpuidle_state *state, \ +		struct cpuidle_state_usage *state_usage, \  		const char *buf, size_t size) \  { \ -	long value; \ +	unsigned long long value; \  	int err; \  	if (!capable(CAP_SYS_ADMIN)) \  		return -EPERM; \ -	err = kstrtol(buf, 0, &value); \ +	err = kstrtoull(buf, 0, &value); \  	if (err) \  		return err; \  	if (value) \ -		state->disable = 1; \ +		state_usage->_name = 1; \  	else \ -		state->disable = 0; \ +		state_usage->_name = 0; \  	return size; \  } @@ -273,8 +275,8 @@ define_show_state_ull_function(usage)  define_show_state_ull_function(time)  define_show_state_str_function(name)  define_show_state_str_function(desc) -define_show_state_function(disable) -define_store_state_function(disable) +define_show_state_ull_function(disable) +define_store_state_ull_function(disable)  define_one_state_ro(name, show_state_name);  define_one_state_ro(desc, show_state_desc); @@ -318,10 +320,11 @@ static ssize_t cpuidle_state_store(struct kobject *kobj,  {  	int ret = -EIO;  	struct cpuidle_state *state = kobj_to_state(kobj); +	struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);  	struct cpuidle_state_attr *cattr = attr_to_stateattr(attr);  	if (cattr->store) -		ret = cattr->store(state, buf, size); +		ret = cattr->store(state, state_usage, buf, size);  	return ret;  } diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 6c26a3da0e0..27cfced7b57 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -34,6 +34,7 @@ struct cpuidle_driver;  struct cpuidle_state_usage {  	void		*driver_data; +	unsigned long long	disable;  	unsigned long long	usage;  	unsigned long long	time; /* in US */  }; @@ -46,7 +47,6 @@ struct cpuidle_state {  	unsigned int	exit_latency; /* in US */  	int		power_usage; /* in mW */  	unsigned int	target_residency; /* in US */ -	unsigned int    disable;  	int (*enter)	(struct cpuidle_device *dev,  			struct cpuidle_driver *drv, @@ -136,7 +136,9 @@ struct cpuidle_driver {  extern void disable_cpuidle(void);  extern int cpuidle_idle_call(void);  extern int cpuidle_register_driver(struct cpuidle_driver *drv); -struct cpuidle_driver *cpuidle_get_driver(void); +extern struct cpuidle_driver *cpuidle_get_driver(void); +extern struct cpuidle_driver *cpuidle_driver_ref(void); +extern void cpuidle_driver_unref(void);  extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);  extern int cpuidle_register_device(struct cpuidle_device *dev);  extern void cpuidle_unregister_device(struct cpuidle_device *dev); @@ -157,6 +159,8 @@ static inline int cpuidle_idle_call(void) { return -ENODEV; }  static inline int cpuidle_register_driver(struct cpuidle_driver *drv)  {return -ENODEV; }  static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; } +static inline struct cpuidle_driver *cpuidle_driver_ref(void) {return NULL; } +static inline void cpuidle_driver_unref(void) {}  static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }  static inline int cpuidle_register_device(struct cpuidle_device *dev)  {return -ENODEV; }  |