Re: [PATCH 4/4] PM / devfreq: Handle monitor start/stop in the devfreq core

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [ARM Kernel]     [Linux ARM]     [Linux ARM MSM]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux