Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: Add sysfs sriov_drivers_autoprobe to control VF driver binding

Sometimes it is not desirable to bind SR-IOV VFs to drivers. This can save
host side resource usage by VF instances that will be assigned to VMs.

Add a new PCI sysfs interface "sriov_drivers_autoprobe" to control that
from the PF. To modify it, echo 0/n/N (disable probe) or 1/y/Y (enable
probe) to:

/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe

Note that this must be done before enabling VFs. The change will not take
effect if VFs are already enabled. Simply, one can disable VFs by setting
sriov_numvfs to 0, choose whether to probe or not, and then re-enable the
VFs by restoring sriov_numvfs.

[bhelgaas: changelog, ABI doc]
Signed-off-by: Bodong Wang <bodong@mellanox.com>
Signed-off-by: Eli Cohen <eli@mellanox.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
Reviewed-by: Alex Williamson <alex.williamson@redhat.com>

authored by

Bodong Wang and committed by
Bjorn Helgaas
0e7df224 f65fd1aa

+82 -4
+22
Documentation/ABI/testing/sysfs-bus-pci
··· 301 301 Description: 302 302 This file contains the revision field of the the PCI device. 303 303 The value comes from device config space. The file is read only. 304 + 305 + What: /sys/bus/pci/devices/.../sriov_drivers_autoprobe 306 + Date: April 2017 307 + Contact: Bodong Wang<bodong@mellanox.com> 308 + Description: 309 + This file is associated with the PF of a device that 310 + supports SR-IOV. It determines whether newly-enabled VFs 311 + are immediately bound to a driver. It initially contains 312 + 1, which means the kernel automatically binds VFs to a 313 + compatible driver immediately after they are enabled. If 314 + an application writes 0 to the file before enabling VFs, 315 + the kernel will not bind VFs to a driver. 316 + 317 + A typical use case is to write 0 to this file, then enable 318 + VFs, then assign the newly-created VFs to virtual machines. 319 + Note that changing this file does not affect already- 320 + enabled VFs. In this scenario, the user must first disable 321 + the VFs, write 0 to sriov_drivers_autoprobe, then re-enable 322 + the VFs. 323 + 324 + This is similar to /sys/bus/pci/drivers_autoprobe, but 325 + affects only the VFs associated with a specific PF.
+12
Documentation/PCI/pci-iov-howto.txt
··· 68 68 echo 0 > \ 69 69 /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs 70 70 71 + To enable auto probing VFs by a compatible driver on the host, run 72 + command below before enabling SR-IOV capabilities. This is the 73 + default behavior. 74 + echo 1 > \ 75 + /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe 76 + 77 + To disable auto probing VFs by a compatible driver on the host, run 78 + command below before enabling SR-IOV capabilities. Updating this 79 + entry will not affect VFs which are already probed. 80 + echo 0 > \ 81 + /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe 82 + 71 83 3.2 Usage example 72 84 73 85 Following piece of code illustrates the usage of the SR-IOV API.
+1
drivers/pci/iov.c
··· 450 450 iov->total_VFs = total; 451 451 iov->pgsz = pgsz; 452 452 iov->self = dev; 453 + iov->drivers_autoprobe = true; 453 454 pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap); 454 455 pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); 455 456 if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END)
+18 -4
drivers/pci/pci-driver.c
··· 394 394 { 395 395 } 396 396 397 + #ifdef CONFIG_PCI_IOV 398 + static inline bool pci_device_can_probe(struct pci_dev *pdev) 399 + { 400 + return (!pdev->is_virtfn || pdev->physfn->sriov->drivers_autoprobe); 401 + } 402 + #else 403 + static inline bool pci_device_can_probe(struct pci_dev *pdev) 404 + { 405 + return true; 406 + } 407 + #endif 408 + 397 409 static int pci_device_probe(struct device *dev) 398 410 { 399 411 int error; ··· 417 405 return error; 418 406 419 407 pci_dev_get(pci_dev); 420 - error = __pci_device_probe(drv, pci_dev); 421 - if (error) { 422 - pcibios_free_irq(pci_dev); 423 - pci_dev_put(pci_dev); 408 + if (pci_device_can_probe(pci_dev)) { 409 + error = __pci_device_probe(drv, pci_dev); 410 + if (error) { 411 + pcibios_free_irq(pci_dev); 412 + pci_dev_put(pci_dev); 413 + } 424 414 } 425 415 426 416 return error;
+28
drivers/pci/pci-sysfs.c
··· 526 526 return count; 527 527 } 528 528 529 + static ssize_t sriov_drivers_autoprobe_show(struct device *dev, 530 + struct device_attribute *attr, 531 + char *buf) 532 + { 533 + struct pci_dev *pdev = to_pci_dev(dev); 534 + 535 + return sprintf(buf, "%u\n", pdev->sriov->drivers_autoprobe); 536 + } 537 + 538 + static ssize_t sriov_drivers_autoprobe_store(struct device *dev, 539 + struct device_attribute *attr, 540 + const char *buf, size_t count) 541 + { 542 + struct pci_dev *pdev = to_pci_dev(dev); 543 + bool drivers_autoprobe; 544 + 545 + if (kstrtobool(buf, &drivers_autoprobe) < 0) 546 + return -EINVAL; 547 + 548 + pdev->sriov->drivers_autoprobe = drivers_autoprobe; 549 + 550 + return count; 551 + } 552 + 529 553 static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs); 530 554 static struct device_attribute sriov_numvfs_attr = 531 555 __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP), 532 556 sriov_numvfs_show, sriov_numvfs_store); 557 + static struct device_attribute sriov_drivers_autoprobe_attr = 558 + __ATTR(sriov_drivers_autoprobe, (S_IRUGO|S_IWUSR|S_IWGRP), 559 + sriov_drivers_autoprobe_show, sriov_drivers_autoprobe_store); 533 560 #endif /* CONFIG_PCI_IOV */ 534 561 535 562 static ssize_t driver_override_store(struct device *dev, ··· 1576 1549 static struct attribute *sriov_dev_attrs[] = { 1577 1550 &sriov_totalvfs_attr.attr, 1578 1551 &sriov_numvfs_attr.attr, 1552 + &sriov_drivers_autoprobe_attr.attr, 1579 1553 NULL, 1580 1554 }; 1581 1555
+1
drivers/pci/pci.h
··· 272 272 struct pci_dev *self; /* this PF */ 273 273 struct mutex lock; /* lock for setting sriov_numvfs in sysfs */ 274 274 resource_size_t barsz[PCI_SRIOV_NUM_BARS]; /* VF BAR size */ 275 + bool drivers_autoprobe; /* auto probing of VFs by driver */ 275 276 }; 276 277 277 278 #ifdef CONFIG_PCI_ATS