drivers/pci/iov.c
Source file repositories/reference/linux-study-clean/drivers/pci/iov.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pci/iov.c- Extension
.c- Size
- 32858 bytes
- Lines
- 1380
- Domain
- Representative Device Path
- Bucket
- PCIe NVMe Storage Path
- Inferred role
- Representative Device Path: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/bits.hlinux/log2.hlinux/pci.hlinux/sizes.hlinux/slab.hlinux/export.hlinux/string.hlinux/delay.hasm/div64.hpci.h
Detected Declarations
function Copyrightfunction pci_iov_virtfn_devfnfunction pci_iov_vf_idfunction removefunction pci_iov_set_numvfsfunction compute_max_vf_busesfunction virtfn_remove_busfunction pci_iov_resource_sizefunction pci_iov_resource_set_sizefunction pci_iov_is_memory_decoding_enabledfunction pci_read_vf_config_commonfunction pci_iov_sysfs_linkfunction sriov_vf_total_msix_showfunction sriov_vf_msix_count_storefunction sriov_vf_attrs_are_visiblefunction pci_iov_add_virtfnfunction pci_iov_remove_virtfnfunction sriov_totalvfs_showfunction sriov_numvfs_showfunction sriov_numvfs_storefunction sriov_offset_showfunction sriov_stride_showfunction sriov_vf_device_showfunction sriov_drivers_autoprobe_showfunction sriov_drivers_autoprobe_storefunction sriov_pf_attrs_are_visiblefunction pcibios_sriov_enablefunction pcibios_sriov_disablefunction sriov_add_vfsfunction sriov_enablefunction sriov_del_vfsfunction sriov_disablefunction sriov_initfunction sriov_releasefunction sriov_restore_vf_rebar_statefunction sriov_restore_statefunction pci_iov_initfunction pci_iov_releasefunction pci_iov_removefunction pci_iov_update_resourcefunction pcibios_iov_resource_alignmentfunction pci_sriov_resource_alignmentfunction pci_restore_iov_statefunction pci_vf_drivers_autoprobefunction busesfunction list_for_each_entryfunction pci_enable_sriovfunction pci_disable_sriov
Annotated Snippet
void *pci_iov_get_pf_drvdata(struct pci_dev *dev, struct pci_driver *pf_driver)
{
struct pci_dev *pf_dev;
if (!dev->is_virtfn)
return ERR_PTR(-EINVAL);
pf_dev = dev->physfn;
if (pf_dev->driver != pf_driver)
return ERR_PTR(-EINVAL);
return pci_get_drvdata(pf_dev);
}
EXPORT_SYMBOL_GPL(pci_iov_get_pf_drvdata);
/*
* Per SR-IOV spec sec 3.3.10 and 3.3.11, First VF Offset and VF Stride may
* change when NumVFs changes.
*
* Update iov->offset and iov->stride when NumVFs is written.
*/
static inline void pci_iov_set_numvfs(struct pci_dev *dev, int nr_virtfn)
{
struct pci_sriov *iov = dev->sriov;
pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn);
pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &iov->offset);
pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &iov->stride);
}
/*
* The PF consumes one bus number. NumVFs, First VF Offset, and VF Stride
* determine how many additional bus numbers will be consumed by VFs.
*
* Iterate over all valid NumVFs, validate offset and stride, and calculate
* the maximum number of bus numbers that could ever be required.
*/
static int compute_max_vf_buses(struct pci_dev *dev)
{
struct pci_sriov *iov = dev->sriov;
int nr_virtfn, busnr, rc = 0;
for (nr_virtfn = iov->total_VFs; nr_virtfn; nr_virtfn--) {
pci_iov_set_numvfs(dev, nr_virtfn);
if (!iov->offset || (nr_virtfn > 1 && !iov->stride)) {
rc = -EIO;
goto out;
}
busnr = pci_iov_virtfn_bus(dev, nr_virtfn - 1);
if (busnr > iov->max_VF_buses)
iov->max_VF_buses = busnr;
}
out:
pci_iov_set_numvfs(dev, 0);
return rc;
}
static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
{
struct pci_bus *child;
if (bus->number == busnr)
return bus;
child = pci_find_bus(pci_domain_nr(bus), busnr);
if (child)
return child;
child = pci_add_new_bus(bus, NULL, busnr);
if (!child)
return NULL;
pci_bus_insert_busn_res(child, busnr, busnr);
return child;
}
static void virtfn_remove_bus(struct pci_bus *physbus, struct pci_bus *virtbus)
{
if (physbus != virtbus && list_empty(&virtbus->devices))
pci_remove_bus(virtbus);
}
resource_size_t pci_iov_resource_size(struct pci_dev *dev, int resno)
{
if (!dev->is_physfn)
return 0;
return dev->sriov->barsz[pci_resource_num_to_vf_bar(resno)];
}
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/bits.h`, `linux/log2.h`, `linux/pci.h`, `linux/sizes.h`, `linux/slab.h`, `linux/export.h`, `linux/string.h`.
- Detected declarations: `function Copyright`, `function pci_iov_virtfn_devfn`, `function pci_iov_vf_id`, `function remove`, `function pci_iov_set_numvfs`, `function compute_max_vf_buses`, `function virtfn_remove_bus`, `function pci_iov_resource_size`, `function pci_iov_resource_set_size`, `function pci_iov_is_memory_decoding_enabled`.
- Atlas domain: Representative Device Path / PCIe NVMe Storage Path.
- Implementation status: pattern implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.