pci-iov-howto.txt 4.3 KB
Newer Older
1 2 3 4
		PCI Express I/O Virtualization Howto
		Copyright (C) 2009 Intel Corporation
		    Yu Zhao <yu.zhao@intel.com>

5 6 7
		Update: November 2012
			-- sysfs-based SRIOV enable-/disable-ment
		Donald Dutile <ddutile@redhat.com>
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

1. Overview

1.1 What is SR-IOV

Single Root I/O Virtualization (SR-IOV) is a PCI Express Extended
capability which makes one physical device appear as multiple virtual
devices. The physical device is referred to as Physical Function (PF)
while the virtual devices are referred to as Virtual Functions (VF).
Allocation of the VF can be dynamically controlled by the PF via
registers encapsulated in the capability. By default, this feature is
not enabled and the PF behaves as traditional PCIe device. Once it's
turned on, each VF's PCI configuration space can be accessed by its own
Bus, Device and Function Number (Routing ID). And each VF also has PCI
Memory Space, which is used to map its register set. VF device driver
operates on the register set so it can be functional and appear as a
real existing PCI device.

2. User Guide

2.1 How can I enable SR-IOV capability

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
Multiple methods are available for SR-IOV enablement.
In the first method, the device driver (PF driver) will control the
enabling and disabling of the capability via API provided by SR-IOV core.
If the hardware has SR-IOV capability, loading its PF driver would
enable it and all VFs associated with the PF.  Some PF drivers require
a module parameter to be set to determine the number of VFs to enable.
In the second method, a write to the sysfs file sriov_numvfs will
enable and disable the VFs associated with a PCIe PF.  This method
enables per-PF, VF enable/disable values versus the first method,
which applies to all PFs of the same device.  Additionally, the
PCI SRIOV core support ensures that enable/disable operations are
valid to reduce duplication in multiple drivers for the same
checks, e.g., check numvfs == 0 if enabling VFs, ensure
numvfs <= totalvfs.
The second method is the recommended method for new/future VF devices.
45 46 47 48 49 50 51 52 53 54 55 56

2.2 How can I use the Virtual Functions

The VF is treated as hot-plugged PCI devices in the kernel, so they
should be able to work in the same way as real PCI devices. The VF
requires device driver that is same as a normal PCI device's.

3. Developer Guide

3.1 SR-IOV API

To enable SR-IOV capability:
57
(a) For the first method, in the driver:
58 59
	int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
	'nr_virtfn' is number of VFs to be enabled.
60 61 62
(b) For the second method, from sysfs:
	echo 'nr_virtfn' > \
        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
63 64

To disable SR-IOV capability:
65
(a) For the first method, in the driver:
66
	void pci_disable_sriov(struct pci_dev *dev);
67 68 69
(b) For the second method, from sysfs:
	echo  0 > \
        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
70

71 72 73 74 75 76 77 78 79 80 81 82
To enable auto probing VFs by a compatible driver on the host, run
command below before enabling SR-IOV capabilities. This is the
default behavior.
	echo 1 > \
        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe

To disable auto probing VFs by a compatible driver on the host, run
command below before enabling SR-IOV capabilities. Updating this
entry will not affect VFs which are already probed.
	echo  0 > \
        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe

83 84 85 86
3.2 Usage example

Following piece of code illustrates the usage of the SR-IOV API.

87
static int dev_probe(struct pci_dev *dev, const struct pci_device_id *id)
88 89 90 91 92 93 94 95
{
	pci_enable_sriov(dev, NR_VIRTFN);

	...

	return 0;
}

96
static void dev_remove(struct pci_dev *dev)
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
{
	pci_disable_sriov(dev);

	...
}

static int dev_suspend(struct pci_dev *dev, pm_message_t state)
{
	...

	return 0;
}

static int dev_resume(struct pci_dev *dev)
{
	...

	return 0;
}

static void dev_shutdown(struct pci_dev *dev)
{
	...
}

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
static int dev_sriov_configure(struct pci_dev *dev, int numvfs)
{
	if (numvfs > 0) {
		...
		pci_enable_sriov(dev, numvfs);
		...
		return numvfs;
	}
	if (numvfs == 0) {
		....
		pci_disable_sriov(dev);
		...
		return 0;
	}
}

138 139 140 141
static struct pci_driver dev_driver = {
	.name =		"SR-IOV Physical Function driver",
	.id_table =	dev_id_table,
	.probe =	dev_probe,
142
	.remove =	dev_remove,
143 144 145
	.suspend =	dev_suspend,
	.resume =	dev_resume,
	.shutdown =	dev_shutdown,
146
	.sriov_configure = dev_sriov_configure,
147
};