On Tuesday 02 June 2009 20:44:25 Brad wrote: > Please test the following diff with any rl(4) adapters using > any apps making use of multicast (IPv6, OSPF, CARP, etc.) and/or > promiscuous mode of operation. > > Please provide a dmesg.
Still looking for feedback. > Index: rtl81x9.c > =================================================================== > RCS file: /cvs/src/sys/dev/ic/rtl81x9.c,v > retrieving revision 1.63 > diff -u -p -r1.63 rtl81x9.c > --- rtl81x9.c 4 Feb 2009 19:54:44 -0000 1.63 > +++ rtl81x9.c 4 May 2009 06:07:47 -0000 > @@ -158,7 +158,7 @@ int rl_miibus_readreg(struct device *, i > void rl_miibus_writereg(struct device *, int, int, int); > void rl_miibus_statchg(struct device *); > > -void rl_setmulti(struct rl_softc *); > +void rl_iff(struct rl_softc *); > void rl_reset(struct rl_softc *); > int rl_list_tx_init(struct rl_softc *); > > @@ -457,63 +457,56 @@ int rl_mii_writereg(sc, frame) > return(0); > } > > -/* > - * Program the 64-bit multicast hash filter. > - */ > -void rl_setmulti(sc) > +void rl_iff(sc) > struct rl_softc *sc; > { > - struct ifnet *ifp; > + struct ifnet *ifp = &sc->sc_arpcom.ac_if; > int h = 0; > - u_int32_t hashes[2] = { 0, 0 }; > + u_int32_t hashes[2]; > struct arpcom *ac = &sc->sc_arpcom; > struct ether_multi *enm; > struct ether_multistep step; > u_int32_t rxfilt; > - int mcnt = 0; > - > - ifp = &sc->sc_arpcom.ac_if; > > rxfilt = CSR_READ_4(sc, RL_RXCFG); > + rxfilt &= ~(RL_RXCFG_RX_ALLPHYS | RL_RXCFG_RX_BROAD | > + RL_RXCFG_RX_INDIV | RL_RXCFG_RX_MULTI); > + ifp->if_flags &= ~IFF_ALLMULTI; > > -allmulti: > - if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { > + /* > + * Always accept frames destined to our station address. > + * Always accept broadcast frames. > + */ > + rxfilt |= RL_RXCFG_RX_INDIV | RL_RXCFG_RX_BROAD; > + > + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { > + ifp ->if_flags |= IFF_ALLMULTI; > rxfilt |= RL_RXCFG_RX_MULTI; > - CSR_WRITE_4(sc, RL_RXCFG, rxfilt); > - CSR_WRITE_4(sc, RL_MAR0, 0xFFFFFFFF); > - CSR_WRITE_4(sc, RL_MAR4, 0xFFFFFFFF); > - return; > - } > + if (ifp->if_flags & IFF_PROMISC) > + rxfilt |= RL_RXCFG_RX_ALLPHYS; > + hashes[0] = hashes[1] = 0xFFFFFFFF; > + } else { > + rxfilt |= RL_RXCFG_RX_MULTI; > + /* Program new filter. */ > + bzero(hashes, sizeof(hashes)); > > - /* first, zot all the existing hash bits */ > - CSR_WRITE_4(sc, RL_MAR0, 0); > - CSR_WRITE_4(sc, RL_MAR4, 0); > - > - /* now program new ones */ > - ETHER_FIRST_MULTI(step, ac, enm); > - while (enm != NULL) { > - if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { > - ifp->if_flags |= IFF_ALLMULTI; > - goto allmulti; > - } > - mcnt++; > - h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26; > - if (h < 32) > - hashes[0] |= (1 << h); > - else > - hashes[1] |= (1 << (h - 32)); > - mcnt++; > - ETHER_NEXT_MULTI(step, enm); > - } > + ETHER_FIRST_MULTI(step, ac, enm); > + while (enm != NULL) { > + h = ether_crc32_be(enm->enm_addrlo, > + ETHER_ADDR_LEN) >> 26; > + > + if (h < 32) > + hashes[0] |= (1 << h); > + else > + hashes[1] |= (1 << (h - 32)); > > - if (mcnt) > - rxfilt |= RL_RXCFG_RX_MULTI; > - else > - rxfilt &= ~RL_RXCFG_RX_MULTI; > + ETHER_NEXT_MULTI(step, enm); > + } > + } > > - CSR_WRITE_4(sc, RL_RXCFG, rxfilt); > CSR_WRITE_4(sc, RL_MAR0, hashes[0]); > CSR_WRITE_4(sc, RL_MAR4, hashes[1]); > + CSR_WRITE_4(sc, RL_RXCFG, rxfilt); > } > > void > @@ -958,7 +951,6 @@ void rl_init(xsc) > struct rl_softc *sc = xsc; > struct ifnet *ifp = &sc->sc_arpcom.ac_if; > int s; > - u_int32_t rxcfg = 0; > > s = splnet(); > > @@ -996,30 +988,10 @@ void rl_init(xsc) > CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG); > CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG); > > - /* Set the individual bit to receive frames for this host only. */ > - rxcfg = CSR_READ_4(sc, RL_RXCFG); > - rxcfg |= RL_RXCFG_RX_INDIV; > - > - /* If we want promiscuous mode, set the allframes bit. */ > - if (ifp->if_flags & IFF_PROMISC) > - rxcfg |= RL_RXCFG_RX_ALLPHYS; > - else > - rxcfg &= ~RL_RXCFG_RX_ALLPHYS; > - CSR_WRITE_4(sc, RL_RXCFG, rxcfg); > - > /* > - * Set capture broadcast bit to capture broadcast frames. > + * Program promiscuous mode and multicast filters. > */ > - if (ifp->if_flags & IFF_BROADCAST) > - rxcfg |= RL_RXCFG_RX_BROAD; > - else > - rxcfg &= ~RL_RXCFG_RX_BROAD; > - CSR_WRITE_4(sc, RL_RXCFG, rxcfg); > - > - /* > - * Program the multicast filter, if necessary. > - */ > - rl_setmulti(sc); > + rl_iff(sc); > > /* > * Enable interrupts. > @@ -1089,38 +1061,38 @@ int rl_ioctl(ifp, command, data) > switch(command) { > case SIOCSIFADDR: > ifp->if_flags |= IFF_UP; > - switch (ifa->ifa_addr->sa_family) { > -#ifdef INET > - case AF_INET: > + if (!(ifp->if_flags & IFF_RUNNING)) > rl_init(sc); > +#ifdef INET > + if (ifa->ifa_addr->sa_family == AF_INET) > arp_ifinit(&sc->sc_arpcom, ifa); > - break; > #endif /* INET */ > - default: > - rl_init(sc); > - break; > - } > break; > + > case SIOCSIFFLAGS: > if (ifp->if_flags & IFF_UP) { > - rl_init(sc); > + if (ifp->if_flags & IFF_RUNNING) > + error = ENETRESET; > + else > + rl_init(sc); > } else { > if (ifp->if_flags & IFF_RUNNING) > rl_stop(sc); > } > - error = 0; > break; > + > case SIOCGIFMEDIA: > case SIOCSIFMEDIA: > error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command); > break; > + > default: > error = ether_ioctl(ifp, &sc->sc_arpcom, command, data); > } > > if (error == ENETRESET) { > if (ifp->if_flags & IFF_RUNNING) > - rl_setmulti(sc); > + rl_iff(sc); > error = 0; > } -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.