diff options
| author | Will Deacon <will.deacon@arm.com> | 2014-06-25 06:29:12 -0400 |
|---|---|---|
| committer | Will Deacon <will.deacon@arm.com> | 2014-07-03 10:50:22 -0400 |
| commit | 44680eedf9409daf0fed618ae101f35d1f83d1a4 (patch) | |
| tree | 5951a5e3af529803ead15a7885a12f0008fabb70 | |
| parent | d0948945638635487111d0851218080e81de5104 (diff) | |
iommu/arm-smmu: remove support for chained SMMUs
The ARM SMMU driver has supported chained SMMUs (i.e. SMMUs connected
back-to-back in series) via the smmu-parent property in device tree.
This was in anticipation of somebody building such a configuration,
however that seems not to be the case.
This patch removes the unused chained SMMU hack from the driver. We can
consider adding it back later if somebody decided they need it, but for
the time being it's just pointless mess that we're carrying in mainline.
Removal of the feature also makes migration to the generic IOMMU bindings
easier.
Signed-off-by: Will Deacon <will.deacon@arm.com>
| -rw-r--r-- | Documentation/devicetree/bindings/iommu/arm,smmu.txt | 6 | ||||
| -rw-r--r-- | drivers/iommu/arm-smmu.c | 263 |
2 files changed, 77 insertions, 192 deletions
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt b/Documentation/devicetree/bindings/iommu/arm,smmu.txt index f284b99402bc..2d0f7cd867ea 100644 --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt | |||
| @@ -42,12 +42,6 @@ conditions. | |||
| 42 | 42 | ||
| 43 | ** System MMU optional properties: | 43 | ** System MMU optional properties: |
| 44 | 44 | ||
| 45 | - smmu-parent : When multiple SMMUs are chained together, this | ||
| 46 | property can be used to provide a phandle to the | ||
| 47 | parent SMMU (that is the next SMMU on the path going | ||
| 48 | from the mmu-masters towards memory) node for this | ||
| 49 | SMMU. | ||
| 50 | |||
| 51 | - calxeda,smmu-secure-config-access : Enable proper handling of buggy | 45 | - calxeda,smmu-secure-config-access : Enable proper handling of buggy |
| 52 | implementations that always use secure access to | 46 | implementations that always use secure access to |
| 53 | SMMU configuration registers. In this case non-secure | 47 | SMMU configuration registers. In this case non-secure |
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 3ae50be49269..2961b8c474eb 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
| @@ -333,28 +333,17 @@ struct arm_smmu_smr { | |||
| 333 | struct arm_smmu_master_cfg { | 333 | struct arm_smmu_master_cfg { |
| 334 | int num_streamids; | 334 | int num_streamids; |
| 335 | u16 streamids[MAX_MASTER_STREAMIDS]; | 335 | u16 streamids[MAX_MASTER_STREAMIDS]; |
| 336 | |||
| 337 | /* | ||
| 338 | * We only need to allocate these on the root SMMU, as we | ||
| 339 | * configure unmatched streams to bypass translation. | ||
| 340 | */ | ||
| 341 | struct arm_smmu_smr *smrs; | 336 | struct arm_smmu_smr *smrs; |
| 342 | }; | 337 | }; |
| 343 | 338 | ||
| 344 | struct arm_smmu_master { | 339 | struct arm_smmu_master { |
| 345 | struct device_node *of_node; | 340 | struct device_node *of_node; |
| 346 | |||
| 347 | /* | ||
| 348 | * The following is specific to the master's position in the | ||
| 349 | * SMMU chain. | ||
| 350 | */ | ||
| 351 | struct rb_node node; | 341 | struct rb_node node; |
| 352 | struct arm_smmu_master_cfg cfg; | 342 | struct arm_smmu_master_cfg cfg; |
| 353 | }; | 343 | }; |
| 354 | 344 | ||
| 355 | struct arm_smmu_device { | 345 | struct arm_smmu_device { |
| 356 | struct device *dev; | 346 | struct device *dev; |
| 357 | struct device_node *parent_of_node; | ||
| 358 | 347 | ||
| 359 | void __iomem *base; | 348 | void __iomem *base; |
| 360 | unsigned long size; | 349 | unsigned long size; |
| @@ -392,7 +381,6 @@ struct arm_smmu_device { | |||
| 392 | }; | 381 | }; |
| 393 | 382 | ||
| 394 | struct arm_smmu_cfg { | 383 | struct arm_smmu_cfg { |
| 395 | struct arm_smmu_device *smmu; | ||
| 396 | u8 cbndx; | 384 | u8 cbndx; |
| 397 | u8 irptndx; | 385 | u8 irptndx; |
| 398 | u32 cbar; | 386 | u32 cbar; |
| @@ -404,15 +392,8 @@ struct arm_smmu_cfg { | |||
| 404 | #define ARM_SMMU_CB_VMID(cfg) ((cfg)->cbndx + 1) | 392 | #define ARM_SMMU_CB_VMID(cfg) ((cfg)->cbndx + 1) |
| 405 | 393 | ||
| 406 | struct arm_smmu_domain { | 394 | struct arm_smmu_domain { |
| 407 | /* | 395 | struct arm_smmu_device *smmu; |
| 408 | * A domain can span across multiple, chained SMMUs and requires | 396 | struct arm_smmu_cfg cfg; |
| 409 | * all devices within the domain to follow the same translation | ||
| 410 | * path. | ||
| 411 | */ | ||
| 412 | struct arm_smmu_device *leaf_smmu; | ||
| 413 | struct arm_smmu_cfg root_cfg; | ||
| 414 | phys_addr_t output_mask; | ||
| 415 | |||
| 416 | spinlock_t lock; | 397 | spinlock_t lock; |
| 417 | }; | 398 | }; |
| 418 | 399 | ||
| @@ -546,59 +527,20 @@ static int register_smmu_master(struct arm_smmu_device *smmu, | |||
| 546 | return insert_smmu_master(smmu, master); | 527 | return insert_smmu_master(smmu, master); |
| 547 | } | 528 | } |
| 548 | 529 | ||
| 549 | static struct arm_smmu_device *find_parent_smmu(struct arm_smmu_device *smmu) | 530 | static struct arm_smmu_device *find_smmu_for_device(struct device *dev) |
| 550 | { | 531 | { |
| 551 | struct arm_smmu_device *parent; | 532 | struct arm_smmu_device *smmu; |
| 552 | |||
| 553 | if (!smmu->parent_of_node) | ||
| 554 | return NULL; | ||
| 555 | |||
| 556 | spin_lock(&arm_smmu_devices_lock); | ||
| 557 | list_for_each_entry(parent, &arm_smmu_devices, list) | ||
| 558 | if (parent->dev->of_node == smmu->parent_of_node) | ||
| 559 | goto out_unlock; | ||
| 560 | |||
| 561 | parent = NULL; | ||
| 562 | dev_warn(smmu->dev, | ||
| 563 | "Failed to find SMMU parent despite parent in DT\n"); | ||
| 564 | out_unlock: | ||
| 565 | spin_unlock(&arm_smmu_devices_lock); | ||
| 566 | return parent; | ||
| 567 | } | ||
| 568 | |||
| 569 | static struct arm_smmu_device *find_parent_smmu_for_device(struct device *dev) | ||
| 570 | { | ||
| 571 | struct arm_smmu_device *child, *parent, *smmu; | ||
| 572 | struct arm_smmu_master *master = NULL; | 533 | struct arm_smmu_master *master = NULL; |
| 573 | struct device_node *dev_node = dev_get_master_dev(dev)->of_node; | 534 | struct device_node *dev_node = dev_get_master_dev(dev)->of_node; |
| 574 | 535 | ||
| 575 | spin_lock(&arm_smmu_devices_lock); | 536 | spin_lock(&arm_smmu_devices_lock); |
| 576 | list_for_each_entry(parent, &arm_smmu_devices, list) { | 537 | list_for_each_entry(smmu, &arm_smmu_devices, list) { |
| 577 | smmu = parent; | ||
| 578 | |||
| 579 | /* Try to find a child of the current SMMU. */ | ||
| 580 | list_for_each_entry(child, &arm_smmu_devices, list) { | ||
| 581 | if (child->parent_of_node == parent->dev->of_node) { | ||
| 582 | /* Does the child sit above our master? */ | ||
| 583 | master = find_smmu_master(child, dev_node); | ||
| 584 | if (master) { | ||
| 585 | smmu = NULL; | ||
| 586 | break; | ||
| 587 | } | ||
| 588 | } | ||
| 589 | } | ||
| 590 | |||
| 591 | /* We found some children, so keep searching. */ | ||
| 592 | if (!smmu) { | ||
| 593 | master = NULL; | ||
| 594 | continue; | ||
| 595 | } | ||
| 596 | |||
| 597 | master = find_smmu_master(smmu, dev_node); | 538 | master = find_smmu_master(smmu, dev_node); |
| 598 | if (master) | 539 | if (master) |
| 599 | break; | 540 | break; |
| 600 | } | 541 | } |
| 601 | spin_unlock(&arm_smmu_devices_lock); | 542 | spin_unlock(&arm_smmu_devices_lock); |
| 543 | |||
| 602 | return master ? smmu : NULL; | 544 | return master ? smmu : NULL; |
| 603 | } | 545 | } |
| 604 | 546 | ||
| @@ -639,9 +581,10 @@ static void arm_smmu_tlb_sync(struct arm_smmu_device *smmu) | |||
| 639 | } | 581 | } |
| 640 | } | 582 | } |
| 641 | 583 | ||
| 642 | static void arm_smmu_tlb_inv_context(struct arm_smmu_cfg *cfg) | 584 | static void arm_smmu_tlb_inv_context(struct arm_smmu_domain *smmu_domain) |
| 643 | { | 585 | { |
| 644 | struct arm_smmu_device *smmu = cfg->smmu; | 586 | struct arm_smmu_cfg *cfg = &smmu_domain->cfg; |
| 587 | struct arm_smmu_device *smmu = smmu_domain->smmu; | ||
| 645 | void __iomem *base = ARM_SMMU_GR0(smmu); | 588 | void __iomem *base = ARM_SMMU_GR0(smmu); |
| 646 | bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS; | 589 | bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS; |
| 647 | 590 | ||
| @@ -665,11 +608,11 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) | |||
| 665 | unsigned long iova; | 608 | unsigned long iova; |
| 666 | struct iommu_domain *domain = dev; | 609 | struct iommu_domain *domain = dev; |
| 667 | struct arm_smmu_domain *smmu_domain = domain->priv; | 610 | struct arm_smmu_domain *smmu_domain = domain->priv; |
| 668 | struct arm_smmu_cfg *root_cfg = &smmu_domain->root_cfg; | 611 | struct arm_smmu_cfg *cfg = &smmu_domain->cfg; |
| 669 | struct arm_smmu_device *smmu = root_cfg->smmu; | 612 | struct arm_smmu_device *smmu = smmu_domain->smmu; |
| 670 | void __iomem *cb_base; | 613 | void __iomem *cb_base; |
| 671 | 614 | ||
| 672 | cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, root_cfg->cbndx); | 615 | cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx); |
| 673 | fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR); | 616 | fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR); |
| 674 | |||
