From: Lyude Paul <lyude@redhat.com>
To: dri-devel@lists.freedesktop.org
Cc: "Juston Li" <juston.li@intel.com>,
"Imre Deak" <imre.deak@intel.com>,
"Ville Syrjälä" <ville.syrjala@linux.intel.com>,
"Harry Wentland" <hwentlan@amd.com>,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Maxime Ripard" <maxime.ripard@bootlin.com>,
"Sean Paul" <sean@poorly.run>, "David Airlie" <airlied@linux.ie>,
"Daniel Vetter" <daniel@ffwll.ch>,
linux-kernel@vger.kernel.org
Subject: [PATCH 02/26] drm/dp_mst: Destroy mstbs from destroy_connector_work
Date: Wed, 17 Jul 2019 21:42:25 -0400 [thread overview]
Message-ID: <20190718014329.8107-3-lyude@redhat.com> (raw)
In-Reply-To: <20190718014329.8107-1-lyude@redhat.com>
Currently we remove MST branch devices from the in-memory topology
immediately when their topology refcount reaches 0. This works just fine
at the moment, but since we're about to add suspend/resume reprobing for
MST topologies we're going to need to be able to travel through the
topology and drop topology refs on branch devices while holding
mgr->mutex. Since we currently can't do this due to the circular locking
dependencies that would incur, move all of the actual work for
drm_dp_destroy_mst_branch_device() into drm_dp_destroy_connector_work()
so we can drop topology refs on MSTBs in any locking context.
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>
Signed-off-by: Lyude Paul <lyude@redhat.com>
---
drivers/gpu/drm/drm_dp_mst_topology.c | 121 +++++++++++++++++---------
include/drm/drm_dp_mst_helper.h | 10 +++
2 files changed, 90 insertions(+), 41 deletions(-)
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 998081b9b205..d7c3d9233834 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1108,34 +1108,17 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref)
struct drm_dp_mst_branch *mstb =
container_of(kref, struct drm_dp_mst_branch, topology_kref);
struct drm_dp_mst_topology_mgr *mgr = mstb->mgr;
- struct drm_dp_mst_port *port, *tmp;
- bool wake_tx = false;
-
- mutex_lock(&mgr->lock);
- list_for_each_entry_safe(port, tmp, &mstb->ports, next) {
- list_del(&port->next);
- drm_dp_mst_topology_put_port(port);
- }
- mutex_unlock(&mgr->lock);
-
- /* drop any tx slots msg */
- mutex_lock(&mstb->mgr->qlock);
- if (mstb->tx_slots[0]) {
- mstb->tx_slots[0]->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
- mstb->tx_slots[0] = NULL;
- wake_tx = true;
- }
- if (mstb->tx_slots[1]) {
- mstb->tx_slots[1]->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
- mstb->tx_slots[1] = NULL;
- wake_tx = true;
- }
- mutex_unlock(&mstb->mgr->qlock);
- if (wake_tx)
- wake_up_all(&mstb->mgr->tx_waitq);
+ INIT_LIST_HEAD(&mstb->destroy_next);
- drm_dp_mst_put_mstb_malloc(mstb);
+ /*
+ * This can get called under mgr->mutex, so we need to perform the
+ * actual destruction of the mstb in another worker
+ */
+ mutex_lock(&mgr->destroy_connector_lock);
+ list_add(&mstb->destroy_next, &mgr->destroy_branch_device_list);
+ mutex_unlock(&mgr->destroy_connector_lock);
+ schedule_work(&mgr->destroy_connector_work);
}
/**
@@ -3618,10 +3601,56 @@ static void drm_dp_tx_work(struct work_struct *work)
mutex_unlock(&mgr->qlock);
}
+static inline void
+drm_dp_finish_destroy_port(struct drm_dp_mst_port *port)
+{
+ INIT_LIST_HEAD(&port->next);
+
+ port->mgr->cbs->destroy_connector(port->mgr, port->connector);
+
+ drm_dp_port_teardown_pdt(port, port->pdt);
+ port->pdt = DP_PEER_DEVICE_NONE;
+
+ drm_dp_mst_put_port_malloc(port);
+}
+
+static inline void
+drm_dp_finish_destroy_mst_branch_device(struct drm_dp_mst_branch *mstb)
+{
+ struct drm_dp_mst_topology_mgr *mgr = mstb->mgr;
+ struct drm_dp_mst_port *port, *tmp;
+ bool wake_tx = false;
+
+ mutex_lock(&mgr->lock);
+ list_for_each_entry_safe(port, tmp, &mstb->ports, next) {
+ list_del(&port->next);
+ drm_dp_mst_topology_put_port(port);
+ }
+ mutex_unlock(&mgr->lock);
+
+ /* drop any tx slots msg */
+ mutex_lock(&mstb->mgr->qlock);
+ if (mstb->tx_slots[0]) {
+ mstb->tx_slots[0]->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
+ mstb->tx_slots[0] = NULL;
+ wake_tx = true;
+ }
+ if (mstb->tx_slots[1]) {
+ mstb->tx_slots[1]->state = DRM_DP_SIDEBAND_TX_TIMEOUT;
+ mstb->tx_slots[1] = NULL;
+ wake_tx = true;
+ }
+ mutex_unlock(&mstb->mgr->qlock);
+
+ if (wake_tx)
+ wake_up_all(&mstb->mgr->tx_waitq);
+
+ drm_dp_mst_put_mstb_malloc(mstb);
+}
+
static void drm_dp_destroy_connector_work(struct work_struct *work)
{
struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
- struct drm_dp_mst_port *port;
bool send_hotplug = false;
/*
* Not a regular list traverse as we have to drop the destroy
@@ -3629,24 +3658,33 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
* ordering between this lock and the config mutex.
*/
for (;;) {
+ struct drm_dp_mst_branch *mstb = NULL;
+ struct drm_dp_mst_port *port = NULL;
+
+ /* Destroy any MSTBs first, and then their ports second */
mutex_lock(&mgr->destroy_connector_lock);
- port = list_first_entry_or_null(&mgr->destroy_connector_list, struct drm_dp_mst_port, next);
- if (!port) {
- mutex_unlock(&mgr->destroy_connector_lock);
- break;
+ mstb = list_first_entry_or_null(&mgr->destroy_branch_device_list,
+ struct drm_dp_mst_branch,
+ destroy_next);
+ if (mstb) {
+ list_del(&mstb->destroy_next);
+ } else {
+ port = list_first_entry_or_null(&mgr->destroy_connector_list,
+ struct drm_dp_mst_port,
+ next);
+ if (port)
+ list_del(&port->next);
}
- list_del(&port->next);
mutex_unlock(&mgr->destroy_connector_lock);
- INIT_LIST_HEAD(&port->next);
-
- mgr->cbs->destroy_connector(mgr, port->connector);
-
- drm_dp_port_teardown_pdt(port, port->pdt);
- port->pdt = DP_PEER_DEVICE_NONE;
-
- drm_dp_mst_put_port_malloc(port);
- send_hotplug = true;
+ if (mstb) {
+ drm_dp_finish_destroy_mst_branch_device(mstb);
+ } else if (port) {
+ drm_dp_finish_destroy_port(port);
+ send_hotplug = true;
+ } else {
+ break;
+ }
}
if (send_hotplug)
drm_kms_helper_hotplug_event(mgr->dev);
@@ -3840,6 +3878,7 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
mutex_init(&mgr->destroy_connector_lock);
INIT_LIST_HEAD(&mgr->tx_msg_downq);
INIT_LIST_HEAD(&mgr->destroy_connector_list);
+ INIT_LIST_HEAD(&mgr->destroy_branch_device_list);
INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
INIT_WORK(&mgr->tx_work, drm_dp_tx_work);
INIT_WORK(&mgr->destroy_connector_work, drm_dp_destroy_connector_work);
diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h
index 8c97a5f92c47..c01f3ea72756 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_destroy_connector_work()
+ */
+ struct list_head destroy_next;
+
u8 rad[8];
u8 lct;
int num_ports;
@@ -578,6 +584,10 @@ struct drm_dp_mst_topology_mgr {
* @destroy_connector_list: List of to be destroyed connectors.
*/
struct list_head destroy_connector_list;
+ /**
+ * @destroy_branch_device_list: List of to be destroyed branch devices
+ */
+ struct list_head destroy_branch_device_list;
/**
* @destroy_connector_lock: Protects @connector_list.
*/
--
2.21.0
next prev parent reply other threads:[~2019-07-18 1:44 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20190718014329.8107-1-lyude@redhat.com>
2019-07-18 1:42 ` [PATCH 01/26] drm/dp_mst: Move link address dumping into a function Lyude Paul
2019-08-08 19:53 ` Daniel Vetter
2019-08-26 21:51 ` Lyude Paul
2019-08-27 16:16 ` Daniel Vetter
2019-07-18 1:42 ` Lyude Paul [this message]
2019-08-13 13:00 ` [PATCH 02/26] drm/dp_mst: Destroy mstbs from destroy_connector_work Daniel Vetter
2019-08-26 22:07 ` Lyude Paul
2019-07-18 1:42 ` [PATCH 03/26] drm/dp_mst: Move test_calc_pbn_mode() into an actual selftest Lyude Paul
2019-08-13 13:01 ` Daniel Vetter
2019-07-18 1:42 ` [PATCH 04/26] drm/print: Add drm_err_printer() Lyude Paul
2019-08-13 13:04 ` Daniel Vetter
2019-07-18 1:42 ` [PATCH 05/26] drm/dp_mst: Add sideband down request tracing + selftests Lyude Paul
2019-08-13 14:50 ` Daniel Vetter
2019-08-27 16:43 ` Lyude Paul
2019-08-27 16:49 ` Lyude Paul
2019-08-27 17:15 ` Daniel Vetter
2019-08-31 0:31 ` Lyude Paul
2019-09-03 7:40 ` Daniel Vetter
2019-07-18 1:42 ` [PATCH 06/26] drm/dp_mst: Move PDT teardown for ports into destroy_connector_work Lyude Paul
2019-08-13 14:52 ` Daniel Vetter
2019-08-30 23:46 ` Lyude Paul
2019-07-18 1:42 ` [PATCH 07/26] drm/dp_mst: Get rid of list clear in drm_dp_finish_destroy_port() Lyude Paul
2019-08-13 14:55 ` Daniel Vetter
2019-07-18 1:42 ` [PATCH 08/26] drm/dp_mst: Refactor drm_dp_send_enum_path_resources Lyude Paul
2019-08-14 15:05 ` Daniel Vetter
2019-07-18 1:42 ` [PATCH 09/26] drm/dp_mst: Remove huge conditional in drm_dp_mst_handle_up_req() Lyude Paul
2019-08-13 14:56 ` Daniel Vetter
2019-07-18 1:42 ` [PATCH 10/26] drm/dp_mst: Constify guid in drm_dp_get_mst_branch_by_guid() Lyude Paul
2019-07-18 1:42 ` [PATCH 11/26] drm/dp_mst: Refactor drm_dp_mst_handle_up_req() Lyude Paul
2019-07-18 1:42 ` [PATCH 12/26] drm/dp_mst: Refactor drm_dp_mst_handle_down_rep() Lyude Paul
2019-07-18 1:42 ` [PATCH 13/26] drm/dp_mst: Destroy topology_mgr mutexes Lyude Paul
2019-07-18 1:42 ` [PATCH 14/26] drm/dp_mst: Cleanup drm_dp_send_link_address() a bit Lyude Paul
2019-07-18 1:42 ` [PATCH 15/26] drm/dp_mst: Refactor pdt setup/teardown, add more locking Lyude Paul
2019-07-18 1:42 ` [PATCH 16/26] drm/dp_mst: Rename drm_dp_add_port and drm_dp_update_port Lyude Paul
2019-07-18 1:42 ` [PATCH 17/26] drm/dp_mst: Remove lies in {up,down}_rep_recv documentation Lyude Paul
2019-07-18 1:42 ` [PATCH 18/26] drm/dp_mst: Handle UP requests asynchronously Lyude Paul
2019-07-18 1:42 ` [PATCH 19/26] drm/dp_mst: Protect drm_dp_mst_port members with connection_mutex Lyude Paul
2019-07-18 1:42 ` [PATCH 20/26] drm/dp_mst: Don't forget to update port->input in drm_dp_mst_handle_conn_stat() Lyude Paul
2019-07-18 1:42 ` [PATCH 21/26] drm/nouveau: Don't grab runtime PM refs for HPD IRQs Lyude Paul
2019-07-18 1:42 ` [PATCH 22/26] drm/amdgpu: Iterate through DRM connectors correctly Lyude Paul
2019-07-18 1:42 ` [PATCH 23/26] drm/amdgpu/dm: Resume short HPD IRQs before resuming MST topology Lyude Paul
2019-07-18 1:42 ` [PATCH 24/26] drm/dp_mst: Add basic topology reprobing when resuming Lyude Paul
2019-07-18 1:42 ` [PATCH 25/26] drm/dp_mst: Also print unhashed pointers for malloc/topology references Lyude Paul
2019-07-18 1:42 ` [PATCH 26/26] drm/dp_mst: Add topology ref history tracking for debugging Lyude Paul
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190718014329.8107-3-lyude@redhat.com \
--to=lyude@redhat.com \
--cc=airlied@linux.ie \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=hwentlan@amd.com \
--cc=imre.deak@intel.com \
--cc=juston.li@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=maxime.ripard@bootlin.com \
--cc=sean@poorly.run \
--cc=ville.syrjala@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome