Hi,

On Fri, 1 Mar 2013 13:43:00 +0000
"Wade, Daniel" <dw...@meridium.com> wrote:
> -----Original Message-----
> From: owner-t...@openbsd.org [mailto:owner-t...@openbsd.org] On Behalf Of 
> Stefan Sperling
> Sent: Thursday, February 28, 2013 12:16 PM
> To: Edd Barrett
> Cc: tech@openbsd.org
> 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);
 }
 


Reply via email to