aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2015-03-31 09:38:02 -0400
committerJoerg Roedel <jroedel@suse.de>2015-03-31 09:38:02 -0400
commitb61e2e62aa2dee89d6e71aa90a9341607c4a7a97 (patch)
treeaa2f0ab23c4dcf657f5059a989589e7939fb48a0
parente42391cd048809d903291d07f86ed3934ce138e9 (diff)
parent63979b8da30013ce58d8447f34dde60802d1ccba (diff)
Merge branch 'for-joerg/arm-smmu/updates' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into arm/smmu
-rw-r--r--drivers/iommu/arm-smmu.c125
-rw-r--r--drivers/iommu/io-pgtable-arm.c5
2 files changed, 85 insertions, 45 deletions
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index fc13dd56953e..6ac184669295 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -730,6 +730,20 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
730 stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS; 730 stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
731 cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx); 731 cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
732 732
733 if (smmu->version > ARM_SMMU_V1) {
734 /*
735 * CBA2R.
736 * *Must* be initialised before CBAR thanks to VMID16
737 * architectural oversight affected some implementations.
738 */
739#ifdef CONFIG_64BIT
740 reg = CBA2R_RW64_64BIT;
741#else
742 reg = CBA2R_RW64_32BIT;
743#endif
744 writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBA2R(cfg->cbndx));
745 }
746
733 /* CBAR */ 747 /* CBAR */
734 reg = cfg->cbar; 748 reg = cfg->cbar;
735 if (smmu->version == ARM_SMMU_V1) 749 if (smmu->version == ARM_SMMU_V1)
@@ -747,16 +761,6 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
747 } 761 }
748 writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx)); 762 writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));
749 763
750 if (smmu->version > ARM_SMMU_V1) {
751 /* CBA2R */
752#ifdef CONFIG_64BIT
753 reg = CBA2R_RW64_64BIT;
754#else
755 reg = CBA2R_RW64_32BIT;
756#endif
757 writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBA2R(cfg->cbndx));
758 }
759
760 /* TTBRs */ 764 /* TTBRs */
761 if (stage1) { 765 if (stage1) {
762 reg = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0]; 766 reg = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];
@@ -1326,61 +1330,83 @@ static void __arm_smmu_release_pci_iommudata(void *data)
1326 kfree(data); 1330 kfree(data);
1327} 1331}
1328 1332
1329static int arm_smmu_add_device(struct device *dev) 1333static int arm_smmu_add_pci_device(struct pci_dev *pdev)
1330{ 1334{
1331 struct arm_smmu_device *smmu; 1335 int i, ret;
1332 struct arm_smmu_master_cfg *cfg; 1336 u16 sid;
1333 struct iommu_group *group; 1337 struct iommu_group *group;
1334 void (*releasefn)(void *) = NULL; 1338 struct arm_smmu_master_cfg *cfg;
1335 int ret;
1336
1337 smmu = find_smmu_for_device(dev);
1338 if (!smmu)
1339 return -ENODEV;
1340 1339
1341 group = iommu_group_alloc(); 1340 group = iommu_group_get_for_dev(&pdev->dev);
1342 if (IS_ERR(group)) { 1341 if (IS_ERR(group))
1343 dev_err(dev, "Failed to allocate IOMMU group\n");
1344 return PTR_ERR(group); 1342 return PTR_ERR(group);
1345 }
1346
1347 if (dev_is_pci(dev)) {
1348 struct pci_dev *pdev = to_pci_dev(dev);
1349 1343
1344 cfg = iommu_group_get_iommudata(group);
1345 if (!cfg) {
1350 cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); 1346 cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
1351 if (!cfg) { 1347 if (!cfg) {
1352 ret = -ENOMEM; 1348 ret = -ENOMEM;
1353 goto out_put_group; 1349 goto out_put_group;
1354 } 1350 }
1355 1351
1356 cfg->num_streamids = 1; 1352 iommu_group_set_iommudata(group, cfg,
1357 /* 1353 __arm_smmu_release_pci_iommudata);
1358 * Assume Stream ID == Requester ID for now. 1354 }
1359 * We need a way to describe the ID mappings in FDT.
1360 */
1361 pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid,
1362 &cfg->streamids[0]);
1363 releasefn = __arm_smmu_release_pci_iommudata;
1364 } else {
1365 struct arm_smmu_master *master;
1366
1367 master = find_smmu_master(smmu, dev->of_node);
1368 if (!master) {
1369 ret = -ENODEV;
1370 goto out_put_group;
1371 }
1372 1355
1373 cfg = &master->cfg; 1356 if (cfg->num_streamids >= MAX_MASTER_STREAMIDS) {
1357 ret = -ENOSPC;
1358 goto out_put_group;
1374 } 1359 }
1375 1360
1376 iommu_group_set_iommudata(group, cfg, releasefn); 1361 /*
1377 ret = iommu_group_add_device(group, dev); 1362 * Assume Stream ID == Requester ID for now.
1363 * We need a way to describe the ID mappings in FDT.
1364 */
1365 pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid, &sid);
1366 for (i = 0; i < cfg->num_streamids; ++i)
1367 if (cfg->streamids[i] == sid)
1368 break;
1369
1370 /* Avoid duplicate SIDs, as this can lead to SMR conflicts */
1371 if (i == cfg->num_streamids)
1372 cfg->streamids[cfg->num_streamids++] = sid;
1378 1373
1374 return 0;
1379out_put_group: 1375out_put_group:
1380 iommu_group_put(group); 1376 iommu_group_put(group);
1381 return ret; 1377 return ret;
1382} 1378}
1383 1379
1380static int arm_smmu_add_platform_device(struct device *dev)
1381{
1382 struct iommu_group *group;
1383 struct arm_smmu_master *master;
1384 struct arm_smmu_device *smmu = find_smmu_for_device(dev);
1385
1386 if (!smmu)
1387 return -ENODEV;
1388
1389 master = find_smmu_master(smmu, dev->of_node);
1390 if (!master)
1391 return -ENODEV;
1392
1393 /* No automatic group creation for platform devices */
1394 group = iommu_group_alloc();
1395 if (IS_ERR(group))
1396 return PTR_ERR(group);
1397
1398 iommu_group_set_iommudata(group, &master->cfg, NULL);
1399 return iommu_group_add_device(group, dev);
1400}
1401
1402static int arm_smmu_add_device(struct device *dev)
1403{
1404 if (dev_is_pci(dev))
1405 return arm_smmu_add_pci_device(to_pci_dev(dev));
1406
1407 return arm_smmu_add_platform_device(dev);
1408}
1409
1384static void arm_smmu_remove_device(struct device *dev) 1410static void arm_smmu_remove_device(struct device *dev)
1385{ 1411{
1386 iommu_group_remove_device(dev); 1412 iommu_group_remove_device(dev);
@@ -1630,6 +1656,15 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
1630 size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK); 1656 size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK);
1631 smmu->pa_size = size; 1657 smmu->pa_size = size;
1632 1658
1659 /*
1660 * What the page table walker can address actually depends on which
1661 * descriptor format is in use, but since a) we don't know that yet,
1662 * and b) it can vary per context bank, this will have to do...
1663 */
1664 if (dma_set_mask_and_coherent(smmu->dev, DMA_BIT_MASK(size)))
1665 dev_warn(smmu->dev,
1666 "failed to set DMA mask for table walker\n");
1667
1633 if (smmu->version == ARM_SMMU_V1) { 1668 if (smmu->version == ARM_SMMU_V1) {
1634 smmu->va_size = smmu->ipa_size; 1669 smmu->va_size = smmu->ipa_size;
1635 size = SZ_4K | SZ_2M | SZ_1G; 1670 size = SZ_4K | SZ_2M | SZ_1G;
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index b610a8dee238..4e460216bd16 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -116,6 +116,8 @@
116#define ARM_32_LPAE_TCR_EAE (1 << 31) 116#define ARM_32_LPAE_TCR_EAE (1 << 31)
117#define ARM_64_LPAE_S2_TCR_RES1 (1 << 31) 117#define ARM_64_LPAE_S2_TCR_RES1 (1 << 31)
118 118
119#define ARM_LPAE_TCR_EPD1 (1 << 23)
120
119#define ARM_LPAE_TCR_TG0_4K (0 << 14) 121#define ARM_LPAE_TCR_TG0_4K (0 << 14)
120#define ARM_LPAE_TCR_TG0_64K (1 << 14) 122#define ARM_LPAE_TCR_TG0_64K (1 << 14)
121#define ARM_LPAE_TCR_TG0_16K (2 << 14) 123#define ARM_LPAE_TCR_TG0_16K (2 << 14)
@@ -621,6 +623,9 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
621 } 623 }
622 624
623 reg |= (64ULL - cfg->ias) << ARM_LPAE_TCR_T0SZ_SHIFT; 625 reg |= (64ULL - cfg->ias) << ARM_LPAE_TCR_T0SZ_SHIFT;
626
627 /* Disable speculative walks through TTBR1 */
628 reg |= ARM_LPAE_TCR_EPD1;
624 cfg->arm_lpae_s1_cfg.tcr = reg; 629 cfg->arm_lpae_s1_cfg.tcr = reg;
625 630
626 /* MAIRs */ 631 /* MAIRs */