git: 56caa9e82b46 - stable/13 - umodem(4): Clear stall at every open.

From: Hans Petter Selasky <hselasky_at_FreeBSD.org>
Date: Tue, 06 Sep 2022 08:43:56 UTC
The branch stable/13 has been updated by hselasky:

URL: https://cgit.FreeBSD.org/src/commit/?id=56caa9e82b46eeea3c7c21b44e7170d77a61b492

commit 56caa9e82b46eeea3c7c21b44e7170d77a61b492
Author:     Hans Petter Selasky <hselasky@FreeBSD.org>
AuthorDate: 2022-08-30 14:01:43 +0000
Commit:     Hans Petter Selasky <hselasky@FreeBSD.org>
CommitDate: 2022-09-06 08:43:17 +0000

    umodem(4): Clear stall at every open.
    
    Some controllers like the XHCI(4) loose track of the data toggle value when
    USB receive transfers are cancelled at close. This in turn can lead to to
    data loss after the next open.
    
    To avoid data loss, make sure both the receive and transmit data toggles
    get reset, before trying to read or write any data.
    
    Differential Revision:  https://reviews.freebsd.org/D36391
    Submitted by:           Dave Baukus <daveb@spectralogic.com>
    Sponsored by:   NVIDIA Networking
    
    (cherry picked from commit 40e43b056df9aa2392f673fcacc72725c2201658)
---
 sys/dev/usb/serial/umodem.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c
index 4fa108e962f2..c4aba1bdd3e2 100644
--- a/sys/dev/usb/serial/umodem.c
+++ b/sys/dev/usb/serial/umodem.c
@@ -218,6 +218,7 @@ static void	umodem_cfg_get_status(struct ucom_softc *, uint8_t *,
 		    uint8_t *);
 static int	umodem_pre_param(struct ucom_softc *, struct termios *);
 static void	umodem_cfg_param(struct ucom_softc *, struct termios *);
+static void	umodem_cfg_open(struct ucom_softc *);
 static int	umodem_ioctl(struct ucom_softc *, uint32_t, caddr_t, int,
 		    struct thread *);
 static void	umodem_cfg_set_dtr(struct ucom_softc *, uint8_t);
@@ -283,6 +284,7 @@ static const struct ucom_callback umodem_callback = {
 	.ucom_cfg_set_break = &umodem_cfg_set_break,
 	.ucom_cfg_param = &umodem_cfg_param,
 	.ucom_pre_param = &umodem_pre_param,
+	.ucom_cfg_open = &umodem_cfg_open,
 	.ucom_ioctl = &umodem_ioctl,
 	.ucom_start_read = &umodem_start_read,
 	.ucom_stop_read = &umodem_stop_read,
@@ -449,14 +451,6 @@ umodem_attach(device_t dev)
 		goto detach;
 	}
 
-	/* clear stall at first run, if USB host mode */
-	if (uaa->usb_mode == USB_MODE_HOST) {
-		mtx_lock(&sc->sc_mtx);
-		usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_WR]);
-		usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_RD]);
-		mtx_unlock(&sc->sc_mtx);
-	}
-
 	ucom_set_usb_mode(&sc->sc_super_ucom, uaa->usb_mode);
 
 	error = ucom_attach(&sc->sc_super_ucom, &sc->sc_ucom, 1, sc,
@@ -635,6 +629,18 @@ umodem_cfg_param(struct ucom_softc *ucom, struct termios *t)
 	    &req, &ls, 0, 1000);
 }
 
+static void	
+umodem_cfg_open(struct ucom_softc *ucom)
+{
+	struct umodem_softc *sc = ucom->sc_parent;
+
+	/* clear stall, if in USB host mode */
+	if ((sc->sc_super_ucom.sc_flag & UCOM_FLAG_DEVICE_MODE) == 0) {
+		usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_WR]);
+		usbd_xfer_set_stall(sc->sc_xfer[UMODEM_BULK_RD]);
+	}
+}
+
 static int
 umodem_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data,
     int flag, struct thread *td)