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.
This commit is contained in:
jfv 2013-04-03 23:39:54 +00:00
parent 318b0921c1
commit 8f86323b51
3 changed files with 89 additions and 13 deletions

View File

@ -94,7 +94,7 @@ int em_display_debug_stats = 0;
/********************************************************************* /*********************************************************************
* Driver version: * Driver version:
*********************************************************************/ *********************************************************************/
char em_driver_version[] = "7.3.7"; char em_driver_version[] = "7.3.8";
/********************************************************************* /*********************************************************************
* PCI Device ID Table * PCI Device ID Table
@ -2133,12 +2133,37 @@ em_set_promisc(struct adapter *adapter)
static void static void
em_disable_promisc(struct adapter *adapter) 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_READ_REG(&adapter->hw, E1000_RCTL);
reg_rctl &= (~E1000_RCTL_UPE); 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); reg_rctl &= (~E1000_RCTL_SBP);
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
} }

View File

@ -100,7 +100,7 @@ int igb_display_debug_stats = 0;
/********************************************************************* /*********************************************************************
* Driver version: * Driver version:
*********************************************************************/ *********************************************************************/
char igb_driver_version[] = "version - 2.3.9"; char igb_driver_version[] = "version - 2.3.10";
/********************************************************************* /*********************************************************************
@ -374,9 +374,9 @@ SYSCTL_INT(_hw_igb, OID_AUTO, header_split, CTLFLAG_RDTUN, &igb_header_split, 0,
"Enable receive mbuf header split"); "Enable receive mbuf header split");
/* /*
** This will autoconfigure based on ** This will autoconfigure based on the
** the number of CPUs and max supported MSI-X messages ** number of CPUs and max supported
** if left at 0. ** MSIX messages if left at 0.
*/ */
static int igb_num_queues = 0; static int igb_num_queues = 0;
TUNABLE_INT("hw.igb.num_queues", &igb_num_queues); TUNABLE_INT("hw.igb.num_queues", &igb_num_queues);
@ -2096,7 +2096,9 @@ static void
igb_disable_promisc(struct adapter *adapter) igb_disable_promisc(struct adapter *adapter)
{ {
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
struct ifnet *ifp = adapter->ifp;
u32 reg; u32 reg;
int mcnt = 0;
if (adapter->vf_ifp) { if (adapter->vf_ifp) {
e1000_promisc_set_vf(hw, e1000_promisc_disabled); e1000_promisc_set_vf(hw, e1000_promisc_disabled);
@ -2104,7 +2106,31 @@ igb_disable_promisc(struct adapter *adapter)
} }
reg = E1000_READ_REG(hw, E1000_RCTL); reg = E1000_READ_REG(hw, E1000_RCTL);
reg &= (~E1000_RCTL_UPE); reg &= (~E1000_RCTL_UPE);
reg &= (~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 &= (~E1000_RCTL_MPE);
E1000_WRITE_REG(hw, E1000_RCTL, reg); E1000_WRITE_REG(hw, E1000_RCTL, reg);
} }

View File

@ -85,7 +85,7 @@
/********************************************************************* /*********************************************************************
* Legacy Em Driver version: * Legacy Em Driver version:
*********************************************************************/ *********************************************************************/
char lem_driver_version[] = "1.0.5"; char lem_driver_version[] = "1.0.6";
/********************************************************************* /*********************************************************************
* PCI Device ID Table * PCI Device ID Table
@ -1856,12 +1856,37 @@ lem_set_promisc(struct adapter *adapter)
static void static void
lem_disable_promisc(struct adapter *adapter) lem_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_READ_REG(&adapter->hw, E1000_RCTL);
reg_rctl &= (~E1000_RCTL_UPE); 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); reg_rctl &= (~E1000_RCTL_SBP);
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl); E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
} }