Please test the following diff with any em(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_em.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_em.c,v
retrieving revision 1.208
diff -u -p -r1.208 if_em.c
--- if_em.c     25 May 2009 10:17:55 -0000      1.208
+++ if_em.c     28 May 2009 00:12:28 -0000
@@ -179,8 +179,7 @@ void em_receive_checksum(struct em_softc
 void em_transmit_checksum_setup(struct em_softc *, struct mbuf *,
                                u_int32_t *, u_int32_t *);
 #endif
-void em_set_promisc(struct em_softc *);
-void em_set_multi(struct em_softc *);
+void em_iff(struct em_softc *);
 #ifdef EM_DEBUG
 void em_print_hw_stats(struct em_softc *);
 #endif
@@ -566,24 +565,14 @@ em_ioctl(struct ifnet *ifp, u_long comma
        case SIOCSIFFLAGS:
                IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFFLAGS (Set Interface 
Flags)");
                if (ifp->if_flags & IFF_UP) {
-                       /*
-                        * If only the PROMISC or ALLMULTI flag changes, then
-                        * don't do a full re-init of the chip, just update
-                        * the Rx filter.
-                        */
-                       if ((ifp->if_flags & IFF_RUNNING) &&
-                           ((ifp->if_flags ^ sc->if_flags) &
-                            (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
-                               em_set_promisc(sc);
-                       } else {
-                               if (!(ifp->if_flags & IFF_RUNNING))
-                                       em_init(sc);
-                       }
+                       if (ifp->if_flags & IFF_RUNNING)
+                               error = ENETRESET;
+                       else
+                               em_init(sc);
                } else {
                        if (ifp->if_flags & IFF_RUNNING)
                                em_stop(sc);
                }
-               sc->if_flags = ifp->if_flags;
                break;
 
        case SIOCSIFMEDIA:
@@ -605,7 +594,7 @@ em_ioctl(struct ifnet *ifp, u_long comma
        if (error == ENETRESET) {
                if (ifp->if_flags & IFF_RUNNING) {
                        em_disable_intr(sc);
-                       em_set_multi(sc);
+                       em_iff(sc);
                        if (sc->hw.mac_type == em_82542_rev2_0)
                                em_initialize_receive_unit(sc);
                        em_enable_intr(sc);
@@ -742,9 +731,6 @@ em_init(void *arg)
        }
        em_initialize_transmit_unit(sc);
 
-       /* Setup Multicast table */
-       em_set_multi(sc);
-
        /* Prepare receive descriptors and buffers */
        if (em_setup_receive_structures(sc)) {
                printf("%s: Could not setup receive structures\n", 
@@ -755,8 +741,8 @@ em_init(void *arg)
        }
        em_initialize_receive_unit(sc);
 
-       /* Don't lose promiscuous settings */
-       em_set_promisc(sc);
+       /* Program promiscuous mode and multicast filters. */
+       em_iff(sc);
 
        ifp->if_flags |= IFF_RUNNING;
        ifp->if_flags &= ~IFF_OACTIVE;
@@ -1291,44 +1277,17 @@ em_82547_tx_fifo_reset(struct em_softc *
 }
 
 void
-em_set_promisc(struct em_softc *sc)
+em_iff(struct em_softc *sc)
 {
-       u_int32_t       reg_rctl;
-       struct ifnet   *ifp = &sc->interface_data.ac_if;
-
-       reg_rctl = E1000_READ_REG(&sc->hw, RCTL);
-
-       if (ifp->if_flags & IFF_PROMISC) {
-               reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE);
-       } else if (ifp->if_flags & IFF_ALLMULTI) {
-               reg_rctl |= E1000_RCTL_MPE;
-               reg_rctl &= ~E1000_RCTL_UPE;
-       } else {
-               reg_rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE);
-       }
-       E1000_WRITE_REG(&sc->hw, RCTL, reg_rctl);
-}
-
-/*********************************************************************
- *  Multicast Update
- *
- *  This routine is called whenever multicast address list is updated.
- *
- **********************************************************************/
-
-void
-em_set_multi(struct em_softc *sc)
-{
-       u_int32_t reg_rctl = 0;
-       u_int8_t  mta[MAX_NUM_MULTICAST_ADDRESSES * ETH_LENGTH_OF_ADDRESS];
        struct ifnet *ifp = &sc->interface_data.ac_if;
        struct arpcom *ac = &sc->interface_data;
+       u_int32_t reg_rctl = 0;
+       u_int8_t  mta[MAX_NUM_MULTICAST_ADDRESSES * ETH_LENGTH_OF_ADDRESS];
        struct ether_multi *enm;
        struct ether_multistep step;
        int i = 0;
 
-       IOCTL_DEBUGOUT("em_set_multi: begin");
-       ifp->if_flags &= ~IFF_ALLMULTI;
+       IOCTL_DEBUGOUT("em_iff: begin");
 
        if (sc->hw.mac_type == em_82542_rev2_0) {
                reg_rctl = E1000_READ_REG(&sc->hw, RCTL);
@@ -1340,13 +1299,17 @@ em_set_multi(struct em_softc *sc)
        }
 
        reg_rctl = E1000_READ_REG(&sc->hw, RCTL);
-       if (ac->ac_multirangecnt > 0 ||
+       reg_rctl &= ~(E1000_RCTL_MPE | E1000_RCTL_UPE);
+       ifp->if_flags &= ~IFF_ALLMULTI;
+
+       if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0 ||
            ac->ac_multicnt > MAX_NUM_MULTICAST_ADDRESSES) {
                ifp->if_flags |= IFF_ALLMULTI;
                reg_rctl |= E1000_RCTL_MPE;
+               if (ifp->if_flags & IFF_PROMISC)
+                       reg_rctl |= E1000_RCTL_UPE;
        } else {
                ETHER_FIRST_MULTI(step, ac, enm);
-
                while (enm != NULL) {
                        bcopy(enm->enm_addrlo, mta + i, ETH_LENGTH_OF_ADDRESS);
                        i += ETH_LENGTH_OF_ADDRESS;
@@ -1355,8 +1318,8 @@ em_set_multi(struct em_softc *sc)
                }
 
                em_mc_addr_list_update(&sc->hw, mta, ac->ac_multicnt, 0, 1);
-               reg_rctl &= ~E1000_RCTL_MPE;
        }
+
        E1000_WRITE_REG(&sc->hw, RCTL, reg_rctl);
 
        if (sc->hw.mac_type == em_82542_rev2_0) {
Index: if_em.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_em.h,v
retrieving revision 1.43
diff -u -p -r1.43 if_em.h
--- if_em.h     15 Dec 2008 02:33:04 -0000      1.43
+++ if_em.h     6 Jan 2009 21:11:58 -0000
@@ -324,7 +324,6 @@ struct em_softc {
        struct timeout  em_intr_enable;
        struct timeout  timer_handle;
        struct timeout  tx_fifo_timer_handle;
-       int             if_flags;
        void            *sc_powerhook;
        void            *sc_shutdownhook;
 

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

Reply via email to