patch-2.3.99-pre9 linux/drivers/usb/usb-uhci.c
Next file: linux/drivers/usb/usb-uhci.h
Previous file: linux/drivers/usb/usb-storage.h
Back to the patch index
Back to the overall index
- Lines: 188
- Date:
Mon May 15 12:05:15 2000
- Orig file:
v2.3.99-pre8/linux/drivers/usb/usb-uhci.c
- Orig date:
Thu May 11 15:30:08 2000
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
@@ -12,7 +12,7 @@
* (C) Copyright 1999 Johannes Erdfelt
* (C) Copyright 1999 Randy Dunlap
*
- * $Id: usb-uhci.c,v 1.228 2000/04/02 19:55:51 acher Exp $
+ * $Id: usb-uhci.c,v 1.231 2000/05/13 15:34:17 acher Exp $
*/
#include <linux/config.h>
@@ -48,7 +48,7 @@
/* This enables an extra UHCI slab for memory debugging */
#define DEBUG_SLAB
-#define VERSTR "$Revision: 1.228 $ time " __TIME__ " " __DATE__
+#define VERSTR "$Revision: 1.231 $ time " __TIME__ " " __DATE__
#include <linux/usb.h>
#include "usb-uhci.h"
@@ -109,10 +109,10 @@
while (q != &s->free_desc) {
qh = list_entry (q, uhci_desc_t, horizontal);
+ q=qh->horizontal.prev;
+
if ((qh->last_used!=now) || force)
delete_qh(s,qh);
-
- q=qh->horizontal.prev;
}
}
/*-------------------------------------------------------------------*/
@@ -1142,6 +1142,12 @@
if (!(urb->transfer_flags & USB_TIMEOUT_KILLED))
urb->status = -ENOENT; // now the urb is really dead
+ switch (usb_pipetype (pipe)) {
+ case PIPE_ISOCHRONOUS:
+ case PIPE_INTERRUPT:
+ uhci_clean_iso_step2(s, urb_priv);
+ break;
+ }
usb_dec_dev_use (dev);
#ifdef DEBUG_SLAB
@@ -1149,12 +1155,7 @@
#else
kfree (urb_priv);
#endif
- switch (usb_pipetype (pipe)) {
- case PIPE_ISOCHRONOUS:
- case PIPE_INTERRUPT:
- uhci_clean_iso_step2(s, urb_priv);
- break;
- }
+
list_del (&urb->urb_list);
}
}
@@ -1168,7 +1169,9 @@
async_dbg("unlink_urb_async called %p",urb);
- if (urb->status == -EINPROGRESS) {
+ if ((urb->status == -EINPROGRESS) ||
+ ((usb_pipetype (urb->pipe) == PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags))
+ {
((urb_priv_t*)urb->hcpriv)->started = ~0;
dequeue_urb (s, urb);
@@ -1560,7 +1563,7 @@
urb->hcpriv = urb_priv;
INIT_LIST_HEAD (&urb_priv->desc_list);
- urb_priv->short_control_packet = 0;
+ urb_priv->flags = 0;
dbg("submit_urb: scheduling %p", urb);
urb_priv->next_queued_urb = NULL;
urb_priv->prev_queued_urb = NULL;
@@ -2151,7 +2154,7 @@
status stage is completed
*/
- if (urb_priv->short_control_packet &&
+ if (urb_priv->flags &&
((qh->hw.qh.element == UHCI_PTR_TERM) ||(!(last_desc->hw.td.status & TD_CTRL_ACTIVE))))
goto transfer_finished;
@@ -2199,7 +2202,7 @@
dbg("short packet during control transfer, retrigger status stage @ %p",last_desc);
//uhci_show_td (desc);
//uhci_show_td (last_desc);
- urb_priv->short_control_packet=1;
+ urb_priv->flags = 1; // mark as short control packet
return 0;
}
}
@@ -2280,35 +2283,43 @@
if (urb->complete) {
//dbg("process_interrupt: calling completion, status %i",status);
urb->status = status;
-
+ ((urb_priv_t*)urb->hcpriv)->flags=1; // if unlink_urb is called during completion
+
spin_unlock(&s->urb_list_lock);
urb->complete ((struct urb *) urb);
spin_lock(&s->urb_list_lock);
-
- urb->status = -EINPROGRESS;
+
+ ((urb_priv_t*)urb->hcpriv)->flags=0;
}
+
+ if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) &&
+ (urb->status != -ENOENT)) {
- // Recycle INT-TD if interval!=0, else mark TD as one-shot
- if (urb->interval) {
+ urb->status = -EINPROGRESS;
- desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE);
- if (status==0) {
- ((urb_priv_t*)urb->hcpriv)->started=jiffies;
- desc->hw.td.info |= (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
- usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
- usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
- } else {
- desc->hw.td.info |= (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
- usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+ // Recycle INT-TD if interval!=0, else mark TD as one-shot
+ if (urb->interval) {
+
+ desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE);
+ if (status==0) {
+ ((urb_priv_t*)urb->hcpriv)->started=jiffies;
+ desc->hw.td.info |= (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+ usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+ usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+ } else {
+ desc->hw.td.info |= (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+ usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+ }
+ desc->hw.td.status= (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
+ (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+ mb();
+ }
+ else {
+ uhci_unlink_urb_async(s, urb);
+ desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD
}
- desc->hw.td.status= (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
- (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
- mb();
- }
- else {
- desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD
}
}
@@ -2334,7 +2345,7 @@
dbg("process iso urb %p, %li, %i, %i, %i %08x",urb,jiffies,UHCI_GET_CURRENT_FRAME(s),
urb->number_of_packets,mode,desc->hw.td.status);
- for (i = 0; p != &urb_priv->desc_list; p = p->next, i++) {
+ for (i = 0; p != &urb_priv->desc_list; i++) {
desc = list_entry (p, uhci_desc_t, desc_list);
//uhci_show_td(desc);
@@ -2378,8 +2389,9 @@
dbg("process_iso: %i: len:%d %08x status:%x",
i, urb->iso_frame_desc[i].actual_length, desc->hw.td.status,urb->iso_frame_desc[i].status);
- delete_desc (desc);
list_del (p);
+ p = p->next;
+ delete_desc (desc);
}
dbg("process_iso: exit %i (%d), actual_len %i", i, ret,urb->actual_length);
@@ -2823,7 +2835,6 @@
pci_read_config_byte (dev, PCI_CLASS_PROG, &type);
if (type != 0)
continue;
-
if (pci_enable_device (dev) < 0)
continue;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)