Please test the following diff with any sis(4) adapters using
any apps making use of multicast (IPv6, OSPF, CARP, etc.) and/or
promiscuous mode of operation.

Please provide a dmesg.


Index: if_sis.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_sis.c,v
retrieving revision 1.88
diff -u -p -r1.88 if_sis.c
--- if_sis.c    14 Apr 2009 19:06:49 -0000      1.88
+++ if_sis.c    15 Apr 2009 05:56:10 -0000
@@ -153,10 +153,9 @@ void sis_miibus_writereg(struct device *
 void sis_miibus_statchg(struct device *);
 
 u_int32_t sis_mchash(struct sis_softc *, const uint8_t *);
-void sis_setmulti(struct sis_softc *);
-void sis_setmulti_sis(struct sis_softc *);
-void sis_setmulti_ns(struct sis_softc *);
-void sis_setpromisc(struct sis_softc *);
+void sis_iff(struct sis_softc *);
+void sis_iff_ns(struct sis_softc *);
+void sis_iff_sis(struct sis_softc *);
 void sis_reset(struct sis_softc *);
 int sis_ring_init(struct sis_softc *);
 
@@ -699,144 +698,129 @@ sis_mchash(struct sis_softc *sc, const u
 }
 
 void
-sis_setmulti(struct sis_softc *sc)
+sis_iff(struct sis_softc *sc)
 {
        if (sc->sis_type == SIS_TYPE_83815)
-               sis_setmulti_ns(sc);
+               sis_iff_ns(sc);
        else
-               sis_setmulti_sis(sc);
+               sis_iff_sis(sc);
 }
 
 void
-sis_setmulti_ns(struct sis_softc *sc)
+sis_iff_ns(struct sis_softc *sc)
 {
-       struct ifnet            *ifp;
+       struct ifnet            *ifp = &sc->arpcom.ac_if;
        struct arpcom           *ac = &sc->arpcom;
        struct ether_multi      *enm;
        struct ether_multistep  step;
-       u_int32_t               h = 0, i, filtsave;
+       u_int32_t               h = 0, i, rxfilt;
        int                     bit, index;
 
-       ifp = &sc->arpcom.ac_if;
+       rxfilt = CSR_READ_4(sc, SIS_RXFILT_CTL);
+       rxfilt &= ~(SIS_RXFILTCTL_ALLMULTI | SIS_RXFILTCTL_ALLPHYS |
+           SIS_RXFILTCTL_BROAD | NS_RXFILTCTL_MCHASH);
+       ifp->if_flags &= ~IFF_ALLMULTI;
 
-       if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
-allmulti:
-               SIS_CLRBIT(sc, SIS_RXFILT_CTL, NS_RXFILTCTL_MCHASH);
-               SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLMULTI);
-               return;
-       }
+       /*
+        * Always accept broadcast frames.
+        */
+       rxfilt |= SIS_RXFILTCTL_BROAD;
 
-       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;
+       if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
+               ifp->if_flags |= IFF_ALLMULTI;
+               rxfilt |= SIS_RXFILTCTL_ALLMULTI;
+               if (ifp->if_flags & IFF_PROMISC)
+                       rxfilt |= SIS_RXFILTCTL_ALLPHYS;
+       } else {
+               /*
+                * We have to explicitly enable the multicast hash table
+                * on the NatSemi chip if we want to use it, which we do.
+                */
+               rxfilt |= NS_RXFILTCTL_MCHASH;
+
+               /* first, zot all the existing hash bits */
+               for (i = 0; i < 32; i++) {
+                       CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + 
(i*2));
+                       CSR_WRITE_4(sc, SIS_RXFILT_DATA, 0);
                }
-               ETHER_NEXT_MULTI(step, enm);
-       }
 
-       /*
-        * We have to explicitly enable the multicast hash table
-        * on the NatSemi chip if we want to use it, which we do.
-        */
-       SIS_SETBIT(sc, SIS_RXFILT_CTL, NS_RXFILTCTL_MCHASH);
-       SIS_CLRBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLMULTI);
+               ETHER_FIRST_MULTI(step, ac, enm);
+               while (enm != NULL) {
+                       h = sis_mchash(sc, enm->enm_addrlo);
 
-       filtsave = CSR_READ_4(sc, SIS_RXFILT_CTL);
+                       index = h >> 3;
+                       bit = h & 0x1F;
 
-       /* first, zot all the existing hash bits */
-       for (i = 0; i < 32; i++) {
-               CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + (i*2));
-               CSR_WRITE_4(sc, SIS_RXFILT_DATA, 0);
-       }
+                       CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + 
index);
 
-       ETHER_FIRST_MULTI(step, ac, enm);
-       while (enm != NULL) {
-               h = sis_mchash(sc, enm->enm_addrlo);
-               index = h >> 3;
-               bit = h & 0x1F;
-               CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + index);
-               if (bit > 0xF)
-                       bit -= 0x10;
-               SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << bit));
-               ETHER_NEXT_MULTI(step, enm);
+                       if (bit > 0xF)
+                               bit -= 0x10;
+
+                       SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << bit));
+
+                       ETHER_NEXT_MULTI(step, enm);
+               }
        }
 
-       CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave);
+       CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt);
 }
 
 void
-sis_setmulti_sis(struct sis_softc *sc)
+sis_iff_sis(struct sis_softc *sc)
 {
-       struct ifnet            *ifp;
+       struct ifnet            *ifp = &sc->arpcom.ac_if;
        struct arpcom           *ac = &sc->arpcom;
        struct ether_multi      *enm;
        struct ether_multistep  step;
-       u_int32_t               h, i, n, ctl;
+       u_int32_t               h, i, maxmulti, rxfilt;
        u_int16_t               hashes[16];
 
-       ifp = &sc->arpcom.ac_if;
-
        /* hash table size */
        if (sc->sis_rev >= SIS_REV_635 ||
            sc->sis_rev == SIS_REV_900B)
-               n = 16;
+               maxmulti = 16;
        else
-               n = 8;
+               maxmulti = 8;
 
-       ctl = CSR_READ_4(sc, SIS_RXFILT_CTL) & SIS_RXFILTCTL_ENABLE;
+       rxfilt = CSR_READ_4(sc, SIS_RXFILT_CTL);
+       rxfilt &= ~(SIS_RXFILTCTL_ALLMULTI | SIS_RXFILTCTL_ALLPHYS |
+           SIS_RXFILTCTL_BROAD);
+       ifp->if_flags &= ~IFF_ALLMULTI;
 
-       if (ifp->if_flags & IFF_BROADCAST)
-               ctl |= SIS_RXFILTCTL_BROAD;
+       /*
+        * Always accept broadcast frames.
+        */
+       rxfilt |= SIS_RXFILTCTL_BROAD;
 
-       if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
-allmulti:
-               ctl |= SIS_RXFILTCTL_ALLMULTI;
+       if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0 ||
+           ac->ac_multicnt > maxmulti) {
+               ifp->if_flags |= IFF_ALLMULTI;
+               rxfilt |= SIS_RXFILTCTL_ALLMULTI;
                if (ifp->if_flags & IFF_PROMISC)
-                       ctl |= SIS_RXFILTCTL_BROAD|SIS_RXFILTCTL_ALLPHYS;
-               for (i = 0; i < n; i++)
+                       rxfilt |= SIS_RXFILTCTL_ALLPHYS;
+
+               for (i = 0; i < maxmulti; i++)
                        hashes[i] = ~0;
        } else {
-               for (i = 0; i < n; i++)
+               for (i = 0; i < maxmulti; i++)
                        hashes[i] = 0;
-               i = 0;
+
                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;
-                       }
-
                        h = sis_mchash(sc, enm->enm_addrlo);
+
                        hashes[h >> 4] |= 1 << (h & 0xf);
-                       i++;
+
                        ETHER_NEXT_MULTI(step, enm);
                }
-               if (i > n) {
-                       ctl |= SIS_RXFILTCTL_ALLMULTI;
-                       for (i = 0; i < n; i++)
-                               hashes[i] = ~0;
-               }
        }
 
-       for (i = 0; i < n; i++) {
+       for (i = 0; i < maxmulti; i++) {
                CSR_WRITE_4(sc, SIS_RXFILT_CTL, (4 + i) << 16);
                CSR_WRITE_4(sc, SIS_RXFILT_DATA, hashes[i]);
        }
 
-       CSR_WRITE_4(sc, SIS_RXFILT_CTL, ctl);
-}
-
-void
-sis_setpromisc(struct sis_softc *sc)
-{
-       struct ifnet    *ifp = &sc->arpcom.ac_if;
-
-       /* If we want promiscuous mode, set the allframes bit. */
-       if (ifp->if_flags & IFF_PROMISC)
-               SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLPHYS);
-       else
-               SIS_CLRBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLPHYS);
+       CSR_WRITE_4(sc, SIS_RXFILT_CTL, rxfilt);
 }
 
 void
@@ -1745,20 +1729,9 @@ sis_init(void *xsc)
        }
 
        /*
-        * Set the capture broadcast bit to capture broadcast frames.
-        */
-       if (ifp->if_flags & IFF_BROADCAST)
-               SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_BROAD);
-       else
-               SIS_CLRBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_BROAD);
-
-       /* Set promiscuous mode. */
-       sis_setpromisc(sc);
-
-       /*
-        * Load the multicast filter.
+        * Program promiscuous mode and multicast filters.
         */
-       sis_setmulti(sc);
+       sis_iff(sc);
 
        /* Turn the receive filter on */
        SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ENABLE);
@@ -1919,24 +1892,14 @@ sis_ioctl(struct ifnet *ifp, u_long comm
 
        case SIOCSIFFLAGS:
                if (ifp->if_flags & IFF_UP) {
-                       if (ifp->if_flags & IFF_RUNNING &&
-                           (ifp->if_flags ^ sc->sc_if_flags) &
-                            IFF_PROMISC) {
-                               sis_setpromisc(sc);
-                               sis_setmulti(sc);
-                       } else if (ifp->if_flags & IFF_RUNNING &&
-                           (ifp->if_flags ^ sc->sc_if_flags) &
-                            IFF_ALLMULTI) {
-                               sis_setmulti(sc);
-                       } else {
-                               if (!(ifp->if_flags & IFF_RUNNING))
-                                       sis_init(sc);
-                       }
+                       if (ifp->if_flags & IFF_RUNNING)
+                               error = ENETRESET;
+                       else
+                               sis_init(sc);
                } else {
                        if (ifp->if_flags & IFF_RUNNING)
                                sis_stop(sc);
                }
-               sc->sc_if_flags = ifp->if_flags;
                break;
 
        case SIOCGIFMEDIA:
@@ -1951,7 +1914,7 @@ sis_ioctl(struct ifnet *ifp, u_long comm
 
        if (error == ENETRESET) {
                if (ifp->if_flags & IFF_RUNNING)
-                       sis_setmulti(sc);
+                       sis_iff(sc);
                error = 0;
        }
 
Index: if_sisreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_sisreg.h,v
retrieving revision 1.29
diff -u -p -r1.29 if_sisreg.h
--- if_sisreg.h 14 Apr 2009 19:06:49 -0000      1.29
+++ if_sisreg.h 15 Apr 2009 06:40:50 -0000
@@ -465,7 +465,6 @@ struct sis_softc {
        caddr_t                 sc_listkva;
        bus_dmamap_t            sc_tx_sparemap;
        int                     sis_stopped;
-       int                     sc_if_flags;
 };
 
 /*

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to