[+cc Rafael] On Tue, Feb 20, 2018 at 05:04:00PM +0200, Jyri Sarha wrote: > On 20/02/18 14:03, Thierry Reding wrote: > > On Tue, Feb 20, 2018 at 01:28:48PM +0200, Jyri Sarha wrote: > >> On 20/02/18 12:34, Thierry Reding wrote: > >>>> On Mon, Feb 19, 2018 at 10:06:22PM +0200, Jyri Sarha wrote: > >>>>> Currently there is no way for a master drm driver to protect against an > >>>>> attached panel driver from being unloaded while it is in use. The > >>>>> least we can do is to indicate the usage by incrementing the module > >>>>> reference count. [...] > >>> I disagree. module_get() is only going to protect you from unloading a > >>> module that's in use, but there are other ways to unbind a driver from > >>> the device and cause subsequent mayhem. > >>> > >>> struct device_link was "recently" introduced to fix that issue. > >> > >> Unfortunately I do not have time to do full fix for the issue, but in > >> any case I think this patch is a step to the right direction. The module > >> reference count should anyway be increased at least to know that the > >> driver code remains in memory, even if the device is not there any more. > > > > I think device links are actually a lot easier to use and give you a > > full solution for this. Essentially the only thing you need to do is add > > a call to device_link_add() in the correct place. > > > > That said, it seems to me like drm_panel_bridge_add() is not a good > > place to add this, because the panel/bridge does not follow a typical > > consumer/supplier model. It is rather a helper construct with a well- > > defined lifetime. > > > > What you do want to protect is the panel (the "parent" of the panel/ > > bridge) from going away unexpectedly. I think the best way to achieve > > that is to make the link in drm_panel_attach() with something like > > this: > > > > u32 flags = DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE; > > struct device *consumer = connector->dev->dev; > > > > link = device_link_add(consumer, panel->dev, flags); > > if (!link) { > > dev_err(panel->dev, "failed to link panel %s to %s\n", > > dev_name(panel->dev), dev_name(consumer)); > > return -EINVAL; > > } > > > > Ideally I think we'd link the panel to the connector rather than the > > top-level DRM device, but we don't have a struct device * for that, so > > this is probably as good as it gets for now. > > Thanks for the hint. Adding the link indeed unbinds the master drm > device when the panel is unloaded without any complaints. > > The annoying thing is that the master drm device does not probe again > and bind when the supplier device becomes available again. However, > forcing a manual bind brings the whole device back without a problem. > > Is there any trivial way to fix this? How about the below, would this work for you? Or is the device link added in the consumer's driver, hence is gone when the consumer is unbound? If so, it should be added somewhere else, or it shouldn't be removed on consumer unbind. @Thierry: Thanks for shifting the discussion in the right direction, it's good to see device links getting more adoption, instead of proliferating yet more kludges. However I don't understand why you say we don't have a struct device for the connector, drm_sysfs_connector_add() does create one. -- >8 -- Subject: [PATCH] driver core: Ensure consumers are probed when supplier is bound When a device link supplier is unbound (either manually or because one of its own suppliers was unbound), its consumers are unbound as well. However when that supplier is subsequently rebound, its consumers should likewise be given a chance to rebind. Achieve that by putting them on the deferred probe list in device_links_driver_bound(). The sole caller of that function, driver_bound(), triggers deferred probing afterwards. Reported-by: Jyri Sarha <jsarha@xxxxxx> Cc: Thierry Reding <thierry.reding@xxxxxxxxx> Cc: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> Signed-off-by: Lukas Wunner <lukas@xxxxxxxxx> --- drivers/base/base.h | 1 + drivers/base/core.c | 4 +++- drivers/base/dd.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/base/base.h b/drivers/base/base.h index d800de6..39370eb 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -114,6 +114,7 @@ extern void device_release_driver_internal(struct device *dev, extern void driver_detach(struct device_driver *drv); extern int driver_probe_device(struct device_driver *drv, struct device *dev); +extern void driver_deferred_probe_add(struct device *dev); extern void driver_deferred_probe_del(struct device *dev); static inline int driver_match_device(struct device_driver *drv, struct device *dev) diff --git a/drivers/base/core.c b/drivers/base/core.c index 920af22..2869d21 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -402,7 +402,8 @@ int device_links_check_suppliers(struct device *dev) * @dev: Device to update the links for. * * The probe has been successful, so update links from this device to any - * consumers by changing their status to "available". + * consumers by changing their status to "available". Mark the consumers + * for deferred probing in case the supplier was unbound and is now rebound. * * Also change the status of @dev's links to suppliers to "active". * @@ -420,6 +421,7 @@ void device_links_driver_bound(struct device *dev) WARN_ON(link->status != DL_STATE_DORMANT); WRITE_ONCE(link->status, DL_STATE_AVAILABLE); + driver_deferred_probe_add(link->consumer); } list_for_each_entry(link, &dev->links.suppliers, c_node) { diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 2c964f5..ac5a21a 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -141,7 +141,7 @@ static void deferred_probe_work_func(struct work_struct *work) } static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func); -static void driver_deferred_probe_add(struct device *dev) +void driver_deferred_probe_add(struct device *dev) { mutex_lock(&deferred_probe_mutex); if (list_empty(&dev->p->deferred_probe)) { -- 2.15.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel