|
@@ -1878,6 +1878,7 @@ struct efx_farch_filter_table {
|
|
};
|
|
};
|
|
|
|
|
|
struct efx_farch_filter_state {
|
|
struct efx_farch_filter_state {
|
|
|
|
+ struct rw_semaphore lock; /* Protects table contents */
|
|
struct efx_farch_filter_table table[EFX_FARCH_FILTER_TABLE_COUNT];
|
|
struct efx_farch_filter_table table[EFX_FARCH_FILTER_TABLE_COUNT];
|
|
};
|
|
};
|
|
|
|
|
|
@@ -2397,9 +2398,13 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
|
|
if (rc)
|
|
if (rc)
|
|
return rc;
|
|
return rc;
|
|
|
|
|
|
|
|
+ down_write(&state->lock);
|
|
|
|
+
|
|
table = &state->table[efx_farch_filter_spec_table_id(&spec)];
|
|
table = &state->table[efx_farch_filter_spec_table_id(&spec)];
|
|
- if (table->size == 0)
|
|
|
|
- return -EINVAL;
|
|
|
|
|
|
+ if (table->size == 0) {
|
|
|
|
+ rc = -EINVAL;
|
|
|
|
+ goto out_unlock;
|
|
|
|
+ }
|
|
|
|
|
|
netif_vdbg(efx, hw, efx->net_dev,
|
|
netif_vdbg(efx, hw, efx->net_dev,
|
|
"%s: type %d search_limit=%d", __func__, spec.type,
|
|
"%s: type %d search_limit=%d", __func__, spec.type,
|
|
@@ -2412,8 +2417,6 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
|
|
EFX_FARCH_FILTER_MC_DEF - EFX_FARCH_FILTER_UC_DEF);
|
|
EFX_FARCH_FILTER_MC_DEF - EFX_FARCH_FILTER_UC_DEF);
|
|
rep_index = spec.type - EFX_FARCH_FILTER_UC_DEF;
|
|
rep_index = spec.type - EFX_FARCH_FILTER_UC_DEF;
|
|
ins_index = rep_index;
|
|
ins_index = rep_index;
|
|
-
|
|
|
|
- spin_lock_bh(&efx->filter_lock);
|
|
|
|
} else {
|
|
} else {
|
|
/* Search concurrently for
|
|
/* Search concurrently for
|
|
* (1) a filter to be replaced (rep_index): any filter
|
|
* (1) a filter to be replaced (rep_index): any filter
|
|
@@ -2443,8 +2446,6 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
|
|
ins_index = -1;
|
|
ins_index = -1;
|
|
depth = 1;
|
|
depth = 1;
|
|
|
|
|
|
- spin_lock_bh(&efx->filter_lock);
|
|
|
|
-
|
|
|
|
for (;;) {
|
|
for (;;) {
|
|
if (!test_bit(i, table->used_bitmap)) {
|
|
if (!test_bit(i, table->used_bitmap)) {
|
|
if (ins_index < 0)
|
|
if (ins_index < 0)
|
|
@@ -2463,7 +2464,7 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
|
|
/* Case (b) */
|
|
/* Case (b) */
|
|
if (ins_index < 0) {
|
|
if (ins_index < 0) {
|
|
rc = -EBUSY;
|
|
rc = -EBUSY;
|
|
- goto out;
|
|
|
|
|
|
+ goto out_unlock;
|
|
}
|
|
}
|
|
rep_index = -1;
|
|
rep_index = -1;
|
|
break;
|
|
break;
|
|
@@ -2483,11 +2484,11 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
|
|
|
|
|
|
if (spec.priority == saved_spec->priority && !replace_equal) {
|
|
if (spec.priority == saved_spec->priority && !replace_equal) {
|
|
rc = -EEXIST;
|
|
rc = -EEXIST;
|
|
- goto out;
|
|
|
|
|
|
+ goto out_unlock;
|
|
}
|
|
}
|
|
if (spec.priority < saved_spec->priority) {
|
|
if (spec.priority < saved_spec->priority) {
|
|
rc = -EPERM;
|
|
rc = -EPERM;
|
|
- goto out;
|
|
|
|
|
|
+ goto out_unlock;
|
|
}
|
|
}
|
|
if (saved_spec->priority == EFX_FILTER_PRI_AUTO ||
|
|
if (saved_spec->priority == EFX_FILTER_PRI_AUTO ||
|
|
saved_spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO)
|
|
saved_spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO)
|
|
@@ -2528,8 +2529,8 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
|
|
__func__, spec.type, ins_index, spec.dmaq_id);
|
|
__func__, spec.type, ins_index, spec.dmaq_id);
|
|
rc = efx_farch_filter_make_id(&spec, ins_index);
|
|
rc = efx_farch_filter_make_id(&spec, ins_index);
|
|
|
|
|
|
-out:
|
|
|
|
- spin_unlock_bh(&efx->filter_lock);
|
|
|
|
|
|
+out_unlock:
|
|
|
|
+ up_write(&state->lock);
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2604,11 +2605,11 @@ int efx_farch_filter_remove_safe(struct efx_nic *efx,
|
|
filter_idx = efx_farch_filter_id_index(filter_id);
|
|
filter_idx = efx_farch_filter_id_index(filter_id);
|
|
if (filter_idx >= table->size)
|
|
if (filter_idx >= table->size)
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
|
|
+ down_write(&state->lock);
|
|
spec = &table->spec[filter_idx];
|
|
spec = &table->spec[filter_idx];
|
|
|
|
|
|
- spin_lock_bh(&efx->filter_lock);
|
|
|
|
rc = efx_farch_filter_remove(efx, table, filter_idx, priority);
|
|
rc = efx_farch_filter_remove(efx, table, filter_idx, priority);
|
|
- spin_unlock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ up_write(&state->lock);
|
|
|
|
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
@@ -2622,30 +2623,28 @@ int efx_farch_filter_get_safe(struct efx_nic *efx,
|
|
struct efx_farch_filter_table *table;
|
|
struct efx_farch_filter_table *table;
|
|
struct efx_farch_filter_spec *spec;
|
|
struct efx_farch_filter_spec *spec;
|
|
unsigned int filter_idx;
|
|
unsigned int filter_idx;
|
|
- int rc;
|
|
|
|
|
|
+ int rc = -ENOENT;
|
|
|
|
+
|
|
|
|
+ down_read(&state->lock);
|
|
|
|
|
|
table_id = efx_farch_filter_id_table_id(filter_id);
|
|
table_id = efx_farch_filter_id_table_id(filter_id);
|
|
if ((unsigned int)table_id >= EFX_FARCH_FILTER_TABLE_COUNT)
|
|
if ((unsigned int)table_id >= EFX_FARCH_FILTER_TABLE_COUNT)
|
|
- return -ENOENT;
|
|
|
|
|
|
+ goto out_unlock;
|
|
table = &state->table[table_id];
|
|
table = &state->table[table_id];
|
|
|
|
|
|
filter_idx = efx_farch_filter_id_index(filter_id);
|
|
filter_idx = efx_farch_filter_id_index(filter_id);
|
|
if (filter_idx >= table->size)
|
|
if (filter_idx >= table->size)
|
|
- return -ENOENT;
|
|
|
|
|
|
+ goto out_unlock;
|
|
spec = &table->spec[filter_idx];
|
|
spec = &table->spec[filter_idx];
|
|
|
|
|
|
- spin_lock_bh(&efx->filter_lock);
|
|
|
|
-
|
|
|
|
if (test_bit(filter_idx, table->used_bitmap) &&
|
|
if (test_bit(filter_idx, table->used_bitmap) &&
|
|
spec->priority == priority) {
|
|
spec->priority == priority) {
|
|
efx_farch_filter_to_gen_spec(spec_buf, spec);
|
|
efx_farch_filter_to_gen_spec(spec_buf, spec);
|
|
rc = 0;
|
|
rc = 0;
|
|
- } else {
|
|
|
|
- rc = -ENOENT;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- spin_unlock_bh(&efx->filter_lock);
|
|
|
|
-
|
|
|
|
|
|
+out_unlock:
|
|
|
|
+ up_read(&state->lock);
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2658,13 +2657,13 @@ efx_farch_filter_table_clear(struct efx_nic *efx,
|
|
struct efx_farch_filter_table *table = &state->table[table_id];
|
|
struct efx_farch_filter_table *table = &state->table[table_id];
|
|
unsigned int filter_idx;
|
|
unsigned int filter_idx;
|
|
|
|
|
|
- spin_lock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ down_write(&state->lock);
|
|
for (filter_idx = 0; filter_idx < table->size; ++filter_idx) {
|
|
for (filter_idx = 0; filter_idx < table->size; ++filter_idx) {
|
|
if (table->spec[filter_idx].priority != EFX_FILTER_PRI_AUTO)
|
|
if (table->spec[filter_idx].priority != EFX_FILTER_PRI_AUTO)
|
|
efx_farch_filter_remove(efx, table,
|
|
efx_farch_filter_remove(efx, table,
|
|
filter_idx, priority);
|
|
filter_idx, priority);
|
|
}
|
|
}
|
|
- spin_unlock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ up_write(&state->lock);
|
|
}
|
|
}
|
|
|
|
|
|
int efx_farch_filter_clear_rx(struct efx_nic *efx,
|
|
int efx_farch_filter_clear_rx(struct efx_nic *efx,
|
|
@@ -2688,7 +2687,7 @@ u32 efx_farch_filter_count_rx_used(struct efx_nic *efx,
|
|
unsigned int filter_idx;
|
|
unsigned int filter_idx;
|
|
u32 count = 0;
|
|
u32 count = 0;
|
|
|
|
|
|
- spin_lock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ down_read(&state->lock);
|
|
|
|
|
|
for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
|
|
for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
|
|
table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
|
|
table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
|
|
@@ -2701,7 +2700,7 @@ u32 efx_farch_filter_count_rx_used(struct efx_nic *efx,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- spin_unlock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ up_read(&state->lock);
|
|
|
|
|
|
return count;
|
|
return count;
|
|
}
|
|
}
|
|
@@ -2716,7 +2715,7 @@ s32 efx_farch_filter_get_rx_ids(struct efx_nic *efx,
|
|
unsigned int filter_idx;
|
|
unsigned int filter_idx;
|
|
s32 count = 0;
|
|
s32 count = 0;
|
|
|
|
|
|
- spin_lock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ down_read(&state->lock);
|
|
|
|
|
|
for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
|
|
for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
|
|
table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
|
|
table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
|
|
@@ -2735,7 +2734,7 @@ s32 efx_farch_filter_get_rx_ids(struct efx_nic *efx,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
out:
|
|
out:
|
|
- spin_unlock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ up_read(&state->lock);
|
|
|
|
|
|
return count;
|
|
return count;
|
|
}
|
|
}
|
|
@@ -2749,7 +2748,7 @@ void efx_farch_filter_table_restore(struct efx_nic *efx)
|
|
efx_oword_t filter;
|
|
efx_oword_t filter;
|
|
unsigned int filter_idx;
|
|
unsigned int filter_idx;
|
|
|
|
|
|
- spin_lock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ down_write(&state->lock);
|
|
|
|
|
|
for (table_id = 0; table_id < EFX_FARCH_FILTER_TABLE_COUNT; table_id++) {
|
|
for (table_id = 0; table_id < EFX_FARCH_FILTER_TABLE_COUNT; table_id++) {
|
|
table = &state->table[table_id];
|
|
table = &state->table[table_id];
|
|
@@ -2770,7 +2769,7 @@ void efx_farch_filter_table_restore(struct efx_nic *efx)
|
|
efx_farch_filter_push_rx_config(efx);
|
|
efx_farch_filter_push_rx_config(efx);
|
|
efx_farch_filter_push_tx_limits(efx);
|
|
efx_farch_filter_push_tx_limits(efx);
|
|
|
|
|
|
- spin_unlock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ up_write(&state->lock);
|
|
}
|
|
}
|
|
|
|
|
|
void efx_farch_filter_table_remove(struct efx_nic *efx)
|
|
void efx_farch_filter_table_remove(struct efx_nic *efx)
|
|
@@ -2864,7 +2863,7 @@ void efx_farch_filter_update_rx_scatter(struct efx_nic *efx)
|
|
efx_oword_t filter;
|
|
efx_oword_t filter;
|
|
unsigned int filter_idx;
|
|
unsigned int filter_idx;
|
|
|
|
|
|
- spin_lock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ down_write(&state->lock);
|
|
|
|
|
|
for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
|
|
for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
|
|
table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
|
|
table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
|
|
@@ -2896,7 +2895,7 @@ void efx_farch_filter_update_rx_scatter(struct efx_nic *efx)
|
|
|
|
|
|
efx_farch_filter_push_rx_config(efx);
|
|
efx_farch_filter_push_rx_config(efx);
|
|
|
|
|
|
- spin_unlock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ up_write(&state->lock);
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_RFS_ACCEL
|
|
#ifdef CONFIG_RFS_ACCEL
|
|
@@ -2908,7 +2907,7 @@ bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
|
|
struct efx_farch_filter_table *table;
|
|
struct efx_farch_filter_table *table;
|
|
bool ret = false;
|
|
bool ret = false;
|
|
|
|
|
|
- spin_lock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ down_write(&state->lock);
|
|
table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
|
|
table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
|
|
if (test_bit(index, table->used_bitmap) &&
|
|
if (test_bit(index, table->used_bitmap) &&
|
|
table->spec[index].priority == EFX_FILTER_PRI_HINT &&
|
|
table->spec[index].priority == EFX_FILTER_PRI_HINT &&
|
|
@@ -2918,7 +2917,7 @@ bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
|
|
ret = true;
|
|
ret = true;
|
|
}
|
|
}
|
|
|
|
|
|
- spin_unlock_bh(&efx->filter_lock);
|
|
|
|
|
|
+ up_write(&state->lock);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|