Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-9]: src/sys/dev/usb Pull up following revision(s) (requested by r...



details:   https://anonhg.NetBSD.org/src/rev/54a30d29367d
branches:  netbsd-9
changeset: 745399:54a30d29367d
user:      martin <martin%NetBSD.org@localhost>
date:      Sun Mar 01 12:38:59 2020 +0000

description:
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.

diffstat:

 sys/dev/usb/umass.c |  137 +++++++++++++++++++++++++++++----------------------
 1 files changed, 79 insertions(+), 58 deletions(-)

diffs (truncated from 316 to 300 lines):

diff -r d6fd589b0bf7 -r 54a30d29367d sys/dev/usb/umass.c
--- a/sys/dev/usb/umass.c       Sun Mar 01 12:35:16 2020 +0000
+++ b/sys/dev/usb/umass.c       Sun Mar 01 12:38:59 2020 +0000
@@ -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 @@
                                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 @@
                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 @@
 {
        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 @@
        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 @@
                   "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 @@
        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 @@
                   "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 @@
                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 @@
                            "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 @@
                               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 @@
                   "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 @@
        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 @@
                   "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 @@
        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 @@
                         * 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 @@
                        /* 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 @@
                                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 @@
                                        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 @@
                            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 @@
                               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);
                }



Home | Main Index | Thread Index | Old Index