Hi,
On Fri, 1 Mar 2013 13:43:00 +0000
"Wade, Daniel" <[email protected]> wrote:
> -----Original Message-----
> From: [email protected] [mailto:[email protected]] On Behalf Of
> Stefan Sperling
> Sent: Thursday, February 28, 2013 12:16 PM
> To: Edd Barrett
> Cc: [email protected]
> Subject: Re: Wake from zzz causes panic on thinkpad x60
>
> On Thu, Feb 28, 2013 at 04:59:12PM +0000, Edd Barrett wrote:
>> Went to run some TESTS for release and I am seeing panics when waking
>> my thinkpad x60 from zzz.
>>
>> I didn't have a serial line attached to get trace and ps, so I have
>> taken pictures of the kernel debugger. Sorry about that.
>>
>> http://farm9.staticflickr.com/8505/8516467142_1f3580e87a_c.jpg
>
> I've seen this panic in usb_abort_task_thread() on an x60s before.
> It doesn't happen often. It's not a new issue in recent snaps.
Same problem happens on my sony vaio vgn-sz94s.
Attached diff will fix the problem.
Remove `abort_task' from usb task queue before recycling a `struct
usbd_xfer object' which includes the `abort_task'. Otherwise
usb_abort_task_thread() may try to dequeue the recycled task then it
causes panic with page fault.
test, comment or ok?
Index: sys/dev/usb/ehci.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ehci.c,v
retrieving revision 1.131
diff -u -p -r1.131 ehci.c
--- sys/dev/usb/ehci.c 19 Apr 2013 08:58:53 -0000 1.131
+++ sys/dev/usb/ehci.c 17 May 2013 08:37:12 -0000
@@ -1204,6 +1204,7 @@ void
ehci_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
{
struct ehci_softc *sc = (struct ehci_softc *)bus;
+ struct usb_task *task = &EXFER(xfer)->abort_task;
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_BUSY) {
@@ -1217,6 +1218,8 @@ ehci_freex(struct usbd_bus *bus, struct
return;
}
#endif
+ if ((task->state & USB_TASK_STATE_ONQ) != 0)
+ usb_rem_task(xfer->pipe->device, task);
SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
}
Index: sys/dev/usb/ohci.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/ohci.c,v
retrieving revision 1.111
diff -u -p -r1.111 ohci.c
--- sys/dev/usb/ohci.c 19 Apr 2013 08:58:53 -0000 1.111
+++ sys/dev/usb/ohci.c 17 May 2013 08:37:13 -0000
@@ -974,6 +974,7 @@ void
ohci_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
{
struct ohci_softc *sc = (struct ohci_softc *)bus;
+ struct usb_task *task = &((struct ohci_xfer *)xfer)->abort_task;
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_BUSY) {
@@ -983,6 +984,8 @@ ohci_freex(struct usbd_bus *bus, struct
}
xfer->busy_free = XFER_FREE;
#endif
+ if ((task->state & USB_TASK_STATE_ONQ) != 0)
+ usb_rem_task(xfer->pipe->device, task);
SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
}
Index: sys/dev/usb/uhci.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/uhci.c,v
retrieving revision 1.96
diff -u -p -r1.96 uhci.c
--- sys/dev/usb/uhci.c 19 Apr 2013 08:58:53 -0000 1.96
+++ sys/dev/usb/uhci.c 17 May 2013 08:37:14 -0000
@@ -653,6 +653,7 @@ void
uhci_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
{
struct uhci_softc *sc = (struct uhci_softc *)bus;
+ struct usb_task *task = &UXFER(xfer)->abort_task;
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_BUSY) {
@@ -666,6 +667,8 @@ uhci_freex(struct usbd_bus *bus, struct
return;
}
#endif
+ if ((task->state & USB_TASK_STATE_ONQ) != 0)
+ usb_rem_task(xfer->pipe->device, task);
SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
}