Module Name:    src
Committed By:   jdc
Date:           Mon Jun 22 17:38:27 UTC 2020

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

Log Message:
Add sedetach() and also use it to remove duplicate code from seattach().
Correct a comment about sedone().


To generate a diff of this commit:
cvs rdiff -u -r1.106 -r1.107 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.106 src/sys/dev/scsipi/if_se.c:1.107
--- src/sys/dev/scsipi/if_se.c:1.106	Mon Jun 22 16:05:20 2020
+++ src/sys/dev/scsipi/if_se.c	Mon Jun 22 17:38:27 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_se.c,v 1.106 2020/06/22 16:05:20 jdc Exp $	*/
+/*	$NetBSD: if_se.c,v 1.107 2020/06/22 17:38:27 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.106 2020/06/22 16:05:20 jdc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_se.c,v 1.107 2020/06/22 17:38:27 jdc Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -198,10 +198,12 @@ struct se_softc {
 	int sc_flags;
 	int sc_last_timeout;
 	int sc_enabled;
+	int sc_attach_state;
 };
 
 static int	sematch(device_t, cfdata_t, void *);
 static void	seattach(device_t, device_t, void *);
+static int	sedetach(device_t, int);
 
 static void	se_ifstart(struct ifnet *);
 
@@ -240,7 +242,7 @@ int	se_enable(struct se_softc *);
 void	se_disable(struct se_softc *);
 
 CFATTACH_DECL_NEW(se, sizeof(struct se_softc),
-    sematch, seattach, NULL, NULL);
+    sematch, seattach, sedetach, NULL);
 
 extern struct cfdriver se_cd;
 
@@ -267,7 +269,7 @@ const struct scsipi_periphsw se_switch =
 	NULL,			/* Use default error handler */
 	NULL,			/* have no queue */
 	NULL,			/* have no async handler */
-	sedone,			/* deal with stats at interrupt time */
+	sedone,			/* deal with send/recv completion */
 };
 
 const struct scsipi_inquiry_pattern se_patterns[] = {
@@ -330,6 +332,7 @@ seattach(device_t parent, device_t self,
 	printf("\n");
 	SC_DEBUG(periph, SCSIPI_DB2, ("seattach: "));
 
+	sc->sc_attach_state = 0;
 	callout_init(&sc->sc_recv_ch, CALLOUT_MPSAFE);
 	mutex_init(&sc->sc_iflock, MUTEX_DEFAULT, IPL_SOFTNET);
 
@@ -363,43 +366,82 @@ seattach(device_t parent, device_t self,
 	IFQ_SET_READY(&ifp->if_snd);
 
 	se_get_addr(sc, myaddr);
+	sc->sc_attach_state = 1;
 
 	/* Attach the interface. */
 	rv = if_initialize(ifp);
 	if (rv != 0) {
-		free(sc->sc_tbuf, M_DEVBUF);
-		callout_destroy(&sc->sc_recv_ch);
-		mutex_destroy(&sc->sc_iflock);
+		sedetach(sc->sc_dev, 0);
 		return; /* Error */
 	}
+	
 	snprintf(wqname, sizeof(wqname), "%sRx", device_xname(sc->sc_dev));
 	rv = workqueue_create(&sc->sc_recv_wq, wqname, se_recv_worker, sc,
 	    PRI_SOFTNET, IPL_NET, WQ_MPSAFE);
 	if (rv != 0) {
 		aprint_error_dev(sc->sc_dev,
-		    "unable to create recv workqueue\n");
-		free(sc->sc_tbuf, M_DEVBUF);
-		callout_destroy(&sc->sc_recv_ch);
-		mutex_destroy(&sc->sc_iflock);
+		    "unable to create recv Rx workqueue\n");
+		sedetach(sc->sc_dev, 0);
 		return; /* Error */
 	}
 	sc->sc_recv_work_pending = false;
+	sc->sc_attach_state = 2;
+
 	snprintf(wqname, sizeof(wqname), "%sTx", device_xname(sc->sc_dev));
 	rv = workqueue_create(&sc->sc_send_wq, wqname, se_send_worker, ifp,
 	    PRI_SOFTNET, IPL_NET, WQ_MPSAFE);
 	if (rv != 0) {
 		aprint_error_dev(sc->sc_dev,
-		    "unable to create send workqueue\n");
-		free(sc->sc_tbuf, M_DEVBUF);
-		callout_destroy(&sc->sc_recv_ch);
-		mutex_destroy(&sc->sc_iflock);
-		workqueue_destroy(sc->sc_send_wq);
+		    "unable to create send Tx workqueue\n");
+		sedetach(sc->sc_dev, 0);
 		return; /* Error */
 	}
 	sc->sc_send_work_pending = false;
+	sc->sc_attach_state = 3;
+
 	sc->sc_ipq = if_percpuq_create(&sc->sc_ethercom.ec_if);
 	ether_ifattach(ifp, myaddr);
 	if_register(ifp);
+	sc->sc_attach_state = 4;
+}
+
+static int
+sedetach(device_t self, int flags)
+{
+	struct se_softc *sc = device_private(self);
+	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+
+	switch(sc->sc_attach_state) {
+	case 4:
+		se_stop(sc);
+		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);
+		if_percpuq_destroy(sc->sc_ipq);
+		/*FALLTHROUGH*/
+	case 3:
+		workqueue_destroy(sc->sc_send_wq);
+		/*FALLTHROUGH*/
+	case 2:
+		workqueue_destroy(sc->sc_recv_wq);
+		/*FALLTHROUGH*/
+	case 1:
+		free(sc->sc_rbuf, M_DEVBUF);
+		free(sc->sc_tbuf, M_DEVBUF);
+		callout_destroy(&sc->sc_recv_ch);
+		mutex_destroy(&sc->sc_iflock);
+		break;
+	default:
+		aprint_error_dev(sc->sc_dev, "detach failed (state %d)\n",
+		    sc->sc_attach_state);
+		return 1;
+		break;
+	}
+	return 0;
 }
 
 /*

Reply via email to