summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/bfe/if_bfe.c104
-rw-r--r--sys/dev/bfe/if_bfereg.h5
2 files changed, 49 insertions, 60 deletions
diff --git a/sys/dev/bfe/if_bfe.c b/sys/dev/bfe/if_bfe.c
index 805cd26..4d9a462 100644
--- a/sys/dev/bfe/if_bfe.c
+++ b/sys/dev/bfe/if_bfe.c
@@ -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,11 +1336,22 @@ 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;
int idx, queued = 0;
@@ -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);
}
diff --git a/sys/dev/bfe/if_bfereg.h b/sys/dev/bfe/if_bfereg.h
index 10b26db..383154f 100644
--- a/sys/dev/bfe/if_bfereg.h
+++ b/sys/dev/bfe/if_bfereg.h
@@ -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
OpenPOWER on IntegriCloud