Commit 148cbab6 authored by Edward Cree's avatar Edward Cree Committed by David S. Miller

sfc: don't insert mc_list on low-latency firmware if it's too long

If the mc_list is longer than 256 addresses, we enter mc_promisc mode.
If we're in mc_promisc mode and the firmware doesn't support cascaded
 multicast, normally we also insert our mc_list, to prevent stealing by
 another VI.  However, if the mc_list was too long, this isn't really
 helpful - the MC groups that didn't fit in the list can still get
 stolen, and having only some of them stealable will probably cause
 more confusing behaviour than having them all stealable.  Since
 inserting 256 multicast filters takes a long time and can lead to MCDI
 state machine timeouts, just skip the mc_list insert in this overflow
 condition.
Signed-off-by: default avatarEdward Cree <ecree@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a4b7c07f
...@@ -119,6 +119,7 @@ struct efx_ef10_filter_table { ...@@ -119,6 +119,7 @@ struct efx_ef10_filter_table {
bool mc_promisc; bool mc_promisc;
/* Whether in multicast promiscuous mode when last changed */ /* Whether in multicast promiscuous mode when last changed */
bool mc_promisc_last; bool mc_promisc_last;
bool mc_overflow; /* Too many MC addrs; should always imply mc_promisc */
bool vlan_filter; bool vlan_filter;
struct list_head vlan_list; struct list_head vlan_list;
}; };
...@@ -5058,6 +5059,7 @@ static void efx_ef10_filter_mc_addr_list(struct efx_nic *efx) ...@@ -5058,6 +5059,7 @@ static void efx_ef10_filter_mc_addr_list(struct efx_nic *efx)
struct netdev_hw_addr *mc; struct netdev_hw_addr *mc;
unsigned int i, addr_count; unsigned int i, addr_count;
table->mc_overflow = false;
table->mc_promisc = !!(net_dev->flags & (IFF_PROMISC | IFF_ALLMULTI)); table->mc_promisc = !!(net_dev->flags & (IFF_PROMISC | IFF_ALLMULTI));
addr_count = netdev_mc_count(net_dev); addr_count = netdev_mc_count(net_dev);
...@@ -5065,6 +5067,7 @@ static void efx_ef10_filter_mc_addr_list(struct efx_nic *efx) ...@@ -5065,6 +5067,7 @@ static void efx_ef10_filter_mc_addr_list(struct efx_nic *efx)
netdev_for_each_mc_addr(mc, net_dev) { netdev_for_each_mc_addr(mc, net_dev) {
if (i >= EFX_EF10_FILTER_DEV_MC_MAX) { if (i >= EFX_EF10_FILTER_DEV_MC_MAX) {
table->mc_promisc = true; table->mc_promisc = true;
table->mc_overflow = true;
break; break;
} }
ether_addr_copy(table->dev_mc_list[i].addr, mc->addr); ether_addr_copy(table->dev_mc_list[i].addr, mc->addr);
...@@ -5469,12 +5472,15 @@ static void efx_ef10_filter_vlan_sync_rx_mode(struct efx_nic *efx, ...@@ -5469,12 +5472,15 @@ static void efx_ef10_filter_vlan_sync_rx_mode(struct efx_nic *efx,
} }
} else { } else {
/* If we failed to insert promiscuous filters, don't /* If we failed to insert promiscuous filters, don't
* rollback. Regardless, also insert the mc_list * rollback. Regardless, also insert the mc_list,
* unless it's incomplete due to overflow
*/ */
efx_ef10_filter_insert_def(efx, vlan, efx_ef10_filter_insert_def(efx, vlan,
EFX_ENCAP_TYPE_NONE, EFX_ENCAP_TYPE_NONE,
true, false); true, false);
efx_ef10_filter_insert_addr_list(efx, vlan, true, false); if (!table->mc_overflow)
efx_ef10_filter_insert_addr_list(efx, vlan,
true, false);
} }
} else { } else {
/* If any filters failed to insert, rollback and fall back to /* If any filters failed to insert, rollback and fall back to
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment