mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 04:34:11 +08:00
sfc: Add flag for stack-owned RX MAC filters
MAC filters inserted on request from the stack (ndo_set_rx_mode) should allow manual steering but not removal. Currently we have a special case for Siena's all-multicast and all-unicast MAC filters, but on EF10 we need to allow for steering of precise MAC filters as well. The EFX_FILTER_FLAG_RX_STACK flag changes the behaviour of replacement and removal requests: - Replacement *of* a filter with this flag never clears the flag but does change steering and saved priority - Replacement *by* a filter with this flag only sets the flag but does not change steering - Removal with priority < EFX_FILTER_PRI_REQUIRED really resets RX steering and saved priority This could support precise MAC filtering on Siena in future. As a side-benefit, the default MAC filters are hidden from ethtool until they are steered. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
This commit is contained in:
parent
14990a5d66
commit
8803e15042
@ -2186,23 +2186,17 @@ efx_farch_filter_to_gen_spec(struct efx_filter_spec *gen_spec,
|
||||
}
|
||||
|
||||
static void
|
||||
efx_farch_filter_reset_rx_def(struct efx_nic *efx, unsigned filter_idx)
|
||||
efx_farch_filter_init_rx_for_stack(struct efx_nic *efx,
|
||||
struct efx_farch_filter_spec *spec)
|
||||
{
|
||||
struct efx_farch_filter_state *state = efx->filter_state;
|
||||
struct efx_farch_filter_table *table =
|
||||
&state->table[EFX_FARCH_FILTER_TABLE_RX_DEF];
|
||||
struct efx_farch_filter_spec *spec = &table->spec[filter_idx];
|
||||
|
||||
/* If there's only one channel then disable RSS for non VF
|
||||
* traffic, thereby allowing VFs to use RSS when the PF can't.
|
||||
*/
|
||||
spec->type = EFX_FARCH_FILTER_UC_DEF + filter_idx;
|
||||
spec->priority = EFX_FILTER_PRI_MANUAL;
|
||||
spec->flags = (EFX_FILTER_FLAG_RX |
|
||||
spec->priority = EFX_FILTER_PRI_REQUIRED;
|
||||
spec->flags = (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_STACK |
|
||||
(efx->n_rx_channels > 1 ? EFX_FILTER_FLAG_RX_RSS : 0) |
|
||||
(efx->rx_scatter ? EFX_FILTER_FLAG_RX_SCATTER : 0));
|
||||
spec->dmaq_id = 0;
|
||||
table->used_bitmap[0] |= 1 << filter_idx;
|
||||
}
|
||||
|
||||
/* Build a filter entry and return its n-tuple key. */
|
||||
@ -2464,10 +2458,20 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
|
||||
rc = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
if (spec.priority < saved_spec->priority) {
|
||||
if (spec.priority < saved_spec->priority &&
|
||||
!(saved_spec->priority == EFX_FILTER_PRI_REQUIRED &&
|
||||
saved_spec->flags & EFX_FILTER_FLAG_RX_STACK)) {
|
||||
rc = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
if (spec.flags & EFX_FILTER_FLAG_RX_STACK) {
|
||||
/* Just make sure it won't be removed */
|
||||
saved_spec->flags |= EFX_FILTER_FLAG_RX_STACK;
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
/* Retain the RX_STACK flag */
|
||||
spec.flags |= saved_spec->flags & EFX_FILTER_FLAG_RX_STACK;
|
||||
}
|
||||
|
||||
/* Insert the filter */
|
||||
@ -2517,6 +2521,7 @@ efx_farch_filter_table_clear_entry(struct efx_nic *efx,
|
||||
static efx_oword_t filter;
|
||||
|
||||
EFX_WARN_ON_PARANOID(!test_bit(filter_idx, table->used_bitmap));
|
||||
BUG_ON(table->offset == 0); /* can't clear MAC default filters */
|
||||
|
||||
__clear_bit(filter_idx, table->used_bitmap);
|
||||
--table->used;
|
||||
@ -2550,9 +2555,8 @@ static int efx_farch_filter_remove(struct efx_nic *efx,
|
||||
spec->priority > priority)
|
||||
return -ENOENT;
|
||||
|
||||
if (table->id == EFX_FARCH_FILTER_TABLE_RX_DEF) {
|
||||
/* RX default filters must always exist */
|
||||
efx_farch_filter_reset_rx_def(efx, filter_idx);
|
||||
if (spec->flags & EFX_FILTER_FLAG_RX_STACK) {
|
||||
efx_farch_filter_init_rx_for_stack(efx, spec);
|
||||
efx_farch_filter_push_rx_config(efx);
|
||||
} else {
|
||||
efx_farch_filter_table_clear_entry(efx, table, filter_idx);
|
||||
@ -2647,6 +2651,8 @@ void efx_farch_filter_clear_rx(struct efx_nic *efx,
|
||||
priority);
|
||||
efx_farch_filter_table_clear(efx, EFX_FARCH_FILTER_TABLE_RX_MAC,
|
||||
priority);
|
||||
efx_farch_filter_table_clear(efx, EFX_FARCH_FILTER_TABLE_RX_DEF,
|
||||
priority);
|
||||
}
|
||||
|
||||
u32 efx_farch_filter_count_rx_used(struct efx_nic *efx,
|
||||
@ -2806,11 +2812,18 @@ int efx_farch_filter_table_probe(struct efx_nic *efx)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (state->table[EFX_FARCH_FILTER_TABLE_RX_DEF].size) {
|
||||
table = &state->table[EFX_FARCH_FILTER_TABLE_RX_DEF];
|
||||
if (table->size) {
|
||||
/* RX default filters must always exist */
|
||||
struct efx_farch_filter_spec *spec;
|
||||
unsigned i;
|
||||
for (i = 0; i < EFX_FARCH_FILTER_SIZE_RX_DEF; i++)
|
||||
efx_farch_filter_reset_rx_def(efx, i);
|
||||
|
||||
for (i = 0; i < EFX_FARCH_FILTER_SIZE_RX_DEF; i++) {
|
||||
spec = &table->spec[i];
|
||||
spec->type = EFX_FARCH_FILTER_UC_DEF + i;
|
||||
efx_farch_filter_init_rx_for_stack(efx, spec);
|
||||
__set_bit(i, table->used_bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
efx_farch_filter_push_rx_config(efx);
|
||||
|
@ -78,12 +78,19 @@ enum efx_filter_priority {
|
||||
* according to the indirection table.
|
||||
* @EFX_FILTER_FLAG_RX_SCATTER: Enable DMA scatter on the receiving
|
||||
* queue.
|
||||
* @EFX_FILTER_FLAG_RX_STACK: Indicates a filter inserted for the
|
||||
* network stack. The filter must have a priority of
|
||||
* %EFX_FILTER_PRI_REQUIRED. It can be steered by a replacement
|
||||
* request with priority %EFX_FILTER_PRI_MANUAL, and a removal
|
||||
* request with priority %EFX_FILTER_PRI_MANUAL will reset the
|
||||
* steering (but not remove the filter).
|
||||
* @EFX_FILTER_FLAG_RX: Filter is for RX
|
||||
* @EFX_FILTER_FLAG_TX: Filter is for TX
|
||||
*/
|
||||
enum efx_filter_flags {
|
||||
EFX_FILTER_FLAG_RX_RSS = 0x01,
|
||||
EFX_FILTER_FLAG_RX_SCATTER = 0x02,
|
||||
EFX_FILTER_FLAG_RX_STACK = 0x04,
|
||||
EFX_FILTER_FLAG_RX = 0x08,
|
||||
EFX_FILTER_FLAG_TX = 0x10,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user