From 09eaccf5f12a3e7a8446ede2dc34c188506b49cc Mon Sep 17 00:00:00 2001 From: mpi Date: Fri, 9 May 2014 11:01:06 +0000 Subject: [PATCH] Plug an xfer leak when detaching root hubs. 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 | 21 +++++---------------- sys/dev/usb/ohci.c | 18 ++++-------------- sys/dev/usb/uhci.c | 13 ++++--------- sys/dev/usb/xhci.c | 12 ++++-------- 4 files changed, 17 insertions(+), 47 deletions(-) diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index 98c5f83dcaf..d9f83687d29 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -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) { diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index 3cbc1f79dbe..f0aa949be77 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -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) { diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index b720b39eb74..7451e0dca60 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -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 diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c index 74af7cb4d1a..7f880e46fbd 100644 --- a/sys/dev/usb/xhci.c +++ b/sys/dev/usb/xhci.c @@ -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 -- 2.20.1