Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 273df963 authored by Robin Murphy's avatar Robin Murphy Committed by Joerg Roedel
Browse files

iommu/dma: Make PCI window reservation generic



Now that we're applying the IOMMU API reserved regions to our IOVA
domains, we shouldn't need to privately special-case PCI windows, or
indeed anything else which isn't specific to our iommu-dma layer.
However, since those aren't IOMMU-specific either, rather than start
duplicating code into IOMMU drivers let's transform the existing
function into an iommu_get_resv_regions() helper that they can share.

Signed-off-by: default avatarRobin Murphy <robin.murphy@arm.com>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 7c1b058c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1893,6 +1893,8 @@ static void arm_smmu_get_resv_regions(struct device *dev,
		return;

	list_add_tail(&region->list, head);

	iommu_dma_get_resv_regions(dev, head);
}

static void arm_smmu_put_resv_regions(struct device *dev,
+2 −0
Original line number Diff line number Diff line
@@ -1613,6 +1613,8 @@ static void arm_smmu_get_resv_regions(struct device *dev,
		return;

	list_add_tail(&region->list, head);

	iommu_dma_get_resv_regions(dev, head);
}

static void arm_smmu_put_resv_regions(struct device *dev,
+28 −10
Original line number Diff line number Diff line
@@ -167,22 +167,43 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
}
EXPORT_SYMBOL(iommu_put_dma_cookie);

static void iova_reserve_pci_windows(struct pci_dev *dev,
		struct iova_domain *iovad)
/**
 * iommu_dma_get_resv_regions - Reserved region driver helper
 * @dev: Device from iommu_get_resv_regions()
 * @list: Reserved region list from iommu_get_resv_regions()
 *
 * IOMMU drivers can use this to implement their .get_resv_regions callback
 * for general non-IOMMU-specific reservations. Currently, this covers host
 * bridge windows for PCI devices.
 */
void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
{
	struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);
	struct pci_host_bridge *bridge;
	struct resource_entry *window;
	unsigned long lo, hi;

	if (!dev_is_pci(dev))
		return;

	bridge = pci_find_host_bridge(to_pci_dev(dev)->bus);
	resource_list_for_each_entry(window, &bridge->windows) {
		struct iommu_resv_region *region;
		phys_addr_t start;
		size_t length;

		if (resource_type(window->res) != IORESOURCE_MEM)
			continue;

		lo = iova_pfn(iovad, window->res->start - window->offset);
		hi = iova_pfn(iovad, window->res->end - window->offset);
		reserve_iova(iovad, lo, hi);
		start = window->res->start - window->offset;
		length = window->res->end - window->res->start + 1;
		region = iommu_alloc_resv_region(start, length, 0,
				IOMMU_RESV_RESERVED);
		if (!region)
			return;

		list_add_tail(&region->list, list);
	}
}
EXPORT_SYMBOL(iommu_dma_get_resv_regions);

static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie,
		phys_addr_t start, phys_addr_t end)
@@ -218,9 +239,6 @@ static int iova_reserve_iommu_regions(struct device *dev,
	LIST_HEAD(resv_regions);
	int ret = 0;

	if (dev_is_pci(dev))
		iova_reserve_pci_windows(to_pci_dev(dev), iovad);

	iommu_get_resv_regions(dev, &resv_regions);
	list_for_each_entry(region, &resv_regions, list) {
		unsigned long lo, hi;
+5 −0
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);

/* The DMA API isn't _quite_ the whole story, though... */
void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);

#else

@@ -100,6 +101,10 @@ static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
{
}

static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
{
}

#endif	/* CONFIG_IOMMU_DMA */
#endif	/* __KERNEL__ */
#endif	/* __DMA_IOMMU_H */