patch-2.4.4 linux/drivers/usb/usb-uhci.c
Next file: linux/drivers/usb/usb.c
Previous file: linux/drivers/usb/usb-ohci.h
Back to the patch index
Back to the overall index
- Lines: 142
- Date:
Fri Apr 27 15:13:07 2001
- Orig file:
v2.4.3/linux/drivers/usb/usb-uhci.c
- Orig date:
Sat Mar 3 10:55:48 2001
diff -u --recursive --new-file v2.4.3/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
@@ -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);
}
}
}
@@ -1411,7 +1414,7 @@
/*-------------------------------------------------------------------*/
// submits USB interrupt (ie. polling ;-)
// ASAP-flag set implicitely
-// if period==0, the the transfer is only done once
+// if period==0, the transfer is only done once
_static int uhci_submit_int_urb (urb_t *urb)
{
@@ -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;
@@ -2390,7 +2396,7 @@
usb_endpoint_halt (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
}
- // if any error occured: ignore this td, and continue
+ // if any error occurred: ignore this td, and continue
if (status != 0) {
//uhci_show_td (desc);
urb->error_count++;
@@ -2625,19 +2631,22 @@
// Completion
if (urb->complete) {
+ int was_unlinked = (urb->status == -ENOENT);
urb->dev = NULL;
spin_unlock(&s->urb_list_lock);
urb->complete ((struct urb *) urb);
// Re-submit the URB if ring-linked
- if (is_ring && (urb->status != -ENOENT) && !contains_killed) {
+ if (is_ring && !was_unlinked && !contains_killed) {
urb->dev=usb_dev;
uhci_submit_urb (urb);
- }
+ } else
+ urb = 0;
spin_lock(&s->urb_list_lock);
}
usb_dec_dev_use (usb_dev);
- spin_unlock(&urb->lock);
+ if (urb)
+ spin_unlock(&urb->lock);
}
}
@@ -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;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)