usb/78986: crash when printing to usb connected printer

Ian Dowse iedowse at maths.tcd.ie
Sat Mar 19 07:50:06 PST 2005


The following reply was made to PR usb/78986; it has been noted by GNATS.

From: Ian Dowse <iedowse at maths.tcd.ie>
To: Marc van Kempen <marc at bowtie.nl>
Cc: FreeBSD-gnats-submit at 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 at 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))
  
  /*
 
 


More information about the freebsd-usb mailing list