Here is a diff for the txp(4) 3Com 3XP Typhoon/Sidewinder 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_txp.c =================================================================== RCS file: /home/cvs/src/sys/dev/pci/if_txp.c,v retrieving revision 1.108 diff -u -p -r1.108 if_txp.c --- if_txp.c 26 Nov 2013 09:50:33 -0000 1.108 +++ if_txp.c 2 Dec 2013 02:04:44 -0000 @@ -103,7 +103,7 @@ int txp_download_fw_section(struct txp_s int txp_alloc_rings(struct txp_softc *); void txp_dma_free(struct txp_softc *, struct txp_dma_alloc *); int txp_dma_malloc(struct txp_softc *, bus_size_t, struct txp_dma_alloc *, int); -void txp_set_filter(struct txp_softc *); +void txp_iff(struct txp_softc *); int txp_cmd_desc_numfree(struct txp_softc *); int txp_command(struct txp_softc *, u_int16_t, u_int16_t, u_int32_t, @@ -1184,22 +1184,21 @@ txp_ioctl(struct ifnet *ifp, u_long comm 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)) txp_init(sc); + +#ifdef INET + if (ifa->ifa_addr->sa_family == AF_INET) arp_ifinit(&sc->sc_arpcom, ifa); - break; -#endif /* INET */ - default: - txp_init(sc); - break; - } +#endif break; case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { - txp_init(sc); + if (ifp->if_flags & IFF_RUNNING) + error = ENETRESET; + else + txp_init(sc); } else { if (ifp->if_flags & IFF_RUNNING) txp_stop(sc); @@ -1217,7 +1216,7 @@ txp_ioctl(struct ifnet *ifp, u_long comm if (error == ENETRESET) { if (ifp->if_flags & IFF_RUNNING) - txp_set_filter(sc); + txp_iff(sc); error = 0; } @@ -1235,7 +1234,8 @@ txp_init(struct txp_softc *sc) s = splnet(); - txp_set_filter(sc); + /* Program promiscuous mode and multicast filters. */ + txp_iff(sc); txp_command(sc, TXP_CMD_TX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1); txp_command(sc, TXP_CMD_RX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1); @@ -1843,51 +1843,46 @@ txp_show_descriptor(void *d) } void -txp_set_filter(struct txp_softc *sc) +txp_iff(struct txp_softc *sc) { struct arpcom *ac = &sc->sc_arpcom; struct ifnet *ifp = &sc->sc_arpcom.ac_if; - u_int32_t hashbit, hash[2]; - u_int16_t filter; - int mcnt = 0; struct ether_multi *enm; struct ether_multistep step; + u_int32_t hashbit, hash[2]; + u_int16_t filter; - if (ifp->if_flags & IFF_PROMISC) { - filter = TXP_RXFILT_PROMISC; - goto setit; - } - - if (ac->ac_multirangecnt > 0) - ifp->if_flags |= IFF_ALLMULTI; - - filter = TXP_RXFILT_DIRECT; + bzero(hash, sizeof(hash)); + ifp->if_flags &= ~IFF_ALLMULTI; - if (ifp->if_flags & IFF_BROADCAST) - filter |= TXP_RXFILT_BROADCAST; + /* + * Always accept broadcast packets. + * Always accept frames destined to our station address. + */ + filter = TXP_RXFILT_BROADCAST | TXP_RXFILT_DIRECT; - if (ifp->if_flags & IFF_ALLMULTI) - filter |= TXP_RXFILT_ALLMULTI; - else { - hash[0] = hash[1] = 0; + if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) { + ifp->if_flags |= IFF_ALLMULTI; + if (ifp->if_flags & IFF_PROMISC) + filter |= TXP_RXFILT_PROMISC; + else + filter |= TXP_RXFILT_ALLMULTI; + } else { + filter |= TXP_RXFILT_HASHMULTI; ETHER_FIRST_MULTI(step, ac, enm); while (enm != NULL) { - mcnt++; hashbit = (u_int16_t)(ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) & (64 - 1)); + hash[hashbit / 32] |= (1 << hashbit % 32); - ETHER_NEXT_MULTI(step, enm); - } - if (mcnt > 0) { - filter |= TXP_RXFILT_HASHMULTI; - txp_command(sc, TXP_CMD_MCAST_HASH_MASK_WRITE, - 2, hash[0], hash[1], NULL, NULL, NULL, 0); + ETHER_NEXT_MULTI(step, enm); } } -setit: + txp_command(sc, TXP_CMD_MCAST_HASH_MASK_WRITE, + 2, hash[0], hash[1], NULL, NULL, NULL, 0); txp_command(sc, TXP_CMD_RX_FILTER_WRITE, filter, 0, 0, NULL, NULL, NULL, 1); } -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.