summaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/Kconfig1
-rw-r--r--drivers/iommu/amd_iommu.c68
-rw-r--r--drivers/iommu/arm-smmu.c2
-rw-r--r--drivers/iommu/dmar.c2
-rw-r--r--drivers/iommu/intel-iommu.c4
-rw-r--r--drivers/iommu/omap-iommu.c2
-rw-r--r--drivers/iommu/rockchip-iommu.c2
-rw-r--r--drivers/iommu/tegra-gart.c2
8 files changed, 54 insertions, 29 deletions
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 8ea77efb2e29..e055d228bfb9 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -107,7 +107,6 @@ config IOMMU_PGTABLES_L2
# AMD IOMMU support
config AMD_IOMMU
bool "AMD IOMMU support"
- select DMA_DIRECT_OPS
select SWIOTLB
select PCI_MSI
select PCI_ATS
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 0cea80be2888..596b95c50051 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2596,32 +2596,51 @@ static void *alloc_coherent(struct device *dev, size_t size,
unsigned long attrs)
{
u64 dma_mask = dev->coherent_dma_mask;
- struct protection_domain *domain = get_domain(dev);
- bool is_direct = false;
- void *virt_addr;
+ struct protection_domain *domain;
+ struct dma_ops_domain *dma_dom;
+ struct page *page;
+
+ domain = get_domain(dev);
+ if (PTR_ERR(domain) == -EINVAL) {
+ page = alloc_pages(flag, get_order(size));
+ *dma_addr = page_to_phys(page);
+ return page_address(page);
+ } else if (IS_ERR(domain))
+ return NULL;
- if (IS_ERR(domain)) {
- if (PTR_ERR(domain) != -EINVAL)
+ dma_dom = to_dma_ops_domain(domain);
+ size = PAGE_ALIGN(size);
+ dma_mask = dev->coherent_dma_mask;
+ flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+ flag |= __GFP_ZERO;
+
+ page = alloc_pages(flag | __GFP_NOWARN, get_order(size));
+ if (!page) {
+ if (!gfpflags_allow_blocking(flag))
return NULL;
- is_direct = true;
- }
- virt_addr = dma_direct_alloc(dev, size, dma_addr, flag, attrs);
- if (!virt_addr || is_direct)
- return virt_addr;
+ page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
+ get_order(size), flag);
+ if (!page)
+ return NULL;
+ }
if (!dma_mask)
dma_mask = *dev->dma_mask;
- *dma_addr = __map_single(dev, to_dma_ops_domain(domain),
- virt_to_phys(virt_addr), PAGE_ALIGN(size),
- DMA_BIDIRECTIONAL, dma_mask);
+ *dma_addr = __map_single(dev, dma_dom, page_to_phys(page),
+ size, DMA_BIDIRECTIONAL, dma_mask);
+
if (*dma_addr == AMD_IOMMU_MAPPING_ERROR)
goto out_free;
- return virt_addr;
+
+ return page_address(page);
out_free:
- dma_direct_free(dev, size, virt_addr, *dma_addr, attrs);
+
+ if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
+ __free_pages(page, get_order(size));
+
return NULL;
}
@@ -2632,17 +2651,24 @@ static void free_coherent(struct device *dev, size_t size,
void *virt_addr, dma_addr_t dma_addr,
unsigned long attrs)
{
- struct protection_domain *domain = get_domain(dev);
+ struct protection_domain *domain;
+ struct dma_ops_domain *dma_dom;
+ struct page *page;
+ page = virt_to_page(virt_addr);
size = PAGE_ALIGN(size);
- if (!IS_ERR(domain)) {
- struct dma_ops_domain *dma_dom = to_dma_ops_domain(domain);
+ domain = get_domain(dev);
+ if (IS_ERR(domain))
+ goto free_mem;
- __unmap_single(dma_dom, dma_addr, size, DMA_BIDIRECTIONAL);
- }
+ dma_dom = to_dma_ops_domain(domain);
+
+ __unmap_single(dma_dom, dma_addr, size, DMA_BIDIRECTIONAL);
- dma_direct_free(dev, size, virt_addr, dma_addr, attrs);
+free_mem:
+ if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
+ __free_pages(page, get_order(size));
}
/*
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 69e7c60792a8..f7a96bcf94a6 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2082,7 +2082,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
return -ENODEV;
}
- smmu->irqs = devm_kzalloc(dev, sizeof(*smmu->irqs) * num_irqs,
+ smmu->irqs = devm_kcalloc(dev, num_irqs, sizeof(*smmu->irqs),
GFP_KERNEL);
if (!smmu->irqs) {
dev_err(dev, "failed to allocate %d irqs\n", num_irqs);
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 4321f7704b23..75456b5aa825 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -1458,7 +1458,7 @@ int dmar_enable_qi(struct intel_iommu *iommu)
qi->desc = page_address(desc_page);
- qi->desc_status = kzalloc(QI_LENGTH * sizeof(int), GFP_ATOMIC);
+ qi->desc_status = kcalloc(QI_LENGTH, sizeof(int), GFP_ATOMIC);
if (!qi->desc_status) {
free_page((unsigned long) qi->desc);
kfree(qi);
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 89e49a429c57..14e4b3722428 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3189,7 +3189,7 @@ static int copy_translation_tables(struct intel_iommu *iommu)
/* This is too big for the stack - allocate it from slab */
ctxt_table_entries = ext ? 512 : 256;
ret = -ENOMEM;
- ctxt_tbls = kzalloc(ctxt_table_entries * sizeof(void *), GFP_KERNEL);
+ ctxt_tbls = kcalloc(ctxt_table_entries, sizeof(void *), GFP_KERNEL);
if (!ctxt_tbls)
goto out_unmap;
@@ -4032,7 +4032,7 @@ static int iommu_suspend(void)
unsigned long flag;
for_each_active_iommu(iommu, drhd) {
- iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS,
+ iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
GFP_ATOMIC);
if (!iommu->iommu_state)
goto nomem;
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index c33b7b104e72..af4a8e7fcd27 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1455,7 +1455,7 @@ static int omap_iommu_add_device(struct device *dev)
if (num_iommus < 0)
return 0;
- arch_data = kzalloc((num_iommus + 1) * sizeof(*arch_data), GFP_KERNEL);
+ arch_data = kcalloc(num_iommus + 1, sizeof(*arch_data), GFP_KERNEL);
if (!arch_data)
return -ENOMEM;
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 0468acfa131f..054cd2c8e9c8 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1135,7 +1135,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
iommu->dev = dev;
iommu->num_mmu = 0;
- iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * num_res,
+ iommu->bases = devm_kcalloc(dev, num_res, sizeof(*iommu->bases),
GFP_KERNEL);
if (!iommu->bases)
return -ENOMEM;
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index 89ec24c6952c..a004f6da35f2 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -465,7 +465,7 @@ static int tegra_gart_probe(struct platform_device *pdev)
gart->iovmm_base = (dma_addr_t)res_remap->start;
gart->page_count = (resource_size(res_remap) >> GART_PAGE_SHIFT);
- gart->savedata = vmalloc(sizeof(u32) * gart->page_count);
+ gart->savedata = vmalloc(array_size(sizeof(u32), gart->page_count));
if (!gart->savedata) {
dev_err(dev, "failed to allocate context save area\n");
return -ENOMEM;
OpenPOWER on IntegriCloud