myx_intr should be able to run without a lock, except in teh situation where 
are bringing an interface down.

this interlock was done by serialising the changes myx_down and myx_intr needed 
to do with a mutex, but for the many millions and billions of interrupts you 
get when you're actually using the interface, this is an annoying overhead.

this plays tricks to avoid the mutex.

it works for me, but im throwing it out so someone else can try and hopefully 
break it.

Index: if_myx.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_myx.c,v
retrieving revision 1.82
diff -u -p -r1.82 if_myx.c
--- if_myx.c    15 Aug 2015 01:17:01 -0000      1.82
+++ if_myx.c    1 Sep 2015 05:09:34 -0000
@@ -32,6 +32,7 @@
 #include <sys/pool.h>
 #include <sys/timeout.h>
 #include <sys/device.h>
+#include <sys/proc.h>
 #include <sys/queue.h>
 #include <sys/atomic.h>
 
@@ -123,7 +124,6 @@ struct myx_softc {
 
        struct myx_dmamem        sc_sts_dma;
        volatile struct myx_status      *sc_sts;
-       struct mutex             sc_sts_mtx;
 
        int                      sc_intx;
        void                    *sc_irqh;
@@ -226,26 +226,6 @@ void                       myx_tx_free(struct myx_softc *);
 
 void                   myx_refill(void *);
 
-static inline void
-myx_sts_enter(struct myx_softc *sc)
-{
-       bus_dmamap_t             map = sc->sc_sts_dma.mxm_map;
-
-       mtx_enter(&sc->sc_sts_mtx);
-       bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
-           BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
-}
-
-static inline void
-myx_sts_leave(struct myx_softc *sc)
-{
-       bus_dmamap_t             map = sc->sc_sts_dma.mxm_map;
-
-       bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
-           BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
-       mtx_leave(&sc->sc_sts_mtx);
-}
-
 struct cfdriver myx_cd = {
        NULL, "myx", DV_IFNET
 };
@@ -285,8 +265,6 @@ myx_attach(struct device *parent, struct
        timeout_set(&sc->sc_rx_ring[MYX_RXBIG].mrr_refill, myx_refill,
            &sc->sc_rx_ring[MYX_RXBIG]);
 
-       mtx_init(&sc->sc_sts_mtx, IPL_NET);
-
        /* Map the PCI memory space */
        memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, MYXBAR0);
        if (pci_mapreg_map(pa, MYXBAR0, memtype, BUS_SPACE_MAP_PREFETCHABLE,
@@ -889,6 +867,7 @@ void
 myx_media_status(struct ifnet *ifp, struct ifmediareq *imr)
 {
        struct myx_softc        *sc = (struct myx_softc *)ifp->if_softc;
+       bus_dmamap_t             map = sc->sc_sts_dma.mxm_map;
        u_int32_t                sts;
 
        imr->ifm_active = IFM_ETHER | IFM_AUTO;
@@ -897,9 +876,11 @@ myx_media_status(struct ifnet *ifp, stru
                return;
        }
 
-       myx_sts_enter(sc);
+       bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+           BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        sts = sc->sc_sts->ms_linkstate;
-       myx_sts_leave(sc);
+       bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+           BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
 
        myx_link_state(sc, sts);
 
@@ -1220,9 +1201,7 @@ myx_up(struct myx_softc *sc)
                goto empty_rx_ring_big;
        }
 
-       mtx_enter(&sc->sc_sts_mtx);
        sc->sc_state = MYX_S_RUNNING;
-       mtx_leave(&sc->sc_sts_mtx);
 
        if (myx_cmd(sc, MYXCMD_SET_IFUP, &mc, NULL) != 0) {
                printf("%s: failed to start the device\n", DEVNAME(sc));
@@ -1349,24 +1328,28 @@ myx_down(struct myx_softc *sc)
        struct ifnet            *ifp = &sc->sc_ac.ac_if;
        volatile struct myx_status *sts = sc->sc_sts;
        bus_dmamap_t             map = sc->sc_sts_dma.mxm_map;
+       struct sleep_state       sls;
        struct myx_cmd           mc;
        int                      s;
        int                      ring;
 
-       myx_sts_enter(sc);
+       bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+           BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        sc->sc_linkdown = sts->ms_linkdown;
+       bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+           BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+
        sc->sc_state = MYX_S_DOWN;
+       membar_producer();
 
        memset(&mc, 0, sizeof(mc));
        (void)myx_cmd(sc, MYXCMD_SET_IFDOWN, &mc, NULL);
 
-       bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
-           BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
-       while (sc->sc_state != MYX_S_OFF)
-               msleep(sts, &sc->sc_sts_mtx, 0, "myxdown", 0);
-       bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
-           BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
-       mtx_leave(&sc->sc_sts_mtx);
+       while (sc->sc_state != MYX_S_OFF) {
+               sleep_setup(&sls, sts, PWAIT, "myxdown");
+               membar_consumer();
+               sleep_finish(&sls, sc->sc_state != MYX_S_OFF);
+       }
 
        s = splnet();
        if (ifp->if_link_state != LINK_STATE_UNKNOWN) {
@@ -1604,23 +1587,22 @@ myx_intr(void *arg)
        struct myx_softc        *sc = (struct myx_softc *)arg;
        struct ifnet            *ifp = &sc->sc_ac.ac_if;
        volatile struct myx_status *sts = sc->sc_sts;
-       enum myx_state           state = MYX_S_RUNNING;
+       enum myx_state           state;
        bus_dmamap_t             map = sc->sc_sts_dma.mxm_map;
-       u_int32_t                data, link = 0xffffffff;
+       u_int32_t                data, start;
        u_int8_t                 valid = 0;
 
-       mtx_enter(&sc->sc_sts_mtx);
-       if (sc->sc_state == MYX_S_OFF) {
-               mtx_leave(&sc->sc_sts_mtx);
+       state = sc->sc_state;
+       if (state == MYX_S_OFF)
                return (0);
-       }
 
        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
 
        valid = sts->ms_isvalid;
        if (valid == 0x0) {
-               myx_sts_leave(sc);
+               bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+                   BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
                return (0);
        }
 
@@ -1639,15 +1621,6 @@ myx_intr(void *arg)
                    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        } while (sts->ms_isvalid);
 
-       if (sts->ms_statusupdated) {
-               link = sts->ms_linkstate;
-
-               if (sc->sc_state == MYX_S_DOWN &&
-                   sc->sc_linkdown != sts->ms_linkdown)
-                       state = MYX_S_DOWN;
-       }
-       myx_sts_leave(sc);
-
        data = betoh32(data);
        if (data != sc->sc_tx_count)
                myx_txeof(sc, data);
@@ -1662,23 +1635,29 @@ myx_intr(void *arg)
        bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh,
            sc->sc_irqclaimoff + sizeof(data), &data, sizeof(data));
 
-       if (state == MYX_S_DOWN) {
-               /* myx_down is waiting for us */
-               mtx_enter(&sc->sc_sts_mtx);
-               sc->sc_state = MYX_S_OFF;
-               wakeup(sts);
-               mtx_leave(&sc->sc_sts_mtx);
+       start = ISSET(ifp->if_flags, IFF_OACTIVE);
 
-               return (1);
+       if (sts->ms_statusupdated) {
+               if (state == MYX_S_DOWN &&
+                   sc->sc_linkdown != sts->ms_linkdown) {
+                       sc->sc_state = MYX_S_OFF;
+                       membar_producer();
+                       wakeup(sts);
+                       start = 0;
+               } else {
+                       data = sts->ms_linkstate;
+                       if (data != 0xffffffff) {
+                               KERNEL_LOCK();
+                               myx_link_state(sc, data);
+                               KERNEL_UNLOCK();
+                       }
+               }
        }
 
-       if (link != 0xffffffff) {
-               KERNEL_LOCK();
-               myx_link_state(sc, link);
-               KERNEL_UNLOCK();
-       }
+       bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+           BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
 
-       if (ISSET(ifp->if_flags, IFF_OACTIVE)) {
+       if (start) {
                KERNEL_LOCK();
                CLR(ifp->if_flags, IFF_OACTIVE);
                myx_start(ifp);

Reply via email to