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;
/* 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;
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);
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 {
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.
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;
/* 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)
/* 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);
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;
}
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",
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,