The following diff rewrites parts of the code for promiscuous mode
and multicast handling for the txp(4) driver, as well as rewriting bits
of the ioctl handling code to eleminate unnecessary interface resets
when configuring IP aliases and/or re-configuring IP addresses or enabling
and disabling promisc mode. Please test promisc mode and multicast mode of
operation with any txp(4) adapters.

Please provide a dmesg.


Index: if_txp.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_txp.c,v
retrieving revision 1.100
diff -u -p -r1.100 if_txp.c
--- if_txp.c    24 Mar 2009 11:12:10 -0000      1.100
+++ if_txp.c    6 Jun 2009 09:03:45 -0000
@@ -105,7 +105,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,
@@ -1204,22 +1204,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);
@@ -1237,7 +1236,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;
        }
 
@@ -1255,7 +1254,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);
@@ -1863,64 +1863,45 @@ 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;
 
-       if (ifp->if_flags & IFF_PROMISC) {
-               filter = TXP_RXFILT_PROMISC;
-               goto setit;
-       }
-
-again:
-       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) {
-                       if (bcmp(enm->enm_addrlo, enm->enm_addrhi, 
ETHER_ADDR_LEN)) {
-                               /*
-                                * We must listen to a range of multicast
-                                * addresses.  For now, just accept all
-                                * multicasts, rather than trying to set only
-                                * those filter bits needed to match the range.
-                                * (At this time, the only use of address
-                                * ranges is for IP multicast routing, for
-                                * which the range is big enough to require
-                                * all bits set.)
-                                */
-                               ifp->if_flags |= IFF_ALLMULTI;
-                               goto again;
-                       }
-
-                       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