On Fri, May 05, 2023 at 11:46:11PM +0300, Imre Deak wrote: > If the output on a DP-alt link with its sink disconnected is kept > enabled for too long (about 20 sec), then some IOM/TCSS firmware timeout > will cause havoc on the PCI bus, at least for other GFX devices on it > which will stop powering up. Since user space is not guaranteed to do a > disabling modeset in time, switch such disconnected but active links to > TBT mode - which is without such shortcomings - with a 2 second delay. > > If the above condition is detected already during the driver load/system > resume sanitization step disable the output instead, as at that point no > user space or kernel client depends on a consistent output state yet and > because subsequent atomic modeset on such connectors - without the > actual sink capabilities available - can fail. > > An active/disconnected port as above will also block the HPD status of > other active/disconnected ports to get updated (stuck in the connected > state), until the former port is disabled, its PHY is disconnected and > a ~10 ms delay has elapsed. This means the link state for all TypeC > ports/CRTCs must be rechecked after a CRTC is disabled due to the above > reason. For this disconnect the PHY synchronously after the CRTC/port is > disabled and recheck all CRTCs for the above condition whenever such a > port is disabled. > > To account for a race condition during driver loading where the sink is > disconnected after the above sanitization step and before the HPD > interrupts get enabled, do an explicit check/link reset if needed from > the encoder's late_register hook, which is called after the HPD > interrupts are enabled already. > > v2: > - Handle an active/disconnected port blocking the HPD state update of > another active/disconnected port. > - Cancel the delayed work resetting the link also from the encoder > enable/suspend/shutdown hooks. > - Rebase on the earlier intel_modeset_lock_ctx_retry() addition, > fixing here the missed atomic state reset in case of a retry. > - Fix handling of an error return from intel_atomic_get_crtc_state(). > - Recheck if the port needs to be reset after all the atomic state > is locked and async commits are waited on. > > v3: > - Add intel_crtc_needs_link_reset(), instead of open-coding it, > keep intel_crtc_has_encoders(). (Ville) > - Fix state dumping and use a bitmask to track disabled CRTCs in > intel_sanitize_all_crtcs(). (Ville) > - Set internal in intel_atomic_state right after allocating it. > (Ville) > - Recheck all CRTCs (not yet force-disabled) after a CRTC is > force-disabled for any reason (not only due to a link state) > in intel_sanitize_all_crtcs(). > - Reduce delay after CRTC disabling to 20ms, and use the simpler > msleep(). > - Clarify code comment about HPD behaviour in > intel_sanitize_all_crtcs(). > - Move all the TC link reset logic to intel_tc.c . > - Cancel the link reset work synchronously during system suspend, > driver unload and shutdown. > > Cc: Kai-Heng Feng <kai.heng.feng@xxxxxxxxxxxxx> > Cc: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > Tested-by: Kai-Heng Feng <kai.heng.feng@xxxxxxxxxxxxx> > Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5860 > Signed-off-by: Imre Deak <imre.deak@xxxxxxxxx> > --- > drivers/gpu/drm/i915/display/intel_ddi.c | 32 +++- > .../drm/i915/display/intel_display_driver.c | 5 + > .../drm/i915/display/intel_display_driver.h | 2 + > drivers/gpu/drm/i915/display/intel_dp.c | 6 +- > drivers/gpu/drm/i915/display/intel_dp.h | 3 + > .../drm/i915/display/intel_modeset_setup.c | 85 +++++++-- > drivers/gpu/drm/i915/display/intel_tc.c | 164 +++++++++++++++++- > drivers/gpu/drm/i915/display/intel_tc.h | 5 +- > 8 files changed, 277 insertions(+), 25 deletions(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c > index 813be957ed11b..ba56c705ad64f 100644 > --- a/drivers/gpu/drm/i915/display/intel_ddi.c > +++ b/drivers/gpu/drm/i915/display/intel_ddi.c > @@ -3313,6 +3313,8 @@ static void intel_disable_ddi(struct intel_atomic_state *state, > const struct intel_crtc_state *old_crtc_state, > const struct drm_connector_state *old_conn_state) > { > + intel_tc_port_link_cancel_reset_work(enc_to_dig_port(encoder)); > + > intel_hdcp_disable(to_intel_connector(old_conn_state->connector)); > > if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI)) > @@ -3381,6 +3383,8 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state, > enum phy phy = intel_port_to_phy(dev_priv, encoder->port); > bool is_tc_port = intel_phy_is_tc(dev_priv, phy); > > + intel_tc_port_link_cancel_reset_work(dig_port); > + > if (is_tc_port) { > struct intel_crtc *master_crtc = > to_intel_crtc(crtc_state->uapi.crtc); > @@ -4232,9 +4236,19 @@ static void intel_ddi_encoder_reset(struct drm_encoder *encoder) > intel_tc_port_init_mode(dig_port); > } > > +static int intel_ddi_encoder_late_register(struct drm_encoder *_encoder) > +{ > + struct intel_encoder *encoder = to_intel_encoder(_encoder); > + > + intel_tc_port_link_reset(enc_to_dig_port(encoder)); > + > + return 0; > +} > + > static const struct drm_encoder_funcs intel_ddi_funcs = { > .reset = intel_ddi_encoder_reset, > .destroy = intel_ddi_encoder_destroy, > + .late_register = intel_ddi_encoder_late_register, > }; > > static struct intel_connector * > @@ -4404,14 +4418,16 @@ intel_ddi_hotplug(struct intel_encoder *encoder, > > state = intel_encoder_hotplug(encoder, connector); > > - intel_modeset_lock_ctx_retry(&ctx, NULL, 0, ret) { > - if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) > - ret = intel_hdmi_reset_link(encoder, &ctx); > - else > - ret = intel_dp_retrain_link(encoder, &ctx); > - } > + if (!intel_tc_port_link_reset(dig_port)) { > + intel_modeset_lock_ctx_retry(&ctx, NULL, 0, ret) { > + if (connector->base.connector_type == DRM_MODE_CONNECTOR_HDMIA) > + ret = intel_hdmi_reset_link(encoder, &ctx); > + else > + ret = intel_dp_retrain_link(encoder, &ctx); > + } > > - drm_WARN_ON(encoder->base.dev, ret); > + drm_WARN_ON(encoder->base.dev, ret); > + } > > /* > * Unpowered type-c dongles can take some time to boot and be > @@ -4627,7 +4643,7 @@ static void intel_ddi_encoder_suspend(struct intel_encoder *encoder) > if (!intel_phy_is_tc(i915, phy)) > return; > > - intel_tc_port_flush_work(dig_port); > + intel_tc_port_suspend(dig_port); > } > > static void intel_ddi_encoder_shutdown(struct intel_encoder *encoder) > diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.c b/drivers/gpu/drm/i915/display/intel_display_driver.c > index 60ce10fc72058..b62cf9d751011 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_driver.c > +++ b/drivers/gpu/drm/i915/display/intel_display_driver.c > @@ -505,6 +505,11 @@ int intel_display_driver_suspend(struct drm_i915_private *i915) > return ret; > } > > +bool intel_display_driver_is_suspended(struct drm_i915_private *i915) > +{ > + return i915->display.restore.modeset_state; > +} > + > int > __intel_display_driver_resume(struct drm_i915_private *i915, > struct drm_atomic_state *state, > diff --git a/drivers/gpu/drm/i915/display/intel_display_driver.h b/drivers/gpu/drm/i915/display/intel_display_driver.h > index c276a58ee3293..9dcd9d5b2b1c7 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_driver.h > +++ b/drivers/gpu/drm/i915/display/intel_display_driver.h > @@ -32,5 +32,7 @@ int __intel_display_driver_resume(struct drm_i915_private *i915, > struct drm_atomic_state *state, > struct drm_modeset_acquire_ctx *ctx); > > +bool intel_display_driver_is_suspended(struct drm_i915_private *i915); > + > #endif /* __INTEL_DISPLAY_DRIVER_H__ */ > > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c > index 99ceaa7d90b62..9a13ec09755fc 100644 > --- a/drivers/gpu/drm/i915/display/intel_dp.c > +++ b/drivers/gpu/drm/i915/display/intel_dp.c > @@ -4231,9 +4231,9 @@ static bool intel_dp_has_connector(struct intel_dp *intel_dp, > return false; > } > > -static int intel_dp_get_active_pipes(struct intel_dp *intel_dp, > - struct drm_modeset_acquire_ctx *ctx, > - u8 *pipe_mask) > +int intel_dp_get_active_pipes(struct intel_dp *intel_dp, > + struct drm_modeset_acquire_ctx *ctx, > + u8 *pipe_mask) > { > struct drm_i915_private *i915 = dp_to_i915(intel_dp); > struct drm_connector_list_iter conn_iter; > diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h > index ef39e4f7a329e..5f86157a10d2d 100644 > --- a/drivers/gpu/drm/i915/display/intel_dp.h > +++ b/drivers/gpu/drm/i915/display/intel_dp.h > @@ -42,6 +42,9 @@ void intel_dp_set_link_params(struct intel_dp *intel_dp, > int link_rate, int lane_count); > int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp, > int link_rate, u8 lane_count); > +int intel_dp_get_active_pipes(struct intel_dp *intel_dp, > + struct drm_modeset_acquire_ctx *ctx, > + u8 *pipe_mask); > int intel_dp_retrain_link(struct intel_encoder *encoder, > struct drm_modeset_acquire_ctx *ctx); > void intel_dp_set_power(struct intel_dp *intel_dp, u8 mode); > diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c > index 75b4dea1e442b..85f6401b8c709 100644 > --- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c > +++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c > @@ -26,6 +26,7 @@ > #include "intel_fifo_underrun.h" > #include "intel_modeset_setup.h" > #include "intel_pch_display.h" > +#include "intel_tc.h" > #include "intel_vblank.h" > #include "intel_wm.h" > #include "skl_watermark.h" > @@ -379,6 +380,21 @@ static bool intel_crtc_has_encoders(struct intel_crtc *crtc) > return false; > } > > +static bool intel_crtc_needs_link_reset(struct intel_crtc *crtc) > +{ > + struct drm_device *dev = crtc->base.dev; > + struct intel_encoder *encoder; > + > + for_each_encoder_on_crtc(dev, &crtc->base, encoder) { > + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); > + > + if (dig_port && intel_tc_port_link_needs_reset(dig_port)) > + return true; > + } > + > + return false; > +} > + > static struct intel_connector *intel_encoder_find_connector(struct intel_encoder *encoder) > { > struct drm_i915_private *i915 = to_i915(encoder->base.dev); > @@ -421,11 +437,12 @@ static void intel_sanitize_fifo_underrun_reporting(const struct intel_crtc_state > !HAS_GMCH(i915)); > } > > -static void intel_sanitize_crtc(struct intel_crtc *crtc, > +static bool intel_sanitize_crtc(struct intel_crtc *crtc, > struct drm_modeset_acquire_ctx *ctx) > { > struct drm_i915_private *i915 = to_i915(crtc->base.dev); > struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); > + bool needs_link_reset; > > if (crtc_state->hw.active) { > struct intel_plane *plane; > @@ -445,13 +462,65 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, > intel_color_commit_arm(crtc_state); > } > > + if (!crtc_state->hw.active || > + intel_crtc_is_bigjoiner_slave(crtc_state)) > + return false; > + > + needs_link_reset = intel_crtc_needs_link_reset(crtc); > + > /* > * Adjust the state of the output pipe according to whether we have > * active connectors/encoders. > */ > - if (crtc_state->hw.active && !intel_crtc_has_encoders(crtc) && > - !intel_crtc_is_bigjoiner_slave(crtc_state)) > - intel_crtc_disable_noatomic(crtc, ctx); > + if (!needs_link_reset && intel_crtc_has_encoders(crtc)) > + return false; > + > + intel_crtc_disable_noatomic(crtc, ctx); > + > + /* > + * The HPD state on other active/disconnected TC ports may be stuck in > + * the connected state until this port is disabled and a ~10ms delay has > + * passed, wait here for that so that sanitizing other CRTCs will see the > + * up-to-date HPD state. > + */ > + if (needs_link_reset) > + msleep(20); > + > + return true; > +} > + > +static void intel_sanitize_all_crtcs(struct drm_i915_private *i915, > + struct drm_modeset_acquire_ctx *ctx) > +{ > + struct intel_crtc *crtc; > + u8 crtcs_forced_off = 0; > + > + /* > + * An active and disconnected TypeC port prevents the HPD live state > + * to get updated on other active/disconnected TypeC ports, so after > + * a port gets disabled the CRTCs using other TypeC ports must be > + * rechecked wrt. their link status. > + */ > + for (;;) { > + u8 old_mask = crtcs_forced_off; > + > + for_each_intel_crtc(&i915->drm, crtc) { > + if (BIT(crtc->pipe) & crtcs_forced_off) > + continue; > + > + if (intel_sanitize_crtc(crtc, ctx)) > + crtcs_forced_off |= BIT(crtc->pipe); > + } > + if (crtcs_forced_off == old_mask) > + break; > + } > + > + for_each_intel_crtc(&i915->drm, crtc) { > + struct intel_crtc_state *crtc_state = > + to_intel_crtc_state(crtc->base.state); > + > + intel_crtc_state_dump(crtc_state, NULL, "setup_hw_state"); > + } > } > > static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) > @@ -871,13 +940,7 @@ void intel_modeset_setup_hw_state(struct drm_i915_private *i915, > */ > intel_modeset_update_connector_atomic_state(i915); > > - for_each_intel_crtc(&i915->drm, crtc) { > - struct intel_crtc_state *crtc_state = > - to_intel_crtc_state(crtc->base.state); > - > - intel_sanitize_crtc(crtc, ctx); > - intel_crtc_state_dump(crtc_state, NULL, "setup_hw_state"); > - } > + intel_sanitize_all_crtcs(i915, ctx); > > intel_dpll_sanitize_state(i915); > > diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c > index 4fca711a58bce..f0fde20158c0b 100644 > --- a/drivers/gpu/drm/i915/display/intel_tc.c > +++ b/drivers/gpu/drm/i915/display/intel_tc.c > @@ -5,15 +5,19 @@ > > #include "i915_drv.h" > #include "i915_reg.h" > +#include "intel_atomic.h" > #include "intel_cx0_phy_regs.h" > #include "intel_ddi.h" > #include "intel_de.h" > #include "intel_display.h" > +#include "intel_display_driver.h" > #include "intel_display_power_map.h" > #include "intel_display_types.h" > #include "intel_dkl_phy_regs.h" > +#include "intel_dp.h" > #include "intel_dp_mst.h" > #include "intel_mg_phy_regs.h" > +#include "intel_modeset_lock.h" > #include "intel_tc.h" > > #define DP_PIN_ASSIGNMENT_C 0x3 > @@ -51,6 +55,7 @@ struct intel_tc_port { > enum intel_display_power_domain lock_power_domain; > #endif > struct delayed_work disconnect_phy_work; > + struct delayed_work link_reset_work; > int link_refcount; > bool legacy_port:1; > char port_name[8]; > @@ -1572,6 +1577,143 @@ bool intel_tc_port_connected(struct intel_encoder *encoder) > return is_connected; > } > > +static bool __intel_tc_port_link_needs_reset(struct intel_tc_port *tc) > +{ > + bool ret; > + > + mutex_lock(&tc->lock); > + > + ret = tc->link_refcount && > + tc->mode == TC_PORT_DP_ALT && > + intel_tc_port_needs_reset(tc); > + > + mutex_unlock(&tc->lock); > + > + return ret; > +} > + > +bool intel_tc_port_link_needs_reset(struct intel_digital_port *dig_port) > +{ > + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); > + enum phy phy = intel_port_to_phy(i915, dig_port->base.port); > + > + if (!intel_phy_is_tc(i915, phy)) > + return false; > + > + return __intel_tc_port_link_needs_reset(to_tc_port(dig_port)); > +} > + > +static int reset_link(struct intel_tc_port *tc) > +{ > + struct drm_i915_private *i915 = tc_to_i915(tc); > + struct intel_digital_port *dig_port = tc->dig_port; > + struct intel_dp *intel_dp = enc_to_intel_dp(&dig_port->base); > + struct drm_modeset_acquire_ctx ctx; > + struct drm_atomic_state *_state; > + struct intel_atomic_state *state; > + int ret = 0; > + > + _state = drm_atomic_state_alloc(&i915->drm); > + if (!_state) > + return -ENOMEM; > + > + state = to_intel_atomic_state(_state); > + state->internal = true; > + > + intel_modeset_lock_ctx_retry(&ctx, state, 0, ret) { > + struct intel_crtc *crtc; > + u8 pipe_mask; > + > + ret = drm_modeset_lock(&i915->drm.mode_config.connection_mutex, &ctx); > + if (ret) > + continue; > + > + ret = intel_dp_get_active_pipes(intel_dp, &ctx, &pipe_mask); > + if (ret) > + continue; > + > + if (!pipe_mask) > + continue; > + > + for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, pipe_mask) { > + struct intel_crtc_state *crtc_state; > + > + crtc_state = intel_atomic_get_crtc_state(&state->base, crtc); > + if (IS_ERR(crtc_state)) { > + ret = PTR_ERR(crtc_state); > + break; > + } > + > + crtc_state->uapi.connectors_changed = true; > + } > + > + if (ret) > + continue; > + > + if (!__intel_tc_port_link_needs_reset(tc)) > + continue; > + > + ret = drm_atomic_commit(&state->base); > + } > + > + drm_atomic_state_put(&state->base); > + > + return ret; > +} > + > +static void intel_tc_port_link_reset_work(struct work_struct *work) > +{ > + struct intel_tc_port *tc = > + container_of(work, struct intel_tc_port, link_reset_work.work); > + struct drm_i915_private *i915 = tc_to_i915(tc); > + int ret; > + > + if (!__intel_tc_port_link_needs_reset(tc)) > + return; > + > + /* > + * This shouldn't happen as while suspended the port is disabled and > + * hence does not require a link reset; still check for it to avoid a > + * modeset deadlock during suspending the encoder. > + */ > + if (drm_WARN_ON(&i915->drm, intel_display_driver_is_suspended(i915))) > + return; Arg, the above should've been: suspended = intel_display_driver_is_suspended(i915); barrier(); if (!__intel_tc_port_link_needs_reset(tc)) return; if (drm_WARN_ON(suspended)) return; > + > + mutex_lock(&i915->drm.mode_config.mutex); > + > + drm_dbg_kms(&i915->drm, > + "Port %s: TypeC DP-alt sink disconnected, resetting link\n", > + tc->port_name); > + ret = reset_link(tc); > + drm_WARN_ON(&i915->drm, ret); > + > + mutex_unlock(&i915->drm.mode_config.mutex); > +} > + > +bool intel_tc_port_link_reset(struct intel_digital_port *dig_port) > +{ > + if (!intel_tc_port_link_needs_reset(dig_port)) > + return false; > + > + queue_delayed_work(system_unbound_wq, > + &to_tc_port(dig_port)->link_reset_work, > + msecs_to_jiffies(2000)); > + > + return true; > +} > + > +void intel_tc_port_link_cancel_reset_work(struct intel_digital_port *dig_port) > +{ > + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); > + enum phy phy = intel_port_to_phy(i915, dig_port->base.port); > + struct intel_tc_port *tc = to_tc_port(dig_port); > + > + if (!intel_phy_is_tc(i915, phy)) > + return; > + > + cancel_delayed_work(&tc->link_reset_work); > +} > + > static void __intel_tc_port_lock(struct intel_tc_port *tc, > int required_lanes) > { > @@ -1619,11 +1761,19 @@ static void intel_tc_port_disconnect_phy_work(struct work_struct *work) > * > * Flush the delayed work disconnecting an idle PHY. > */ > -void intel_tc_port_flush_work(struct intel_digital_port *dig_port) > +static void intel_tc_port_flush_work(struct intel_digital_port *dig_port) > { > flush_delayed_work(&to_tc_port(dig_port)->disconnect_phy_work); > } > > +void intel_tc_port_suspend(struct intel_digital_port *dig_port) > +{ > + struct intel_tc_port *tc = to_tc_port(dig_port); > + > + cancel_delayed_work_sync(&tc->link_reset_work); > + intel_tc_port_flush_work(dig_port); > +} > + > void intel_tc_port_unlock(struct intel_digital_port *dig_port) > { > struct intel_tc_port *tc = to_tc_port(dig_port); > @@ -1660,6 +1810,14 @@ void intel_tc_port_put_link(struct intel_digital_port *dig_port) > intel_tc_port_lock(dig_port); > __intel_tc_port_put_link(tc); > intel_tc_port_unlock(dig_port); > + > + /* > + * The firmware will not update the HPD status of other TypeC ports > + * that are active in DP-alt mode with their sink disconnected, until > + * this port is disabled and its PHY gets disconnected. Make sure this > + * happens in a timely manner by disconnecting the PHY synchronously. > + */ > + intel_tc_port_flush_work(dig_port); > } > > int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy) > @@ -1692,7 +1850,9 @@ int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy) > "%c/TC#%d", port_name(port), tc_port + 1); > > mutex_init(&tc->lock); > + /* TODO: Combine the two works */ > INIT_DELAYED_WORK(&tc->disconnect_phy_work, intel_tc_port_disconnect_phy_work); > + INIT_DELAYED_WORK(&tc->link_reset_work, intel_tc_port_link_reset_work); > tc->legacy_port = is_legacy; > tc->mode = TC_PORT_DISCONNECTED; > tc->link_refcount = 0; > @@ -1706,7 +1866,7 @@ int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy) > > void intel_tc_port_cleanup(struct intel_digital_port *dig_port) > { > - intel_tc_port_flush_work(dig_port); > + intel_tc_port_suspend(dig_port); > > kfree(dig_port->tc); > dig_port->tc = NULL; > diff --git a/drivers/gpu/drm/i915/display/intel_tc.h b/drivers/gpu/drm/i915/display/intel_tc.h > index dd0810f9ea95e..3b16491925fa9 100644 > --- a/drivers/gpu/drm/i915/display/intel_tc.h > +++ b/drivers/gpu/drm/i915/display/intel_tc.h > @@ -30,11 +30,14 @@ void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port, > const struct intel_crtc_state *crtc_state); > void intel_tc_port_lock(struct intel_digital_port *dig_port); > void intel_tc_port_unlock(struct intel_digital_port *dig_port); > -void intel_tc_port_flush_work(struct intel_digital_port *dig_port); > +void intel_tc_port_suspend(struct intel_digital_port *dig_port); > void intel_tc_port_get_link(struct intel_digital_port *dig_port, > int required_lanes); > void intel_tc_port_put_link(struct intel_digital_port *dig_port); > bool intel_tc_port_ref_held(struct intel_digital_port *dig_port); > +bool intel_tc_port_link_needs_reset(struct intel_digital_port *dig_port); > +bool intel_tc_port_link_reset(struct intel_digital_port *dig_port); > +void intel_tc_port_link_cancel_reset_work(struct intel_digital_port *dig_port); > > int intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy); > void intel_tc_port_cleanup(struct intel_digital_port *dig_port); > -- > 2.37.2 >