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>