summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorLyude Paul <lyude@redhat.com>2019-02-19 17:41:02 -0500
committerLyude Paul <lyude@redhat.com>2019-10-24 14:21:55 -0400
commit7cb12d48314eabdaaf30e4b3275f04811b458ed3 (patch)
tree830ee3c4fa0362aa6c5cbf07c47fb53dbe6cd02c /include
parent2e79e22e092acd55da0b2db066e4826d7d152c41 (diff)
drm/dp_mst: Destroy MSTBs asynchronously
When reprobing an MST topology during resume, we have to account for the fact that while we were suspended it's possible that mstbs may have been removed from any ports in the topology. Since iterating downwards in the topology requires that we hold &mgr->lock, destroying MSTBs from this context would result in attempting to lock &mgr->lock a second time and deadlocking. So, fix this by first moving destruction of MSTBs into destroy_connector_work, then rename destroy_connector_work and friends to reflect that they now destroy both ports and mstbs. Note that even though this means that MSTBs will still be accessible for a short period of time between their removal from the topology and delayed destruction, we are still protected against referencing a MSTB with a refcount of 0 since we use kref_get_unless_zero() in most places. Changes since v1: * s/destroy_connector_list/destroy_port_list/ s/connector_destroy_lock/delayed_destroy_lock/ s/connector_destroy_work/delayed_destroy_work/ s/drm_dp_finish_destroy_branch_device/drm_dp_delayed_destroy_mstb/ s/drm_dp_finish_destroy_port/drm_dp_delayed_destroy_port/ - danvet * Use two loops in drm_dp_delayed_destroy_work() - danvet * Better explain why we need to do this - danvet * Use cancel_work_sync() instead of flush_work() - flush_work() doesn't account for work requeing Cc: Juston Li <juston.li@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Harry Wentland <hwentlan@amd.com> Cc: Daniel Vetter <daniel@ffwll.ch> Reviewed-by: Sean Paul <sean@poorly.run> Signed-off-by: Lyude Paul <lyude@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/20191022023641.8026-2-lyude@redhat.com
Diffstat (limited to 'include')
-rw-r--r--include/drm/drm_dp_mst_helper.h26
1 files changed, 19 insertions, 7 deletions
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 4a25e0577ae0..b2160c366fb7 100644
--- a/include/drm/drm_dp_mst_helper.h
+++ b/include/drm/drm_dp_mst_helper.h
@@ -143,6 +143,12 @@ struct drm_dp_mst_branch {
*/
struct kref malloc_kref;
+ /**
+ * @destroy_next: linked-list entry used by
+ * drm_dp_delayed_destroy_work()
+ */
+ struct list_head destroy_next;
+
u8 rad[8];
u8 lct;
int num_ports;
@@ -571,18 +577,24 @@ struct drm_dp_mst_topology_mgr {
struct work_struct tx_work;
/**
- * @destroy_connector_list: List of to be destroyed connectors.
+ * @destroy_port_list: List of to be destroyed connectors.
+ */
+ struct list_head destroy_port_list;
+ /**
+ * @destroy_branch_device_list: List of to be destroyed branch
+ * devices.
*/
- struct list_head destroy_connector_list;
+ struct list_head destroy_branch_device_list;
/**
- * @destroy_connector_lock: Protects @connector_list.
+ * @delayed_destroy_lock: Protects @destroy_port_list and
+ * @destroy_branch_device_list.
*/
- struct mutex destroy_connector_lock;
+ struct mutex delayed_destroy_lock;
/**
- * @destroy_connector_work: Work item to destroy connectors. Needed to
- * avoid locking inversion.
+ * @delayed_destroy_work: Work item to destroy MST port and branch
+ * devices, needed to avoid locking inversion.
*/
- struct work_struct destroy_connector_work;
+ struct work_struct delayed_destroy_work;
};
int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,