On Mon, Dec 08, 2003 at 04:37:26PM -0500, Alan Stern wrote:
> On Tue, 9 Dec 2003, Herbert Xu wrote:
> 
> > On Mon, Dec 08, 2003 at 01:04:39PM -0500, Johannes Erdfelt wrote:
> >
> > > Regardless, this patch makes things worse. We need to wait for the next
> > > frame to know the hardware is done using the QHs and TDs before we can
> > > clean them up.
> > > 
> > > This patch changes this so we clean up those entries before the hardware
> > > is done, which is very bad.
> > 
> > Sorry about that.  Can you please comment on the following patch which
> > no longer frees the QHs and TDs outside of the interrupt routine.
> 
> I suspect your patch is not really needed.  Try implementing what I said 
> above and see if it helps.  Better yet, go through the code in uhci_stop() 
> more carefully than I did and figure out what it really should be doing.

Well it is still dead-locking in the same way.  Please see
http://bugs.debian.org/239245.

I've updated my async removal patch for 2.6.6.

Cheers,
-- 
Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ )
Email:  Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: drivers/usb/host/uhci-hcd.c
===================================================================
RCS file: 
/home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/drivers/usb/host/uhci-hcd.c,v
retrieving revision 1.11
diff -u -r1.11 uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c       10 May 2004 12:21:42 -0000      1.11
+++ b/drivers/usb/host/uhci-hcd.c       13 May 2004 11:56:54 -0000
@@ -95,6 +95,7 @@
 static int uhci_get_current_frame_number(struct uhci_hcd *uhci);
 static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
 static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb);
+static void uhci_irq_tail(struct usb_hcd *hcd, struct pt_regs *regs);
 
 static void hc_state_transitions(struct uhci_hcd *uhci);
 
@@ -1527,9 +1528,9 @@
 
        uhci_unlink_generic(uhci, urb);
 
-       /* If we're the first, set the next interrupt bit */
+       /* If we're the first, schedule tasklet */
        if (list_empty(&uhci->urb_remove_list))
-               uhci_set_next_interrupt(uhci);
+               tasklet_schedule(&uhci->irq_tasklet);
        list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
 
 done:
@@ -1789,6 +1790,17 @@
        return IRQ_HANDLED;
 }
 
+static void uhci_irq_tasklet(unsigned long data)
+{
+       struct usb_hcd *hcd = (void *)data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&uhci->schedule_lock, flags);
+       uhci_remove_pending_urbps(hcd_to_uhci(hcd));
+       uhci_finish_completion(hcd, NULL);
+       spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+}
+
 static void reset_hc(struct uhci_hcd *uhci)
 {
        unsigned int io_addr = uhci->io_addr;
@@ -2284,6 +2296,7 @@
         * At this point, we're guaranteed that no new connects can be made
         * to this bus since there are no more parents
         */
+       tasklet_kill(&uhci->irq_tasklet);
 
        reset_hc(uhci);
 
@@ -2353,6 +2366,8 @@
 
        memset(uhci, 0, sizeof(*uhci));
        uhci->hcd.product_desc = "UHCI Host Controller";
+       tasklet_init(&uhci->irq_tasklet, uhci_irq_tasklet,
+                    (unsigned long)&uhci->hcd);
        return &uhci->hcd;
 }
 
Index: drivers/usb/host/uhci-hcd.h
===================================================================
RCS file: 
/home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/drivers/usb/host/uhci-hcd.h,v
retrieving revision 1.7
diff -u -r1.7 uhci-hcd.h
--- a/drivers/usb/host/uhci-hcd.h       10 May 2004 12:21:42 -0000      1.7
+++ b/drivers/usb/host/uhci-hcd.h       13 May 2004 11:57:27 -0000
@@ -3,6 +3,7 @@
 
 #include <linux/list.h>
 #include <linux/usb.h>
+#include <linux/interrupt.h>
 
 #define usb_packetid(pipe)     (usb_pipein(pipe) ? USB_PID_IN : USB_PID_OUT)
 #define PIPE_DEVEP_MASK                0x0007ff00
@@ -370,6 +371,8 @@
        int rh_numports;
 
        struct timer_list stall_timer;
+
+       struct tasklet_struct irq_tasklet;
 };
 
 struct urb_priv {

Reply via email to