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

From: Robert Foss
Date: Mon Oct 24 2022 - 04:07:43 EST


On Thu, 13 Oct 2022 at 13:04, Pin-yen Lin <treapking@xxxxxxxxxxxx> 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@xxxxxxxxxxxx>
> ---
>
> 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@xxxxxxxxxx>