[PATCH 14/15] drm/i915/mst: use reference counted connectors.

Daniel Vetter daniel at ffwll.ch
Wed Apr 27 06:29:31 UTC 2016


On Wed, Apr 27, 2016 at 11:54:35AM +1000, Dave Airlie wrote:
> On 22 April 2016 at 19:03, Daniel Vetter <daniel at ffwll.ch> wrote:
> > On Fri, Apr 15, 2016 at 03:10:45PM +1000, Dave Airlie wrote:
> >> From: Dave Airlie <airlied at redhat.com>
> >>
> >> Don't just free the connector when we get the destroy callback.
> >>
> >> Drop a reference to it, and set it's mst_port to NULL so
> >> no more mst work is done on it.
> >>
> >> Signed-off-by: Dave Airlie <airlied at redhat.com>
> >
> > Looks correct, but two comments for better api for shared helpers inline below.
> > -Daniel
> >
> >> ---
> >>  drivers/gpu/drm/i915/intel_dp_mst.c | 46 ++++++++++++++++++-------------------
> >>  drivers/gpu/drm/i915/intel_drv.h    |  2 +-
> >>  2 files changed, 24 insertions(+), 24 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
> >> index a2bd698..2e730b6 100644
> >> --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> >> +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> >> @@ -113,7 +113,7 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder)
> >>
> >>       DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> >>
> >> -     drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->port);
> >> +     drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, intel_mst->connector->port);
> >>
> >>       ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr);
> >>       if (ret) {
> >> @@ -138,10 +138,12 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder)
> >>       /* and this can also fail */
> >>       drm_dp_update_payload_part2(&intel_dp->mst_mgr);
> >>
> >> -     drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->port);
> >> +     drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, intel_mst->connector->port);
> >>
> >>       intel_dp->active_mst_links--;
> >> -     intel_mst->port = NULL;
> >> +
> >> +     drm_connector_unreference(&intel_mst->connector->base);
> >> +     intel_mst->connector = NULL;
> >>       if (intel_dp->active_mst_links == 0) {
> >>               intel_dig_port->base.post_disable(&intel_dig_port->base);
> >>               intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
> >> @@ -181,7 +183,9 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
> >>       found->encoder = encoder;
> >>
> >>       DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links);
> >> -     intel_mst->port = found->port;
> >> +
> >> +     intel_mst->connector = found;
> >> +     drm_connector_reference(&intel_mst->connector->base);
> >>
> >>       if (intel_dp->active_mst_links == 0) {
> >>               intel_prepare_ddi_buffer(&intel_dig_port->base);
> >> @@ -199,7 +203,7 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder)
> >>       }
> >>
> >>       ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr,
> >> -                                    intel_mst->port,
> >> +                                    intel_mst->connector->port,
> >>                                      intel_crtc->config->pbn, &slots);
> >>       if (ret == false) {
> >>               DRM_ERROR("failed to allocate vcpi\n");
> >> @@ -248,7 +252,7 @@ static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
> >>  {
> >>       struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
> >>       *pipe = intel_mst->pipe;
> >> -     if (intel_mst->port)
> >> +     if (intel_mst->connector)
> >>               return true;
> >>       return false;
> >>  }
> >> @@ -312,6 +316,11 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector)
> >>       struct edid *edid;
> >>       int ret;
> >>
> >> +     if (!intel_connector->port || !intel_dp) {
> >> +             ret = intel_connector_update_modes(connector, NULL);
> >> +             return ret;
> >> +     }
> >> +
> >>       edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port);
> >>       if (!edid)
> >>               return 0;
> >> @@ -328,6 +337,8 @@ intel_dp_mst_detect(struct drm_connector *connector, bool force)
> >>       struct intel_connector *intel_connector = to_intel_connector(connector);
> >>       struct intel_dp *intel_dp = intel_connector->mst_port;
> >>
> >> +     if (!intel_connector->port || !intel_dp)
> >> +             return connector_status_disconnected;
> >>       return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, intel_connector->port);
> >
> > Should we push this change and the preceeding one into dp helpers, i.e.
> > make them cope with a null port? Otoh more work to fish out the
> > ->mst_mgr, so not sure.
> 
> Actually they cope with a NULL port fine, so we can drop a bit of
> those two hunks,
> 
> >
> > Hm ... isn't the mst_mgr a redundant argument, and we could figure that
> > out purely from the port? Would be a bit of refactoring, but I think the
> > shared code for this crucial bit of semantics (there's no way the mst port
> > is ever connected if it's unplugged) would be good.
> 
> No the port isn't a reference counted object, it's just a point we
> revalidate in the
> mst code. The MST manager does't disappear. So you can't get from port
> to anything
> else until you check it's valid. You can't reference count port on the
> connector or
> else you just end up with circular references between the two.

Yeah I think this is beyond my understanding of the mst helpers. Really
should fix that sometimes ;-)

> >> -     drm_modeset_unlock_all(dev);
> >> -
> >>       intel_connector->unregister(intel_connector);
> >>
> >>       drm_modeset_lock_all(dev);
> >>       intel_connector_remove_from_fbdev(intel_connector);
> >> -     drm_connector_cleanup(connector);
> >> +     intel_connector->mst_port = NULL;
> >>       drm_modeset_unlock_all(dev);
> >
> > Hm, ugly that we still need to grab modeset locks here. I'd like to avoid
> > that, since it could be a major stall. Maybe we need to have a separate
> > lock for the fbdev connector list, and then push the locking for that
> > (including refcounting) down into fbdev helpers?
> 
> If you plug out an MST device a stall isn't going to be a major worry, you
> are going to get a modeset most likely straight away.
> 
> So I think we should only address this problem when we have this problem.

Well it's more general unhappiness with how fbdev locking piggy-packs on
top of drm_modeset_lock_all(). At least ime reusing BKLs because they're
there already sooner or later leads to headaches - having separate locks
for separate things makes review easier. Avoid the stall is just a benefit
on top. Anyway, was just an idea.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the dri-devel mailing list