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.