Subject: Re: USB Printing still panicking ...sometimes
To: Martin S. Weber <Ephaeton@gmx.net>
From: Lennart Augustsson <lennart@augustsson.net>
List: current-users
Date: 04/28/2005 16:42:11
This is a multi-part message in MIME format.
--------------050803080504090401000100
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Here's a patch (derived from FreeBSD) that I think should
fix the problem. Could you try it?
-- Lennart
Martin S. Weber wrote:
> Yo,
>
> I'm still experiencing problems with printing to a USB printer as
> previously described in a reply on netbsd-users[1] (System panics
> with "concurrent" lps, printing from like xpdf, soffice etc.) which
> I thought had disappeared. It's happening with NetBSD 3.99.3 (GENERIC.MP)
> #0: Wed Apr 20 20:26:27 CEST 2005 (whole system built at that date).
>
> This is on a p4 (ht - mp) based dell:
>
> uhci0 at pci0 dev 29 function 0: Intel 82801EB/ER USB UHCI Controller (rev. 0x02)
> uhci0: interrupting at ioapic0 pin 16 (irq 11)
> usb0 at uhci0: USB revision 1.0
> uhub0 at usb0
> uhub0: Intel UHCI root hub, class 9/0, rev 1.00/1.00, addr 1
> uhub0: 2 ports with 2 removable, self powered
> uhci[1-3] follow
> usb[1-3] follow
> uhub[1-3] follow
> ehci0 + usb4 + uhub4 follow
> ulpt0 at uhub0 port 1 configuration 1 interface 0
> ulpt0: Dell Dell Laser Printer P1500, rev 1.10/1.00, addr 2, iclass 7/1
> ulpt0: using bi-directional mode
>
> (gdb) bt
> #0 0xc0b00000 in ?? ()
> #1 0xc04a0748 in cpu_reboot ()
> #2 0xc039b783 in db_sync_cmd ()
> #3 0xc039b1ce in db_command ()
> #4 0xc039aed8 in db_command_loop ()
> #5 0xc039e2b9 in db_trap ()
> #6 0xc049d33a in kdb_trap ()
> #7 0xc04ad4da in trap ()
> #8 0xc010be63 in calltrap ()
> #9 0xc02cdde0 in uhci_abort_xfer ()
> #10 0xc02cdbf8 in uhci_device_bulk_abort ()
> #11 0xc06229f5 in usbd_ar_pipe ()
> #12 0xc06226f2 in usbd_abort_pipe ()
> #13 0xc0633ee9 in ulptclose ()
> #14 0xc04322d7 in spec_close ()
> #15 0xc0399a52 in ufsspec_close ()
> #16 0xc042b16f in VOP_CLOSE ()
> #17 0xc0429c62 in vn_close ()
> #18 0xc042a745 in vn_closefile ()
> #19 0xc03c75e7 in closef ()
> #20 0xc03c7404 in fdfree ()
> #21 0xc03cc94e in exit1 ()
> #22 0xc03cc756 in sys_exit ()
> #23 0xc04acf08 in syscall_plain ()
>
>
> I'm baking a DEBUG kernel (along with a netbsd.gdb) and see if I can
> reproduce it (it's become harder to trigger AFAICT, so could take some
> time.). I have the dump lying around if it helps someone.
>
> Regards,
>
> -Martin
>
> [1] http://mail-index.netbsd.org/netbsd-users/2005/04/12/0005.html
>
--------------050803080504090401000100
Content-Type: text/plain;
name="race.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="race.diff"
? TODO.la
? a.out
? aaa
? apa
? axe.diff
? control.ps
? ehci
? ehci.c.la
? net
? obsd
? open
? umass.c.la
? ut
Index: ehci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ehci.c,v
retrieving revision 1.95
diff -c -r1.95 ehci.c
*** ehci.c 27 Apr 2005 23:39:54 -0000 1.95
--- ehci.c 28 Apr 2005 14:38:57 -0000
***************
*** 2443,2448 ****
--- 2443,2449 ----
u_int32_t qhstatus;
int s;
int hit;
+ int wake;
DPRINTF(("ehci_abort_xfer: xfer=%p pipe=%p\n", xfer, epipe));
***************
*** 2460,2465 ****
--- 2461,2486 ----
panic("ehci_abort_xfer: not in process context");
/*
+ * If an abort is already in progress then just wait for it to
+ * complete and return.
+ */
+ if (xfer->hcflags & UXFER_ABORTING) {
+ DPRINTFN(2, ("ehci_abort_xfer: already aborting\n"));
+ #ifdef DIAGNOSTIC
+ if (status == USBD_TIMEOUT)
+ printf("ehci_abort_xfer: TIMEOUT while aborting\n");
+ #endif
+ /* Override the status which might be USBD_TIMEOUT. */
+ xfer->status = status;
+ DPRINTFN(2, ("ehci_abort_xfer: waiting for abort to finish\n"));
+ xfer->hcflags |= UXFER_ABORTWAIT;
+ while (xfer->hcflags & UXFER_ABORTING)
+ tsleep(&xfer->hcflags, PZERO, "ehciaw", 0);
+ return;
+ }
+ xfer->hcflags |= UXFER_ABORTING;
+
+ /*
* Step 1: Make interrupt routine and hardware ignore xfer.
*/
s = splusb();
***************
*** 2521,2527 ****
--- 2542,2552 ----
#ifdef DIAGNOSTIC
exfer->isdone = 1;
#endif
+ wake = xfer->hcflags & UXFER_ABORTWAIT;
+ xfer->hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT);
usb_transfer_complete(xfer);
+ if (wake)
+ wakeup(&xfer->hcflags);
splx(s);
#undef exfer
Index: ohci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/ohci.c,v
retrieving revision 1.158
diff -c -r1.158 ohci.c
*** ohci.c 17 Apr 2005 14:46:49 -0000 1.158
--- ohci.c 28 Apr 2005 14:38:58 -0000
***************
*** 2146,2151 ****
--- 2146,2152 ----
ohci_soft_td_t *p, *n;
ohci_physaddr_t headp;
int s, hit;
+ int wake;
DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,sed));
***************
*** 2162,2167 ****
--- 2163,2188 ----
panic("ohci_abort_xfer: not in process context");
/*
+ * If an abort is already in progress then just wait for it to
+ * complete and return.
+ */
+ if (xfer->hcflags & UXFER_ABORTING) {
+ DPRINTFN(2, ("ohci_abort_xfer: already aborting\n"));
+ #ifdef DIAGNOSTIC
+ if (status == USBD_TIMEOUT)
+ printf("0hci_abort_xfer: TIMEOUT while aborting\n");
+ #endif
+ /* Override the status which might be USBD_TIMEOUT. */
+ xfer->status = status;
+ DPRINTFN(2, ("ohci_abort_xfer: waiting for abort to finish\n"));
+ xfer->hcflags |= UXFER_ABORTWAIT;
+ while (xfer->hcflags & UXFER_ABORTING)
+ tsleep(&xfer->hcflags, PZERO, "ohciaw", 0);
+ return;
+ }
+ xfer->hcflags |= UXFER_ABORTING;
+
+ /*
* Step 1: Make interrupt routine and hardware ignore xfer.
*/
s = splusb();
***************
*** 2198,2203 ****
--- 2219,2225 ----
p = xfer->hcpriv;
#ifdef DIAGNOSTIC
if (p == NULL) {
+ xfer->hcflags &= ~UXFER_ABORTING; /* XXX */
splx(s);
printf("ohci_abort_xfer: hcpriv is NULL\n");
return;
***************
*** 2234,2240 ****
--- 2256,2266 ----
/*
* Step 5: Execute callback.
*/
+ wake = xfer->hcflags & UXFER_ABORTWAIT;
+ xfer->hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT);
usb_transfer_complete(xfer);
+ if (wake)
+ wakeup(&xfer->hcflags);
splx(s);
}
Index: uhci.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uhci.c,v
retrieving revision 1.185
diff -c -r1.185 uhci.c
*** uhci.c 2 Mar 2005 11:37:27 -0000 1.185
--- uhci.c 28 Apr 2005 14:38:58 -0000
***************
*** 1938,1943 ****
--- 1938,1944 ----
uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus;
uhci_soft_td_t *std;
int s;
+ int wake;
DPRINTFN(1,("uhci_abort_xfer: xfer=%p, status=%d\n", xfer, status));
***************
*** 1954,1959 ****
--- 1955,1980 ----
panic("uhci_abort_xfer: not in process context");
/*
+ * If an abort is already in progress then just wait for it to
+ * complete and return.
+ */
+ if (xfer->hcflags & UXFER_ABORTING) {
+ DPRINTFN(2, ("uhci_abort_xfer: already aborting\n"));
+ #ifdef DIAGNOSTIC
+ if (status == USBD_TIMEOUT)
+ printf("uhci_abort_xfer: TIMEOUT while aborting\n");
+ #endif
+ /* Override the status which might be USBD_TIMEOUT. */
+ xfer->status = status;
+ DPRINTFN(2, ("uhci_abort_xfer: waiting for abort to finish\n"));
+ xfer->hcflags |= UXFER_ABORTWAIT;
+ while (xfer->hcflags & UXFER_ABORTING)
+ tsleep(&xfer->hcflags, PZERO, "uhciaw", 0);
+ return;
+ }
+ xfer->hcflags |= UXFER_ABORTING;
+
+ /*
* Step 1: Make interrupt routine and hardware ignore xfer.
*/
s = splusb();
***************
*** 1989,1995 ****
--- 2010,2020 ----
#ifdef DIAGNOSTIC
ii->isdone = 1;
#endif
+ wake = xfer->hcflags & UXFER_ABORTWAIT;
+ xfer->hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT);
usb_transfer_complete(xfer);
+ if (wake)
+ wakeup(&xfer->hcflags);
splx(s);
}
Index: usbdivar.h
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/usbdivar.h,v
retrieving revision 1.73
diff -c -r1.73 usbdivar.h
*** usbdivar.h 24 Jan 2005 01:30:38 -0000 1.73
--- usbdivar.h 28 Apr 2005 14:38:59 -0000
***************
*** 217,223 ****
struct usbd_device *device;
usb_dma_t dmabuf;
! int rqflags;
#define URQ_REQUEST 0x01
#define URQ_AUTO_DMABUF 0x10
#define URQ_DEV_DMABUF 0x20
--- 217,223 ----
struct usbd_device *device;
usb_dma_t dmabuf;
! u_int8_t rqflags;
#define URQ_REQUEST 0x01
#define URQ_AUTO_DMABUF 0x10
#define URQ_DEV_DMABUF 0x20
***************
*** 225,230 ****
--- 225,233 ----
SIMPLEQ_ENTRY(usbd_xfer) next;
void *hcpriv; /* private use by the HC driver */
+ u_int8_t hcflags; /* private use by the HC driver */
+ #define UXFER_ABORTING 0x01 /* xfer is aborting. */
+ #define UXFER_ABORTWAIT 0x02 /* abort completion is being awaited. */
usb_callout_t timeout_handle;
};
--------------050803080504090401000100--