- 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:
parent
e1d2045e3f
commit
36ffa1b9de
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user