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