On Sat, 10 Jul 2004, David Brownell wrote: > That's part of the point. It doesn't fix those problems which > will show up most easily with suspend/resume of a device tree. > We've been over that one before, not long after I first posted > locktree() code and early CONFIG_USB_SUSPEND patches.
Yes. As I recall, we agreed that suspend/resume were special cases that really did need to use locktree(), but other things (like disconnect) did not. > > There are relatively few places that need to lock more than one device at > > a time, and they can all be fixed up. Most of them will be fairly simple > > to change; probably usb_disconnect() will be the worst case. > > In part because its calling convention has always been kind of rude! > > So that "lock(dev); usb_disconnect(dev); unlock(dev); release(dev);" > and similar "obviously correct" code sequences don't work, since it's > got more than the usual amount of side-effects magic. That's part of the problem, yes. Another part is the way usb_disconnect() needs to receive a pointer to a pointer so that it can break the appropriate tree link. Not to mention the fact that it has to be able to disconnect root hubs, which don't have normal parents. On the whole, usb_disconnect() is so special that I don't mind giving it individualized treatment. If only it were called from fewer places! > Only people working inside usbcore should ever need to worry about > the complicated stuff. Everyone else just goes lock()...unlock(). > > As currently coded (nyet integration tested) the rwsem is still > hidden, but "hub-aware" code is allowed to down(&serialize) > after lock_device() for the root of a subtree. Okay, I'll do it that way. > > I don't understand why this is needed. On all occasions when a device is > > locked, apart from suspend() and resume(), it's not necessary to lock the > > entire subtree below the device. Locktree() would be overkill. > > That's not very true. Disconnect processing will certainly lock > the whole subtree. You can't reset hubs without resetting their > children. You shouldn't be able to unbind the hub driver from > a hub without disconnecting the children. And so on. I disagree. Bear in mind that the whole point of locktree() is that it prevents thread B from locking a sub-portion of the subtree already locked by thread A. Thus, it prevents B from resuming a subset of the devices that A is trying to suspend. There's no need for such a thing with disconnect -- who cares if B tries to do something with devices that A has disconnected (or is about to disconnect)? Or vice versa, who cares if B wants to disconnect some devices that A has suspended (or is about to suspend)? Locktree() is overkill here, as I said. While it's true that you can't reset hubs without resetting their children, in our current implementation you can't reset hubs without _disconnecting_ their children. (Doesn't resetting an external hub cause it to turn off power to all its ports?) Thus resetting falls into the same category as disconnect and doesn't need locktree(). Likewise, since unbinding the hub driver from a hub now disconnects the hub's children, again this is an instance of disconnect and doesn't need locktree(). > Plus of course, if it's not a hub, none of that's an issue. It'll > be transparent to device drivers that don't manipulate hubs, and > the only cost will be a few instructions that prevent some nasty > interference scenarios. Instructions that involve taking unnecessary locks, causing unknown delays, and not preventing any scenarios I've been able to think of. > > It's not clear why usb_lock_device() has to check whether the device is > > gone. If the device is gone, that fact will be detected later on anyway. > > Why disturb all the existing code that assumes device locking always > > succeeds? > > Any disturbance isn't actually much at all, considering that the code > I changed is more or less from > > lock_device(); > if (it_vanished()) { > unlock_device(); > return -ENODEV; > } > to > if (lock_device() < 0) > return -ENODEV; Okay, that's easily added into usb_lock_device() if you really want. But given that locktree() is going to explicitly call down(&udev->serialize), it will have to make this check for itself anyway. So I don't see much advantage to adding it into usb_lock_device(). > Inconsistencies in locking models always bother me, since they > normally provide very pleasant spots for bug colonies to settle. > > I'd ask it this way: why should lock_for_reset() ever succeed > in a case where lock() would fail? Actually there is one case where lock_for_reset() succeeds and lock() would fail. It's by design. If you call lock_for_reset() from within probe() it immediately returns success, without actually locking anything -- there's no need since the device lock is already held. Of course if you tried a simple lock() under those circumstances it would hang. In fact, that special case was one of the two main reasons for creating lock_for_reset(). The other special case was locking during disconnect(), which fails immediately rather than hanging. Alan Stern ------------------------------------------------------- This SF.Net email sponsored by Black Hat Briefings & Training. Attend Black Hat Briefings & Training, Las Vegas July 24-29 - digital self defense, top technical experts, no vendor pitches, unmatched networking opportunities. Visit www.blackhat.com _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel