aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/arm-smmu.c
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2014-07-15 06:27:08 -0400
committerWill Deacon <will.deacon@arm.com>2014-09-16 14:14:16 -0400
commit8f68f8e28298abdf518648e794c71e534eb8841c (patch)
treeb84a1dd2233efcda165e48446f81e564d636ce1e /drivers/iommu/arm-smmu.c
parent4cf740b0b6628bda1e5c9201ae0d4f56fc6c06a5 (diff)
iommu/arm-smmu: add support for multi-master iommu groups
Whilst the driver currently creates one IOMMU group per device, this will soon change when we start supporting non-transparent PCI bridges which require all upstream masters to be assigned to the same address space. This patch reworks our IOMMU group code so that we can easily support multi-master groups. The master configuration (streamids and smrs) is stored as private iommudata on the group, whilst the low-level attach/detach code is updated to avoid double alloc/free when dealing with multiple masters sharing the same SMMU configuration. This unifies device handling, regardless of whether the device sits on the platform or pci bus. Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu/arm-smmu.c')
-rw-r--r--drivers/iommu/arm-smmu.c65
1 files changed, 39 insertions, 26 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 958ae8194afe..38f8d670afb3 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -431,17 +431,17 @@ static void parse_driver_options(struct arm_smmu_device *smmu)
431 } while (arm_smmu_options[++i].opt); 431 } while (arm_smmu_options[++i].opt);
432} 432}
433 433
434static struct device *dev_get_master_dev(struct device *dev) 434static struct device_node *dev_get_dev_node(struct device *dev)
435{ 435{
436 if (dev_is_pci(dev)) { 436 if (dev_is_pci(dev)) {
437 struct pci_bus *bus = to_pci_dev(dev)->bus; 437 struct pci_bus *bus = to_pci_dev(dev)->bus;
438 438
439 while (!pci_is_root_bus(bus)) 439 while (!pci_is_root_bus(bus))
440 bus = bus->parent; 440 bus = bus->parent;
441 return bus->bridge->parent; 441 return bus->bridge->parent->of_node;
442 } 442 }
443 443
444 return dev; 444 return dev->of_node;
445} 445}
446 446
447static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu, 447static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu,
@@ -466,15 +466,17 @@ static struct arm_smmu_master *find_smmu_master(struct arm_smmu_device *smmu,
466} 466}
467 467
468static struct arm_smmu_master_cfg * 468static struct arm_smmu_master_cfg *
469find_smmu_master_cfg(struct arm_smmu_device *smmu, struct device *dev) 469find_smmu_master_cfg(struct device *dev)
470{ 470{
471 struct arm_smmu_master *master; 471 struct arm_smmu_master_cfg *cfg = NULL;
472 struct iommu_group *group = iommu_group_get(dev);
472 473
473 if (dev_is_pci(dev)) 474 if (group) {
474 return dev->archdata.iommu; 475 cfg = iommu_group_get_iommudata(group);
476 iommu_group_put(group);
477 }
475 478
476 master = find_smmu_master(smmu, dev->of_node); 479 return cfg;
477 return master ? &master->cfg : NULL;
478} 480}
479 481
480static int insert_smmu_master(struct arm_smmu_device *smmu, 482static int insert_smmu_master(struct arm_smmu_device *smmu,
@@ -550,7 +552,7 @@ static struct arm_smmu_device *find_smmu_for_device(struct device *dev)
550{ 552{
551 struct arm_smmu_device *smmu; 553 struct arm_smmu_device *smmu;
552 struct arm_smmu_master *master = NULL; 554 struct arm_smmu_master *master = NULL;
553 struct device_node *dev_node = dev_get_master_dev(dev)->of_node; 555 struct device_node *dev_node = dev_get_dev_node(dev);
554 556
555 spin_lock(&arm_smmu_devices_lock); 557 spin_lock(&arm_smmu_devices_lock);
556 list_for_each_entry(smmu, &arm_smmu_devices, list) { 558 list_for_each_entry(smmu, &arm_smmu_devices, list) {
@@ -1156,9 +1158,10 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
1156 struct arm_smmu_device *smmu = smmu_domain->smmu; 1158 struct arm_smmu_device *smmu = smmu_domain->smmu;
1157 void __iomem *gr0_base = ARM_SMMU_GR0(smmu); 1159 void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1158 1160
1161 /* Devices in an IOMMU group may already be configured */
1159 ret = arm_smmu_master_configure_smrs(smmu, cfg); 1162 ret = arm_smmu_master_configure_smrs(smmu, cfg);
1160 if (ret) 1163 if (ret)
1161 return ret; 1164 return ret == -EEXIST ? 0 : ret;
1162 1165
1163 for (i = 0; i < cfg->num_streamids; ++i) { 1166 for (i = 0; i < cfg->num_streamids; ++i) {
1164 u32 idx, s2cr; 1167 u32 idx, s2cr;
@@ -1179,6 +1182,10 @@ static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain,
1179 struct arm_smmu_device *smmu = smmu_domain->smmu; 1182 struct arm_smmu_device *smmu = smmu_domain->smmu;
1180 void __iomem *gr0_base = ARM_SMMU_GR0(smmu); 1183 void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1181 1184
1185 /* An IOMMU group is torn down by the first device to be removed */
1186 if ((smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) && !cfg->smrs)
1187 return;
1188
1182 /* 1189 /*
1183 * We *must* clear the S2CR first, because freeing the SMR means 1190 * We *must* clear the S2CR first, because freeing the SMR means
1184 * that it can be re-allocated immediately. 1191 * that it can be re-allocated immediately.
@@ -1200,7 +1207,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
1200 struct arm_smmu_device *smmu, *dom_smmu; 1207 struct arm_smmu_device *smmu, *dom_smmu;
1201 struct arm_smmu_master_cfg *cfg; 1208 struct arm_smmu_master_cfg *cfg;
1202 1209
1203 smmu = dev_get_master_dev(dev)->archdata.iommu; 1210 smmu = find_smmu_for_device(dev);
1204 if (!smmu) { 1211 if (!smmu) {
1205 dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n"); 1212 dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
1206 return -ENXIO; 1213 return -ENXIO;
@@ -1228,7 +1235,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
1228 } 1235 }
1229 1236
1230 /* Looks ok, so add the device to the domain */ 1237 /* Looks ok, so add the device to the domain */
1231 cfg = find_smmu_master_cfg(smmu_domain->smmu, dev); 1238 cfg = find_smmu_master_cfg(dev);
1232 if (!cfg) 1239 if (!cfg)
1233 return -ENODEV; 1240 return -ENODEV;
1234 1241
@@ -1240,7 +1247,7 @@ static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
1240 struct arm_smmu_domain *smmu_domain = domain->priv; 1247 struct arm_smmu_domain *smmu_domain = domain->priv;
1241 struct arm_smmu_master_cfg *cfg; 1248 struct arm_smmu_master_cfg *cfg;
1242 1249
1243 cfg = find_smmu_master_cfg(smmu_domain->smmu, dev); 1250 cfg = find_smmu_master_cfg(dev);
1244 if (cfg) 1251 if (cfg)
1245 arm_smmu_domain_remove_master(smmu_domain, cfg); 1252 arm_smmu_domain_remove_master(smmu_domain, cfg);
1246} 1253}
@@ -1554,17 +1561,19 @@ static int __arm_smmu_get_pci_sid(struct pci_dev *pdev, u16 alias, void *data)
1554 return 0; /* Continue walking */ 1561 return 0; /* Continue walking */
1555} 1562}
1556 1563
1564static void __arm_smmu_release_pci_iommudata(void *data)
1565{
1566 kfree(data);
1567}
1568
1557static int arm_smmu_add_device(struct device *dev) 1569static int arm_smmu_add_device(struct device *dev)
1558{ 1570{
1559 struct arm_smmu_device *smmu; 1571 struct arm_smmu_device *smmu;
1572 struct arm_smmu_master_cfg *cfg;
1560 struct iommu_group *group; 1573 struct iommu_group *group;
1574 void (*releasefn)(void *) = NULL;
1561 int ret; 1575 int ret;
1562 1576
1563 if (dev->archdata.iommu) {
1564 dev_warn(dev, "IOMMU driver already assigned to device\n");
1565 return -EINVAL;
1566 }
1567
1568 smmu = find_smmu_for_device(dev); 1577 smmu = find_smmu_for_device(dev);
1569 if (!smmu) 1578 if (!smmu)
1570 return -ENODEV; 1579 return -ENODEV;
@@ -1576,7 +1585,6 @@ static int arm_smmu_add_device(struct device *dev)
1576 } 1585 }
1577 1586
1578 if (dev_is_pci(dev)) { 1587 if (dev_is_pci(dev)) {
1579 struct arm_smmu_master_cfg *cfg;
1580 struct pci_dev *pdev = to_pci_dev(dev); 1588 struct pci_dev *pdev = to_pci_dev(dev);
1581 1589
1582 cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); 1590 cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
@@ -1592,11 +1600,20 @@ static int arm_smmu_add_device(struct device *dev)
1592 */ 1600 */
1593 pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid, 1601 pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid,
1594 &cfg->streamids[0]); 1602 &cfg->streamids[0]);
1595 dev->archdata.iommu = cfg; 1603 releasefn = __arm_smmu_release_pci_iommudata;
1596 } else { 1604 } else {
1597 dev->archdata.iommu = smmu; 1605 struct arm_smmu_master *master;
1606
1607 master = find_smmu_master(smmu, dev->of_node);
1608 if (!master) {
1609 ret = -ENODEV;
1610 goto out_put_group;
1611 }
1612
1613 cfg = &master->cfg;
1598 } 1614 }
1599 1615
1616 iommu_group_set_iommudata(group, cfg, releasefn);
1600 ret = iommu_group_add_device(group, dev); 1617 ret = iommu_group_add_device(group, dev);
1601 1618
1602out_put_group: 1619out_put_group:
@@ -1606,10 +1623,6 @@ out_put_group:
1606 1623
1607static void arm_smmu_remove_device(struct device *dev) 1624static void arm_smmu_remove_device(struct device *dev)
1608{ 1625{
1609 if (dev_is_pci(dev))
1610 kfree(dev->archdata.iommu);
1611
1612 dev->archdata.iommu = NULL;
1613 iommu_group_remove_device(dev); 1626 iommu_group_remove_device(dev);
1614} 1627}
1615 1628