Module Name:    src
Committed By:   skrll
Date:           Fri Jul 15 08:50:59 UTC 2016

Modified Files:
        src/sys/dev/usb [nick-nhusb]: if_smsc.c if_smscvar.h

Log Message:
WIP MPification


To generate a diff of this commit:
cvs rdiff -u -r1.22.2.12 -r1.22.2.13 src/sys/dev/usb/if_smsc.c
cvs rdiff -u -r1.3.4.3 -r1.3.4.4 src/sys/dev/usb/if_smscvar.h

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_smsc.c
diff -u src/sys/dev/usb/if_smsc.c:1.22.2.12 src/sys/dev/usb/if_smsc.c:1.22.2.13
--- src/sys/dev/usb/if_smsc.c:1.22.2.12	Sat Jul  9 20:25:15 2016
+++ src/sys/dev/usb/if_smsc.c	Fri Jul 15 08:50:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_smsc.c,v 1.22.2.12 2016/07/09 20:25:15 skrll Exp $	*/
+/*	$NetBSD: if_smsc.c,v 1.22.2.13 2016/07/15 08:50:59 skrll Exp $	*/
 
 /*	$OpenBSD: if_smsc.c,v 1.4 2012/09/27 12:38:11 jsg Exp $	*/
 /* $FreeBSD: src/sys/dev/usb/net/if_smsc.c,v 1.1 2012/08/15 04:03:55 gonzo Exp $ */
@@ -161,9 +161,12 @@ int		 smsc_detach(device_t, int);
 int		 smsc_activate(device_t, enum devact);
 
 int		 smsc_init(struct ifnet *);
+int		 smsc_init_locked(struct ifnet *);
 void		 smsc_start(struct ifnet *);
+void		 smsc_start_locked(struct ifnet *);
 int		 smsc_ioctl(struct ifnet *, u_long, void *);
 void		 smsc_stop(struct ifnet *, int);
+void		 smsc_stop_locked(struct ifnet *, int);
 
 void		 smsc_reset(struct smsc_softc *);
 struct mbuf	*smsc_newbuf(void);
@@ -179,7 +182,9 @@ void		 smsc_lock_mii(struct smsc_softc *
 void		 smsc_unlock_mii(struct smsc_softc *);
 
 int		 smsc_tx_list_init(struct smsc_softc *);
+void		 smsc_tx_list_free(struct smsc_softc *);
 int		 smsc_rx_list_init(struct smsc_softc *);
+void		 smsc_rx_list_free(struct smsc_softc *);
 int		 smsc_encap(struct smsc_softc *, struct mbuf *, int);
 void		 smsc_rxeof(struct usbd_xfer *, void *, usbd_status);
 void		 smsc_txeof(struct usbd_xfer *, void *, usbd_status);
@@ -543,19 +548,27 @@ smsc_reset(struct smsc_softc *sc)
 int
 smsc_init(struct ifnet *ifp)
 {
-	struct smsc_softc	*sc = ifp->if_softc;
-	struct smsc_chain	*c;
-	usbd_status		 err;
-	int			 s, i;
+	struct smsc_softc *sc = ifp->if_softc;
+
+	mutex_enter(&sc->sc_lock);
+	int ret = smsc_init_locked(ifp);
+	mutex_exit(&sc->sc_lock);
+
+	return ret;
+}
+
+
+int
+smsc_init_locked(struct ifnet *ifp)
+{
+	struct smsc_softc * const sc = ifp->if_softc;
+	usbd_status err;
 
 	if (sc->sc_dying)
 		return EIO;
 
-	s = splnet();
-
 	/* Cancel pending I/O */
-	if (ifp->if_flags & IFF_RUNNING)
-		smsc_stop(ifp, 1);
+	smsc_stop_locked(ifp, 1);
 
 	/* Reset the ethernet interface. */
 	smsc_reset(sc);
@@ -572,8 +585,7 @@ smsc_init(struct ifnet *ifp)
 	if (err) {
 		printf("%s: open rx pipe failed: %s\n",
 		    device_xname(sc->sc_dev), usbd_errstr(err));
-		splx(s);
-		return EIO;
+		goto fail;
 	}
 
 	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_TX],
@@ -581,27 +593,24 @@ smsc_init(struct ifnet *ifp)
 	if (err) {
 		printf("%s: open tx pipe failed: %s\n",
 		    device_xname(sc->sc_dev), usbd_errstr(err));
-		splx(s);
-		return EIO;
+		goto fail1;
 	}
 
 	/* Init RX ring. */
 	if (smsc_rx_list_init(sc)) {
 		aprint_error_dev(sc->sc_dev, "rx list init failed\n");
-		splx(s);
-		return EIO;
+		goto fail2;
 	}
 
 	/* Init TX ring. */
 	if (smsc_tx_list_init(sc)) {
 		aprint_error_dev(sc->sc_dev, "tx list init failed\n");
-		splx(s);
-		return EIO;
+		goto fail3;
 	}
 
 	/* Start up the receive pipe. */
-	for (i = 0; i < SMSC_RX_LIST_CNT; i++) {
-		c = &sc->sc_cdata.rx_chain[i];
+	for (size_t i = 0; i < SMSC_RX_LIST_CNT; i++) {
+		struct smsc_chain *c = &sc->sc_cdata.rx_chain[i];
 		usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, sc->sc_bufsz,
 		    USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, smsc_rxeof);
 		usbd_transfer(c->sc_xfer);
@@ -611,18 +620,38 @@ smsc_init(struct ifnet *ifp)
 	ifp->if_flags |= IFF_RUNNING;
 	ifp->if_flags &= ~IFF_OACTIVE;
 
-	splx(s);
-
 	callout_reset(&sc->sc_stat_ch, hz, smsc_tick, sc);
 
 	return 0;
+
+fail3:
+	smsc_tx_list_free(sc);
+fail2:
+	smsc_rx_list_free(sc);
+
+	usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_TX]);
+fail1:
+	usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_RX]);
+fail:
+	return EIO;
 }
 
 void
 smsc_start(struct ifnet *ifp)
 {
-	struct smsc_softc	*sc = ifp->if_softc;
-	struct mbuf		*m_head = NULL;
+	struct smsc_softc * const sc = ifp->if_softc;
+	KASSERT(ifp->if_extflags & IFEF_START_MPSAFE);
+
+	mutex_enter(&sc->sc_txlock);
+	smsc_start_locked(ifp);
+	mutex_exit(&sc->sc_txlock);
+}
+
+void
+smsc_start_locked(struct ifnet *ifp)
+{
+	struct smsc_softc * const sc = ifp->if_softc;
+	struct mbuf *m_head = NULL;
 
 	/* Don't send anything if there is no link or controller is busy. */
 	if ((sc->sc_flags & SMSC_FLAG_LINK) == 0) {
@@ -637,7 +666,6 @@ smsc_start(struct ifnet *ifp)
 		return;
 
 	if (smsc_encap(sc, m_head, 0)) {
-		ifp->if_flags |= IFF_OACTIVE;
 		return;
 	}
 	IFQ_DEQUEUE(&ifp->if_snd, m_head);
@@ -669,15 +697,20 @@ smsc_tick(void *xsc)
 void
 smsc_stop(struct ifnet *ifp, int disable)
 {
-	usbd_status		err;
-	struct smsc_softc	*sc = ifp->if_softc;
-	int			i;
+	struct smsc_softc * const sc = ifp->if_softc;
 
-	smsc_reset(sc);
+	mutex_enter(&sc->sc_lock);
+	smsc_stop_locked(ifp, disable);
+	mutex_exit(&sc->sc_lock);
+}
 
-	ifp = &sc->sc_ec.ec_if;
-	ifp->if_timer = 0;
-	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+void
+smsc_stop_locked(struct ifnet *ifp, int disable)
+{
+	struct smsc_softc * const sc = ifp->if_softc;
+	usbd_status err;
+
+//	smsc_reset(sc);
 
 	callout_stop(&sc->sc_stat_ch);
 
@@ -706,29 +739,10 @@ smsc_stop(struct ifnet *ifp, int disable
 		}
 	}
 
-	/* Free RX resources. */
-	for (i = 0; i < SMSC_RX_LIST_CNT; i++) {
-		if (sc->sc_cdata.rx_chain[i].sc_mbuf != NULL) {
-			m_freem(sc->sc_cdata.rx_chain[i].sc_mbuf);
-			sc->sc_cdata.rx_chain[i].sc_mbuf = NULL;
-		}
-		if (sc->sc_cdata.rx_chain[i].sc_xfer != NULL) {
-			usbd_destroy_xfer(sc->sc_cdata.rx_chain[i].sc_xfer);
-			sc->sc_cdata.rx_chain[i].sc_xfer = NULL;
-		}
-	}
+	smsc_rx_list_free(sc);
+
+	smsc_tx_list_free(sc);
 
-	/* Free TX resources. */
-	for (i = 0; i < SMSC_TX_LIST_CNT; i++) {
-		if (sc->sc_cdata.tx_chain[i].sc_mbuf != NULL) {
-			m_freem(sc->sc_cdata.tx_chain[i].sc_mbuf);
-			sc->sc_cdata.tx_chain[i].sc_mbuf = NULL;
-		}
-		if (sc->sc_cdata.tx_chain[i].sc_xfer != NULL) {
-			usbd_destroy_xfer(sc->sc_cdata.tx_chain[i].sc_xfer);
-			sc->sc_cdata.tx_chain[i].sc_xfer = NULL;
-		}
-	}
 	/* Close pipes */
 	if (sc->sc_ep[SMSC_ENDPT_RX] != NULL) {
 		err = usbd_close_pipe(sc->sc_ep[SMSC_ENDPT_RX]);
@@ -756,6 +770,13 @@ smsc_stop(struct ifnet *ifp, int disable
 		}
 		sc->sc_ep[SMSC_ENDPT_INTR] = NULL;
 	}
+
+	ifp->if_timer = 0;
+	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+
+	if (disable) {
+		/* drain */
+	}
 }
 
 int
@@ -787,7 +808,7 @@ smsc_chip_init(struct smsc_softc *sc)
 	usbd_delay_ms(sc->sc_udev, 40);
 
 	/* Set the mac address */
-	struct ifnet *ifp = &sc->sc_ec.ec_if;
+	struct ifnet * const ifp = &sc->sc_ec.ec_if;
 	const char *eaddr = CLLADDR(ifp->if_sadl);
 	if ((err = smsc_setmacaddress(sc, eaddr)) != 0) {
 		smsc_warn_printf(sc, "failed to set the MAC address\n");
@@ -906,68 +927,65 @@ init_failed:
 	return err;
 }
 
+static int
+smsc_ifflags_cb(struct ethercom *ec)
+{
+	struct ifnet *ifp = &ec->ec_if;
+	struct smsc_softc *sc = ifp->if_softc;
+	int rc = 0;
+
+	mutex_enter(&sc->sc_lock);
+
+	int change = ifp->if_flags ^ sc->sc_if_flags;
+	sc->sc_if_flags = ifp->if_flags;
+
+	if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
+		rc = ENETRESET;
+		goto out;
+	}
+
+	if ((change & IFF_PROMISC) != 0) {
+		if (ifp->if_flags & IFF_PROMISC) {
+			sc->sc_mac_csr |= SMSC_MAC_CSR_PRMS;
+			smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+		} else if (!(ifp->if_flags & IFF_PROMISC)) {
+			sc->sc_mac_csr &= ~SMSC_MAC_CSR_PRMS;
+			smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+		}
+		smsc_setmulti(sc);
+	}
+
+out:
+	mutex_exit(&sc->sc_lock);
+
+	return rc;
+}
+
+
 int
 smsc_ioctl(struct ifnet *ifp, u_long cmd, void *data)
 {
 	struct smsc_softc	*sc = ifp->if_softc;
-	struct ifreq /*const*/	*ifr = data;
+// 	struct ifreq /*const*/	*ifr = data;
 	int			s, error = 0;
 
 	if (sc->sc_dying)
 		return EIO;
 
 	s = splnet();
+	error = ether_ioctl(ifp, cmd, data);
+	splx(s);
 
-	switch(cmd) {
-	case SIOCSIFFLAGS:
-		if ((error = ifioctl_common(ifp, cmd, data)) != 0)
-			break;
-
-		switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
-		case IFF_RUNNING:
-			smsc_stop(ifp, 1);
-			break;
-		case IFF_UP:
-			smsc_init(ifp);
-			break;
-		case IFF_UP | IFF_RUNNING:
-			if (ifp->if_flags & IFF_PROMISC &&
-			    !(sc->sc_if_flags & IFF_PROMISC)) {
-				sc->sc_mac_csr |= SMSC_MAC_CSR_PRMS;
-				smsc_write_reg(sc, SMSC_MAC_CSR,
-				    sc->sc_mac_csr);
-				smsc_setmulti(sc);
-			} else if (!(ifp->if_flags & IFF_PROMISC) &&
-			    sc->sc_if_flags & IFF_PROMISC) {
-				sc->sc_mac_csr &= ~SMSC_MAC_CSR_PRMS;
-				smsc_write_reg(sc, SMSC_MAC_CSR,
-				    sc->sc_mac_csr);
-				smsc_setmulti(sc);
-			} else {
-				smsc_init(ifp);
-			}
-			break;
-		}
-		sc->sc_if_flags = ifp->if_flags;
-		break;
-
-	case SIOCGIFMEDIA:
-	case SIOCSIFMEDIA:
-		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
-		break;
-
-	default:
-		if ((error = ether_ioctl(ifp, cmd, data)) != ENETRESET)
-			break;
-
+	if (error == ENETRESET) {
 		error = 0;
-
-		if (cmd == SIOCADDMULTI || cmd == SIOCDELMULTI)
+		if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
+			;
+		else if (ifp->if_flags & IFF_RUNNING) {
+			mutex_enter(&sc->sc_lock);
 			smsc_setmulti(sc);
-
+			mutex_exit(&sc->sc_lock);
+		}
 	}
-	splx(s);
-
 	return error;
 }
 
@@ -991,7 +1009,7 @@ smsc_attach(device_t parent, device_t se
 	char *devinfop;
 	struct mii_data *mii;
 	struct ifnet *ifp;
-	int err, s, i;
+	int err, i;
 	uint32_t mac_h, mac_l;
 
 	sc->sc_dev = self;
@@ -1013,6 +1031,10 @@ smsc_attach(device_t parent, device_t se
 	/* Setup the endpoints for the SMSC LAN95xx device(s) */
 	usb_init_task(&sc->sc_tick_task, smsc_tick_task, sc, 0);
 	usb_init_task(&sc->sc_stop_task, (void (*)(void *))smsc_stop, sc, 0);
+
+	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+	mutex_init(&sc->sc_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
+	mutex_init(&sc->sc_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
 	mutex_init(&sc->sc_mii_lock, MUTEX_DEFAULT, IPL_NONE);
 
 	err = usbd_device2interface_handle(dev, SMSC_IFACE_IDX, &sc->sc_iface);
@@ -1047,12 +1069,11 @@ smsc_attach(device_t parent, device_t se
 		}
 	}
 
-	s = splnet();
-
 	ifp = &sc->sc_ec.ec_if;
 	ifp->if_softc = sc;
 	strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+	ifp->if_extflags = IFEF_START_MPSAFE;
 	ifp->if_init = smsc_init;
 	ifp->if_ioctl = smsc_ioctl;
 	ifp->if_start = smsc_start;
@@ -1120,16 +1141,17 @@ smsc_attach(device_t parent, device_t se
 	} else
 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
 
-	if_attach(ifp);
+	if_initialize(ifp);
+	sc->sc_ipq = if_percpuq_create(&sc->sc_ec.ec_if);
 	ether_ifattach(ifp, sc->sc_enaddr);
+	if_register(ifp);
+	ether_set_ifflags_cb(&sc->sc_ec, smsc_ifflags_cb);
 
 	rnd_attach_source(&sc->sc_rnd_source, device_xname(sc->sc_dev),
 	    RND_TYPE_NET, RND_FLAG_DEFAULT);
 
 	callout_init(&sc->sc_stat_ch, 0);
 
-	splx(s);
-
 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
 }
 
@@ -1500,6 +1522,22 @@ smsc_tx_list_init(struct smsc_softc *sc)
 	return 0;
 }
 
+void
+smsc_tx_list_free(struct smsc_softc *sc)
+{
+	/* Free TX resources. */
+	for (size_t i = 0; i < SMSC_TX_LIST_CNT; i++) {
+		if (sc->sc_cdata.tx_chain[i].sc_mbuf != NULL) {
+			m_freem(sc->sc_cdata.tx_chain[i].sc_mbuf);
+			sc->sc_cdata.tx_chain[i].sc_mbuf = NULL;
+		}
+		if (sc->sc_cdata.tx_chain[i].sc_xfer != NULL) {
+			usbd_destroy_xfer(sc->sc_cdata.tx_chain[i].sc_xfer);
+			sc->sc_cdata.tx_chain[i].sc_xfer = NULL;
+		}
+	}
+}
+
 int
 smsc_rx_list_init(struct smsc_softc *sc)
 {
@@ -1525,6 +1563,22 @@ smsc_rx_list_init(struct smsc_softc *sc)
 	return 0;
 }
 
+void
+smsc_rx_list_free(struct smsc_softc *sc)
+{
+	/* Free RX resources. */
+	for (size_t i = 0; i < SMSC_RX_LIST_CNT; i++) {
+		if (sc->sc_cdata.rx_chain[i].sc_mbuf != NULL) {
+			m_freem(sc->sc_cdata.rx_chain[i].sc_mbuf);
+			sc->sc_cdata.rx_chain[i].sc_mbuf = NULL;
+		}
+		if (sc->sc_cdata.rx_chain[i].sc_xfer != NULL) {
+			usbd_destroy_xfer(sc->sc_cdata.rx_chain[i].sc_xfer);
+			sc->sc_cdata.rx_chain[i].sc_xfer = NULL;
+		}
+	}
+}
+
 struct mbuf *
 smsc_newbuf(void)
 {
@@ -1546,13 +1600,10 @@ smsc_newbuf(void)
 int
 smsc_encap(struct smsc_softc *sc, struct mbuf *m, int idx)
 {
-	struct ifnet		*ifp = &sc->sc_ec.ec_if;
-	struct smsc_chain	*c;
-	usbd_status		 err;
-	uint32_t		 txhdr;
-	uint32_t		 frm_len = 0;
-
-	c = &sc->sc_cdata.tx_chain[idx];
+	struct ifnet * const ifp = &sc->sc_ec.ec_if;
+	struct smsc_chain * const c = &sc->sc_cdata.tx_chain[idx];
+	uint32_t txhdr;
+	uint32_t frm_len = 0;
 
 	/*
 	 * Each frame is prefixed with two 32-bit values describing the
@@ -1578,7 +1629,7 @@ smsc_encap(struct smsc_softc *sc, struct
 	usbd_setup_xfer(c->sc_xfer, c, c->sc_buf, frm_len,
 	    USBD_FORCE_SHORT_XFER, 10000, smsc_txeof);
 
-	err = usbd_transfer(c->sc_xfer);
+	usbd_status err = usbd_transfer(c->sc_xfer);
 	/* XXXNH get task to stop interface */
 	if (err != USBD_IN_PROGRESS) {
 		smsc_stop(ifp, 0);

Index: src/sys/dev/usb/if_smscvar.h
diff -u src/sys/dev/usb/if_smscvar.h:1.3.4.3 src/sys/dev/usb/if_smscvar.h:1.3.4.4
--- src/sys/dev/usb/if_smscvar.h:1.3.4.3	Sun Mar 20 08:42:19 2016
+++ src/sys/dev/usb/if_smscvar.h	Fri Jul 15 08:50:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_smscvar.h,v 1.3.4.3 2016/03/20 08:42:19 skrll Exp $	*/
+/*	$NetBSD: if_smscvar.h,v 1.3.4.4 2016/07/15 08:50:59 skrll Exp $	*/
 
 /*	$OpenBSD: if_smscreg.h,v 1.2 2012/09/27 12:38:11 jsg Exp $	*/
 /*-
@@ -82,6 +82,9 @@ struct smsc_softc {
 	int			sc_ed[SMSC_ENDPT_MAX];
 	struct usbd_pipe *	sc_ep[SMSC_ENDPT_MAX];
 
+	kmutex_t		sc_lock;
+	kmutex_t		sc_txlock;
+	kmutex_t		sc_rxlock;
 	kmutex_t		sc_mii_lock;
 
 	struct smsc_cdata	sc_cdata;
@@ -92,6 +95,9 @@ struct smsc_softc {
 
 	uint32_t		sc_flags;
 #define	SMSC_FLAG_LINK      0x0001
+
+	struct if_percpuq *sc_ipq;		/* softint-based input queues */
+
 };
 
 #define SMSC_MIN_BUFSZ		2048

Reply via email to