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.

Reply via email to