Plug an xfer leak when detaching root hubs.
authormpi <mpi@openbsd.org>
Fri, 9 May 2014 11:01:06 +0000 (11:01 +0000)
committermpi <mpi@openbsd.org>
Fri, 9 May 2014 11:01:06 +0000 (11:01 +0000)
This leak is similar to the public xfer leak #1 that was affecting
device interrupt pipes except that root hubs are rarely detached.

Note that this xfer is never associated to any TD and is just used
to indicate that some of the HC ports has changed status, so there
is no need to flag it as "done" before completing it.

sys/dev/usb/ehci.c
sys/dev/usb/ohci.c
sys/dev/usb/uhci.c
sys/dev/usb/xhci.c

index 98c5f83..d9f8368 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ehci.c,v 1.152 2014/05/08 14:00:52 mpi Exp $ */
+/*     $OpenBSD: ehci.c,v 1.153 2014/05/09 11:01:06 mpi Exp $ */
 /*     $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $        */
 
 /*
@@ -2305,8 +2305,7 @@ ehci_root_intr_transfer(struct usbd_xfer *xfer)
 usbd_status
 ehci_root_intr_start(struct usbd_xfer *xfer)
 {
-       struct usbd_pipe *pipe = xfer->pipe;
-       struct ehci_softc *sc = (struct ehci_softc *)pipe->device->bus;
+       struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
 
        if (sc->sc_bus.dying)
                return (USBD_IOERROR);
@@ -2316,31 +2315,23 @@ ehci_root_intr_start(struct usbd_xfer *xfer)
        return (USBD_IN_PROGRESS);
 }
 
-/* Abort a root interrupt request. */
 void
 ehci_root_intr_abort(struct usbd_xfer *xfer)
 {
+       struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
        int s;
 
-       if (xfer->pipe->intrxfer == xfer) {
-               DPRINTF(("ehci_root_intr_abort: remove\n"));
-               xfer->pipe->intrxfer = NULL;
-       }
+       sc->sc_intrxfer = NULL;
+
        xfer->status = USBD_CANCELLED;
        s = splusb();
        usb_transfer_complete(xfer);
        splx(s);
 }
 
-/* Close the root pipe. */
 void
 ehci_root_intr_close(struct usbd_pipe *pipe)
 {
-       struct ehci_softc *sc = (struct ehci_softc *)pipe->device->bus;
-
-       DPRINTF(("ehci_root_intr_close\n"));
-
-       sc->sc_intrxfer = NULL;
 }
 
 void
@@ -2348,8 +2339,6 @@ ehci_root_ctrl_done(struct usbd_xfer *xfer)
 {
 }
 
-/************************/
-
 struct ehci_soft_qh *
 ehci_alloc_sqh(struct ehci_softc *sc)
 {
index 3cbc1f7..f0aa949 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ohci.c,v 1.128 2014/05/04 14:42:36 mpi Exp $ */
+/*     $OpenBSD: ohci.c,v 1.129 2014/05/09 11:01:06 mpi Exp $ */
 /*     $NetBSD: ohci.c,v 1.139 2003/02/22 05:24:16 tsutsui Exp $       */
 /*     $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $       */
 
@@ -2624,35 +2624,25 @@ ohci_root_intr_start(struct usbd_xfer *xfer)
        return (USBD_IN_PROGRESS);
 }
 
-/* Abort a root interrupt request. */
 void
 ohci_root_intr_abort(struct usbd_xfer *xfer)
 {
+       struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
        int s;
 
-       if (xfer->pipe->intrxfer == xfer) {
-               DPRINTF(("ohci_root_intr_abort: remove\n"));
-               xfer->pipe->intrxfer = NULL;
-       }
+       sc->sc_intrxfer = NULL;
+
        xfer->status = USBD_CANCELLED;
        s = splusb();
        usb_transfer_complete(xfer);
        splx(s);
 }
 
-/* Close the root pipe. */
 void
 ohci_root_intr_close(struct usbd_pipe *pipe)
 {
-       struct ohci_softc *sc = (struct ohci_softc *)pipe->device->bus;
-
-       DPRINTF(("ohci_root_intr_close\n"));
-
-       sc->sc_intrxfer = NULL;
 }
 
-/************************/
-
 usbd_status
 ohci_device_ctrl_transfer(struct usbd_xfer *xfer)
 {
index b720b39..7451e0d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uhci.c,v 1.115 2014/05/08 14:00:52 mpi Exp $  */
+/*     $OpenBSD: uhci.c,v 1.116 2014/05/09 11:01:06 mpi Exp $  */
 /*     $NetBSD: uhci.c,v 1.172 2003/02/23 04:19:26 simonb Exp $        */
 /*     $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $       */
 
@@ -3294,24 +3294,19 @@ uhci_root_ctrl_close(struct usbd_pipe *pipe)
        DPRINTF(("uhci_root_ctrl_close\n"));
 }
 
-/* Abort a root interrupt request. */
 void
 uhci_root_intr_abort(struct usbd_xfer *xfer)
 {
        struct uhci_softc *sc = (struct uhci_softc *)xfer->device->bus;
+       int s;
 
        timeout_del(&sc->sc_poll_handle);
        sc->sc_intr_xfer = NULL;
 
-       if (xfer->pipe->intrxfer == xfer) {
-               DPRINTF(("uhci_root_intr_abort: remove\n"));
-               xfer->pipe->intrxfer = 0;
-       }
        xfer->status = USBD_CANCELLED;
-#ifdef DIAGNOSTIC
-       ((struct uhci_xfer *)xfer)->isdone = 1;
-#endif
+       s = splusb();
        usb_transfer_complete(xfer);
+       splx(s);
 }
 
 usbd_status
index 74af7cb..7f880e4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: xhci.c,v 1.10 2014/04/29 12:45:29 mpi Exp $ */
+/* $OpenBSD: xhci.c,v 1.11 2014/05/09 11:01:06 mpi Exp $ */
 
 /*
  * Copyright (c) 2014 Martin Pieuchot
@@ -2092,10 +2092,12 @@ xhci_root_intr_start(struct usbd_xfer *xfer)
 void
 xhci_root_intr_abort(struct usbd_xfer *xfer)
 {
+       struct xhci_softc *sc = (struct xhci_softc *)xfer->device->bus;
        int s;
 
-       xfer->status = USBD_CANCELLED;
+       sc->sc_intrxfer = NULL;
 
+       xfer->status = USBD_CANCELLED;
        s = splusb();
        usb_transfer_complete(xfer);
        splx(s);
@@ -2104,12 +2106,6 @@ xhci_root_intr_abort(struct usbd_xfer *xfer)
 void
 xhci_root_intr_done(struct usbd_xfer *xfer)
 {
-       struct xhci_softc *sc = (struct xhci_softc *)xfer->device->bus;
-
-       KASSERT(sc->sc_intrxfer == xfer);
-
-       if (!xfer->pipe->repeat)
-               sc->sc_intrxfer = NULL;
 }
 
 usbd_status