Hello:
I am having some misunderstanding with the list software,
so I am sending this backwards, with To: list, cc: Johannes
I found that my fix for interlock between disconnects and khubd
was not entirely correct. The khubd can call usb_hub_disconnect,
which disconnects the hub under processing, and it causes
a recursive lock. The fix is to unlock the hub before
disconnecting.
Also, the way I used semaphores hurt my sense of aesthetics
very much, so I have it redone.
I would like the following patch to be reviewed, and hopefuly
applied.
Greetings,
-- Pete
--- linux-2.4.3/drivers/usb/hub.h Fri Mar 23 11:50:01 2001
+++ linux-2.4.3-p3/drivers/usb/hub.h Thu Apr 12 13:51:33 2001
@@ -109,7 +109,8 @@
struct usb_hub_descriptor *descriptor;
- struct semaphore khubd_sem;
+ atomic_t locked; /* The hub is in use by khubd */
+ wait_queue_head_t wait; /* disconnects wait here */
};
#endif
--- linux-2.4.3/drivers/usb/hub.c Sun Mar 25 18:14:21 2001
+++ linux-2.4.3-p3/drivers/usb/hub.c Thu Apr 12 16:40:50 2001
@@ -293,7 +297,7 @@
INIT_LIST_HEAD(&hub->event_list);
hub->dev = dev;
- init_MUTEX(&hub->khubd_sem);
+ init_waitqueue_head(&hub->wait);
/* Record the new hub's existence */
spin_lock_irqsave(&hub_event_lock, flags);
@@ -337,8 +341,16 @@
spin_unlock_irqrestore(&hub_event_lock, flags);
- down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
- up(&hub->khubd_sem);
+ if (atomic_read(&hub->locked)) {
+ DECLARE_WAITQUEUE(waita, current);
+ add_wait_queue(&hub->wait, &waita);
+ while (atomic_read(&hub->locked)) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule();
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&dmabuf->wait, &waita);
+ }
if (hub->urb) {
usb_unlink_urb(hub->urb);
@@ -663,16 +675,17 @@
list_del(tmp);
INIT_LIST_HEAD(tmp);
- down(&hub->khubd_sem); /* never blocks, we were on list */
+ atomic_set(&hub->locked, 1);
spin_unlock_irqrestore(&hub_event_lock, flags);
if (hub->error) {
dbg("resetting hub %d for error %d", dev->devnum, hub->error);
if (usb_hub_reset(hub)) {
+ atomic_set(&hub->locked, 0);
+ /* wake_up(&hub->wait); */
err("error resetting hub %d - disconnecting",
dev->devnum);
usb_hub_disconnect(dev);
- up(&hub->khubd_sem);
continue;
}
@@ -748,7 +761,9 @@
usb_hub_power_on(hub);
}
}
- up(&hub->khubd_sem);
+
+ atomic_set(&hub->locked, 0);
+ wake_up(&hub->wait);
} /* end while (1) */
spin_unlock_irqrestore(&hub_event_lock, flags);
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
http://lists.sourceforge.net/lists/listinfo/linux-usb-devel