Commit d12537df authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller

nfp: add mutex protection for the port list

We will want to unregister netdevs after their port got reconfigured.
For that we need to make sure manipulations of port list from the
port reconfiguration flow will not race with driver's .remove()
callback.
Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: default avatarSimon Horman <simon.horman@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b9de0077
...@@ -385,7 +385,6 @@ static void nfp_pci_remove(struct pci_dev *pdev) ...@@ -385,7 +385,6 @@ static void nfp_pci_remove(struct pci_dev *pdev)
{ {
struct nfp_pf *pf = pci_get_drvdata(pdev); struct nfp_pf *pf = pci_get_drvdata(pdev);
if (!list_empty(&pf->ports))
nfp_net_pci_remove(pf); nfp_net_pci_remove(pf);
nfp_pcie_sriov_disable(pdev); nfp_pcie_sriov_disable(pdev);
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/msi.h> #include <linux/msi.h>
#include <linux/mutex.h>
#include <linux/pci.h> #include <linux/pci.h>
struct dentry; struct dentry;
...@@ -67,6 +68,7 @@ struct nfp_eth_table; ...@@ -67,6 +68,7 @@ struct nfp_eth_table;
* @num_ports: Number of adapter ports app firmware supports * @num_ports: Number of adapter ports app firmware supports
* @num_netdevs: Number of netdevs spawned * @num_netdevs: Number of netdevs spawned
* @ports: Linked list of port structures (struct nfp_net) * @ports: Linked list of port structures (struct nfp_net)
* @port_lock: Protects @ports, @num_ports, @num_netdevs
*/ */
struct nfp_pf { struct nfp_pf {
struct pci_dev *pdev; struct pci_dev *pdev;
...@@ -92,6 +94,7 @@ struct nfp_pf { ...@@ -92,6 +94,7 @@ struct nfp_pf {
unsigned int num_netdevs; unsigned int num_netdevs;
struct list_head ports; struct list_head ports;
struct mutex port_lock;
}; };
extern struct pci_driver nfp_netvf_pci_driver; extern struct pci_driver nfp_netvf_pci_driver;
......
...@@ -481,17 +481,22 @@ int nfp_net_pci_probe(struct nfp_pf *pf) ...@@ -481,17 +481,22 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
int stride; int stride;
int err; int err;
mutex_init(&pf->port_lock);
/* Verify that the board has completed initialization */ /* Verify that the board has completed initialization */
if (!nfp_is_ready(pf->cpp)) { if (!nfp_is_ready(pf->cpp)) {
nfp_err(pf->cpp, "NFP is not ready for NIC operation.\n"); nfp_err(pf->cpp, "NFP is not ready for NIC operation.\n");
return -EINVAL; return -EINVAL;
} }
mutex_lock(&pf->port_lock);
pf->num_ports = nfp_net_pf_get_num_ports(pf); pf->num_ports = nfp_net_pf_get_num_ports(pf);
ctrl_bar = nfp_net_pf_map_ctrl_bar(pf); ctrl_bar = nfp_net_pf_map_ctrl_bar(pf);
if (!ctrl_bar) if (!ctrl_bar) {
return pf->fw_loaded ? -EINVAL : -EPROBE_DEFER; err = pf->fw_loaded ? -EINVAL : -EPROBE_DEFER;
goto err_unlock;
}
nfp_net_get_fw_version(&fw_ver, ctrl_bar); nfp_net_get_fw_version(&fw_ver, ctrl_bar);
if (fw_ver.resv || fw_ver.class != NFP_NET_CFG_VERSION_CLASS_GENERIC) { if (fw_ver.resv || fw_ver.class != NFP_NET_CFG_VERSION_CLASS_GENERIC) {
...@@ -565,6 +570,8 @@ int nfp_net_pci_probe(struct nfp_pf *pf) ...@@ -565,6 +570,8 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
if (err) if (err)
goto err_clean_ddir; goto err_clean_ddir;
mutex_unlock(&pf->port_lock);
return 0; return 0;
err_clean_ddir: err_clean_ddir:
...@@ -574,6 +581,8 @@ int nfp_net_pci_probe(struct nfp_pf *pf) ...@@ -574,6 +581,8 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
nfp_cpp_area_release_free(pf->tx_area); nfp_cpp_area_release_free(pf->tx_area);
err_ctrl_unmap: err_ctrl_unmap:
nfp_cpp_area_release_free(pf->ctrl_area); nfp_cpp_area_release_free(pf->ctrl_area);
err_unlock:
mutex_unlock(&pf->port_lock);
return err; return err;
} }
...@@ -581,6 +590,10 @@ void nfp_net_pci_remove(struct nfp_pf *pf) ...@@ -581,6 +590,10 @@ void nfp_net_pci_remove(struct nfp_pf *pf)
{ {
struct nfp_net *nn; struct nfp_net *nn;
mutex_lock(&pf->port_lock);
if (list_empty(&pf->ports))
goto out;
list_for_each_entry(nn, &pf->ports, port_list) { list_for_each_entry(nn, &pf->ports, port_list) {
nfp_net_debugfs_dir_clean(&nn->debugfs_dir); nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
...@@ -597,4 +610,6 @@ void nfp_net_pci_remove(struct nfp_pf *pf) ...@@ -597,4 +610,6 @@ void nfp_net_pci_remove(struct nfp_pf *pf)
nfp_cpp_area_release_free(pf->rx_area); nfp_cpp_area_release_free(pf->rx_area);
nfp_cpp_area_release_free(pf->tx_area); nfp_cpp_area_release_free(pf->tx_area);
nfp_cpp_area_release_free(pf->ctrl_area); nfp_cpp_area_release_free(pf->ctrl_area);
out:
mutex_unlock(&pf->port_lock);
} }
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