]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/iommu/amd_iommu.c
Merge branches 'iommu/fixes', 'arm/exynos', 'arm/renesas', 'arm/smmu', 'arm/mediatek...
[mirror_ubuntu-bionic-kernel.git] / drivers / iommu / amd_iommu.c
index 3ef0f42984f2b1ec716509203988f9ebb70533cb..1b5b8c5361c506f2b835642eff2e3e57fbdf1370 100644 (file)
@@ -112,7 +112,7 @@ static struct timer_list queue_timer;
  * Domain for untranslated devices - only allocated
  * if iommu=pt passed on kernel cmd line.
  */
-static const struct iommu_ops amd_iommu_ops;
+const struct iommu_ops amd_iommu_ops;
 
 static ATOMIC_NOTIFIER_HEAD(ppr_notifier);
 int amd_iommu_max_glx_val = -1;
@@ -445,6 +445,7 @@ static void init_iommu_group(struct device *dev)
 static int iommu_init_device(struct device *dev)
 {
        struct iommu_dev_data *dev_data;
+       struct amd_iommu *iommu;
        int devid;
 
        if (dev->archdata.iommu)
@@ -454,6 +455,8 @@ static int iommu_init_device(struct device *dev)
        if (devid < 0)
                return devid;
 
+       iommu = amd_iommu_rlookup_table[devid];
+
        dev_data = find_dev_data(devid);
        if (!dev_data)
                return -ENOMEM;
@@ -469,8 +472,7 @@ static int iommu_init_device(struct device *dev)
 
        dev->archdata.iommu = dev_data;
 
-       iommu_device_link(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
-                         dev);
+       iommu_device_link(&iommu->iommu, dev);
 
        return 0;
 }
@@ -495,13 +497,16 @@ static void iommu_ignore_device(struct device *dev)
 
 static void iommu_uninit_device(struct device *dev)
 {
-       int devid;
        struct iommu_dev_data *dev_data;
+       struct amd_iommu *iommu;
+       int devid;
 
        devid = get_device_id(dev);
        if (devid < 0)
                return;
 
+       iommu = amd_iommu_rlookup_table[devid];
+
        dev_data = search_dev_data(devid);
        if (!dev_data)
                return;
@@ -509,8 +514,7 @@ static void iommu_uninit_device(struct device *dev)
        if (dev_data->domain)
                detach_device(dev);
 
-       iommu_device_unlink(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
-                           dev);
+       iommu_device_unlink(&iommu->iommu, dev);
 
        iommu_group_remove_device(dev);
 
@@ -3161,9 +3165,10 @@ static bool amd_iommu_capable(enum iommu_cap cap)
        return false;
 }
 
-static void amd_iommu_get_dm_regions(struct device *dev,
-                                    struct list_head *head)
+static void amd_iommu_get_resv_regions(struct device *dev,
+                                      struct list_head *head)
 {
+       struct iommu_resv_region *region;
        struct unity_map_entry *entry;
        int devid;
 
@@ -3172,41 +3177,56 @@ static void amd_iommu_get_dm_regions(struct device *dev,
                return;
 
        list_for_each_entry(entry, &amd_iommu_unity_map, list) {
-               struct iommu_dm_region *region;
+               size_t length;
+               int prot = 0;
 
                if (devid < entry->devid_start || devid > entry->devid_end)
                        continue;
 
-               region = kzalloc(sizeof(*region), GFP_KERNEL);
+               length = entry->address_end - entry->address_start;
+               if (entry->prot & IOMMU_PROT_IR)
+                       prot |= IOMMU_READ;
+               if (entry->prot & IOMMU_PROT_IW)
+                       prot |= IOMMU_WRITE;
+
+               region = iommu_alloc_resv_region(entry->address_start,
+                                                length, prot,
+                                                IOMMU_RESV_DIRECT);
                if (!region) {
                        pr_err("Out of memory allocating dm-regions for %s\n",
                                dev_name(dev));
                        return;
                }
-
-               region->start = entry->address_start;
-               region->length = entry->address_end - entry->address_start;
-               if (entry->prot & IOMMU_PROT_IR)
-                       region->prot |= IOMMU_READ;
-               if (entry->prot & IOMMU_PROT_IW)
-                       region->prot |= IOMMU_WRITE;
-
                list_add_tail(&region->list, head);
        }
+
+       region = iommu_alloc_resv_region(MSI_RANGE_START,
+                                        MSI_RANGE_END - MSI_RANGE_START + 1,
+                                        0, IOMMU_RESV_RESERVED);
+       if (!region)
+               return;
+       list_add_tail(&region->list, head);
+
+       region = iommu_alloc_resv_region(HT_RANGE_START,
+                                        HT_RANGE_END - HT_RANGE_START + 1,
+                                        0, IOMMU_RESV_RESERVED);
+       if (!region)
+               return;
+       list_add_tail(&region->list, head);
 }
 
-static void amd_iommu_put_dm_regions(struct device *dev,
+static void amd_iommu_put_resv_regions(struct device *dev,
                                     struct list_head *head)
 {
-       struct iommu_dm_region *entry, *next;
+       struct iommu_resv_region *entry, *next;
 
        list_for_each_entry_safe(entry, next, head, list)
                kfree(entry);
 }
 
-static void amd_iommu_apply_dm_region(struct device *dev,
+static void amd_iommu_apply_resv_region(struct device *dev,
                                      struct iommu_domain *domain,
-                                     struct iommu_dm_region *region)
+                                     struct iommu_resv_region *region)
 {
        struct dma_ops_domain *dma_dom = to_dma_ops_domain(to_pdomain(domain));
        unsigned long start, end;
@@ -3217,7 +3237,7 @@ static void amd_iommu_apply_dm_region(struct device *dev,
        WARN_ON_ONCE(reserve_iova(&dma_dom->iovad, start, end) == NULL);
 }
 
-static const struct iommu_ops amd_iommu_ops = {
+const struct iommu_ops amd_iommu_ops = {
        .capable = amd_iommu_capable,
        .domain_alloc = amd_iommu_domain_alloc,
        .domain_free  = amd_iommu_domain_free,
@@ -3230,9 +3250,9 @@ static const struct iommu_ops amd_iommu_ops = {
        .add_device = amd_iommu_add_device,
        .remove_device = amd_iommu_remove_device,
        .device_group = amd_iommu_device_group,
-       .get_dm_regions = amd_iommu_get_dm_regions,
-       .put_dm_regions = amd_iommu_put_dm_regions,
-       .apply_dm_region = amd_iommu_apply_dm_region,
+       .get_resv_regions = amd_iommu_get_resv_regions,
+       .put_resv_regions = amd_iommu_put_resv_regions,
+       .apply_resv_region = amd_iommu_apply_resv_region,
        .pgsize_bitmap  = AMD_IOMMU_PGSIZES,
 };