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

Reply via email to