[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1471932332-14150-1-git-send-email-hariprasad@chelsio.com>
Date: Tue, 23 Aug 2016 11:35:32 +0530
From: Hariprasad Shenai <hariprasad@...lsio.com>
To: netdev@...r.kernel.org
Cc: davem@...emloft.net, nirranjan@...lsioc.com,
Hariprasad Shenai <hariprasad@...lsio.com>
Subject: [PATCH net-next] cxgb4: Fix issue while re-registering VF mgmt netdev
When we disable SRIOV, we used to unregister the netdev but wasn't
freed. But next time when the same netdev is registered, since the state
was in 'NETREG_UNREGISTERED', we used to hit BUG_ON in register_netdevice,
where it expects the state to be 'NETREG_UNINITIALIZED'.
Alloc netdev and register them while configuring SRIOV, and free them
when SRIOV is disabled. Also added a new function to setup ethernet
properties instead of using ether_setup. Set carrier off by default,
since we don't have to do any transmit on the interface.
Fixes: 7829451c695e ("cxgb4: Add control net_device for configuring PCIe VF")
Signed-off-by: Hariprasad Shenai <hariprasad@...lsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 1 +
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 97 +++++++++++++++-------
2 files changed, 67 insertions(+), 31 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index f988c60..3f7b33a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -798,6 +798,7 @@ struct adapter {
unsigned int mbox;
unsigned int pf;
unsigned int flags;
+ unsigned int adap_idx;
enum chip_type chip;
int msg_enable;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index be5c942..44019bd 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -3085,6 +3085,15 @@ static int cxgb_change_mtu(struct net_device *dev, int new_mtu)
}
#ifdef CONFIG_PCI_IOV
+static int dummy_open(struct net_device *dev)
+{
+ /* Turn carrier off since we don't have to transmit anything on this
+ * interface.
+ */
+ netif_carrier_off(dev);
+ return 0;
+}
+
static int cxgb_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
{
struct port_info *pi = netdev_priv(dev);
@@ -3246,11 +3255,12 @@ static const struct net_device_ops cxgb4_netdev_ops = {
.ndo_set_tx_maxrate = cxgb_set_tx_maxrate,
};
-static const struct net_device_ops cxgb4_mgmt_netdev_ops = {
#ifdef CONFIG_PCI_IOV
+static const struct net_device_ops cxgb4_mgmt_netdev_ops = {
+ .ndo_open = dummy_open,
.ndo_set_vf_mac = cxgb_set_vf_mac,
-#endif
};
+#endif
static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
@@ -5023,6 +5033,51 @@ static int get_chip_type(struct pci_dev *pdev, u32 pl_rev)
}
#ifdef CONFIG_PCI_IOV
+static void dummy_setup(struct net_device *dev)
+{
+ dev->type = ARPHRD_NONE;
+ dev->mtu = 0;
+ dev->hard_header_len = 0;
+ dev->addr_len = 0;
+ dev->tx_queue_len = 0;
+ dev->flags |= IFF_NOARP;
+ dev->priv_flags |= IFF_NO_QUEUE;
+
+ /* Initialize the device structure. */
+ dev->netdev_ops = &cxgb4_mgmt_netdev_ops;
+ dev->ethtool_ops = &cxgb4_mgmt_ethtool_ops;
+ dev->destructor = free_netdev;
+}
+
+static int config_mgmt_dev(struct pci_dev *pdev)
+{
+ struct adapter *adap = pci_get_drvdata(pdev);
+ struct net_device *netdev;
+ struct port_info *pi;
+ char name[IFNAMSIZ];
+ int err;
+
+ snprintf(name, IFNAMSIZ, "mgmtpf%d%d", adap->adap_idx, adap->pf);
+ netdev = alloc_netdev(0, name, NET_NAME_UNKNOWN, dummy_setup);
+ if (!netdev)
+ return -ENOMEM;
+
+ pi = netdev_priv(netdev);
+ pi->adapter = adap;
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+
+ adap->port[0] = netdev;
+
+ err = register_netdev(adap->port[0]);
+ if (err) {
+ pr_info("Unable to register VF mgmt netdev %s\n", name);
+ free_netdev(adap->port[0]);
+ adap->port[0] = NULL;
+ return err;
+ }
+ return 0;
+}
+
static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
{
struct adapter *adap = pci_get_drvdata(pdev);
@@ -5057,8 +5112,10 @@ static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
*/
if (!num_vfs) {
pci_disable_sriov(pdev);
- if (adap->port[0]->reg_state == NETREG_REGISTERED)
+ if (adap->port[0]) {
unregister_netdev(adap->port[0]);
+ adap->port[0] = NULL;
+ }
return num_vfs;
}
@@ -5067,11 +5124,9 @@ static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
if (err)
return err;
- if (adap->port[0]->reg_state == NETREG_UNINITIALIZED) {
- err = register_netdev(adap->port[0]);
- if (err < 0)
- pr_info("Unable to register VF mgmt netdev\n");
- }
+ err = config_mgmt_dev(pdev);
+ if (err)
+ return err;
}
return num_vfs;
}
@@ -5084,9 +5139,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
bool highdma = false;
struct adapter *adapter = NULL;
struct net_device *netdev;
-#ifdef CONFIG_PCI_IOV
- char name[IFNAMSIZ];
-#endif
void __iomem *regs;
u32 whoami, pl_rev;
enum chip_type chip;
@@ -5447,40 +5499,24 @@ sriov:
goto free_pci_region;
}
- snprintf(name, IFNAMSIZ, "mgmtpf%d%d", adap_idx, func);
- netdev = alloc_netdev(0, name, NET_NAME_UNKNOWN, ether_setup);
- if (!netdev) {
- err = -ENOMEM;
- goto free_adapter;
- }
-
adapter->pdev = pdev;
adapter->pdev_dev = &pdev->dev;
adapter->name = pci_name(pdev);
adapter->mbox = func;
adapter->pf = func;
adapter->regs = regs;
+ adapter->adap_idx = adap_idx;
adapter->mbox_log = kzalloc(sizeof(*adapter->mbox_log) +
(sizeof(struct mbox_cmd) *
T4_OS_LOG_MBOX_CMDS),
GFP_KERNEL);
if (!adapter->mbox_log) {
err = -ENOMEM;
- goto free_netdevice;
+ goto free_adapter;
}
- pi = netdev_priv(netdev);
- pi->adapter = adapter;
- SET_NETDEV_DEV(netdev, &pdev->dev);
pci_set_drvdata(pdev, adapter);
-
- adapter->port[0] = netdev;
- netdev->netdev_ops = &cxgb4_mgmt_netdev_ops;
- netdev->ethtool_ops = &cxgb4_mgmt_ethtool_ops;
-
return 0;
- free_netdevice:
- free_netdev(adapter->port[0]);
free_adapter:
kfree(adapter);
free_pci_region:
@@ -5582,9 +5618,8 @@ static void remove_one(struct pci_dev *pdev)
}
#ifdef CONFIG_PCI_IOV
else {
- if (adapter->port[0]->reg_state == NETREG_REGISTERED)
+ if (adapter->port[0])
unregister_netdev(adapter->port[0]);
- free_netdev(adapter->port[0]);
iounmap(adapter->regs);
kfree(adapter);
pci_disable_sriov(pdev);
--
1.7.3
Powered by blists - more mailing lists