Message ID | 20190613225022.969533311@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | cpuidle haltpoll driver and governor (v4) | expand |
On Fri, Jun 14, 2019 at 12:55 AM Marcelo Tosatti <mtosatti@redhat.com> wrote: > > Add a "get_poll_time" callback to the cpuidle_governor structure, > and change poll state to poll for that amount of time. > > Provide a default method for it, while allowing individual governors > to override it. > > Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Fair enough: Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > > --- > drivers/cpuidle/cpuidle.c | 40 ++++++++++++++++++++++++++++++++++++++++ > drivers/cpuidle/poll_state.c | 11 ++--------- > include/linux/cpuidle.h | 8 ++++++++ > 3 files changed, 50 insertions(+), 9 deletions(-) > > Index: linux-2.6.git/drivers/cpuidle/cpuidle.c > =================================================================== > --- linux-2.6.git.orig/drivers/cpuidle/cpuidle.c 2019-06-13 17:57:33.111185824 -0400 > +++ linux-2.6.git/drivers/cpuidle/cpuidle.c 2019-06-13 18:09:48.158500660 -0400 > @@ -362,6 +362,46 @@ > } > > /** > + * cpuidle_default_poll_time - default routine used to return poll time > + * governors can override it if necessary > + * > + * @drv: the cpuidle driver tied with the cpu > + * @dev: the cpuidle device > + * > + */ > +static u64 cpuidle_default_poll_time(struct cpuidle_driver *drv, > + struct cpuidle_device *dev) > +{ > + int i; > + > + for (i = 1; i < drv->state_count; i++) { > + if (drv->states[i].disabled || dev->states_usage[i].disable) > + continue; > + > + return (u64)drv->states[i].target_residency * NSEC_PER_USEC; > + } > + > + return TICK_NSEC; > +} > + > +/** > + * cpuidle_get_poll_time - tell the polling driver how much time to poll, > + * in nanoseconds. > + * > + * @drv: the cpuidle driver tied with the cpu > + * @dev: the cpuidle device > + * > + */ > +u64 cpuidle_get_poll_time(struct cpuidle_driver *drv, > + struct cpuidle_device *dev) > +{ > + if (cpuidle_curr_governor->get_poll_time) > + return cpuidle_curr_governor->get_poll_time(drv, dev); > + > + return cpuidle_default_poll_time(drv, dev); > +} > + > +/** > * cpuidle_install_idle_handler - installs the cpuidle idle loop handler > */ > void cpuidle_install_idle_handler(void) > Index: linux-2.6.git/drivers/cpuidle/poll_state.c > =================================================================== > --- linux-2.6.git.orig/drivers/cpuidle/poll_state.c 2019-06-13 17:57:33.111185824 -0400 > +++ linux-2.6.git/drivers/cpuidle/poll_state.c 2019-06-13 18:01:19.846944820 -0400 > @@ -20,16 +20,9 @@ > 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_get_poll_time(drv, dev); > > while (!need_resched()) { > cpu_relax(); > Index: linux-2.6.git/include/linux/cpuidle.h > =================================================================== > --- linux-2.6.git.orig/include/linux/cpuidle.h 2019-06-13 17:57:33.111185824 -0400 > +++ linux-2.6.git/include/linux/cpuidle.h 2019-06-13 18:01:19.846944820 -0400 > @@ -132,6 +132,8 @@ > 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_get_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 +168,9 @@ > struct cpuidle_device *dev, int index) > {return -ENODEV; } > static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { } > +extern u64 cpuidle_get_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; } > @@ -246,6 +251,9 @@ > struct cpuidle_device *dev, > bool *stop_tick); > void (*reflect) (struct cpuidle_device *dev, int index); > + > + u64 (*get_poll_time) (struct cpuidle_driver *drv, > + struct cpuidle_device *dev); > }; > > #ifdef CONFIG_CPU_IDLE > >
Index: linux-2.6.git/drivers/cpuidle/cpuidle.c =================================================================== --- linux-2.6.git.orig/drivers/cpuidle/cpuidle.c 2019-06-13 17:57:33.111185824 -0400 +++ linux-2.6.git/drivers/cpuidle/cpuidle.c 2019-06-13 18:09:48.158500660 -0400 @@ -362,6 +362,46 @@ } /** + * cpuidle_default_poll_time - default routine used to return poll time + * governors can override it if necessary + * + * @drv: the cpuidle driver tied with the cpu + * @dev: the cpuidle device + * + */ +static u64 cpuidle_default_poll_time(struct cpuidle_driver *drv, + struct cpuidle_device *dev) +{ + int i; + + for (i = 1; i < drv->state_count; i++) { + if (drv->states[i].disabled || dev->states_usage[i].disable) + continue; + + return (u64)drv->states[i].target_residency * NSEC_PER_USEC; + } + + return TICK_NSEC; +} + +/** + * cpuidle_get_poll_time - tell the polling driver how much time to poll, + * in nanoseconds. + * + * @drv: the cpuidle driver tied with the cpu + * @dev: the cpuidle device + * + */ +u64 cpuidle_get_poll_time(struct cpuidle_driver *drv, + struct cpuidle_device *dev) +{ + if (cpuidle_curr_governor->get_poll_time) + return cpuidle_curr_governor->get_poll_time(drv, dev); + + return cpuidle_default_poll_time(drv, dev); +} + +/** * cpuidle_install_idle_handler - installs the cpuidle idle loop handler */ void cpuidle_install_idle_handler(void) Index: linux-2.6.git/drivers/cpuidle/poll_state.c =================================================================== --- linux-2.6.git.orig/drivers/cpuidle/poll_state.c 2019-06-13 17:57:33.111185824 -0400 +++ linux-2.6.git/drivers/cpuidle/poll_state.c 2019-06-13 18:01:19.846944820 -0400 @@ -20,16 +20,9 @@ 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_get_poll_time(drv, dev); while (!need_resched()) { cpu_relax(); Index: linux-2.6.git/include/linux/cpuidle.h =================================================================== --- linux-2.6.git.orig/include/linux/cpuidle.h 2019-06-13 17:57:33.111185824 -0400 +++ linux-2.6.git/include/linux/cpuidle.h 2019-06-13 18:01:19.846944820 -0400 @@ -132,6 +132,8 @@ 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_get_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 +168,9 @@ struct cpuidle_device *dev, int index) {return -ENODEV; } static inline void cpuidle_reflect(struct cpuidle_device *dev, int index) { } +extern u64 cpuidle_get_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; } @@ -246,6 +251,9 @@ struct cpuidle_device *dev, bool *stop_tick); void (*reflect) (struct cpuidle_device *dev, int index); + + u64 (*get_poll_time) (struct cpuidle_driver *drv, + struct cpuidle_device *dev); }; #ifdef CONFIG_CPU_IDLE
Add a "get_poll_time" callback to the cpuidle_governor structure, and change poll state to poll for that amount of time. Provide a default method for it, while allowing individual governors to override it. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> --- drivers/cpuidle/cpuidle.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/cpuidle/poll_state.c | 11 ++--------- include/linux/cpuidle.h | 8 ++++++++ 3 files changed, 50 insertions(+), 9 deletions(-)