- Fix promisc/multicast/broadcast parameters setting by introducing the

new ate_rxfilter function to set requested parameters. Use this function
  on parameters change rather than  reinitializing the chip.
This commit is contained in:
Stanislav Sedov 2009-05-10 08:54:10 +00:00
parent e1d2045e3f
commit 36ffa1b9de

View File

@ -76,6 +76,11 @@ __FBSDID("$FreeBSD$");
#define ATE_MAX_TX_BUFFERS 2 /* We have ping-pong tx buffers */
#define ATE_MAX_RX_BUFFERS 64
/*
* Driver-specific flags.
*/
#define ATE_FLAG_DETACHING 0x01
struct ate_softc
{
struct ifnet *ifp; /* ifnet pointer */
@ -100,6 +105,8 @@ struct ate_softc
eth_rx_desc_t *rx_descs;
int use_rmii;
struct ifmib_iso_8802_3 mibdata; /* stuff for network mgmt */
int flags;
int if_flags;
};
static inline uint32_t
@ -149,6 +156,7 @@ static int ate_ifmedia_upd(struct ifnet *ifp);
static void ate_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr);
static int ate_get_mac(struct ate_softc *sc, u_char *eaddr);
static void ate_set_mac(struct ate_softc *sc, u_char *eaddr);
static void ate_rxfilter(struct ate_softc *sc);
/*
* The AT91 family of products has the ethernet called EMAC. However,
@ -238,6 +246,7 @@ ate_attach(device_t dev)
ifp->if_linkmib = &sc->mibdata;
ifp->if_linkmiblen = sizeof(sc->mibdata);
sc->mibdata.dot3Compliance = DOT3COMPLIANCE_COLLS;
sc->if_flags = ifp->if_flags;
ether_ifattach(ifp, eaddr);
@ -763,13 +772,6 @@ ateinit_locked(void *xsc)
else
WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) & ~ETH_CFG_RMII);
/*
* Turn on the multicast hash, and write 0's to it.
*/
WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_MTI);
WR4(sc, ETH_HSH, 0);
WR4(sc, ETH_HSL, 0);
WR4(sc, ETH_CTL, RD4(sc, ETH_CTL) | ETH_CTL_TE | ETH_CTL_RE);
WR4(sc, ETH_IER, ETH_ISR_RCOM | ETH_ISR_TCOM | ETH_ISR_RBNA);
@ -780,6 +782,7 @@ ateinit_locked(void *xsc)
* swapping to do. Again, if we need it (which I don't think we do).
*/
ate_setmcast(sc);
ate_rxfilter(sc);
/* enable big packets */
WR4(sc, ETH_CFG, RD4(sc, ETH_CFG) | ETH_CFG_BIG);
@ -940,25 +943,63 @@ atestop(struct ate_softc *sc)
*/
}
static void
ate_rxfilter(struct ate_softc *sc)
{
struct ifnet *ifp;
uint32_t reg;
KASSERT(sc != NULL, ("[ate, %d]: sc is NULL!", __LINE__));
ATE_ASSERT_LOCKED(sc);
ifp = sc->ifp;
/*
* Wipe out old filter settings.
*/
reg = RD4(sc, ETH_CFG);
reg &= ~(ETH_CFG_CAF | ETH_CFG_MTI | ETH_CFG_UNI);
reg |= ETH_CFG_NBC;
/*
* Set new parameters.
*/
if ((ifp->if_flags & IFF_BROADCAST) != 0)
reg &= ~ETH_CFG_NBC;
if ((ifp->if_flags & IFF_PROMISC) != 0)
reg |= ETH_CFG_CAF;
if ((ifp->if_flags & IFF_ALLMULTI) != 0)
reg |= ETH_CFG_MTI;
WR4(sc, ETH_CFG, reg);
}
static int
ateioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct ate_softc *sc = ifp->if_softc;
struct mii_data *mii;
struct ifreq *ifr = (struct ifreq *)data;
int drv_flags, flags;
int mask, error = 0;
flags = ifp->if_flags;
drv_flags = ifp->if_drv_flags;
switch (cmd) {
case SIOCSIFFLAGS:
ATE_LOCK(sc);
if ((ifp->if_flags & IFF_UP) == 0 &&
ifp->if_drv_flags & IFF_DRV_RUNNING) {
if ((flags & IFF_UP) != 0) {
if ((drv_flags & IFF_DRV_RUNNING) != 0) {
if (((flags ^ sc->if_flags)
& (IFF_PROMISC | IFF_ALLMULTI)) != 0)
ate_rxfilter(sc);
} else {
if ((sc->flags & ATE_FLAG_DETACHING) == 0)
ateinit_locked(sc);
}
} else if ((drv_flags & IFF_DRV_RUNNING) != 0) {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
atestop(sc);
} else {
/* reinitialize card on any parameter change */
ateinit_locked(sc);
}
sc->if_flags = flags;
ATE_UNLOCK(sc);
break;