On Wed, Dec 09, 2020 at 02:28:18PM -0600, Bjorn Andersson wrote: > On Tue 08 Dec 17:52 CST 2020, Daniel Vetter wrote: > > > On Tue, Dec 08, 2020 at 04:02:16PM -0600, Bjorn Andersson wrote: > > > On Tue 08 Dec 06:47 CST 2020, Thierry Reding wrote: > > > > > > > On Mon, Dec 07, 2020 at 10:44:46PM -0600, Bjorn Andersson wrote: > > > > > Some bridge chips, such as the TI SN65DSI86 DSI/eDP bridge, provides > > > > > means of generating a PWM signal for backlight control of the attached > > > > > panel. The provided PWM chip is typically controlled by the > > > > > pwm-backlight driver, which if tied to the panel will provide DPMS. > > > > > > > > > > But with the current implementation the panel will refuse to probe > > > > > because the bridge driver has yet to probe and register the PWM chip, > > > > > and the bridge driver will refuse to probe because it's unable to find > > > > > the panel. > > > > > > > > What you're describing is basically a circular dependency. Can't we get > > > > rid of that in some other way? Why exactly does the bridge driver refuse > > > > to probe if the panel can't be found? > > > > > > > > In other words, I see how the bridge would /use/ the panel in that it > > > > forward a video stream to it. But how does the panel /use/ the bridge? > > > > > > > > > > Yes, this is indeed a circular dependency between the components. > > > > > > The involved parts are: > > > * the bridge driver that implements the PWM chip probe defers on > > > drm_of_find_panel_or_bridge() failing to find the panel. > > > * the pwm-backlight driver that consumes the PWM channel probe defer > > > because the pwm_chip was not registered by the bridge. > > > * the panel that uses the backlight for DPMS purposes probe defer > > > because drm_panel_of_backlight() fails to find the pwm-backlight. > > > > > > I looked at means of postponing drm_of_find_panel_or_bridge() to > > > drm_bridge_funcs->attach(), but at that time "deferral" would be fatal. > > > I looked at registering the pwm_chip earlier, but that would depend on a > > > guarantee of the pwm-backlight and panel driver to probe concurrently. > > > And the current solution of not tying the backlight to the panel means > > > that when userspace decides to DPMS the display the backlight stays on. > > > > > > > > > The proposed solution (hack?) means that DPMS operations happening > > > before the pwm-backlight has probed will be missed, so it's not perfect. > > > It does however allow the backlight on my laptop to turn off, which is a > > > big improvement. > > > > > > But I'm certainly welcome to suggestions. > > > > Entirely hand-waving, why doesn't the following work: > > > > 1. driver for the platform device which is the bridge loads > > 2. that platform driver registers the pwm > > 3. it registers some magic for later on (more below) > > 4. panel driver has deferred loading until step 2 happened > > 5. panel driver registers drm_panel > > 6. the magic from step 3 picks up (after having been deferred for a few > > times probably) grabs the panel, and sets up the actual drm_bridge driver > > > > Everyone happy, or not? From the description it looks like the problem > > that the pwm that we need for the backlight is tied to the same driver as > > the drm_bridge, and always torn down too if the drm_bridge setup fails > > somehow for a reason. And that reason is the circular dependency this > > creates. > > > > Now for the magic in step 3, there's options: > > - change DT to split out that pwm as a separate platform_device, that way > > bridge and panel can load indepedently (hopefully) > > > > This is an i2c device, so describing it multiple times would mean we > have multiple devices with the same address... > > > - convert bridge to a multi-function device (mfd), essentially a way to > > instantiate more devices with their drivers at runtime. Then the actual > > pwm and drm_bridge parts of your bridge driver bind against those > > sub-functions, and can defer indepedently > > > > But, this sounds reasonable and would rely on the existing probe > deferral logic and if there's ever any improvements in this area we > would directly benefit from it. > > > - we could create a callback/wait function for "pls wait for any panel to > > show up". Then your bridge driver could launch a work_struct with that > > wait function, which will do the bridge setup once the panel has shown > > up. The pwm will be registered right away. It's essentially hand-rolling > > EPROBE_DEFERRED for work_struct in drm/panel. Maybe we might even have > > that exported from the driver core, e.g. > > > > register_bridge_fn(struct work *) > > { > > do_wait_probe_defer(); > > panel = drm_of_find_panel_or_bridge(); > > if (!panel) { > > schedule_work(); /* want to restart the work so it can be > > stopped on driver unload */ > > return; > > } > > > > /* we have the panel now, register drm_bridge */ > > } > > > > - cobble something together with component.c, but that's more for > > collecting unrelated struct device into a logical one than splitting it > > up more. > > > > tldr; I think you can split this loop here at the bridge by untangling the > > pwm from the drm_bridge part sufficiently. > > Yes, it seems like a reasonable path forward. But I wanted some input > before refactoring the whole thing.
Yeah it's unfortunately a bit of work. But I think it's the proper approach since EPROBE_DEFERRED is fundamentally linked to struct device and bound drivers. So we do need a struct device for every part in our dependency graph to make sure we can resolve the dependencies all correctly with reprobing. -Daniel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch