diff options
| -rw-r--r-- | drivers/iommu/arm-smmu-v3.c | 201 |
1 files changed, 195 insertions, 6 deletions
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 3e7198ee9530..3bde137a3755 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/of_iommu.h> | 29 | #include <linux/of_iommu.h> |
| 30 | #include <linux/of_platform.h> | 30 | #include <linux/of_platform.h> |
| 31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
| 32 | #include <linux/pci-ats.h> | ||
| 32 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
| 33 | 34 | ||
| 34 | #include <linux/amba/bus.h> | 35 | #include <linux/amba/bus.h> |
| @@ -86,6 +87,7 @@ | |||
| 86 | #define IDR5_VAX_52_BIT 1 | 87 | #define IDR5_VAX_52_BIT 1 |
| 87 | 88 | ||
| 88 | #define ARM_SMMU_CR0 0x20 | 89 | #define ARM_SMMU_CR0 0x20 |
| 90 | #define CR0_ATSCHK (1 << 4) | ||
| 89 | #define CR0_CMDQEN (1 << 3) | 91 | #define CR0_CMDQEN (1 << 3) |
| 90 | #define CR0_EVTQEN (1 << 2) | 92 | #define CR0_EVTQEN (1 << 2) |
| 91 | #define CR0_PRIQEN (1 << 1) | 93 | #define CR0_PRIQEN (1 << 1) |
| @@ -294,6 +296,7 @@ | |||
| 294 | #define CMDQ_ERR_CERROR_NONE_IDX 0 | 296 | #define CMDQ_ERR_CERROR_NONE_IDX 0 |
| 295 | #define CMDQ_ERR_CERROR_ILL_IDX 1 | 297 | #define CMDQ_ERR_CERROR_ILL_IDX 1 |
| 296 | #define CMDQ_ERR_CERROR_ABT_IDX 2 | 298 | #define CMDQ_ERR_CERROR_ABT_IDX 2 |
| 299 | #define CMDQ_ERR_CERROR_ATC_INV_IDX 3 | ||
| 297 | 300 | ||
| 298 | #define CMDQ_0_OP GENMASK_ULL(7, 0) | 301 | #define CMDQ_0_OP GENMASK_ULL(7, 0) |
| 299 | #define CMDQ_0_SSV (1UL << 11) | 302 | #define CMDQ_0_SSV (1UL << 11) |
| @@ -312,6 +315,12 @@ | |||
| 312 | #define CMDQ_TLBI_1_VA_MASK GENMASK_ULL(63, 12) | 315 | #define CMDQ_TLBI_1_VA_MASK GENMASK_ULL(63, 12) |
| 313 | #define CMDQ_TLBI_1_IPA_MASK GENMASK_ULL(51, 12) | 316 | #define CMDQ_TLBI_1_IPA_MASK GENMASK_ULL(51, 12) |
| 314 | 317 | ||
| 318 | #define CMDQ_ATC_0_SSID GENMASK_ULL(31, 12) | ||
| 319 | #define CMDQ_ATC_0_SID GENMASK_ULL(63, 32) | ||
| 320 | #define CMDQ_ATC_0_GLOBAL (1UL << 9) | ||
| 321 | #define CMDQ_ATC_1_SIZE GENMASK_ULL(5, 0) | ||
| 322 | #define CMDQ_ATC_1_ADDR_MASK GENMASK_ULL(63, 12) | ||
| 323 | |||
| 315 | #define CMDQ_PRI_0_SSID GENMASK_ULL(31, 12) | 324 | #define CMDQ_PRI_0_SSID GENMASK_ULL(31, 12) |
| 316 | #define CMDQ_PRI_0_SID GENMASK_ULL(63, 32) | 325 | #define CMDQ_PRI_0_SID GENMASK_ULL(63, 32) |
| 317 | #define CMDQ_PRI_1_GRPID GENMASK_ULL(8, 0) | 326 | #define CMDQ_PRI_1_GRPID GENMASK_ULL(8, 0) |
| @@ -433,6 +442,16 @@ struct arm_smmu_cmdq_ent { | |||
| 433 | u64 addr; | 442 | u64 addr; |
| 434 | } tlbi; | 443 | } tlbi; |
| 435 | 444 | ||
| 445 | #define CMDQ_OP_ATC_INV 0x40 | ||
| 446 | #define ATC_INV_SIZE_ALL 52 | ||
| 447 | struct { | ||
| 448 | u32 sid; | ||
| 449 | u32 ssid; | ||
| 450 | u64 addr; | ||
| 451 | u8 size; | ||
| 452 | bool global; | ||
| 453 | } atc; | ||
| 454 | |||
| 436 | #define CMDQ_OP_PRI_RESP 0x41 | 455 | #define CMDQ_OP_PRI_RESP 0x41 |
| 437 | struct { | 456 | struct { |
| 438 | u32 sid; | 457 | u32 sid; |
| @@ -580,10 +599,12 @@ struct arm_smmu_device { | |||
| 580 | /* SMMU private data for each master */ | 599 | /* SMMU private data for each master */ |
| 581 | struct arm_smmu_master { | 600 | struct arm_smmu_master { |
| 582 | struct arm_smmu_device *smmu; | 601 | struct arm_smmu_device *smmu; |
| 602 | struct device *dev; | ||
| 583 | struct arm_smmu_domain *domain; | 603 | struct arm_smmu_domain *domain; |
| 584 | struct list_head domain_head; | 604 | struct list_head domain_head; |
| 585 | u32 *sids; | 605 | u32 *sids; |
| 586 | unsigned int num_sids; | 606 | unsigned int num_sids; |
| 607 | bool ats_enabled :1; | ||
| 587 | }; | 608 | }; |
| 588 | 609 | ||
| 589 | /* SMMU private data for an IOMMU domain */ | 610 | /* SMMU private data for an IOMMU domain */ |
| @@ -813,6 +834,14 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent) | |||
| 813 | case CMDQ_OP_TLBI_S12_VMALL: | 834 | case CMDQ_OP_TLBI_S12_VMALL: |
| 814 | cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid); | 835 | cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid); |
| 815 | break; | 836 | break; |
| 837 | case CMDQ_OP_ATC_INV: | ||
| 838 | cmd[0] |= FIELD_PREP(CMDQ_0_SSV, ent->substream_valid); | ||
| 839 | cmd[0] |= FIELD_PREP(CMDQ_ATC_0_GLOBAL, ent->atc.global); | ||
| 840 | cmd[0] |= FIELD_PREP(CMDQ_ATC_0_SSID, ent->atc.ssid); | ||
| 841 | cmd[0] |= FIELD_PREP(CMDQ_ATC_0_SID, ent->atc.sid); | ||
| 842 | cmd[1] |= FIELD_PREP(CMDQ_ATC_1_SIZE, ent->atc.size); | ||
| 843 | cmd[1] |= ent->atc.addr & CMDQ_ATC_1_ADDR_MASK; | ||
| 844 | break; | ||
| 816 | case CMDQ_OP_PRI_RESP: | 845 | case CMDQ_OP_PRI_RESP: |
| 817 | cmd[0] |= FIELD_PREP(CMDQ_0_SSV, ent->substream_valid); | 846 | cmd[0] |= FIELD_PREP(CMDQ_0_SSV, ent->substream_valid); |
| 818 | cmd[0] |= FIELD_PREP(CMDQ_PRI_0_SSID, ent->pri.ssid); | 847 | cmd[0] |= FIELD_PREP(CMDQ_PRI_0_SSID, ent->pri.ssid); |
| @@ -857,6 +886,7 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu) | |||
| 857 | [CMDQ_ERR_CERROR_NONE_IDX] = "No error", | 886 | [CMDQ_ERR_CERROR_NONE_IDX] = "No error", |
| 858 | [CMDQ_ERR_CERROR_ILL_IDX] = "Illegal command", | 887 | [CMDQ_ERR_CERROR_ILL_IDX] = "Illegal command", |
| 859 | [CMDQ_ERR_CERROR_ABT_IDX] = "Abort on command fetch", | 888 | [CMDQ_ERR_CERROR_ABT_IDX] = "Abort on command fetch", |
| 889 | [CMDQ_ERR_CERROR_ATC_INV_IDX] = "ATC invalidate timeout", | ||
| 860 | }; | 890 | }; |
| 861 | 891 | ||
| 862 | int i; | 892 | int i; |
| @@ -876,6 +906,14 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu) | |||
| 876 | dev_err(smmu->dev, "retrying command fetch\n"); | 906 | dev_err(smmu->dev, "retrying command fetch\n"); |
| 877 | case CMDQ_ERR_CERROR_NONE_IDX: | 907 | case CMDQ_ERR_CERROR_NONE_IDX: |
| 878 | return; | 908 | return; |
| 909 | case CMDQ_ERR_CERROR_ATC_INV_IDX: | ||
| 910 | /* | ||
| 911 | * ATC Invalidation Completion timeout. CONS is still pointing | ||
| 912 | * at the CMD_SYNC. Attempt to complete other pending commands | ||
| 913 | * by repeating the CMD_SYNC, though we might well end up back | ||
| 914 | * here since the ATC invalidation may still be pending. | ||
| 915 | */ | ||
| 916 | return; | ||
| 879 | case CMDQ_ERR_CERROR_ILL_IDX: | 917 | case CMDQ_ERR_CERROR_ILL_IDX: |
| 880 | /* Fallthrough */ | 918 | /* Fallthrough */ |
| 881 | default: | 919 | default: |
| @@ -992,7 +1030,7 @@ static int __arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu) | |||
| 992 | return ret; | 1030 | return ret; |
| 993 | } | 1031 | } |
| 994 | 1032 | ||
| 995 | static void arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu) | 1033 | static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu) |
| 996 | { | 1034 | { |
| 997 | int ret; | 1035 | int ret; |
| 998 | bool msi = (smmu->features & ARM_SMMU_FEAT_MSI) && | 1036 | bool msi = (smmu->features & ARM_SMMU_FEAT_MSI) && |
| @@ -1002,6 +1040,7 @@ static void arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu) | |||
| 1002 | : __arm_smmu_cmdq_issue_sync(smmu); | 1040 | : __arm_smmu_cmdq_issue_sync(smmu); |
| 1003 | if (ret) | 1041 | if (ret) |
| 1004 | dev_err_ratelimited(smmu->dev, "CMD_SYNC timeout\n"); | 1042 | dev_err_ratelimited(smmu->dev, "CMD_SYNC timeout\n"); |
| 1043 | return ret; | ||
| 1005 | } | 1044 | } |
| 1006 | 1045 | ||
| 1007 | /* Context descriptor manipulation functions */ | 1046 | /* Context descriptor manipulation functions */ |
| @@ -1174,9 +1213,6 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid, | |||
| 1174 | FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) | | 1213 | FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) | |
| 1175 | FIELD_PREP(STRTAB_STE_1_S1COR, STRTAB_STE_1_S1C_CACHE_WBRA) | | 1214 | FIELD_PREP(STRTAB_STE_1_S1COR, STRTAB_STE_1_S1C_CACHE_WBRA) | |
| 1176 | FIELD_PREP(STRTAB_STE_1_S1CSH, ARM_SMMU_SH_ISH) | | 1215 | FIELD_PREP(STRTAB_STE_1_S1CSH, ARM_SMMU_SH_ISH) | |
| 1177 | #ifdef CONFIG_PCI_ATS | ||
| 1178 | FIELD_PREP(STRTAB_STE_1_EATS, STRTAB_STE_1_EATS_TRANS) | | ||
| 1179 | #endif | ||
| 1180 | FIELD_PREP(STRTAB_STE_1_STRW, STRTAB_STE_1_STRW_NSEL1)); | 1216 | FIELD_PREP(STRTAB_STE_1_STRW, STRTAB_STE_1_STRW_NSEL1)); |
| 1181 | 1217 | ||
| 1182 | if (smmu->features & ARM_SMMU_FEAT_STALLS && | 1218 | if (smmu->features & ARM_SMMU_FEAT_STALLS && |
| @@ -1203,6 +1239,10 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid, | |||
| 1203 | val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S2_TRANS); | 1239 | val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S2_TRANS); |
| 1204 | } | 1240 | } |
| 1205 | 1241 | ||
| 1242 | if (master->ats_enabled) | ||
| 1243 | dst[1] |= cpu_to_le64(FIELD_PREP(STRTAB_STE_1_EATS, | ||
| 1244 | STRTAB_STE_1_EATS_TRANS)); | ||
| 1245 | |||
| 1206 | arm_smmu_sync_ste_for_sid(smmu, sid); | 1246 | arm_smmu_sync_ste_for_sid(smmu, sid); |
| 1207 | dst[0] = cpu_to_le64(val); | 1247 | dst[0] = cpu_to_le64(val); |
| 1208 | arm_smmu_sync_ste_for_sid(smmu, sid); | 1248 | arm_smmu_sync_ste_for_sid(smmu, sid); |
| @@ -1405,6 +1445,96 @@ static irqreturn_t arm_smmu_combined_irq_handler(int irq, void *dev) | |||
| 1405 | return IRQ_WAKE_THREAD; | 1445 | return IRQ_WAKE_THREAD; |
| 1406 | } | 1446 | } |
| 1407 | 1447 | ||
| 1448 | static void | ||
| 1449 | arm_smmu_atc_inv_to_cmd(int ssid, unsigned long iova, size_t size, | ||
| 1450 | struct arm_smmu_cmdq_ent *cmd) | ||
| 1451 | { | ||
| 1452 | size_t log2_span; | ||
| 1453 | size_t span_mask; | ||
| 1454 | /* ATC invalidates are always on 4096-bytes pages */ | ||
| 1455 | size_t inval_grain_shift = 12; | ||
| 1456 | unsigned long page_start, page_end; | ||
| 1457 | |||
| 1458 | *cmd = (struct arm_smmu_cmdq_ent) { | ||
| 1459 | .opcode = CMDQ_OP_ATC_INV, | ||
| 1460 | .substream_valid = !!ssid, | ||
| 1461 | .atc.ssid = ssid, | ||
| 1462 | }; | ||
| 1463 | |||
| 1464 | if (!size) { | ||
| 1465 | cmd->atc.size = ATC_INV_SIZE_ALL; | ||
| 1466 | return; | ||
| 1467 | } | ||
| 1468 | |||
| 1469 | page_start = iova >> inval_grain_shift; | ||
| 1470 | page_end = (iova + size - 1) >> inval_grain_shift; | ||
| 1471 | |||
| 1472 | /* | ||
| 1473 | * In an ATS Invalidate Request, the address must be aligned on the | ||
| 1474 | * range size, which must be a power of two number of page sizes. We | ||
| 1475 | * thus have to choose between grossly over-invalidating the region, or | ||
| 1476 | * splitting the invalidation into multiple commands. For simplicity | ||
| 1477 | * we'll go with the first solution, but should refine it in the future | ||
| 1478 | * if multiple commands are shown to be more efficient. | ||
| 1479 | * | ||
| 1480 | * Find the smallest power of two that covers the range. The most | ||
| 1481 | * significant differing bit between the start and end addresses, | ||
| 1482 | * fls(start ^ end), indicates the required span. For example: | ||
| 1483 | * | ||
| 1484 | * We want to invalidate pages [8; 11]. This is already the ideal range: | ||
| 1485 | * x = 0b1000 ^ 0b1011 = 0b11 | ||
| 1486 | * span = 1 << fls(x) = 4 | ||
| 1487 | * | ||
| 1488 | * To invalidate pages [7; 10], we need to invalidate [0; 15]: | ||
| 1489 | * x = 0b0111 ^ 0b1010 = 0b1101 | ||
| 1490 | * span = 1 << fls(x) = 16 | ||
| 1491 | */ | ||
| 1492 | log2_span = fls_long(page_start ^ page_end); | ||
| 1493 | span_mask = (1ULL << log2_span) - 1; | ||
| 1494 | |||
| 1495 | page_start &= ~span_mask; | ||
| 1496 | |||
| 1497 | cmd->atc.addr = page_start << inval_grain_shift; | ||
| 1498 | cmd->atc.size = log2_span; | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | static int arm_smmu_atc_inv_master(struct arm_smmu_master *master, | ||
| 1502 | struct arm_smmu_cmdq_ent *cmd) | ||
| 1503 | { | ||
| 1504 | int i; | ||
| 1505 | |||
| 1506 | if (!master->ats_enabled) | ||
| 1507 | return 0; | ||
| 1508 | |||
| 1509 | for (i = 0; i < master->num_sids; i++) { | ||
| 1510 | cmd->atc.sid = master->sids[i]; | ||
| 1511 | arm_smmu_cmdq_issue_cmd(master->smmu, cmd); | ||
| 1512 | } | ||
| 1513 | |||
| 1514 | return arm_smmu_cmdq_issue_sync(master->smmu); | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | static int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, | ||
| 1518 | int ssid, unsigned long iova, size_t size) | ||
| 1519 | { | ||
| 1520 | int ret = 0; | ||
| 1521 | unsigned long flags; | ||
| 1522 | struct arm_smmu_cmdq_ent cmd; | ||
| 1523 | struct arm_smmu_master *master; | ||
| 1524 | |||
| 1525 | if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS)) | ||
| 1526 | return 0; | ||
| 1527 | |||
| 1528 | arm_smmu_atc_inv_to_cmd(ssid, iova, size, &cmd); | ||
| 1529 | |||
| 1530 | spin_lock_irqsave(&smmu_domain->devices_lock, flags); | ||
| 1531 | list_for_each_entry(master, &smmu_domain->devices, domain_head) | ||
| 1532 | ret |= arm_smmu_atc_inv_master(master, &cmd); | ||
| 1533 | spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); | ||
| 1534 | |||
| 1535 | return ret ? -ETIMEDOUT : 0; | ||
| 1536 | } | ||
| 1537 | |||
| 1408 | /* IO_PGTABLE API */ | 1538 | /* IO_PGTABLE API */ |
| 1409 | static void arm_smmu_tlb_sync(void *cookie) | 1539 | static void arm_smmu_tlb_sync(void *cookie) |
| 1410 | { | 1540 | { |
| @@ -1726,6 +1856,42 @@ static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master) | |||
| 1726 | } | 1856 | } |
| 1727 | } | 1857 | } |
| 1728 | 1858 | ||
| 1859 | static int arm_smmu_enable_ats(struct arm_smmu_master *master) | ||
| 1860 | { | ||
| 1861 | int ret; | ||
| 1862 | size_t stu; | ||
| 1863 | struct pci_dev *pdev; | ||
| 1864 | struct arm_smmu_device *smmu = master->smmu; | ||
| 1865 | struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev); | ||
| 1866 | |||
| 1867 | if (!(smmu->features & ARM_SMMU_FEAT_ATS) || !dev_is_pci(master->dev) || | ||
| 1868 | !(fwspec->flags & IOMMU_FWSPEC_PCI_RC_ATS) || pci_ats_disabled()) | ||
| 1869 | return -ENXIO; | ||
| 1870 | |||
| 1871 | pdev = to_pci_dev(master->dev); | ||
| 1872 | if (pdev->untrusted) | ||
| 1873 | return -EPERM; | ||
| 1874 | |||
| 1875 | /* Smallest Translation Unit: log2 of the smallest supported granule */ | ||
| 1876 | stu = __ffs(smmu->pgsize_bitmap); | ||
| 1877 | |||
| 1878 | ret = pci_enable_ats(pdev, stu); | ||
| 1879 | if (ret) | ||
| 1880 | return ret; | ||
| 1881 | |||
| 1882 | master->ats_enabled = true; | ||
| 1883 | return 0; | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | static void arm_smmu_disable_ats(struct arm_smmu_master *master) | ||
| 1887 | { | ||
| 1888 | if (!master->ats_enabled || !dev_is_pci(master->dev)) | ||
| 1889 | return; | ||
| 1890 | |||
| 1891 | pci_disable_ats(to_pci_dev(master->dev)); | ||
| 1892 | master->ats_enabled = false; | ||
| 1893 | } | ||
| 1894 | |||
| 1729 | static void arm_smmu_detach_dev(struct arm_smmu_master *master) | 1895 | static void arm_smmu_detach_dev(struct arm_smmu_master *master) |
| 1730 | { | 1896 | { |
| 1731 | unsigned long flags; | 1897 | unsigned long flags; |
| @@ -1740,6 +1906,9 @@ static void arm_smmu_detach_dev(struct arm_smmu_master *master) | |||
| 1740 | 1906 | ||
| 1741 | master->domain = NULL; | 1907 | master->domain = NULL; |
| 1742 | arm_smmu_install_ste_for_dev(master); | 1908 | arm_smmu_install_ste_for_dev(master); |
| 1909 | |||
| 1910 | /* Disabling ATS invalidates all ATC entries */ | ||
| 1911 | arm_smmu_disable_ats(master); | ||
| 1743 | } | 1912 | } |
| 1744 | 1913 | ||
| 1745 | static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | 1914 | static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) |
| @@ -1783,6 +1952,9 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
| 1783 | list_add(&master->domain_head, &smmu_domain->devices); | 1952 | list_add(&master->domain_head, &smmu_domain->devices); |
| 1784 | spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); | 1953 | spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); |
| 1785 | 1954 | ||
| 1955 | if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS) | ||
| 1956 | arm_smmu_enable_ats(master); | ||
| 1957 | |||
| 1786 | if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) | 1958 | if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) |
| 1787 | arm_smmu_write_ctx_desc(smmu, &smmu_domain->s1_cfg); | 1959 | arm_smmu_write_ctx_desc(smmu, &smmu_domain->s1_cfg); |
| 1788 | 1960 | ||
| @@ -1806,12 +1978,18 @@ static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, | |||
| 1806 | static size_t | 1978 | static size_t |
| 1807 | arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) | 1979 | arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) |
| 1808 | { | 1980 | { |
| 1809 | struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; | 1981 | int ret; |
| 1982 | struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); | ||
| 1983 | struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops; | ||
| 1810 | 1984 | ||
| 1811 | if (!ops) | 1985 | if (!ops) |
| 1812 | return 0; | 1986 | return 0; |
| 1813 | 1987 | ||
| 1814 | return ops->unmap(ops, iova, size); | 1988 | ret = ops->unmap(ops, iova, size); |
| 1989 | if (ret && arm_smmu_atc_inv_domain(smmu_domain, 0, iova, size)) | ||
| 1990 | return 0; | ||
| 1991 | |||
| 1992 | return ret; | ||
| 1815 | } | 1993 | } |
| 1816 | 1994 | ||
| 1817 | static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) | 1995 | static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) |
| @@ -1898,6 +2076,7 @@ static int arm_smmu_add_device(struct device *dev) | |||
| 1898 | if (!master) | 2076 | if (!master) |
| 1899 | return -ENOMEM; | 2077 | return -ENOMEM; |
| 1900 | 2078 | ||
| 2079 | master->dev = dev; | ||
| 1901 | master->smmu = smmu; | 2080 | master->smmu = smmu; |
| 1902 | master->sids = fwspec->ids; | 2081 | master->sids = fwspec->ids; |
| 1903 | master->num_sids = fwspec->num_ids; | 2082 | master->num_sids = fwspec->num_ids; |
| @@ -2564,6 +2743,16 @@ static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass) | |||
| 2564 | } | 2743 | } |
| 2565 | } | 2744 | } |
| 2566 | 2745 | ||
| 2746 | if (smmu->features & ARM_SMMU_FEAT_ATS) { | ||
| 2747 | enables |= CR0_ATSCHK; | ||
| 2748 | ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0, | ||
| 2749 | ARM_SMMU_CR0ACK); | ||
| 2750 | if (ret) { | ||
| 2751 | dev_err(smmu->dev, "failed to enable ATS check\n"); | ||
| 2752 | return ret; | ||
| 2753 | } | ||
| 2754 | } | ||
| 2755 | |||
| 2567 | ret = arm_smmu_setup_irqs(smmu); | 2756 | ret = arm_smmu_setup_irqs(smmu); |
| 2568 | if (ret) { | 2757 | if (ret) { |
| 2569 | dev_err(smmu->dev, "failed to setup irqs\n"); | 2758 | dev_err(smmu->dev, "failed to setup irqs\n"); |
