Commit 77eb4074 authored by Edward Cree's avatar Edward Cree Committed by Jakub Kicinski

sfc: move table locking into filter_table_{probe,remove} methods

We need to be able to drop the efx->filter_sem in ef100_filter_table_up()
 so that we can call functions that insert filters (and thus take that
 rwsem for read), which means the efx->type->filter_table_probe method
 needs to be responsible for taking the lock in the first place.
Signed-off-by: default avatarEdward Cree <ecree.xilinx@gmail.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 67ab160e
...@@ -2538,23 +2538,33 @@ static int efx_ef10_filter_table_probe(struct efx_nic *efx) ...@@ -2538,23 +2538,33 @@ static int efx_ef10_filter_table_probe(struct efx_nic *efx)
if (rc) if (rc)
return rc; return rc;
down_write(&efx->filter_sem);
rc = efx_mcdi_filter_table_probe(efx, nic_data->workaround_26807); rc = efx_mcdi_filter_table_probe(efx, nic_data->workaround_26807);
if (rc) if (rc)
return rc; goto out_unlock;
list_for_each_entry(vlan, &nic_data->vlan_list, list) { list_for_each_entry(vlan, &nic_data->vlan_list, list) {
rc = efx_mcdi_filter_add_vlan(efx, vlan->vid); rc = efx_mcdi_filter_add_vlan(efx, vlan->vid);
if (rc) if (rc)
goto fail_add_vlan; goto fail_add_vlan;
} }
return 0; goto out_unlock;
fail_add_vlan: fail_add_vlan:
efx_mcdi_filter_table_remove(efx); efx_mcdi_filter_table_remove(efx);
out_unlock:
up_write(&efx->filter_sem);
return rc; return rc;
} }
static void efx_ef10_filter_table_remove(struct efx_nic *efx)
{
down_write(&efx->filter_sem);
efx_mcdi_filter_table_remove(efx);
up_write(&efx->filter_sem);
}
/* This creates an entry in the RX descriptor queue */ /* This creates an entry in the RX descriptor queue */
static inline void static inline void
efx_ef10_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index) efx_ef10_build_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index)
...@@ -3211,9 +3221,7 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx) ...@@ -3211,9 +3221,7 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
efx_device_detach_sync(efx); efx_device_detach_sync(efx);
efx_net_stop(efx->net_dev); efx_net_stop(efx->net_dev);
down_write(&efx->filter_sem); efx_ef10_filter_table_remove(efx);
efx_mcdi_filter_table_remove(efx);
up_write(&efx->filter_sem);
rc = efx_ef10_vadaptor_free(efx, efx->vport_id); rc = efx_ef10_vadaptor_free(efx, efx->vport_id);
if (rc) if (rc)
...@@ -3243,9 +3251,7 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx) ...@@ -3243,9 +3251,7 @@ static int efx_ef10_vport_set_mac_address(struct efx_nic *efx)
if (rc2) if (rc2)
goto reset_nic; goto reset_nic;
restore_filters: restore_filters:
down_write(&efx->filter_sem);
rc2 = efx_ef10_filter_table_probe(efx); rc2 = efx_ef10_filter_table_probe(efx);
up_write(&efx->filter_sem);
if (rc2) if (rc2)
goto reset_nic; goto reset_nic;
...@@ -3275,8 +3281,7 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx) ...@@ -3275,8 +3281,7 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
efx_net_stop(efx->net_dev); efx_net_stop(efx->net_dev);
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
down_write(&efx->filter_sem); efx_ef10_filter_table_remove(efx);
efx_mcdi_filter_table_remove(efx);
ether_addr_copy(MCDI_PTR(inbuf, VADAPTOR_SET_MAC_IN_MACADDR), ether_addr_copy(MCDI_PTR(inbuf, VADAPTOR_SET_MAC_IN_MACADDR),
efx->net_dev->dev_addr); efx->net_dev->dev_addr);
...@@ -3286,7 +3291,6 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx) ...@@ -3286,7 +3291,6 @@ static int efx_ef10_set_mac_address(struct efx_nic *efx)
sizeof(inbuf), NULL, 0, NULL); sizeof(inbuf), NULL, 0, NULL);
efx_ef10_filter_table_probe(efx); efx_ef10_filter_table_probe(efx);
up_write(&efx->filter_sem);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
if (was_enabled) if (was_enabled)
...@@ -4092,7 +4096,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = { ...@@ -4092,7 +4096,7 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
.ev_test_generate = efx_ef10_ev_test_generate, .ev_test_generate = efx_ef10_ev_test_generate,
.filter_table_probe = efx_ef10_filter_table_probe, .filter_table_probe = efx_ef10_filter_table_probe,
.filter_table_restore = efx_mcdi_filter_table_restore, .filter_table_restore = efx_mcdi_filter_table_restore,
.filter_table_remove = efx_mcdi_filter_table_remove, .filter_table_remove = efx_ef10_filter_table_remove,
.filter_update_rx_scatter = efx_mcdi_update_rx_scatter, .filter_update_rx_scatter = efx_mcdi_update_rx_scatter,
.filter_insert = efx_mcdi_filter_insert, .filter_insert = efx_mcdi_filter_insert,
.filter_remove_safe = efx_mcdi_filter_remove_safe, .filter_remove_safe = efx_mcdi_filter_remove_safe,
......
...@@ -375,26 +375,32 @@ static int ef100_filter_table_up(struct efx_nic *efx) ...@@ -375,26 +375,32 @@ static int ef100_filter_table_up(struct efx_nic *efx)
{ {
int rc; int rc;
down_write(&efx->filter_sem);
rc = efx_mcdi_filter_add_vlan(efx, EFX_FILTER_VID_UNSPEC); rc = efx_mcdi_filter_add_vlan(efx, EFX_FILTER_VID_UNSPEC);
if (rc) { if (rc)
efx_mcdi_filter_table_down(efx); goto fail_unspec;
return rc;
}
rc = efx_mcdi_filter_add_vlan(efx, 0); rc = efx_mcdi_filter_add_vlan(efx, 0);
if (rc) { if (rc)
efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC); goto fail_vlan0;
efx_mcdi_filter_table_down(efx); up_write(&efx->filter_sem);
} return 0;
fail_vlan0:
efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC);
fail_unspec:
efx_mcdi_filter_table_down(efx);
up_write(&efx->filter_sem);
return rc; return rc;
} }
static void ef100_filter_table_down(struct efx_nic *efx) static void ef100_filter_table_down(struct efx_nic *efx)
{ {
down_write(&efx->filter_sem);
efx_mcdi_filter_del_vlan(efx, 0); efx_mcdi_filter_del_vlan(efx, 0);
efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC); efx_mcdi_filter_del_vlan(efx, EFX_FILTER_VID_UNSPEC);
efx_mcdi_filter_table_down(efx); efx_mcdi_filter_table_down(efx);
up_write(&efx->filter_sem);
} }
/* Other /* Other
......
...@@ -501,14 +501,11 @@ int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, const u8 *mac) ...@@ -501,14 +501,11 @@ int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, const u8 *mac)
efx_device_detach_sync(vf->efx); efx_device_detach_sync(vf->efx);
efx_net_stop(vf->efx->net_dev); efx_net_stop(vf->efx->net_dev);
down_write(&vf->efx->filter_sem);
vf->efx->type->filter_table_remove(vf->efx); vf->efx->type->filter_table_remove(vf->efx);
rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED); rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED);
if (rc) { if (rc)
up_write(&vf->efx->filter_sem);
return rc; return rc;
}
} }
rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i); rc = efx_ef10_evb_port_assign(efx, EVB_PORT_ID_NULL, vf_i);
...@@ -539,12 +536,9 @@ int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, const u8 *mac) ...@@ -539,12 +536,9 @@ int efx_ef10_sriov_set_vf_mac(struct efx_nic *efx, int vf_i, const u8 *mac)
if (vf->efx) { if (vf->efx) {
/* VF cannot use the vport_id that the PF created */ /* VF cannot use the vport_id that the PF created */
rc = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED); rc = efx_ef10_vadaptor_alloc(vf->efx, EVB_PORT_ID_ASSIGNED);
if (rc) { if (rc)
up_write(&vf->efx->filter_sem);
return rc; return rc;
}
vf->efx->type->filter_table_probe(vf->efx); vf->efx->type->filter_table_probe(vf->efx);
up_write(&vf->efx->filter_sem);
efx_net_open(vf->efx->net_dev); efx_net_open(vf->efx->net_dev);
efx_device_attach_if_not_resetting(vf->efx); efx_device_attach_if_not_resetting(vf->efx);
} }
...@@ -580,7 +574,6 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan, ...@@ -580,7 +574,6 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,
efx_net_stop(vf->efx->net_dev); efx_net_stop(vf->efx->net_dev);
mutex_lock(&vf->efx->mac_lock); mutex_lock(&vf->efx->mac_lock);
down_write(&vf->efx->filter_sem);
vf->efx->type->filter_table_remove(vf->efx); vf->efx->type->filter_table_remove(vf->efx);
rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED); rc = efx_ef10_vadaptor_free(vf->efx, EVB_PORT_ID_ASSIGNED);
...@@ -654,7 +647,6 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan, ...@@ -654,7 +647,6 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,
if (rc2) if (rc2)
goto reset_nic_up_write; goto reset_nic_up_write;
up_write(&vf->efx->filter_sem);
mutex_unlock(&vf->efx->mac_lock); mutex_unlock(&vf->efx->mac_lock);
rc2 = efx_net_open(vf->efx->net_dev); rc2 = efx_net_open(vf->efx->net_dev);
...@@ -666,10 +658,8 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan, ...@@ -666,10 +658,8 @@ int efx_ef10_sriov_set_vf_vlan(struct efx_nic *efx, int vf_i, u16 vlan,
return rc; return rc;
reset_nic_up_write: reset_nic_up_write:
if (vf->efx) { if (vf->efx)
up_write(&vf->efx->filter_sem);
mutex_unlock(&vf->efx->mac_lock); mutex_unlock(&vf->efx->mac_lock);
}
reset_nic: reset_nic:
if (vf->efx) { if (vf->efx) {
netif_err(efx, drv, efx->net_dev, netif_err(efx, drv, efx->net_dev,
......
...@@ -89,6 +89,7 @@ struct efx_mcdi_filter_table { ...@@ -89,6 +89,7 @@ struct efx_mcdi_filter_table {
*/ */
bool mc_chaining; bool mc_chaining;
bool vlan_filter; bool vlan_filter;
/* Entries on the vlan_list are added/removed under filter_sem */
struct list_head vlan_list; struct list_head vlan_list;
}; };
......
...@@ -793,7 +793,6 @@ int efx_probe_filters(struct efx_nic *efx) ...@@ -793,7 +793,6 @@ int efx_probe_filters(struct efx_nic *efx)
int rc; int rc;
mutex_lock(&efx->mac_lock); mutex_lock(&efx->mac_lock);
down_write(&efx->filter_sem);
rc = efx->type->filter_table_probe(efx); rc = efx->type->filter_table_probe(efx);
if (rc) if (rc)
goto out_unlock; goto out_unlock;
...@@ -830,7 +829,6 @@ int efx_probe_filters(struct efx_nic *efx) ...@@ -830,7 +829,6 @@ int efx_probe_filters(struct efx_nic *efx)
} }
#endif #endif
out_unlock: out_unlock:
up_write(&efx->filter_sem);
mutex_unlock(&efx->mac_lock); mutex_unlock(&efx->mac_lock);
return rc; return rc;
} }
...@@ -846,9 +844,7 @@ void efx_remove_filters(struct efx_nic *efx) ...@@ -846,9 +844,7 @@ void efx_remove_filters(struct efx_nic *efx)
channel->rps_flow_id = NULL; channel->rps_flow_id = NULL;
} }
#endif #endif
down_write(&efx->filter_sem);
efx->type->filter_table_remove(efx); efx->type->filter_table_remove(efx);
up_write(&efx->filter_sem);
} }
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
......
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