Currently pci_iov_add_virtfn() scans the SR-IOV BARs, adds the VF to the bus and also creates the sysfs links between the newly added VF and its parent PF. With pdev->no_vf_scan fencing off the entire pci_iov_add_virtfn() call s390 as the sole pdev->no_vf_scan user thus ends up missing these sysfs links which are required for example by QEMU/libvirt. Instead of duplicating the code refactor pci_iov_add_virtfn() to make sysfs link creation callable separately.
Unified · Split
| @@ -133,12 +133,35 @@ static void pci_read_vf_config_common(struct pci_dev *virtfn) · 132 unmodified lines | ||
| 133 | 133 | &physfn->sriov->subsystem_device); |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | +int pci_iov_sysfs_link(struct pci_dev *dev, | |
| 137 | + struct pci_dev *virtfn, int id) | |
| 138 | +{ | |
| 139 | + char buf[VIRTFN_ID_LEN]; | |
| 140 | + int rc; | |
| 141 | + | |
| 142 | + sprintf(buf, "virtfn%u", id); | |
| 143 | + rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf); | |
| 144 | + if (rc) | |
| 145 | + goto failed; | |
| 146 | + rc = sysfs_create_link(&virtfn->dev.kobj, &dev->dev.kobj, "physfn"); | |
| 147 | + if (rc) | |
| 148 | + goto failed1; | |
| 149 | + | |
| 150 | + kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE); | |
| 151 | + | |
| 152 | + return 0; | |
| 153 | + | |
| 154 | +failed1: | |
| 155 | + sysfs_remove_link(&dev->dev.kobj, buf); | |
| 156 | +failed: | |
| 157 | + return rc; | |
| 158 | +} | |
| 159 | + | |
| 136 | 160 | int pci_iov_add_virtfn(struct pci_dev *dev, int id) |
| 137 | 161 | { |
| 138 | 162 | int i; |
| 139 | 163 | int rc = -ENOMEM; |
| 140 | 164 | u64 size; |
| 141 | − char buf[VIRTFN_ID_LEN]; | |
| 142 | 165 | struct pci_dev *virtfn; |
| 143 | 166 | struct resource *res; |
| 144 | 167 | struct pci_sriov *iov = dev->sriov; |
| @@ -182,23 +205,14 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id) · 37 unmodified lines | ||
| 182 | 205 | } |
| 183 | 206 | |
| 184 | 207 | pci_device_add(virtfn, virtfn->bus); |
| 185 | − | |
| 186 | − sprintf(buf, "virtfn%u", id); | |
| 187 | − rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf); | |
| 208 | + rc = pci_iov_sysfs_link(dev, virtfn, id); | |
| 188 | 209 | if (rc) |
| 189 | 210 | goto failed1; |
| 190 | − rc = sysfs_create_link(&virtfn->dev.kobj, &dev->dev.kobj, "physfn"); | |
| 191 | − if (rc) | |
| 192 | − goto failed2; | |
| 193 | − | |
| 194 | − kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE); | |
| 195 | 211 | |
| 196 | 212 | pci_bus_add_device(virtfn); |
| 197 | 213 | |
| 198 | 214 | return 0; |
| 199 | 215 | |
| 200 | −failed2: | |
| 201 | − sysfs_remove_link(&dev->dev.kobj, buf); | |
| 202 | 216 | failed1: |
| 203 | 217 | pci_stop_and_remove_bus_device(virtfn); |
| 204 | 218 | pci_dev_put(dev); |
| @@ -2048,6 +2048,8 @@ int pci_iov_virtfn_devfn(struct pci_dev *dev, int id); · 2047 unmodified lines | ||
| 2048 | 2048 | |
| 2049 | 2049 | int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn); |
| 2050 | 2050 | void pci_disable_sriov(struct pci_dev *dev); |
| 2051 | + | |
| 2052 | +int pci_iov_sysfs_link(struct pci_dev *dev, struct pci_dev *virtfn, int id); | |
| 2051 | 2053 | int pci_iov_add_virtfn(struct pci_dev *dev, int id); |
| 2052 | 2054 | void pci_iov_remove_virtfn(struct pci_dev *dev, int id); |
| 2053 | 2055 | int pci_num_vf(struct pci_dev *dev); |
| @@ -2073,6 +2075,12 @@ static inline int pci_iov_virtfn_devfn(struct pci_dev *dev, int id) · 19 unmodified lines | ||
| 2073 | 2075 | } |
| 2074 | 2076 | static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) |
| 2075 | 2077 | { return -ENODEV; } |
| 2078 | + | |
| 2079 | +static inline int pci_iov_sysfs_link(struct pci_dev *dev, | |
| 2080 | + struct pci_dev *virtfn, int id) | |
| 2081 | +{ | |
| 2082 | + return -ENODEV; | |
| 2083 | +} | |
| 2076 | 2084 | static inline int pci_iov_add_virtfn(struct pci_dev *dev, int id) |
| 2077 | 2085 | { |
| 2078 | 2086 | return -ENOSYS; |