diff options
| author | riastradh <riastradh@NetBSD.org> | 2022-03-20 13:13:10 +0000 |
|---|---|---|
| committer | riastradh <riastradh@NetBSD.org> | 2022-03-20 13:13:10 +0000 |
| commit | ae75f01ac680e0b881536ca925dbd2c24492fbc8 (patch) | |
| tree | 8f7c72d753942e0f365f6d2a0ed1b76cb56eba44 /sys/dev/usb | |
| parent | dba80493dd1a18111290688f923caa1507973e64 (diff) | |
ualea(4): Simplify xfer error branches.
- Avoid going into a loop in case the transfer fails repeatedly --
just give up immediately if it fails.
- Assert result size is reasonable; no need to assume usbdi(9) is
malicious. If it can return ux_actlen > ux_length, that's a bug in
usbdi(9) that we should fix.
Diffstat (limited to 'sys/dev/usb')
| -rw-r--r-- | sys/dev/usb/ualea.c | 40 |
1 files changed, 19 insertions, 21 deletions
diff --git a/sys/dev/usb/ualea.c b/sys/dev/usb/ualea.c index 444f996a7ae..ab49ccaea04 100644 --- a/sys/dev/usb/ualea.c +++ b/sys/dev/usb/ualea.c @@ -1,4 +1,4 @@ -/* $NetBSD: ualea.c,v 1.17 2022/03/20 00:41:01 riastradh Exp $ */ +/* $NetBSD: ualea.c,v 1.18 2022/03/20 13:13:10 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.17 2022/03/20 00:41:01 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ualea.c,v 1.18 2022/03/20 13:13:10 riastradh Exp $"); #include <sys/types.h> #include <sys/atomic.h> @@ -230,39 +230,37 @@ ualea_xfer_done(struct usbd_xfer *xfer, void *cookie, usbd_status status) void *pkt; uint32_t pktsize; - /* Check the transfer status. */ + /* + * If the transfer failed, give up -- forget what we need and + * don't reschedule ourselves. + */ if (status) { device_printf(sc->sc_dev, "xfer failed: %s\n", usbd_errstr(status)); - pktsize = 0; - goto out; + mutex_enter(&sc->sc_lock); + sc->sc_needed = 0; + sc->sc_inflight = false; + mutex_exit(&sc->sc_lock); + return; } - /* Get and sanity-check the transferred size. */ + /* Get the transferred size. */ usbd_get_xfer_status(xfer, NULL, &pkt, &pktsize, NULL); - if (pktsize > sc->sc_maxpktsize) { - device_printf(sc->sc_dev, - "bogus packet size: %"PRIu32" > %"PRIu16" (max), ignoring" - "\n", - pktsize, sc->sc_maxpktsize); - goto out; - } + KASSERTMSG(pktsize <= sc->sc_maxpktsize, + "pktsize %"PRIu32" > %"PRIu16" (max)", + pktsize, sc->sc_maxpktsize); /* Add the data to the pool. */ rnd_add_data(&sc->sc_rnd, pkt, pktsize, NBBY*pktsize); -out: + /* + * Debit what we contributed from what we need, mark the xfer + * as done, and reschedule the xfer if we still need more. + */ mutex_enter(&sc->sc_lock); - - /* Debit what we contributed from what we need. */ sc->sc_needed -= MIN(sc->sc_needed, pktsize); - - /* Mark xfer done. */ sc->sc_inflight = false; - - /* Reissue xfer if we still need more. */ ualea_xfer(sc); - mutex_exit(&sc->sc_lock); } |
