@@ -4904,13 +4904,15 @@ static bool intel_dp_mst_link_status(struct intel_dp *intel_dp)
49044904 * - %true if pending interrupts were serviced (or no interrupts were
49054905 * pending) w/o detecting an error condition.
49064906 * - %false if an error condition - like AUX failure or a loss of link - is
4907- * detected, which needs servicing from the hotplug work.
4907+ * detected, or another condition - like a DP tunnel BW state change - needs
4908+ * servicing from the hotplug work.
49084909 */
49094910static bool
49104911intel_dp_check_mst_status (struct intel_dp * intel_dp )
49114912{
49124913 struct drm_i915_private * i915 = dp_to_i915 (intel_dp );
49134914 bool link_ok = true;
4915+ bool reprobe_needed = false;
49144916
49154917 drm_WARN_ON_ONCE (& i915 -> drm , intel_dp -> active_mst_links < 0 );
49164918
@@ -4937,6 +4939,13 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
49374939
49384940 intel_dp_mst_hpd_irq (intel_dp , esi , ack );
49394941
4942+ if (esi [3 ] & DP_TUNNELING_IRQ ) {
4943+ if (drm_dp_tunnel_handle_irq (i915 -> display .dp_tunnel_mgr ,
4944+ & intel_dp -> aux ))
4945+ reprobe_needed = true;
4946+ ack [3 ] |= DP_TUNNELING_IRQ ;
4947+ }
4948+
49404949 if (!memchr_inv (ack , 0 , sizeof (ack )))
49414950 break ;
49424951
@@ -4947,7 +4956,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
49474956 drm_dp_mst_hpd_irq_send_new_request (& intel_dp -> mst_mgr );
49484957 }
49494958
4950- return link_ok ;
4959+ return link_ok && ! reprobe_needed ;
49514960}
49524961
49534962static void
@@ -5307,23 +5316,32 @@ static void intel_dp_check_device_service_irq(struct intel_dp *intel_dp)
53075316 drm_dbg_kms (& i915 -> drm , "Sink specific irq unhandled\n" );
53085317}
53095318
5310- static void intel_dp_check_link_service_irq (struct intel_dp * intel_dp )
5319+ static bool intel_dp_check_link_service_irq (struct intel_dp * intel_dp )
53115320{
5321+ struct drm_i915_private * i915 = dp_to_i915 (intel_dp );
5322+ bool reprobe_needed = false;
53125323 u8 val ;
53135324
53145325 if (intel_dp -> dpcd [DP_DPCD_REV ] < 0x11 )
5315- return ;
5326+ return false ;
53165327
53175328 if (drm_dp_dpcd_readb (& intel_dp -> aux ,
53185329 DP_LINK_SERVICE_IRQ_VECTOR_ESI0 , & val ) != 1 || !val )
5319- return ;
5330+ return false;
5331+
5332+ if ((val & DP_TUNNELING_IRQ ) &&
5333+ drm_dp_tunnel_handle_irq (i915 -> display .dp_tunnel_mgr ,
5334+ & intel_dp -> aux ))
5335+ reprobe_needed = true;
53205336
53215337 if (drm_dp_dpcd_writeb (& intel_dp -> aux ,
53225338 DP_LINK_SERVICE_IRQ_VECTOR_ESI0 , val ) != 1 )
5323- return ;
5339+ return reprobe_needed ;
53245340
53255341 if (val & HDMI_LINK_STATUS_CHANGED )
53265342 intel_dp_handle_hdmi_link_status_change (intel_dp );
5343+
5344+ return reprobe_needed ;
53275345}
53285346
53295347/*
@@ -5344,6 +5362,7 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
53445362{
53455363 struct drm_i915_private * dev_priv = dp_to_i915 (intel_dp );
53465364 u8 old_sink_count = intel_dp -> sink_count ;
5365+ bool reprobe_needed = false;
53475366 bool ret ;
53485367
53495368 /*
@@ -5366,7 +5385,7 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
53665385 }
53675386
53685387 intel_dp_check_device_service_irq (intel_dp );
5369- intel_dp_check_link_service_irq (intel_dp );
5388+ reprobe_needed = intel_dp_check_link_service_irq (intel_dp );
53705389
53715390 /* Handle CEC interrupts, if any */
53725391 drm_dp_cec_irq (& intel_dp -> aux );
@@ -5393,10 +5412,10 @@ intel_dp_short_pulse(struct intel_dp *intel_dp)
53935412 * FIXME get rid of the ad-hoc phy test modeset code
53945413 * and properly incorporate it into the normal modeset.
53955414 */
5396- return false ;
5415+ reprobe_needed = true ;
53975416 }
53985417
5399- return true ;
5418+ return ! reprobe_needed ;
54005419}
54015420
54025421/* XXX this is probably wrong for multiple downstream ports */
0 commit comments