• Daniel Vetter's avatar
    drm/dp-mst: Remove branches before dropping the reference · 0391359d
    Daniel Vetter authored
    When we unplug a dp mst branch we unreference the entire tree from
    the root towards the leaves. Which is ok, since that's the way the
    pointers and so also the refcounts go.
    
    But when we drop the reference we must make sure that we remove the
    branches/ports from the lists/pointers before dropping the reference.
    Otherwise the get_validated functions will still return it instead
    of returning NULL (which indicates a potentially on-going unplug).
    
    The mst branch destroy gets this right for ports: First it deletes
    the port from the ports list, then it unrefs. But the ports destroy
    function gets it wrong: First it unrefs, then it drops the ref. Which
    means a zombie mst branch can still be validate with get_validated_mstb_ref
    when it shouldn't.
    
    Fix this.
    
    This should address a backtrace Dave dug out somewhere on unplug:
    
     [<ffffffffa00cc262>] drm_dp_mst_get_validated_mstb_ref_locked+0x92/0xa0 [drm_kms_helper]
     [<ffffffffa00cc211>] drm_dp_mst_get_validated_mstb_ref_locked+0x41/0xa0 [drm_kms_helper]
     [<ffffffffa00cc2aa>] drm_dp_get_validated_mstb_ref+0x3a/0x60 [drm_kms_helper]
     [<ffffffffa00cc2fb>] drm_dp_payload_send_msg.isra.14+0x2b/0x100 [drm_kms_helper]
     [<ffffffffa00cc547>] drm_dp_update_payload_part1+0x177/0x360 [drm_kms_helper]
     [<ffffffffa015c52e>] intel_mst_disable_dp+0x3e/0x80 [i915]
     [<ffffffffa013d60b>] haswell_crtc_disable+0x1cb/0x340 [i915]
     [<ffffffffa0136739>] intel_crtc_control+0x49/0x100 [i915]
     [<ffffffffa0136857>] intel_crtc_update_dpms+0x67/0x80 [i915]
     [<ffffffffa013fa59>] intel_connector_dpms+0x59/0x70 [i915]
     [<ffffffffa015c752>] intel_dp_destroy_mst_connector+0x32/0xc0 [i915]
     [<ffffffffa00cb44b>] drm_dp_destroy_port+0x6b/0xa0 [drm_kms_helper]
     [<ffffffffa00cb588>] drm_dp_destroy_mst_branch_device+0x108/0x130 [drm_kms_helper]
     [<ffffffffa00cb3cd>] drm_dp_port_teardown_pdt+0x3d/0x50 [drm_kms_helper]
     [<ffffffffa00cdb79>] drm_dp_mst_handle_up_req+0x499/0x540 [drm_kms_helper]
     [<ffffffff810d9ead>] ? trace_hardirqs_on_caller+0x15d/0x200 [<ffffffffa00cdc73>]
     drm_dp_mst_hpd_irq+0x53/0xa00 [drm_kms_helper] [<ffffffffa00c7dfb>]
     ? drm_dp_dpcd_read+0x1b/0x20 [drm_kms_helper] [<ffffffffa0153ed8>]
     ? intel_dp_dpcd_read_wake+0x38/0x70 [i915] [<ffffffffa015a225>]
     intel_dp_check_mst_status+0xb5/0x250 [i915] [<ffffffffa015ac71>]
     intel_dp_hpd_pulse+0x181/0x210 [i915] [<ffffffffa01104f6>]
     i915_digport_work_func+0x96/0x120 [i915]
    Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
    0391359d
drm_dp_mst_topology.c 74.2 KB