Here is a diff for the bce(4) Broadcom BCM4401 driver to clean up and update the receive filter / ioctl handling code to be in line with the other drivers.
Anyone with hw and able to test? OK? Index: if_bce.c =================================================================== RCS file: /home/cvs/src/sys/dev/pci/if_bce.c,v retrieving revision 1.37 diff -u -p -r1.37 if_bce.c --- if_bce.c 21 Aug 2013 05:21:43 -0000 1.37 +++ if_bce.c 9 Sep 2013 18:31:22 -0000 @@ -146,7 +146,7 @@ void bce_add_mac(struct bce_softc *, u_i void bce_add_rxbuf(struct bce_softc *, int); void bce_stop(struct ifnet *); void bce_reset(struct bce_softc *); -void bce_set_filter(struct ifnet *); +void bce_iff(struct ifnet *); int bce_mii_read(struct device *, int, int); void bce_mii_write(struct device *, int, int, int); void bce_statchg(struct device *); @@ -473,28 +473,24 @@ bce_ioctl(struct ifnet *ifp, u_long cmd, switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; - - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: + if (!(ifp->if_flags & IFF_RUNNING)) bce_init(ifp); +#ifdef INET + if (ifa->ifa_addr->sa_family == AF_INET) arp_ifinit(&sc->bce_ac, ifa); - break; -#endif /* INET */ - default: - bce_init(ifp); - break; - } +#endif break; case SIOCSIFFLAGS: - if (ifp->if_flags & IFF_UP) + if (ifp->if_flags & IFF_UP) { if (ifp->if_flags & IFF_RUNNING) - bce_set_filter(ifp); + error = ENETRESET; else bce_init(ifp); - else if (ifp->if_flags & IFF_RUNNING) - bce_stop(ifp); + } else { + if (ifp->if_flags & IFF_RUNNING) + bce_stop(ifp); + } break; case SIOCSIFMEDIA: @@ -508,7 +504,7 @@ bce_ioctl(struct ifnet *ifp, u_long cmd, if (error == ENETRESET) { if (ifp->if_flags & IFF_RUNNING) - bce_set_filter(ifp); + bce_iff(ifp); error = 0; } @@ -871,8 +867,8 @@ bce_init(struct ifnet *ifp) /* setup DMA interrupt control */ bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMAI_CTL, 1 << 24); /* MAGIC */ - /* setup packet filter */ - bce_set_filter(ifp); + /* program promiscuous mode and multicast filters */ + bce_iff(ifp); /* set max frame length, account for possible VLAN tag */ bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_MAX, @@ -1198,51 +1194,35 @@ bce_reset(struct bce_softc *sc) /* Set up the receive filter. */ void -bce_set_filter(struct ifnet *ifp) +bce_iff(struct ifnet *ifp) { struct bce_softc *sc = ifp->if_softc; + struct arpcom *ac = &sc->bce_ac; + u_int32_t rxctl; - if (ifp->if_flags & IFF_PROMISC) { - ifp->if_flags |= IFF_ALLMULTI; - bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL, - bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL) - | ERC_PE); - } else { - ifp->if_flags &= ~IFF_ALLMULTI; - - /* turn off promiscuous */ - bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL, - bus_space_read_4(sc->bce_btag, sc->bce_bhandle, - BCE_RX_CTL) & ~ERC_PE); + rxctl = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL); + rxctl &= ~(ERC_AM | ERC_DB | ERC_PE); + ifp->if_flags |= IFF_ALLMULTI; - /* enable/disable broadcast */ - if (ifp->if_flags & IFF_BROADCAST) - bus_space_write_4(sc->bce_btag, sc->bce_bhandle, - BCE_RX_CTL, bus_space_read_4(sc->bce_btag, - sc->bce_bhandle, BCE_RX_CTL) & ~ERC_DB); - else - bus_space_write_4(sc->bce_btag, sc->bce_bhandle, - BCE_RX_CTL, bus_space_read_4(sc->bce_btag, - sc->bce_bhandle, BCE_RX_CTL) | ERC_DB); - - /* disable the filter */ - bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL, - 0); + /* disable the filter */ + bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL, 0); - /* add our own address */ - bce_add_mac(sc, sc->bce_ac.ac_enaddr, 0); + /* add our own address */ + bce_add_mac(sc, ac->ac_enaddr, 0); - /* for now accept all multicast */ - bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL, - bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL) | - ERC_AM); + if (ifp->if_flags & IFF_PROMISC || ac->ac_multicnt > 0) { ifp->if_flags |= IFF_ALLMULTI; - - /* enable the filter */ - bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL, - bus_space_read_4(sc->bce_btag, sc->bce_bhandle, - BCE_FILT_CTL) | 1); + if (ifp->if_flags & IFF_PROMISC) + rxctl |= ERC_PE; + else + rxctl |= ERC_AM; } + + /* enable the filter */ + bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL, + bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL) | 1); + + bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL, rxctl); } /* Read a PHY register on the MII. */ -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.