Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next

Ben Hutchings says:

====================
Some bug fixes that should go into 3.7:

1. Fix oops when removing device with SR-IOV enabled.  (This regression
was introduced by the last set of changes, so the fix does not need to
be applied to any earlier kernel versions.)
2. Fix firmware structure field lookup bug that resulted in missing
sensor information.
3. Fix bug that makes self-test do very little in some configurations.
4. Fix the numbering of ethtool RX flow steering filters to reflect the
real hardware priorities.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2012-10-01 21:32:55 -04:00
commit d3d5df2c4b
7 changed files with 76 additions and 82 deletions

View File

@ -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] \

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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,