svn commit: r200906 - head/sys/dev/ste
Pyun YongHyeon
yongari at FreeBSD.org
Wed Dec 23 18:24:22 UTC 2009
Author: yongari
Date: Wed Dec 23 18:24:22 2009
New Revision: 200906
URL: http://svn.freebsd.org/changeset/base/200906
Log:
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.
Modified:
head/sys/dev/ste/if_ste.c
Modified: head/sys/dev/ste/if_ste.c
==============================================================================
--- head/sys/dev/ste/if_ste.c Wed Dec 23 17:54:24 2009 (r200905)
+++ head/sys/dev/ste/if_ste.c Wed Dec 23 18:24:22 2009 (r200906)
@@ -123,7 +123,7 @@ static int ste_read_eeprom(struct ste_so
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, ca
}
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;
+ STE_LOCK_ASSERT(sc);
+
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;
+ 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;
}
- /* 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);
-
- /* now program new ones */
+ 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 comm
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:
More information about the svn-src-all
mailing list