Re: [PATCH v4 2/2] drm/panel: Add device_link from panel device to drm device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 23.05.2018 10:29, Peter Rosin wrote:
> On 2018-05-22 17:03, Peter Rosin wrote:
>> On 2018-05-22 11:45, Andrzej Hajda wrote:
>>> On 22.05.2018 09:36, Peter Rosin wrote:
>>>> On 2018-05-22 08:29, Andrzej Hajda wrote:
>>>>> On 21.05.2018 23:56, Peter Rosin wrote:
>>>>>> On 2018-05-21 11:21, Andrzej Hajda wrote:
>>>>>>> On 21.05.2018 10:53, Peter Rosin wrote:
>>>>>>>> On 2018-05-21 10:15, Andrzej Hajda wrote:
>>>>>>>>> On 19.05.2018 18:48, Peter Rosin wrote:
>>>>>>>>>> On 2018-05-18 13:51, Andrzej Hajda wrote:
>>>>>>>>>>> On 26.04.2018 10:07, Jyri Sarha wrote:
>>>>>>>>>>>> Add device_link from panel device (supplier) to drm device (consumer)
>>>>>>>>>>>> when drm_panel_attach() is called. This patch should protect the
>>>>>>>>>>>> master drm driver if an attached panel driver unbinds while it is in
>>>>>>>>>>>> use. The device_link should make sure the drm device is unbound before
>>>>>>>>>>>> the panel driver becomes unavailable.
>>>>>>>>>>>>
>>>>>>>>>>>> The device_link is removed when drm_panel_detach() is called. The
>>>>>>>>>>>> drm_panel_detach() should be called by the consumer DRM driver, not the
>>>>>>>>>>>> panel driver, otherwise both drivers are racing to delete the same link.
>>>>>>>>>>>>
>>>>>>>>>>>> Signed-off-by: Jyri Sarha <jsarha@xxxxxx>
>>>>>>>>>>>> Reviewed-by: Eric Anholt <eric@xxxxxxxxxx>
>>>>>>>>>>> Hi Jyri,
>>>>>>>>>>>
>>>>>>>>>>> This patch breaks few platforms: tm2, tm2e, trats2 - ie all platforms
>>>>>>>>>>> using exynos_drm_dsi and dsi panels.
>>>>>>>>>>> Exynos-DSI properly handles panels unbind - ie references to panel are
>>>>>>>>>>> properly removed on panels removal and respective drm_connector enters
>>>>>>>>>>> disconnected state, without destroying whole drm device.
>>>>>>>>>>> And again on panel driver re-bind drm_panel is properly attached to
>>>>>>>>>>> exynos-dsi and panel pipeline is working again.
>>>>>>>>>>> This patch will break this behavior, ie it will destroy whole drm device.
>>>>>>>>>>>
>>>>>>>>>>> Making device_links for panels optional seems to me the best solution,
>>>>>>>>>>> what do you think?
>>>>>>>>>>>
>>>>>>>>>>> The funny thing is that due to bug in device link code, your patch has
>>>>>>>>>>> no effect on these platforms. So it does not hurt these platform yet,
>>>>>>>>>>> but the bug will be fixed sooner or later.
>>>>>>>>>> Ah, that's a pretty strong hint that we are doing something unusual. So,
>>>>>>>>>> I had a deeper look and I think that device-links (with state, i.e. not
>>>>>>>>>> DL_FLAG_STATELESS links) are assumed to be created by the .probe function
>>>>>>>>>> of either the consumer or the supplier. Then it seems to works as expected.
>>>>>>>>>> And that makes some sense too, because a link indicates that there exist
>>>>>>>>>> a dependency between the two and that the consumer cannot really exist
>>>>>>>>>> without the supplier. This is also what happens for the drm devices
>>>>>>>>>> (panel/bridge consumers) Jyri and I are working with; they call panel or
>>>>>>>>>> bridge attach during their probe. But this is not the case for exynos,
>>>>>>>>>> which calls panel/bridge attach at some later stage, and that obviously
>>>>>>>>>> violates the assumption that the device-link consumer cannot exist w/o
>>>>>>>>>> the supplier ("obviously" since the drm driver has managed to successfully
>>>>>>>>>> probe without the supplier).
>>>>>>>>>>
>>>>>>>>>> So, when the panel/bridge supplier is probed after the consumer is
>>>>>>>>>> bound, the link starts out as DL_STATE_DORMANT, and progresses to
>>>>>>>>>> DL_STATE_AVAILABLE once the panel/bridge has finished the probe. This is
>>>>>>>>>> not what *we* want.
>>>>>>>>> And this is also incorrect from Documentation PoV:
>>>>>>>>>  * @DL_STATE_DORMANT: None of the supplier/consumer drivers is present.
>>>>>>>>>  * @DL_STATE_AVAILABLE: The supplier driver is present, but the consumer
>>>>>>>>> is not.
>>>>>>>>>
>>>>>>>>>> So, one idea I have is to, on panel/bridge attach, verify if the
>>>>>>>>>> consumer is in its probe, and only create the link if that is the
>>>>>>>>>> case. So, the link would be optional, but it would all be automatic.
>>>>>>>>> Making it automatic looks tempting, but also error prone. In case of
>>>>>>>>> component framework bind callbacks can be called from probe of any
>>>>>>>>> component, so sometimes it can be called also from exynos-dsi probe,
>>>>>>>>> sometimes not (depending on order of probing, which we cannot rely on).
>>>>>>>>> So in some cases we will end-up with links, sometimes without. Ie
>>>>>>>>> following scenarios are possible in drm_panel_attach:
>>>>>>>>> 1. exynos-dsi bound, panel during probe.
>>>>>>>>> 2. exynos-dsi during probe, panel during probe.
>>>>>>>> 2. exynos-dsi during probe, panel bound? Or is this case 3, and 2 happens
>>>>>>>> when drivers probe in parallel?
>>>>>>> Panel is always probed not earlier than the end of exynos-dsi bind, so
>>>>>>> only scenarios 1 and 2 should be possible.
>>>>>>>
>>>>>>>> Whichever, you are right, I naively thought that the bind happened
>>>>>>>> after the probe of all devices, but naturally it happens as part of
>>>>>>>> the last device to register its component, and that normally happens
>>>>>>>> during its probe.
>>>>>>>>
>>>>>>>> Sigh. So, scratch that, I guess we need a flag...
>>>>>> I looked into that, and it seems very fragile to get the flag to be
>>>>>> correct for all cases. That road is bound to produce lots of bugs, and
>>>>>> it will be hard to get it right. In short, I would not descend into that
>>>>>> particular rabbit hole.
>>>>>>
>>>>>> Can it be assumed that the drm_device of the encoder in drm_bridge_attach
>>>>>> is a master component, if the drm "cluster" is componentized?
>>>>> I wouldn't call it assumption, I would say rather it is a common practice.
>>>>>
>>>>>> Are there
>>>>>> currently other ways of handling drm driver binding changes than
>>>>>> components?
>>>>> No, there are drivers which do not use components, but call
>>>>> drm_panel_attach:
>>>>> $ for d in drivers/gpu/drm/*/; do git grep -q 'struct component_ops' $d
>>>>> && continue; git grep -q drm_panel_attach $d && echo $d; done
>>>>> drivers/gpu/drm/bridge/
>>>>> drivers/gpu/drm/fsl-dcu/
>>>>> drivers/gpu/drm/mxsfb/
>>>>> drivers/gpu/drm/rcar-du/
>>>>> drivers/gpu/drm/tegra/
>>>>>
>>>>> Components are optional.
>>>> Yes, of course components are optional. The question was if there are
>>>> currently *other* ways (i.e. not the component framework, not device links)
>>>> of dealing with disappearing panels/bridges. However, see below, the
>>>> question is irrelevant with my below suggestion.
>>>>
>>>>>> If the answers are "yes" and "no", it might be possible to check if
>>>>>> encoder->dev is a master component and only establish the device link if
>>>>>> it isn't. All it would take is to add a component_device_is_master()
>>>>>> query function to drivers/base/component.c
>>>>>> Something like this (untested):
>>>>>>
>>>>>> bool component_device_is_master(struct device *dev)
>>>>>> {
>>>>>> 	struct master *m;
>>>>>>
>>>>>> 	mutex_lock(&component_mutex);
>>>>>> 	m = __master_find(dev, NULL);
>>>>>> 	mutex_unlock(&component_mutex);
>>>>>>
>>>>>> 	return !!m;
>>>>>> }
>>>>>> EXPORT_SYMBOL_GPL(component_device_is_master);
>>>>>>
>>>>>> And then check that before calling device_link_add().
>>>>> Why do not use simpler solution, just create function
>>>>> drm_panel_attach_without_link and call it explicitly from drivers, or
>>>>> add additional flag argument to either drm_panel_attach either to
>>>>> drm_panel structure? Maybe it will not be prettier but will be more
>>>>> explicit.
>>>> Because, if you take bridges into account as well and add a
>>>> drm_bridge_attach_without_link, which function do you call from e.g.
>>>> drm_simple_display_pipe_attach_bridge()? Sure, you can probably verify
>>>> the callers and come to the conclusion that you maybe always want the
>>>> link, currently. Same question for the tda998x driver, which function
>>>> to use for attaching the bridge would have to depend on how the driver
>>>> was bound (as a component or not, yes I know, currently tda998x only
>>>> does component, but the whole reason I'm involved is that I want it
>>>> to also register as a standalone drm_bridge). Not doing this with some
>>>> automatic check simply leads to combinatorial hell.
>>> I was focused on panels, which are managed not by drm core, but by
>>> upstream pipeline element (bridge/encoder). For them decision about
>>> using device links should be made by the manager not drm core, I guess.
>>> In case of bridges it is different, bridges are attached by upstream
>>> elements, but then they are tracked/managed/detached only by drm core
>>> (at least this is current practice).  If somebody wants to implement
>>> dynamic bridges this pattern cannot be used, ie bridge should be
>>> attached/detached by upstream element, like in case of panels.
>>>
>>>> Maybe a better solution is for the drm driver to record whether it
>>>> wants links in its struct drm_device, before calling drm_dev_register?
>>>> That's also explicit. drm_panel_attach/drm_bridge_attach could then
>>>> easily determine if the link should be made. IMHO, it would also be
>>>> quite easy to set this correctly for any given drm_device.
>>> As I said earlier I think decision about link creation should be always
>>> up to element which performs attachment, It only knows what should be
>>> attached, so it is the best candidate to handle dynamic unbind and
>>> re-bind of the downstream element.
>> But does the attacher in fact know *what* should be attached? And
>> how? Take e.g. the drm_panel_attach in analogix_dp_bridge_attach, in
>> analogix_dp_core.c. Should that attach be with or without a
>> device-link? 
analogix_dp_core.c is a 'library' used by exynos_dp and rockchip_dp,
neither of these drivers perform dynamic panel management so answer is
simple: device_link will protect them from panel unbind.
>> That function has no knowledge whatsoever about the
>> requirements for dp->plat_data->panel. That panel could e.g. come
>> from rockchip_dp_probe, in analogix_dp-rockchip.c, which can be
>> further traced back to drm_of_find_panel_or_bridge. But what kind of
>> requirements do that panel have? It might be a dsi panel, in which
>> case we had better not create a device-link, as you have shown
>> previously in the thread. Or it might be some little trivial panel,
>> like panel-lg-lg4573.c, in which case we *really* want the device-
>> link so that the panel doesn't disappear on us.

In general it is not a matter of panel, but of panel's consumer, ie
upstream pipe element, for example dsi host.

>>
>> Maybe it's easy to see this, if you know the ins and outs of the
>> code. But I don't see it. And I don't see how this path leads to
>> maintainable code. I still think the link-or-no-link decision needs
>> to be in a central place.
> Are not all dsi panels client on a bus, and therefore managed by a
> dsi host?

Panels are managed by dsi host only if dsi host implements it, and it is
up to dsi host author, it is not mandatory. The only case I am aware of
is exynos-dsi. I guess most developers are not aware of the problem, or
they do not care, or ... whatever. This patch shows it very clearly.

>  And are not all dsi panels attached to a dsi connector?
>
> How about this:
>
> int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
> {
> 	int ret;
>
> 	if (panel->connector)
> 		return -EBUSY;
>
> 	if (connector->connector_type != DRM_MODE_CONNECTOR_DSI) {
> 		panel->link = device_link_add(connector->dev->dev,
> 					      panel->dev, 0);
> 		if (!panel->link) {
> 			dev_err(panel->dev, "failed to link panel to %s\n",
> 				dev_name(connector->dev->dev));
> 			return -EINVAL;
> 		}
> 	}
>
> 	panel->connector = connector;
> 	panel->drm = connector->dev;
>
> 	return 0;
> }

With such approach you do not protect dsi hosts without dynamic panel
management support. As I said earlier: it is matter of panel consumers
(for example dsi host), ie if it implements dynamic panel management, it
should attach panel without creating device_links, as it take care of
disappearing panels. If it does not perform dynamic management it should
rely on default behavior - links should be created, to protect drm
device from using dangling pointers.

Regards
Andrzej

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/dri-devel




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux