[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <d120d5000704200857s6661f700ifc18084b32675db0@mail.gmail.com>
Date: Fri, 20 Apr 2007 11:57:27 -0400
From: "Dmitry Torokhov" <dmitry.torokhov@...il.com>
To: "Alan Stern" <stern@...land.harvard.edu>
Cc: "Tejun Heo" <htejun@...il.com>,
"Cornelia Huck" <cornelia.huck@...ibm.com>,
linux-kernel <linux-kernel@...r.kernel.org>,
"Greg K-H" <greg@...ah.com>,
"Rusty Russell" <rusty@...tcorp.com.au>
Subject: Re: [PATCH RFD] alternative kobject release wait mechanism
On 4/20/07, Alan Stern <stern@...land.harvard.edu> wrote:
>
> Dmitry, in thinking things over some more I realized there's going to be a
> problem with the autosuspend support in USB. It has to do with the way a
> driver needs to prevent (or block) suspends from occurring while it is
> actively using a device.
>
> To understand this, you need to know that USB adds a pm_mutex to the
> device structure. It gets used for synchronizing all suspend- or
> resume-related activities. In particular, the driver's suspend() method
> is called with usbdev->pm_mutex held.
>
> The next idea is that a driver needs to synchronize its remove() method
> with other methods such as read() -- we mustn't allow read() to try and
> refer to the device after the driver has been unbound. Let's say the
> driver has unbind_mutex embedded in its private data structure for this
> purpose.
>
> Now consider what read() has to do. It needs to block suspends from
> occurring while it runs, and it needs to do an autoresume if the device
> was already suspended. So read() will look like this:
>
> mutex_lock(&private->unbind_mutex);
> if (private->gone) {
> ret = -ENODEV;
> goto done;
> }
> if (private->suspended)
> autoresume(private->usbdev);
> ...
> done:
> mutex_unlock(&private->unbind_mutex);
> return ret;
>
> Meanwhile, the suspend() method needs to block while read() is running.
> So it will look like this:
>
> private->suspended = 1;
> mutex_lock(&private->unbind_mutex);
> /* Now the driver has quiesced */
> mutex_unlock(&private->unbind_mutex);
>
> Here's the problem: The autoresume() call inside read() tries to acquire
> usbdev->pm_mutex while holding private->unbind_mutex. The suspend()
> method does the reverse, a locking-order violation.
>
> So far I haven't figured out any way to make this work. Do you have a
> suggestion? (Don't say read() should hold pm_mutex as well as
> unbind_mutex; that's no good -- although the reason is rather obscure.)
>
First of all I think that I would merge pm and unbind mutex into one -
you also need to synchronize resume and suspend with bind and unbind
so you pretty much need to always acquire both of them.
Second (and I admit I have not followed USB autoresume discussions, my
usb-devle backlog is over 5000 messages ;( ) is I am not sure why
woudl a read block autoresume. I can see write doing that but passive
reads should not affect device state.
--
Dmitry
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists