summaryrefslogtreecommitdiffstats
path: root/sys/arm/at91
diff options
context:
space:
mode:
authorstas <stas@FreeBSD.org>2009-05-12 21:14:36 +0000
committerstas <stas@FreeBSD.org>2009-05-12 21:14:36 +0000
commit85e0be635417bf8ffaf1f53db3dbcea5f7ef1eac (patch)
tree26dc6a19edf7d519e70def991e0a646f9b767a08 /sys/arm/at91
parent373616f83a50e69c8627a8da758c975fb6f3f8dc (diff)
downloadFreeBSD-src-85e0be635417bf8ffaf1f53db3dbcea5f7ef1eac.zip
FreeBSD-src-85e0be635417bf8ffaf1f53db3dbcea5f7ef1eac.tar.gz
- Eliminate extra register reads by using a variable to store
registers contents. - Use memory barriers to preserve the order of buffer space operations. This might be needed if we'll ever use this driver on architectures where ordering is not guaranteed.
Diffstat (limited to 'sys/arm/at91')
-rw-r--r--sys/arm/at91/if_ate.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/sys/arm/at91/if_ate.c b/sys/arm/at91/if_ate.c
index e062192..967f62e3 100644
--- a/sys/arm/at91/if_ate.c
+++ b/sys/arm/at91/if_ate.c
@@ -118,6 +118,13 @@ WR4(struct ate_softc *sc, bus_size_t off, uint32_t val)
bus_write_4(sc->mem_res, off, val);
}
+static inline void
+BARRIER(struct ate_softc *sc, bus_size_t off, bus_size_t len, int flags)
+{
+
+ bus_barrier(sc->mem_res, off, len, flags);
+}
+
#define ATE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
#define ATE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define ATE_LOCK_INIT(_sc) \
@@ -586,18 +593,19 @@ ate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
static void
ate_stat_update(struct ate_softc *sc, int active)
{
+ uint32_t reg;
+
/*
* The speed and full/half-duplex state needs to be reflected
* in the ETH_CFG register.
*/
- if (IFM_SUBTYPE(active) == IFM_10_T)
- WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_SPD);
- else
- WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_SPD);
+ reg = RD4(sc, ETH_CFG);
+ reg &= ~(ETH_CFG_SPD | ETH_CFG_FD);
+ if (IFM_SUBTYPE(active) != IFM_10_T)
+ reg |= ETH_CFG_SPD;
if (active & IFM_FDX)
- WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_FD);
- else
- WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_FD);
+ reg |= ETH_CFG_FD;
+ WR4(sc, ETH_CFG, reg);
}
static void
@@ -709,11 +717,10 @@ ate_intr(void *xsc)
{
struct ate_softc *sc = xsc;
struct ifnet *ifp = sc->ifp;
- int status;
- int i;
- void *bp;
struct mbuf *mb;
- uint32_t rx_stat;
+ void *bp;
+ uint32_t status, reg, rx_stat;
+ int i;
status = RD4(sc, ETH_ISR);
if (status == 0)
@@ -800,10 +807,11 @@ ate_intr(void *xsc)
ATE_UNLOCK(sc);
}
if (status & ETH_ISR_RBNA) {
- printf("RBNA workaround\n");
/* Workaround Errata #11 */
- WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) &~ ETH_CTL_RE);
- WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_RE);
+ reg = RD4(sc, ETH_CTL);
+ WR4(sc, ETH_CTL, reg & ~ETH_CTL_RE);
+ BARRIER(sc, ETH_CTL, 4, BUS_SPACE_BARRIER_WRITE);
+ WR4(sc, ETH_CTL, reg | ETH_CTL_RE);
}
}
@@ -816,6 +824,7 @@ ateinit_locked(void *xsc)
struct ate_softc *sc = xsc;
struct ifnet *ifp = sc->ifp;
struct mii_data *mii;
+ uint32_t reg;
ATE_ASSERT_LOCKED(sc);
@@ -834,10 +843,12 @@ ateinit_locked(void *xsc)
* to this chip. Select the right one based on a compile-time
* option.
*/
+ reg = RD4(sc, ETH_CFG);
if (sc->use_rmii)
- WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_RMII);
+ reg |= ETH_CFG_RMII;
else
- WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_RMII);
+ reg &= ~ETH_CFG_RMII;
+ WR4(sc, ETH_CFG, reg);
ate_rxfilter(sc);
@@ -926,6 +937,7 @@ atestart_locked(struct ifnet *ifp)
* tell the hardware to xmit the packet.
*/
WR4(sc, ETH_TAR, segs[0].ds_addr);
+ BARRIER(sc, ETH_TAR, 8, BUS_SPACE_BARRIER_WRITE);
WR4(sc, ETH_TCR, segs[0].ds_len);
/*
OpenPOWER on IntegriCloud