On Sun, 2 May 2004, David Brownell wrote:
I think the notion of device-to-parent reset locking is the problem. What if the device gets unplugged while you try to reset it, or it was already reset and that's why it failed, making the driver try to reset it?
With device-to-hub locking, there's no problem if the device gets
unplugged while you try to reset it. Khubd will release its lock on the
And with top-down, you'll either get a clean error before you start to reset it -- especially if that locktree() returned -ENODEV for any device already marked as NOTATTACHED! -- or, assuming khubd safely marks devices that NOTATTACHED, during the reset.
hub before calling usb_disconnect, then the reset will proceed, then khubd will lock the device and disconnect it. I don't understand the point of your second example -- what difference should it make if the device was already reset?
Typo, I meant to say "already unplugged".
Just define usb_reset_device() so the calling task may not hold the dev->serialize lock, and have its first act be to get the lock for the hub. That would imply that probe() paths would (still) not be able to call it directly though. Maybe the reset should always be queued for later.
That might be workable; I will have to think it through. Disallowing resets during probe() might be a considerable inconvenience, though. On
Except that it's never worked, so ... :)
the other hand, for usb-storage Matt Dharm just recently floated the idea of creating a work queue to perform device scanning in a separate process from probe(). Since that's where the resets would take place, it would solve this problem.
That would be good for usb-storage. DFU-style devices
Another question I need to think about: Would the reset have to acquire dev->serialize at all? Probably yes, but if it does so blindly it's liable to deadlock with disconnect. Presumably a driver's disconnect() routine won't return until the thread doing the reset has finished, but that will never happen if the thread is waiting for the serialize lock owned by the disconnect thread.
If all the locking obeys the same (correct, and presumably top-down) locking protocol, then deadlocks won't happen. That'd include the code doing the reset ... which would see -ENODEV faults starting at some point, and then fail cleanly.
Alan Stern
P.S.: Here's a question for you to consider. If the first thing usb_disconnect() does is to go through all the devices in the subtree rooted at the hub being disconnected and mark them all as USB_STATE_DISCONNECTED, and if it wants to do this as quickly as possible (hence not waiting to acquire any semaphores), how can it be sure the topology will remain stable? One possible solution, not elegant, is to require that any process deleting a children[] pointer must hold the global device-state spinlock as well as the global topology semaphore.
Last time we talked about this particular thing, I thought we agreed a spinlock protecting just usb_device->state would be correct. Some routine along these lines:
// internal to usbcore
void change_device_state(struct usb_device *dev,
enum usb_device_state state)
{
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
unsigned long flags; spin_lock_irqsave(&lock, flags);
if (dev->state != USB_STATE_UNATTACHED) {
dev->state = state;
/* hey, why not recurse right here? */
}
spin_unlock_irqrestore(&lock, flags);
}I'm not quite sure what your concern is with children[].
- Dave
-------------------------------------------------------
This SF.Net email is sponsored by: Oracle 10g
Get certified on the hottest thing ever to hit the market... Oracle 10g. Take an Oracle 10g class now, and we'll give you the exam FREE. http://ads.osdn.com/?ad_id=3149&alloc_id=8166&op=click
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
