From: Joerg Roedel Date: Thu, 2 Oct 2014 10:24:45 +0000 (+0200) Subject: Merge branches 'arm/exynos', 'arm/omap', 'arm/smmu', 'x86/vt-d', 'x86/amd' and 'core... X-Git-Tag: v3.18-rc1~38^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=09b5269a1b3d47525d7c25efeb16f5407ef82ea2;p=thirdparty%2Fkernel%2Flinux.git Merge branches 'arm/exynos', 'arm/omap', 'arm/smmu', 'x86/vt-d', 'x86/amd' and 'core' into next Conflicts: drivers/iommu/arm-smmu.c --- 09b5269a1b3d47525d7c25efeb16f5407ef82ea2 diff --cc drivers/iommu/amd_iommu.c index ecb0109a53604,18405314168be,ecb0109a53604,ecb0109a53604,18405314168be,23c5be6a3a1eb,2f4f45d8dbfd4..505a9adac2d51 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@@@@@@@ -362,14 -362,14 -362,14 -362,14 -362,14 -384,17 -357,8 +379,11 @@@@@@@@ static int iommu_init_device(struct dev return -ENOTSUPP; } dev_data->alias_data = alias_data; ----- } + ----- ret = init_iommu_group(dev); ----- if (ret) { ----- free_dev_data(dev_data); ----- return ret; +++++ + /* Add device to the alias_list */ +++++ + list_add(&dev_data->alias_list, &alias_data->alias_list); } - ret = init_iommu_group(dev); - if (ret) { - free_dev_data(dev_data); - return ret; - } - if (pci_iommuv2_capable(pdev)) { struct amd_iommu *iommu; @@@@@@@@ -2127,30 -2127,30 -2127,30 -2127,30 -2127,30 -2156,23 -2125,30 +2154,23 @@@@@@@@ static int __attach_device(struct iommu /* lock domain */ spin_lock(&domain->lock); ----- - if (dev_data->alias_data != NULL) { ----- - struct iommu_dev_data *alias_data = dev_data->alias_data; +++++ + head = dev_data; ----- - /* Some sanity checks */ ----- - ret = -EBUSY; ----- - if (alias_data->domain != NULL && ----- - alias_data->domain != domain) ----- - goto out_unlock; +++++ + if (head->alias_data != NULL) +++++ + head = head->alias_data; ----- - if (dev_data->domain != NULL && ----- - dev_data->domain != domain) ----- - goto out_unlock; +++++ + /* Now we have the root of the alias group, if any */ ----- - /* Do real assignment */ ----- - if (alias_data->domain == NULL) ----- - do_attach(alias_data, domain); ----- ----- atomic_inc(&alias_data->bind); ----- } +++++ + ret = -EBUSY; +++++ + if (head->domain != NULL) +++++ + goto out_unlock; ----- if (dev_data->domain == NULL) ----- do_attach(dev_data, domain); - atomic_inc(&alias_data->bind); - } +++++ + /* Attach alias group root */ +++++ + do_attach(head, domain); - if (dev_data->domain == NULL) - do_attach(dev_data, domain); - ----- - atomic_inc(&dev_data->bind); +++++ + /* Attach other devices in the alias group */ +++++ + list_for_each_entry(entry, &head->alias_list, alias_list) +++++ + do_attach(entry, domain); ret = 0; @@@@@@@@ -3154,11 -3154,9 -3154,11 -3154,11 -3154,9 -3176,10 -3153,11 +3175,10 @@@@@@@@ static void cleanup_domain(struct prote write_lock_irqsave(&amd_iommu_devtable_lock, flags); - - list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) { - - __detach_device(dev_data); - - atomic_set(&dev_data->bind, 0); + + while (!list_empty(&domain->dev_list)) { + + entry = list_first_entry(&domain->dev_list, + + struct iommu_dev_data, list); + + __detach_device(entry); - -- - atomic_set(&entry->bind, 0); } write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); diff --cc drivers/iommu/arm-smmu.c index a83cc2a2a2cab,ca18d6d42a9be,ca18d6d42a9be,37dc3dd0df962,ca18d6d42a9be,ca18d6d42a9be,ce39b1294bfdb..60558f794922f --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@@@@@@@ -911,10 -890,10 -890,10 -924,10 -890,10 -890,10 -911,10 +924,10 @@@@@@@@ static int arm_smmu_init_domain_context ret = __arm_smmu_alloc_bitmap(smmu->context_map, start, smmu->num_context_banks); if (IS_ERR_VALUE(ret)) -- -- return ret; ++ ++ goto out_unlock; cfg->cbndx = ret; --- --- if (smmu->version == 1) { +++ +++ if (smmu->version == ARM_SMMU_V1) { cfg->irptndx = atomic_inc_return(&smmu->irptndx); cfg->irptndx %= smmu->num_context_irqs; } else { @@@@@@@@ -1170,10 -1160,8 -1160,8 -1184,14 -1160,8 -1160,8 -1170,10 +1184,14 @@@@@@@@ static int arm_smmu_domain_add_master(s static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain, struct arm_smmu_master_cfg *cfg) { ++ ++ int i; struct arm_smmu_device *smmu = smmu_domain->smmu; ++ ++ void __iomem *gr0_base = ARM_SMMU_GR0(smmu); ++ ++ +++ +++ /* An IOMMU group is torn down by the first device to be removed */ +++ +++ if ((smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) && !cfg->smrs) +++ +++ return; + + /* * We *must* clear the S2CR first, because freeing the SMR means * that it can be re-allocated immediately. @@@@@@@@ -1190,12 -1172,13 -1172,13 -1208,12 -1172,13 -1172,13 -1190,12 +1208,12 @@@@@@@@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) { -- -- int ret = -EINVAL; ++ ++ int ret; struct arm_smmu_domain *smmu_domain = domain->priv; -- -- struct arm_smmu_device *smmu; ++ ++ struct arm_smmu_device *smmu, *dom_smmu; struct arm_smmu_master_cfg *cfg; -- -- unsigned long flags; --- --- smmu = dev_get_master_dev(dev)->archdata.iommu; +++ +++ smmu = find_smmu_for_device(dev); if (!smmu) { dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n"); return -ENXIO; @@@@@@@@ -1210,24 -1193,26 -1193,26 -1233,27 -1193,26 -1193,26 -1210,24 +1233,27 @@@@@@@@ /* Now that we have a master, we can finalise the domain */ ret = arm_smmu_init_domain_context(domain, smmu); if (IS_ERR_VALUE(ret)) -- -- goto err_unlock; -- -- } else if (smmu_domain->smmu != smmu) { ++ ++ return ret; ++ ++ ++ ++ dom_smmu = smmu_domain->smmu; ++ ++ } ++ ++ ++ ++ if (dom_smmu != smmu) { dev_err(dev, "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n", -- -- dev_name(smmu_domain->smmu->dev), -- -- dev_name(smmu->dev)); -- -- goto err_unlock; ++ ++ dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev)); ++ ++ return -EINVAL; } -- -- spin_unlock_irqrestore(&smmu_domain->lock, flags); /* Looks ok, so add the device to the domain */ --- --- cfg = find_smmu_master_cfg(smmu_domain->smmu, dev); +++ +++ cfg = find_smmu_master_cfg(dev); if (!cfg) return -ENODEV; --- --- return arm_smmu_domain_add_master(smmu_domain, cfg); -- -- -- -- err_unlock: -- -- spin_unlock_irqrestore(&smmu_domain->lock, flags); +++ +++ ret = arm_smmu_domain_add_master(smmu_domain, cfg); +++ +++ if (!ret) +++ +++ dev->archdata.iommu = domain; + + return ret; } static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev) @@@@@@@@ -1803,21 -1789,16 -1789,16 -1842,14 -1789,16 -1789,16 -1802,21 +1841,14 @@@@@@@@ static int arm_smmu_device_cfg_probe(st /* ID2 */ id = readl_relaxed(gr0_base + ARM_SMMU_GR0_ID2); size = arm_smmu_id_size_to_bits((id >> ID2_IAS_SHIFT) & ID2_IAS_MASK); +++ +++ smmu->s1_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, size); --- --- /* --- --- * Stage-1 output limited by stage-2 input size due to pgd --- --- * allocation (PTRS_PER_PGD). --- --- */ - - if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) { +++ +++ /* Stage-2 input size limited due to pgd allocation (PTRS_PER_PGD) */ #ifdef CONFIG_64BIT - - smmu->s1_output_size = min_t(unsigned long, VA_BITS, size); -- -- smmu->s1_output_size = min_t(unsigned long, VA_BITS, size); +++ +++ smmu->s2_input_size = min_t(unsigned long, VA_BITS, size); #else - - smmu->s1_output_size = min(32UL, size); -- -- smmu->s1_output_size = min(32UL, size); +++ +++ smmu->s2_input_size = min(32UL, size); #endif - - } else { - - smmu->s1_output_size = min_t(unsigned long, PHYS_MASK_SHIFT, - - size); - - } /* The stage-2 output mask is also applied for bypass */ size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK); @@@@@@@@ -1850,8 -1831,8 -1831,8 -1886,19 -1831,8 -1831,8 -1849,8 +1885,19 @@@@@@@@ return 0; } - static struct of_device_id arm_smmu_of_match[] = { +++++++static const struct of_device_id arm_smmu_of_match[] = { +++ +++ { .compatible = "arm,smmu-v1", .data = (void *)ARM_SMMU_V1 }, +++ +++ { .compatible = "arm,smmu-v2", .data = (void *)ARM_SMMU_V2 }, +++ +++ { .compatible = "arm,mmu-400", .data = (void *)ARM_SMMU_V1 }, +++ +++ { .compatible = "arm,mmu-401", .data = (void *)ARM_SMMU_V1 }, +++ +++ { .compatible = "arm,mmu-500", .data = (void *)ARM_SMMU_V2 }, +++ +++ { }, +++ +++}; +++ +++MODULE_DEVICE_TABLE(of, arm_smmu_of_match); +++ +++ static int arm_smmu_device_dt_probe(struct platform_device *pdev) { +++ +++ const struct of_device_id *of_id; struct resource *res; struct arm_smmu_device *smmu; struct device *dev = &pdev->dev; @@@@@@@@ -1928,9 -1905,13 -1905,13 -1978,9 -1905,13 -1905,13 -1927,9 +1977,9 @@@@@@@@ } dev_notice(dev, "registered %d master devices\n", i); -- -- err = arm_smmu_device_cfg_probe(smmu); -- -- if (err) -- -- goto out_put_masters; -- -- parse_driver_options(smmu); --- --- if (smmu->version > 1 && +++ +++ if (smmu->version > ARM_SMMU_V1 && smmu->num_context_banks != smmu->num_context_irqs) { dev_err(dev, "found only %d context interrupt(s) but %d required\n", @@@@@@@@ -2011,17 -1992,17 -1992,17 -2061,6 -1992,17 -1992,17 -2010,17 +2060,6 @@@@@@@@ static int arm_smmu_device_remove(struc return 0; } --- ---#ifdef CONFIG_OF --- -- static struct of_device_id arm_smmu_of_match[] = { -static const struct of_device_id arm_smmu_of_match[] = { --- --- { .compatible = "arm,smmu-v1", }, --- --- { .compatible = "arm,smmu-v2", }, --- --- { .compatible = "arm,mmu-400", }, --- --- { .compatible = "arm,mmu-500", }, --- --- { }, --- ---}; --- ---MODULE_DEVICE_TABLE(of, arm_smmu_of_match); --- ---#endif --- --- static struct platform_driver arm_smmu_driver = { .driver = { .owner = THIS_MODULE, diff --cc drivers/iommu/intel-iommu.c index 5619f264862d9,d1f5caad04f99,5619f264862d9,5619f264862d9,eaf825ac7d28f,5619f264862d9,bc1a203954451..a27d6cb1a793e --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@@@@@@@ -3865,18 -3865,10 -3865,18 -3865,18 -3865,9 -3865,18 -3865,18 +3865,17 @@@@@@@@ static int device_notifier(struct notif if (iommu_dummy(dev)) return 0; ---- -- if (action != BUS_NOTIFY_UNBOUND_DRIVER && ---- -- action != BUS_NOTIFY_DEL_DEVICE) ++++ ++ if (action != BUS_NOTIFY_REMOVED_DEVICE) + return 0; + + + /* + + * If the device is still attached to a device driver we can't + + * tear down the domain yet as DMA mappings may still be in use. + + * Wait for the BUS_NOTIFY_UNBOUND_DRIVER event to do that. + + */ + + if (action == BUS_NOTIFY_DEL_DEVICE && dev->driver != NULL) + return 0; + domain = find_domain(dev); if (!domain) return 0;