Module Name:    src
Committed By:   jdc
Date:           Mon Jul 27 15:41:03 UTC 2020

Modified Files:
        src/sys/dev/scsipi: if_se.c

Log Message:
Improve the workqueue and callout handling.  Prompted by riastradh@.


To generate a diff of this commit:
cvs rdiff -u -r1.110 -r1.111 src/sys/dev/scsipi/if_se.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/scsipi/if_se.c
diff -u src/sys/dev/scsipi/if_se.c:1.110 src/sys/dev/scsipi/if_se.c:1.111
--- src/sys/dev/scsipi/if_se.c:1.110	Wed Jul 22 17:18:10 2020
+++ src/sys/dev/scsipi/if_se.c	Mon Jul 27 15:41:03 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_se.c,v 1.110 2020/07/22 17:18:10 riastradh Exp $	*/
+/*	$NetBSD: if_se.c,v 1.111 2020/07/27 15:41:03 jdc Exp $	*/
 
 /*
  * Copyright (c) 1997 Ian W. Dall <ian.d...@dsto.defence.gov.au>
@@ -59,7 +59,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_se.c,v 1.110 2020/07/22 17:18:10 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_se.c,v 1.111 2020/07/27 15:41:03 jdc Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -332,6 +332,7 @@ seattach(device_t parent, device_t self,
 
 	sc->sc_attach_state = 0;
 	callout_init(&sc->sc_recv_ch, CALLOUT_MPSAFE);
+	callout_setfunc(&sc->sc_recv_ch, se_recv_callout, (void *)sc);
 	mutex_init(&sc->sc_iflock, MUTEX_DEFAULT, IPL_SOFTNET);
 
 	/*
@@ -415,7 +416,6 @@ sedetach(device_t self, int flags)
 		mutex_enter(&sc->sc_iflock);
 		ifp->if_flags &= ~IFF_RUNNING;
 		se_disable(sc);
-		callout_halt(&sc->sc_recv_ch, NULL);
 		ether_ifdetach(ifp);
 		if_detach(ifp);
 		mutex_exit(&sc->sc_iflock);
@@ -464,18 +464,13 @@ static void
 se_ifstart(struct ifnet *ifp)
 {
 	struct se_softc *sc = ifp->if_softc;
-	int i = 100;
 
 	mutex_enter(&sc->sc_iflock);
-	while (i && sc->sc_send_work_pending == true) {
-		i--;
-		delay(10);
-	}
-	if (i) {
+	if (!sc->sc_send_work_pending)  {
 		sc->sc_send_work_pending = true;
 		workqueue_enqueue(sc->sc_send_wq, &sc->sc_send_work, NULL);
-	} else
-		if_statinc(ifp, if_oerrors);
+	} 
+	/* else: nothing to do - work is already queued */
 	mutex_exit(&sc->sc_iflock);
 }
 
@@ -575,8 +570,7 @@ sedone(struct scsipi_xfer *xs, int error
 		/* scsipi_free_xs will call start. Harmless. */
 		if (error) {
 			/* Reschedule after a delay */
-			callout_reset(&sc->sc_recv_ch, se_poll,
-			    se_recv_callout, (void *)sc);
+			callout_schedule(&sc->sc_recv_ch, se_poll);
 		} else {
 			int n, ntimeo;
 			n = se_read(sc, xs->data, xs->datalen - xs->resid);
@@ -597,8 +591,7 @@ sedone(struct scsipi_xfer *xs, int error
 					  se_poll: ntimeo);
 			}
 			sc->sc_last_timeout = ntimeo;
-			callout_reset(&sc->sc_recv_ch, ntimeo,
-			    se_recv_callout, (void *)sc);
+			callout_schedule(&sc->sc_recv_ch, ntimeo);
 		}
 	}
 }
@@ -618,8 +611,8 @@ se_recv_callout(void *v)
 
 	mutex_enter(&sc->sc_iflock);
 	if (sc->sc_recv_work_pending == true) {
-		callout_reset(&sc->sc_recv_ch, se_poll,
-		    se_recv_callout, (void *)sc);
+		callout_schedule(&sc->sc_recv_ch, se_poll);
+		mutex_exit(&sc->sc_iflock);
 		return;
 	}
 
@@ -660,8 +653,7 @@ se_recv(struct se_softc *sc)
 	    sc->sc_rbuf, RBUF_LEN, SERETRIES, SETIMEOUT, NULL,
 	    XS_CTL_NOSLEEP | XS_CTL_DATA_IN);
 	if (error)
-		callout_reset(&sc->sc_recv_ch, se_poll,
-		    se_recv_callout, (void *)sc);
+		callout_schedule(&sc->sc_recv_ch, se_poll);
 }
 
 /*
@@ -923,12 +915,19 @@ se_init(struct se_softc *sc)
 	if ((ifp->if_flags & (IFF_RUNNING | IFF_UP)) == IFF_UP) {
 		ifp->if_flags |= IFF_RUNNING;
 		mutex_enter(&sc->sc_iflock);
-		sc->sc_recv_work_pending = true;
-		workqueue_enqueue(sc->sc_recv_wq, &sc->sc_recv_work, NULL);
+		if (!sc->sc_recv_work_pending)  {
+			sc->sc_recv_work_pending = true;
+			workqueue_enqueue(sc->sc_recv_wq, &sc->sc_recv_work,
+			    NULL);
+		} 
 		mutex_exit(&sc->sc_iflock);
 		ifp->if_flags &= ~IFF_OACTIVE;
 		mutex_enter(&sc->sc_iflock);
-		workqueue_enqueue(sc->sc_send_wq, &sc->sc_send_work, NULL);
+		if (!sc->sc_send_work_pending)  {
+			sc->sc_send_work_pending = true;
+			workqueue_enqueue(sc->sc_send_wq, &sc->sc_send_work,
+			    NULL);
+		} 
 		mutex_exit(&sc->sc_iflock);
 	}
 	return (error);
@@ -1019,7 +1018,7 @@ se_stop(struct se_softc *sc)
 {
 
 	/* Don't schedule any reads */
-	callout_stop(&sc->sc_recv_ch);
+	callout_halt(&sc->sc_recv_ch, &sc->sc_iflock);
 
 	/* Wait for the workqueues to finish */
 	mutex_enter(&sc->sc_iflock);

Reply via email to