Re: [RFC][PATCH 1/3] PM: Introduce new top level suspend and hibernation callbacks

Alan Stern
2008-03-20T22:57:05Z

On Fri, 21 Mar 2008, Benjamin Herrenschmidt wrote:

>
> On Thu, 2008-03-20 at 14:26 -0400, Alan Stern wrote:
> >
> > One of the things we don't want to do is bind a new driver to a device
> > after it has gone through the prepare() stage. Doing so would involve
> > calling the driver's probe() routine, which is likely to want to
> > register new children and who knows what else. The probe routine might
> > even end up running after the device was suspended! Clearly this
> > should be avoided.
> >
> > But the user can force a binding to occur by writing the device's path
> > to the driver's "bind" attribute in sysfs. This means that
> > driver_bind() in drivers/base/bus.c will need to know whether or not
> > the device has gone through the prepare() stage, which means the device
> > structure will need to have a flag set before prepare() is called (more
> > precisely, the flag must be set before dev->sem is released following
> > the call to prepare).
> >
> > Either that or else driver_bind() must always block whenever a system
> > sleep is in progress. That would be easier -- but it's a lot like what
> > the freezer would do. Which would you prefer?
>
> I don't fully understand what you are saying here.
>
> You say "bind a new driver to a device after it has gone through the
> prepare() stage"
>
> So either there was already a driver bound to that device, which got a
> prepare() callback, and in which case bind() doesn't mean much. Or there
> was not, in which case there was no prepare() call involved.

That's why I said "gone through the prepare() stage" instead of saying
"after prepare() was called". Yes, if there's no driver bound then
there's no method to call. But the PM core will still pass the device
to a subroutine whose job is to call the corresponding method, if one
exists.

> I suppose if you prepare(), then unbind(), then something tries to
> bind()... But wouldn't the core flag set after prepare() be plenty
> enough to shield against that ?
>
> I fail to see the race you are talking about here.

Let's say Task 0 is starting a sleep transition when Task 1 calls
driver_bind():

Task 0 Task 1
------ ------
down(&dev->sem) succeeds down(&dev->sem) blocks
Sees that dev has no driver
so there is no prepare
method to call
up(&dev->sem)
down() succeeds
Sees that dev->power.prepared
flag isn't set
Calls (drv->probe)(dev)
Sets dev->power.prepared
flag
drv tries to register a child
device and fails for no good
reason

One way to fix this is to set dev->power.prepared before releasing
dev->sem. Another way to fix it is to have driver_bind() block
(as though it were frozen) whenever a system sleep is underway.

Which do you prefer?

Alan Stern