Module Name:    src
Committed By:   martin
Date:           Sun Mar  1 12:38:59 UTC 2020

Modified Files:
        src/sys/dev/usb [netbsd-9]: umass.c

Log Message:
Pull up following revision(s) (requested by riastradh in ticket #745):

        sys/dev/usb/umass.c: revision 1.177
        sys/dev/usb/umass.c: revision 1.178
        sys/dev/usb/umass.c: revision 1.179

Abort default pipe too on detach before detaching children.

This ensures that pending xfers on the default pipe will be aborted
before we wait for children, which, in the case of scsibus -> sd,
means waiting for pending xfers to complete -- xfers that may never
complete if something is wedged.

Consolidate logic to call the transfer callback.
No functional change intended.

Make sure the umass transfer callback is run in error branches.


To generate a diff of this commit:
cvs rdiff -u -r1.175 -r1.175.2.1 src/sys/dev/usb/umass.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/dev/usb/umass.c
diff -u src/sys/dev/usb/umass.c:1.175 src/sys/dev/usb/umass.c:1.175.2.1
--- src/sys/dev/usb/umass.c:1.175	Sun May  5 03:17:54 2019
+++ src/sys/dev/usb/umass.c	Sun Mar  1 12:38:59 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: umass.c,v 1.175 2019/05/05 03:17:54 mrg Exp $	*/
+/*	$NetBSD: umass.c,v 1.175.2.1 2020/03/01 12:38:59 martin Exp $	*/
 
 /*
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -124,7 +124,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.175 2019/05/05 03:17:54 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: umass.c,v 1.175.2.1 2020/03/01 12:38:59 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -236,6 +236,8 @@ Static usbd_status umass_setup_ctrl_tran
 				struct usbd_xfer *);
 Static void umass_clear_endpoint_stall(struct umass_softc *, int,
 				struct usbd_xfer *);
+Static void umass_transfer_done(struct umass_softc *, int, int);
+Static void umass_transfer_reset(struct umass_softc *);
 #if 0
 Static void umass_reset(struct umass_softc *, transfer_cb_f, void *);
 #endif
@@ -809,6 +811,7 @@ umass_detach(device_t self, int flags)
 		if (sc->sc_pipe[i] != NULL)
 			usbd_abort_pipe(sc->sc_pipe[i]);
 	}
+	usbd_abort_default_pipe(sc->sc_udev);
 
 	/* Do we really need reference counting?  Perhaps in ioctl() */
 	mutex_enter(&sc->sc_lock);
@@ -992,8 +995,11 @@ umass_clear_endpoint_stall(struct umass_
 {
 	UMASSHIST_FUNC(); UMASSHIST_CALLED();
 
-	if (sc->sc_dying)
+	if (sc->sc_dying) {
+		umass_transfer_done(sc, sc->transfer_datalen,
+		    STATUS_WIRE_FAILED);
 		return;
+	}
 
 	DPRINTFM(UDMASS_BBB, "Clear endpoint 0x%02jx stall",
 	    sc->sc_epaddr[endpt], 0, 0, 0);
@@ -1005,7 +1011,29 @@ umass_clear_endpoint_stall(struct umass_
 	USETW(sc->sc_req.wValue, UF_ENDPOINT_HALT);
 	USETW(sc->sc_req.wIndex, sc->sc_epaddr[endpt]);
 	USETW(sc->sc_req.wLength, 0);
-	umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, xfer);
+	if (umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0, xfer))
+		umass_transfer_done(sc, sc->transfer_datalen,
+		    STATUS_WIRE_FAILED);
+}
+
+Static void
+umass_transfer_done(struct umass_softc *sc, int residue, int status)
+{
+	UMASSHIST_FUNC(); UMASSHIST_CALLED();
+
+	sc->transfer_state = TSTATE_IDLE;
+	sc->transfer_cb(sc, sc->transfer_priv, residue, status);
+}
+
+Static void
+umass_transfer_reset(struct umass_softc *sc)
+{
+	UMASSHIST_FUNC(); UMASSHIST_CALLED();
+
+	sc->transfer_state = TSTATE_IDLE;
+	if (sc->transfer_priv)
+		sc->transfer_cb(sc, sc->transfer_priv, sc->transfer_datalen,
+		    sc->transfer_status);
 }
 
 #if 0
@@ -1032,8 +1060,10 @@ umass_bbb_reset(struct umass_softc *sc, 
 		   "sc->sc_wire == 0x%02x wrong for umass_bbb_reset\n",
 		   sc->sc_wire);
 
-	if (sc->sc_dying)
+	if (sc->sc_dying) {
+		umass_transfer_done(sc, sc->transfer_datalen, status);
 		return;
+	}
 
 	/*
 	 * Reset recovery (5.3.4 in Universal Serial Bus Mass Storage Class)
@@ -1062,8 +1092,9 @@ umass_bbb_reset(struct umass_softc *sc, 
 	USETW(sc->sc_req.wValue, 0);
 	USETW(sc->sc_req.wIndex, sc->sc_ifaceno);
 	USETW(sc->sc_req.wLength, 0);
-	umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0,
-				  sc->transfer_xfer[XFER_BBB_RESET1]);
+	if (umass_setup_ctrl_transfer(sc, &sc->sc_req, NULL, 0, 0,
+		sc->transfer_xfer[XFER_BBB_RESET1]))
+		umass_transfer_done(sc, sc->transfer_datalen, status);
 }
 
 Static void
@@ -1081,8 +1112,10 @@ umass_bbb_transfer(struct umass_softc *s
 		   "sc->sc_wire == 0x%02x wrong for umass_bbb_transfer\n",
 		   sc->sc_wire);
 
-	if (sc->sc_dying)
+	if (sc->sc_dying) {
+		cb(sc, priv, datalen, STATUS_WIRE_FAILED);
 		return;
+	}
 
 	/* Be a little generous. */
 	sc->timeout = timeout + USBD_DEFAULT_TIMEOUT;
@@ -1216,13 +1249,15 @@ umass_bbb_state(struct usbd_xfer *xfer, 
 		DPRINTFM(UDMASS_BBB, "sc %#jx xfer %#jx cancelled",
 		    (uintptr_t)sc, (uintptr_t)xfer, 0, 0);
 
-		sc->transfer_state = TSTATE_IDLE;
-		sc->transfer_cb(sc, sc->transfer_priv, 0, STATUS_TIMEOUT);
+		umass_transfer_done(sc, 0, STATUS_TIMEOUT);
 		return;
 	}
 
-	if (sc->sc_dying)
+	if (sc->sc_dying) {
+		umass_transfer_done(sc, sc->transfer_datalen,
+		    STATUS_WIRE_FAILED);
 		return;
+	}
 
 	switch (sc->transfer_state) {
 
@@ -1453,17 +1488,11 @@ umass_bbb_state(struct usbd_xfer *xfer, 
 			    "res = %jd", (uintptr_t)sc, residue, 0, 0);
 
 			/* SCSI command failed but transfer was succesful */
-			sc->transfer_state = TSTATE_IDLE;
-			sc->transfer_cb(sc, sc->transfer_priv, residue,
-					STATUS_CMD_FAILED);
-
+			umass_transfer_done(sc, residue, STATUS_CMD_FAILED);
 			return;
 
 		} else {	/* success */
-			sc->transfer_state = TSTATE_IDLE;
-			sc->transfer_cb(sc, sc->transfer_priv, residue,
-					STATUS_CMD_OK);
-
+			umass_transfer_done(sc, residue, STATUS_CMD_OK);
 			return;
 		}
 
@@ -1495,12 +1524,7 @@ umass_bbb_state(struct usbd_xfer *xfer, 
 			       device_xname(sc->sc_dev), usbd_errstr(err));
 			/* no error recovery, otherwise we end up in a loop */
 
-		sc->transfer_state = TSTATE_IDLE;
-		if (sc->transfer_priv) {
-			sc->transfer_cb(sc, sc->transfer_priv,
-					sc->transfer_datalen,
-					sc->transfer_status);
-		}
+		umass_transfer_reset(sc);
 
 		return;
 
@@ -1550,8 +1574,10 @@ umass_cbi_reset(struct umass_softc *sc, 
 		   "sc->sc_wire == 0x%02x wrong for umass_cbi_reset\n",
 		   sc->sc_wire);
 
-	if (sc->sc_dying)
+	if (sc->sc_dying) {
+		umass_transfer_done(sc, sc->transfer_datalen, status);
 		return;
+	}
 
 	/*
 	 * Command Block Reset Protocol
@@ -1587,8 +1613,9 @@ umass_cbi_reset(struct umass_softc *sc, 
 	for (i = 2; i < SEND_DIAGNOSTIC_CMDLEN; i++)
 		sc->cbl[i] = 0xff;
 
-	umass_cbi_adsc(sc, sc->cbl, SEND_DIAGNOSTIC_CMDLEN, 0,
-		       sc->transfer_xfer[XFER_CBI_RESET1]);
+	if (umass_cbi_adsc(sc, sc->cbl, SEND_DIAGNOSTIC_CMDLEN, 0,
+		sc->transfer_xfer[XFER_CBI_RESET1]))
+		umass_transfer_done(sc, sc->transfer_datalen, status);
 	/* XXX if the command fails we should reset the port on the bub */
 }
 
@@ -1606,8 +1633,10 @@ umass_cbi_transfer(struct umass_softc *s
 		   "sc->sc_wire == 0x%02x wrong for umass_cbi_transfer\n",
 		   sc->sc_wire);
 
-	if (sc->sc_dying)
+	if (sc->sc_dying) {
+		cb(sc, priv, datalen, STATUS_WIRE_FAILED);
 		return;
+	}
 
 	/* Be a little generous. */
 	sc->timeout = timeout + USBD_DEFAULT_TIMEOUT;
@@ -1668,13 +1697,15 @@ umass_cbi_state(struct usbd_xfer *xfer, 
 	if (err == USBD_CANCELLED) {
 		DPRINTFM(UDMASS_BBB, "sc %#jx xfer %#jx cancelled",
 			(uintptr_t)sc, (uintptr_t)xfer, 0, 0);
-		sc->transfer_state = TSTATE_IDLE;
-		sc->transfer_cb(sc, sc->transfer_priv, 0, STATUS_TIMEOUT);
+		umass_transfer_done(sc, 0, STATUS_TIMEOUT);
 		return;
 	}
 
-	if (sc->sc_dying)
+	if (sc->sc_dying) {
+		umass_transfer_done(sc, sc->transfer_datalen,
+		    STATUS_WIRE_FAILED);
 		return;
+	}
 
 	/*
 	 * State handling for CBI transfers.
@@ -1699,12 +1730,8 @@ umass_cbi_state(struct usbd_xfer *xfer, 
 			 * Section 2.4.3.1.1 states that the bulk in endpoints
 			 * should not stalled at this point.
 			 */
-
-			sc->transfer_state = TSTATE_IDLE;
-			sc->transfer_cb(sc, sc->transfer_priv,
-					sc->transfer_datalen,
-					STATUS_CMD_FAILED);
-
+			umass_transfer_done(sc, sc->transfer_datalen,
+			    STATUS_CMD_FAILED);
 			return;
 		} else if (err) {
 			DPRINTFM(UDMASS_CBI, "sc %#jx: failed to send ADSC",
@@ -1793,10 +1820,9 @@ umass_cbi_state(struct usbd_xfer *xfer, 
 			/* No command completion interrupt. Request
 			 * sense to get status of command.
 			 */
-			sc->transfer_state = TSTATE_IDLE;
-			sc->transfer_cb(sc, sc->transfer_priv,
-				sc->transfer_datalen - sc->transfer_actlen,
-				STATUS_CMD_UNKNOWN);
+			umass_transfer_done(sc,
+			    sc->transfer_datalen - sc->transfer_actlen,
+			    STATUS_CMD_UNKNOWN);
 		}
 		return;
 
@@ -1847,9 +1873,9 @@ umass_cbi_state(struct usbd_xfer *xfer, 
 				status = STATUS_CMD_FAILED;
 
 			/* No autosense, command successful */
-			sc->transfer_state = TSTATE_IDLE;
-			sc->transfer_cb(sc, sc->transfer_priv,
-			    sc->transfer_datalen - sc->transfer_actlen, status);
+			umass_transfer_done(sc,
+			    sc->transfer_datalen - sc->transfer_actlen,
+			    status);
 		} else {
 			int status;
 
@@ -1874,10 +1900,13 @@ umass_cbi_state(struct usbd_xfer *xfer, 
 					break;
 				}
 
-				sc->transfer_state = TSTATE_IDLE;
-				sc->transfer_cb(sc, sc->transfer_priv,
+				umass_transfer_done(sc,
 				    sc->transfer_datalen - sc->transfer_actlen,
 				    status);
+			} else {
+				/* XXX What to do?  */
+				umass_transfer_done(sc, sc->transfer_datalen,
+				    STATUS_WIRE_FAILED);
 			}
 		}
 		return;
@@ -1890,8 +1919,7 @@ umass_cbi_state(struct usbd_xfer *xfer, 
 			    usbd_errstr(err));
 			umass_cbi_reset(sc, STATUS_WIRE_FAILED);
 		} else {
-			sc->transfer_state = TSTATE_IDLE;
-			sc->transfer_cb(sc, sc->transfer_priv,
+			umass_transfer_done(sc,
 			    sc->transfer_datalen, STATUS_CMD_FAILED);
 		}
 		return;
@@ -1902,8 +1930,7 @@ umass_cbi_state(struct usbd_xfer *xfer, 
 			       device_xname(sc->sc_dev), usbd_errstr(err));
 			umass_cbi_reset(sc, STATUS_WIRE_FAILED);
 		} else {
-			sc->transfer_state = TSTATE_IDLE;
-			sc->transfer_cb(sc, sc->transfer_priv,
+			umass_transfer_done(sc,
 			    sc->transfer_datalen, STATUS_CMD_FAILED);
 		}
 		return;
@@ -1936,13 +1963,7 @@ umass_cbi_state(struct usbd_xfer *xfer, 
 			       device_xname(sc->sc_dev), usbd_errstr(err));
 			/* no error recovery, otherwise we end up in a loop */
 
-		sc->transfer_state = TSTATE_IDLE;
-		if (sc->transfer_priv) {
-			sc->transfer_cb(sc, sc->transfer_priv,
-					sc->transfer_datalen,
-					sc->transfer_status);
-		}
-
+		umass_transfer_reset(sc);
 		return;
 
 

Reply via email to