hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/pci/iov.c
....@@ -9,11 +9,9 @@
99
1010 #include <linux/pci.h>
1111 #include <linux/slab.h>
12
-#include <linux/mutex.h>
1312 #include <linux/export.h>
1413 #include <linux/string.h>
1514 #include <linux/delay.h>
16
-#include <linux/pci-ats.h>
1715 #include "pci.h"
1816
1917 #define VIRTFN_ID_LEN 16
....@@ -135,12 +133,35 @@
135133 &physfn->sriov->subsystem_device);
136134 }
137135
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
+
138160 int pci_iov_add_virtfn(struct pci_dev *dev, int id)
139161 {
140162 int i;
141163 int rc = -ENOMEM;
142164 u64 size;
143
- char buf[VIRTFN_ID_LEN];
144165 struct pci_dev *virtfn;
145166 struct resource *res;
146167 struct pci_sriov *iov = dev->sriov;
....@@ -159,6 +180,7 @@
159180 virtfn->device = iov->vf_device;
160181 virtfn->is_virtfn = 1;
161182 virtfn->physfn = pci_dev_get(dev);
183
+ virtfn->no_command_memory = 1;
162184
163185 if (id == 0)
164186 pci_read_vf_config_common(virtfn);
....@@ -184,23 +206,14 @@
184206 }
185207
186208 pci_device_add(virtfn, virtfn->bus);
187
-
188
- sprintf(buf, "virtfn%u", id);
189
- rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
209
+ rc = pci_iov_sysfs_link(dev, virtfn, id);
190210 if (rc)
191211 goto failed1;
192
- rc = sysfs_create_link(&virtfn->dev.kobj, &dev->dev.kobj, "physfn");
193
- if (rc)
194
- goto failed2;
195
-
196
- kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE);
197212
198213 pci_bus_add_device(virtfn);
199214
200215 return 0;
201216
202
-failed2:
203
- sysfs_remove_link(&dev->dev.kobj, buf);
204217 failed1:
205218 pci_stop_and_remove_bus_device(virtfn);
206219 pci_dev_put(dev);
....@@ -240,6 +253,179 @@
240253 pci_dev_put(dev);
241254 }
242255
256
+static ssize_t sriov_totalvfs_show(struct device *dev,
257
+ struct device_attribute *attr,
258
+ char *buf)
259
+{
260
+ struct pci_dev *pdev = to_pci_dev(dev);
261
+
262
+ return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev));
263
+}
264
+
265
+static ssize_t sriov_numvfs_show(struct device *dev,
266
+ struct device_attribute *attr,
267
+ char *buf)
268
+{
269
+ struct pci_dev *pdev = to_pci_dev(dev);
270
+ u16 num_vfs;
271
+
272
+ /* Serialize vs sriov_numvfs_store() so readers see valid num_VFs */
273
+ device_lock(&pdev->dev);
274
+ num_vfs = pdev->sriov->num_VFs;
275
+ device_unlock(&pdev->dev);
276
+
277
+ return sprintf(buf, "%u\n", num_vfs);
278
+}
279
+
280
+/*
281
+ * num_vfs > 0; number of VFs to enable
282
+ * num_vfs = 0; disable all VFs
283
+ *
284
+ * Note: SRIOV spec does not allow partial VF
285
+ * disable, so it's all or none.
286
+ */
287
+static ssize_t sriov_numvfs_store(struct device *dev,
288
+ struct device_attribute *attr,
289
+ const char *buf, size_t count)
290
+{
291
+ struct pci_dev *pdev = to_pci_dev(dev);
292
+ int ret;
293
+ u16 num_vfs;
294
+
295
+ ret = kstrtou16(buf, 0, &num_vfs);
296
+ if (ret < 0)
297
+ return ret;
298
+
299
+ if (num_vfs > pci_sriov_get_totalvfs(pdev))
300
+ return -ERANGE;
301
+
302
+ device_lock(&pdev->dev);
303
+
304
+ if (num_vfs == pdev->sriov->num_VFs)
305
+ goto exit;
306
+
307
+ /* is PF driver loaded w/callback */
308
+ if (!pdev->driver || !pdev->driver->sriov_configure) {
309
+ pci_info(pdev, "Driver does not support SRIOV configuration via sysfs\n");
310
+ ret = -ENOENT;
311
+ goto exit;
312
+ }
313
+
314
+ if (num_vfs == 0) {
315
+ /* disable VFs */
316
+ ret = pdev->driver->sriov_configure(pdev, 0);
317
+ goto exit;
318
+ }
319
+
320
+ /* enable VFs */
321
+ if (pdev->sriov->num_VFs) {
322
+ pci_warn(pdev, "%d VFs already enabled. Disable before enabling %d VFs\n",
323
+ pdev->sriov->num_VFs, num_vfs);
324
+ ret = -EBUSY;
325
+ goto exit;
326
+ }
327
+
328
+ ret = pdev->driver->sriov_configure(pdev, num_vfs);
329
+ if (ret < 0)
330
+ goto exit;
331
+
332
+ if (ret != num_vfs)
333
+ pci_warn(pdev, "%d VFs requested; only %d enabled\n",
334
+ num_vfs, ret);
335
+
336
+exit:
337
+ device_unlock(&pdev->dev);
338
+
339
+ if (ret < 0)
340
+ return ret;
341
+
342
+ return count;
343
+}
344
+
345
+static ssize_t sriov_offset_show(struct device *dev,
346
+ struct device_attribute *attr,
347
+ char *buf)
348
+{
349
+ struct pci_dev *pdev = to_pci_dev(dev);
350
+
351
+ return sprintf(buf, "%u\n", pdev->sriov->offset);
352
+}
353
+
354
+static ssize_t sriov_stride_show(struct device *dev,
355
+ struct device_attribute *attr,
356
+ char *buf)
357
+{
358
+ struct pci_dev *pdev = to_pci_dev(dev);
359
+
360
+ return sprintf(buf, "%u\n", pdev->sriov->stride);
361
+}
362
+
363
+static ssize_t sriov_vf_device_show(struct device *dev,
364
+ struct device_attribute *attr,
365
+ char *buf)
366
+{
367
+ struct pci_dev *pdev = to_pci_dev(dev);
368
+
369
+ return sprintf(buf, "%x\n", pdev->sriov->vf_device);
370
+}
371
+
372
+static ssize_t sriov_drivers_autoprobe_show(struct device *dev,
373
+ struct device_attribute *attr,
374
+ char *buf)
375
+{
376
+ struct pci_dev *pdev = to_pci_dev(dev);
377
+
378
+ return sprintf(buf, "%u\n", pdev->sriov->drivers_autoprobe);
379
+}
380
+
381
+static ssize_t sriov_drivers_autoprobe_store(struct device *dev,
382
+ struct device_attribute *attr,
383
+ const char *buf, size_t count)
384
+{
385
+ struct pci_dev *pdev = to_pci_dev(dev);
386
+ bool drivers_autoprobe;
387
+
388
+ if (kstrtobool(buf, &drivers_autoprobe) < 0)
389
+ return -EINVAL;
390
+
391
+ pdev->sriov->drivers_autoprobe = drivers_autoprobe;
392
+
393
+ return count;
394
+}
395
+
396
+static DEVICE_ATTR_RO(sriov_totalvfs);
397
+static DEVICE_ATTR_RW(sriov_numvfs);
398
+static DEVICE_ATTR_RO(sriov_offset);
399
+static DEVICE_ATTR_RO(sriov_stride);
400
+static DEVICE_ATTR_RO(sriov_vf_device);
401
+static DEVICE_ATTR_RW(sriov_drivers_autoprobe);
402
+
403
+static struct attribute *sriov_dev_attrs[] = {
404
+ &dev_attr_sriov_totalvfs.attr,
405
+ &dev_attr_sriov_numvfs.attr,
406
+ &dev_attr_sriov_offset.attr,
407
+ &dev_attr_sriov_stride.attr,
408
+ &dev_attr_sriov_vf_device.attr,
409
+ &dev_attr_sriov_drivers_autoprobe.attr,
410
+ NULL,
411
+};
412
+
413
+static umode_t sriov_attrs_are_visible(struct kobject *kobj,
414
+ struct attribute *a, int n)
415
+{
416
+ struct device *dev = kobj_to_dev(kobj);
417
+
418
+ if (!dev_is_pf(dev))
419
+ return 0;
420
+
421
+ return a->mode;
422
+}
423
+
424
+const struct attribute_group sriov_dev_attr_group = {
425
+ .attrs = sriov_dev_attrs,
426
+ .is_visible = sriov_attrs_are_visible,
427
+};
428
+
243429 int __weak pcibios_sriov_enable(struct pci_dev *pdev, u16 num_vfs)
244430 {
245431 return 0;
....@@ -248,6 +434,27 @@
248434 int __weak pcibios_sriov_disable(struct pci_dev *pdev)
249435 {
250436 return 0;
437
+}
438
+
439
+static int sriov_add_vfs(struct pci_dev *dev, u16 num_vfs)
440
+{
441
+ unsigned int i;
442
+ int rc;
443
+
444
+ if (dev->no_vf_scan)
445
+ return 0;
446
+
447
+ for (i = 0; i < num_vfs; i++) {
448
+ rc = pci_iov_add_virtfn(dev, i);
449
+ if (rc)
450
+ goto failed;
451
+ }
452
+ return 0;
453
+failed:
454
+ while (i--)
455
+ pci_iov_remove_virtfn(dev, i);
456
+
457
+ return rc;
251458 }
252459
253460 static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
....@@ -335,20 +542,14 @@
335542 msleep(100);
336543 pci_cfg_access_unlock(dev);
337544
338
- for (i = 0; i < initial; i++) {
339
- rc = pci_iov_add_virtfn(dev, i);
340
- if (rc)
341
- goto failed;
342
- }
545
+ rc = sriov_add_vfs(dev, initial);
546
+ if (rc)
547
+ goto err_pcibios;
343548
344549 kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);
345550 iov->num_VFs = nr_virtfn;
346551
347552 return 0;
348
-
349
-failed:
350
- while (i--)
351
- pci_iov_remove_virtfn(dev, i);
352553
353554 err_pcibios:
354555 iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
....@@ -366,17 +567,23 @@
366567 return rc;
367568 }
368569
570
+static void sriov_del_vfs(struct pci_dev *dev)
571
+{
572
+ struct pci_sriov *iov = dev->sriov;
573
+ int i;
574
+
575
+ for (i = 0; i < iov->num_VFs; i++)
576
+ pci_iov_remove_virtfn(dev, i);
577
+}
578
+
369579 static void sriov_disable(struct pci_dev *dev)
370580 {
371
- int i;
372581 struct pci_sriov *iov = dev->sriov;
373582
374583 if (!iov->num_VFs)
375584 return;
376585
377
- for (i = 0; i < iov->num_VFs; i++)
378
- pci_iov_remove_virtfn(dev, i);
379
-
586
+ sriov_del_vfs(dev);
380587 iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
381588 pci_cfg_access_lock(dev);
382589 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
....@@ -533,8 +740,8 @@
533740 ctrl |= iov->ctrl & PCI_SRIOV_CTRL_ARI;
534741 pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, ctrl);
535742
536
- for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++)
537
- pci_update_resource(dev, i);
743
+ for (i = 0; i < PCI_SRIOV_NUM_BARS; i++)
744
+ pci_update_resource(dev, i + PCI_IOV_RESOURCES);
538745
539746 pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
540747 pci_iov_set_numvfs(dev, iov->num_VFs);