static int set_msi_sid(struct irte *irte, struct pci_dev *dev) { struct set_msi_sid_data data; if (!irte || !dev) return -1; pci_for_each_dma_alias(dev, set_msi_sid_cb, &data); /* * DMA alias provides us with a PCI device and alias. The only case * where the it will return an alias on a different bus than the * device is the case of a PCIe-to-PCI bridge, where the alias is for * the subordinate bus. In this case we can only verify the bus. * * If the alias device is on a different bus than our source device * then we have a topology based alias, use it. * * Otherwise, the alias is for a device DMA quirk and we cannot * assume that MSI uses the same requester ID. Therefore use the * original device. */ if (PCI_BUS_NUM(data.alias) != data.pdev->bus->number) set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, PCI_DEVID(PCI_BUS_NUM(data.alias), dev->bus->number)); else if (data.pdev->bus->number != dev->bus->number) set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, data.alias); else set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, PCI_DEVID(dev->bus->number, dev->devfn)); return 0; }
static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, msi_alloc_info_t *info) { struct pci_dev *pdev, *alias_dev; struct msi_domain_info *msi_info; int alias_count = 0; if (!dev_is_pci(dev)) return -EINVAL; msi_info = msi_get_domain_info(domain->parent); pdev = to_pci_dev(dev); /* * If pdev is downstream of any aliasing bridges, take an upper * bound of how many other vectors could map to the same DevID. */ pci_for_each_dma_alias(pdev, its_get_pci_alias, &alias_dev); if (alias_dev != pdev && alias_dev->subordinate) pci_walk_bus(alias_dev->subordinate, its_pci_msi_vec_count, &alias_count); /* ITS specific DeviceID, as the core ITS ignores dev. */ info->scratchpad[0].ul = pci_msi_domain_get_msi_rid(domain, pdev); return msi_info->ops->msi_prepare(domain->parent, dev, max(nvec, alias_count), info); }
/* * Allocate a pasid table for @dev. It should be called in a * single-thread context. */ int intel_pasid_alloc_table(struct device *dev) { struct device_domain_info *info; struct pasid_table *pasid_table; struct pasid_table_opaque data; struct page *pages; size_t size, count; int ret, order; info = dev->archdata.iommu; if (WARN_ON(!info || !dev_is_pci(dev) || !info->pasid_supported || info->pasid_table)) return -EINVAL; /* DMA alias device already has a pasid table, use it: */ data.pasid_table = &pasid_table; ret = pci_for_each_dma_alias(to_pci_dev(dev), &get_alias_pasid_table, &data); if (ret) goto attach_out; pasid_table = kzalloc(sizeof(*pasid_table), GFP_ATOMIC); if (!pasid_table) return -ENOMEM; INIT_LIST_HEAD(&pasid_table->dev); size = sizeof(struct pasid_entry); count = min_t(int, pci_max_pasids(to_pci_dev(dev)), intel_pasid_max_id); order = get_order(size * count); pages = alloc_pages_node(info->iommu->node, GFP_ATOMIC | __GFP_ZERO, order); if (!pages) return -ENOMEM; pasid_table->table = page_address(pages); pasid_table->order = order; pasid_table->max_pasid = count; attach_out: device_attach_pasid_table(info, pasid_table); return 0; }
static int set_msi_sid(struct irte *irte, struct pci_dev *dev) { struct set_msi_sid_data data; if (!irte || !dev) return -1; data.count = 0; data.busmatch_count = 0; pci_for_each_dma_alias(dev, set_msi_sid_cb, &data); /* * DMA alias provides us with a PCI device and alias. The only case * where the it will return an alias on a different bus than the * device is the case of a PCIe-to-PCI bridge, where the alias is for * the subordinate bus. In this case we can only verify the bus. * * If there are multiple aliases, all with the same bus number, * then all we can do is verify the bus. This is typical in NTB * hardware which use proxy IDs where the device will generate traffic * from multiple devfn numbers on the same bus. * * If the alias device is on a different bus than our source device * then we have a topology based alias, use it. * * Otherwise, the alias is for a device DMA quirk and we cannot * assume that MSI uses the same requester ID. Therefore use the * original device. */ if (PCI_BUS_NUM(data.alias) != data.pdev->bus->number) set_irte_verify_bus(irte, PCI_BUS_NUM(data.alias), dev->bus->number); else if (data.count >= 2 && data.busmatch_count == data.count) set_irte_verify_bus(irte, dev->bus->number, dev->bus->number); else if (data.pdev->bus->number != dev->bus->number) set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, data.alias); else set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, pci_dev_id(dev)); return 0; }
static int its_pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec, msi_alloc_info_t *info) { struct pci_dev *pdev; struct its_pci_alias dev_alias; struct msi_domain_info *msi_info; if (!dev_is_pci(dev)) return -EINVAL; msi_info = msi_get_domain_info(domain->parent); pdev = to_pci_dev(dev); dev_alias.pdev = pdev; dev_alias.count = nvec; pci_for_each_dma_alias(pdev, its_get_pci_alias, &dev_alias); /* ITS specific DeviceID, as the core ITS ignores dev. */ info->scratchpad[0].ul = dev_alias.dev_id; return msi_info->ops->msi_prepare(domain->parent, dev, dev_alias.count, info); }