Merge tag 'iommu-fixes-v5.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Jan 2019 17:30:03 +0000 (09:30 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Jan 2019 17:30:03 +0000 (09:30 -0800)
Pull IOMMU fixes from Joerg Roedel:
 "A few more fixes this time:

   - Two patches to fix the error path of the map_sg implementation of
     the AMD IOMMU driver.

   - Also a missing IOTLB flush is fixed in the AMD IOMMU driver.

   - Memory leak fix for the Intel IOMMU driver.

   - Fix a regression in the Mediatek IOMMU driver which caused device
     initialization to fail (seen as broken HDMI output)"

* tag 'iommu-fixes-v5.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  iommu/amd: Fix IOMMU page flush when detach device from a domain
  iommu/mediatek: Use correct fwspec in mtk_iommu_add_device()
  iommu/vt-d: Fix memory leak in intel_iommu_put_resv_regions()
  iommu/amd: Unmap all mapped pages in error path of map_sg
  iommu/amd: Call free_iova_fast with pfn in map_sg

drivers/iommu/amd_iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/mtk_iommu_v1.c

index 87ba23a75b381ff245690a1106ddf190b0b327f7..2a7b78bb98b43a7b8ed9ede772d1f15f706afb99 100644 (file)
@@ -1991,16 +1991,13 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+       struct protection_domain *domain = dev_data->domain;
        struct amd_iommu *iommu;
        u16 alias;
 
        iommu = amd_iommu_rlookup_table[dev_data->devid];
        alias = dev_data->alias;
 
-       /* decrease reference counters */
-       dev_data->domain->dev_iommu[iommu->index] -= 1;
-       dev_data->domain->dev_cnt                 -= 1;
-
        /* Update data structures */
        dev_data->domain = NULL;
        list_del(&dev_data->list);
@@ -2010,6 +2007,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
        /* Flush the DTE entry */
        device_flush_dte(dev_data);
+
+       /* Flush IOTLB */
+       domain_flush_tlb_pde(domain);
+
+       /* Wait for the flushes to finish */
+       domain_flush_complete(domain);
+
+       /* decrease reference counters - needs to happen after the flushes */
+       domain->dev_iommu[iommu->index] -= 1;
+       domain->dev_cnt                 -= 1;
 }
 
 /*
@@ -2617,13 +2624,13 @@ out_unmap:
                        bus_addr  = address + s->dma_address + (j << PAGE_SHIFT);
                        iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
 
-                       if (--mapped_pages)
+                       if (--mapped_pages == 0)
                                goto out_free_iova;
                }
        }
 
 out_free_iova:
-       free_iova_fast(&dma_dom->iovad, address, npages);
+       free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
 
 out_err:
        return 0;
index 2bd9ac285c0dee363fe9b9feecf2f9082e49ebbe..1457f931218e0bede0c3c34660aaf870afaaa5a7 100644 (file)
@@ -5294,7 +5294,7 @@ static void intel_iommu_put_resv_regions(struct device *dev,
        struct iommu_resv_region *entry, *next;
 
        list_for_each_entry_safe(entry, next, head, list) {
-               if (entry->type == IOMMU_RESV_RESERVED)
+               if (entry->type == IOMMU_RESV_MSI)
                        kfree(entry);
        }
 }
index 730f7dabcf37bf1495df35024c57d8117c964da1..7e0df67bd3e976077102ec659f4cb21d3a26652a 100644 (file)
@@ -441,6 +441,10 @@ static int mtk_iommu_add_device(struct device *dev)
                iommu_spec.args_count = count;
 
                mtk_iommu_create_mapping(dev, &iommu_spec);
+
+               /* dev->iommu_fwspec might have changed */
+               fwspec = dev_iommu_fwspec_get(dev);
+
                of_node_put(iommu_spec.np);
        }