Commit 1ff9c66b authored by David S. Miller's avatar David S. Miller

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 9e3bff92 193f2003
...@@ -4288,9 +4288,9 @@ static int efx_ef10_filter_pri(struct efx_ef10_filter_table *table, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment