summaryrefslogtreecommitdiffstats
path: root/sys/dev/e1000/if_em.c
diff options
context:
space:
mode:
authorjfv <jfv@FreeBSD.org>2013-04-03 23:39:54 +0000
committerjfv <jfv@FreeBSD.org>2013-04-03 23:39:54 +0000
commit8f86323b516396dac627133e46a94b9db684dc7f (patch)
treea3a6d2b2b62dca67f128c47313873d022628d100 /sys/dev/e1000/if_em.c
parent318b0921c12fae5505d2e0e6de3ba7e716b7be95 (diff)
downloadFreeBSD-src-8f86323b516396dac627133e46a94b9db684dc7f.zip
FreeBSD-src-8f86323b516396dac627133e46a94b9db684dc7f.tar.gz
Correct the multicast handling in the E1000 drivers as was
done in ixgbe, thanks to Mike Karels for this fix. When exiting promiscuous mode MPE bit was being unconditionally cleared, this should not be done if we are in MAX multicast groups.
Diffstat (limited to 'sys/dev/e1000/if_em.c')
-rw-r--r--sys/dev/e1000/if_em.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 64be42d..12d8834 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -94,7 +94,7 @@ int em_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char em_driver_version[] = "7.3.7";
+char em_driver_version[] = "7.3.8";
/*********************************************************************
* PCI Device ID Table
@@ -2133,12 +2133,37 @@ em_set_promisc(struct adapter *adapter)
static void
em_disable_promisc(struct adapter *adapter)
{
- u32 reg_rctl;
+ struct ifnet *ifp = adapter->ifp;
+ u32 reg_rctl;
+ int mcnt = 0;
reg_rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
-
reg_rctl &= (~E1000_RCTL_UPE);
- reg_rctl &= (~E1000_RCTL_MPE);
+ if (ifp->if_flags & IFF_ALLMULTI)
+ mcnt = MAX_NUM_MULTICAST_ADDRESSES;
+ else {
+ struct ifmultiaddr *ifma;
+#if __FreeBSD_version < 800000
+ IF_ADDR_LOCK(ifp);
+#else
+ if_maddr_rlock(ifp);
+#endif
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ if (mcnt == MAX_NUM_MULTICAST_ADDRESSES)
+ break;
+ mcnt++;
+ }
+#if __FreeBSD_version < 800000
+ IF_ADDR_UNLOCK(ifp);
+#else
+ if_maddr_runlock(ifp);
+#endif
+ }
+ /* Don't disable if in MAX groups */
+ if (mcnt < MAX_NUM_MULTICAST_ADDRESSES)
+ reg_rctl &= (~E1000_RCTL_MPE);
reg_rctl &= (~E1000_RCTL_SBP);
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
}
OpenPOWER on IntegriCloud