Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/pci bge(4): fix the MP improvements and improve some...



details:   https://anonhg.NetBSD.org/src/rev/25861b6c86ff
branches:  trunk
changeset: 369849:25861b6c86ff
user:      skrll <skrll%NetBSD.org@localhost>
date:      Sun Sep 04 08:50:25 2022 +0000

description:
bge(4): fix the MP improvements and improve some more.

- Have two locks sc_core_lock at IPL_NONE and sc_intr_lock at IPL_NET and
  use appropriately.

- Use stopping flags instead of bge_if_flags so that bge_if_flags only
  needs to be protected by the sc_core_lock

- Use ifmedia_init_with_lock and provide the sc_intr_lock. mii operatiions
  are done from the interrupt handler.

- Fixup locking in bge_detach.

- Rename bge_watchdog to bge_watchdog_tick to avoid confusion with the
  if_watchdog method.

- Sprinkle some more asserts.

diffstat:

 sys/dev/pci/if_bge.c    |  156 ++++++++++++++++++++++++++++++-----------------
 sys/dev/pci/if_bgevar.h |    5 +-
 2 files changed, 103 insertions(+), 58 deletions(-)

diffs (truncated from 435 to 300 lines):

diff -r df43382526dc -r 25861b6c86ff sys/dev/pci/if_bge.c
--- a/sys/dev/pci/if_bge.c      Sun Sep 04 08:42:02 2022 +0000
+++ b/sys/dev/pci/if_bge.c      Sun Sep 04 08:50:25 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_bge.c,v 1.385 2022/09/04 08:42:02 skrll Exp $       */
+/*     $NetBSD: if_bge.c,v 1.386 2022/09/04 08:50:25 skrll Exp $       */
 
 /*
  * Copyright (c) 2001 Wind River Systems
@@ -79,7 +79,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.385 2022/09/04 08:42:02 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.386 2022/09/04 08:50:25 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -205,8 +205,8 @@
 static int bge_init(struct ifnet *);
 static int bge_init_locked(struct ifnet *);
 static void bge_stop(struct ifnet *, int);
-static void bge_stop_locked(struct ifnet *, int);
-static bool bge_watchdog(struct ifnet *);
+static void bge_stop_locked(struct ifnet *, bool);
+static bool bge_watchdog_tick(struct ifnet *);
 static int bge_ifmedia_upd(struct ifnet *);
 static void bge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
 static void bge_handle_reset_work(struct work *, void *);
@@ -1260,11 +1260,11 @@
         * occasionally cause glitches where Rx-interrupts are not
         * honoured for up to 10 seconds. jonathan%NetBSD.org@localhost, 2003-04-05
         */
-       mutex_enter(sc->sc_core_lock);
+       mutex_enter(sc->sc_intr_lock);
        sc->bge_rx_coal_ticks = bge_rx_threshes[lvl].rx_ticks;
        sc->bge_rx_max_coal_bds = bge_rx_threshes[lvl].rx_max_bds;
        sc->bge_pending_rxintr_change = true;
-       mutex_exit(sc->sc_core_lock);
+       mutex_exit(sc->sc_intr_lock);
 }
 
 
@@ -1456,14 +1456,14 @@
        if (i < 0 || i >= BGE_JSLOTS)
                panic("bge_jfree: asked to free buffer that we don't manage!");
 
-       mutex_enter(sc->sc_core_lock);
+       mutex_enter(sc->sc_intr_lock);
        entry = SLIST_FIRST(&sc->bge_jinuse_listhead);
        if (entry == NULL)
                panic("bge_jfree: buffer not in use!");
        entry->slot = i;
        SLIST_REMOVE_HEAD(&sc->bge_jinuse_listhead, jpool_entries);
        SLIST_INSERT_HEAD(&sc->bge_jfree_listhead, entry, jpool_entries);
-       mutex_exit(sc->sc_core_lock);
+       mutex_exit(sc->sc_intr_lock);
 
        if (__predict_true(m != NULL))
                pool_cache_put(mb_cache, m);
@@ -3297,6 +3297,9 @@
                return;
        }
 
+       sc->bge_stopping = false;
+       sc->bge_txrx_stopping = false;
+
        /* Save various chip information. */
        sc->bge_chipid = bge_chipid(pa);
        sc->bge_phy_addr = bge_phy_addr(sc);
@@ -3868,7 +3871,8 @@
        else
                sc->bge_return_ring_cnt = BGE_RETURN_RING_CNT;
 
-       sc->sc_core_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
+       sc->sc_core_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
+       sc->sc_intr_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
 
        /* Set up ifnet structure */
        ifp = &sc->ethercom.ec_if;
@@ -3943,8 +3947,9 @@
 
                struct ifmedia * const ifm = &sc->bge_ifmedia;
                sc->ethercom.ec_ifmedia = ifm;
-               ifmedia_init(ifm, IFM_IMASK, bge_ifmedia_upd,
-                   bge_ifmedia_sts);
+
+               ifmedia_init_with_lock(ifm, IFM_IMASK,
+                   bge_ifmedia_upd, bge_ifmedia_sts, sc->sc_intr_lock);
                ifmedia_add(ifm, IFM_ETHER | IFM_1000_SX, 0, NULL);
                ifmedia_add(ifm, IFM_ETHER | IFM_1000_SX | IFM_FDX, 0, NULL);
                ifmedia_add(ifm, IFM_ETHER | IFM_AUTO, 0, NULL);
@@ -3978,8 +3983,8 @@
                trys = 0;
                BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
                sc->ethercom.ec_mii = mii;
-               ifmedia_init(&mii->mii_media, 0, bge_ifmedia_upd,
-                            bge_ifmedia_sts);
+               ifmedia_init_with_lock(&mii->mii_media, 0, bge_ifmedia_upd,
+                   bge_ifmedia_sts, sc->sc_intr_lock);
                mii_flags = MIIF_DOPAUSE;
                if (sc->bge_flags & BGEF_FIBER_MII)
                        mii_flags |= MIIF_HAVEFIBER;
@@ -4087,8 +4092,13 @@
        struct bge_softc * const sc = device_private(self);
        struct ifnet * const ifp = &sc->ethercom.ec_if;
 
+       IFNET_LOCK(ifp);
+
        /* Stop the interface. Callouts are stopped in it. */
        bge_stop(ifp, 1);
+       sc->bge_detaching = true;
+
+       IFNET_UNLOCK(ifp);
 
        mii_detach(&sc->bge_mii, MII_PHY_ANY, MII_OFFSET_ANY);
 
@@ -4701,7 +4711,11 @@
        if (BGE_IS_5717_PLUS(sc))
                intrmask = 0;
 
-       mutex_enter(sc->sc_core_lock);
+       mutex_enter(sc->sc_intr_lock);
+       if (sc->bge_txrx_stopping) {
+               mutex_exit(sc->sc_intr_lock);
+               return 1;
+       }
 
        /*
         * It is possible for the interrupt to arrive before
@@ -4723,7 +4737,7 @@
                if (sc->bge_lasttag == statustag &&
                    (~pcistate & intrmask)) {
                        BGE_EVCNT_INCR(sc->bge_ev_intr_spurious);
-                       mutex_exit(sc->sc_core_lock);
+                       mutex_exit(sc->sc_intr_lock);
                        return 0;
                }
                sc->bge_lasttag = statustag;
@@ -4731,7 +4745,7 @@
                if (!(statusword & BGE_STATFLAG_UPDATED) &&
                    !(~pcistate & intrmask)) {
                        BGE_EVCNT_INCR(sc->bge_ev_intr_spurious2);
-                       mutex_exit(sc->sc_core_lock);
+                       mutex_exit(sc->sc_intr_lock);
                        return 0;
                }
                statustag = 0;
@@ -4753,13 +4767,11 @@
            BGE_STS_BIT(sc, BGE_STS_LINK_EVT))
                bge_link_upd(sc);
 
-       if (sc->bge_if_flags & IFF_RUNNING) {
-               /* Check RX return ring producer/consumer */
-               bge_rxeof(sc);
-
-               /* Check TX ring producer/consumer */
-               bge_txeof(sc);
-       }
+       /* Check RX return ring producer/consumer */
+       bge_rxeof(sc);
+
+       /* Check TX ring producer/consumer */
+       bge_txeof(sc);
 
        if (sc->bge_pending_rxintr_change) {
                uint32_t rx_ticks = sc->bge_rx_coal_ticks;
@@ -4780,10 +4792,9 @@
        /* Re-enable interrupts. */
        bge_writembx_flush(sc, BGE_MBX_IRQ0_LO, statustag);
 
-       if (sc->bge_if_flags & IFF_RUNNING)
-               if_schedule_deferred_start(ifp);
-
-       mutex_exit(sc->sc_core_lock);
+       if_schedule_deferred_start(ifp);
+
+       mutex_exit(sc->sc_intr_lock);
 
        return 1;
 }
@@ -4820,6 +4831,10 @@
        struct mii_data * const mii = &sc->bge_mii;
 
        mutex_enter(sc->sc_core_lock);
+       if (sc->bge_stopping) {
+               mutex_exit(sc->sc_core_lock);
+               return;
+       }
 
        if (BGE_IS_5705_PLUS(sc))
                bge_stats_update_regs(sc);
@@ -4840,15 +4855,17 @@
                 * IPMI/ASF mode or produce extra input errors.
                 * (extra input errors was reported for bcm5701 & bcm5704).
                 */
-               if (!BGE_STS_BIT(sc, BGE_STS_LINK))
+               if (!BGE_STS_BIT(sc, BGE_STS_LINK)) {
+                       mutex_enter(sc->sc_intr_lock);
                        mii_tick(mii);
+                       mutex_exit(sc->sc_intr_lock);
+               }
        }
 
        bge_asf_driver_up(sc);
 
-       const bool ok = bge_watchdog(ifp);
-
-       if (ok && !sc->bge_detaching)
+       const bool ok = bge_watchdog_tick(ifp);
+       if (ok)
                callout_schedule(&sc->bge_timeout, hz);
 
        mutex_exit(sc->sc_core_lock);
@@ -5454,9 +5471,10 @@
 {
        struct bge_softc * const sc = ifp->if_softc;
 
-       mutex_enter(sc->sc_core_lock);
-       bge_start_locked(ifp);
-       mutex_exit(sc->sc_core_lock);
+       mutex_enter(sc->sc_intr_lock);
+       if (!sc->bge_txrx_stopping)
+               bge_start_locked(ifp);
+       mutex_exit(sc->sc_intr_lock);
 }
 
 /*
@@ -5473,8 +5491,7 @@
        int pkts = 0;
        int error;
 
-       if ((sc->bge_if_flags & IFF_RUNNING) != IFF_RUNNING)
-               return;
+       KASSERT(mutex_owned(sc->sc_intr_lock));
 
        prodidx = sc->bge_tx_prodidx;
 
@@ -5549,6 +5566,11 @@
 {
        struct bge_softc * const sc = ifp->if_softc;
 
+       KASSERT(IFNET_LOCKED(ifp));
+
+       if (sc->bge_detaching)
+               return ENXIO;
+
        mutex_enter(sc->sc_core_lock);
        int ret = bge_init_locked(ifp);
        mutex_exit(sc->sc_core_lock);
@@ -5565,12 +5587,13 @@
        uint32_t mode, reg;
        int error = 0;
 
+       ASSERT_SLEEPABLE();
        KASSERT(IFNET_LOCKED(ifp));
        KASSERT(mutex_owned(sc->sc_core_lock));
        KASSERT(ifp == &sc->ethercom.ec_if);
 
        /* Cancel pending I/O and flush buffers. */
-       bge_stop_locked(ifp, 0);
+       bge_stop_locked(ifp, false);
 
        bge_stop_fw(sc);
        bge_sig_pre_reset(sc, BGE_RESET_START);
@@ -5740,15 +5763,18 @@
        BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
        bge_writembx_flush(sc, BGE_MBX_IRQ0_LO, 0);
 
-       if ((error = bge_ifmedia_upd(ifp)) != 0)
-               goto out;
-
-       /* IFNET_LOCKED asserted above */
-       ifp->if_flags |= IFF_RUNNING;
-
-       callout_schedule(&sc->bge_timeout, hz);
-
-out:
+       mutex_enter(sc->sc_intr_lock);
+       if ((error = bge_ifmedia_upd(ifp)) == 0) {
+               sc->bge_stopping = false;
+               sc->bge_txrx_stopping = false;
+
+               /* IFNET_LOCKED asserted above */
+               ifp->if_flags |= IFF_RUNNING;
+
+               callout_schedule(&sc->bge_timeout, hz);
+       }
+       mutex_exit(sc->sc_intr_lock);
+
        sc->bge_if_flags = ifp->if_flags;
 
        return error;
@@ -5765,6 +5791,8 @@
        struct ifmedia * const ifm = &sc->bge_ifmedia;
        int rc;
 
+       KASSERT(mutex_owned(sc->sc_intr_lock));
+
        /* If this is a 1000baseX NIC, enable the TBI port. */



Home | Main Index | Thread Index | Old Index