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 {