From 1a4afaef91f97dab46a6a74174ffb0142e2d9a56 Mon Sep 17 00:00:00 2001 From: Intel Date: Mon, 3 Jun 2013 00:00:00 +0000 Subject: [PATCH] pci: configure SR-IOV with max_vfs Signed-off-by: Intel --- lib/librte_eal/common/include/rte_pci.h | 1 + lib/librte_eal/linuxapp/eal/eal_pci.c | 8 +++ lib/librte_eal/linuxapp/igb_uio/igb_uio.c | 67 +++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/lib/librte_eal/common/include/rte_pci.h b/lib/librte_eal/common/include/rte_pci.h index 1a97367837..2235acb1bf 100644 --- a/lib/librte_eal/common/include/rte_pci.h +++ b/lib/librte_eal/common/include/rte_pci.h @@ -142,6 +142,7 @@ struct rte_pci_device { struct rte_pci_resource mem_resource[PCI_MAX_RESOURCE]; /**< PCI Memory Resource */ struct rte_intr_handle intr_handle; /**< Interrupt handle */ const struct rte_pci_driver *driver; /**< Associated driver */ + uint16_t max_vfs; /**< sriov enable if not zero */ unsigned int blacklisted:1; /**< Device is blacklisted */ }; diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index 03e3d52549..de975ad83f 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -766,6 +766,14 @@ pci_scan_one(const char *dirname, uint16_t domain, uint8_t bus, } dev->id.subsystem_device_id = (uint16_t)tmp; + /* get max_vfs */ + dev->max_vfs = 0; + rte_snprintf(filename, sizeof(filename), "%s/max_vfs", dirname); + if (!access(filename, F_OK) && + eal_parse_sysfs_value(filename, &tmp) == 0) { + dev->max_vfs = (uint16_t)tmp; + } + /* parse resources */ rte_snprintf(filename, sizeof(filename), "%s/resource", dirname); if (pci_parse_sysfs_resource(filename, dev) < 0) { diff --git a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c index 4d77712a99..64ecd9153e 100644 --- a/lib/librte_eal/linuxapp/igb_uio/igb_uio.c +++ b/lib/librte_eal/linuxapp/igb_uio/igb_uio.c @@ -88,6 +88,68 @@ igbuio_get_uio_pci_dev(struct uio_info *info) return container_of(info, struct rte_uio_pci_dev, info); } +/* sriov sysfs */ +int local_pci_num_vf(struct pci_dev *dev) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) + struct iov { + int pos; + int nres; + u32 cap; + u16 ctrl; + u16 total; + u16 initial; + u16 nr_virtfn; + } *iov = (struct iov*)dev->sriov; + + if (!dev->is_physfn) + return 0; + + return iov->nr_virtfn; +#else + return pci_num_vf(dev); +#endif +} + +static ssize_t +show_max_vfs(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, 10, "%u\n", local_pci_num_vf( + container_of(dev, struct pci_dev, dev))); +} + +static ssize_t +store_max_vfs(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int err = 0; + unsigned long max_vfs; + struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); + + if (0 != strict_strtoul(buf, 0, &max_vfs)) + return -EINVAL; + + if (0 == max_vfs) + pci_disable_sriov(pdev); + else if (0 == local_pci_num_vf(pdev)) + err = pci_enable_sriov(pdev, max_vfs); + else /* do nothing if change max_vfs number */ + err = -EINVAL; + + return err ? err : count; +} + +static DEVICE_ATTR(max_vfs, S_IRUGO | S_IWUSR, show_max_vfs, store_max_vfs); +static struct attribute *dev_attrs[] = { + &dev_attr_max_vfs.attr, + NULL, +}; + +static const struct attribute_group dev_attr_grp = { + .attrs = dev_attrs, +}; + static inline int pci_lock(struct pci_dev * pdev) { @@ -438,6 +500,9 @@ igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) pci_set_drvdata(dev, udev); igbuio_pci_irqcontrol(&udev->info, 0); + if (sysfs_create_group(&dev->dev.kobj, &dev_attr_grp)) + goto fail_release_iomem; + /* register uio driver */ if (uio_register_device(&dev->dev, &udev->info)) goto fail_release_iomem; @@ -447,6 +512,7 @@ igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) return 0; fail_release_iomem: + sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); igbuio_pci_release_iomem(&udev->info); if (udev->mode == IGBUIO_MSIX_INTR_MODE) pci_disable_msix(udev->pdev); @@ -469,6 +535,7 @@ igbuio_pci_remove(struct pci_dev *dev) return; } + sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); uio_unregister_device(info); igbuio_pci_release_iomem(info); if (((struct rte_uio_pci_dev *)info->priv)->mode == -- 2.20.1