Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Make smsc(4) MPSAFE. Patch from skrll@.



details:   https://anonhg.NetBSD.org/src/rev/e4111b536553
branches:  trunk
changeset: 433332:e4111b536553
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Sat Sep 08 13:10:08 2018 +0000

description:
Make smsc(4) MPSAFE. Patch from skrll@.

diffstat:

 sys/dev/usb/if_smsc.c    |  671 ++++++++++++++++++++++++++++------------------
 sys/dev/usb/if_smscvar.h |   19 +-
 2 files changed, 426 insertions(+), 264 deletions(-)

diffs (truncated from 1255 to 300 lines):

diff -r 929c326a197e -r e4111b536553 sys/dev/usb/if_smsc.c
--- a/sys/dev/usb/if_smsc.c     Sat Sep 08 12:40:17 2018 +0000
+++ b/sys/dev/usb/if_smsc.c     Sat Sep 08 13:10:08 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_smsc.c,v 1.37 2018/08/12 06:02:38 rin Exp $ */
+/*     $NetBSD: if_smsc.c,v 1.38 2018/09/08 13:10:08 mlelstv 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 $ */
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_smsc.c,v 1.37 2018/08/12 06:02:38 rin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_smsc.c,v 1.38 2018/09/08 13:10:08 mlelstv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -70,17 +70,15 @@
 
 #include <sys/param.h>
 #include <sys/bus.h>
-#include <sys/systm.h>
-#include <sys/sockio.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
 #include <sys/mbuf.h>
 #include <sys/mutex.h>
-#include <sys/kernel.h>
 #include <sys/proc.h>
+#include <sys/rndsource.h>
 #include <sys/socket.h>
-
-#include <sys/device.h>
-
-#include <sys/rndsource.h>
+#include <sys/sockio.h>
+#include <sys/systm.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -164,9 +162,12 @@
 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);
@@ -174,6 +175,7 @@
 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 *);
@@ -182,7 +184,9 @@
 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);
@@ -259,7 +263,7 @@
 int
 smsc_miibus_readreg(device_t dev, int phy, int reg)
 {
-       struct smsc_softc *sc = device_private(dev);
+       struct smsc_softc * const sc = device_private(dev);
        uint32_t addr;
        uint32_t val = 0;
 
@@ -286,7 +290,7 @@
 void
 smsc_miibus_writereg(device_t dev, int phy, int reg, int val)
 {
-       struct smsc_softc *sc = device_private(dev);
+       struct smsc_softc * const sc = device_private(dev);
        uint32_t addr;
 
        if (sc->sc_phyno != phy)
@@ -312,15 +316,37 @@
 void
 smsc_miibus_statchg(struct ifnet *ifp)
 {
-       struct smsc_softc *sc = ifp->if_softc;
-       struct mii_data *mii = &sc->sc_mii;
+       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 (mii == NULL || ifp == NULL ||
-           (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;
@@ -386,8 +412,8 @@
 int
 smsc_ifmedia_upd(struct ifnet *ifp)
 {
-       struct smsc_softc *sc = ifp->if_softc;
-       struct mii_data *mii = &sc->sc_mii;
+       struct smsc_softc * const sc = ifp->if_softc;
+       struct mii_data * const mii = &sc->sc_mii;
        int err;
 
        if (mii->mii_instance) {
@@ -403,13 +429,17 @@
 void
 smsc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
 {
-       struct smsc_softc *sc = ifp->if_softc;
-       struct mii_data *mii = &sc->sc_mii;
+       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
@@ -422,11 +452,13 @@
 void
 smsc_setmulti(struct smsc_softc *sc)
 {
-       struct ifnet            *ifp = &sc->sc_ec.ec_if;
-       struct ether_multi      *enm;
-       struct ether_multistep   step;
-       uint32_t                 hashtbl[2] = { 0, 0 };
-       uint32_t                 hash;
+       struct ifnet * const ifp = &sc->sc_ec.ec_if;
+       struct ether_multi *enm;
+       struct ether_multistep step;
+       uint32_t hashtbl[2] = { 0, 0 };
+       uint32_t hash;
+
+       KASSERT(mutex_owned(&sc->sc_lock));
 
        if (sc->sc_dying)
                return;
@@ -443,16 +475,19 @@
                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) {
@@ -471,13 +506,10 @@
 int
 smsc_sethwcsum(struct smsc_softc *sc)
 {
-       struct ifnet *ifp = &sc->sc_ec.ec_if;
+       struct ifnet * const ifp = &sc->sc_ec.ec_if;
        uint32_t val;
        int err;
 
-       if (!ifp)
-               return EIO;
-
        err = smsc_read_reg(sc, SMSC_COE_CTRL, &val);
        if (err != 0) {
                smsc_warn_printf(sc, "failed to read SMSC_COE_CTRL (err=%d)\n",
@@ -533,6 +565,7 @@
 void
 smsc_reset(struct smsc_softc *sc)
 {
+       KASSERT(mutex_owned(&sc->sc_lock));
        if (sc->sc_dying)
                return;
 
@@ -546,19 +579,26 @@
 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 * const 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);
@@ -571,83 +611,122 @@
 
        /* Open RX and TX pipes. */
        err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_RX],
-           USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_RX]);
+           USBD_EXCLUSIVE_USE | USBD_MPSAFE, &sc->sc_ep[SMSC_ENDPT_RX]);
        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],
-           USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_TX]);
+           USBD_EXCLUSIVE_USE | USBD_MPSAFE, &sc->sc_ep[SMSC_ENDPT_TX]);
        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;



Home | Main Index | Thread Index | Old Index