Module Name:    src
Committed By:   riastradh
Date:           Sat Feb 15 01:21:56 UTC 2020

Modified Files:
        src/sys/arch/mips/adm5120/dev: ahci.c
        src/sys/dev/ic: sl811hs.c
        src/sys/dev/usb: ehci.c motg.c ohci.c uhci.c vhci.c xhci.c
        src/sys/external/bsd/dwc2: dwc2.c

Log Message:
Fix mistakes in previous sloppy change with root intr xfers.

- Make sure ux_status is set to USBD_IN_PROGRESS when started.
  Otherwise, if it is still in flight when we abort the pipe,
  usbd_ar_pipe will skip calling upm_abort.

- Initialize ux_status under the lock; in principle a completion
  interrupt (or a delay) could race with the initialization.

- KASSERT that the xfer is in progress when we're about to complete
  it.

Candidate fix for PR kern/54963 for other HCI drivers than uhci.

ok nick
ok phone

(This is the change that nick evidently MEANT to ok when he ok'd the
previous one!)


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/mips/adm5120/dev/ahci.c
cvs rdiff -u -r1.102 -r1.103 src/sys/dev/ic/sl811hs.c
cvs rdiff -u -r1.272 -r1.273 src/sys/dev/usb/ehci.c
cvs rdiff -u -r1.26 -r1.27 src/sys/dev/usb/motg.c
cvs rdiff -u -r1.294 -r1.295 src/sys/dev/usb/ohci.c
cvs rdiff -u -r1.292 -r1.293 src/sys/dev/usb/uhci.c
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/usb/vhci.c
cvs rdiff -u -r1.117 -r1.118 src/sys/dev/usb/xhci.c
cvs rdiff -u -r1.68 -r1.69 src/sys/external/bsd/dwc2/dwc2.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/mips/adm5120/dev/ahci.c
diff -u src/sys/arch/mips/adm5120/dev/ahci.c:1.19 src/sys/arch/mips/adm5120/dev/ahci.c:1.20
--- src/sys/arch/mips/adm5120/dev/ahci.c:1.19	Wed Feb 12 16:02:01 2020
+++ src/sys/arch/mips/adm5120/dev/ahci.c	Sat Feb 15 01:21:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: ahci.c,v 1.19 2020/02/12 16:02:01 riastradh Exp $	*/
+/*	$NetBSD: ahci.c,v 1.20 2020/02/15 01:21:56 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2007 Ruslan Ermilov and Vsevolod Lobko.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ahci.c,v 1.19 2020/02/12 16:02:01 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ahci.c,v 1.20 2020/02/15 01:21:56 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -438,6 +438,7 @@ ahci_poll_hub(void *arg)
 	xfer = sc->sc_intr_xfer;
 	if (xfer == NULL)
 		goto out;
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
 
 	/*
 	 * If the intr xfer for which we were scheduled is done, and
@@ -754,11 +755,14 @@ ahci_root_intr_start(struct usbd_xfer *x
 
 	DPRINTF(D_TRACE, ("SLRIstart "));
 
+	mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intr_xfer == NULL);
-
 	sc->sc_interval = MS_TO_TICKS(xfer->ux_pipe->up_endpoint->ue_edesc->bInterval);
 	callout_schedule(&sc->sc_poll_handle, sc->sc_interval);
 	sc->sc_intr_xfer = xfer;
+	xfer->ux_status = USBD_IN_PROGRESS;
+	mutex_exit(&sc->sc_lock);
+
 	return USBD_IN_PROGRESS;
 }
 

Index: src/sys/dev/ic/sl811hs.c
diff -u src/sys/dev/ic/sl811hs.c:1.102 src/sys/dev/ic/sl811hs.c:1.103
--- src/sys/dev/ic/sl811hs.c:1.102	Fri Dec 27 09:41:50 2019
+++ src/sys/dev/ic/sl811hs.c	Sat Feb 15 01:21:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: sl811hs.c,v 1.102 2019/12/27 09:41:50 msaitoh Exp $	*/
+/*	$NetBSD: sl811hs.c,v 1.103 2020/02/15 01:21:56 riastradh Exp $	*/
 
 /*
  * Not (c) 2007 Matthew Orgass
@@ -68,7 +68,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.102 2019/12/27 09:41:50 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sl811hs.c,v 1.103 2020/02/15 01:21:56 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_slhci.h"
@@ -1030,7 +1030,9 @@ slhci_root_start(struct usbd_xfer *xfer)
 	KASSERT(spipe->ptype == PT_ROOT_INTR);
 
 	mutex_enter(&sc->sc_intr_lock);
+	KASSERT(t->rootintr == NULL);
 	t->rootintr = xfer;
+	xfer->ux_status = USBD_IN_PROGRESS;
 	mutex_exit(&sc->sc_intr_lock);
 
 	return USBD_IN_PROGRESS;
@@ -2389,6 +2391,8 @@ slhci_callback(struct slhci_softc *sc)
 			if (t->rootintr != NULL) {
 				u_char *p;
 
+				KASSERT(t->rootintr->ux_status ==
+				    USBD_IN_PROGRESS);
 				p = t->rootintr->ux_buf;
 				p[0] = 2;
 				t->rootintr->ux_actlen = 1;

Index: src/sys/dev/usb/ehci.c
diff -u src/sys/dev/usb/ehci.c:1.272 src/sys/dev/usb/ehci.c:1.273
--- src/sys/dev/usb/ehci.c:1.272	Wed Feb 12 16:02:01 2020
+++ src/sys/dev/usb/ehci.c	Sat Feb 15 01:21:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: ehci.c,v 1.272 2020/02/12 16:02:01 riastradh Exp $ */
+/*	$NetBSD: ehci.c,v 1.273 2020/02/15 01:21:56 riastradh Exp $ */
 
 /*
  * Copyright (c) 2004-2012 The NetBSD Foundation, Inc.
@@ -53,7 +53,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.272 2020/02/12 16:02:01 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.273 2020/02/15 01:21:56 riastradh Exp $");
 
 #include "ohci.h"
 #include "uhci.h"
@@ -785,6 +785,7 @@ ehci_pcd(void *addr)
 		/* Just ignore the change. */
 		goto done;
 	}
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
 
 	p = xfer->ux_buf;
 	m = uimin(sc->sc_noport, xfer->ux_length * 8 - 1);
@@ -2724,11 +2725,11 @@ ehci_root_intr_start(struct usbd_xfer *x
 		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer == NULL);
 	sc->sc_intrxfer = xfer;
+	xfer->ux_status = USBD_IN_PROGRESS;
 	if (!polling)
 		mutex_exit(&sc->sc_lock);
 
-	xfer->ux_status = USBD_IN_PROGRESS;
-	return xfer->ux_status;
+	return USBD_IN_PROGRESS;
 }
 
 /* Abort a root interrupt request. */

Index: src/sys/dev/usb/motg.c
diff -u src/sys/dev/usb/motg.c:1.26 src/sys/dev/usb/motg.c:1.27
--- src/sys/dev/usb/motg.c:1.26	Wed Feb 12 16:01:00 2020
+++ src/sys/dev/usb/motg.c	Sat Feb 15 01:21:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: motg.c,v 1.26 2020/02/12 16:01:00 riastradh Exp $	*/
+/*	$NetBSD: motg.c,v 1.27 2020/02/15 01:21:56 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004, 2011, 2012, 2014 The NetBSD Foundation, Inc.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.26 2020/02/12 16:01:00 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.27 2020/02/15 01:21:56 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -991,8 +991,16 @@ motg_root_intr_abort(struct usbd_xfer *x
 	KASSERT(mutex_owned(&sc->sc_lock));
 	KASSERT(xfer->ux_pipe->up_intrxfer == xfer);
 
-	sc->sc_intr_xfer = NULL;
+	/* If xfer has already completed, nothing to do here.  */
+	if (sc->sc_intr_xfer == NULL)
+		return;
 
+	/*
+	 * Otherwise, sc->sc_intr_xfer had better be this transfer.
+	 * Cancel it.
+	 */
+	KASSERT(sc->sc_intr_xfer == xfer);
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
 	xfer->ux_status = USBD_CANCELLED;
 	usb_transfer_complete(xfer);
 }
@@ -1032,7 +1040,14 @@ motg_root_intr_start(struct usbd_xfer *x
 	if (sc->sc_dying)
 		return USBD_IOERROR;
 
+	if (!polling)
+		mutex_enter(&sc->sc_lock);
+	KASSERT(sc->sc_intr_xfer == NULL);
 	sc->sc_intr_xfer = xfer;
+	xfer->ux_status = USBD_IN_PROGRESS;
+	if (!polling)
+		mutex_exit(&sc->sc_lock);
+
 	return USBD_IN_PROGRESS;
 }
 
@@ -1045,12 +1060,25 @@ motg_root_intr_close(struct usbd_pipe *p
 
 	KASSERT(mutex_owned(&sc->sc_lock));
 
-	sc->sc_intr_xfer = NULL;
+	/*
+	 * Caller must guarantee the xfer has completed first, by
+	 * closing the pipe only after normal completion or an abort.
+	 */
+	KASSERT(sc->sc_intr_xfer == NULL);
 }
 
 void
 motg_root_intr_done(struct usbd_xfer *xfer)
 {
+	struct motg_softc *sc = MOTG_PIPE2SC(pipe);
+	MOTGHIST_FUNC(); MOTGHIST_CALLED();
+
+	KASSERT(mutex_owned(&sc->sc_lock));
+
+	/* Claim the xfer so it doesn't get completed again.  */
+	KASSERT(sc->sc_intr_xfer == xfer);
+	KASSERT(xfer->ux_status != USBD_IN_PROGRESS);
+	sc->sc_intr_xfer = NULL;
 }
 
 void
@@ -1101,6 +1129,7 @@ motg_hub_change(struct motg_softc *sc)
 
 	if (xfer == NULL)
 		return; /* the interrupt pipe is not open */
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
 
 	pipe = xfer->ux_pipe;
 	if (pipe->up_dev == NULL || pipe->up_dev->ud_bus == NULL)

Index: src/sys/dev/usb/ohci.c
diff -u src/sys/dev/usb/ohci.c:1.294 src/sys/dev/usb/ohci.c:1.295
--- src/sys/dev/usb/ohci.c:1.294	Wed Feb 12 16:02:01 2020
+++ src/sys/dev/usb/ohci.c	Sat Feb 15 01:21:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: ohci.c,v 1.294 2020/02/12 16:02:01 riastradh Exp $	*/
+/*	$NetBSD: ohci.c,v 1.295 2020/02/15 01:21:56 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004, 2005, 2012 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.294 2020/02/12 16:02:01 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.295 2020/02/15 01:21:56 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -1698,6 +1698,8 @@ ohci_rhsc(ohci_softc_t *sc, struct usbd_
 		/* Just ignore the change. */
 		return;
 	}
+	KASSERT(xfer == sc->sc_intrxfer);
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
 
 	p = xfer->ux_buf;
 	m = uimin(sc->sc_noport, xfer->ux_length * 8 - 1);
@@ -2516,11 +2518,11 @@ ohci_root_intr_start(struct usbd_xfer *x
 		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer == NULL);
 	sc->sc_intrxfer = xfer;
+	xfer->ux_status = USBD_IN_PROGRESS;
 	if (!polling)
 		mutex_exit(&sc->sc_lock);
 
-	xfer->ux_status = USBD_IN_PROGRESS;
-	return xfer->ux_status;
+	return USBD_IN_PROGRESS;
 }
 
 /* Abort a root interrupt request. */

Index: src/sys/dev/usb/uhci.c
diff -u src/sys/dev/usb/uhci.c:1.292 src/sys/dev/usb/uhci.c:1.293
--- src/sys/dev/usb/uhci.c:1.292	Fri Feb 14 16:47:28 2020
+++ src/sys/dev/usb/uhci.c	Sat Feb 15 01:21:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: uhci.c,v 1.292 2020/02/14 16:47:28 riastradh Exp $	*/
+/*	$NetBSD: uhci.c,v 1.293 2020/02/15 01:21:56 riastradh Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004, 2011, 2012 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.292 2020/02/14 16:47:28 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.293 2020/02/15 01:21:56 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -1013,6 +1013,7 @@ uhci_poll_hub(void *addr)
 	xfer = sc->sc_intr_xfer;
 	if (xfer == NULL)
 		goto out;
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
 
 	/*
 	 * If the intr xfer for which we were scheduled is done, and
@@ -3905,12 +3906,12 @@ uhci_root_intr_start(struct usbd_xfer *x
 	sc->sc_ival = mstohz(ival);
 	callout_schedule(&sc->sc_poll_handle, sc->sc_ival);
 	sc->sc_intr_xfer = xfer;
+	xfer->ux_status = USBD_IN_PROGRESS;
 
 	if (!polling)
 		mutex_exit(&sc->sc_lock);
 
-	xfer->ux_status = USBD_IN_PROGRESS;
-	return xfer->ux_status;
+	return USBD_IN_PROGRESS;
 }
 
 /* Close the root interrupt pipe. */

Index: src/sys/dev/usb/vhci.c
diff -u src/sys/dev/usb/vhci.c:1.5 src/sys/dev/usb/vhci.c:1.6
--- src/sys/dev/usb/vhci.c:1.5	Wed Feb 12 16:02:01 2020
+++ src/sys/dev/usb/vhci.c	Sat Feb 15 01:21:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: vhci.c,v 1.5 2020/02/12 16:02:01 riastradh Exp $ */
+/*	$NetBSD: vhci.c,v 1.6 2020/02/15 01:21:56 riastradh Exp $ */
 
 /*
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.5 2020/02/12 16:02:01 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vhci.c,v 1.6 2020/02/15 01:21:56 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -629,6 +629,7 @@ vhci_root_intr_start(struct usbd_xfer *x
 		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer == NULL);
 	sc->sc_intrxfer = xfer;
+	xfer->ux_status = USBD_IN_PROGRESS;
 	if (!polling)
 		mutex_exit(&sc->sc_lock);
 
@@ -654,6 +655,7 @@ vhci_root_intr_abort(struct usbd_xfer *x
 	 * Cancel it.
 	 */
 	KASSERT(sc->sc_intrxfer == xfer);
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
 	xfer->ux_status = USBD_CANCELLED;
 	usb_transfer_complete(xfer);
 }
@@ -748,6 +750,7 @@ vhci_usb_attach(vhci_fd_t *vfd, struct v
 		ret = ENOBUFS;
 		goto done;
 	}
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
 
 	p = xfer->ux_buf;
 	memset(p, 0, xfer->ux_length);
@@ -823,6 +826,7 @@ vhci_usb_detach(vhci_fd_t *vfd, struct v
 		mutex_exit(&sc->sc_lock);
 		return ENOBUFS;
 	}
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
 
 	mutex_enter(&port->lock);
 

Index: src/sys/dev/usb/xhci.c
diff -u src/sys/dev/usb/xhci.c:1.117 src/sys/dev/usb/xhci.c:1.118
--- src/sys/dev/usb/xhci.c:1.117	Wed Feb 12 16:02:01 2020
+++ src/sys/dev/usb/xhci.c	Sat Feb 15 01:21:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: xhci.c,v 1.117 2020/02/12 16:02:01 riastradh Exp $	*/
+/*	$NetBSD: xhci.c,v 1.118 2020/02/15 01:21:56 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.117 2020/02/12 16:02:01 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.118 2020/02/15 01:21:56 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -1879,6 +1879,7 @@ xhci_rhpsc(struct xhci_softc * const sc,
 
 	if (xfer == NULL)
 		return;
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
 
 	uint8_t *p = xfer->ux_buf;
 	memset(p, 0, xfer->ux_length);
@@ -3717,6 +3718,7 @@ xhci_root_intr_start(struct usbd_xfer *x
 		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer[bn] == NULL);
 	sc->sc_intrxfer[bn] = xfer;
+	xfer->ux_status = USBD_IN_PROGRESS;
 	if (!polling)
 		mutex_exit(&sc->sc_lock);
 

Index: src/sys/external/bsd/dwc2/dwc2.c
diff -u src/sys/external/bsd/dwc2/dwc2.c:1.68 src/sys/external/bsd/dwc2/dwc2.c:1.69
--- src/sys/external/bsd/dwc2/dwc2.c:1.68	Wed Feb 12 16:02:01 2020
+++ src/sys/external/bsd/dwc2/dwc2.c	Sat Feb 15 01:21:56 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: dwc2.c,v 1.68 2020/02/12 16:02:01 riastradh Exp $	*/
+/*	$NetBSD: dwc2.c,v 1.69 2020/02/15 01:21:56 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.68 2020/02/12 16:02:01 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2.c,v 1.69 2020/02/15 01:21:56 riastradh Exp $");
 
 #include "opt_usb.h"
 
@@ -301,6 +301,8 @@ dwc2_rhc(void *addr)
 		return;
 
 	}
+	KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
+
 	/* set port bit */
 	p = KERNADDR(&xfer->ux_dmabuf, 0);
 
@@ -646,11 +648,11 @@ dwc2_root_intr_start(struct usbd_xfer *x
 		mutex_enter(&sc->sc_lock);
 	KASSERT(sc->sc_intrxfer == NULL);
 	sc->sc_intrxfer = xfer;
+	xfer->ux_status = USBD_IN_PROGRESS;
 	if (!polling)
 		mutex_exit(&sc->sc_lock);
 
-	xfer->ux_status = USBD_IN_PROGRESS;
-	return xfer->ux_status;
+	return USBD_IN_PROGRESS;
 }
 
 /* Abort a root interrupt request. */

Reply via email to