sfc: Rename Falcon-arch filter implementation types and functions

The filter table(s) on EF10 are managed by firmware and will need
almost entirely separate code.  Rename the types and functions used
within the existing implementation.  The current definition of struct
efx_filter_spec is really implementation-specific, so we need to keep
it.  For now, define a separate structure for the internal
representation but leave them identical.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
This commit is contained in:
Ben Hutchings 2012-10-26 23:55:46 +01:00
parent 910c485dc1
commit 33a8985c4a
1 changed files with 242 additions and 208 deletions

View File

@ -19,60 +19,69 @@
* Due to pipelined implementation we need to program H/W with a value that
* is larger than the hop limit we want.
*/
#define FILTER_CTL_SRCH_FUDGE_WILD 3
#define FILTER_CTL_SRCH_FUDGE_FULL 1
#define EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD 3
#define EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL 1
/* Hard maximum hop limit. Hardware will time-out beyond 200-something.
* We also need to avoid infinite loops in efx_filter_search() when the
* We also need to avoid infinite loops in efx_farch_filter_search() when the
* table is full.
*/
#define FILTER_CTL_SRCH_MAX 200
#define EFX_FARCH_FILTER_CTL_SRCH_MAX 200
/* Don't try very hard to find space for performance hints, as this is
* counter-productive. */
#define FILTER_CTL_SRCH_HINT_MAX 5
#define EFX_FARCH_FILTER_CTL_SRCH_HINT_MAX 5
enum efx_filter_table_id {
EFX_FILTER_TABLE_RX_IP = 0,
EFX_FILTER_TABLE_RX_MAC,
EFX_FILTER_TABLE_RX_DEF,
EFX_FILTER_TABLE_TX_MAC,
EFX_FILTER_TABLE_COUNT,
enum efx_farch_filter_table_id {
EFX_FARCH_FILTER_TABLE_RX_IP = 0,
EFX_FARCH_FILTER_TABLE_RX_MAC,
EFX_FARCH_FILTER_TABLE_RX_DEF,
EFX_FARCH_FILTER_TABLE_TX_MAC,
EFX_FARCH_FILTER_TABLE_COUNT,
};
enum efx_filter_index {
EFX_FILTER_INDEX_UC_DEF,
EFX_FILTER_INDEX_MC_DEF,
EFX_FILTER_SIZE_RX_DEF,
enum efx_farch_filter_index {
EFX_FARCH_FILTER_INDEX_UC_DEF,
EFX_FARCH_FILTER_INDEX_MC_DEF,
EFX_FARCH_FILTER_SIZE_RX_DEF,
};
struct efx_filter_table {
enum efx_filter_table_id id;
struct efx_farch_filter_spec {
u8 type:4;
u8 priority:4;
u8 flags;
u16 dmaq_id;
u32 data[3];
};
struct efx_farch_filter_table {
enum efx_farch_filter_table_id id;
u32 offset; /* address of table relative to BAR */
unsigned size; /* number of entries */
unsigned step; /* step between entries */
unsigned used; /* number currently used */
unsigned long *used_bitmap;
struct efx_filter_spec *spec;
struct efx_farch_filter_spec *spec;
unsigned search_depth[EFX_FILTER_TYPE_COUNT];
};
struct efx_filter_state {
spinlock_t lock;
struct efx_filter_table table[EFX_FILTER_TABLE_COUNT];
struct efx_farch_filter_table table[EFX_FARCH_FILTER_TABLE_COUNT];
#ifdef CONFIG_RFS_ACCEL
u32 *rps_flow_id;
unsigned rps_expire_index;
#endif
};
static void efx_filter_table_clear_entry(struct efx_nic *efx,
struct efx_filter_table *table,
unsigned int filter_idx);
static void
efx_farch_filter_table_clear_entry(struct efx_nic *efx,
struct efx_farch_filter_table *table,
unsigned int filter_idx);
/* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
* key derived from the n-tuple. The initial LFSR state is 0xffff. */
static u16 efx_filter_hash(u32 key)
static u16 efx_farch_filter_hash(u32 key)
{
u16 tmp;
@ -88,89 +97,97 @@ static u16 efx_filter_hash(u32 key)
/* To allow for hash collisions, filter search continues at these
* increments from the first possible entry selected by the hash. */
static u16 efx_filter_increment(u32 key)
static u16 efx_farch_filter_increment(u32 key)
{
return key * 2 - 1;
}
static enum efx_filter_table_id
efx_filter_spec_table_id(const struct efx_filter_spec *spec)
static enum efx_farch_filter_table_id
efx_farch_filter_spec_table_id(const struct efx_farch_filter_spec *spec)
{
BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_TCP_FULL >> 2));
BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_TCP_WILD >> 2));
BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_UDP_FULL >> 2));
BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_UDP_WILD >> 2));
BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_MAC_FULL >> 2));
BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_MAC_WILD >> 2));
BUILD_BUG_ON(EFX_FILTER_TABLE_TX_MAC != EFX_FILTER_TABLE_RX_MAC + 2);
BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP !=
(EFX_FILTER_TCP_FULL >> 2));
BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP !=
(EFX_FILTER_TCP_WILD >> 2));
BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP !=
(EFX_FILTER_UDP_FULL >> 2));
BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP !=
(EFX_FILTER_UDP_WILD >> 2));
BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_MAC !=
(EFX_FILTER_MAC_FULL >> 2));
BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_MAC !=
(EFX_FILTER_MAC_WILD >> 2));
BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_TX_MAC !=
EFX_FARCH_FILTER_TABLE_RX_MAC + 2);
EFX_BUG_ON_PARANOID(spec->type == EFX_FILTER_UNSPEC);
return (spec->type >> 2) + ((spec->flags & EFX_FILTER_FLAG_TX) ? 2 : 0);
}
static struct efx_filter_table *
efx_filter_spec_table(struct efx_filter_state *state,
const struct efx_filter_spec *spec)
static struct efx_farch_filter_table *
efx_farch_filter_spec_table(struct efx_filter_state *state,
const struct efx_farch_filter_spec *spec)
{
if (spec->type == EFX_FILTER_UNSPEC)
return NULL;
else
return &state->table[efx_filter_spec_table_id(spec)];
return &state->table[efx_farch_filter_spec_table_id(spec)];
}
static void efx_filter_table_reset_search_depth(struct efx_filter_table *table)
static void
efx_farch_filter_table_reset_search_depth(struct efx_farch_filter_table *table)
{
memset(table->search_depth, 0, sizeof(table->search_depth));
}
static void efx_filter_push_rx_config(struct efx_nic *efx)
static void efx_farch_filter_push_rx_config(struct efx_nic *efx)
{
struct efx_filter_state *state = efx->filter_state;
struct efx_filter_table *table;
struct efx_farch_filter_table *table;
efx_oword_t filter_ctl;
efx_reado(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
table = &state->table[EFX_FILTER_TABLE_RX_IP];
table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT,
table->search_depth[EFX_FILTER_TCP_FULL] +
FILTER_CTL_SRCH_FUDGE_FULL);
EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT,
table->search_depth[EFX_FILTER_TCP_WILD] +
FILTER_CTL_SRCH_FUDGE_WILD);
EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT,
table->search_depth[EFX_FILTER_UDP_FULL] +
FILTER_CTL_SRCH_FUDGE_FULL);
EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT,
table->search_depth[EFX_FILTER_UDP_WILD] +
FILTER_CTL_SRCH_FUDGE_WILD);
EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
table = &state->table[EFX_FILTER_TABLE_RX_MAC];
table = &state->table[EFX_FARCH_FILTER_TABLE_RX_MAC];
if (table->size) {
EFX_SET_OWORD_FIELD(
filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
table->search_depth[EFX_FILTER_MAC_FULL] +
FILTER_CTL_SRCH_FUDGE_FULL);
EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
EFX_SET_OWORD_FIELD(
filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
table->search_depth[EFX_FILTER_MAC_WILD] +
FILTER_CTL_SRCH_FUDGE_WILD);
EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
}
table = &state->table[EFX_FILTER_TABLE_RX_DEF];
table = &state->table[EFX_FARCH_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);
table->spec[EFX_FARCH_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 &
!!(table->spec[EFX_FARCH_FILTER_INDEX_UC_DEF].flags &
EFX_FILTER_FLAG_RX_RSS));
EFX_SET_OWORD_FIELD(
filter_ctl, FRF_CZ_MULTICAST_NOMATCH_Q_ID,
table->spec[EFX_FILTER_INDEX_MC_DEF].dmaq_id);
table->spec[EFX_FARCH_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 &
!!(table->spec[EFX_FARCH_FILTER_INDEX_MC_DEF].flags &
EFX_FILTER_FLAG_RX_RSS));
/* There is a single bit to enable RX scatter for all
@ -179,8 +196,8 @@ static void efx_filter_push_rx_config(struct efx_nic *efx)
*/
EFX_SET_OWORD_FIELD(
filter_ctl, FRF_BZ_SCATTER_ENBL_NO_MATCH_Q,
!!(table->spec[EFX_FILTER_INDEX_UC_DEF].flags &
table->spec[EFX_FILTER_INDEX_MC_DEF].flags &
!!(table->spec[EFX_FARCH_FILTER_INDEX_UC_DEF].flags &
table->spec[EFX_FARCH_FILTER_INDEX_MC_DEF].flags &
EFX_FILTER_FLAG_RX_SCATTER));
} else if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
/* We don't expose 'default' filters because unmatched
@ -196,24 +213,24 @@ static void efx_filter_push_rx_config(struct efx_nic *efx)
efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
}
static void efx_filter_push_tx_limits(struct efx_nic *efx)
static void efx_farch_filter_push_tx_limits(struct efx_nic *efx)
{
struct efx_filter_state *state = efx->filter_state;
struct efx_filter_table *table;
struct efx_farch_filter_table *table;
efx_oword_t tx_cfg;
efx_reado(efx, &tx_cfg, FR_AZ_TX_CFG);
table = &state->table[EFX_FILTER_TABLE_TX_MAC];
table = &state->table[EFX_FARCH_FILTER_TABLE_TX_MAC];
if (table->size) {
EFX_SET_OWORD_FIELD(
tx_cfg, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
table->search_depth[EFX_FILTER_MAC_FULL] +
FILTER_CTL_SRCH_FUDGE_FULL);
EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
EFX_SET_OWORD_FIELD(
tx_cfg, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
table->search_depth[EFX_FILTER_MAC_WILD] +
FILTER_CTL_SRCH_FUDGE_WILD);
EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
}
efx_writeo(efx, &tx_cfg, FR_AZ_TX_CFG);
@ -427,24 +444,23 @@ int efx_filter_set_mc_def(struct efx_filter_spec *spec)
return 0;
}
static void efx_filter_reset_rx_def(struct efx_nic *efx, unsigned filter_idx)
static void
efx_farch_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];
enum efx_filter_flags flags = 0;
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.
*/
if (efx->n_rx_channels > 1)
flags |= EFX_FILTER_FLAG_RX_RSS;
if (efx->rx_scatter)
flags |= EFX_FILTER_FLAG_RX_SCATTER;
efx_filter_init_rx(spec, EFX_FILTER_PRI_MANUAL, flags, 0);
spec->type = EFX_FILTER_UC_DEF + filter_idx;
spec->priority = EFX_FILTER_PRI_MANUAL;
spec->flags = (EFX_FILTER_FLAG_RX |
(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;
}
@ -472,12 +488,13 @@ int efx_filter_get_eth_local(const struct efx_filter_spec *spec,
}
/* Build a filter entry and return its n-tuple key. */
static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
static u32 efx_farch_filter_build(efx_oword_t *filter,
struct efx_farch_filter_spec *spec)
{
u32 data3;
switch (efx_filter_spec_table_id(spec)) {
case EFX_FILTER_TABLE_RX_IP: {
switch (efx_farch_filter_spec_table_id(spec)) {
case EFX_FARCH_FILTER_TABLE_RX_IP: {
bool is_udp = (spec->type == EFX_FILTER_UDP_FULL ||
spec->type == EFX_FILTER_UDP_WILD);
EFX_POPULATE_OWORD_7(
@ -495,7 +512,7 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
break;
}
case EFX_FILTER_TABLE_RX_MAC: {
case EFX_FARCH_FILTER_TABLE_RX_MAC: {
bool is_wild = spec->type == EFX_FILTER_MAC_WILD;
EFX_POPULATE_OWORD_7(
*filter,
@ -512,7 +529,7 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
break;
}
case EFX_FILTER_TABLE_TX_MAC: {
case EFX_FARCH_FILTER_TABLE_TX_MAC: {
bool is_wild = spec->type == EFX_FILTER_MAC_WILD;
EFX_POPULATE_OWORD_5(*filter,
FRF_CZ_TMFT_TXQ_ID, spec->dmaq_id,
@ -531,8 +548,8 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
return spec->data[0] ^ spec->data[1] ^ spec->data[2] ^ data3;
}
static bool efx_filter_equal(const struct efx_filter_spec *left,
const struct efx_filter_spec *right)
static bool efx_farch_filter_equal(const struct efx_farch_filter_spec *left,
const struct efx_farch_filter_spec *right)
{
if (left->type != right->type ||
memcmp(left->data, right->data, sizeof(left->data)))
@ -554,9 +571,9 @@ static bool efx_filter_equal(const struct efx_filter_spec *left,
* accept user-provided IDs.
*/
#define EFX_FILTER_MATCH_PRI_COUNT 5
#define EFX_FARCH_FILTER_MATCH_PRI_COUNT 5
static const u8 efx_filter_type_match_pri[EFX_FILTER_TYPE_COUNT] = {
static const u8 efx_farch_filter_type_match_pri[EFX_FILTER_TYPE_COUNT] = {
[EFX_FILTER_TCP_FULL] = 0,
[EFX_FILTER_UDP_FULL] = 0,
[EFX_FILTER_TCP_WILD] = 1,
@ -567,58 +584,58 @@ static const u8 efx_filter_type_match_pri[EFX_FILTER_TYPE_COUNT] = {
[EFX_FILTER_MC_DEF] = 4,
};
static const enum efx_filter_table_id efx_filter_range_table[] = {
EFX_FILTER_TABLE_RX_IP, /* RX match pri 0 */
EFX_FILTER_TABLE_RX_IP,
EFX_FILTER_TABLE_RX_MAC,
EFX_FILTER_TABLE_RX_MAC,
EFX_FILTER_TABLE_RX_DEF, /* RX match pri 4 */
EFX_FILTER_TABLE_COUNT, /* TX match pri 0; invalid */
EFX_FILTER_TABLE_COUNT, /* invalid */
EFX_FILTER_TABLE_TX_MAC,
EFX_FILTER_TABLE_TX_MAC, /* TX match pri 3 */
static const enum efx_farch_filter_table_id efx_farch_filter_range_table[] = {
EFX_FARCH_FILTER_TABLE_RX_IP, /* RX match pri 0 */
EFX_FARCH_FILTER_TABLE_RX_IP,
EFX_FARCH_FILTER_TABLE_RX_MAC,
EFX_FARCH_FILTER_TABLE_RX_MAC,
EFX_FARCH_FILTER_TABLE_RX_DEF, /* RX match pri 4 */
EFX_FARCH_FILTER_TABLE_TX_MAC, /* TX match pri 0 */
EFX_FARCH_FILTER_TABLE_TX_MAC, /* TX match pri 1 */
};
#define EFX_FILTER_INDEX_WIDTH 13
#define EFX_FILTER_INDEX_MASK ((1 << EFX_FILTER_INDEX_WIDTH) - 1)
#define EFX_FARCH_FILTER_INDEX_WIDTH 13
#define EFX_FARCH_FILTER_INDEX_MASK ((1 << EFX_FARCH_FILTER_INDEX_WIDTH) - 1)
static inline u32
efx_filter_make_id(const struct efx_filter_spec *spec, unsigned int index)
efx_farch_filter_make_id(const struct efx_farch_filter_spec *spec,
unsigned int index)
{
unsigned int range;
range = efx_filter_type_match_pri[spec->type];
range = efx_farch_filter_type_match_pri[spec->type];
if (!(spec->flags & EFX_FILTER_FLAG_RX))
range += EFX_FILTER_MATCH_PRI_COUNT;
range += EFX_FARCH_FILTER_MATCH_PRI_COUNT;
return range << EFX_FILTER_INDEX_WIDTH | index;
return range << EFX_FARCH_FILTER_INDEX_WIDTH | index;
}
static inline enum efx_filter_table_id efx_filter_id_table_id(u32 id)
static inline enum efx_farch_filter_table_id
efx_farch_filter_id_table_id(u32 id)
{
unsigned int range = id >> EFX_FILTER_INDEX_WIDTH;
unsigned int range = id >> EFX_FARCH_FILTER_INDEX_WIDTH;
if (range < ARRAY_SIZE(efx_filter_range_table))
return efx_filter_range_table[range];
if (range < ARRAY_SIZE(efx_farch_filter_range_table))
return efx_farch_filter_range_table[range];
else
return EFX_FILTER_TABLE_COUNT; /* invalid */
return EFX_FARCH_FILTER_TABLE_COUNT; /* invalid */
}
static inline unsigned int efx_filter_id_index(u32 id)
static inline unsigned int efx_farch_filter_id_index(u32 id)
{
return id & EFX_FILTER_INDEX_MASK;
return id & EFX_FARCH_FILTER_INDEX_MASK;
}
u32 efx_filter_get_rx_id_limit(struct efx_nic *efx)
{
struct efx_filter_state *state = efx->filter_state;
unsigned int range = EFX_FILTER_MATCH_PRI_COUNT - 1;
enum efx_filter_table_id table_id;
unsigned int range = EFX_FARCH_FILTER_MATCH_PRI_COUNT - 1;
enum efx_farch_filter_table_id table_id;
do {
table_id = efx_filter_range_table[range];
table_id = efx_farch_filter_range_table[range];
if (state->table[table_id].size != 0)
return range << EFX_FILTER_INDEX_WIDTH |
return range << EFX_FARCH_FILTER_INDEX_WIDTH |
state->table[table_id].size;
} while (range--);
@ -643,29 +660,35 @@ u32 efx_filter_get_rx_id_limit(struct efx_nic *efx)
* the existing filter has higher priority or -%EEXIST if it has
* equal priority.
*/
s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
s32 efx_filter_insert_filter(struct efx_nic *efx,
struct efx_filter_spec *gen_spec,
bool replace_equal)
{
struct efx_filter_state *state = efx->filter_state;
struct efx_filter_table *table = efx_filter_spec_table(state, spec);
struct efx_farch_filter_table *table;
struct efx_farch_filter_spec spec;
efx_oword_t filter;
int rep_index, ins_index;
unsigned int depth = 0;
int rc;
/* XXX efx_farch_filter_spec and efx_filter_spec will diverge in future */
memcpy(&spec, gen_spec, sizeof(*gen_spec));
table = efx_farch_filter_spec_table(state, &spec);
if (!table || table->size == 0)
return -EINVAL;
netif_vdbg(efx, hw, efx->net_dev,
"%s: type %d search_depth=%d", __func__, spec->type,
table->search_depth[spec->type]);
"%s: type %d search_depth=%d", __func__, spec.type,
table->search_depth[spec.type]);
if (table->id == EFX_FILTER_TABLE_RX_DEF) {
if (table->id == EFX_FARCH_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 !=
BUILD_BUG_ON(EFX_FARCH_FILTER_INDEX_UC_DEF != 0);
BUILD_BUG_ON(EFX_FARCH_FILTER_INDEX_MC_DEF !=
EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF);
rep_index = spec->type - EFX_FILTER_UC_DEF;
rep_index = spec.type - EFX_FILTER_UC_DEF;
ins_index = rep_index;
spin_lock_bh(&state->lock);
@ -685,13 +708,14 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
* (b) we have searched exhaustively for (1), and have
* either found (2) or searched exhaustively for it
*/
u32 key = efx_filter_build(&filter, spec);
unsigned int hash = efx_filter_hash(key);
unsigned int incr = efx_filter_increment(key);
unsigned int max_rep_depth = table->search_depth[spec->type];
u32 key = efx_farch_filter_build(&filter, &spec);
unsigned int hash = efx_farch_filter_hash(key);
unsigned int incr = efx_farch_filter_increment(key);
unsigned int max_rep_depth = table->search_depth[spec.type];
unsigned int max_ins_depth =
spec->priority <= EFX_FILTER_PRI_HINT ?
FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX;
spec.priority <= EFX_FILTER_PRI_HINT ?
EFX_FARCH_FILTER_CTL_SRCH_HINT_MAX :
EFX_FARCH_FILTER_CTL_SRCH_MAX;
unsigned int i = hash & (table->size - 1);
ins_index = -1;
@ -703,7 +727,8 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
if (!test_bit(i, table->used_bitmap)) {
if (ins_index < 0)
ins_index = i;
} else if (efx_filter_equal(spec, &table->spec[i])) {
} else if (efx_farch_filter_equal(&spec,
&table->spec[i])) {
/* Case (a) */
if (ins_index < 0)
ins_index = i;
@ -731,13 +756,14 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
* should do so
*/
if (rep_index >= 0) {
struct efx_filter_spec *saved_spec = &table->spec[rep_index];
struct efx_farch_filter_spec *saved_spec =
&table->spec[rep_index];
if (spec->priority == saved_spec->priority && !replace_equal) {
if (spec.priority == saved_spec->priority && !replace_equal) {
rc = -EEXIST;
goto out;
}
if (spec->priority < saved_spec->priority) {
if (spec.priority < saved_spec->priority) {
rc = -EPERM;
goto out;
}
@ -748,17 +774,17 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
__set_bit(ins_index, table->used_bitmap);
++table->used;
}
table->spec[ins_index] = *spec;
table->spec[ins_index] = spec;
if (table->id == EFX_FILTER_TABLE_RX_DEF) {
efx_filter_push_rx_config(efx);
if (table->id == EFX_FARCH_FILTER_TABLE_RX_DEF) {
efx_farch_filter_push_rx_config(efx);
} else {
if (table->search_depth[spec->type] < depth) {
table->search_depth[spec->type] = depth;
if (spec->flags & EFX_FILTER_FLAG_TX)
efx_filter_push_tx_limits(efx);
if (table->search_depth[spec.type] < depth) {
table->search_depth[spec.type] = depth;
if (spec.flags & EFX_FILTER_FLAG_TX)
efx_farch_filter_push_tx_limits(efx);
else
efx_filter_push_rx_config(efx);
efx_farch_filter_push_rx_config(efx);
}
efx_writeo(efx, &filter,
@ -768,29 +794,31 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
* at a lower depth, clear the replaced filter
*/
if (ins_index != rep_index && rep_index >= 0)
efx_filter_table_clear_entry(efx, table, rep_index);
efx_farch_filter_table_clear_entry(efx, table,
rep_index);
}
netif_vdbg(efx, hw, efx->net_dev,
"%s: filter type %d index %d rxq %u set",
__func__, spec->type, ins_index, spec->dmaq_id);
rc = efx_filter_make_id(spec, ins_index);
__func__, spec.type, ins_index, spec.dmaq_id);
rc = efx_farch_filter_make_id(&spec, ins_index);
out:
spin_unlock_bh(&state->lock);
return rc;
}
static void efx_filter_table_clear_entry(struct efx_nic *efx,
struct efx_filter_table *table,
unsigned int filter_idx)
static void
efx_farch_filter_table_clear_entry(struct efx_nic *efx,
struct efx_farch_filter_table *table,
unsigned int filter_idx)
{
static efx_oword_t filter;
if (table->id == EFX_FILTER_TABLE_RX_DEF) {
if (table->id == EFX_FARCH_FILTER_TABLE_RX_DEF) {
/* RX default filters must always exist */
efx_filter_reset_rx_def(efx, filter_idx);
efx_filter_push_rx_config(efx);
efx_farch_filter_reset_rx_def(efx, filter_idx);
efx_farch_filter_push_rx_config(efx);
} else if (test_bit(filter_idx, table->used_bitmap)) {
__clear_bit(filter_idx, table->used_bitmap);
--table->used;
@ -815,18 +843,18 @@ int efx_filter_remove_id_safe(struct efx_nic *efx,
u32 filter_id)
{
struct efx_filter_state *state = efx->filter_state;
enum efx_filter_table_id table_id;
struct efx_filter_table *table;
enum efx_farch_filter_table_id table_id;
struct efx_farch_filter_table *table;
unsigned int filter_idx;
struct efx_filter_spec *spec;
struct efx_farch_filter_spec *spec;
int rc;
table_id = efx_filter_id_table_id(filter_id);
if ((unsigned int)table_id >= EFX_FILTER_TABLE_COUNT)
table_id = efx_farch_filter_id_table_id(filter_id);
if ((unsigned int)table_id >= EFX_FARCH_FILTER_TABLE_COUNT)
return -ENOENT;
table = &state->table[table_id];
filter_idx = efx_filter_id_index(filter_id);
filter_idx = efx_farch_filter_id_index(filter_id);
if (filter_idx >= table->size)
return -ENOENT;
spec = &table->spec[filter_idx];
@ -835,9 +863,9 @@ int efx_filter_remove_id_safe(struct efx_nic *efx,
if (test_bit(filter_idx, table->used_bitmap) &&
spec->priority == priority) {
efx_filter_table_clear_entry(efx, table, filter_idx);
efx_farch_filter_table_clear_entry(efx, table, filter_idx);
if (table->used == 0)
efx_filter_table_reset_search_depth(table);
efx_farch_filter_table_reset_search_depth(table);
rc = 0;
} else {
rc = -ENOENT;
@ -863,18 +891,18 @@ int efx_filter_get_filter_safe(struct efx_nic *efx,
u32 filter_id, struct efx_filter_spec *spec_buf)
{
struct efx_filter_state *state = efx->filter_state;
enum efx_filter_table_id table_id;
struct efx_filter_table *table;
struct efx_filter_spec *spec;
enum efx_farch_filter_table_id table_id;
struct efx_farch_filter_table *table;
struct efx_farch_filter_spec *spec;
unsigned int filter_idx;
int rc;
table_id = efx_filter_id_table_id(filter_id);
if ((unsigned int)table_id >= EFX_FILTER_TABLE_COUNT)
table_id = efx_farch_filter_id_table_id(filter_id);
if ((unsigned int)table_id >= EFX_FARCH_FILTER_TABLE_COUNT)
return -ENOENT;
table = &state->table[table_id];
filter_idx = efx_filter_id_index(filter_id);
filter_idx = efx_farch_filter_id_index(filter_id);
if (filter_idx >= table->size)
return -ENOENT;
spec = &table->spec[filter_idx];
@ -883,7 +911,8 @@ int efx_filter_get_filter_safe(struct efx_nic *efx,
if (test_bit(filter_idx, table->used_bitmap) &&
spec->priority == priority) {
*spec_buf = *spec;
/* XXX efx_farch_filter_spec and efx_filter_spec will diverge */
memcpy(spec_buf, spec, sizeof(*spec));
rc = 0;
} else {
rc = -ENOENT;
@ -894,21 +923,23 @@ int efx_filter_get_filter_safe(struct efx_nic *efx,
return rc;
}
static void efx_filter_table_clear(struct efx_nic *efx,
enum efx_filter_table_id table_id,
enum efx_filter_priority priority)
static void
efx_farch_filter_table_clear(struct efx_nic *efx,
enum efx_farch_filter_table_id table_id,
enum efx_filter_priority priority)
{
struct efx_filter_state *state = efx->filter_state;
struct efx_filter_table *table = &state->table[table_id];
struct efx_farch_filter_table *table = &state->table[table_id];
unsigned int filter_idx;
spin_lock_bh(&state->lock);
for (filter_idx = 0; filter_idx < table->size; ++filter_idx)
if (table->spec[filter_idx].priority <= priority)
efx_filter_table_clear_entry(efx, table, filter_idx);
efx_farch_filter_table_clear_entry(efx, table,
filter_idx);
if (table->used == 0)
efx_filter_table_reset_search_depth(table);
efx_farch_filter_table_reset_search_depth(table);
spin_unlock_bh(&state->lock);
}
@ -920,23 +951,25 @@ static void efx_filter_table_clear(struct efx_nic *efx,
*/
void efx_filter_clear_rx(struct efx_nic *efx, enum efx_filter_priority priority)
{
efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_IP, priority);
efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_MAC, priority);
efx_farch_filter_table_clear(efx, EFX_FARCH_FILTER_TABLE_RX_IP,
priority);
efx_farch_filter_table_clear(efx, EFX_FARCH_FILTER_TABLE_RX_MAC,
priority);
}
u32 efx_filter_count_rx_used(struct efx_nic *efx,
enum efx_filter_priority priority)
{
struct efx_filter_state *state = efx->filter_state;
enum efx_filter_table_id table_id;
struct efx_filter_table *table;
enum efx_farch_filter_table_id table_id;
struct efx_farch_filter_table *table;
unsigned int filter_idx;
u32 count = 0;
spin_lock_bh(&state->lock);
for (table_id = EFX_FILTER_TABLE_RX_IP;
table_id <= EFX_FILTER_TABLE_RX_DEF;
for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
table_id++) {
table = &state->table[table_id];
for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
@ -956,15 +989,15 @@ s32 efx_filter_get_rx_ids(struct efx_nic *efx,
u32 *buf, u32 size)
{
struct efx_filter_state *state = efx->filter_state;
enum efx_filter_table_id table_id;
struct efx_filter_table *table;
enum efx_farch_filter_table_id table_id;
struct efx_farch_filter_table *table;
unsigned int filter_idx;
s32 count = 0;
spin_lock_bh(&state->lock);
for (table_id = EFX_FILTER_TABLE_RX_IP;
table_id <= EFX_FILTER_TABLE_RX_DEF;
for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
table_id++) {
table = &state->table[table_id];
for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
@ -974,7 +1007,7 @@ s32 efx_filter_get_rx_ids(struct efx_nic *efx,
count = -EMSGSIZE;
goto out;
}
buf[count++] = efx_filter_make_id(
buf[count++] = efx_farch_filter_make_id(
&table->spec[filter_idx], filter_idx);
}
}
@ -989,14 +1022,14 @@ s32 efx_filter_get_rx_ids(struct efx_nic *efx,
void efx_restore_filters(struct efx_nic *efx)
{
struct efx_filter_state *state = efx->filter_state;
enum efx_filter_table_id table_id;
struct efx_filter_table *table;
enum efx_farch_filter_table_id table_id;
struct efx_farch_filter_table *table;
efx_oword_t filter;
unsigned int filter_idx;
spin_lock_bh(&state->lock);
for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
for (table_id = 0; table_id < EFX_FARCH_FILTER_TABLE_COUNT; table_id++) {
table = &state->table[table_id];
/* Check whether this is a regular register table */
@ -1006,14 +1039,14 @@ void efx_restore_filters(struct efx_nic *efx)
for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
if (!test_bit(filter_idx, table->used_bitmap))
continue;
efx_filter_build(&filter, &table->spec[filter_idx]);
efx_farch_filter_build(&filter, &table->spec[filter_idx]);
efx_writeo(efx, &filter,
table->offset + table->step * filter_idx);
}
}
efx_filter_push_rx_config(efx);
efx_filter_push_tx_limits(efx);
efx_farch_filter_push_rx_config(efx);
efx_farch_filter_push_tx_limits(efx);
spin_unlock_bh(&state->lock);
}
@ -1021,7 +1054,7 @@ void efx_restore_filters(struct efx_nic *efx)
int efx_probe_filters(struct efx_nic *efx)
{
struct efx_filter_state *state;
struct efx_filter_table *table;
struct efx_farch_filter_table *table;
unsigned table_id;
state = kzalloc(sizeof(*efx->filter_state), GFP_KERNEL);
@ -1039,32 +1072,32 @@ int efx_probe_filters(struct efx_nic *efx)
if (!state->rps_flow_id)
goto fail;
#endif
table = &state->table[EFX_FILTER_TABLE_RX_IP];
table->id = EFX_FILTER_TABLE_RX_IP;
table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
table->id = EFX_FARCH_FILTER_TABLE_RX_IP;
table->offset = FR_BZ_RX_FILTER_TBL0;
table->size = FR_BZ_RX_FILTER_TBL0_ROWS;
table->step = FR_BZ_RX_FILTER_TBL0_STEP;
}
if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
table = &state->table[EFX_FILTER_TABLE_RX_MAC];
table->id = EFX_FILTER_TABLE_RX_MAC;
table = &state->table[EFX_FARCH_FILTER_TABLE_RX_MAC];
table->id = EFX_FARCH_FILTER_TABLE_RX_MAC;
table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
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;
table = &state->table[EFX_FARCH_FILTER_TABLE_RX_DEF];
table->id = EFX_FARCH_FILTER_TABLE_RX_DEF;
table->size = EFX_FARCH_FILTER_SIZE_RX_DEF;
table = &state->table[EFX_FILTER_TABLE_TX_MAC];
table->id = EFX_FILTER_TABLE_TX_MAC;
table = &state->table[EFX_FARCH_FILTER_TABLE_TX_MAC];
table->id = EFX_FARCH_FILTER_TABLE_TX_MAC;
table->offset = FR_CZ_TX_MAC_FILTER_TBL0;
table->size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
table->step = FR_CZ_TX_MAC_FILTER_TBL0_STEP;
}
for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
for (table_id = 0; table_id < EFX_FARCH_FILTER_TABLE_COUNT; table_id++) {
table = &state->table[table_id];
if (table->size == 0)
continue;
@ -1078,14 +1111,14 @@ int efx_probe_filters(struct efx_nic *efx)
goto fail;
}
if (state->table[EFX_FILTER_TABLE_RX_DEF].size) {
if (state->table[EFX_FARCH_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);
for (i = 0; i < EFX_FARCH_FILTER_SIZE_RX_DEF; i++)
efx_farch_filter_reset_rx_def(efx, i);
}
efx_filter_push_rx_config(efx);
efx_farch_filter_push_rx_config(efx);
return 0;
@ -1097,9 +1130,9 @@ int efx_probe_filters(struct efx_nic *efx)
void efx_remove_filters(struct efx_nic *efx)
{
struct efx_filter_state *state = efx->filter_state;
enum efx_filter_table_id table_id;
enum efx_farch_filter_table_id table_id;
for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
for (table_id = 0; table_id < EFX_FARCH_FILTER_TABLE_COUNT; table_id++) {
kfree(state->table[table_id].used_bitmap);
vfree(state->table[table_id].spec);
}
@ -1113,15 +1146,15 @@ void efx_remove_filters(struct efx_nic *efx)
void efx_filter_update_rx_scatter(struct efx_nic *efx)
{
struct efx_filter_state *state = efx->filter_state;
enum efx_filter_table_id table_id;
struct efx_filter_table *table;
enum efx_farch_filter_table_id table_id;
struct efx_farch_filter_table *table;
efx_oword_t filter;
unsigned int filter_idx;
spin_lock_bh(&state->lock);
for (table_id = EFX_FILTER_TABLE_RX_IP;
table_id <= EFX_FILTER_TABLE_RX_DEF;
for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
table_id++) {
table = &state->table[table_id];
@ -1138,17 +1171,17 @@ void efx_filter_update_rx_scatter(struct efx_nic *efx)
table->spec[filter_idx].flags &=
~EFX_FILTER_FLAG_RX_SCATTER;
if (table_id == EFX_FILTER_TABLE_RX_DEF)
/* Pushed by efx_filter_push_rx_config() */
if (table_id == EFX_FARCH_FILTER_TABLE_RX_DEF)
/* Pushed by efx_farch_filter_push_rx_config() */
continue;
efx_filter_build(&filter, &table->spec[filter_idx]);
efx_farch_filter_build(&filter, &table->spec[filter_idx]);
efx_writeo(efx, &filter,
table->offset + table->step * filter_idx);
}
}
efx_filter_push_rx_config(efx);
efx_farch_filter_push_rx_config(efx);
spin_unlock_bh(&state->lock);
}
@ -1222,7 +1255,8 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned quota)
{
struct efx_filter_state *state = efx->filter_state;
struct efx_filter_table *table = &state->table[EFX_FILTER_TABLE_RX_IP];
struct efx_farch_filter_table *table =
&state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
unsigned mask = table->size - 1;
unsigned index;
unsigned stop;
@ -1242,14 +1276,14 @@ bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned quota)
netif_info(efx, rx_status, efx->net_dev,
"expiring filter %d [flow %u]\n",
index, state->rps_flow_id[index]);
efx_filter_table_clear_entry(efx, table, index);
efx_farch_filter_table_clear_entry(efx, table, index);
}
index = (index + 1) & mask;
}
state->rps_expire_index = stop;
if (table->used == 0)
efx_filter_table_reset_search_depth(table);
efx_farch_filter_table_reset_search_depth(table);
spin_unlock_bh(&state->lock);
return true;