Skip to content

Commit 7829451

Browse files
Hariprasad Shenaidavem330
authored andcommitted
cxgb4: Add control net_device for configuring PCIe VF
Issue: For instance, the current APIs assume a 1-to-1 mapping of Network Ports, Physical Functions and the SR-IOV Virtual Functions of those Physical Functions. This is not the case with our cards where any Virtual Function can be hooked up to any Port -- or any number of Ports the current Linux APIs also assume only 1 Network Interface/Port can be accessed per Virtual Function. Another issue is that these APIs assume that the Administrative Driver is attached to the Physical Function Associated with a Virtual Function. This is not the case with our card where all administration is performed by a Driver which is not attached to any of the Physical Functions which have SR-IOV PCI Capabilities. Another consequence of these assumptions is the inability to utilize all of the cards SR-IOV resources. For instance, our cards have SR-IOV Capabilities on Physical Functions 0..3 and the administrative Driver attaches to Physical Function 4. Each of the Physical Functions 0..3 can support up to 16 Virtual Functions. With the current Linux APIs, a 2-Port card would only be able to use the Virtual Functions on Physical Function 0..1 and not allow the Virtual Functions on Physical Functions 2..3 to be used since there are no Ports 2..3 on a 2-Port card. Fix: Since the control node is always the netdevice for all VF ACL commands. Created a dummy netdevice for each Physical Function from 0 to 3 through which one could control their VFs. The device won't be associated with any port, since it doesn't need to transmit/receive. Its purely used for VF management purpose only. The device will be registered only when VF for a particular PF is configured using PCI sysfs interface and unregistered while pci_disable_sriov() for the PF is called. Signed-off-by: Hariprasad Shenai <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a878c02 commit 7829451

File tree

1 file changed

+103
-18
lines changed

1 file changed

+103
-18
lines changed

drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c

Lines changed: 103 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3139,6 +3139,24 @@ static const struct net_device_ops cxgb4_netdev_ops = {
31393139

31403140
};
31413141

3142+
static const struct net_device_ops cxgb4_mgmt_netdev_ops = {
3143+
};
3144+
3145+
static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
3146+
{
3147+
struct adapter *adapter = netdev2adap(dev);
3148+
3149+
strlcpy(info->driver, cxgb4_driver_name, sizeof(info->driver));
3150+
strlcpy(info->version, cxgb4_driver_version,
3151+
sizeof(info->version));
3152+
strlcpy(info->bus_info, pci_name(adapter->pdev),
3153+
sizeof(info->bus_info));
3154+
}
3155+
3156+
static const struct ethtool_ops cxgb4_mgmt_ethtool_ops = {
3157+
.get_drvinfo = get_drvinfo,
3158+
};
3159+
31423160
void t4_fatal_err(struct adapter *adap)
31433161
{
31443162
t4_set_reg_field(adap, SGE_CONTROL_A, GLOBALENABLE_F, 0);
@@ -4836,19 +4854,12 @@ static int get_chip_type(struct pci_dev *pdev, u32 pl_rev)
48364854
#ifdef CONFIG_PCI_IOV
48374855
static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
48384856
{
4857+
struct adapter *adap = pci_get_drvdata(pdev);
48394858
int err = 0;
48404859
int current_vfs = pci_num_vf(pdev);
48414860
u32 pcie_fw;
4842-
void __iomem *regs;
48434861

4844-
regs = pci_ioremap_bar(pdev, 0);
4845-
if (!regs) {
4846-
dev_err(&pdev->dev, "cannot map device registers\n");
4847-
return -ENOMEM;
4848-
}
4849-
4850-
pcie_fw = readl(regs + PCIE_FW_A);
4851-
iounmap(regs);
4862+
pcie_fw = readl(adap->regs + PCIE_FW_A);
48524863
/* Check if cxgb4 is the MASTER and fw is initialized */
48534864
if (!(pcie_fw & PCIE_FW_INIT_F) ||
48544865
!(pcie_fw & PCIE_FW_MASTER_VLD_F) ||
@@ -4875,13 +4886,21 @@ static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
48754886
*/
48764887
if (!num_vfs) {
48774888
pci_disable_sriov(pdev);
4889+
if (adap->port[0]->reg_state == NETREG_REGISTERED)
4890+
unregister_netdev(adap->port[0]);
48784891
return num_vfs;
48794892
}
48804893

48814894
if (num_vfs != current_vfs) {
48824895
err = pci_enable_sriov(pdev, num_vfs);
48834896
if (err)
48844897
return err;
4898+
4899+
if (adap->port[0]->reg_state == NETREG_UNINITIALIZED) {
4900+
err = register_netdev(adap->port[0]);
4901+
if (err < 0)
4902+
pr_info("Unable to register VF mgmt netdev\n");
4903+
}
48854904
}
48864905
return num_vfs;
48874906
}
@@ -4893,9 +4912,14 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
48934912
struct port_info *pi;
48944913
bool highdma = false;
48954914
struct adapter *adapter = NULL;
4915+
struct net_device *netdev;
4916+
#ifdef CONFIG_PCI_IOV
4917+
char name[IFNAMSIZ];
4918+
#endif
48964919
void __iomem *regs;
48974920
u32 whoami, pl_rev;
48984921
enum chip_type chip;
4922+
static int adap_idx = 1;
48994923

49004924
printk_once(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION);
49014925

@@ -4930,7 +4954,9 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
49304954
func = CHELSIO_CHIP_VERSION(chip) <= CHELSIO_T5 ?
49314955
SOURCEPF_G(whoami) : T6_SOURCEPF_G(whoami);
49324956
if (func != ent->driver_data) {
4957+
#ifndef CONFIG_PCI_IOV
49334958
iounmap(regs);
4959+
#endif
49344960
pci_disable_device(pdev);
49354961
pci_save_state(pdev); /* to restore SR-IOV later */
49364962
goto sriov;
@@ -4962,6 +4988,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
49624988
err = -ENOMEM;
49634989
goto out_unmap_bar0;
49644990
}
4991+
adap_idx++;
49654992

49664993
adapter->workq = create_singlethread_workqueue("cxgb4");
49674994
if (!adapter->workq) {
@@ -5048,8 +5075,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
50485075
T6_STATMODE_V(0)));
50495076

50505077
for_each_port(adapter, i) {
5051-
struct net_device *netdev;
5052-
50535078
netdev = alloc_etherdev_mq(sizeof(struct port_info),
50545079
MAX_ETH_QSETS);
50555080
if (!netdev) {
@@ -5217,6 +5242,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
52175242
attach_ulds(adapter);
52185243

52195244
print_adapter_info(adapter);
5245+
return 0;
52205246

52215247
sriov:
52225248
#ifdef CONFIG_PCI_IOV
@@ -5230,8 +5256,57 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
52305256
"instantiated %u virtual functions\n",
52315257
num_vf[func]);
52325258
}
5233-
#endif
5259+
5260+
adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
5261+
if (!adapter) {
5262+
err = -ENOMEM;
5263+
goto free_pci_region;
5264+
}
5265+
5266+
snprintf(name, IFNAMSIZ, "mgmtpf%d%d", adap_idx, func);
5267+
netdev = alloc_netdev(0, name, NET_NAME_UNKNOWN, ether_setup);
5268+
if (!netdev) {
5269+
err = -ENOMEM;
5270+
goto free_adapter;
5271+
}
5272+
5273+
adapter->pdev = pdev;
5274+
adapter->pdev_dev = &pdev->dev;
5275+
adapter->name = pci_name(pdev);
5276+
adapter->mbox = func;
5277+
adapter->pf = func;
5278+
adapter->regs = regs;
5279+
adapter->mbox_log = kzalloc(sizeof(*adapter->mbox_log) +
5280+
(sizeof(struct mbox_cmd) *
5281+
T4_OS_LOG_MBOX_CMDS),
5282+
GFP_KERNEL);
5283+
if (!adapter->mbox_log) {
5284+
err = -ENOMEM;
5285+
goto free_netdevice;
5286+
}
5287+
pi = netdev_priv(netdev);
5288+
pi->adapter = adapter;
5289+
SET_NETDEV_DEV(netdev, &pdev->dev);
5290+
pci_set_drvdata(pdev, adapter);
5291+
5292+
adapter->port[0] = netdev;
5293+
netdev->netdev_ops = &cxgb4_mgmt_netdev_ops;
5294+
netdev->ethtool_ops = &cxgb4_mgmt_ethtool_ops;
5295+
5296+
return 0;
5297+
5298+
free_netdevice:
5299+
free_netdev(adapter->port[0]);
5300+
free_adapter:
5301+
kfree(adapter);
5302+
free_pci_region:
5303+
iounmap(regs);
5304+
pci_disable_sriov(pdev);
5305+
pci_release_regions(pdev);
5306+
return err;
5307+
#else
52345308
return 0;
5309+
#endif
52355310

52365311
out_free_dev:
52375312
free_some_resources(adapter);
@@ -5258,12 +5333,12 @@ static void remove_one(struct pci_dev *pdev)
52585333
{
52595334
struct adapter *adapter = pci_get_drvdata(pdev);
52605335

5261-
#ifdef CONFIG_PCI_IOV
5262-
pci_disable_sriov(pdev);
5263-
5264-
#endif
5336+
if (!adapter) {
5337+
pci_release_regions(pdev);
5338+
return;
5339+
}
52655340

5266-
if (adapter) {
5341+
if (adapter->pf == 4) {
52675342
int i;
52685343

52695344
/* Tear down per-adapter Work Queue first since it can contain
@@ -5312,8 +5387,18 @@ static void remove_one(struct pci_dev *pdev)
53125387
kfree(adapter->mbox_log);
53135388
synchronize_rcu();
53145389
kfree(adapter);
5315-
} else
5390+
}
5391+
#ifdef CONFIG_PCI_IOV
5392+
else {
5393+
if (adapter->port[0]->reg_state == NETREG_REGISTERED)
5394+
unregister_netdev(adapter->port[0]);
5395+
free_netdev(adapter->port[0]);
5396+
iounmap(adapter->regs);
5397+
kfree(adapter);
5398+
pci_disable_sriov(pdev);
53165399
pci_release_regions(pdev);
5400+
}
5401+
#endif
53175402
}
53185403

53195404
static struct pci_driver cxgb4_driver = {

0 commit comments

Comments
 (0)