Author: marius
Date: Tue Jun 28 16:16:43 2011
New Revision: 223648
URL: http://svn.freebsd.org/changeset/base/223648
Log:
- In gem_reset_rx() also reset the RX MAC which is necessary in order to
get it out of a stuck condition that can be caused by GEM_MAC_RX_OVERFLOW.
- In gem_reset_rxdma() call gem_setladrf() in order to reprogram the RX
filter and restore the previous content of GEM_MAC_RX_CONFIG. While at it
consistently use the newly introduced sc_mac_rxcfg throughout the driver
instead of reading the its old content.
- Increment if_iqdrops instead of if_ierrors in case of RX buffer allocation
failure.
- According to the GEM datasheet the RX MAC should also be disabled in
gem_setladrf() before changing its configuration.
- Add error messages to gem_disable_{r,t}x() and take advantage of these
throughout the driver instead of duplicating their functionality all over
the place.
In joint forces with: yongari
Modified:
head/sys/dev/gem/if_gem.c
head/sys/dev/gem/if_gemvar.h
Modified: head/sys/dev/gem/if_gem.c
==============================================================================
--- head/sys/dev/gem/if_gem.c Tue Jun 28 15:19:45 2011 (r223647)
+++ head/sys/dev/gem/if_gem.c Tue Jun 28 16:16:43 2011 (r223648)
@@ -121,7 +121,7 @@ static void gem_rint_timeout(void *arg);
#endif
static inline void gem_rxcksum(struct mbuf *m, uint64_t flags);
static void gem_rxdrain(struct gem_softc *sc);
-static void gem_setladrf(struct gem_softc *sc);
+static void gem_setladrf(struct gem_softc *sc, u_int enable);
static void gem_start(struct ifnet *ifp);
static void gem_start_locked(struct ifnet *ifp);
static void gem_stop(struct ifnet *ifp, int disable);
@@ -705,7 +705,7 @@ gem_reset_rx(struct gem_softc *sc)
* Resetting while DMA is in progress can cause a bus hang, so we
* disable DMA first.
*/
- gem_disable_rx(sc);
+ (void)gem_disable_rx(sc);
GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 0);
GEM_BANK1_BARRIER(sc, GEM_RX_CONFIG, 4,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
@@ -715,7 +715,7 @@ gem_reset_rx(struct gem_softc *sc)
/* Wait 5ms extra. */
DELAY(5000);
- /* Finally, reset the ERX. */
+ /* Reset the ERX. */
GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX);
GEM_BANK2_BARRIER(sc, GEM_RESET, 4,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
@@ -724,6 +724,16 @@ gem_reset_rx(struct gem_softc *sc)
device_printf(sc->sc_dev, "cannot reset receiver\n");
return (1);
}
+
+ /* Finally, reset RX MAC. */
+ GEM_BANK1_WRITE_4(sc, GEM_MAC_RXRESET, 1);
+ GEM_BANK1_BARRIER(sc, GEM_MAC_RXRESET, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+ if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RXRESET, 1, 0)) {
+ device_printf(sc->sc_dev, "cannot reset RX MAC\n");
+ return (1);
+ }
+
return (0);
}
@@ -766,12 +776,17 @@ gem_reset_rxdma(struct gem_softc *sc)
GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH,
(3 * sc->sc_rxfifosize / 256) |
((sc->sc_rxfifosize / 256)<< 12));
+ /*
+ * Clear the RX filter and reprogram it. This will also set the
+ * current RX MAC configuration.
+ */
+ gem_setladrf(sc, 0);
GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG,
GEM_BANK1_READ_4(sc, GEM_RX_CONFIG) | GEM_RX_CONFIG_RXDMA_EN);
GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK,
GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT);
GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG,
- GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG) | GEM_MAC_RX_ENABLE);
+ sc->sc_mac_rxcfg | GEM_MAC_RX_ENABLE);
}
static int
@@ -782,7 +797,7 @@ gem_reset_tx(struct gem_softc *sc)
* Resetting while DMA is in progress can cause a bus hang, so we
* disable DMA first.
*/
- gem_disable_tx(sc);
+ (void)gem_disable_tx(sc);
GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, 0);
GEM_BANK1_BARRIER(sc, GEM_TX_CONFIG, 4,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
@@ -812,8 +827,10 @@ gem_disable_rx(struct gem_softc *sc)
GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG)& ~GEM_MAC_RX_ENABLE);
GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- return (GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE,
- 0));
+ if (GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0))
+ return (1);
+ device_printf(sc->sc_dev, "cannot disable RX MAC\n");
+ return (0);
}
static int
@@ -824,8 +841,10 @@ gem_disable_tx(struct gem_softc *sc)
GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG)& ~GEM_MAC_TX_ENABLE);
GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- return (GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE,
- 0));
+ if (GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0))
+ return (1);
+ device_printf(sc->sc_dev, "cannot disable TX MAC\n");
+ return (0);
}
static int
@@ -960,7 +979,7 @@ gem_init_locked(struct gem_softc *sc)
gem_init_regs(sc);
/* step 5. RX MAC registers& counters */
- gem_setladrf(sc);
+ gem_setladrf(sc, 0);
/* step 6& 7. Program Descriptor Ring Base Addresses. */
/* NOTE: we use only 32-bit DMA addresses here. */
@@ -1050,21 +1069,14 @@ gem_init_locked(struct gem_softc *sc)
/* step 12. RX_MAC Configuration Register */
v = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG);
v |= GEM_MAC_RX_ENABLE | GEM_MAC_RX_STRIP_CRC;
- GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 0);
- GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0))
- device_printf(sc->sc_dev, "cannot configure RX MAC\n");
+ (void)gem_disable_rx(sc);
+ sc->sc_mac_rxcfg = v& ~GEM_MAC_RX_ENABLE;
GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v);
/* step 13. TX_MAC Configuration Register */
v = GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG);
v |= GEM_MAC_TX_ENABLE;
- GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 0);
- GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0))
- device_printf(sc->sc_dev, "cannot configure TX MAC\n");
+ (void)gem_disable_tx(sc);
GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, v);
/* step 14. Issue Transmit Pending command. */
@@ -1588,7 +1600,7 @@ gem_rint(struct gem_softc *sc)
* the buffer that's already attached to this descriptor.
*/
if (gem_add_rxbuf(sc, sc->sc_rxptr) != 0) {
- ifp->if_ierrors++;
+ ifp->if_iqdrops++;
GEM_INIT_RXDESC(sc, sc->sc_rxptr);
m = NULL;
}
@@ -2028,8 +2040,8 @@ gem_mii_statchg(device_t dev)
* the GEM Gigabit Ethernet ASIC Specification.
*/
- rxcfg = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG);
- rxcfg&= ~(GEM_MAC_RX_CARR_EXTEND | GEM_MAC_RX_ENABLE);
+ rxcfg = sc->sc_mac_rxcfg;
+ rxcfg&= ~GEM_MAC_RX_CARR_EXTEND;
txcfg = GEM_MAC_TX_ENA_IPG0 | GEM_MAC_TX_NGU | GEM_MAC_TX_NGU_LIMIT;
if ((IFM_OPTIONS(sc->sc_mii->mii_media_active)& IFM_FDX) != 0)
txcfg |= GEM_MAC_TX_IGN_CARRIER | GEM_MAC_TX_IGN_COLLIS;
@@ -2037,17 +2049,9 @@ gem_mii_statchg(device_t dev)
rxcfg |= GEM_MAC_RX_CARR_EXTEND;
txcfg |= GEM_MAC_TX_CARR_EXTEND;
}
- GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 0);
- GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0))
- device_printf(sc->sc_dev, "cannot disable TX MAC\n");
+ (void)gem_disable_tx(sc);
GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, txcfg);
- GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 0);
- GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4,
- BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0))
- device_printf(sc->sc_dev, "cannot disable RX MAC\n");
+ (void)gem_disable_rx(sc);
GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, rxcfg);
v = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_CONFIG)&
@@ -2092,6 +2096,7 @@ gem_mii_statchg(device_t dev)
v |= GEM_MAC_XIF_FDPLX_LED;
GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, v);
+ sc->sc_mac_rxcfg = rxcfg;
if ((sc->sc_ifp->if_drv_flags& IFF_DRV_RUNNING) != 0&&
(sc->sc_flags& GEM_LINK) != 0) {
GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG,
@@ -2147,7 +2152,7 @@ gem_ioctl(struct ifnet *ifp, u_long cmd,
if ((ifp->if_drv_flags& IFF_DRV_RUNNING) != 0&&
((ifp->if_flags ^ sc->sc_ifflags)&
(IFF_ALLMULTI | IFF_PROMISC)) != 0)
- gem_setladrf(sc);
+ gem_setladrf(sc, 1);
else
gem_init_locked(sc);
} else if ((ifp->if_drv_flags& IFF_DRV_RUNNING) != 0)
@@ -2164,7 +2169,8 @@ gem_ioctl(struct ifnet *ifp, u_long cmd,
case SIOCADDMULTI:
case SIOCDELMULTI:
GEM_LOCK(sc);
- gem_setladrf(sc);
+ if ((ifp->if_drv_flags& IFF_DRV_RUNNING) != 0)
+ gem_setladrf(sc, 1);
GEM_UNLOCK(sc);
break;
case SIOCGIFMEDIA:
@@ -2189,7 +2195,7 @@ gem_ioctl(struct ifnet *ifp, u_long cmd,
}
static void
-gem_setladrf(struct gem_softc *sc)
+gem_setladrf(struct gem_softc *sc, u_int enable)
{
struct ifnet *ifp = sc->sc_ifp;
struct ifmultiaddr *inm;
@@ -2199,24 +2205,20 @@ gem_setladrf(struct gem_softc *sc)
GEM_LOCK_ASSERT(sc, MA_OWNED);
- /* Get the current RX configuration. */
- v = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG);
-
/*
- * Turn off promiscuous mode, promiscuous group mode (all multicast),
- * and hash filter. Depending on the case, the right bit will be
- * enabled.
+ * Turn off the RX MAC and the hash filter as required by the Sun GEM
+ * programming restrictions.
*/
- v&= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_HASH_FILTER |
- GEM_MAC_RX_PROMISC_GRP);
-
+ v = sc->sc_mac_rxcfg& GEM_MAC_RX_HASH_FILTER;
GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v);
GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4,
BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
- if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER,
- 0))
- device_printf(sc->sc_dev, "cannot disable RX hash filter\n");
+ if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER |
+ GEM_MAC_RX_ENABLE, 0))
+ device_printf(sc->sc_dev,
+ "cannot disable RX MAC or hash filter\n");
+ v&= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_PROMISC_GRP);
if ((ifp->if_flags& IFF_PROMISC) != 0) {
v |= GEM_MAC_RX_PROMISCUOUS;
goto chipit;
@@ -2262,5 +2264,8 @@ gem_setladrf(struct gem_softc *sc)
hash[i]);
chipit:
+ sc->sc_mac_rxcfg = v;
+ if (enable)
+ v |= GEM_MAC_RX_ENABLE;
GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v);
}
Modified: head/sys/dev/gem/if_gemvar.h
==============================================================================
--- head/sys/dev/gem/if_gemvar.h Tue Jun 28 15:19:45 2011
(r223647)
+++ head/sys/dev/gem/if_gemvar.h Tue Jun 28 16:16:43 2011
(r223648)
@@ -173,6 +173,8 @@ struct gem_softc {
u_int sc_rxptr; /* next ready RX descriptor/state */
u_int sc_rxfifosize; /* RX FIFO size (bytes) */
+ uint32_t sc_mac_rxcfg; /* RX MAC conf. % GEM_MAC_RX_ENABLE */
+
int sc_ifflags;
u_long sc_csum_features;
};