Module Name:    src
Committed By:   martin
Date:           Sun Mar 10 18:59:19 UTC 2024

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

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

        sys/dev/usb/if_urtwn.c: revision 1.109 (patch)

urtwn(4): Ditch old queued commands on overflow.
Don't increment ring->queued past what the task will decrement.

This is a stop-gap measure; really, we should just have one task for
each operation that is deferred to the task thread.

PR kern/57965


To generate a diff of this commit:
cvs rdiff -u -r1.71.2.6 -r1.71.2.7 src/sys/dev/usb/if_urtwn.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/if_urtwn.c
diff -u src/sys/dev/usb/if_urtwn.c:1.71.2.6 src/sys/dev/usb/if_urtwn.c:1.71.2.7
--- src/sys/dev/usb/if_urtwn.c:1.71.2.6	Sat Oct 23 11:21:54 2021
+++ src/sys/dev/usb/if_urtwn.c	Sun Mar 10 18:59:19 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_urtwn.c,v 1.71.2.6 2021/10/23 11:21:54 martin Exp $	*/
+/*	$NetBSD: if_urtwn.c,v 1.71.2.7 2024/03/10 18:59:19 martin Exp $	*/
 /*	$OpenBSD: if_urtwn.c,v 1.42 2015/02/10 23:25:46 mpi Exp $	*/
 
 /*-
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.71.2.6 2021/10/23 11:21:54 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.71.2.7 2024/03/10 18:59:19 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -833,6 +833,24 @@ urtwn_tx_beacon(struct urtwn_softc *sc, 
 }
 
 static void
+urtwn_cmdq_invariants(struct urtwn_softc *sc)
+{
+	struct urtwn_host_cmd_ring *const ring __diagused = &sc->cmdq;
+
+	KASSERT(mutex_owned(&sc->sc_task_mtx));
+	KASSERTMSG((ring->cur >= 0 && ring->cur < URTWN_HOST_CMD_RING_COUNT),
+	    "%s: cur=%d next=%d queued=%d",
+	    device_xname(sc->sc_dev), ring->cur, ring->next, ring->queued);
+	KASSERTMSG((ring->next >= 0 && ring->next < URTWN_HOST_CMD_RING_COUNT),
+	    "%s: cur=%d next=%d queued=%d",
+	    device_xname(sc->sc_dev), ring->cur, ring->next, ring->queued);
+	KASSERTMSG((ring->queued >= 0 &&
+		ring->queued <= URTWN_HOST_CMD_RING_COUNT),
+	    "%s: %d commands queued",
+	    device_xname(sc->sc_dev), ring->queued);
+}
+
+static void
 urtwn_task(void *arg)
 {
 	struct urtwn_softc *sc = arg;
@@ -865,7 +883,11 @@ urtwn_task(void *arg)
 	/* Process host commands. */
 	s = splusb();
 	mutex_spin_enter(&sc->sc_task_mtx);
+	urtwn_cmdq_invariants(sc);
 	while (ring->next != ring->cur) {
+		KASSERTMSG(ring->queued > 0, "%s: cur=%d next=%d queued=%d",
+		    device_xname(sc->sc_dev),
+		    ring->cur, ring->next, ring->queued);
 		cmd = &ring->cmd[ring->next];
 		mutex_spin_exit(&sc->sc_task_mtx);
 		splx(s);
@@ -873,6 +895,10 @@ urtwn_task(void *arg)
 		cmd->cb(sc, cmd->data);
 		s = splusb();
 		mutex_spin_enter(&sc->sc_task_mtx);
+		urtwn_cmdq_invariants(sc);
+		KASSERTMSG(ring->queued > 0, "%s: cur=%d next=%d queued=%d",
+		    device_xname(sc->sc_dev),
+		    ring->cur, ring->next, ring->queued);
 		ring->queued--;
 		ring->next = (ring->next + 1) % URTWN_HOST_CMD_RING_COUNT;
 	}
@@ -887,6 +913,7 @@ urtwn_do_async(struct urtwn_softc *sc, v
 {
 	struct urtwn_host_cmd_ring *ring = &sc->cmdq;
 	struct urtwn_host_cmd *cmd;
+	bool schedtask = false;
 	int s;
 
 	DPRINTFN(DBG_FN, ("%s: %s: cb=%p, arg=%p, len=%d\n",
@@ -894,19 +921,27 @@ urtwn_do_async(struct urtwn_softc *sc, v
 
 	s = splusb();
 	mutex_spin_enter(&sc->sc_task_mtx);
+	urtwn_cmdq_invariants(sc);
 	cmd = &ring->cmd[ring->cur];
 	cmd->cb = cb;
 	KASSERT(len <= sizeof(cmd->data));
 	memcpy(cmd->data, arg, len);
 	ring->cur = (ring->cur + 1) % URTWN_HOST_CMD_RING_COUNT;
 
-	/* If there is no pending command already, schedule a task. */
-	if (!sc->sc_dying && ++ring->queued == 1) {
-		mutex_spin_exit(&sc->sc_task_mtx);
-		usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
-	} else
-		mutex_spin_exit(&sc->sc_task_mtx);
+	/*
+	 * Schedule a task to process the command if need be.
+	 */
+	if (!sc->sc_dying) {
+		if (ring->queued == URTWN_HOST_CMD_RING_COUNT)
+			device_printf(sc->sc_dev, "command queue overflow\n");
+		else if (ring->queued++ == 0)
+			schedtask = true;
+	}
+	mutex_spin_exit(&sc->sc_task_mtx);
 	splx(s);
+
+	if (schedtask)
+		usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
 }
 
 static void

Reply via email to