On Fri, Jun 14, 2019 at 12:55 AM Marcelo Tosatti <mtosatti@xxxxxxxxxx> 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@xxxxxxxxxx> Fair enough: Acked-by: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> > > --- > 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 > >