[PATCH v2 3/3] drm/bridge: it6505: Improve synchronization between extcon subsystem

Robert Foss robert.foss at linaro.org
Mon Oct 24 08:07:23 UTC 2022


On Thu, 13 Oct 2022 at 13:04, Pin-yen Lin <treapking at chromium.org> wrote:
>
> Originally, the it6505 relies on a short sleep in the IRQ handler and a
> long sleep to make sure it6505->lane_swap and it6505->lane_count is
> configured in it6505_extcon_work and it6505_detect, respectively.
>
> Use completion and additional DPCD read to remove the unnecessary waits,
> and use a different lock for it6505_extcon_work and the threaded IRQ
> handler because they no longer need to run exclusively.
>
> The wait time of the completion is usually less than 10ms in local
> experiments, but leave it larger here just in case.
>
> Signed-off-by: Pin-yen Lin <treapking at chromium.org>
> ---
>
> Changes in v2:
> - Add the empty line back
>
>  drivers/gpu/drm/bridge/ite-it6505.c | 18 +++++++++++-------
>  1 file changed, 11 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
> index 4b6061272599..0de44c651c60 100644
> --- a/drivers/gpu/drm/bridge/ite-it6505.c
> +++ b/drivers/gpu/drm/bridge/ite-it6505.c
> @@ -412,6 +412,7 @@ struct it6505 {
>          * Mutex protects extcon and interrupt functions from interfering
>          * each other.
>          */
> +       struct mutex irq_lock;
>         struct mutex extcon_lock;
>         struct mutex mode_lock; /* used to bridge_detect */
>         struct mutex aux_lock; /* used to aux data transfers */
> @@ -440,7 +441,7 @@ struct it6505 {
>         enum hdcp_state hdcp_status;
>         struct delayed_work hdcp_work;
>         struct work_struct hdcp_wait_ksv_list;
> -       struct completion wait_edid_complete;
> +       struct completion extcon_completion;
>         u8 auto_train_retry;
>         bool hdcp_desired;
>         bool is_repeater;
> @@ -2316,8 +2317,8 @@ static void it6505_irq_hpd(struct it6505 *it6505)
>                              it6505->hpd_state ? "high" : "low");
>
>         if (it6505->hpd_state) {
> -               wait_for_completion_timeout(&it6505->wait_edid_complete,
> -                                           msecs_to_jiffies(6000));
> +               wait_for_completion_timeout(&it6505->extcon_completion,
> +                                           msecs_to_jiffies(1000));
>                 it6505_aux_on(it6505);
>                 if (it6505->dpcd[0] == 0) {
>                         it6505_get_dpcd(it6505, DP_DPCD_REV, it6505->dpcd,
> @@ -2493,8 +2494,7 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
>         };
>         int int_status[3], i;
>
> -       msleep(100);
> -       mutex_lock(&it6505->extcon_lock);
> +       mutex_lock(&it6505->irq_lock);
>
>         if (it6505->enable_drv_hold || !it6505->powered)
>                 goto unlock;
> @@ -2524,7 +2524,7 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
>         }
>
>  unlock:
> -       mutex_unlock(&it6505->extcon_lock);
> +       mutex_unlock(&it6505->irq_lock);
>
>         return IRQ_HANDLED;
>  }
> @@ -2701,9 +2701,12 @@ static void it6505_extcon_work(struct work_struct *work)
>                  */
>                 if (ret)
>                         it6505_poweron(it6505);
> +
> +               complete_all(&it6505->extcon_completion);
>         } else {
>                 DRM_DEV_DEBUG_DRIVER(dev, "start to power off");
>                 pm_runtime_put_sync(dev);
> +               reinit_completion(&it6505->extcon_completion);
>
>                 drm_helper_hpd_irq_event(it6505->bridge.dev);
>                 memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
> @@ -3274,6 +3277,7 @@ static int it6505_i2c_probe(struct i2c_client *client,
>         if (!it6505)
>                 return -ENOMEM;
>
> +       mutex_init(&it6505->irq_lock);
>         mutex_init(&it6505->extcon_lock);
>         mutex_init(&it6505->mode_lock);
>         mutex_init(&it6505->aux_lock);
> @@ -3329,7 +3333,7 @@ static int it6505_i2c_probe(struct i2c_client *client,
>         INIT_WORK(&it6505->link_works, it6505_link_training_work);
>         INIT_WORK(&it6505->hdcp_wait_ksv_list, it6505_hdcp_wait_ksv_list);
>         INIT_DELAYED_WORK(&it6505->hdcp_work, it6505_hdcp_work);
> -       init_completion(&it6505->wait_edid_complete);
> +       init_completion(&it6505->extcon_completion);
>         memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
>         it6505->powered = false;
>         it6505->enable_drv_hold = DEFAULT_DRV_HOLD;
> --
> 2.38.0.rc1.362.ged0d419d3c-goog
>

Reviewed-by: Robert Foss <robert.foss at linaro.org>


More information about the dri-devel mailing list