Merge branch 'sfc-filter-locking-fixes'
Bert Kenward says: ==================== sfc: filter locking fixes Two fixes for sfc ef10 filter table locking. Initially spotted by lockdep, but one issue has also been seen in normal use. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1ff9c66b08
|
@ -4288,9 +4288,9 @@ static int efx_ef10_filter_pri(struct efx_ef10_filter_table *table,
|
||||||
return -EPROTONOSUPPORT;
|
return -EPROTONOSUPPORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static s32 efx_ef10_filter_insert(struct efx_nic *efx,
|
static s32 efx_ef10_filter_insert_locked(struct efx_nic *efx,
|
||||||
struct efx_filter_spec *spec,
|
struct efx_filter_spec *spec,
|
||||||
bool replace_equal)
|
bool replace_equal)
|
||||||
{
|
{
|
||||||
DECLARE_BITMAP(mc_rem_map, EFX_EF10_FILTER_SEARCH_LIMIT);
|
DECLARE_BITMAP(mc_rem_map, EFX_EF10_FILTER_SEARCH_LIMIT);
|
||||||
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
struct efx_ef10_nic_data *nic_data = efx->nic_data;
|
||||||
|
@ -4307,7 +4307,7 @@ static s32 efx_ef10_filter_insert(struct efx_nic *efx,
|
||||||
bool is_mc_recip;
|
bool is_mc_recip;
|
||||||
s32 rc;
|
s32 rc;
|
||||||
|
|
||||||
down_read(&efx->filter_sem);
|
WARN_ON(!rwsem_is_locked(&efx->filter_sem));
|
||||||
table = efx->filter_state;
|
table = efx->filter_state;
|
||||||
down_write(&table->lock);
|
down_write(&table->lock);
|
||||||
|
|
||||||
|
@ -4498,10 +4498,22 @@ static s32 efx_ef10_filter_insert(struct efx_nic *efx,
|
||||||
if (rss_locked)
|
if (rss_locked)
|
||||||
mutex_unlock(&efx->rss_lock);
|
mutex_unlock(&efx->rss_lock);
|
||||||
up_write(&table->lock);
|
up_write(&table->lock);
|
||||||
up_read(&efx->filter_sem);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static s32 efx_ef10_filter_insert(struct efx_nic *efx,
|
||||||
|
struct efx_filter_spec *spec,
|
||||||
|
bool replace_equal)
|
||||||
|
{
|
||||||
|
s32 ret;
|
||||||
|
|
||||||
|
down_read(&efx->filter_sem);
|
||||||
|
ret = efx_ef10_filter_insert_locked(efx, spec, replace_equal);
|
||||||
|
up_read(&efx->filter_sem);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void efx_ef10_filter_update_rx_scatter(struct efx_nic *efx)
|
static void efx_ef10_filter_update_rx_scatter(struct efx_nic *efx)
|
||||||
{
|
{
|
||||||
/* no need to do anything here on EF10 */
|
/* no need to do anything here on EF10 */
|
||||||
|
@ -5285,7 +5297,7 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
|
||||||
EFX_WARN_ON_PARANOID(ids[i] != EFX_EF10_FILTER_ID_INVALID);
|
EFX_WARN_ON_PARANOID(ids[i] != EFX_EF10_FILTER_ID_INVALID);
|
||||||
efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
|
efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
|
||||||
efx_filter_set_eth_local(&spec, vlan->vid, addr_list[i].addr);
|
efx_filter_set_eth_local(&spec, vlan->vid, addr_list[i].addr);
|
||||||
rc = efx_ef10_filter_insert(efx, &spec, true);
|
rc = efx_ef10_filter_insert_locked(efx, &spec, true);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
if (rollback) {
|
if (rollback) {
|
||||||
netif_info(efx, drv, efx->net_dev,
|
netif_info(efx, drv, efx->net_dev,
|
||||||
|
@ -5314,7 +5326,7 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
|
||||||
efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
|
efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
|
||||||
eth_broadcast_addr(baddr);
|
eth_broadcast_addr(baddr);
|
||||||
efx_filter_set_eth_local(&spec, vlan->vid, baddr);
|
efx_filter_set_eth_local(&spec, vlan->vid, baddr);
|
||||||
rc = efx_ef10_filter_insert(efx, &spec, true);
|
rc = efx_ef10_filter_insert_locked(efx, &spec, true);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
netif_warn(efx, drv, efx->net_dev,
|
netif_warn(efx, drv, efx->net_dev,
|
||||||
"Broadcast filter insert failed rc=%d\n", rc);
|
"Broadcast filter insert failed rc=%d\n", rc);
|
||||||
|
@ -5370,7 +5382,7 @@ static int efx_ef10_filter_insert_def(struct efx_nic *efx,
|
||||||
if (vlan->vid != EFX_FILTER_VID_UNSPEC)
|
if (vlan->vid != EFX_FILTER_VID_UNSPEC)
|
||||||
efx_filter_set_eth_local(&spec, vlan->vid, NULL);
|
efx_filter_set_eth_local(&spec, vlan->vid, NULL);
|
||||||
|
|
||||||
rc = efx_ef10_filter_insert(efx, &spec, true);
|
rc = efx_ef10_filter_insert_locked(efx, &spec, true);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
const char *um = multicast ? "Multicast" : "Unicast";
|
const char *um = multicast ? "Multicast" : "Unicast";
|
||||||
const char *encap_name = "";
|
const char *encap_name = "";
|
||||||
|
@ -5430,7 +5442,7 @@ static int efx_ef10_filter_insert_def(struct efx_nic *efx,
|
||||||
filter_flags, 0);
|
filter_flags, 0);
|
||||||
eth_broadcast_addr(baddr);
|
eth_broadcast_addr(baddr);
|
||||||
efx_filter_set_eth_local(&spec, vlan->vid, baddr);
|
efx_filter_set_eth_local(&spec, vlan->vid, baddr);
|
||||||
rc = efx_ef10_filter_insert(efx, &spec, true);
|
rc = efx_ef10_filter_insert_locked(efx, &spec, true);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
netif_warn(efx, drv, efx->net_dev,
|
netif_warn(efx, drv, efx->net_dev,
|
||||||
"Broadcast filter insert failed rc=%d\n",
|
"Broadcast filter insert failed rc=%d\n",
|
||||||
|
|
|
@ -1871,12 +1871,6 @@ static void efx_remove_filters(struct efx_nic *efx)
|
||||||
up_write(&efx->filter_sem);
|
up_write(&efx->filter_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void efx_restore_filters(struct efx_nic *efx)
|
|
||||||
{
|
|
||||||
down_read(&efx->filter_sem);
|
|
||||||
efx->type->filter_table_restore(efx);
|
|
||||||
up_read(&efx->filter_sem);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
*
|
*
|
||||||
|
@ -2688,6 +2682,7 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method)
|
||||||
efx_disable_interrupts(efx);
|
efx_disable_interrupts(efx);
|
||||||
|
|
||||||
mutex_lock(&efx->mac_lock);
|
mutex_lock(&efx->mac_lock);
|
||||||
|
down_write(&efx->filter_sem);
|
||||||
mutex_lock(&efx->rss_lock);
|
mutex_lock(&efx->rss_lock);
|
||||||
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
|
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE &&
|
||||||
method != RESET_TYPE_DATAPATH)
|
method != RESET_TYPE_DATAPATH)
|
||||||
|
@ -2745,9 +2740,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
|
||||||
if (efx->type->rx_restore_rss_contexts)
|
if (efx->type->rx_restore_rss_contexts)
|
||||||
efx->type->rx_restore_rss_contexts(efx);
|
efx->type->rx_restore_rss_contexts(efx);
|
||||||
mutex_unlock(&efx->rss_lock);
|
mutex_unlock(&efx->rss_lock);
|
||||||
down_read(&efx->filter_sem);
|
efx->type->filter_table_restore(efx);
|
||||||
efx_restore_filters(efx);
|
up_write(&efx->filter_sem);
|
||||||
up_read(&efx->filter_sem);
|
|
||||||
if (efx->type->sriov_reset)
|
if (efx->type->sriov_reset)
|
||||||
efx->type->sriov_reset(efx);
|
efx->type->sriov_reset(efx);
|
||||||
|
|
||||||
|
@ -2764,6 +2758,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
|
||||||
efx->port_initialized = false;
|
efx->port_initialized = false;
|
||||||
|
|
||||||
mutex_unlock(&efx->rss_lock);
|
mutex_unlock(&efx->rss_lock);
|
||||||
|
up_write(&efx->filter_sem);
|
||||||
mutex_unlock(&efx->mac_lock);
|
mutex_unlock(&efx->mac_lock);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -3473,7 +3468,9 @@ static int efx_pci_probe_main(struct efx_nic *efx)
|
||||||
|
|
||||||
efx_init_napi(efx);
|
efx_init_napi(efx);
|
||||||
|
|
||||||
|
down_write(&efx->filter_sem);
|
||||||
rc = efx->type->init(efx);
|
rc = efx->type->init(efx);
|
||||||
|
up_write(&efx->filter_sem);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
netif_err(efx, probe, efx->net_dev,
|
netif_err(efx, probe, efx->net_dev,
|
||||||
"failed to initialise NIC\n");
|
"failed to initialise NIC\n");
|
||||||
|
@ -3765,7 +3762,9 @@ static int efx_pm_resume(struct device *dev)
|
||||||
rc = efx->type->reset(efx, RESET_TYPE_ALL);
|
rc = efx->type->reset(efx, RESET_TYPE_ALL);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
down_write(&efx->filter_sem);
|
||||||
rc = efx->type->init(efx);
|
rc = efx->type->init(efx);
|
||||||
|
up_write(&efx->filter_sem);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
rc = efx_pm_thaw(dev);
|
rc = efx_pm_thaw(dev);
|
||||||
|
|
Loading…
Reference in New Issue