Commit b6244201 authored by Hariprasad Shenai's avatar Hariprasad Shenai Committed by David S. Miller
Browse files

cxgb4: Enable SR-IOV configuration via PCI sysfs interface



Implement callback in the driver for the new PCI bus driver
interface that allows the user to enable/disable SR-IOV
virtual functions in a device via the sysfs interface.

Deprecate module parameter used to configure SRIOV

Signed-off-by: default avatarHariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c5a8c0f3
Loading
Loading
Loading
Loading
+64 −2
Original line number Diff line number Diff line
@@ -207,7 +207,7 @@ static int rx_dma_offset = 2;
static unsigned int num_vf[NUM_OF_PF_WITH_SRIOV];

module_param_array(num_vf, uint, NULL, 0644);
MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3");
MODULE_PARM_DESC(num_vf, "number of VFs for each of PFs 0-3, deprecated parameter - please use the pci sysfs interface.");
#endif

/* TX Queue select used to determine what algorithm to use for selecting TX
@@ -4836,6 +4836,60 @@ static int get_chip_type(struct pci_dev *pdev, u32 pl_rev)
	return -EINVAL;
}

#ifdef CONFIG_PCI_IOV
static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
{
	int err = 0;
	int current_vfs = pci_num_vf(pdev);
	u32 pcie_fw;
	void __iomem *regs;

	regs = pci_ioremap_bar(pdev, 0);
	if (!regs) {
		dev_err(&pdev->dev, "cannot map device registers\n");
		return -ENOMEM;
	}

	pcie_fw = readl(regs + PCIE_FW_A);
	iounmap(regs);
	/* Check if cxgb4 is the MASTER and fw is initialized */
	if (!(pcie_fw & PCIE_FW_INIT_F) ||
	    !(pcie_fw & PCIE_FW_MASTER_VLD_F) ||
	    PCIE_FW_MASTER_G(pcie_fw) != 4) {
		dev_warn(&pdev->dev,
			 "cxgb4 driver needs to be MASTER to support SRIOV\n");
		return -EOPNOTSUPP;
	}

	/* If any of the VF's is already assigned to Guest OS, then
	 * SRIOV for the same cannot be modified
	 */
	if (current_vfs && pci_vfs_assigned(pdev)) {
		dev_err(&pdev->dev,
			"Cannot modify SR-IOV while VFs are assigned\n");
		num_vfs = current_vfs;
		return num_vfs;
	}

	/* Disable SRIOV when zero is passed.
	 * One needs to disable SRIOV before modifying it, else
	 * stack throws the below warning:
	 * " 'n' VFs already enabled. Disable before enabling 'm' VFs."
	 */
	if (!num_vfs) {
		pci_disable_sriov(pdev);
		return num_vfs;
	}

	if (num_vfs != current_vfs) {
		err = pci_enable_sriov(pdev, num_vfs);
		if (err)
			return err;
	}
	return num_vfs;
}
#endif

static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	int func, i, err, s_qpp, qpp, num_seg;
@@ -5169,11 +5223,16 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)

sriov:
#ifdef CONFIG_PCI_IOV
	if (func < ARRAY_SIZE(num_vf) && num_vf[func] > 0)
	if (func < ARRAY_SIZE(num_vf) && num_vf[func] > 0) {
		dev_warn(&pdev->dev,
			 "Enabling SR-IOV VFs using the num_vf module "
			 "parameter is deprecated - please use the pci sysfs "
			 "interface instead.\n");
		if (pci_enable_sriov(pdev, num_vf[func]) == 0)
			dev_info(&pdev->dev,
				 "instantiated %u virtual functions\n",
				 num_vf[func]);
	}
#endif
	return 0;

@@ -5266,6 +5325,9 @@ static struct pci_driver cxgb4_driver = {
	.probe    = init_one,
	.remove   = remove_one,
	.shutdown = remove_one,
#ifdef CONFIG_PCI_IOV
	.sriov_configure = cxgb4_iov_configure,
#endif
	.err_handler = &cxgb4_eeh,
};