Hi Matthias, As I commented on the first patch, it is not possible to call some codes according to the intention of each governor between 'devfreq_moniotr_*()' and some codes which are executed before or after 'devfreq_moniotr_*()' For example, if some governor requires the following sequence, after this patch, it is not possible. case DEVFREQ_GOV_xxx: /* execute some code before devfreq_monitor_xxx() */ devfreq_monitor_xxx() /* execute some code after devfreq_monitor_xxx() */ 2019년 2월 14일 (목) 오후 7:16, Matthias Kaehlcke <mka@xxxxxxxxxxxx>님이 작성: > > devfreq expects governors to call devfreq_monitor_start/stop() > in response to DEVFREQ_GOV_START/STOP events. Since the devfreq > core itself generates these events and invokes the governor's event > handler the start/stop of the load monitor can be done in the common > code. > > Call devfreq_monitor_start/stop() when the governor reports a > successful handling of DEVFREQ_GOV_START/STOP and remove these > calls from the simpleondemand and tegra governors. Make > devfreq_monitor_start/stop() static since these functions are now > only used by the devfreq core. For better integration with the > callers the functions must now be called with devfreq->lock held. > > Also stop manipulating the monitor workqueue directly, use > devfreq_monitor_start/stop() instead. > > Signed-off-by: Matthias Kaehlcke <mka@xxxxxxxxxxxx> > --- > drivers/devfreq/devfreq.c | 45 +++++++++++------------ > drivers/devfreq/governor.h | 2 - > drivers/devfreq/governor_simpleondemand.c | 8 ---- > drivers/devfreq/tegra-devfreq.c | 2 - > 4 files changed, 22 insertions(+), 35 deletions(-) > > diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c > index eb86461648d74..ac553c00f6790 100644 > --- a/drivers/devfreq/devfreq.c > +++ b/drivers/devfreq/devfreq.c > @@ -404,14 +404,14 @@ static void devfreq_monitor(struct work_struct *work) > * devfreq_monitor_start() - Start load monitoring of devfreq instance > * @devfreq: the devfreq instance. > * > - * Helper function for starting devfreq device load monitoing. By > - * default delayed work based monitoring is supported. Function > - * to be called from governor in response to DEVFREQ_GOV_START > - * event when device is added to devfreq framework. > + * Helper function for starting devfreq device load monitoring. By > + * default delayed work based monitoring is supported. Must be called > + * with devfreq->lock held. > */ > -void devfreq_monitor_start(struct devfreq *devfreq) > +static void devfreq_monitor_start(struct devfreq *devfreq) > { > - mutex_lock(&devfreq->lock); > + WARN(!mutex_is_locked(&devfreq->lock), > + "devfreq->lock must be held by the caller.\n"); > > if (devfreq->profile->polling_ms) { > INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor); > @@ -420,28 +420,28 @@ void devfreq_monitor_start(struct devfreq *devfreq) > > devfreq->monitor_state = DEVFREQ_MONITOR_RUNNING; > } > - > - mutex_unlock(&devfreq->lock); > } > -EXPORT_SYMBOL(devfreq_monitor_start); > > /** > * devfreq_monitor_stop() - Stop load monitoring of a devfreq instance > * @devfreq: the devfreq instance. > * > - * Helper function to stop devfreq device load monitoing. Function > - * to be called from governor in response to DEVFREQ_GOV_STOP > - * event when device is removed from devfreq framework. > + * Helper function to stop devfreq device load monitoring. Must be > + * called with devfreq->lock held. > */ > -void devfreq_monitor_stop(struct devfreq *devfreq) > +static void devfreq_monitor_stop(struct devfreq *devfreq) > { > + /* mutex must be held for symmetry with _start() */ > + WARN(!mutex_is_locked(&devfreq->lock), > + "devfreq->lock must be held by the caller.\n"); > + > + mutex_unlock(&devfreq->lock); > cancel_delayed_work_sync(&devfreq->work); > > mutex_lock(&devfreq->lock); > devfreq->monitor_state = DEVFREQ_MONITOR_STOPPED; > mutex_unlock(&devfreq->lock); > } > -EXPORT_SYMBOL(devfreq_monitor_stop); > > /** > * devfreq_monitor_suspend() - Suspend load monitoring of a devfreq instance > @@ -518,27 +518,22 @@ void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay) > > /* if new delay is zero, stop polling */ > if (!new_delay) { > + devfreq_monitor_stop(devfreq); > mutex_unlock(&devfreq->lock); > - cancel_delayed_work_sync(&devfreq->work); > - devfreq->monitor_state == DEVFREQ_MONITOR_STOPPED; > return; > } > > /* if current delay is zero, start polling with new delay */ > if (!cur_delay) { > - queue_delayed_work(devfreq_wq, &devfreq->work, > - msecs_to_jiffies(devfreq->profile->polling_ms)); > + devfreq_monitor_start(devfreq); > goto out; > } > > /* if current delay is greater than new delay, restart polling */ > if (cur_delay > new_delay) { > - mutex_unlock(&devfreq->lock); > - cancel_delayed_work_sync(&devfreq->work); > - mutex_lock(&devfreq->lock); > + devfreq_monitor_stop(devfreq); > if (devfreq->monitor_state != DEVFREQ_MONITOR_SUSPENDED) > - queue_delayed_work(devfreq_wq, &devfreq->work, > - msecs_to_jiffies(devfreq->profile->polling_ms)); > + devfreq_monitor_start(devfreq); > } > out: > mutex_unlock(&devfreq->lock); > @@ -601,6 +596,8 @@ static int devfreq_governor_start(struct devfreq *devfreq) > return err; > } > > + devfreq_monitor_start(devfreq); > + > return 0; > } > > @@ -624,6 +621,8 @@ static int devfreq_governor_stop(struct devfreq *devfreq) > return err; > } > > + devfreq_monitor_stop(devfreq); > + > return 0; > } > > diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h > index d136792c0cc91..47efe747b6f79 100644 > --- a/drivers/devfreq/governor.h > +++ b/drivers/devfreq/governor.h > @@ -57,8 +57,6 @@ struct devfreq_governor { > unsigned int event, void *data); > }; > > -extern void devfreq_monitor_start(struct devfreq *devfreq); > -extern void devfreq_monitor_stop(struct devfreq *devfreq); > extern void devfreq_interval_update(struct devfreq *devfreq, > unsigned int *delay); > > diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c > index 52eb0c734b312..e0f0944a9c7aa 100644 > --- a/drivers/devfreq/governor_simpleondemand.c > +++ b/drivers/devfreq/governor_simpleondemand.c > @@ -91,14 +91,6 @@ static int devfreq_simple_ondemand_handler(struct devfreq *devfreq, > unsigned int event, void *data) > { > switch (event) { > - case DEVFREQ_GOV_START: > - devfreq_monitor_start(devfreq); > - break; > - > - case DEVFREQ_GOV_STOP: > - devfreq_monitor_stop(devfreq); > - break; > - > case DEVFREQ_GOV_INTERVAL: > devfreq_interval_update(devfreq, (unsigned int *)data); > break; > diff --git a/drivers/devfreq/tegra-devfreq.c b/drivers/devfreq/tegra-devfreq.c > index 79efa1e51bd06..515fb852dbad6 100644 > --- a/drivers/devfreq/tegra-devfreq.c > +++ b/drivers/devfreq/tegra-devfreq.c > @@ -580,13 +580,11 @@ static int tegra_governor_event_handler(struct devfreq *devfreq, > > switch (event) { > case DEVFREQ_GOV_START: > - devfreq_monitor_start(devfreq); > tegra_actmon_enable_interrupts(tegra); > break; > > case DEVFREQ_GOV_STOP: > tegra_actmon_disable_interrupts(tegra); > - devfreq_monitor_stop(devfreq); > break; > > case DEVFREQ_GOV_SUSPEND: > -- > 2.20.1.791.gb4d0f1c61a-goog > -- Best Regards, Chanwoo Choi