Module Name:    src
Committed By:   skrll
Date:           Tue Dec 27 11:37:36 UTC 2016

Modified Files:
        src/sys/dev/usb [nick-nhusb]: if_urndis.c

Log Message:
WIP MPification


To generate a diff of this commit:
cvs rdiff -u -r1.9.4.11 -r1.9.4.12 src/sys/dev/usb/if_urndis.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_urndis.c
diff -u src/sys/dev/usb/if_urndis.c:1.9.4.11 src/sys/dev/usb/if_urndis.c:1.9.4.12
--- src/sys/dev/usb/if_urndis.c:1.9.4.11	Mon Dec  5 10:55:18 2016
+++ src/sys/dev/usb/if_urndis.c	Tue Dec 27 11:37:36 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_urndis.c,v 1.9.4.11 2016/12/05 10:55:18 skrll Exp $ */
+/*	$NetBSD: if_urndis.c,v 1.9.4.12 2016/12/27 11:37:36 skrll Exp $ */
 /*	$OpenBSD: if_urndis.c,v 1.31 2011/07/03 15:47:17 matthew Exp $ */
 
 /*
@@ -21,7 +21,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.9.4.11 2016/12/05 10:55:18 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_urndis.c,v 1.9.4.12 2016/12/27 11:37:36 skrll Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -75,13 +75,18 @@ static void urndis_watchdog(struct ifnet
 #endif
 
 static void urndis_start(struct ifnet *);
+static void urndis_start_locked(struct ifnet *);
 static void urndis_rxeof(struct usbd_xfer *, void *, usbd_status);
 static void urndis_txeof(struct usbd_xfer *, void *, usbd_status);
 static int urndis_rx_list_init(struct urndis_softc *);
+static void urndis_rx_list_free(struct urndis_softc *);
 static int urndis_tx_list_init(struct urndis_softc *);
+static void urndis_tx_list_free(struct urndis_softc *);
 
 static int urndis_init(struct ifnet *);
+static int urndis_init_locked(struct ifnet *);
 static void urndis_stop(struct ifnet *);
+static void urndis_stop_locked(struct ifnet *);
 
 static usbd_status urndis_ctrl_msg(struct urndis_softc *, uint8_t, uint8_t,
     uint16_t, uint16_t, void *, size_t);
@@ -879,7 +884,7 @@ urndis_decap(struct urndis_softc *sc, st
 
 			bpf_mtap(ifp, m);
 
-			if_percpuq_enqueue(ifp->if_percpuq, m);
+			if_percpuq_enqueue(sc->urndis_ipq, m);
 		}
 		splx(s);
 
@@ -941,6 +946,21 @@ urndis_rx_list_init(struct urndis_softc 
 	return 0;
 }
 
+static void
+urndis_rx_list_free(struct urndis_softc *sc)
+{
+	for (int i = 0; i < RNDIS_RX_LIST_CNT; i++) {
+		if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) {
+			m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf);
+			sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL;
+		}
+		if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) {
+			usbd_destroy_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer);
+			sc->sc_data.sc_rx_chain[i].sc_xfer = NULL;
+		}
+	}
+}
+
 static int
 urndis_tx_list_init(struct urndis_softc *sc)
 {
@@ -965,6 +985,21 @@ urndis_tx_list_init(struct urndis_softc 
 	return 0;
 }
 
+static void
+urndis_tx_list_free(struct urndis_softc *sc)
+{
+	for (int i = 0; i < RNDIS_TX_LIST_CNT; i++) {
+		if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) {
+			m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf);
+			sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL;
+		}
+		if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) {
+			usbd_destroy_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer);
+			sc->sc_data.sc_tx_chain[i].sc_xfer = NULL;
+		}
+	}
+}
+
 static int
 urndis_ioctl(struct ifnet *ifp, unsigned long command, void *data)
 {
@@ -979,24 +1014,7 @@ urndis_ioctl(struct ifnet *ifp, unsigned
 
 	s = splnet();
 
-	switch(command) {
-	case SIOCSIFFLAGS:
-		if ((error = ifioctl_common(ifp, command, data)) != 0)
-			break;
-		if (ifp->if_flags & IFF_UP) {
-			if (!(ifp->if_flags & IFF_RUNNING))
-				urndis_init(ifp);
-		} else {
-			if (ifp->if_flags & IFF_RUNNING)
-				urndis_stop(ifp);
-		}
-		error = 0;
-		break;
-
-	default:
-		error = ether_ioctl(ifp, command, data);
-		break;
-	}
+	error = ether_ioctl(ifp, command, data);
 
 	if (error == ENETRESET)
 		error = 0;
@@ -1026,8 +1044,20 @@ urndis_watchdog(struct ifnet *ifp)
 static int
 urndis_init(struct ifnet *ifp)
 {
+	struct urndis_softc *sc = ifp->if_softc;
+
+	mutex_enter(&sc->urndis_lock);
+	int ret = urndis_init_locked(ifp);
+	mutex_exit(&sc->urndis_lock);
+
+	return ret;
+}
+
+static int
+urndis_init_locked(struct ifnet *ifp)
+{
 	struct urndis_softc	*sc;
-	int			 i, s;
+	int			 i;
 	int 			 err;
 	usbd_status		 usberr;
 
@@ -1040,15 +1070,12 @@ urndis_init(struct ifnet *ifp)
 	if (err != RNDIS_STATUS_SUCCESS)
 		return EIO;
 
-	s = splnet();
-
 	usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkin_no,
 	    USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
 	if (usberr) {
 		printf("%s: open rx pipe failed: %s\n", DEVNAME(sc),
 		    usbd_errstr(err));
-		splx(s);
-		return EIO;
+		goto fail;
 	}
 
 	usberr = usbd_open_pipe(sc->sc_iface_data, sc->sc_bulkout_no,
@@ -1056,24 +1083,21 @@ urndis_init(struct ifnet *ifp)
 	if (usberr) {
 		printf("%s: open tx pipe failed: %s\n", DEVNAME(sc),
 		    usbd_errstr(err));
-		splx(s);
-		return EIO;
+		goto fail2;
 	}
 
 	err = urndis_tx_list_init(sc);
 	if (err) {
 		printf("%s: tx list init failed\n",
 		    DEVNAME(sc));
-		splx(s);
-		return err;
+		goto fail3;
 	}
 
 	err = urndis_rx_list_init(sc);
 	if (err) {
 		printf("%s: rx list init failed\n",
 		    DEVNAME(sc));
-		splx(s);
-		return err;
+		goto fail4;
 	}
 
 	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
@@ -1089,16 +1113,33 @@ urndis_init(struct ifnet *ifp)
 	ifp->if_flags |= IFF_RUNNING;
 	ifp->if_flags &= ~IFF_OACTIVE;
 
-	splx(s);
 	return 0;
+
+fail4:
+	urndis_tx_list_free(sc);
+fail3:
+	usbd_close_pipe(sc->sc_bulkout_pipe);
+fail2:
+	usbd_close_pipe(sc->sc_bulkin_pipe);
+fail:
+	return EIO;
 }
 
 static void
 urndis_stop(struct ifnet *ifp)
 {
+	struct urndis_softc *sc = ifp->if_softc;
+
+	mutex_enter(&sc->urndis_lock);
+	urndis_stop_locked(ifp);
+	mutex_exit(&sc->urndis_lock);
+}
+
+static void
+urndis_stop_locked(struct ifnet *ifp)
+{
 	struct urndis_softc	*sc;
 	usbd_status	 err;
-	int		 i;
 
 	sc = ifp->if_softc;
 
@@ -1119,27 +1160,9 @@ urndis_stop(struct ifnet *ifp)
 			    DEVNAME(sc), usbd_errstr(err));
 	}
 
-	for (i = 0; i < RNDIS_RX_LIST_CNT; i++) {
-		if (sc->sc_data.sc_rx_chain[i].sc_mbuf != NULL) {
-			m_freem(sc->sc_data.sc_rx_chain[i].sc_mbuf);
-			sc->sc_data.sc_rx_chain[i].sc_mbuf = NULL;
-		}
-		if (sc->sc_data.sc_rx_chain[i].sc_xfer != NULL) {
-			usbd_destroy_xfer(sc->sc_data.sc_rx_chain[i].sc_xfer);
-			sc->sc_data.sc_rx_chain[i].sc_xfer = NULL;
-		}
-	}
+	urndis_tx_list_free(sc);
 
-	for (i = 0; i < RNDIS_TX_LIST_CNT; i++) {
-		if (sc->sc_data.sc_tx_chain[i].sc_mbuf != NULL) {
-			m_freem(sc->sc_data.sc_tx_chain[i].sc_mbuf);
-			sc->sc_data.sc_tx_chain[i].sc_mbuf = NULL;
-		}
-		if (sc->sc_data.sc_tx_chain[i].sc_xfer != NULL) {
-			usbd_destroy_xfer(sc->sc_data.sc_tx_chain[i].sc_xfer);
-			sc->sc_data.sc_tx_chain[i].sc_xfer = NULL;
-		}
-	}
+	urndis_rx_list_free(sc);
 
 	/* Close pipes. */
 	if (sc->sc_bulkin_pipe != NULL) {
@@ -1162,6 +1185,17 @@ urndis_stop(struct ifnet *ifp)
 static void
 urndis_start(struct ifnet *ifp)
 {
+	struct urndis_softc *sc = ifp->if_softc;
+	KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);
+
+	mutex_enter(&sc->urndis_txlock);
+	urndis_start_locked(ifp);
+	mutex_exit(&sc->urndis_txlock);
+}
+
+static void
+urndis_start_locked(struct ifnet *ifp)
+{
 	struct urndis_softc	*sc;
 	struct mbuf		*m_head = NULL;
 
@@ -1330,7 +1364,6 @@ urndis_attach(device_t parent, device_t 
 	usbd_desc_iter_t		 iter;
 	int				 if_ctl, if_data;
 	int				 i, j, altcnt;
-	int				 s;
 	u_char				 eaddr[ETHER_ADDR_LEN];
 	void				*buf;
 	size_t				 bufsz;
@@ -1355,6 +1388,10 @@ urndis_attach(device_t parent, device_t 
 	sc->sc_ifaceno_ctl = if_ctl;
 	if_data = -1;
 
+	mutex_init(&sc->urndis_lock, MUTEX_DEFAULT, IPL_NONE);
+	mutex_init(&sc->urndis_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+	mutex_init(&sc->urndis_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+
 	usb_desc_iter_init(sc->sc_udev, &iter);
 	while ((desc = (const void *)usb_desc_iter_next(&iter)) != NULL) {
 
@@ -1442,11 +1479,12 @@ urndis_attach(device_t parent, device_t 
 		aprint_error("%s: could not find data bulk out\n",DEVNAME(sc));
 	return;
 
-	found:
+found:
 
 	ifp = GET_IFP(sc);
 	ifp->if_softc = sc;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	ifp->if_extflags = IFEF_START_MPSAFE;
 	ifp->if_start = urndis_start;
 	ifp->if_ioctl = urndis_ioctl;
 	ifp->if_init = urndis_init;
@@ -1460,14 +1498,11 @@ urndis_attach(device_t parent, device_t 
 
 	urndis_init(ifp);
 
-	s = splnet();
-
 	if (urndis_ctrl_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
 	    &buf, &bufsz) != RNDIS_STATUS_SUCCESS) {
 		aprint_error("%s: unable to get hardware address\n",
 		    DEVNAME(sc));
 		urndis_stop(ifp);
-		splx(s);
 		return;
 	}
 
@@ -1480,7 +1515,6 @@ urndis_attach(device_t parent, device_t 
 		aprint_error("%s: invalid address\n", DEVNAME(sc));
 		kmem_free(buf, bufsz);
 		urndis_stop(ifp);
-		splx(s);
 		return;
 	}
 
@@ -1492,15 +1526,15 @@ urndis_attach(device_t parent, device_t 
 	    sizeof(filter)) != RNDIS_STATUS_SUCCESS) {
 		aprint_error("%s: unable to set data filters\n", DEVNAME(sc));
 		urndis_stop(ifp);
-		splx(s);
 		return;
 	}
 
-	if_attach(ifp);
+	if_initialize(ifp);
+	sc->urndis_ipq = if_percpuq_create(&sc->sc_ec.ec_if);
 	ether_ifattach(ifp, eaddr);
+	if_register(ifp);
+	
 	sc->sc_attached = 1;
-
-	splx(s);
 }
 
 static int

Reply via email to