Module Name:    src
Committed By:   skrll
Date:           Sat Apr 15 14:38:44 UTC 2017

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.35 -r1.22.2.36 src/sys/dev/usb/if_smsc.c
cvs rdiff -u -r1.3.4.6 -r1.3.4.7 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.35 src/sys/dev/usb/if_smsc.c:1.22.2.36
--- src/sys/dev/usb/if_smsc.c:1.22.2.35	Mon Feb  6 10:20:01 2017
+++ src/sys/dev/usb/if_smsc.c	Sat Apr 15 14:38:44 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_smsc.c,v 1.22.2.35 2017/02/06 10:20:01 skrll Exp $	*/
+/*	$NetBSD: if_smsc.c,v 1.22.2.36 2017/04/15 14:38:44 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 $ */
@@ -172,6 +172,7 @@ struct mbuf	*smsc_newbuf(void);
 void		 smsc_tick(void *);
 void		 smsc_tick_task(void *);
 void		 smsc_miibus_statchg(struct ifnet *);
+void		 smsc_miibus_statchg_locked(struct ifnet *);
 int		 smsc_miibus_readreg(device_t, int, int);
 void		 smsc_miibus_writereg(device_t, int, int, int);
 int		 smsc_ifmedia_upd(struct ifnet *);
@@ -312,14 +313,37 @@ smsc_miibus_writereg(device_t dev, int p
 void
 smsc_miibus_statchg(struct ifnet *ifp)
 {
+	if (ifp == NULL)
+		return;
+
+	struct smsc_softc * const sc = ifp->if_softc;
+
+	mutex_enter(&sc->sc_lock);
+	if (sc->sc_dying) {
+		mutex_exit(&sc->sc_lock);
+		return;
+	}
+	smsc_miibus_statchg_locked(ifp);
+
+	mutex_exit(&sc->sc_lock);
+}
+
+
+void
+smsc_miibus_statchg_locked(struct ifnet *ifp)
+{
 	struct smsc_softc * const sc = ifp->if_softc;
 	struct mii_data * const mii = &sc->sc_mii;
 	int err;
 	uint32_t flow;
 	uint32_t afc_cfg;
 
-	if ((ifp->if_flags & IFF_RUNNING) == 0)
+	KASSERT(mutex_owned(&sc->sc_lock));
+
+	if ((ifp->if_flags & IFF_RUNNING) == 0) {
+		smsc_dbg_printf(sc, "%s: not running\n", __func__);
 		return;
+	}
 
 	/* Use the MII status to determine link status */
 	sc->sc_flags &= ~SMSC_FLAG_LINK;
@@ -405,15 +429,20 @@ smsc_ifmedia_sts(struct ifnet *ifp, stru
 	struct smsc_softc * const sc = ifp->if_softc;
 	struct mii_data * const mii = &sc->sc_mii;
 
+	/* SMSC_LOCK */
+
 	mii_pollstat(mii);
 
 	ifmr->ifm_active = mii->mii_media_active;
 	ifmr->ifm_status = mii->mii_media_status;
+
+	/* SMSC_UNLOCK */
 }
 
 static inline uint32_t
 smsc_hash(uint8_t addr[ETHER_ADDR_LEN])
 {
+
 	return (ether_crc32_be(addr, ETHER_ADDR_LEN) >> 26) & 0x3f;
 }
 
@@ -426,6 +455,8 @@ smsc_setmulti(struct smsc_softc *sc)
 	uint32_t hashtbl[2] = { 0, 0 };
 	uint32_t hash;
 
+	KASSERT(mutex_owned(&sc->sc_lock));
+
 	if (sc->sc_dying)
 		return;
 
@@ -441,16 +472,19 @@ allmulti:
 		sc->sc_mac_csr &= ~(SMSC_MAC_CSR_PRMS | SMSC_MAC_CSR_MCPAS);
 	}
 
+	ETHER_LOCK(&sc->sc_ec);
 	ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
 	while (enm != NULL) {
-		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
-		    ETHER_ADDR_LEN) != 0)
+		if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+			ETHER_UNLOCK(&sc->sc_ec);
 			goto allmulti;
+		}
 
 		hash = smsc_hash(enm->enm_addrlo);
 		hashtbl[hash >> 5] |= 1 << (hash & 0x1F);
 		ETHER_NEXT_MULTI(step, enm);
 	}
+	ETHER_UNLOCK(&sc->sc_ec);
 
 	/* Debug */
 	if (sc->sc_mac_csr & SMSC_MAC_CSR_HPFILT) {
@@ -528,6 +562,7 @@ done:
 void
 smsc_reset(struct smsc_softc *sc)
 {
+	KASSERT(mutex_owned(&sc->sc_lock));
 	if (sc->sc_dying)
 		return;
 
@@ -600,6 +635,10 @@ smsc_init_locked(struct ifnet *ifp)
 		goto fail3;
 	}
 
+	mutex_enter(&sc->sc_rxlock);
+	mutex_enter(&sc->sc_txlock);
+	sc->sc_stopping = false;
+
 	/* Start up the receive pipe. */
 	for (size_t i = 0; i < SMSC_RX_LIST_CNT; i++) {
 		struct smsc_chain *c = &sc->sc_cdata.rx_chain[i];
@@ -608,7 +647,8 @@ smsc_init_locked(struct ifnet *ifp)
 		usbd_transfer(c->sc_xfer);
 	}
 
-	sc->sc_stopping = false;
+	mutex_exit(&sc->sc_txlock);
+	mutex_exit(&sc->sc_rxlock);
 
 	/* Indicate we are up and running. */
 	ifp->if_flags |= IFF_RUNNING;
@@ -650,20 +690,24 @@ smsc_start_locked(struct ifnet *ifp)
 
 	/* Don't send anything if there is no link or controller is busy. */
 	if ((sc->sc_flags & SMSC_FLAG_LINK) == 0) {
+		smsc_dbg_printf(sc, "%s: no link\n", __func__);
 		return;
 	}
 
-	if ((ifp->if_flags & (IFF_OACTIVE|IFF_RUNNING)) != IFF_RUNNING)
+	if ((ifp->if_flags & (IFF_OACTIVE|IFF_RUNNING)) != IFF_RUNNING) {
+		smsc_dbg_printf(sc, "%s: not running\n", __func__);
 		return;
+	}
 
 	IFQ_POLL(&ifp->if_snd, m_head);
 	if (m_head == NULL)
 		return;
 
+	IFQ_DEQUEUE(&ifp->if_snd, m_head);
 	if (smsc_encap(sc, m_head, 0)) {
+		m_free(m_head);
 		return;
 	}
-	IFQ_DEQUEUE(&ifp->if_snd, m_head);
 
 	bpf_mtap(ifp, m_head);
 
@@ -683,10 +727,19 @@ smsc_tick(void *xsc)
 	if (sc == NULL)
 		return;
 
-	if (sc->sc_dying)
+	mutex_enter(&sc->sc_lock);
+
+	if (sc->sc_dying) {
+		mutex_exit(&sc->sc_lock);
 		return;
+	}
+
+	if (!sc->sc_ttpending) {
+		sc->sc_ttpending = true;
+		usb_add_task(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER);
+	}
 
-	usb_add_task(sc->sc_udev, &sc->sc_tick_task, USB_TASKQ_DRIVER);
+	mutex_exit(&sc->sc_lock);
 }
 
 void
@@ -932,18 +985,17 @@ 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;
-
+	const int change = ifp->if_flags ^ sc->sc_if_flags;
 	if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
-		rc = ENETRESET;
-		goto out;
+		mutex_exit(&sc->sc_lock);
+		return ENETRESET;
 	}
 
+	smsc_dbg_printf(sc, "%s: change %x\n", __func__, change);
+
 	if ((change & IFF_PROMISC) != 0) {
 		if (ifp->if_flags & IFF_PROMISC) {
 			sc->sc_mac_csr |= SMSC_MAC_CSR_PRMS;
@@ -955,25 +1007,20 @@ smsc_ifflags_cb(struct ethercom *ec)
 		smsc_setmulti(sc);
 	}
 
-out:
 	mutex_exit(&sc->sc_lock);
 
-	return rc;
+	return 0;
 }
 
 
 int
 smsc_ioctl(struct ifnet *ifp, u_long cmd, void *data)
 {
-	struct smsc_softc *sc = ifp->if_softc;
-	int s, error = 0;
+	struct smsc_softc * const sc = ifp->if_softc;
 
-	if (sc->sc_dying)
-		return EIO;
+	smsc_dbg_printf(sc, "%s: cmd %0lx data %p\n", __func__, cmd, data);
 
-	s = splnet();
-	error = ether_ioctl(ifp, cmd, data);
-	splx(s);
+	int error = ether_ioctl(ifp, cmd, data);
 
 	if (error == ENETRESET) {
 		error = 0;
@@ -985,6 +1032,13 @@ smsc_ioctl(struct ifnet *ifp, u_long cmd
 			}
 		}
 	}
+
+	mutex_enter(&sc->sc_rxlock);
+	mutex_enter(&sc->sc_txlock);
+	sc->sc_if_flags = ifp->if_flags;
+	mutex_exit(&sc->sc_txlock);
+	mutex_exit(&sc->sc_rxlock);
+
 	return error;
 }
 
@@ -1062,7 +1116,7 @@ smsc_attach(device_t parent, device_t se
 		}
 	}
 
-	usb_init_task(&sc->sc_tick_task, smsc_tick_task, sc, 0);
+	usb_init_task(&sc->sc_tick_task, smsc_tick_task, sc, USB_TASKQ_MPSAFE);
 
 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
 	mutex_init(&sc->sc_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
@@ -1143,17 +1197,17 @@ smsc_attach(device_t parent, device_t se
 	} else
 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
 
+	callout_init(&sc->sc_stat_ch, CALLOUT_MPSAFE);
+
 	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);
+	if_register(ifp);
 
 	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);
-
 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
 }
 
@@ -1162,16 +1216,15 @@ smsc_detach(device_t self, int flags)
 {
 	struct smsc_softc *sc = device_private(self);
 	struct ifnet *ifp = &sc->sc_ec.ec_if;
-	int s;
 
-	callout_stop(&sc->sc_stat_ch);
+	mutex_enter(&sc->sc_lock);
+	sc->sc_dying = true;
+	mutex_exit(&sc->sc_lock);
 
-	if (sc->sc_ep[SMSC_ENDPT_TX] != NULL)
-		usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_TX]);
-	if (sc->sc_ep[SMSC_ENDPT_RX] != NULL)
-		usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_RX]);
-	if (sc->sc_ep[SMSC_ENDPT_INTR] != NULL)
-		usbd_abort_pipe(sc->sc_ep[SMSC_ENDPT_INTR]);
+	callout_halt(&sc->sc_stat_ch, NULL);
+
+	if (ifp->if_flags & IFF_RUNNING)
+		smsc_stop_locked(ifp, 1);
 
 	/*
 	 * Remove any pending tasks.  They cannot be executing because they run
@@ -1179,22 +1232,11 @@ smsc_detach(device_t self, int flags)
 	 */
 	usb_rem_task(sc->sc_udev, &sc->sc_tick_task);
 
-	s = splusb();
-
-	if (--sc->sc_refcnt >= 0) {
+	mutex_enter(&sc->sc_lock);
+	sc->sc_refcnt--;
+	while (sc->sc_refcnt > 0) {
 		/* Wait for processes to go away */
-		usb_detach_waitold(sc->sc_dev);
-	}
-
-	if (ifp->if_flags & IFF_RUNNING)
-		smsc_stop(ifp ,1);
-
-	rnd_detach_source(&sc->sc_rnd_source);
-	mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
-	ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
-	if (ifp->if_softc != NULL) {
-		ether_ifdetach(ifp);
-		if_detach(ifp);
+		cv_wait(&sc->sc_detachcv, &sc->sc_lock);
 	}
 
 #ifdef DIAGNOSTIC
@@ -1205,16 +1247,20 @@ smsc_detach(device_t self, int flags)
 		    device_xname(sc->sc_dev));
 #endif
 
-	if (--sc->sc_refcnt >= 0) {
-		/* Wait for processes to go away. */
-		usb_detach_waitold(sc->sc_dev);
+	mutex_exit(&sc->sc_lock);
+
+	rnd_detach_source(&sc->sc_rnd_source);
+	mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
+	ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
+	if (ifp->if_softc != NULL) {
+		ether_ifdetach(ifp);
+		if_detach(ifp);
 	}
-	splx(s);
 
 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, sc->sc_dev);
 
+	cv_destroy(&sc->sc_detachcv);
 	mutex_destroy(&sc->sc_mii_lock);
-
 	mutex_destroy(&sc->sc_rxlock);
 	mutex_destroy(&sc->sc_txlock);
 	mutex_destroy(&sc->sc_lock);
@@ -1230,19 +1276,36 @@ smsc_tick_task(void *xsc)
 	if (sc == NULL)
 		return;
 
-	if (sc->sc_dying)
+	mutex_enter(&sc->sc_lock);
+
+	if (sc->sc_dying) {
+		mutex_exit(&sc->sc_lock);
 		return;
+	}
 
 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
-	struct mii_data	* const mii = &sc->sc_mii;
-	const int s = splnet();
+	struct mii_data * const mii = &sc->sc_mii;
+
+	sc->sc_refcnt++;
+	mutex_exit(&sc->sc_lock);
 
 	mii_tick(mii);
 	if ((sc->sc_flags & SMSC_FLAG_LINK) == 0)
 		smsc_miibus_statchg(ifp);
+
+	mutex_enter(&sc->sc_lock);
+	sc->sc_ttpending = false;
+
+	if (--sc->sc_refcnt < 0)
+		cv_broadcast(&sc->sc_detachcv);
+
+	if (sc->sc_dying) {
+		mutex_exit(&sc->sc_lock);
+		return;
+	}
 	callout_reset(&sc->sc_stat_ch, hz, smsc_tick, sc);
 
-	splx(s);
+	mutex_exit(&sc->sc_lock);
 }
 
 int
@@ -1253,7 +1316,17 @@ smsc_activate(device_t self, enum devact
 	switch (act) {
 	case DVACT_DEACTIVATE:
 		if_deactivate(&sc->sc_ec.ec_if);
-		sc->sc_dying = 1;
+
+		mutex_enter(&sc->sc_lock);
+		sc->sc_dying = true;
+
+		mutex_enter(&sc->sc_rxlock);
+		mutex_enter(&sc->sc_txlock);
+		sc->sc_stopping = true;
+		mutex_exit(&sc->sc_txlock);
+		mutex_exit(&sc->sc_rxlock);
+
+		mutex_exit(&sc->sc_lock);
 		return 0;
 	default:
 		return EOPNOTSUPP;
@@ -1264,16 +1337,23 @@ smsc_activate(device_t self, enum devact
 void
 smsc_lock_mii(struct smsc_softc *sc)
 {
+
+	mutex_enter(&sc->sc_lock);
 	sc->sc_refcnt++;
+	mutex_exit(&sc->sc_lock);
+
 	mutex_enter(&sc->sc_mii_lock);
 }
 
 void
 smsc_unlock_mii(struct smsc_softc *sc)
 {
+
 	mutex_exit(&sc->sc_mii_lock);
+	mutex_enter(&sc->sc_lock);
 	if (--sc->sc_refcnt < 0)
-		usb_detach_wakeupold(sc->sc_dev);
+		cv_broadcast(&sc->sc_detachcv);
+	mutex_exit(&sc->sc_lock);
 }
 
 void
@@ -1286,13 +1366,14 @@ smsc_rxeof(struct usbd_xfer *xfer, void 
 	uint32_t total_len;
 
 	mutex_enter(&sc->sc_rxlock);
-
-	if (sc->sc_dying) {
+	if (sc->sc_stopping) {
+		smsc_dbg_printf(sc, "%s: stopping\n", __func__);
 		mutex_exit(&sc->sc_rxlock);
 		return;
 	}
 
-	if (!(ifp->if_flags & IFF_RUNNING)) {
+	if (!(sc->sc_if_flags & IFF_RUNNING)) {
+		smsc_dbg_printf(sc, "%s: not running\n", __func__);
 		mutex_exit(&sc->sc_rxlock);
 		return;
 	}
@@ -1446,6 +1527,11 @@ smsc_rxeof(struct usbd_xfer *xfer, void 
 		if_percpuq_enqueue(sc->sc_ipq, m);
 
 		mutex_enter(&sc->sc_rxlock);
+		if (sc->sc_stopping) {
+			smsc_dbg_printf(sc, "%s: stopping\n", __func__);
+			mutex_exit(&sc->sc_rxlock);
+			return;
+		}
 	}
 
 done:
@@ -1467,13 +1553,8 @@ smsc_txeof(struct usbd_xfer *xfer, void 
 	struct ifnet *ifp = &sc->sc_ec.ec_if;
 
 	mutex_enter(&sc->sc_txlock);
-
-	if (sc->sc_dying) {
-		mutex_exit(&sc->sc_txlock);
-		return;
-	}
-
 	if (sc->sc_stopping) {
+		smsc_dbg_printf(sc, "%s: stopping\n", __func__);
 		mutex_exit(&sc->sc_txlock);
 		return;
 	}
@@ -1607,7 +1688,6 @@ smsc_newbuf(void)
 int
 smsc_encap(struct smsc_softc *sc, struct mbuf *m, int 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;
@@ -1637,9 +1717,7 @@ smsc_encap(struct smsc_softc *sc, struct
 	    USBD_FORCE_SHORT_XFER, 10000, smsc_txeof);
 
 	usbd_status err = usbd_transfer(c->sc_xfer);
-	/* XXXNH get task to stop interface */
 	if (err != USBD_IN_PROGRESS) {
-		smsc_stop(ifp, 0);
 		return EIO;
 	}
 

Index: src/sys/dev/usb/if_smscvar.h
diff -u src/sys/dev/usb/if_smscvar.h:1.3.4.6 src/sys/dev/usb/if_smscvar.h:1.3.4.7
--- src/sys/dev/usb/if_smscvar.h:1.3.4.6	Tue Jan 31 11:41:14 2017
+++ src/sys/dev/usb/if_smscvar.h	Sat Apr 15 14:38:44 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_smscvar.h,v 1.3.4.6 2017/01/31 11:41:14 skrll Exp $	*/
+/*	$NetBSD: if_smscvar.h,v 1.3.4.7 2017/04/15 14:38:44 skrll Exp $	*/
 
 /*	$OpenBSD: if_smscreg.h,v 1.2 2012/09/27 12:38:11 jsg Exp $	*/
 /*-
@@ -57,6 +57,7 @@ struct smsc_softc {
 	struct usbd_device *	sc_udev;
 	bool			sc_dying;
 	bool			sc_stopping;
+	bool			sc_ttpending;
 
 	uint8_t			sc_enaddr[ETHER_ADDR_LEN];
 	struct ethercom		sc_ec;
@@ -86,6 +87,7 @@ struct smsc_softc {
 	kmutex_t		sc_txlock;
 	kmutex_t		sc_rxlock;
 	kmutex_t		sc_mii_lock;
+	kcondvar_t		sc_detachcv;
 
 	struct smsc_cdata	sc_cdata;
 	callout_t		sc_stat_ch;

Reply via email to