IOMMU: adjust add/remove operation parameters ... to use a (struct pci_dev *, devfn) pair. --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -83,14 +83,14 @@ static void disable_translation(u32 *dte } static void amd_iommu_setup_domain_device( - struct domain *domain, struct amd_iommu *iommu, int bdf) + struct domain *domain, struct amd_iommu *iommu, + u8 devfn, struct pci_dev *pdev) { void *dte; unsigned long flags; int req_id, valid = 1; int dte_i = 0; - u8 bus = PCI_BUS(bdf); - u8 devfn = PCI_DEVFN2(bdf); + u8 bus = pdev->bus; struct hvm_iommu *hd = domain_hvm_iommu(domain); @@ -103,7 +103,7 @@ static void amd_iommu_setup_domain_devic dte_i = 1; /* get device-table entry */ - req_id = get_dma_requestor_id(iommu->seg, bdf); + req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(bus, devfn)); dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE); spin_lock_irqsave(&iommu->lock, flags); @@ -115,7 +115,7 @@ static void amd_iommu_setup_domain_devic (u32 *)dte, page_to_maddr(hd->root_table), hd->domain_id, hd->paging_mode, valid); - if ( pci_ats_device(iommu->seg, bus, devfn) && + if ( pci_ats_device(iommu->seg, bus, pdev->devfn) && iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) ) iommu_dte_set_iotlb((u32 *)dte, dte_i); @@ -132,32 +132,31 @@ static void amd_iommu_setup_domain_devic ASSERT(spin_is_locked(&pcidevs_lock)); - if ( pci_ats_device(iommu->seg, bus, devfn) && - !pci_ats_enabled(iommu->seg, bus, devfn) ) + if ( pci_ats_device(iommu->seg, bus, pdev->devfn) && + !pci_ats_enabled(iommu->seg, bus, pdev->devfn) ) { - struct pci_dev *pdev; + if ( devfn == pdev->devfn ) + enable_ats_device(iommu->seg, bus, devfn); - enable_ats_device(iommu->seg, bus, devfn); - - ASSERT(spin_is_locked(&pcidevs_lock)); - pdev = pci_get_pdev(iommu->seg, bus, devfn); - - ASSERT( pdev != NULL ); amd_iommu_flush_iotlb(pdev, INV_IOMMU_ALL_PAGES_ADDRESS, 0); } } -static void __init amd_iommu_setup_dom0_device(struct pci_dev *pdev) +static int __init amd_iommu_setup_dom0_device(u8 devfn, struct pci_dev *pdev) { int bdf = PCI_BDF2(pdev->bus, pdev->devfn); struct amd_iommu *iommu = find_iommu_for_device(pdev->seg, bdf); - if ( likely(iommu != NULL) ) - amd_iommu_setup_domain_device(pdev->domain, iommu, bdf); - else + if ( unlikely(!iommu) ) + { AMD_IOMMU_DEBUG("No iommu for device %04x:%02x:%02x.%u\n", pdev->seg, pdev->bus, - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + PCI_SLOT(devfn), PCI_FUNC(devfn)); + return -ENODEV; + } + + amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev); + return 0; } int __init amd_iov_detect(void) @@ -295,16 +294,16 @@ static void __init amd_iommu_dom0_init(s } void amd_iommu_disable_domain_device(struct domain *domain, - struct amd_iommu *iommu, int bdf) + struct amd_iommu *iommu, + u8 devfn, struct pci_dev *pdev) { void *dte; unsigned long flags; int req_id; - u8 bus = PCI_BUS(bdf); - u8 devfn = PCI_DEVFN2(bdf); + u8 bus = pdev->bus; BUG_ON ( iommu->dev_table.buffer == NULL ); - req_id = get_dma_requestor_id(iommu->seg, bdf); + req_id = get_dma_requestor_id(iommu->seg, PCI_BDF2(bus, devfn)); dte = iommu->dev_table.buffer + (req_id * IOMMU_DEV_TABLE_ENTRY_SIZE); spin_lock_irqsave(&iommu->lock, flags); @@ -312,7 +311,7 @@ void amd_iommu_disable_domain_device(str { disable_translation((u32 *)dte); - if ( pci_ats_device(iommu->seg, bus, devfn) && + if ( pci_ats_device(iommu->seg, bus, pdev->devfn) && iommu_has_cap(iommu, PCI_CAP_IOTLB_SHIFT) ) iommu_dte_set_iotlb((u32 *)dte, 0); @@ -327,7 +326,8 @@ void amd_iommu_disable_domain_device(str ASSERT(spin_is_locked(&pcidevs_lock)); - if ( pci_ats_device(iommu->seg, bus, devfn) && + if ( devfn == pdev->devfn && + pci_ats_device(iommu->seg, bus, devfn) && pci_ats_enabled(iommu->seg, bus, devfn) ) disable_ats_device(iommu->seg, bus, devfn); } @@ -350,7 +350,7 @@ static int reassign_device(struct domain return -ENODEV; } - amd_iommu_disable_domain_device(source, iommu, bdf); + amd_iommu_disable_domain_device(source, iommu, devfn, pdev); if ( devfn == pdev->devfn ) { @@ -363,7 +363,7 @@ static int reassign_device(struct domain if ( t->root_table == NULL ) allocate_domain_resources(t); - amd_iommu_setup_domain_device(target, iommu, bdf); + amd_iommu_setup_domain_device(target, iommu, devfn, pdev); AMD_IOMMU_DEBUG("Re-assign %04x:%02x:%02x.%u from dom%d to dom%d\n", pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), source->domain_id, target->domain_id); @@ -449,7 +449,7 @@ static void amd_iommu_domain_destroy(str amd_iommu_flush_all_pages(d); } -static int amd_iommu_add_device(struct pci_dev *pdev) +static int amd_iommu_add_device(u8 devfn, struct pci_dev *pdev) { struct amd_iommu *iommu; u16 bdf; @@ -462,16 +462,16 @@ static int amd_iommu_add_device(struct p { AMD_IOMMU_DEBUG("Fail to find iommu." " %04x:%02x:%02x.%u cannot be assigned to dom%d\n", - pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn), pdev->domain->domain_id); + pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + pdev->domain->domain_id); return -ENODEV; } - amd_iommu_setup_domain_device(pdev->domain, iommu, bdf); + amd_iommu_setup_domain_device(pdev->domain, iommu, devfn, pdev); return 0; } -static int amd_iommu_remove_device(struct pci_dev *pdev) +static int amd_iommu_remove_device(u8 devfn, struct pci_dev *pdev) { struct amd_iommu *iommu; u16 bdf; @@ -484,12 +484,12 @@ static int amd_iommu_remove_device(struc { AMD_IOMMU_DEBUG("Fail to find iommu." " %04x:%02x:%02x.%u cannot be removed from dom%d\n", - pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn), pdev->domain->domain_id); + pdev->seg, pdev->bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + pdev->domain->domain_id); return -ENODEV; } - amd_iommu_disable_domain_device(pdev->domain, iommu, bdf); + amd_iommu_disable_domain_device(pdev->domain, iommu, devfn, pdev); return 0; } --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -164,7 +164,7 @@ int iommu_add_device(struct pci_dev *pde if ( !iommu_enabled || !hd->platform_ops ) return 0; - return hd->platform_ops->add_device(pdev); + return hd->platform_ops->add_device(pdev->devfn, pdev); } int iommu_enable_device(struct pci_dev *pdev) @@ -194,7 +194,7 @@ int iommu_remove_device(struct pci_dev * if ( !iommu_enabled || !hd->platform_ops ) return 0; - return hd->platform_ops->remove_device(pdev); + return hd->platform_ops->remove_device(pdev->devfn, pdev); } /* --- a/xen/drivers/passthrough/pci.c +++ b/xen/drivers/passthrough/pci.c @@ -743,7 +743,7 @@ int __init scan_pci_devices(void) struct setup_dom0 { struct domain *d; - void (*handler)(struct pci_dev *); + int (*handler)(u8 devfn, struct pci_dev *); }; static int __init _setup_dom0_pci_devices(struct pci_seg *pseg, void *arg) @@ -764,12 +764,12 @@ static int __init _setup_dom0_pci_device { pdev->domain = ctxt->d; list_add(&pdev->domain_list, &ctxt->d->arch.pdev_list); - ctxt->handler(pdev); + ctxt->handler(devfn, pdev); } else if ( pdev->domain == dom_xen ) { pdev->domain = ctxt->d; - ctxt->handler(pdev); + ctxt->handler(devfn, pdev); pdev->domain = dom_xen; } else if ( pdev->domain != ctxt->d ) @@ -783,7 +783,7 @@ static int __init _setup_dom0_pci_device } void __init setup_dom0_pci_devices( - struct domain *d, void (*handler)(struct pci_dev *)) + struct domain *d, int (*handler)(u8 devfn, struct pci_dev *)) { struct setup_dom0 ctxt = { .d = d, .handler = handler }; --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -50,7 +50,7 @@ int nr_iommus; static struct tasklet vtd_fault_tasklet; -static void setup_dom0_device(struct pci_dev *); +static int setup_dom0_device(u8 devfn, struct pci_dev *); static void setup_dom0_rmrr(struct domain *d); static int domain_iommu_domid(struct domain *d, @@ -1873,7 +1873,7 @@ static int rmrr_identity_mapping(struct return 0; } -static int intel_iommu_add_device(struct pci_dev *pdev) +static int intel_iommu_add_device(u8 devfn, struct pci_dev *pdev) { struct acpi_rmrr_unit *rmrr; u16 bdf; @@ -1884,8 +1884,7 @@ static int intel_iommu_add_device(struct if ( !pdev->domain ) return -EINVAL; - ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, - pdev->devfn); + ret = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn); if ( ret ) { dprintk(XENLOG_ERR VTDPREFIX, "d%d: context mapping failed\n", @@ -1897,7 +1896,7 @@ static int intel_iommu_add_device(struct { if ( rmrr->segment == pdev->seg && PCI_BUS(bdf) == pdev->bus && - PCI_DEVFN2(bdf) == pdev->devfn ) + PCI_DEVFN2(bdf) == devfn ) { ret = rmrr_identity_mapping(pdev->domain, rmrr); if ( ret ) @@ -1922,7 +1921,7 @@ static int intel_iommu_enable_device(str return ret >= 0 ? 0 : ret; } -static int intel_iommu_remove_device(struct pci_dev *pdev) +static int intel_iommu_remove_device(u8 devfn, struct pci_dev *pdev) { struct acpi_rmrr_unit *rmrr; u16 bdf; @@ -1940,19 +1939,22 @@ static int intel_iommu_remove_device(str { if ( rmrr->segment == pdev->seg && PCI_BUS(bdf) == pdev->bus && - PCI_DEVFN2(bdf) == pdev->devfn ) + PCI_DEVFN2(bdf) == devfn ) return 0; } } - return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus, - pdev->devfn); + return domain_context_unmap(pdev->domain, pdev->seg, pdev->bus, devfn); } -static void __init setup_dom0_device(struct pci_dev *pdev) +static int __init setup_dom0_device(u8 devfn, struct pci_dev *pdev) { - domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, pdev->devfn); - pci_vtd_quirk(pdev); + int err; + + err = domain_context_mapping(pdev->domain, pdev->seg, pdev->bus, devfn); + if ( !err && devfn == pdev->devfn ) + pci_vtd_quirk(pdev); + return err; } void clear_fault_bits(struct iommu *iommu) --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -94,9 +94,9 @@ struct msi_msg; struct iommu_ops { int (*init)(struct domain *d); void (*dom0_init)(struct domain *d); - int (*add_device)(struct pci_dev *pdev); + int (*add_device)(u8 devfn, struct pci_dev *); int (*enable_device)(struct pci_dev *pdev); - int (*remove_device)(struct pci_dev *pdev); + int (*remove_device)(u8 devfn, struct pci_dev *); int (*assign_device)(struct domain *, u8 devfn, struct pci_dev *); void (*teardown)(struct domain *d); int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn, --- a/xen/include/xen/pci.h +++ b/xen/include/xen/pci.h @@ -100,7 +100,8 @@ struct pci_dev *pci_lock_pdev(int seg, i struct pci_dev *pci_lock_domain_pdev( struct domain *, int seg, int bus, int devfn); -void setup_dom0_pci_devices(struct domain *, void (*)(struct pci_dev *)); +void setup_dom0_pci_devices(struct domain *, + int (*)(u8 devfn, struct pci_dev *)); void pci_release_devices(struct domain *d); int pci_add_segment(u16 seg); const unsigned long *pci_get_ro_map(u16 seg);