VF device driver call:
pci_enable_sriov -> sriov_enable -> pci_iov_add_virtfn -> pci_device_add -> device_add ->
1 2 |
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:
1 2 3 4 5 6 7 8 9 10 |
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;”
1 2 3 |
if (action == BUS_NOTIFY_ADD_DEVICE) { if (ops->add_device) return ops->add_device(dev); |
ops->add_device:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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