Module Name:    src
Committed By:   riastradh
Date:           Sun Mar 20 00:41:01 UTC 2022

Modified Files:
        src/sys/dev/usb: ualea.c

Log Message:
ualea(4): Fix detach and error paths.

- Set sc_needed before aborting the pipe to prevent the xfer callback
  from rescheduling itself.

- Make sure all paths out of the xfer callback clear sc_inflight.

While here, use device_printf instead of aprint_* after attach.

Now my system survives repeated insertion and yanking of ualea(4)
during:

sysctl -w kern.entropy.depletion=1
cat </dev/random >/dev/null


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sys/dev/usb/ualea.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/ualea.c
diff -u src/sys/dev/usb/ualea.c:1.16 src/sys/dev/usb/ualea.c:1.17
--- src/sys/dev/usb/ualea.c:1.16	Sat Mar 19 11:37:06 2022
+++ src/sys/dev/usb/ualea.c	Sun Mar 20 00:41:01 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: ualea.c,v 1.16 2022/03/19 11:37:06 riastradh Exp $	*/
+/*	$NetBSD: ualea.c,v 1.17 2022/03/20 00:41:01 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ualea.c,v 1.16 2022/03/19 11:37:06 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ualea.c,v 1.17 2022/03/20 00:41:01 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/atomic.h>
@@ -159,6 +159,11 @@ ualea_detach(device_t self, int flags)
 	if (sc->sc_attached)
 		rnd_detach_source(&sc->sc_rnd);
 
+	/* Prevent xfer from rescheduling itself, if still pending.  */
+	mutex_enter(&sc->sc_lock);
+	sc->sc_needed = 0;
+	mutex_exit(&sc->sc_lock);
+
 	/* Cancel pending xfer.  */
 	if (sc->sc_pipe)
 		usbd_abort_pipe(sc->sc_pipe);
@@ -196,8 +201,8 @@ ualea_xfer(struct ualea_softc *sc)
 	status = usbd_transfer(sc->sc_xfer);
 	KASSERT(status != USBD_NORMAL_COMPLETION); /* asynchronous xfer */
 	if (status != USBD_IN_PROGRESS) {
-		aprint_error_dev(sc->sc_dev, "failed to issue xfer: %d\n",
-		    status);
+		device_printf(sc->sc_dev, "failed to issue xfer: %s\n",
+		    usbd_errstr(status));
 		/* We failed -- let someone else have a go.  */
 		return;
 	}
@@ -227,14 +232,16 @@ ualea_xfer_done(struct usbd_xfer *xfer, 
 
 	/* Check the transfer status.  */
 	if (status) {
-		aprint_error_dev(sc->sc_dev, "xfer failed: %d\n", status);
-		return;
+		device_printf(sc->sc_dev, "xfer failed: %s\n",
+		    usbd_errstr(status));
+		pktsize = 0;
+		goto out;
 	}
 
 	/* Get and sanity-check the transferred size.  */
 	usbd_get_xfer_status(xfer, NULL, &pkt, &pktsize, NULL);
 	if (pktsize > sc->sc_maxpktsize) {
-		aprint_error_dev(sc->sc_dev,
+		device_printf(sc->sc_dev,
 		    "bogus packet size: %"PRIu32" > %"PRIu16" (max), ignoring"
 		    "\n",
 		    pktsize, sc->sc_maxpktsize);

Reply via email to