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
|
@ -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 New Issue