iommu/dma: Make PCI window reservation generic
authorRobin Murphy <robin.murphy@arm.com>
Thu, 16 Mar 2017 17:00:19 +0000 (17:00 +0000)
committerJoerg Roedel <jroedel@suse.de>
Wed, 22 Mar 2017 15:18:59 +0000 (16:18 +0100)
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>
drivers/iommu/arm-smmu-v3.c
drivers/iommu/arm-smmu.c
drivers/iommu/dma-iommu.c
include/linux/dma-iommu.h

index 591bb96047c9765fd3e0fb536d3f26ca0a5f187f..bbd46efbe0754f6c20dbef4d249f0389eda79f73 100644 (file)
@@ -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,
index b493c99e17f74de338805167c3ddb104e3354b62..9b33700b7c69a1b3c2416e3ee6e9ea38f3ef827f 100644 (file)
@@ -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,
index 5787f919f4ec8348d699d721e755c7b6afedaa8f..85652110c8ff1d5fda50cba31006c131deebeaeb 100644 (file)
@@ -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;
index 5725c94b1f121ece268c0fd8558cb94770c2c9cd..b6635a46fc7c75c490e65e49043048639593c0d8 100644 (file)
@@ -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 */