Hi,
this patch for usb-uhci.c (and usb.h) fixes/changes the following:
- Async unlink now really moves the descriptors into the free list,
avoiding potential oopses during unload/reload of usb-uhci.
plusb easily caused that dangling descriptors...
- A small change in the urb unlink/completion sequence. With that,
plusb is much happier...
- pci_set_master called earlier
- The flag to issue zero-sized packets for bulk out, formerly known
as USB_SPD_DISABLE and thus overloaded, is now named
USB_ZERO_PACKET in usb.h
Still not fixed:
- Fix data toggles for killed bulk URBs
- Workaround for VIA-UHCI babble problem (I have contacted VIA...)
The patch is against 2.4.3 and does not include David Brownell's patches.
Johannes, please send it to Linus (and Alan, and whoever is currently
responsible ;-).
--
Georg Acher, [EMAIL PROTECTED]
http://www.in.tum.de/~acher/
"Oh no, not again !" The bowl of petunias
diff -u linux/drivers/usb/usb-uhci.c linux.afs/drivers/usb/usb-uhci.c
--- linux/drivers/usb/usb-uhci.c Sat Mar 3 19:55:48 2001
+++ linux.afs/drivers/usb/usb-uhci.c Fri Mar 30 16:51:59 2001
@@ -16,7 +16,7 @@
* (C) Copyright 1999 Randy Dunlap
* (C) Copyright 1999 Gregory P. Smith
*
- * $Id: usb-uhci.c,v 1.251 2000/11/30 09:47:54 acher Exp $
+ * $Id: usb-uhci.c,v 1.259 2001/03/30 14:51:59 acher Exp $
*/
#include <linux/config.h>
@@ -52,7 +52,7 @@
/* This enables an extra UHCI slab for memory debugging */
#define DEBUG_SLAB
-#define VERSTR "$Revision: 1.251 $ time " __TIME__ " " __DATE__
+#define VERSTR "$Revision: 1.259 $ time " __TIME__ " " __DATE__
#include <linux/usb.h>
#include "usb-uhci.h"
@@ -803,7 +803,7 @@
{
uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv;
urb_priv_t *urb_priv = urb->hcpriv;
- uhci_desc_t *qh, *td, *nqh, *bqh, *first_td=NULL;
+ uhci_desc_t *qh, *td, *nqh=NULL, *bqh=NULL, *first_td=NULL;
unsigned long destination, status;
char *data;
unsigned int pipe = urb->pipe;
@@ -900,8 +900,8 @@
data += pktsze;
len -= pktsze;
-
- last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze ||
!(urb->transfer_flags & USB_DISABLE_SPD)));
+ // Use USB_ZERO_PACKET to finish bulk OUTs always with a zero length
+packet
+ last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze ||
+!(urb->transfer_flags & USB_ZERO_PACKET)));
if (last)
td->hw.td.status |= TD_CTRL_IOC; // last one generates
INT
@@ -1178,6 +1178,9 @@
urb_priv = (urb_priv_t*)urb->hcpriv;
q = urb->urb_list.next;
+ if (!urb_priv) // avoid crash when URB is corrupted
+ break;
+
if (force ||
((urb_priv->started != 0xffffffff) && (urb_priv->started != now)))
{
async_dbg("async cleanup %p",urb);
@@ -1205,7 +1208,8 @@
pipe = urb->pipe; // completion may destroy
all...
dev = urb->dev;
urb_priv = urb->hcpriv;
-
+ list_del (&urb->urb_list);
+
if (urb->complete) {
spin_unlock(&s->urb_list_lock);
urb->dev = NULL;
@@ -1229,7 +1233,6 @@
kfree (urb_priv);
#endif
- list_del (&urb->urb_list);
}
}
}
@@ -2282,8 +2285,11 @@
for (; p != &qh->vertical; p = p->next) {
desc = list_entry (p, uhci_desc_t, vertical);
- if (desc->hw.td.status & TD_CTRL_ACTIVE) // do not process
active TDs
+ if (desc->hw.td.status & TD_CTRL_ACTIVE) { // do not process
+active TDs
+ if (mode==2) // if called from async_unlink
+ uhci_clean_transfer(s, urb, qh, mode);
return ret;
+ }
actual_length = (desc->hw.td.status + 1) & 0x7ff; //
extract transfer parameters from TD
maxlength = (((desc->hw.td.info >> 21) & 0x7ff) + 1) & 0x7ff;
@@ -2942,6 +2951,8 @@
if (pci_enable_device(dev) < 0)
return -ENODEV;
+ pci_set_master(dev);
+
/* Search for the IO base address.. */
for (i = 0; i < 6; i++) {
@@ -2955,8 +2966,7 @@
break;
/* disable legacy emulation */
pci_write_config_word (dev, USBLEGSUP, 0);
-
- pci_set_master(dev);
+
return alloc_uhci(dev, dev->irq, io_addr, io_size);
}
return -ENODEV;
diff -u linux/include/linux/usb.h linux.afs/include/linux/usb.h
--- linux/include/linux/usb.h Tue Mar 27 01:49:54 2001
+++ linux.afs/include/linux/usb.h Fri Mar 30 15:54:08 2001
@@ -424,6 +424,7 @@
#define USB_ASYNC_UNLINK 0x0008
#define USB_QUEUE_BULK 0x0010
#define USB_NO_FSBR 0x0020
+#define USB_ZERO_PACKET 0x0040 // Finish bulk OUTs always with zero length
+packet
#define USB_TIMEOUT_KILLED 0x1000 // only set by HCD!
typedef struct