Commit c274d65c authored by Ben Hutchings's avatar Ben Hutchings

sfc: Add support for configuring RX unicast/multicast default filters

On Siena all received packets that don't match a more specific filter
will match the unicast or multicast default filter.  Currently we
leave these set to the default values (RSS with base queue number of
0).  Allow them to be reconfigured to select a single RX queue.

These default filters are programmed through the FILTER_CTL register,
but we represent them internally as an additional table of size 2.
Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
parent 7c43161c
...@@ -808,11 +808,16 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags) ...@@ -808,11 +808,16 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
return efx_reset(efx, rc); return efx_reset(efx, rc);
} }
/* MAC address mask including only MC flag */
static const u8 mac_addr_mc_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
static int efx_ethtool_get_class_rule(struct efx_nic *efx, static int efx_ethtool_get_class_rule(struct efx_nic *efx,
struct ethtool_rx_flow_spec *rule) struct ethtool_rx_flow_spec *rule)
{ {
struct ethtool_tcpip4_spec *ip_entry = &rule->h_u.tcp_ip4_spec; struct ethtool_tcpip4_spec *ip_entry = &rule->h_u.tcp_ip4_spec;
struct ethtool_tcpip4_spec *ip_mask = &rule->m_u.tcp_ip4_spec; struct ethtool_tcpip4_spec *ip_mask = &rule->m_u.tcp_ip4_spec;
struct ethhdr *mac_entry = &rule->h_u.ether_spec;
struct ethhdr *mac_mask = &rule->m_u.ether_spec;
struct efx_filter_spec spec; struct efx_filter_spec spec;
u16 vid; u16 vid;
u8 proto; u8 proto;
...@@ -828,11 +833,18 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, ...@@ -828,11 +833,18 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
else else
rule->ring_cookie = spec.dmaq_id; rule->ring_cookie = spec.dmaq_id;
rc = efx_filter_get_eth_local(&spec, &vid, if (spec.type == EFX_FILTER_MC_DEF || spec.type == EFX_FILTER_UC_DEF) {
rule->h_u.ether_spec.h_dest); rule->flow_type = ETHER_FLOW;
memcpy(mac_mask->h_dest, mac_addr_mc_mask, ETH_ALEN);
if (spec.type == EFX_FILTER_MC_DEF)
memcpy(mac_entry->h_dest, mac_addr_mc_mask, ETH_ALEN);
return 0;
}
rc = efx_filter_get_eth_local(&spec, &vid, mac_entry->h_dest);
if (rc == 0) { if (rc == 0) {
rule->flow_type = ETHER_FLOW; rule->flow_type = ETHER_FLOW;
memset(rule->m_u.ether_spec.h_dest, ~0, ETH_ALEN); memset(mac_mask->h_dest, ~0, ETH_ALEN);
if (vid != EFX_FILTER_VID_UNSPEC) { if (vid != EFX_FILTER_VID_UNSPEC) {
rule->flow_type |= FLOW_EXT; rule->flow_type |= FLOW_EXT;
rule->h_ext.vlan_tci = htons(vid); rule->h_ext.vlan_tci = htons(vid);
...@@ -1001,27 +1013,40 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx, ...@@ -1001,27 +1013,40 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
} }
case ETHER_FLOW | FLOW_EXT: case ETHER_FLOW | FLOW_EXT:
/* Must match all or none of VID */ case ETHER_FLOW: {
if (rule->m_ext.vlan_tci != htons(0xfff) && u16 vlan_tag_mask = (rule->flow_type & FLOW_EXT ?
rule->m_ext.vlan_tci != 0) ntohs(rule->m_ext.vlan_tci) : 0);
return -EINVAL;
case ETHER_FLOW: /* Must not match on source address or Ethertype */
/* Must match all of destination */
if (!is_broadcast_ether_addr(mac_mask->h_dest))
return -EINVAL;
/* and nothing else */
if (!is_zero_ether_addr(mac_mask->h_source) || if (!is_zero_ether_addr(mac_mask->h_source) ||
mac_mask->h_proto) mac_mask->h_proto)
return -EINVAL; return -EINVAL;
rc = efx_filter_set_eth_local( /* Is it a default UC or MC filter? */
&spec, if (!compare_ether_addr(mac_mask->h_dest, mac_addr_mc_mask) &&
(rule->flow_type & FLOW_EXT && rule->m_ext.vlan_tci) ? vlan_tag_mask == 0) {
ntohs(rule->h_ext.vlan_tci) : EFX_FILTER_VID_UNSPEC, if (is_multicast_ether_addr(mac_entry->h_dest))
mac_entry->h_dest); rc = efx_filter_set_mc_def(&spec);
else
rc = efx_filter_set_uc_def(&spec);
}
/* Otherwise, it must match all of destination and all
* or none of VID.
*/
else if (is_broadcast_ether_addr(mac_mask->h_dest) &&
(vlan_tag_mask == 0xfff || vlan_tag_mask == 0)) {
rc = efx_filter_set_eth_local(
&spec,
vlan_tag_mask ?
ntohs(rule->h_ext.vlan_tci) : EFX_FILTER_VID_UNSPEC,
mac_entry->h_dest);
} else {
rc = -EINVAL;
}
if (rc) if (rc)
return rc; return rc;
break; break;
}
default: default:
return -EINVAL; return -EINVAL;
......
...@@ -35,9 +35,16 @@ ...@@ -35,9 +35,16 @@
enum efx_filter_table_id { enum efx_filter_table_id {
EFX_FILTER_TABLE_RX_IP = 0, EFX_FILTER_TABLE_RX_IP = 0,
EFX_FILTER_TABLE_RX_MAC, EFX_FILTER_TABLE_RX_MAC,
EFX_FILTER_TABLE_RX_DEF,
EFX_FILTER_TABLE_COUNT, EFX_FILTER_TABLE_COUNT,
}; };
enum efx_filter_index {
EFX_FILTER_INDEX_UC_DEF,
EFX_FILTER_INDEX_MC_DEF,
EFX_FILTER_SIZE_RX_DEF,
};
struct efx_filter_table { struct efx_filter_table {
enum efx_filter_table_id id; enum efx_filter_table_id id;
u32 offset; /* address of table relative to BAR */ u32 offset; /* address of table relative to BAR */
...@@ -109,7 +116,7 @@ static void efx_filter_table_reset_search_depth(struct efx_filter_table *table) ...@@ -109,7 +116,7 @@ static void efx_filter_table_reset_search_depth(struct efx_filter_table *table)
memset(table->search_depth, 0, sizeof(table->search_depth)); memset(table->search_depth, 0, sizeof(table->search_depth));
} }
static void efx_filter_push_rx_limits(struct efx_nic *efx) static void efx_filter_push_rx_config(struct efx_nic *efx)
{ {
struct efx_filter_state *state = efx->filter_state; struct efx_filter_state *state = efx->filter_state;
struct efx_filter_table *table; struct efx_filter_table *table;
...@@ -143,6 +150,32 @@ static void efx_filter_push_rx_limits(struct efx_nic *efx) ...@@ -143,6 +150,32 @@ static void efx_filter_push_rx_limits(struct efx_nic *efx)
FILTER_CTL_SRCH_FUDGE_WILD); FILTER_CTL_SRCH_FUDGE_WILD);
} }
table = &state->table[EFX_FILTER_TABLE_RX_DEF];
if (table->size) {
EFX_SET_OWORD_FIELD(
filter_ctl, FRF_CZ_UNICAST_NOMATCH_Q_ID,
table->spec[EFX_FILTER_INDEX_UC_DEF].dmaq_id);
EFX_SET_OWORD_FIELD(
filter_ctl, FRF_CZ_UNICAST_NOMATCH_RSS_ENABLED,
!!(table->spec[EFX_FILTER_INDEX_UC_DEF].flags &
EFX_FILTER_FLAG_RX_RSS));
EFX_SET_OWORD_FIELD(
filter_ctl, FRF_CZ_UNICAST_NOMATCH_IP_OVERRIDE,
!!(table->spec[EFX_FILTER_INDEX_UC_DEF].flags &
EFX_FILTER_FLAG_RX_OVERRIDE_IP));
EFX_SET_OWORD_FIELD(
filter_ctl, FRF_CZ_MULTICAST_NOMATCH_Q_ID,
table->spec[EFX_FILTER_INDEX_MC_DEF].dmaq_id);
EFX_SET_OWORD_FIELD(
filter_ctl, FRF_CZ_MULTICAST_NOMATCH_RSS_ENABLED,
!!(table->spec[EFX_FILTER_INDEX_MC_DEF].flags &
EFX_FILTER_FLAG_RX_RSS));
EFX_SET_OWORD_FIELD(
filter_ctl, FRF_CZ_MULTICAST_NOMATCH_IP_OVERRIDE,
!!(table->spec[EFX_FILTER_INDEX_MC_DEF].flags &
EFX_FILTER_FLAG_RX_OVERRIDE_IP));
}
efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL); efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
} }
...@@ -319,6 +352,52 @@ int efx_filter_set_eth_local(struct efx_filter_spec *spec, ...@@ -319,6 +352,52 @@ int efx_filter_set_eth_local(struct efx_filter_spec *spec,
return 0; return 0;
} }
/**
* efx_filter_set_uc_def - specify matching otherwise-unmatched unicast
* @spec: Specification to initialise
*/
int efx_filter_set_uc_def(struct efx_filter_spec *spec)
{
EFX_BUG_ON_PARANOID(!(spec->flags &
(EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)));
if (spec->type != EFX_FILTER_UNSPEC)
return -EINVAL;
spec->type = EFX_FILTER_UC_DEF;
memset(spec->data, 0, sizeof(spec->data)); /* ensure equality */
return 0;
}
/**
* efx_filter_set_mc_def - specify matching otherwise-unmatched multicast
* @spec: Specification to initialise
*/
int efx_filter_set_mc_def(struct efx_filter_spec *spec)
{
EFX_BUG_ON_PARANOID(!(spec->flags &
(EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)));
if (spec->type != EFX_FILTER_UNSPEC)
return -EINVAL;
spec->type = EFX_FILTER_MC_DEF;
memset(spec->data, 0, sizeof(spec->data)); /* ensure equality */
return 0;
}
static void efx_filter_reset_rx_def(struct efx_nic *efx, unsigned filter_idx)
{
struct efx_filter_state *state = efx->filter_state;
struct efx_filter_table *table = &state->table[EFX_FILTER_TABLE_RX_DEF];
struct efx_filter_spec *spec = &table->spec[filter_idx];
efx_filter_init_rx(spec, EFX_FILTER_PRI_MANUAL,
EFX_FILTER_FLAG_RX_RSS, 0);
spec->type = EFX_FILTER_UC_DEF + filter_idx;
table->used_bitmap[0] |= 1 << filter_idx;
}
int efx_filter_get_eth_local(const struct efx_filter_spec *spec, int efx_filter_get_eth_local(const struct efx_filter_spec *spec,
u16 *vid, u8 *addr) u16 *vid, u8 *addr)
{ {
...@@ -366,6 +445,13 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec) ...@@ -366,6 +445,13 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
break; break;
} }
case EFX_FILTER_TABLE_RX_DEF:
/* One filter spec per type */
BUILD_BUG_ON(EFX_FILTER_INDEX_UC_DEF != 0);
BUILD_BUG_ON(EFX_FILTER_INDEX_MC_DEF !=
EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF);
return spec->type - EFX_FILTER_UC_DEF;
case EFX_FILTER_TABLE_RX_MAC: { case EFX_FILTER_TABLE_RX_MAC: {
bool is_wild = spec->type == EFX_FILTER_MAC_WILD; bool is_wild = spec->type == EFX_FILTER_MAC_WILD;
EFX_POPULATE_OWORD_8( EFX_POPULATE_OWORD_8(
...@@ -448,23 +534,40 @@ static int efx_filter_search(struct efx_filter_table *table, ...@@ -448,23 +534,40 @@ static int efx_filter_search(struct efx_filter_table *table,
* MAC filters without overriding behaviour. * MAC filters without overriding behaviour.
*/ */
#define EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP 0
#define EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP 1
#define EFX_FILTER_MATCH_PRI_NORMAL_BASE 2
#define EFX_FILTER_INDEX_WIDTH 13 #define EFX_FILTER_INDEX_WIDTH 13
#define EFX_FILTER_INDEX_MASK ((1 << EFX_FILTER_INDEX_WIDTH) - 1) #define EFX_FILTER_INDEX_MASK ((1 << EFX_FILTER_INDEX_WIDTH) - 1)
static inline u32 efx_filter_make_id(enum efx_filter_table_id table_id, static inline u32 efx_filter_make_id(enum efx_filter_table_id table_id,
unsigned int index, u8 flags) unsigned int index, u8 flags)
{ {
return (table_id == EFX_FILTER_TABLE_RX_MAC && unsigned int match_pri = EFX_FILTER_MATCH_PRI_NORMAL_BASE + table_id;
flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP) ?
index : if (flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP) {
(table_id + 1) << EFX_FILTER_INDEX_WIDTH | index; if (table_id == EFX_FILTER_TABLE_RX_MAC)
match_pri = EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP;
else if (table_id == EFX_FILTER_TABLE_RX_DEF)
match_pri = EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP;
}
return match_pri << EFX_FILTER_INDEX_WIDTH | index;
} }
static inline enum efx_filter_table_id efx_filter_id_table_id(u32 id) static inline enum efx_filter_table_id efx_filter_id_table_id(u32 id)
{ {
return (id <= EFX_FILTER_INDEX_MASK) ? unsigned int match_pri = id >> EFX_FILTER_INDEX_WIDTH;
EFX_FILTER_TABLE_RX_MAC :
(id >> EFX_FILTER_INDEX_WIDTH) - 1; switch (match_pri) {
case EFX_FILTER_MATCH_PRI_RX_MAC_OVERRIDE_IP:
return EFX_FILTER_TABLE_RX_MAC;
case EFX_FILTER_MATCH_PRI_RX_DEF_OVERRIDE_IP:
return EFX_FILTER_TABLE_RX_DEF;
default:
return match_pri - EFX_FILTER_MATCH_PRI_NORMAL_BASE;
}
} }
static inline unsigned int efx_filter_id_index(u32 id) static inline unsigned int efx_filter_id_index(u32 id)
...@@ -474,23 +577,27 @@ static inline unsigned int efx_filter_id_index(u32 id) ...@@ -474,23 +577,27 @@ static inline unsigned int efx_filter_id_index(u32 id)
static inline u8 efx_filter_id_flags(u32 id) static inline u8 efx_filter_id_flags(u32 id)
{ {
return (id <= EFX_FILTER_INDEX_MASK) ? unsigned int match_pri = id >> EFX_FILTER_INDEX_WIDTH;
EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_OVERRIDE_IP :
EFX_FILTER_FLAG_RX; if (match_pri < EFX_FILTER_MATCH_PRI_NORMAL_BASE)
return EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_OVERRIDE_IP;
else
return EFX_FILTER_FLAG_RX;
} }
u32 efx_filter_get_rx_id_limit(struct efx_nic *efx) u32 efx_filter_get_rx_id_limit(struct efx_nic *efx)
{ {
struct efx_filter_state *state = efx->filter_state; struct efx_filter_state *state = efx->filter_state;
unsigned int table_id = EFX_FILTER_TABLE_RX_DEF;
if (state->table[EFX_FILTER_TABLE_RX_MAC].size != 0) do {
return ((EFX_FILTER_TABLE_RX_MAC + 1) << EFX_FILTER_INDEX_WIDTH) if (state->table[table_id].size != 0)
+ state->table[EFX_FILTER_TABLE_RX_MAC].size; return ((EFX_FILTER_MATCH_PRI_NORMAL_BASE + table_id)
else if (state->table[EFX_FILTER_TABLE_RX_IP].size != 0) << EFX_FILTER_INDEX_WIDTH) +
return ((EFX_FILTER_TABLE_RX_IP + 1) << EFX_FILTER_INDEX_WIDTH) state->table[table_id].size;
+ state->table[EFX_FILTER_TABLE_RX_IP].size; } while (table_id--);
else
return 0; return 0;
} }
/** /**
...@@ -548,12 +655,17 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec, ...@@ -548,12 +655,17 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
} }
*saved_spec = *spec; *saved_spec = *spec;
if (table->search_depth[spec->type] < depth) { if (table->id == EFX_FILTER_TABLE_RX_DEF) {
table->search_depth[spec->type] = depth; efx_filter_push_rx_config(efx);
efx_filter_push_rx_limits(efx); } else {
} if (table->search_depth[spec->type] < depth) {
table->search_depth[spec->type] = depth;
efx_filter_push_rx_config(efx);
}
efx_writeo(efx, &filter, table->offset + table->step * filter_idx); efx_writeo(efx, &filter,
table->offset + table->step * filter_idx);
}
netif_vdbg(efx, hw, efx->net_dev, netif_vdbg(efx, hw, efx->net_dev,
"%s: filter type %d index %d rxq %u set", "%s: filter type %d index %d rxq %u set",
...@@ -571,7 +683,11 @@ static void efx_filter_table_clear_entry(struct efx_nic *efx, ...@@ -571,7 +683,11 @@ static void efx_filter_table_clear_entry(struct efx_nic *efx,
{ {
static efx_oword_t filter; static efx_oword_t filter;
if (test_bit(filter_idx, table->used_bitmap)) { if (table->id == EFX_FILTER_TABLE_RX_DEF) {
/* RX default filters must always exist */
efx_filter_reset_rx_def(efx, filter_idx);
efx_filter_push_rx_config(efx);
} else if (test_bit(filter_idx, table->used_bitmap)) {
__clear_bit(filter_idx, table->used_bitmap); __clear_bit(filter_idx, table->used_bitmap);
--table->used; --table->used;
memset(&table->spec[filter_idx], 0, sizeof(table->spec[0])); memset(&table->spec[filter_idx], 0, sizeof(table->spec[0]));
...@@ -617,7 +733,8 @@ int efx_filter_remove_id_safe(struct efx_nic *efx, ...@@ -617,7 +733,8 @@ int efx_filter_remove_id_safe(struct efx_nic *efx,
spin_lock_bh(&state->lock); spin_lock_bh(&state->lock);
if (test_bit(filter_idx, table->used_bitmap) && if (test_bit(filter_idx, table->used_bitmap) &&
spec->priority == priority && spec->flags == filter_flags) { spec->priority == priority &&
!((spec->flags ^ filter_flags) & EFX_FILTER_FLAG_RX_OVERRIDE_IP)) {
efx_filter_table_clear_entry(efx, table, filter_idx); efx_filter_table_clear_entry(efx, table, filter_idx);
if (table->used == 0) if (table->used == 0)
efx_filter_table_reset_search_depth(table); efx_filter_table_reset_search_depth(table);
...@@ -668,7 +785,8 @@ int efx_filter_get_filter_safe(struct efx_nic *efx, ...@@ -668,7 +785,8 @@ int efx_filter_get_filter_safe(struct efx_nic *efx,
spin_lock_bh(&state->lock); spin_lock_bh(&state->lock);
if (test_bit(filter_idx, table->used_bitmap) && if (test_bit(filter_idx, table->used_bitmap) &&
spec->priority == priority && spec->flags == filter_flags) { spec->priority == priority &&
!((spec->flags ^ filter_flags) & EFX_FILTER_FLAG_RX_OVERRIDE_IP)) {
*spec_buf = *spec; *spec_buf = *spec;
rc = 0; rc = 0;
} else { } else {
...@@ -722,7 +840,7 @@ u32 efx_filter_count_rx_used(struct efx_nic *efx, ...@@ -722,7 +840,7 @@ u32 efx_filter_count_rx_used(struct efx_nic *efx,
spin_lock_bh(&state->lock); spin_lock_bh(&state->lock);
for (table_id = EFX_FILTER_TABLE_RX_IP; for (table_id = EFX_FILTER_TABLE_RX_IP;
table_id <= EFX_FILTER_TABLE_RX_MAC; table_id <= EFX_FILTER_TABLE_RX_DEF;
table_id++) { table_id++) {
table = &state->table[table_id]; table = &state->table[table_id];
for (filter_idx = 0; filter_idx < table->size; filter_idx++) { for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
...@@ -750,7 +868,7 @@ s32 efx_filter_get_rx_ids(struct efx_nic *efx, ...@@ -750,7 +868,7 @@ s32 efx_filter_get_rx_ids(struct efx_nic *efx,
spin_lock_bh(&state->lock); spin_lock_bh(&state->lock);
for (table_id = EFX_FILTER_TABLE_RX_IP; for (table_id = EFX_FILTER_TABLE_RX_IP;
table_id <= EFX_FILTER_TABLE_RX_MAC; table_id <= EFX_FILTER_TABLE_RX_DEF;
table_id++) { table_id++) {
table = &state->table[table_id]; table = &state->table[table_id];
for (filter_idx = 0; filter_idx < table->size; filter_idx++) { for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
...@@ -785,6 +903,11 @@ void efx_restore_filters(struct efx_nic *efx) ...@@ -785,6 +903,11 @@ void efx_restore_filters(struct efx_nic *efx)
for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) { for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
table = &state->table[table_id]; table = &state->table[table_id];
/* Check whether this is a regular register table */
if (table->step == 0)
continue;
for (filter_idx = 0; filter_idx < table->size; filter_idx++) { for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
if (!test_bit(filter_idx, table->used_bitmap)) if (!test_bit(filter_idx, table->used_bitmap))
continue; continue;
...@@ -794,7 +917,7 @@ void efx_restore_filters(struct efx_nic *efx) ...@@ -794,7 +917,7 @@ void efx_restore_filters(struct efx_nic *efx)
} }
} }
efx_filter_push_rx_limits(efx); efx_filter_push_rx_config(efx);
spin_unlock_bh(&state->lock); spin_unlock_bh(&state->lock);
} }
...@@ -833,6 +956,10 @@ int efx_probe_filters(struct efx_nic *efx) ...@@ -833,6 +956,10 @@ int efx_probe_filters(struct efx_nic *efx)
table->offset = FR_CZ_RX_MAC_FILTER_TBL0; table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS; table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP; table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP;
table = &state->table[EFX_FILTER_TABLE_RX_DEF];
table->id = EFX_FILTER_TABLE_RX_DEF;
table->size = EFX_FILTER_SIZE_RX_DEF;
} }
for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) { for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
...@@ -849,6 +976,15 @@ int efx_probe_filters(struct efx_nic *efx) ...@@ -849,6 +976,15 @@ int efx_probe_filters(struct efx_nic *efx)
goto fail; goto fail;
} }
if (state->table[EFX_FILTER_TABLE_RX_DEF].size) {
/* RX default filters must always exist */
unsigned i;
for (i = 0; i < EFX_FILTER_SIZE_RX_DEF; i++)
efx_filter_reset_rx_def(efx, i);
}
efx_filter_push_rx_config(efx);
return 0; return 0;
fail: fail:
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
* @EFX_FILTER_UDP_WILD: Matching UDP/IPv4 destination (host, port) * @EFX_FILTER_UDP_WILD: Matching UDP/IPv4 destination (host, port)
* @EFX_FILTER_MAC_FULL: Matching Ethernet destination MAC address, VID * @EFX_FILTER_MAC_FULL: Matching Ethernet destination MAC address, VID
* @EFX_FILTER_MAC_WILD: Matching Ethernet destination MAC address * @EFX_FILTER_MAC_WILD: Matching Ethernet destination MAC address
* @EFX_FILTER_UC_DEF: Matching all otherwise unmatched unicast
* @EFX_FILTER_MC_DEF: Matching all otherwise unmatched multicast
* @EFX_FILTER_UNSPEC: Match type is unspecified * @EFX_FILTER_UNSPEC: Match type is unspecified
* *
* Falcon NICs only support the TCP/IPv4 and UDP/IPv4 filter types. * Falcon NICs only support the TCP/IPv4 and UDP/IPv4 filter types.
...@@ -31,6 +33,8 @@ enum efx_filter_type { ...@@ -31,6 +33,8 @@ enum efx_filter_type {
EFX_FILTER_UDP_WILD, EFX_FILTER_UDP_WILD,
EFX_FILTER_MAC_FULL = 4, EFX_FILTER_MAC_FULL = 4,
EFX_FILTER_MAC_WILD, EFX_FILTER_MAC_WILD,
EFX_FILTER_UC_DEF = 8,
EFX_FILTER_MC_DEF,
EFX_FILTER_TYPE_COUNT, /* number of specific types */ EFX_FILTER_TYPE_COUNT, /* number of specific types */
EFX_FILTER_UNSPEC = 0xf, EFX_FILTER_UNSPEC = 0xf,
}; };
...@@ -117,6 +121,8 @@ extern int efx_filter_set_eth_local(struct efx_filter_spec *spec, ...@@ -117,6 +121,8 @@ extern int efx_filter_set_eth_local(struct efx_filter_spec *spec,
u16 vid, const u8 *addr); u16 vid, const u8 *addr);
extern int efx_filter_get_eth_local(const struct efx_filter_spec *spec, extern int efx_filter_get_eth_local(const struct efx_filter_spec *spec,
u16 *vid, u8 *addr); u16 *vid, u8 *addr);
extern int efx_filter_set_uc_def(struct efx_filter_spec *spec);
extern int efx_filter_set_mc_def(struct efx_filter_spec *spec);
enum { enum {
EFX_FILTER_VID_UNSPEC = 0xffff, EFX_FILTER_VID_UNSPEC = 0xffff,
}; };
......
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