diff options
author | Linus Torvalds | 2019-01-30 09:30:03 -0800 |
---|---|---|
committer | Linus Torvalds | 2019-01-30 09:30:03 -0800 |
commit | 1c0490ce902206f4685f812fa81304fd1adf4e35 (patch) | |
tree | bee94f03b204cb058662984c173b05163c8f7dc9 /drivers/iommu | |
parent | 877ef51d53abfdadabc64809d045d9c27c1cf757 (diff) | |
parent | 9825bd94e3a2baae1f4874767ae3a7d4c049720e (diff) |
Merge tag 'iommu-fixes-v5.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
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
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/amd_iommu.c | 19 | ||||
-rw-r--r-- | drivers/iommu/intel-iommu.c | 2 | ||||
-rw-r--r-- | drivers/iommu/mtk_iommu_v1.c | 4 |
3 files changed, 18 insertions, 7 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 87ba23a75b38..2a7b78bb98b4 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -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; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 2bd9ac285c0d..1457f931218e 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -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); } } diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index 730f7dabcf37..7e0df67bd3e9 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -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); } |