aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ste/if_ste.c
diff options
context:
space:
mode:
authorPyun YongHyeon <yongari@FreeBSD.org>2009-12-23 18:24:22 +0000
committerPyun YongHyeon <yongari@FreeBSD.org>2009-12-23 18:24:22 +0000
commit931ec15a83e1d6a9517b35e5f3ad52f1114dbce6 (patch)
tree85fc42d6633d36e4ac5dc7ad7adfba58cea5c63d /sys/dev/ste/if_ste.c
parent38c52cfdc1780e751b194731e98698a9fd0bf9c7 (diff)
downloadsrc-931ec15a83e1d6a9517b35e5f3ad52f1114dbce6.tar.gz
src-931ec15a83e1d6a9517b35e5f3ad52f1114dbce6.zip
Overhaul RX filter programming.
o Let RX filter handler program promiscuous/multicast filter as well as broadcasting. o Remove unnecessary register access. o Simplify ioctl handler and have set_rxfilter to handle IFF_PROMISC and IFF_ALLMULTI change instead of directly programming the controller. o Removed unnecessary error variable reinitialization in ioctl handler. o Add IFF_DRV_RUNNING check before programming multicast filter. o Configure maximum allowed frame length before enabling MAC. Datasheet didn't say the exact ordering of programming sequence but it looks more natural to set maximum allowed frame length first prior to enabling controller.
Notes
Notes: svn path=/head/; revision=200906
Diffstat (limited to 'sys/dev/ste/if_ste.c')
-rw-r--r--sys/dev/ste/if_ste.c100
1 files changed, 38 insertions, 62 deletions
diff --git a/sys/dev/ste/if_ste.c b/sys/dev/ste/if_ste.c
index 7249f8427a94..b2cb4d5d4b75 100644
--- a/sys/dev/ste/if_ste.c
+++ b/sys/dev/ste/if_ste.c
@@ -123,7 +123,7 @@ static int ste_read_eeprom(struct ste_softc *, caddr_t, int, int, int);
static void ste_reset(struct ste_softc *);
static void ste_restart_tx(struct ste_softc *);
static int ste_rxeof(struct ste_softc *, int);
-static void ste_setmulti(struct ste_softc *);
+static void ste_rxfilter(struct ste_softc *);
static void ste_start(struct ifnet *);
static void ste_start_locked(struct ifnet *);
static void ste_stats_update(struct ste_softc *);
@@ -563,27 +563,33 @@ ste_read_eeprom(struct ste_softc *sc, caddr_t dest, int off, int cnt, int swap)
}
static void
-ste_setmulti(struct ste_softc *sc)
+ste_rxfilter(struct ste_softc *sc)
{
struct ifnet *ifp;
struct ifmultiaddr *ifma;
uint32_t hashes[2] = { 0, 0 };
+ uint8_t rxcfg;
int h;
- ifp = sc->ste_ifp;
- if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
- STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_ALLMULTI);
- STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_MULTIHASH);
- return;
- }
-
- /* first, zot all the existing hash bits */
- CSR_WRITE_2(sc, STE_MAR0, 0);
- CSR_WRITE_2(sc, STE_MAR1, 0);
- CSR_WRITE_2(sc, STE_MAR2, 0);
- CSR_WRITE_2(sc, STE_MAR3, 0);
+ STE_LOCK_ASSERT(sc);
- /* now program new ones */
+ ifp = sc->ste_ifp;
+ rxcfg = CSR_READ_1(sc, STE_RX_MODE);
+ rxcfg |= STE_RXMODE_UNICAST;
+ rxcfg &= ~(STE_RXMODE_ALLMULTI | STE_RXMODE_MULTIHASH |
+ STE_RXMODE_BROADCAST | STE_RXMODE_PROMISC);
+ if (ifp->if_flags & IFF_BROADCAST)
+ rxcfg |= STE_RXMODE_BROADCAST;
+ if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
+ if ((ifp->if_flags & IFF_ALLMULTI) != 0)
+ rxcfg |= STE_RXMODE_ALLMULTI;
+ if ((ifp->if_flags & IFF_PROMISC) != 0)
+ rxcfg |= STE_RXMODE_PROMISC;
+ goto chipit;
+ }
+
+ rxcfg |= STE_RXMODE_MULTIHASH;
+ /* Now program new ones. */
if_maddr_rlock(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
@@ -597,12 +603,13 @@ ste_setmulti(struct ste_softc *sc)
}
if_maddr_runlock(ifp);
+chipit:
CSR_WRITE_2(sc, STE_MAR0, hashes[0] & 0xFFFF);
CSR_WRITE_2(sc, STE_MAR1, (hashes[0] >> 16) & 0xFFFF);
CSR_WRITE_2(sc, STE_MAR2, hashes[1] & 0xFFFF);
CSR_WRITE_2(sc, STE_MAR3, (hashes[1] >> 16) & 0xFFFF);
- STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_ALLMULTI);
- STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_MULTIHASH);
+ CSR_WRITE_1(sc, STE_RX_MODE, rxcfg);
+ CSR_READ_1(sc, STE_RX_MODE);
}
#ifdef DEVICE_POLLING
@@ -1590,24 +1597,11 @@ ste_init_locked(struct ste_softc *sc)
/* Set the TX reclaim threshold. */
CSR_WRITE_1(sc, STE_TX_RECLAIM_THRESH, (STE_PACKET_SIZE >> 4));
- /* Set up the RX filter. */
- CSR_WRITE_1(sc, STE_RX_MODE, STE_RXMODE_UNICAST);
-
- /* If we want promiscuous mode, set the allframes bit. */
- if (ifp->if_flags & IFF_PROMISC) {
- STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_PROMISC);
- } else {
- STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_PROMISC);
- }
-
- /* Set capture broadcast bit to accept broadcast frames. */
- if (ifp->if_flags & IFF_BROADCAST) {
- STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_BROADCAST);
- } else {
- STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_BROADCAST);
- }
+ /* Accept VLAN length packets */
+ CSR_WRITE_2(sc, STE_MAX_FRAMELEN, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
- ste_setmulti(sc);
+ /* Set up the RX filter. */
+ ste_rxfilter(sc);
/* Load the address of the RX list. */
STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL);
@@ -1647,9 +1641,6 @@ ste_init_locked(struct ste_softc *sc)
/* Enable interrupts. */
CSR_WRITE_2(sc, STE_IMR, STE_INTRS);
- /* Accept VLAN length packets */
- CSR_WRITE_2(sc, STE_MAX_FRAMELEN, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
-
ste_ifmedia_upd_locked(ifp);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -1792,39 +1783,24 @@ ste_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
switch (command) {
case SIOCSIFFLAGS:
STE_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- ifp->if_flags & IFF_PROMISC &&
- !(sc->ste_if_flags & IFF_PROMISC)) {
- STE_SETBIT1(sc, STE_RX_MODE,
- STE_RXMODE_PROMISC);
- } else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- !(ifp->if_flags & IFF_PROMISC) &&
- sc->ste_if_flags & IFF_PROMISC) {
- STE_CLRBIT1(sc, STE_RX_MODE,
- STE_RXMODE_PROMISC);
- }
- if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- (ifp->if_flags ^ sc->ste_if_flags) & IFF_ALLMULTI)
- ste_setmulti(sc);
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- sc->ste_tx_thresh = STE_TXSTART_THRESH;
+ if ((ifp->if_flags & IFF_UP) != 0) {
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 &&
+ ((ifp->if_flags ^ sc->ste_if_flags) &
+ (IFF_PROMISC | IFF_ALLMULTI)) != 0)
+ ste_rxfilter(sc);
+ else
ste_init_locked(sc);
- }
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ste_stop(sc);
- }
+ } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ ste_stop(sc);
sc->ste_if_flags = ifp->if_flags;
STE_UNLOCK(sc);
- error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
STE_LOCK(sc);
- ste_setmulti(sc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ ste_rxfilter(sc);
STE_UNLOCK(sc);
- error = 0;
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA: