forked from mirrors/linux
		
	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: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
		
							parent
							
								
									7c1b058c8b
								
							
						
					
					
						commit
						273df96353
					
				
					 4 changed files with 37 additions and 10 deletions
				
			
		|  | @ -1893,6 +1893,8 @@ static void arm_smmu_get_resv_regions(struct device *dev, | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	list_add_tail(®ion->list, head); | 	list_add_tail(®ion->list, head); | ||||||
|  | 
 | ||||||
|  | 	iommu_dma_get_resv_regions(dev, head); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void arm_smmu_put_resv_regions(struct device *dev, | static void arm_smmu_put_resv_regions(struct device *dev, | ||||||
|  |  | ||||||
|  | @ -1613,6 +1613,8 @@ static void arm_smmu_get_resv_regions(struct device *dev, | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	list_add_tail(®ion->list, head); | 	list_add_tail(®ion->list, head); | ||||||
|  | 
 | ||||||
|  | 	iommu_dma_get_resv_regions(dev, head); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void arm_smmu_put_resv_regions(struct device *dev, | static void arm_smmu_put_resv_regions(struct device *dev, | ||||||
|  |  | ||||||
|  | @ -167,22 +167,43 @@ void iommu_put_dma_cookie(struct iommu_domain *domain) | ||||||
| } | } | ||||||
| EXPORT_SYMBOL(iommu_put_dma_cookie); | 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; | 	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) { | 	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) | 		if (resource_type(window->res) != IORESOURCE_MEM) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		lo = iova_pfn(iovad, window->res->start - window->offset); | 		start = window->res->start - window->offset; | ||||||
| 		hi = iova_pfn(iovad, window->res->end - window->offset); | 		length = window->res->end - window->res->start + 1; | ||||||
| 		reserve_iova(iovad, lo, hi); | 		region = iommu_alloc_resv_region(start, length, 0, | ||||||
|  | 				IOMMU_RESV_RESERVED); | ||||||
|  | 		if (!region) | ||||||
|  | 			return; | ||||||
|  | 
 | ||||||
|  | 		list_add_tail(®ion->list, list); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | EXPORT_SYMBOL(iommu_dma_get_resv_regions); | ||||||
| 
 | 
 | ||||||
| static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie, | static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie, | ||||||
| 		phys_addr_t start, phys_addr_t end) | 		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); | 	LIST_HEAD(resv_regions); | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
| 
 | 
 | ||||||
| 	if (dev_is_pci(dev)) |  | ||||||
| 		iova_reserve_pci_windows(to_pci_dev(dev), iovad); |  | ||||||
| 
 |  | ||||||
| 	iommu_get_resv_regions(dev, &resv_regions); | 	iommu_get_resv_regions(dev, &resv_regions); | ||||||
| 	list_for_each_entry(region, &resv_regions, list) { | 	list_for_each_entry(region, &resv_regions, list) { | ||||||
| 		unsigned long lo, hi; | 		unsigned long lo, hi; | ||||||
|  |  | ||||||
|  | @ -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... */ | /* 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_map_msi_msg(int irq, struct msi_msg *msg); | ||||||
|  | void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list); | ||||||
| 
 | 
 | ||||||
| #else | #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	/* CONFIG_IOMMU_DMA */ | ||||||
| #endif	/* __KERNEL__ */ | #endif	/* __KERNEL__ */ | ||||||
| #endif	/* __DMA_IOMMU_H */ | #endif	/* __DMA_IOMMU_H */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Robin Murphy
						Robin Murphy