diff --git a/drivers/net/ethernet/sfc/bitfield.h b/drivers/net/ethernet/sfc/bitfield.h index b26a954c27f..5400a33f254 100644 --- a/drivers/net/ethernet/sfc/bitfield.h +++ b/drivers/net/ethernet/sfc/bitfield.h @@ -120,10 +120,10 @@ typedef union efx_oword { * [0,high-low), with garbage in bits [high-low+1,...). */ #define EFX_EXTRACT_NATIVE(native_element, min, max, low, high) \ - (((low > max) || (high < min)) ? 0 : \ - ((low > min) ? \ - ((native_element) >> (low - min)) : \ - ((native_element) << (min - low)))) + ((low) > (max) || (high) < (min) ? 0 : \ + (low) > (min) ? \ + (native_element) >> ((low) - (min)) : \ + (native_element) << ((min) - (low))) /* * Extract bit field portion [low,high) from the 64-bit little-endian @@ -142,27 +142,27 @@ typedef union efx_oword { #define EFX_EXTRACT_OWORD64(oword, low, high) \ ((EFX_EXTRACT64((oword).u64[0], 0, 63, low, high) | \ EFX_EXTRACT64((oword).u64[1], 64, 127, low, high)) & \ - EFX_MASK64(high + 1 - low)) + EFX_MASK64((high) + 1 - (low))) #define EFX_EXTRACT_QWORD64(qword, low, high) \ (EFX_EXTRACT64((qword).u64[0], 0, 63, low, high) & \ - EFX_MASK64(high + 1 - low)) + EFX_MASK64((high) + 1 - (low))) #define EFX_EXTRACT_OWORD32(oword, low, high) \ ((EFX_EXTRACT32((oword).u32[0], 0, 31, low, high) | \ EFX_EXTRACT32((oword).u32[1], 32, 63, low, high) | \ EFX_EXTRACT32((oword).u32[2], 64, 95, low, high) | \ EFX_EXTRACT32((oword).u32[3], 96, 127, low, high)) & \ - EFX_MASK32(high + 1 - low)) + EFX_MASK32((high) + 1 - (low))) #define EFX_EXTRACT_QWORD32(qword, low, high) \ ((EFX_EXTRACT32((qword).u32[0], 0, 31, low, high) | \ EFX_EXTRACT32((qword).u32[1], 32, 63, low, high)) & \ - EFX_MASK32(high + 1 - low)) + EFX_MASK32((high) + 1 - (low))) #define EFX_EXTRACT_DWORD(dword, low, high) \ (EFX_EXTRACT32((dword).u32[0], 0, 31, low, high) & \ - EFX_MASK32(high + 1 - low)) + EFX_MASK32((high) + 1 - (low))) #define EFX_OWORD_FIELD64(oword, field) \ EFX_EXTRACT_OWORD64(oword, EFX_LOW_BIT(field), \ @@ -442,10 +442,10 @@ typedef union efx_oword { cpu_to_le32(EFX_INSERT_NATIVE(min, max, low, high, value)) #define EFX_INPLACE_MASK64(min, max, low, high) \ - EFX_INSERT64(min, max, low, high, EFX_MASK64(high + 1 - low)) + EFX_INSERT64(min, max, low, high, EFX_MASK64((high) + 1 - (low))) #define EFX_INPLACE_MASK32(min, max, low, high) \ - EFX_INSERT32(min, max, low, high, EFX_MASK32(high + 1 - low)) + EFX_INSERT32(min, max, low, high, EFX_MASK32((high) + 1 - (low))) #define EFX_SET_OWORD64(oword, low, high, value) do { \ (oword).u64[0] = (((oword).u64[0] \ diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 9df556c01b8..90f078eff8e 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -337,7 +337,8 @@ static int efx_fill_loopback_test(struct efx_nic *efx, unsigned int test_index, struct ethtool_string *strings, u64 *data) { - struct efx_channel *channel = efx_get_channel(efx, 0); + struct efx_channel *channel = + efx_get_channel(efx, efx->tx_channel_offset); struct efx_tx_queue *tx_queue; efx_for_each_channel_tx_queue(tx_queue, channel) { @@ -960,9 +961,7 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx, int rc; /* Check that user wants us to choose the location */ - if (rule->location != RX_CLS_LOC_ANY && - rule->location != RX_CLS_LOC_FIRST && - rule->location != RX_CLS_LOC_LAST) + if (rule->location != RX_CLS_LOC_ANY) return -EINVAL; /* Range-check ring_cookie */ @@ -976,9 +975,7 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx, rule->m_ext.data[1])) return -EINVAL; - efx_filter_init_rx(&spec, EFX_FILTER_PRI_MANUAL, - (rule->location == RX_CLS_LOC_FIRST) ? - EFX_FILTER_FLAG_RX_OVERRIDE_IP : 0, + efx_filter_init_rx(&spec, EFX_FILTER_PRI_MANUAL, 0, (rule->ring_cookie == RX_CLS_FLOW_DISC) ? 0xfff : rule->ring_cookie); diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c index c3fd61f0a95..8af42cd1fed 100644 --- a/drivers/net/ethernet/sfc/filter.c +++ b/drivers/net/ethernet/sfc/filter.c @@ -161,10 +161,6 @@ static void efx_filter_push_rx_config(struct efx_nic *efx) 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); @@ -172,10 +168,6 @@ static void efx_filter_push_rx_config(struct efx_nic *efx) 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); @@ -480,14 +472,12 @@ static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec) case EFX_FILTER_TABLE_RX_MAC: { bool is_wild = spec->type == EFX_FILTER_MAC_WILD; - EFX_POPULATE_OWORD_8( + EFX_POPULATE_OWORD_7( *filter, FRF_CZ_RMFT_RSS_EN, !!(spec->flags & EFX_FILTER_FLAG_RX_RSS), FRF_CZ_RMFT_SCATTER_EN, !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER), - FRF_CZ_RMFT_IP_OVERRIDE, - !!(spec->flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP), FRF_CZ_RMFT_RXQ_ID, spec->dmaq_id, FRF_CZ_RMFT_WILDCARD_MATCH, is_wild, FRF_CZ_RMFT_DEST_MAC_HI, spec->data[2], @@ -567,49 +557,62 @@ static int efx_filter_search(struct efx_filter_table *table, } /* - * Construct/deconstruct external filter IDs. These must be ordered - * by matching priority, for RX NFC semantics. + * Construct/deconstruct external filter IDs. At least the RX filter + * IDs must be ordered by matching priority, for RX NFC semantics. * - * Each RX MAC filter entry has a flag for whether it can override an - * RX IP filter that also matches. So we assign locations for MAC - * filters with overriding behaviour, then for IP filters, then for - * MAC filters without overriding behaviour. + * Deconstruction needs to be robust against invalid IDs so that + * efx_filter_remove_id_safe() and efx_filter_get_filter_safe() can + * accept user-provided IDs. */ -#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_MATCH_PRI_COUNT 5 + +static const u8 efx_filter_type_match_pri[EFX_FILTER_TYPE_COUNT] = { + [EFX_FILTER_TCP_FULL] = 0, + [EFX_FILTER_UDP_FULL] = 0, + [EFX_FILTER_TCP_WILD] = 1, + [EFX_FILTER_UDP_WILD] = 1, + [EFX_FILTER_MAC_FULL] = 2, + [EFX_FILTER_MAC_WILD] = 3, + [EFX_FILTER_UC_DEF] = 4, + [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 */ +}; #define EFX_FILTER_INDEX_WIDTH 13 #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, - unsigned int index, u8 flags) +static inline u32 +efx_filter_make_id(const struct efx_filter_spec *spec, unsigned int index) { - unsigned int match_pri = EFX_FILTER_MATCH_PRI_NORMAL_BASE + table_id; + unsigned int range; - if (flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP) { - 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; - } + range = efx_filter_type_match_pri[spec->type]; + if (!(spec->flags & EFX_FILTER_FLAG_RX)) + range += EFX_FILTER_MATCH_PRI_COUNT; - return match_pri << EFX_FILTER_INDEX_WIDTH | index; + return range << EFX_FILTER_INDEX_WIDTH | index; } static inline enum efx_filter_table_id efx_filter_id_table_id(u32 id) { - unsigned int match_pri = id >> EFX_FILTER_INDEX_WIDTH; + unsigned int range = id >> EFX_FILTER_INDEX_WIDTH; - 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; - } + if (range < ARRAY_SIZE(efx_filter_range_table)) + return efx_filter_range_table[range]; + else + return EFX_FILTER_TABLE_COUNT; /* invalid */ } static inline unsigned int efx_filter_id_index(u32 id) @@ -619,12 +622,9 @@ static inline unsigned int efx_filter_id_index(u32 id) static inline u8 efx_filter_id_flags(u32 id) { - unsigned int match_pri = id >> EFX_FILTER_INDEX_WIDTH; + unsigned int range = id >> EFX_FILTER_INDEX_WIDTH; - if (match_pri < EFX_FILTER_MATCH_PRI_NORMAL_BASE) - return EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_OVERRIDE_IP; - else if (match_pri <= - EFX_FILTER_MATCH_PRI_NORMAL_BASE + EFX_FILTER_TABLE_RX_DEF) + if (range < EFX_FILTER_MATCH_PRI_COUNT) return EFX_FILTER_FLAG_RX; else return EFX_FILTER_FLAG_TX; @@ -633,14 +633,15 @@ static inline u8 efx_filter_id_flags(u32 id) u32 efx_filter_get_rx_id_limit(struct efx_nic *efx) { struct efx_filter_state *state = efx->filter_state; - unsigned int table_id = EFX_FILTER_TABLE_RX_DEF; + unsigned int range = EFX_FILTER_MATCH_PRI_COUNT - 1; + enum efx_filter_table_id table_id; do { + table_id = efx_filter_range_table[range]; if (state->table[table_id].size != 0) - return ((EFX_FILTER_MATCH_PRI_NORMAL_BASE + table_id) - << EFX_FILTER_INDEX_WIDTH) + + return range << EFX_FILTER_INDEX_WIDTH | state->table[table_id].size; - } while (table_id--); + } while (range--); return 0; } @@ -718,7 +719,7 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec, netif_vdbg(efx, hw, efx->net_dev, "%s: filter type %d index %d rxq %u set", __func__, spec->type, filter_idx, spec->dmaq_id); - rc = efx_filter_make_id(table->id, filter_idx, spec->flags); + rc = efx_filter_make_id(spec, filter_idx); out: spin_unlock_bh(&state->lock); @@ -781,8 +782,7 @@ int efx_filter_remove_id_safe(struct efx_nic *efx, spin_lock_bh(&state->lock); if (test_bit(filter_idx, table->used_bitmap) && - spec->priority == priority && - !((spec->flags ^ filter_flags) & EFX_FILTER_FLAG_RX_OVERRIDE_IP)) { + spec->priority == priority) { efx_filter_table_clear_entry(efx, table, filter_idx); if (table->used == 0) efx_filter_table_reset_search_depth(table); @@ -833,8 +833,7 @@ int efx_filter_get_filter_safe(struct efx_nic *efx, spin_lock_bh(&state->lock); if (test_bit(filter_idx, table->used_bitmap) && - spec->priority == priority && - !((spec->flags ^ filter_flags) & EFX_FILTER_FLAG_RX_OVERRIDE_IP)) { + spec->priority == priority) { *spec_buf = *spec; rc = 0; } else { @@ -927,8 +926,7 @@ s32 efx_filter_get_rx_ids(struct efx_nic *efx, goto out; } buf[count++] = efx_filter_make_id( - table_id, filter_idx, - table->spec[filter_idx].flags); + &table->spec[filter_idx], filter_idx); } } } diff --git a/drivers/net/ethernet/sfc/filter.h b/drivers/net/ethernet/sfc/filter.h index 3c77802aed6..5cb54723b82 100644 --- a/drivers/net/ethernet/sfc/filter.h +++ b/drivers/net/ethernet/sfc/filter.h @@ -61,16 +61,12 @@ 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_OVERRIDE_IP: Enables a MAC filter to override - * any IP filter that matches the same packet. By default, IP - * filters take precedence. * @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_OVERRIDE_IP = 0x04, EFX_FILTER_FLAG_RX = 0x08, EFX_FILTER_FLAG_TX = 0x10, }; @@ -88,8 +84,7 @@ enum efx_filter_flags { * * The @priority field is used by software to determine whether a new * filter may replace an old one. The hardware priority of a filter - * depends on the filter type and %EFX_FILTER_FLAG_RX_OVERRIDE_IP - * flag. + * depends on the filter type. */ struct efx_filter_spec { u8 type:4; diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index dc25caaa398..3ba2e5b5a9c 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -113,11 +113,13 @@ extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); #define MCDI_EVENT_FIELD(_ev, _field) \ EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field) #define MCDI_ARRAY_FIELD(_buf, _field1, _type, _index, _field2) \ - EFX_DWORD_FIELD( \ + EFX_EXTRACT_DWORD( \ *((efx_dword_t *) \ (MCDI_ARRAY_PTR(_buf, _field1, _type, _index) + \ (MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _OFST & ~3))), \ - MC_CMD_ ## _type ## _TYPEDEF_ ## _field2) + MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _LBN & 0x1f, \ + (MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _LBN & 0x1f) + \ + MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _WIDTH - 1) extern void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len); extern int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 96068d15b60..ce72ae4f399 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -614,7 +614,8 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests, { enum efx_loopback_mode mode; struct efx_loopback_state *state; - struct efx_channel *channel = efx_get_channel(efx, 0); + struct efx_channel *channel = + efx_get_channel(efx, efx->tx_channel_offset); struct efx_tx_queue *tx_queue; int rc = 0; diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c index a8f48a45584..d49b53dc2a5 100644 --- a/drivers/net/ethernet/sfc/siena_sriov.c +++ b/drivers/net/ethernet/sfc/siena_sriov.c @@ -1035,6 +1035,7 @@ efx_sriov_get_channel_name(struct efx_channel *channel, char *buf, size_t len) static const struct efx_channel_type efx_sriov_channel_type = { .handle_no_channel = efx_sriov_handle_no_channel, .pre_probe = efx_sriov_probe_channel, + .post_remove = efx_channel_dummy_op_void, .get_name = efx_sriov_get_channel_name, /* no copy operation; channel must not be reallocated */ .keep_eventq = true,