Locking cleanups to remove the need for a recursive mutex

o Instead of locking and unlocking all over the place, use
	  lock assertions to make certain that the bfe lock is held
	  where necessary.
	o Create locked and unlocked versions of bfe_init and bfe_start. These
	  functions can be called from outside the module and by functions
	  within the bfe module. The calls from outside the module don't
	  hold the bfe lock so the unlocked versions called by these functions
	  simple obtain the bfe lock and call the locked version.

- Fix a typo (scp) in the locking macros that only worked because in all the
  instances in which it was called the softc pointer happened to be named 'sc'.

- Mark the interrupt MPSAFE

Tested by: matusita, Dario Freni <saturnero@gufi.org>
Silence from: -net, wpaul
This commit is contained in:
Mike Makonnen 2004-10-23 08:33:10 +00:00
parent ec6f2b9b88
commit f16b4811d2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=136804
2 changed files with 49 additions and 60 deletions

View File

@ -94,8 +94,10 @@ static int bfe_detach (device_t);
static void bfe_release_resources (struct bfe_softc *);
static void bfe_intr (void *);
static void bfe_start (struct ifnet *);
static void bfe_start_locked (struct ifnet *);
static int bfe_ioctl (struct ifnet *, u_long, caddr_t);
static void bfe_init (void *);
static void bfe_init_locked (void *);
static void bfe_stop (struct bfe_softc *);
static void bfe_watchdog (struct ifnet *);
static void bfe_shutdown (device_t);
@ -329,7 +331,7 @@ bfe_attach(device_t dev)
sc = device_get_softc(dev);
mtx_init(&sc->bfe_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
MTX_DEF);
unit = device_get_unit(dev);
sc->bfe_dev = dev;
@ -411,7 +413,9 @@ bfe_attach(device_t dev)
bfe_get_config(sc);
/* Reset the chip and turn on the PHY */
BFE_LOCK(sc);
bfe_chip_reset(sc);
BFE_UNLOCK(sc);
if (mii_phy_probe(dev, &sc->bfe_miibus,
bfe_ifmedia_upd, bfe_ifmedia_sts)) {
@ -433,7 +437,7 @@ bfe_attach(device_t dev)
/*
* Hook interrupt last to avoid having to lock softc
*/
error = bus_setup_intr(dev, sc->bfe_irq, INTR_TYPE_NET,
error = bus_setup_intr(dev, sc->bfe_irq, INTR_TYPE_NET | INTR_MPSAFE,
bfe_intr, sc, &sc->bfe_intrhand);
if (error) {
@ -456,7 +460,7 @@ bfe_detach(device_t dev)
sc = device_get_softc(dev);
KASSERT(mtx_initialized(&sc->bfe_mtx), ("bfe mutex not initialized"));
BFE_LOCK(scp);
BFE_LOCK(sc);
ifp = &sc->arpcom.ac_if;
@ -674,15 +678,13 @@ bfe_clear_stats(struct bfe_softc *sc)
{
u_long reg;
BFE_LOCK(sc);
BFE_LOCK_ASSERT(sc);
CSR_WRITE_4(sc, BFE_MIB_CTRL, BFE_MIB_CLR_ON_READ);
for (reg = BFE_TX_GOOD_O; reg <= BFE_TX_PAUSE; reg += 4)
CSR_READ_4(sc, reg);
for (reg = BFE_RX_GOOD_O; reg <= BFE_RX_NPAUSE; reg += 4)
CSR_READ_4(sc, reg);
BFE_UNLOCK(sc);
}
static int
@ -690,23 +692,20 @@ bfe_resetphy(struct bfe_softc *sc)
{
u_int32_t val;
BFE_LOCK(sc);
bfe_writephy(sc, 0, BMCR_RESET);
DELAY(100);
bfe_readphy(sc, 0, &val);
if (val & BMCR_RESET) {
printf("bfe%d: PHY Reset would not complete.\n", sc->bfe_unit);
BFE_UNLOCK(sc);
return (ENXIO);
}
BFE_UNLOCK(sc);
return (0);
}
static void
bfe_chip_halt(struct bfe_softc *sc)
{
BFE_LOCK(sc);
BFE_LOCK_ASSERT(sc);
/* disable interrupts - not that it actually does..*/
CSR_WRITE_4(sc, BFE_IMASK, 0);
CSR_READ_4(sc, BFE_IMASK);
@ -717,8 +716,6 @@ bfe_chip_halt(struct bfe_softc *sc)
CSR_WRITE_4(sc, BFE_DMARX_CTRL, 0);
CSR_WRITE_4(sc, BFE_DMATX_CTRL, 0);
DELAY(10);
BFE_UNLOCK(sc);
}
static void
@ -726,7 +723,7 @@ bfe_chip_reset(struct bfe_softc *sc)
{
u_int32_t val;
BFE_LOCK(sc);
BFE_LOCK_ASSERT(sc);
/* Set the interrupt vector for the enet core */
bfe_pci_setup(sc, BFE_INTVEC_ENET0);
@ -804,8 +801,6 @@ bfe_chip_reset(struct bfe_softc *sc)
bfe_resetphy(sc);
bfe_setupphy(sc);
BFE_UNLOCK(sc);
}
static void
@ -1032,7 +1027,6 @@ bfe_readphy(struct bfe_softc *sc, u_int32_t reg, u_int32_t *val)
{
int err;
BFE_LOCK(sc);
/* Clear MII ISR */
CSR_WRITE_4(sc, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII);
CSR_WRITE_4(sc, BFE_MDIO_DATA, (BFE_MDIO_SB_START |
@ -1043,7 +1037,6 @@ bfe_readphy(struct bfe_softc *sc, u_int32_t reg, u_int32_t *val)
err = bfe_wait_bit(sc, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII, 100, 0);
*val = CSR_READ_4(sc, BFE_MDIO_DATA) & BFE_MDIO_DATA_DATA;
BFE_UNLOCK(sc);
return (err);
}
@ -1052,7 +1045,6 @@ bfe_writephy(struct bfe_softc *sc, u_int32_t reg, u_int32_t val)
{
int status;
BFE_LOCK(sc);
CSR_WRITE_4(sc, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII);
CSR_WRITE_4(sc, BFE_MDIO_DATA, (BFE_MDIO_SB_START |
(BFE_MDIO_OP_WRITE << BFE_MDIO_OP_SHIFT) |
@ -1061,7 +1053,6 @@ bfe_writephy(struct bfe_softc *sc, u_int32_t reg, u_int32_t val)
(BFE_MDIO_TA_VALID << BFE_MDIO_TA_SHIFT) |
(val & BFE_MDIO_DATA_DATA)));
status = bfe_wait_bit(sc, BFE_EMAC_ISTAT, BFE_EMAC_INT_MII, 100, 0);
BFE_UNLOCK(sc);
return (status);
}
@ -1074,7 +1065,6 @@ static int
bfe_setupphy(struct bfe_softc *sc)
{
u_int32_t val;
BFE_LOCK(sc);
/* Enable activity LED */
bfe_readphy(sc, 26, &val);
@ -1085,7 +1075,6 @@ bfe_setupphy(struct bfe_softc *sc)
bfe_readphy(sc, 27, &val);
bfe_writephy(sc, 27, val | (1 << 6));
BFE_UNLOCK(sc);
return (0);
}
@ -1111,7 +1100,7 @@ bfe_txeof(struct bfe_softc *sc)
struct ifnet *ifp;
int i, chipidx;
BFE_LOCK(sc);
BFE_LOCK_ASSERT(sc);
ifp = &sc->arpcom.ac_if;
@ -1141,8 +1130,6 @@ bfe_txeof(struct bfe_softc *sc)
ifp->if_timer = 0;
else
ifp->if_timer = 5;
BFE_UNLOCK(sc);
}
/* Pass a received packet up the stack */
@ -1156,7 +1143,7 @@ bfe_rxeof(struct bfe_softc *sc)
int cons;
u_int32_t status, current, len, flags;
BFE_LOCK(sc);
BFE_LOCK_ASSERT(sc);
cons = sc->bfe_rx_cons;
status = CSR_READ_4(sc, BFE_DMARX_STAT);
current = (status & BFE_STAT_CDMASK) / sizeof(struct bfe_desc);
@ -1206,7 +1193,6 @@ bfe_rxeof(struct bfe_softc *sc)
BFE_INC(cons, BFE_RX_LIST_CNT);
}
sc->bfe_rx_cons = cons;
BFE_UNLOCK(sc);
}
static void
@ -1248,7 +1234,7 @@ bfe_intr(void *xsc)
ifp->if_ierrors++;
ifp->if_flags &= ~IFF_RUNNING;
bfe_init(sc);
bfe_init_locked(sc);
}
/* A packet was received */
@ -1261,7 +1247,7 @@ bfe_intr(void *xsc)
/* We have packets pending, fire them out */
if (ifp->if_flags & IFF_RUNNING && !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
bfe_start(ifp);
bfe_start_locked(ifp);
BFE_UNLOCK(sc);
}
@ -1350,10 +1336,21 @@ bfe_encap(struct bfe_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
}
/*
* Set up to transmit a packet
* Set up to transmit a packet.
*/
static void
bfe_start(struct ifnet *ifp)
{
BFE_LOCK((struct bfe_softc *)ifp->if_softc);
bfe_start_locked(ifp);
BFE_UNLOCK((struct bfe_softc *)ifp->if_softc);
}
/*
* Set up to transmit a packet. The softc is already locked.
*/
static void
bfe_start_locked(struct ifnet *ifp)
{
struct bfe_softc *sc;
struct mbuf *m_head = NULL;
@ -1362,21 +1359,17 @@ bfe_start(struct ifnet *ifp)
sc = ifp->if_softc;
idx = sc->bfe_tx_prod;
BFE_LOCK(sc);
BFE_LOCK_ASSERT(sc);
/*
* Not much point trying to send if the link is down
* or we have nothing to send.
*/
if (!sc->bfe_link && ifp->if_snd.ifq_len < 10) {
BFE_UNLOCK(sc);
if (!sc->bfe_link && ifp->if_snd.ifq_len < 10)
return;
}
if (ifp->if_flags & IFF_OACTIVE) {
BFE_UNLOCK(sc);
if (ifp->if_flags & IFF_OACTIVE)
return;
}
while(sc->bfe_tx_ring[idx].bfe_mbuf == NULL) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
@ -1413,22 +1406,26 @@ bfe_start(struct ifnet *ifp)
*/
ifp->if_timer = 5;
}
BFE_UNLOCK(sc);
}
static void
bfe_init(void *xsc)
{
BFE_LOCK((struct bfe_softc *)xsc);
bfe_init_locked(xsc);
BFE_UNLOCK((struct bfe_softc *)xsc);
}
static void
bfe_init_locked(void *xsc)
{
struct bfe_softc *sc = (struct bfe_softc*)xsc;
struct ifnet *ifp = &sc->arpcom.ac_if;
BFE_LOCK(sc);
BFE_LOCK_ASSERT(sc);
if (ifp->if_flags & IFF_RUNNING) {
BFE_UNLOCK(sc);
if (ifp->if_flags & IFF_RUNNING)
return;
}
bfe_stop(sc);
bfe_chip_reset(sc);
@ -1452,7 +1449,6 @@ bfe_init(void *xsc)
ifp->if_flags &= ~IFF_OACTIVE;
sc->bfe_stat_ch = timeout(bfe_tick, sc, hz);
BFE_UNLOCK(sc);
}
/*
@ -1466,8 +1462,6 @@ bfe_ifmedia_upd(struct ifnet *ifp)
sc = ifp->if_softc;
BFE_LOCK(sc);
mii = device_get_softc(sc->bfe_miibus);
sc->bfe_link = 0;
if (mii->mii_instance) {
@ -1478,7 +1472,6 @@ bfe_ifmedia_upd(struct ifnet *ifp)
}
mii_mediachg(mii);
BFE_UNLOCK(sc);
return (0);
}
@ -1491,14 +1484,10 @@ bfe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
struct bfe_softc *sc = ifp->if_softc;
struct mii_data *mii;
BFE_LOCK(sc);
mii = device_get_softc(sc->bfe_miibus);
mii_pollstat(mii);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
BFE_UNLOCK(sc);
}
static int
@ -1509,22 +1498,24 @@ bfe_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct mii_data *mii;
int error = 0;
BFE_LOCK(sc);
switch(command) {
case SIOCSIFFLAGS:
BFE_LOCK(sc);
if(ifp->if_flags & IFF_UP)
if(ifp->if_flags & IFF_RUNNING)
bfe_set_rx_mode(sc);
else
bfe_init(sc);
bfe_init_locked(sc);
else if(ifp->if_flags & IFF_RUNNING)
bfe_stop(sc);
BFE_UNLOCK(sc);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
BFE_LOCK(sc);
if(ifp->if_flags & IFF_RUNNING)
bfe_set_rx_mode(sc);
BFE_UNLOCK(sc);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
@ -1537,7 +1528,6 @@ bfe_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
break;
}
BFE_UNLOCK(sc);
return (error);
}
@ -1553,7 +1543,7 @@ bfe_watchdog(struct ifnet *ifp)
printf("bfe%d: watchdog timeout -- resetting\n", sc->bfe_unit);
ifp->if_flags &= ~IFF_RUNNING;
bfe_init(sc);
bfe_init_locked(sc);
ifp->if_oerrors++;
@ -1598,7 +1588,7 @@ bfe_stop(struct bfe_softc *sc)
{
struct ifnet *ifp;
BFE_LOCK(sc);
BFE_LOCK_ASSERT(sc);
untimeout(bfe_tick, sc, sc->bfe_stat_ch);
@ -1609,6 +1599,4 @@ bfe_stop(struct bfe_softc *sc)
bfe_rx_ring_free(sc);
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
BFE_UNLOCK(sc);
}

View File

@ -445,8 +445,9 @@
#define BFE_AND(sc, name, val) \
CSR_WRITE_4(sc, name, CSR_READ_4(sc, name) & val)
#define BFE_LOCK(scp) mtx_lock(&sc->bfe_mtx)
#define BFE_UNLOCK(scp) mtx_unlock(&sc->bfe_mtx)
#define BFE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->bfe_mtx, MA_OWNED)
#define BFE_LOCK(_sc) mtx_lock(&(_sc)->bfe_mtx)
#define BFE_UNLOCK(_sc) mtx_unlock(&(_sc)->bfe_mtx)
#define BFE_INC(x, y) (x) = ((x) == ((y)-1)) ? 0 : (x)+1