Skip to content

Commit

Permalink
Merge branches 'iommu/fixes', 'arm/omap', 'arm/exynos', 'x86/amd', 'x…
Browse files Browse the repository at this point in the history
…86/vt-d' and 'core' into next
  • Loading branch information
Joerg Roedel committed Oct 13, 2017
6 parents ce76353 + 9d5018d + 7a974b2 + 53b9ec3 + b117e03 + 538d5b3 commit a593472
Show file tree
Hide file tree
Showing 20 changed files with 518 additions and 321 deletions.
3 changes: 1 addition & 2 deletions drivers/gpu/drm/tegra/drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,7 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)

order = __ffs(tegra->domain->pgsize_bitmap);
init_iova_domain(&tegra->carveout.domain, 1UL << order,
carveout_start >> order,
carveout_end >> order);
carveout_start >> order);

tegra->carveout.shift = iova_shift(&tegra->carveout.domain);
tegra->carveout.limit = carveout_end >> tegra->carveout.shift;
Expand Down
3 changes: 1 addition & 2 deletions drivers/gpu/host1x/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,7 @@ static int host1x_probe(struct platform_device *pdev)

order = __ffs(host->domain->pgsize_bitmap);
init_iova_domain(&host->iova, 1UL << order,
geometry->aperture_start >> order,
geometry->aperture_end >> order);
geometry->aperture_start >> order);
host->iova_end = geometry->aperture_end;
}

Expand Down
36 changes: 21 additions & 15 deletions drivers/iommu/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
/* IO virtual address start page frame number */
#define IOVA_START_PFN (1)
#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
#define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32))

/* Reserved IOVA ranges */
#define MSI_RANGE_START (0xfee00000)
Expand Down Expand Up @@ -1547,10 +1546,11 @@ static unsigned long dma_ops_alloc_iova(struct device *dev,

if (dma_mask > DMA_BIT_MASK(32))
pfn = alloc_iova_fast(&dma_dom->iovad, pages,
IOVA_PFN(DMA_BIT_MASK(32)));
IOVA_PFN(DMA_BIT_MASK(32)), false);

if (!pfn)
pfn = alloc_iova_fast(&dma_dom->iovad, pages, IOVA_PFN(dma_mask));
pfn = alloc_iova_fast(&dma_dom->iovad, pages,
IOVA_PFN(dma_mask), true);

return (pfn << PAGE_SHIFT);
}
Expand Down Expand Up @@ -1788,8 +1788,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(void)
if (!dma_dom->domain.pt_root)
goto free_dma_dom;

init_iova_domain(&dma_dom->iovad, PAGE_SIZE,
IOVA_START_PFN, DMA_32BIT_PFN);
init_iova_domain(&dma_dom->iovad, PAGE_SIZE, IOVA_START_PFN);

if (init_iova_flush_queue(&dma_dom->iovad, iova_domain_flush_tlb, NULL))
goto free_dma_dom;
Expand Down Expand Up @@ -2696,8 +2695,7 @@ static int init_reserved_iova_ranges(void)
struct pci_dev *pdev = NULL;
struct iova *val;

init_iova_domain(&reserved_iova_ranges, PAGE_SIZE,
IOVA_START_PFN, DMA_32BIT_PFN);
init_iova_domain(&reserved_iova_ranges, PAGE_SIZE, IOVA_START_PFN);

lockdep_set_class(&reserved_iova_ranges.iova_rbtree_lock,
&reserved_rbtree_key);
Expand Down Expand Up @@ -3663,11 +3661,11 @@ static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic)
return table;
}

static int alloc_irq_index(u16 devid, int count)
static int alloc_irq_index(u16 devid, int count, bool align)
{
struct irq_remap_table *table;
int index, c, alignment = 1;
unsigned long flags;
int index, c;
struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];

if (!iommu)
Expand All @@ -3677,16 +3675,22 @@ static int alloc_irq_index(u16 devid, int count)
if (!table)
return -ENODEV;

if (align)
alignment = roundup_pow_of_two(count);

spin_lock_irqsave(&table->lock, flags);

/* Scan table for free entries */
for (c = 0, index = table->min_index;
for (index = ALIGN(table->min_index, alignment), c = 0;
index < MAX_IRQS_PER_TABLE;
++index) {
if (!iommu->irte_ops->is_allocated(table, index))
index++) {
if (!iommu->irte_ops->is_allocated(table, index)) {
c += 1;
else
c = 0;
} else {
c = 0;
index = ALIGN(index, alignment);
continue;
}

if (c == count) {
for (; c != 0; --c)
Expand Down Expand Up @@ -4099,7 +4103,9 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
else
ret = -ENOMEM;
} else {
index = alloc_irq_index(devid, nr_irqs);
bool align = (info->type == X86_IRQ_ALLOC_TYPE_MSI);

index = alloc_irq_index(devid, nr_irqs, align);
}
if (index < 0) {
pr_warn("Failed to allocate IRTE\n");
Expand Down
10 changes: 10 additions & 0 deletions drivers/iommu/arm-smmu-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -1743,6 +1743,14 @@ arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size)
return ops->unmap(ops, iova, size);
}

static void arm_smmu_iotlb_sync(struct iommu_domain *domain)
{
struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu;

if (smmu)
__arm_smmu_tlb_sync(smmu);
}

static phys_addr_t
arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
{
Expand Down Expand Up @@ -1963,6 +1971,8 @@ static struct iommu_ops arm_smmu_ops = {
.map = arm_smmu_map,
.unmap = arm_smmu_unmap,
.map_sg = default_iommu_map_sg,
.flush_iotlb_all = arm_smmu_iotlb_sync,
.iotlb_sync = arm_smmu_iotlb_sync,
.iova_to_phys = arm_smmu_iova_to_phys,
.add_device = arm_smmu_add_device,
.remove_device = arm_smmu_remove_device,
Expand Down
20 changes: 15 additions & 5 deletions drivers/iommu/arm-smmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ enum arm_smmu_domain_stage {
struct arm_smmu_domain {
struct arm_smmu_device *smmu;
struct io_pgtable_ops *pgtbl_ops;
const struct iommu_gather_ops *tlb_ops;
struct arm_smmu_cfg cfg;
enum arm_smmu_domain_stage stage;
struct mutex init_mutex; /* Protects smmu pointer */
Expand Down Expand Up @@ -735,7 +736,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
enum io_pgtable_fmt fmt;
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
const struct iommu_gather_ops *tlb_ops;

mutex_lock(&smmu_domain->init_mutex);
if (smmu_domain->smmu)
Expand Down Expand Up @@ -813,7 +813,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
ias = min(ias, 32UL);
oas = min(oas, 32UL);
}
tlb_ops = &arm_smmu_s1_tlb_ops;
smmu_domain->tlb_ops = &arm_smmu_s1_tlb_ops;
break;
case ARM_SMMU_DOMAIN_NESTED:
/*
Expand All @@ -833,9 +833,9 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
oas = min(oas, 40UL);
}
if (smmu->version == ARM_SMMU_V2)
tlb_ops = &arm_smmu_s2_tlb_ops_v2;
smmu_domain->tlb_ops = &arm_smmu_s2_tlb_ops_v2;
else
tlb_ops = &arm_smmu_s2_tlb_ops_v1;
smmu_domain->tlb_ops = &arm_smmu_s2_tlb_ops_v1;
break;
default:
ret = -EINVAL;
Expand Down Expand Up @@ -863,7 +863,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
.pgsize_bitmap = smmu->pgsize_bitmap,
.ias = ias,
.oas = oas,
.tlb = tlb_ops,
.tlb = smmu_domain->tlb_ops,
.iommu_dev = smmu->dev,
};

Expand Down Expand Up @@ -1259,6 +1259,14 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
return ops->unmap(ops, iova, size);
}

static void arm_smmu_iotlb_sync(struct iommu_domain *domain)
{
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);

if (smmu_domain->tlb_ops)
smmu_domain->tlb_ops->tlb_sync(smmu_domain);
}

static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
dma_addr_t iova)
{
Expand Down Expand Up @@ -1562,6 +1570,8 @@ static struct iommu_ops arm_smmu_ops = {
.map = arm_smmu_map,
.unmap = arm_smmu_unmap,
.map_sg = default_iommu_map_sg,
.flush_iotlb_all = arm_smmu_iotlb_sync,
.iotlb_sync = arm_smmu_iotlb_sync,
.iova_to_phys = arm_smmu_iova_to_phys,
.add_device = arm_smmu_add_device,
.remove_device = arm_smmu_remove_device,
Expand Down
24 changes: 5 additions & 19 deletions drivers/iommu/dma-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,18 +292,7 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
/* ...then finally give it a kicking to make sure it fits */
base_pfn = max_t(unsigned long, base_pfn,
domain->geometry.aperture_start >> order);
end_pfn = min_t(unsigned long, end_pfn,
domain->geometry.aperture_end >> order);
}
/*
* PCI devices may have larger DMA masks, but still prefer allocating
* within a 32-bit mask to avoid DAC addressing. Such limitations don't
* apply to the typical platform device, so for those we may as well
* leave the cache limit at the top of their range to save an rb_last()
* traversal on every allocation.
*/
if (dev && dev_is_pci(dev))
end_pfn &= DMA_BIT_MASK(32) >> order;

/* start_pfn is always nonzero for an already-initialised domain */
if (iovad->start_pfn) {
Expand All @@ -312,16 +301,11 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
pr_warn("Incompatible range for DMA domain\n");
return -EFAULT;
}
/*
* If we have devices with different DMA masks, move the free
* area cache limit down for the benefit of the smaller one.
*/
iovad->dma_32bit_pfn = min(end_pfn + 1, iovad->dma_32bit_pfn);

return 0;
}

init_iova_domain(iovad, 1UL << order, base_pfn, end_pfn);
init_iova_domain(iovad, 1UL << order, base_pfn);
if (!dev)
return 0;

Expand Down Expand Up @@ -386,10 +370,12 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,

/* Try to get PCI devices a SAC address */
if (dma_limit > DMA_BIT_MASK(32) && dev_is_pci(dev))
iova = alloc_iova_fast(iovad, iova_len, DMA_BIT_MASK(32) >> shift);
iova = alloc_iova_fast(iovad, iova_len,
DMA_BIT_MASK(32) >> shift, false);

if (!iova)
iova = alloc_iova_fast(iovad, iova_len, dma_limit >> shift);
iova = alloc_iova_fast(iovad, iova_len, dma_limit >> shift,
true);

return (dma_addr_t)iova << shift;
}
Expand Down
7 changes: 5 additions & 2 deletions drivers/iommu/dmar.c
Original file line number Diff line number Diff line change
Expand Up @@ -801,13 +801,16 @@ int __init dmar_dev_scope_init(void)
dmar_free_pci_notify_info(info);
}
}

bus_register_notifier(&pci_bus_type, &dmar_pci_bus_nb);
}

return dmar_dev_scope_status;
}

void dmar_register_bus_notifier(void)
{
bus_register_notifier(&pci_bus_type, &dmar_pci_bus_nb);
}


int __init dmar_table_init(void)
{
Expand Down
23 changes: 16 additions & 7 deletions drivers/iommu/exynos-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ struct exynos_iommu_domain {
struct sysmmu_drvdata {
struct device *sysmmu; /* SYSMMU controller device */
struct device *master; /* master device (owner) */
struct device_link *link; /* runtime PM link to master */
void __iomem *sfrbase; /* our registers */
struct clk *clk; /* SYSMMU's clock */
struct clk *aclk; /* SYSMMU's aclk clock */
Expand Down Expand Up @@ -1250,6 +1251,8 @@ static struct iommu_group *get_device_iommu_group(struct device *dev)

static int exynos_iommu_add_device(struct device *dev)
{
struct exynos_iommu_owner *owner = dev->archdata.iommu;
struct sysmmu_drvdata *data;
struct iommu_group *group;

if (!has_sysmmu(dev))
Expand All @@ -1260,6 +1263,15 @@ static int exynos_iommu_add_device(struct device *dev)
if (IS_ERR(group))
return PTR_ERR(group);

list_for_each_entry(data, &owner->controllers, owner_node) {
/*
* SYSMMU will be runtime activated via device link
* (dependency) to its master device, so there are no
* direct calls to pm_runtime_get/put in this driver.
*/
data->link = device_link_add(dev, data->sysmmu,
DL_FLAG_PM_RUNTIME);
}
iommu_group_put(group);

return 0;
Expand All @@ -1268,6 +1280,7 @@ static int exynos_iommu_add_device(struct device *dev)
static void exynos_iommu_remove_device(struct device *dev)
{
struct exynos_iommu_owner *owner = dev->archdata.iommu;
struct sysmmu_drvdata *data;

if (!has_sysmmu(dev))
return;
Expand All @@ -1283,6 +1296,9 @@ static void exynos_iommu_remove_device(struct device *dev)
}
}
iommu_group_remove_device(dev);

list_for_each_entry(data, &owner->controllers, owner_node)
device_link_del(data->link);
}

static int exynos_iommu_of_xlate(struct device *dev,
Expand Down Expand Up @@ -1316,13 +1332,6 @@ static int exynos_iommu_of_xlate(struct device *dev,
list_add_tail(&data->owner_node, &owner->controllers);
data->master = dev;

/*
* SYSMMU will be runtime activated via device link (dependency) to its
* master device, so there are no direct calls to pm_runtime_get/put
* in this driver.
*/
device_link_add(dev, data->sysmmu, DL_FLAG_PM_RUNTIME);

return 0;
}

Expand Down
Loading

0 comments on commit a593472

Please sign in to comment.