forked from luck/tmp_suning_uos_patched
nfp: add port state refresh
We will need a way of refreshing port state for link settings get/set. For get we need to refresh port speed and type. When settings are changed the reconfiguration may require reboot before it's effective. Unregister netdevs affected by reconfiguration from a workqueue. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
cee4295133
commit
172f638c93
|
@ -44,6 +44,7 @@
|
||||||
#include <linux/msi.h>
|
#include <linux/msi.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
struct dentry;
|
struct dentry;
|
||||||
struct pci_dev;
|
struct pci_dev;
|
||||||
|
@ -69,6 +70,7 @@ struct nfp_eth_table;
|
||||||
* @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
|
* @port_lock: Protects @ports, @num_ports, @num_netdevs
|
||||||
|
* @port_refresh_work: Work entry for taking netdevs out
|
||||||
*/
|
*/
|
||||||
struct nfp_pf {
|
struct nfp_pf {
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
|
@ -94,6 +96,7 @@ struct nfp_pf {
|
||||||
unsigned int num_netdevs;
|
unsigned int num_netdevs;
|
||||||
|
|
||||||
struct list_head ports;
|
struct list_head ports;
|
||||||
|
struct work_struct port_refresh_work;
|
||||||
struct mutex port_lock;
|
struct mutex port_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -813,6 +813,7 @@ struct nfp_net_dp *nfp_net_clone_dp(struct nfp_net *nn);
|
||||||
int nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_dp *new);
|
int nfp_net_ring_reconfig(struct nfp_net *nn, struct nfp_net_dp *new);
|
||||||
|
|
||||||
bool nfp_net_link_changed_read_clear(struct nfp_net *nn);
|
bool nfp_net_link_changed_read_clear(struct nfp_net *nn);
|
||||||
|
void nfp_net_refresh_port_config(struct nfp_net *nn);
|
||||||
|
|
||||||
#ifdef CONFIG_NFP_DEBUG
|
#ifdef CONFIG_NFP_DEBUG
|
||||||
void nfp_net_debugfs_create(void);
|
void nfp_net_debugfs_create(void);
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include <linux/pci_regs.h>
|
#include <linux/pci_regs.h>
|
||||||
#include <linux/msi.h>
|
#include <linux/msi.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
#include "nfpcore/nfp.h"
|
#include "nfpcore/nfp.h"
|
||||||
#include "nfpcore/nfp_cpp.h"
|
#include "nfpcore/nfp_cpp.h"
|
||||||
|
@ -468,6 +469,82 @@ nfp_net_pf_spawn_netdevs(struct nfp_pf *pf,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nfp_net_pci_remove_finish(struct nfp_pf *pf)
|
||||||
|
{
|
||||||
|
nfp_net_debugfs_dir_clean(&pf->ddir);
|
||||||
|
|
||||||
|
nfp_net_irqs_disable(pf->pdev);
|
||||||
|
kfree(pf->irq_entries);
|
||||||
|
|
||||||
|
nfp_cpp_area_release_free(pf->rx_area);
|
||||||
|
nfp_cpp_area_release_free(pf->tx_area);
|
||||||
|
nfp_cpp_area_release_free(pf->ctrl_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nfp_net_refresh_netdevs(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct nfp_pf *pf = container_of(work, struct nfp_pf,
|
||||||
|
port_refresh_work);
|
||||||
|
struct nfp_net *nn, *next;
|
||||||
|
|
||||||
|
mutex_lock(&pf->port_lock);
|
||||||
|
|
||||||
|
/* Check for nfp_net_pci_remove() racing against us */
|
||||||
|
if (list_empty(&pf->ports))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(nn, next, &pf->ports, port_list) {
|
||||||
|
if (!nn->eth_port) {
|
||||||
|
nfp_warn(pf->cpp, "Warning: port %d not present after reconfig\n",
|
||||||
|
nn->eth_port->eth_index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!nn->eth_port->override_changed)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nn_warn(nn, "Port config changed, unregistering. Reboot required before port will be operational again.\n");
|
||||||
|
|
||||||
|
nfp_net_debugfs_dir_clean(&nn->debugfs_dir);
|
||||||
|
nfp_net_netdev_clean(nn->dp.netdev);
|
||||||
|
|
||||||
|
list_del(&nn->port_list);
|
||||||
|
pf->num_netdevs--;
|
||||||
|
nfp_net_netdev_free(nn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list_empty(&pf->ports))
|
||||||
|
nfp_net_pci_remove_finish(pf);
|
||||||
|
out:
|
||||||
|
mutex_unlock(&pf->port_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfp_net_refresh_port_config(struct nfp_net *nn)
|
||||||
|
{
|
||||||
|
struct nfp_pf *pf = pci_get_drvdata(nn->pdev);
|
||||||
|
struct nfp_eth_table *old_table;
|
||||||
|
|
||||||
|
ASSERT_RTNL();
|
||||||
|
|
||||||
|
old_table = pf->eth_tbl;
|
||||||
|
|
||||||
|
list_for_each_entry(nn, &pf->ports, port_list)
|
||||||
|
nfp_net_link_changed_read_clear(nn);
|
||||||
|
|
||||||
|
pf->eth_tbl = nfp_eth_read_ports(pf->cpp);
|
||||||
|
if (!pf->eth_tbl) {
|
||||||
|
pf->eth_tbl = old_table;
|
||||||
|
nfp_err(pf->cpp, "Error refreshing port config!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(nn, &pf->ports, port_list)
|
||||||
|
nn->eth_port = nfp_net_find_port(pf, nn->eth_port->eth_index);
|
||||||
|
|
||||||
|
kfree(old_table);
|
||||||
|
|
||||||
|
schedule_work(&pf->port_refresh_work);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PCI device functions
|
* PCI device functions
|
||||||
*/
|
*/
|
||||||
|
@ -481,6 +558,7 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
|
||||||
int stride;
|
int stride;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
INIT_WORK(&pf->port_refresh_work, nfp_net_refresh_netdevs);
|
||||||
mutex_init(&pf->port_lock);
|
mutex_init(&pf->port_lock);
|
||||||
|
|
||||||
/* Verify that the board has completed initialization */
|
/* Verify that the board has completed initialization */
|
||||||
|
@ -602,14 +680,9 @@ void nfp_net_pci_remove(struct nfp_pf *pf)
|
||||||
|
|
||||||
nfp_net_pf_free_netdevs(pf);
|
nfp_net_pf_free_netdevs(pf);
|
||||||
|
|
||||||
nfp_net_debugfs_dir_clean(&pf->ddir);
|
nfp_net_pci_remove_finish(pf);
|
||||||
|
|
||||||
nfp_net_irqs_disable(pf->pdev);
|
|
||||||
kfree(pf->irq_entries);
|
|
||||||
|
|
||||||
nfp_cpp_area_release_free(pf->rx_area);
|
|
||||||
nfp_cpp_area_release_free(pf->tx_area);
|
|
||||||
nfp_cpp_area_release_free(pf->ctrl_area);
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&pf->port_lock);
|
mutex_unlock(&pf->port_lock);
|
||||||
|
|
||||||
|
cancel_work_sync(&pf->port_refresh_work);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user