cpuidle: add poll_limit_ns to cpuidle_device structure
Add a poll_limit_ns variable to cpuidle_device structure. Calculate and configure it in the new cpuidle_poll_time function, in case its zero. Individual governors are allowed to override this value. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Родитель
fa86ee90eb
Коммит
259231a045
|
@ -361,6 +361,36 @@ void cpuidle_reflect(struct cpuidle_device *dev, int index)
|
|||
cpuidle_curr_governor->reflect(dev, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* cpuidle_poll_time - return amount of time to poll for,
|
||||
* governors can override dev->poll_limit_ns if necessary
|
||||
*
|
||||
* @drv: the cpuidle driver tied with the cpu
|
||||
* @dev: the cpuidle device
|
||||
*
|
||||
*/
|
||||
u64 cpuidle_poll_time(struct cpuidle_driver *drv,
|
||||
struct cpuidle_device *dev)
|
||||
{
|
||||
int i;
|
||||
u64 limit_ns;
|
||||
|
||||
if (dev->poll_limit_ns)
|
||||
return dev->poll_limit_ns;
|
||||
|
||||
limit_ns = TICK_NSEC;
|
||||
for (i = 1; i < drv->state_count; i++) {
|
||||
if (drv->states[i].disabled || dev->states_usage[i].disable)
|
||||
continue;
|
||||
|
||||
limit_ns = (u64)drv->states[i].target_residency * NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
dev->poll_limit_ns = limit_ns;
|
||||
|
||||
return dev->poll_limit_ns;
|
||||
}
|
||||
|
||||
/**
|
||||
* cpuidle_install_idle_handler - installs the cpuidle idle loop handler
|
||||
*/
|
||||
|
|
|
@ -20,16 +20,9 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev,
|
|||
local_irq_enable();
|
||||
if (!current_set_polling_and_test()) {
|
||||
unsigned int loop_count = 0;
|
||||
u64 limit = TICK_NSEC;
|
||||
int i;
|
||||
u64 limit;
|
||||
|
||||
for (i = 1; i < drv->state_count; i++) {
|
||||
if (drv->states[i].disabled || dev->states_usage[i].disable)
|
||||
continue;
|
||||
|
||||
limit = (u64)drv->states[i].target_residency * NSEC_PER_USEC;
|
||||
break;
|
||||
}
|
||||
limit = cpuidle_poll_time(drv, dev);
|
||||
|
||||
while (!need_resched()) {
|
||||
cpu_relax();
|
||||
|
|
|
@ -334,6 +334,7 @@ struct cpuidle_state_kobj {
|
|||
struct cpuidle_state_usage *state_usage;
|
||||
struct completion kobj_unregister;
|
||||
struct kobject kobj;
|
||||
struct cpuidle_device *device;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
|
@ -391,6 +392,7 @@ static inline void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *k
|
|||
#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
|
||||
#define kobj_to_state(k) (kobj_to_state_obj(k)->state)
|
||||
#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
|
||||
#define kobj_to_device(k) (kobj_to_state_obj(k)->device)
|
||||
#define attr_to_stateattr(a) container_of(a, struct cpuidle_state_attr, attr)
|
||||
|
||||
static ssize_t cpuidle_state_show(struct kobject *kobj, struct attribute *attr,
|
||||
|
@ -414,10 +416,14 @@ static ssize_t cpuidle_state_store(struct kobject *kobj, struct attribute *attr,
|
|||
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);
|
||||
struct cpuidle_device *dev = kobj_to_device(kobj);
|
||||
|
||||
if (cattr->store)
|
||||
ret = cattr->store(state, state_usage, buf, size);
|
||||
|
||||
/* reset poll time cache */
|
||||
dev->poll_limit_ns = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -468,6 +474,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
|
|||
}
|
||||
kobj->state = &drv->states[i];
|
||||
kobj->state_usage = &device->states_usage[i];
|
||||
kobj->device = device;
|
||||
init_completion(&kobj->kobj_unregister);
|
||||
|
||||
ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
|
||||
|
|
|
@ -86,6 +86,7 @@ struct cpuidle_device {
|
|||
ktime_t next_hrtimer;
|
||||
|
||||
int last_residency;
|
||||
u64 poll_limit_ns;
|
||||
struct cpuidle_state_usage states_usage[CPUIDLE_STATE_MAX];
|
||||
struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
|
||||
struct cpuidle_driver_kobj *kobj_driver;
|
||||
|
@ -132,6 +133,8 @@ extern int cpuidle_select(struct cpuidle_driver *drv,
|
|||
extern int cpuidle_enter(struct cpuidle_driver *drv,
|
||||
struct cpuidle_device *dev, int index);
|
||||
extern void cpuidle_reflect(struct cpuidle_device *dev, int index);
|
||||
extern u64 cpuidle_poll_time(struct cpuidle_driver *drv,
|
||||
struct cpuidle_device *dev);
|
||||
|
||||
extern int cpuidle_register_driver(struct cpuidle_driver *drv);
|
||||
extern struct cpuidle_driver *cpuidle_get_driver(void);
|
||||
|
@ -166,6 +169,9 @@ static inline int cpuidle_enter(struct cpuidle_driver *drv,
|
|||
struct cpuidle_device *dev, int index)
|
||||
{return -ENODEV; }
|
||||
static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { }
|
||||
extern u64 cpuidle_poll_time(struct cpuidle_driver *drv,
|
||||
struct cpuidle_device *dev)
|
||||
{return 0; }
|
||||
static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
|
||||
{return -ENODEV; }
|
||||
static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче