Merge tag 'perf_urgent_for_v5.13_rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / pci / iov.c
index 4afd4ee..afc06e6 100644 (file)
@@ -31,6 +31,7 @@ int pci_iov_virtfn_devfn(struct pci_dev *dev, int vf_id)
        return (dev->devfn + dev->sriov->offset +
                dev->sriov->stride * vf_id) & 0xff;
 }
+EXPORT_SYMBOL_GPL(pci_iov_virtfn_devfn);
 
 /*
  * Per SR-IOV spec sec 3.3.10 and 3.3.11, First VF Offset and VF Stride may
@@ -157,6 +158,92 @@ failed:
        return rc;
 }
 
+#ifdef CONFIG_PCI_MSI
+static ssize_t sriov_vf_total_msix_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       u32 vf_total_msix = 0;
+
+       device_lock(dev);
+       if (!pdev->driver || !pdev->driver->sriov_get_vf_total_msix)
+               goto unlock;
+
+       vf_total_msix = pdev->driver->sriov_get_vf_total_msix(pdev);
+unlock:
+       device_unlock(dev);
+       return sysfs_emit(buf, "%u\n", vf_total_msix);
+}
+static DEVICE_ATTR_RO(sriov_vf_total_msix);
+
+static ssize_t sriov_vf_msix_count_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct pci_dev *vf_dev = to_pci_dev(dev);
+       struct pci_dev *pdev = pci_physfn(vf_dev);
+       int val, ret;
+
+       ret = kstrtoint(buf, 0, &val);
+       if (ret)
+               return ret;
+
+       if (val < 0)
+               return -EINVAL;
+
+       device_lock(&pdev->dev);
+       if (!pdev->driver || !pdev->driver->sriov_set_msix_vec_count) {
+               ret = -EOPNOTSUPP;
+               goto err_pdev;
+       }
+
+       device_lock(&vf_dev->dev);
+       if (vf_dev->driver) {
+               /*
+                * A driver is already attached to this VF and has configured
+                * itself based on the current MSI-X vector count. Changing
+                * the vector size could mess up the driver, so block it.
+                */
+               ret = -EBUSY;
+               goto err_dev;
+       }
+
+       ret = pdev->driver->sriov_set_msix_vec_count(vf_dev, val);
+
+err_dev:
+       device_unlock(&vf_dev->dev);
+err_pdev:
+       device_unlock(&pdev->dev);
+       return ret ? : count;
+}
+static DEVICE_ATTR_WO(sriov_vf_msix_count);
+#endif
+
+static struct attribute *sriov_vf_dev_attrs[] = {
+#ifdef CONFIG_PCI_MSI
+       &dev_attr_sriov_vf_msix_count.attr,
+#endif
+       NULL,
+};
+
+static umode_t sriov_vf_attrs_are_visible(struct kobject *kobj,
+                                         struct attribute *a, int n)
+{
+       struct device *dev = kobj_to_dev(kobj);
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       if (!pdev->is_virtfn)
+               return 0;
+
+       return a->mode;
+}
+
+const struct attribute_group sriov_vf_dev_attr_group = {
+       .attrs = sriov_vf_dev_attrs,
+       .is_visible = sriov_vf_attrs_are_visible,
+};
+
 int pci_iov_add_virtfn(struct pci_dev *dev, int id)
 {
        int i;
@@ -400,18 +487,21 @@ static DEVICE_ATTR_RO(sriov_stride);
 static DEVICE_ATTR_RO(sriov_vf_device);
 static DEVICE_ATTR_RW(sriov_drivers_autoprobe);
 
-static struct attribute *sriov_dev_attrs[] = {
+static struct attribute *sriov_pf_dev_attrs[] = {
        &dev_attr_sriov_totalvfs.attr,
        &dev_attr_sriov_numvfs.attr,
        &dev_attr_sriov_offset.attr,
        &dev_attr_sriov_stride.attr,
        &dev_attr_sriov_vf_device.attr,
        &dev_attr_sriov_drivers_autoprobe.attr,
+#ifdef CONFIG_PCI_MSI
+       &dev_attr_sriov_vf_total_msix.attr,
+#endif
        NULL,
 };
 
-static umode_t sriov_attrs_are_visible(struct kobject *kobj,
-                                      struct attribute *a, int n)
+static umode_t sriov_pf_attrs_are_visible(struct kobject *kobj,
+                                         struct attribute *a, int n)
 {
        struct device *dev = kobj_to_dev(kobj);
 
@@ -421,9 +511,9 @@ static umode_t sriov_attrs_are_visible(struct kobject *kobj,
        return a->mode;
 }
 
-const struct attribute_group sriov_dev_attr_group = {
-       .attrs = sriov_dev_attrs,
-       .is_visible = sriov_attrs_are_visible,
+const struct attribute_group sriov_pf_dev_attr_group = {
+       .attrs = sriov_pf_dev_attrs,
+       .is_visible = sriov_pf_attrs_are_visible,
 };
 
 int __weak pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)