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 {