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