VF device driver call:
pci_enable_sriov -> sriov_enable -> pci_iov_add_virtfn -> pci_device_add -> device_add ->
blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_ADD_DEVICE, dev);
pci bus register a iommu notifier will be called when device_add start to notify:
static int __init pci_iommu_init(void) { if (iommu_detected) intel_iommu_init(); return 0; } /* Must execute after PCI subsystem */ fs_initcall(pci_iommu_init);
intel_iommu_init -> iommu_bus_init -> “nb->notifier_call = iommu_bus_notifier;”
if (action == BUS_NOTIFY_ADD_DEVICE) { if (ops->add_device) return ops->add_device(dev);
ops->add_device:
static struct iommu_ops intel_iommu_ops = { .capable = intel_iommu_capable, .domain_alloc = intel_iommu_domain_alloc, .domain_free = intel_iommu_domain_free, .attach_dev = intel_iommu_attach_device, .detach_dev = intel_iommu_detach_device, .map = intel_iommu_map, .unmap = intel_iommu_unmap, .map_sg = default_iommu_map_sg, .iova_to_phys = intel_iommu_iova_to_phys, .add_device =intel_iommu_add_device, .remove_device = intel_iommu_remove_device, .pgsize_bitmap = INTEL_IOMMU_PGSIZES, };
intel_iommu_add_device:
static int intel_iommu_add_device(struct device *dev) { struct intel_iommu *iommu; struct iommu_group *group; u8 bus, devfn; iommu = device_to_iommu(dev, &bus, &devfn); if (!iommu) return -ENODEV; iommu_device_link(iommu->iommu_dev, dev); group = iommu_group_get_for_dev(dev); if (IS_ERR(group)) return PTR_ERR(group); iommu_group_put(group); return 0; }
iommu_group_get_for_dev:
this will find or create an iommu group for the VF device