On Mon, Jun 22, 2015 at 02:40:43PM +1000, Dave Airlie wrote: > From: Dave Airlie <airlied@xxxxxxxxxx> > > 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@xxxxxxxxxx> 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@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel