Hi,
this patch fixes the oops which was detected by the poisoning in slab.c.
The bug was on of the usual "brown paper bag"-types ;-)
The rest of the patch allows the correct unlink of interrupt urbs when
done in the completion. Additionally, one-shot interrupts are
automatically unlinked after execution, thus it is also possible to stop an
periodic interrupt by setting urb->interval to zero.
Please apply to 2.3.99-pre7.
--
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 Apr 29 07:53:10 2000
+++ linux.afs/drivers/usb/usb-uhci.c Sat May 13 14:50:29 2000
@@ -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.230 2000/05/13 12:50:29 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.230 $ 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;
}
}
/*-------------------------------------------------------------------*/
@@ -1168,7 +1168,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 +1562,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 +2153,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 +2201,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 +2282,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
}
}
@@ -2823,7 +2833,6 @@
pci_read_config_byte (dev, PCI_CLASS_PROG, &type);
if (type != 0)
continue;
-
if (pci_enable_device (dev) < 0)
continue;
diff -u linux/drivers/usb/usb-uhci.h linux.afs/drivers/usb/usb-uhci.h
--- linux/drivers/usb/usb-uhci.h Thu Apr 6 02:01:25 2000
+++ linux.afs/drivers/usb/usb-uhci.h Sat May 13 14:50:30 2000
@@ -2,7 +2,7 @@
#define __LINUX_UHCI_H
/*
- $Id: usb-uhci.h,v 1.54 2000/04/02 19:55:53 acher Exp $
+ $Id: usb-uhci.h,v 1.55 2000/05/13 12:50:30 acher Exp $
*/
#define MODNAME "usb-uhci"
#define UHCI_LATENCY_TIMER 0
@@ -160,7 +160,7 @@
uhci_desc_t *bottom_qh;
uhci_desc_t *next_qh; // next helper QH
char use_loop;
- char short_control_packet;
+ char flags;
} urb_priv_t, *purb_priv_t;
struct virt_root_hub {
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]