On Mon, Jun 22, 2015 at 02:40:43PM +1000, Dave Airlie wrote:
From: Dave Airlie airlied@redhat.com
We should validate the passed in mstb under the lock this should stop us getting an invalid mstb here.
(first attempt with cancelling work has lockdep issues). Bugzilla: https://bugs.archlinux.org/task/45369
v2: update bugzilla, add some notes on why passing mst_primary is okay.
Signed-off-by: Dave Airlie airlied@redhat.com
On 2nd look I realized that pulling out mgr->lock and using the _locked variant won't work cleanly since the _put might also take the mgr->lock. I guess we could fix that too by also pulling the ref grab/drop for its argument out of check_and_send like this:
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 132581ca4ad8..08c131536b2b 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1189,6 +1189,7 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m struct drm_dp_mst_branch *mstb) { struct drm_dp_mst_port *port; + struct drm_dp_mst_branch *mstb_child;
if (!mstb->link_address_sent) { drm_dp_send_link_address(mgr, mstb); @@ -1204,17 +1205,31 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m if (!port->available_pbn) drm_dp_send_enum_path_resources(mgr, mstb, port);
- if (port->mstb) - drm_dp_check_and_send_link_address(mgr, port->mstb); + if (port->mstb) { + mstb_child = drm_dp_get_validated_mstb_ref(mgr, + port->mstb); + if (mstb_child) { + drm_dp_check_and_send_link_address(mgr, + mstb_child); + drm_dp_put_mst_branch_device(mstb_child); + } + } } }
static void drm_dp_mst_link_probe_work(struct work_struct *work) { struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, work); + struct drm_dp_mst_branch *mstb;
- drm_dp_check_and_send_link_address(mgr, mgr->mst_primary); + mutex_lock(&mgr->lock); + kref_get(&mgr->mst_primary->kref); + mstb = mgr->mst_primary; + mutex_unlock(&mgr->lock);
+ drm_dp_check_and_send_link_address(mgr, mstb); + + drm_dp_put_mst_branch_device(mstb); }
static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
Upside is that we don't need a comment, and imo non-tricky code is better code. Or am I still missing something? -Daniel
drivers/gpu/drm/drm_dp_mst_topology.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index fb65f5d..3c7e5cd 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1198,9 +1198,14 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_ }
static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *mgr,
struct drm_dp_mst_branch *mstb)
struct drm_dp_mst_branch *mstb_in)
{ struct drm_dp_mst_port *port;
struct drm_dp_mst_branch *mstb;
mstb = drm_dp_get_validated_mstb_ref(mgr, mstb_in);
if (!mstb)
return;
if (!mstb->link_address_sent) { drm_dp_send_link_address(mgr, mstb);
@@ -1219,12 +1224,20 @@ static void drm_dp_check_and_send_link_address(struct drm_dp_mst_topology_mgr *m if (port->mstb) drm_dp_check_and_send_link_address(mgr, port->mstb); }
- drm_dp_put_mst_branch_device(mstb);
}
static void drm_dp_mst_link_probe_work(struct work_struct *work) { struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, work);
- /*
* Note this passes mgr->mst_primary without validation
* it could be a) valid, b) NULL, c) some value between
* since we haven't taken the lock,
* however the validation sequence in check and send
* will take the lock, and if the value isn't valid
* it will fail appropriately.
drm_dp_check_and_send_link_address(mgr, mgr->mst_primary);*/
}
2.4.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel