[PATCH] drm/crtc: fix connector reference counting mismatch in drm_crtc_helper_set_config
Philipp Zabel
p.zabel at pengutronix.de
Thu Jun 2 17:28:30 UTC 2016
Hi Daniel,
Am Donnerstag, den 02.06.2016, 18:21 +0200 schrieb Daniel Vetter:
[...]
> > Only the reference count of connectors that weren't previously bound to
> > an encoder should be incremented after a call to drm_crtc_helper_set_config.
> > And only the reference count of connectors that were previously bound to
> > an encoder and are unbound afterwards should ever be decremented.
> > The reference counts of the temporary copies in the save_connectors
> > should not be touched at all.
> >
> > This patch fixes the above error by only incrementing the reference count
> > of those connectors in the set that are initially not bound to any encoder,
> > and also by restoring the reference count of only those connectors in the
> > set in the failure case.
> >
> > Fixes: 0955c1250e96 ("drm/crtc: take references to connectors used in a modeset. (v2)")
> > Signed-off-by: Philipp Zabel <p.zabel at pengutronix.de>
>
> I think this is worse. We can't save/restore the connector when there's a
> kref inside of it. But there's really only 2 things we need to save
> restore:
> - connector->encoder pointer, for each connector.
> - encoder->crtc pointer, for each encoder.
>
> For a proper fix I think we need to rectify that first, then apply your
> bugfix on top. The refcount logic itself seems sound, but I've screwed
> that up way too often already.
Ok. Do we have to do it first, though? If we first get rid of the
drm_connector_unreference(&save_connectors[count++]);
part first, we can don't have to fix it up when the connector array goes
away.
> Also I'm somewhat confused about how you manage to blow things up. The
> refcount of each connector we're seeing should be 1 already: Once from the
> connector list, and a 2nd one from the lookup in the setcrtc ioctl code.
All I saw is that inside drm_crtc_helper_set_config all connectors in
the set have their refcount incremented and then *all* connectors have
their refcount decremented. Isn't the lookup refcount increment only
done for connectors in the set?
I see it look up connector 36, then reference it once more as part of
the set. At the end it tries to unreference connector 34 from
save_connectors, followed by the error:
[drm:drm_ioctl] pid=205, dev=0xe201, auth=1, DRM_IOCTL_MODE_SETCRTC
[drm:drm_mode_setcrtc] [CRTC:24:crtc-0]
[drm:drm_mode_setcrtc] [CONNECTOR:36:LVDS-1]
[drm:drm_crtc_helper_set_config]
[drm:drm_crtc_helper_set_config] [CRTC:24:c 13.982686] [drm:drm_mode_debug_printmodeline] Modeline 0:"" 0 0 0 0 0 0 0 0 0 0 0x0 0x0
[drm:drm_mode_debug_printmodeline] Modeline 41:"1280x800" 60 71100 1280 1281 1439 1440 800 801 822 823 0x40 0x0
[drm:drm_mode_object_reference] OBJ ID: 36 (2)
[drm:drm_crtc_helper_set_config] encoder changed, full mode switch
[drm:drm_crtc_helper_set_config] crtc changed, full mode switch
[drm:drm_crtc_helper_set_config] [CONNECTOR:36:LVDS-1] to [CRtc-0]
[drm:drm_crtc_helper_set_mode] [ENCODER:35:LVDS-35] set [MODE:41:1280x800]
[drm:drm_calc_timestamping_constants] crtc 24: hwmode: htotal 1440, vtotal 823, vdisplay 800
[drm:drm_calc_timestamping_constants] crtc 24: clock 71100 kHz framedur 16668354 linedur 20253
[drm:drm_crtc_helper_set_config] Setting connector DPMS state to on
[drm:drm_crtc_helper_set_config] [CONNECTOR:36:LVDS-1] set DPMS on
[drm:drm_mode_object_unreference] OBJ ID: 34 (1)
> Which means when we drop that 1 reference in the saved connector (which is
> entirely bogus code, I agree) it should only drop to 1, not 0. And youre
> cleanup code should not be called.
>
> The other thing is that radeon/nouveau also uses this code, and no one
> complained yet. Together I think that's some good evidence that suggests
> there's also something strange going on in imx itself.
That's what I wonder, too. Right now I can't see it though.
regards
Philipp
More information about the dri-devel
mailing list