usb/76687: ugen USB_SET_TIMEOUT panics kernel when timeout ocurrs

Adam Kropelin akropel1 at rochester.rr.com
Tue Jan 25 15:50:18 PST 2005


>Number:         76687
>Category:       usb
>Synopsis:       ugen USB_SET_TIMEOUT panics kernel when timeout ocurrs
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-usb
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jan 25 23:50:17 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Adam Kropelin
>Release:        6.0-CURRENT
>Organization:
>Environment:
FreeBSD freebsd53.kroptech.com 6.0-CURRENT FreeBSD 6.0-CURRENT #0: Mon Jan 24 22:19:49 EST 2005     root at freebsd53.kroptech.com:/usr/src/sys/i386/compile/GENERIC.adk  i386
>Description:
My userspace device driver (apcupsd bsd-usb) makes extensive use of ugen ioctls. Occasionally the USB_DO_REQUEST ioctl hangs (seemingly forever) and as a workaround I am attempting to implement timeouts via USB_SET_TIMEOUT. In doing so I am finding that if a request times out and the device still responds afterward, the kernel panics.

The backtrace is...

usb_transfer_complete+0xcd
uhci_abort_xfer+0xcf
uhci_timeout_task+0xd
usb_task_thread+0x7d
fork_exit+0xa4
fork_trampoline+0x8
--- trap 0x1, eip = 0, esp = 0xcc744d7c, ebp = 0 ---

..which corresponds to this code...

	/* if we allocated the buffer in usbd_transfer() we free it here. */
	if (xfer->rqflags & URQ_AUTO_DMABUF) {
c059e6d4 <usb_transfer_complete+0xa0> testb  $0x10,0x48(%ebx)
c059e6d8 <usb_transfer_complete+0xa4> je     c059e6f8 <usb_transfer_complete+0xc4>
		if (!repeat) {
c059e6da <usb_transfer_complete+0xa6> cmpl   $0x0,0xffffffe8(%ebp)
c059e6de <usb_transfer_complete+0xaa> jne    c059e714 <usb_transfer_complete+0xe0>
			struct usbd_bus *bus = pipe->device->bus;
c059e6e0 <usb_transfer_complete+0xac> mov    0x4(%esi),%eax
c059e6e3 <usb_transfer_complete+0xaf> mov    (%eax),%eax
			bus->methods->freem(bus, dmap);
c059e6e5 <usb_transfer_complete+0xb1> mov    0x4(%eax),%edx
c059e6e8 <usb_transfer_complete+0xb4> pushl  0xfffffff0(%ebp)
c059e6eb <usb_transfer_complete+0xb7> push   %eax
c059e6ec <usb_transfer_complete+0xb8> call   *0x10(%edx)
			xfer->rqflags &= ~URQ_AUTO_DMABUF;
c059e6ef <usb_transfer_complete+0xbb> andl   $0xffffffef,0x48(%ebx)
c059e6f3 <usb_transfer_complete+0xbf> add    $0x8,%esp
c059e6f6 <usb_transfer_complete+0xc2> mov    %esi,%esi
		}
	}

	if (!repeat) {
c059e6f8 <usb_transfer_complete+0xc4> cmpl   $0x0,0xffffffe8(%ebp)
c059e6fc <usb_transfer_complete+0xc8> jne    c059e714 <usb_transfer_complete+0xe0>
		/* Remove request from queue. */
#ifdef DIAGNOSTIC
		if (xfer != SIMPLEQ_FIRST(&pipe->queue))
			printf("usb_transfer_complete: bad dequeue %p != %p\n",
			       xfer, SIMPLEQ_FIRST(&pipe->queue));
		xfer->busy_free = XFER_BUSY;
#endif
		SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
c059e6fe <usb_transfer_complete+0xca> mov    0x14(%esi),%eax
c059e701 <usb_transfer_complete+0xcd> mov    0x4c(%eax),%eax
c059e704 <usb_transfer_complete+0xd0> mov    %eax,0x14(%esi)
c059e707 <usb_transfer_complete+0xd3> test   %eax,%eax
c059e709 <usb_transfer_complete+0xd5> jne    c059e714 <usb_transfer_complete+0xe0>
c059e70b <usb_transfer_complete+0xd7> lea    0x14(%esi),%eax
c059e70e <usb_transfer_complete+0xda> mov    %eax,0x18(%esi)
c059e711 <usb_transfer_complete+0xdd> lea    0x0(%esi),%esi
	}

>How-To-Repeat:
Open a ugen control endpoint, set a very short timeout (say, 1 msec) using USB_SET_TIMEOUT ioctl, and issue a valid USB_DO_REQUEST ioctl.
>Fix:
      
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-usb mailing list