[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1377636581.13272.86.camel@bwh-desktop.uk.level5networks.com>
Date: Tue, 27 Aug 2013 21:49:41 +0100
From: Ben Hutchings <bhutchings@...arflare.com>
To: David Miller <davem@...emloft.net>
CC: <netdev@...r.kernel.org>, <linux-net-drivers@...arflare.com>
Subject: [PATCH net-next 12/16] 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@...arflare.com>
---
drivers/net/ethernet/sfc/farch.c | 47 +++++++++++++++++++++++++--------------
drivers/net/ethernet/sfc/filter.h | 7 ++++++
2 files changed, 37 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index d91bced..1e21e51 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -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);
diff --git a/drivers/net/ethernet/sfc/filter.h b/drivers/net/ethernet/sfc/filter.h
index 1b410de..e459e43 100644
--- a/drivers/net/ethernet/sfc/filter.h
+++ b/drivers/net/ethernet/sfc/filter.h
@@ -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,
};
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists