diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2013-01-15 01:23:15 +0400 |
---|---|---|
committer | Ben Hutchings <bhutchings@solarflare.com> | 2013-03-08 00:22:00 +0400 |
commit | 385904f819e31fcf5a5aa53fa91f3352bffa6d19 (patch) | |
tree | 92edabc7a7ce6e22d5bb61f4b185de1dfea9402b /drivers/net/ethernet/sfc | |
parent | e3a699fab34a724fa8693c1274d3ddb3e213a134 (diff) | |
download | linux-385904f819e31fcf5a5aa53fa91f3352bffa6d19.tar.xz |
sfc: Don't use efx_filter_{build,hash,increment}() for default MAC filters
These functions happen to work for default MAC filters: they generate
an initial index of 1/0 for unicast/multicast respectively and an
increment of 1 for either, so a search succeeds at depth 2. But this
is a matter of luck rather than design, and it really won't work well
with the bug fix we're about to do.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r-- | drivers/net/ethernet/sfc/filter.c | 35 |
1 files changed, 19 insertions, 16 deletions
diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c index 3d94ed73c65e..8d83d9832b21 100644 --- a/drivers/net/ethernet/sfc/filter.c +++ b/drivers/net/ethernet/sfc/filter.c @@ -463,13 +463,6 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec) 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: { bool is_wild = spec->type == EFX_FILTER_MAC_WILD; EFX_POPULATE_OWORD_7( @@ -667,25 +660,35 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec, struct efx_filter_spec *saved_spec; efx_oword_t filter; unsigned int filter_idx, depth = 0; - u32 key; int rc; if (!table || table->size == 0) return -EINVAL; - key = efx_filter_build(&filter, spec); - netif_vdbg(efx, hw, efx->net_dev, "%s: type %d search_depth=%d", __func__, spec->type, table->search_depth[spec->type]); - spin_lock_bh(&state->lock); + if (table->id == 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); + filter_idx = spec->type - EFX_FILTER_INDEX_UC_DEF; + + spin_lock_bh(&state->lock); + } else { + u32 key = efx_filter_build(&filter, spec); + + spin_lock_bh(&state->lock); + + rc = efx_filter_search(table, spec, key, &depth); + if (rc < 0) + goto out; + filter_idx = rc; + BUG_ON(filter_idx >= table->size); + } - rc = efx_filter_search(table, spec, key, &depth); - if (rc < 0) - goto out; - filter_idx = rc; - BUG_ON(filter_idx >= table->size); saved_spec = &table->spec[filter_idx]; if (test_bit(filter_idx, table->used_bitmap)) { |