From owner-freebsd-usb@FreeBSD.ORG Sat Mar 19 15:50:05 2005 Return-Path: Delivered-To: freebsd-usb@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D5FC316A4CE for ; Sat, 19 Mar 2005 15:50:05 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id A2E6A43D5D for ; Sat, 19 Mar 2005 15:50:05 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.3/8.13.3) with ESMTP id j2JFo5oU096128 for ; Sat, 19 Mar 2005 15:50:05 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.3/8.13.1/Submit) id j2JFo5FG096127; Sat, 19 Mar 2005 15:50:05 GMT (envelope-from gnats) Date: Sat, 19 Mar 2005 15:50:05 GMT Message-Id: <200503191550.j2JFo5FG096127@freefall.freebsd.org> To: freebsd-usb@FreeBSD.org From: Ian Dowse Subject: Re: usb/78986: crash when printing to usb connected printer X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Ian Dowse List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 19 Mar 2005 15:50:06 -0000 The following reply was made to PR usb/78986; it has been noted by GNATS. From: Ian Dowse To: Marc van Kempen Cc: FreeBSD-gnats-submit@FreeBSD.org Subject: Re: usb/78986: crash when printing to usb connected printer Date: Sat, 19 Mar 2005 15:40:34 +0000 In message <200503181455.j2IEtfQx073610@e16014.upc-e.chello.nl>, Marc van Kempe n writes: >Every once in a while, printing to my Samsung ML-1510 laserprinter connected >through usb will completely lock up the computer. > >>How-To-Repeat: >Print several times until it locks up. The problem is that there doesn't >seem to be a pattern to it. Hi, could you try the following patch. There appears to be a race condition when aborting a USB transfer while the transfer is currently being timed out. This fixes only the UHCI case - there are probably similar problems with the other host controllers. Ian Index: uhci.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/dev/usb/uhci.c,v retrieving revision 1.154.2.4 diff -u -r1.154.2.4 uhci.c --- uhci.c 30 Jan 2005 01:00:10 -0000 1.154.2.4 +++ uhci.c 19 Mar 2005 15:29:50 -0000 @@ -646,6 +646,7 @@ UXFER(xfer)->iinfo.sc = sc; usb_init_task(&UXFER(xfer)->abort_task, uhci_timeout_task, xfer); + UXFER(xfer)->uhci_xfer_flags = 0; #ifdef DIAGNOSTIC UXFER(xfer)->iinfo.isdone = 1; xfer->busy_free = XFER_BUSY; @@ -1933,7 +1934,8 @@ void uhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) { - uhci_intr_info_t *ii = &UXFER(xfer)->iinfo; + struct uhci_xfer *uxfer = UXFER(xfer); + uhci_intr_info_t *ii = &uxfer->iinfo; struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe; uhci_softc_t *sc = (uhci_softc_t *)upipe->pipe.device->bus; uhci_soft_td_t *std; @@ -1956,9 +1958,28 @@ 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 (uxfer->uhci_xfer_flags & UHCI_XFER_ABORTING) { + DPRINTFN(2, ("uhci_abort_xfer: already aborting\n")); + /* No need to wait if we're aborting from a timeout. */ + if (status == USBD_TIMEOUT) + return; + /* Override the status which might be USBD_TIMEOUT. */ + xfer->status = status; + DPRINTFN(2, ("uhci_abort_xfer: waiting for abort to finish\n")); + uxfer->uhci_xfer_flags |= UHCI_XFER_ABORTWAIT; + while (uxfer->uhci_xfer_flags & UHCI_XFER_ABORTING) + tsleep(&uxfer->uhci_xfer_flags, PZERO, "uhciaw", 0); + return; + } + + /* * Step 1: Make interrupt routine and hardware ignore xfer. */ s = splusb(); + uxfer->uhci_xfer_flags |= UHCI_XFER_ABORTING; xfer->status = status; /* make software ignore it */ usb_uncallout(xfer->timeout_handle, uhci_timeout, ii); usb_rem_task(xfer->pipe->device, &UXFER(xfer)->abort_task); @@ -1992,6 +2013,12 @@ #ifdef DIAGNOSTIC ii->isdone = 1; #endif + /* Do the wakeup first to avoid touching the xfer after the callback. */ + uxfer->uhci_xfer_flags &= ~UHCI_XFER_ABORTING; + if (uxfer->uhci_xfer_flags & UHCI_XFER_ABORTWAIT) { + uxfer->uhci_xfer_flags &= ~UHCI_XFER_ABORTWAIT; + wakeup(&uxfer->uhci_xfer_flags); + } usb_transfer_complete(xfer); splx(s); } Index: uhcivar.h =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/dev/usb/uhcivar.h,v retrieving revision 1.37.2.1 diff -u -r1.37.2.1 uhcivar.h --- uhcivar.h 30 Jan 2005 01:00:10 -0000 1.37.2.1 +++ uhcivar.h 19 Mar 2005 15:29:50 -0000 @@ -85,8 +85,12 @@ uhci_intr_info_t iinfo; struct usb_task abort_task; int curframe; + u_int32_t uhci_xfer_flags; }; +#define UHCI_XFER_ABORTING 0x0001 /* xfer is aborting. */ +#define UHCI_XFER_ABORTWAIT 0x0002 /* abort completion is being awaited. */ + #define UXFER(xfer) ((struct uhci_xfer *)(xfer)) /*