12d7ca2c4SAndrew Murray // SPDX-License-Identifier: GPL-2.0 248ec83bcSWill Deacon /* 348ec83bcSWill Deacon * IOMMU API for ARM architected SMMUv3 implementations. 448ec83bcSWill Deacon * 548ec83bcSWill Deacon * Copyright (C) 2015 ARM Limited 648ec83bcSWill Deacon * 748ec83bcSWill Deacon * Author: Will Deacon <will.deacon@arm.com> 848ec83bcSWill Deacon * 948ec83bcSWill Deacon * This driver is powered by bad coffee and bombay mix. 1048ec83bcSWill Deacon */ 1148ec83bcSWill Deacon 12e4dadfa8SLorenzo Pieralisi #include <linux/acpi.h> 13e4dadfa8SLorenzo Pieralisi #include <linux/acpi_iort.h> 141cf9e54eSRobin Murphy #include <linux/bitops.h> 15b63b3439SWill Deacon #include <linux/crash_dump.h> 1648ec83bcSWill Deacon #include <linux/delay.h> 179adb9594SRobin Murphy #include <linux/dma-iommu.h> 1848ec83bcSWill Deacon #include <linux/err.h> 1948ec83bcSWill Deacon #include <linux/interrupt.h> 20b77cf11fSRob Herring #include <linux/io-pgtable.h> 2148ec83bcSWill Deacon #include <linux/iopoll.h> 226e8fa740SWill Deacon #include <linux/module.h> 23166bdbd2SMarc Zyngier #include <linux/msi.h> 2448ec83bcSWill Deacon #include <linux/of.h> 2548ec83bcSWill Deacon #include <linux/of_address.h> 268f785154SRobin Murphy #include <linux/of_iommu.h> 27941a802dSWill Deacon #include <linux/of_platform.h> 2848ec83bcSWill Deacon #include <linux/pci.h> 299ce27afcSJean-Philippe Brucker #include <linux/pci-ats.h> 3048ec83bcSWill Deacon #include <linux/platform_device.h> 3148ec83bcSWill Deacon 3208d4ca2aSRobin Murphy #include <linux/amba/bus.h> 3308d4ca2aSRobin Murphy 34e881e783SJean-Philippe Brucker #include "arm-smmu-v3.h" 35395ad89dSJean-Philippe Brucker #include "../../iommu-sva-lib.h" 3650019f09SEric Auger 373045fe45SKaixu Xia static bool disable_bypass = true; 389305d02aSBarry Song module_param(disable_bypass, bool, 0444); 3948ec83bcSWill Deacon MODULE_PARM_DESC(disable_bypass, 4048ec83bcSWill Deacon "Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU."); 4148ec83bcSWill Deacon 42bd07a20aSBarry Song static bool disable_msipolling; 43bd07a20aSBarry Song module_param(disable_msipolling, bool, 0444); 44bd07a20aSBarry Song MODULE_PARM_DESC(disable_msipolling, 45bd07a20aSBarry Song "Disable MSI-based polling for CMD_SYNC completion."); 46bd07a20aSBarry Song 47166bdbd2SMarc Zyngier enum arm_smmu_msi_index { 48166bdbd2SMarc Zyngier EVTQ_MSI_INDEX, 49166bdbd2SMarc Zyngier GERROR_MSI_INDEX, 50166bdbd2SMarc Zyngier PRIQ_MSI_INDEX, 51166bdbd2SMarc Zyngier ARM_SMMU_MAX_MSIS, 52166bdbd2SMarc Zyngier }; 53166bdbd2SMarc Zyngier 54166bdbd2SMarc Zyngier static phys_addr_t arm_smmu_msi_cfg[ARM_SMMU_MAX_MSIS][3] = { 55166bdbd2SMarc Zyngier [EVTQ_MSI_INDEX] = { 56166bdbd2SMarc Zyngier ARM_SMMU_EVTQ_IRQ_CFG0, 57166bdbd2SMarc Zyngier ARM_SMMU_EVTQ_IRQ_CFG1, 58166bdbd2SMarc Zyngier ARM_SMMU_EVTQ_IRQ_CFG2, 59166bdbd2SMarc Zyngier }, 60166bdbd2SMarc Zyngier [GERROR_MSI_INDEX] = { 61166bdbd2SMarc Zyngier ARM_SMMU_GERROR_IRQ_CFG0, 62166bdbd2SMarc Zyngier ARM_SMMU_GERROR_IRQ_CFG1, 63166bdbd2SMarc Zyngier ARM_SMMU_GERROR_IRQ_CFG2, 64166bdbd2SMarc Zyngier }, 65166bdbd2SMarc Zyngier [PRIQ_MSI_INDEX] = { 66166bdbd2SMarc Zyngier ARM_SMMU_PRIQ_IRQ_CFG0, 67166bdbd2SMarc Zyngier ARM_SMMU_PRIQ_IRQ_CFG1, 68166bdbd2SMarc Zyngier ARM_SMMU_PRIQ_IRQ_CFG2, 69166bdbd2SMarc Zyngier }, 70166bdbd2SMarc Zyngier }; 71166bdbd2SMarc Zyngier 725e92946cSZhen Lei struct arm_smmu_option_prop { 735e92946cSZhen Lei u32 opt; 745e92946cSZhen Lei const char *prop; 755e92946cSZhen Lei }; 765e92946cSZhen Lei 773f1ce8e8SJean-Philippe Brucker DEFINE_XARRAY_ALLOC1(arm_smmu_asid_xa); 783f1ce8e8SJean-Philippe Brucker DEFINE_MUTEX(arm_smmu_asid_lock); 790299a1a8SJean-Philippe Brucker 8032784a95SJean-Philippe Brucker /* 8132784a95SJean-Philippe Brucker * Special value used by SVA when a process dies, to quiesce a CD without 8232784a95SJean-Philippe Brucker * disabling it. 8332784a95SJean-Philippe Brucker */ 8432784a95SJean-Philippe Brucker struct arm_smmu_ctx_desc quiet_cd = { 0 }; 8532784a95SJean-Philippe Brucker 865e92946cSZhen Lei static struct arm_smmu_option_prop arm_smmu_options[] = { 875e92946cSZhen Lei { ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" }, 88e5b829deSLinu Cherian { ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium,cn9900-broken-page1-regspace"}, 895e92946cSZhen Lei { 0, NULL}, 905e92946cSZhen Lei }; 915e92946cSZhen Lei 925e92946cSZhen Lei static void parse_driver_options(struct arm_smmu_device *smmu) 935e92946cSZhen Lei { 945e92946cSZhen Lei int i = 0; 955e92946cSZhen Lei 965e92946cSZhen Lei do { 975e92946cSZhen Lei if (of_property_read_bool(smmu->dev->of_node, 985e92946cSZhen Lei arm_smmu_options[i].prop)) { 995e92946cSZhen Lei smmu->options |= arm_smmu_options[i].opt; 1005e92946cSZhen Lei dev_notice(smmu->dev, "option %s\n", 1015e92946cSZhen Lei arm_smmu_options[i].prop); 1025e92946cSZhen Lei } 1035e92946cSZhen Lei } while (arm_smmu_options[++i].opt); 1045e92946cSZhen Lei } 1055e92946cSZhen Lei 10648ec83bcSWill Deacon /* Low-level queue manipulation functions */ 107587e6c10SWill Deacon static bool queue_has_space(struct arm_smmu_ll_queue *q, u32 n) 108587e6c10SWill Deacon { 109587e6c10SWill Deacon u32 space, prod, cons; 110587e6c10SWill Deacon 111587e6c10SWill Deacon prod = Q_IDX(q, q->prod); 112587e6c10SWill Deacon cons = Q_IDX(q, q->cons); 113587e6c10SWill Deacon 114587e6c10SWill Deacon if (Q_WRP(q, q->prod) == Q_WRP(q, q->cons)) 115587e6c10SWill Deacon space = (1 << q->max_n_shift) - (prod - cons); 116587e6c10SWill Deacon else 117587e6c10SWill Deacon space = cons - prod; 118587e6c10SWill Deacon 119587e6c10SWill Deacon return space >= n; 120587e6c10SWill Deacon } 121587e6c10SWill Deacon 1227c288a5bSWill Deacon static bool queue_full(struct arm_smmu_ll_queue *q) 12348ec83bcSWill Deacon { 12448ec83bcSWill Deacon return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) && 12548ec83bcSWill Deacon Q_WRP(q, q->prod) != Q_WRP(q, q->cons); 12648ec83bcSWill Deacon } 12748ec83bcSWill Deacon 1287c288a5bSWill Deacon static bool queue_empty(struct arm_smmu_ll_queue *q) 12948ec83bcSWill Deacon { 13048ec83bcSWill Deacon return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) && 13148ec83bcSWill Deacon Q_WRP(q, q->prod) == Q_WRP(q, q->cons); 13248ec83bcSWill Deacon } 13348ec83bcSWill Deacon 134587e6c10SWill Deacon static bool queue_consumed(struct arm_smmu_ll_queue *q, u32 prod) 13548ec83bcSWill Deacon { 136587e6c10SWill Deacon return ((Q_WRP(q, q->cons) == Q_WRP(q, prod)) && 137587e6c10SWill Deacon (Q_IDX(q, q->cons) > Q_IDX(q, prod))) || 138587e6c10SWill Deacon ((Q_WRP(q, q->cons) != Q_WRP(q, prod)) && 139587e6c10SWill Deacon (Q_IDX(q, q->cons) <= Q_IDX(q, prod))); 14048ec83bcSWill Deacon } 14148ec83bcSWill Deacon 1422a8868f1SWill Deacon static void queue_sync_cons_out(struct arm_smmu_queue *q) 14348ec83bcSWill Deacon { 144a868e853SWill Deacon /* 145a868e853SWill Deacon * Ensure that all CPU accesses (reads and writes) to the queue 146a868e853SWill Deacon * are complete before we update the cons pointer. 147a868e853SWill Deacon */ 148a76a3777SZhou Wang __iomb(); 14952be8637SWill Deacon writel_relaxed(q->llq.cons, q->cons_reg); 15048ec83bcSWill Deacon } 15148ec83bcSWill Deacon 1527c288a5bSWill Deacon static void queue_inc_cons(struct arm_smmu_ll_queue *q) 1532a8868f1SWill Deacon { 1547c288a5bSWill Deacon u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1; 1557c288a5bSWill Deacon q->cons = Q_OVF(q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons); 1562a8868f1SWill Deacon } 1572a8868f1SWill Deacon 1582a8868f1SWill Deacon static int queue_sync_prod_in(struct arm_smmu_queue *q) 15948ec83bcSWill Deacon { 160a76a3777SZhou Wang u32 prod; 16148ec83bcSWill Deacon int ret = 0; 162a76a3777SZhou Wang 163a76a3777SZhou Wang /* 164a76a3777SZhou Wang * We can't use the _relaxed() variant here, as we must prevent 165a76a3777SZhou Wang * speculative reads of the queue before we have determined that 166a76a3777SZhou Wang * prod has indeed moved. 167a76a3777SZhou Wang */ 168a76a3777SZhou Wang prod = readl(q->prod_reg); 16948ec83bcSWill Deacon 17052be8637SWill Deacon if (Q_OVF(prod) != Q_OVF(q->llq.prod)) 17148ec83bcSWill Deacon ret = -EOVERFLOW; 17248ec83bcSWill Deacon 17352be8637SWill Deacon q->llq.prod = prod; 17448ec83bcSWill Deacon return ret; 17548ec83bcSWill Deacon } 17648ec83bcSWill Deacon 177587e6c10SWill Deacon static u32 queue_inc_prod_n(struct arm_smmu_ll_queue *q, int n) 17848ec83bcSWill Deacon { 179587e6c10SWill Deacon u32 prod = (Q_WRP(q, q->prod) | Q_IDX(q, q->prod)) + n; 180587e6c10SWill Deacon return Q_OVF(q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod); 18148ec83bcSWill Deacon } 18248ec83bcSWill Deacon 183587e6c10SWill Deacon static void queue_poll_init(struct arm_smmu_device *smmu, 184587e6c10SWill Deacon struct arm_smmu_queue_poll *qp) 18548ec83bcSWill Deacon { 186587e6c10SWill Deacon qp->delay = 1; 187587e6c10SWill Deacon qp->spin_cnt = 0; 188587e6c10SWill Deacon qp->wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV); 189587e6c10SWill Deacon qp->timeout = ktime_add_us(ktime_get(), ARM_SMMU_POLL_TIMEOUT_US); 19048ec83bcSWill Deacon } 191b847de4eSSunil Goutham 192587e6c10SWill Deacon static int queue_poll(struct arm_smmu_queue_poll *qp) 19348ec83bcSWill Deacon { 194587e6c10SWill Deacon if (ktime_compare(ktime_get(), qp->timeout) > 0) 19548ec83bcSWill Deacon return -ETIMEDOUT; 19648ec83bcSWill Deacon 197587e6c10SWill Deacon if (qp->wfe) { 19848ec83bcSWill Deacon wfe(); 199587e6c10SWill Deacon } else if (++qp->spin_cnt < ARM_SMMU_POLL_SPIN_COUNT) { 20048ec83bcSWill Deacon cpu_relax(); 2018ff0f723SRobin Murphy } else { 202587e6c10SWill Deacon udelay(qp->delay); 203587e6c10SWill Deacon qp->delay *= 2; 204587e6c10SWill Deacon qp->spin_cnt = 0; 20548ec83bcSWill Deacon } 20648ec83bcSWill Deacon 20748ec83bcSWill Deacon return 0; 20848ec83bcSWill Deacon } 20948ec83bcSWill Deacon 21048ec83bcSWill Deacon static void queue_write(__le64 *dst, u64 *src, size_t n_dwords) 21148ec83bcSWill Deacon { 21248ec83bcSWill Deacon int i; 21348ec83bcSWill Deacon 21448ec83bcSWill Deacon for (i = 0; i < n_dwords; ++i) 21548ec83bcSWill Deacon *dst++ = cpu_to_le64(*src++); 21648ec83bcSWill Deacon } 21748ec83bcSWill Deacon 218376cdf66SJean-Philippe Brucker static void queue_read(u64 *dst, __le64 *src, size_t n_dwords) 21948ec83bcSWill Deacon { 22048ec83bcSWill Deacon int i; 22148ec83bcSWill Deacon 22248ec83bcSWill Deacon for (i = 0; i < n_dwords; ++i) 22348ec83bcSWill Deacon *dst++ = le64_to_cpu(*src++); 22448ec83bcSWill Deacon } 22548ec83bcSWill Deacon 22648ec83bcSWill Deacon static int queue_remove_raw(struct arm_smmu_queue *q, u64 *ent) 22748ec83bcSWill Deacon { 2287c288a5bSWill Deacon if (queue_empty(&q->llq)) 22948ec83bcSWill Deacon return -EAGAIN; 23048ec83bcSWill Deacon 23152be8637SWill Deacon queue_read(ent, Q_ENT(q, q->llq.cons), q->ent_dwords); 2327c288a5bSWill Deacon queue_inc_cons(&q->llq); 2332a8868f1SWill Deacon queue_sync_cons_out(q); 23448ec83bcSWill Deacon return 0; 23548ec83bcSWill Deacon } 23648ec83bcSWill Deacon 23748ec83bcSWill Deacon /* High-level queue accessors */ 23848ec83bcSWill Deacon static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent) 23948ec83bcSWill Deacon { 240d25f6eadSWill Deacon memset(cmd, 0, 1 << CMDQ_ENT_SZ_SHIFT); 2417417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_0_OP, ent->opcode); 24248ec83bcSWill Deacon 24348ec83bcSWill Deacon switch (ent->opcode) { 24448ec83bcSWill Deacon case CMDQ_OP_TLBI_EL2_ALL: 24548ec83bcSWill Deacon case CMDQ_OP_TLBI_NSNH_ALL: 24648ec83bcSWill Deacon break; 24748ec83bcSWill Deacon case CMDQ_OP_PREFETCH_CFG: 2487417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_PREFETCH_0_SID, ent->prefetch.sid); 24948ec83bcSWill Deacon break; 25087f42391SJean-Philippe Brucker case CMDQ_OP_CFGI_CD: 25187f42391SJean-Philippe Brucker cmd[0] |= FIELD_PREP(CMDQ_CFGI_0_SSID, ent->cfgi.ssid); 252df561f66SGustavo A. R. Silva fallthrough; 25348ec83bcSWill Deacon case CMDQ_OP_CFGI_STE: 2547417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_CFGI_0_SID, ent->cfgi.sid); 2557417b99cSRobin Murphy cmd[1] |= FIELD_PREP(CMDQ_CFGI_1_LEAF, ent->cfgi.leaf); 25648ec83bcSWill Deacon break; 25787f42391SJean-Philippe Brucker case CMDQ_OP_CFGI_CD_ALL: 25887f42391SJean-Philippe Brucker cmd[0] |= FIELD_PREP(CMDQ_CFGI_0_SID, ent->cfgi.sid); 25987f42391SJean-Philippe Brucker break; 26048ec83bcSWill Deacon case CMDQ_OP_CFGI_ALL: 26148ec83bcSWill Deacon /* Cover the entire SID range */ 2627417b99cSRobin Murphy cmd[1] |= FIELD_PREP(CMDQ_CFGI_1_RANGE, 31); 26348ec83bcSWill Deacon break; 26448ec83bcSWill Deacon case CMDQ_OP_TLBI_NH_VA: 2659111aebfSJean-Philippe Brucker cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid); 2669111aebfSJean-Philippe Brucker fallthrough; 2679111aebfSJean-Philippe Brucker case CMDQ_OP_TLBI_EL2_VA: 2686a481a95SRob Herring cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_NUM, ent->tlbi.num); 2696a481a95SRob Herring cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_SCALE, ent->tlbi.scale); 2707417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid); 2717417b99cSRobin Murphy cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_LEAF, ent->tlbi.leaf); 2726a481a95SRob Herring cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_TTL, ent->tlbi.ttl); 2736a481a95SRob Herring cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_TG, ent->tlbi.tg); 2741c27df1cSWill Deacon cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_VA_MASK; 2751c27df1cSWill Deacon break; 27648ec83bcSWill Deacon case CMDQ_OP_TLBI_S2_IPA: 2776a481a95SRob Herring cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_NUM, ent->tlbi.num); 2786a481a95SRob Herring cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_SCALE, ent->tlbi.scale); 2797417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid); 2807417b99cSRobin Murphy cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_LEAF, ent->tlbi.leaf); 2816a481a95SRob Herring cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_TTL, ent->tlbi.ttl); 2826a481a95SRob Herring cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_TG, ent->tlbi.tg); 2831c27df1cSWill Deacon cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_IPA_MASK; 28448ec83bcSWill Deacon break; 28548ec83bcSWill Deacon case CMDQ_OP_TLBI_NH_ASID: 2867417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid); 287df561f66SGustavo A. R. Silva fallthrough; 28848ec83bcSWill Deacon case CMDQ_OP_TLBI_S12_VMALL: 2897417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid); 29048ec83bcSWill Deacon break; 2919111aebfSJean-Philippe Brucker case CMDQ_OP_TLBI_EL2_ASID: 2929111aebfSJean-Philippe Brucker cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid); 2939111aebfSJean-Philippe Brucker break; 2949ce27afcSJean-Philippe Brucker case CMDQ_OP_ATC_INV: 2959ce27afcSJean-Philippe Brucker cmd[0] |= FIELD_PREP(CMDQ_0_SSV, ent->substream_valid); 2969ce27afcSJean-Philippe Brucker cmd[0] |= FIELD_PREP(CMDQ_ATC_0_GLOBAL, ent->atc.global); 2979ce27afcSJean-Philippe Brucker cmd[0] |= FIELD_PREP(CMDQ_ATC_0_SSID, ent->atc.ssid); 2989ce27afcSJean-Philippe Brucker cmd[0] |= FIELD_PREP(CMDQ_ATC_0_SID, ent->atc.sid); 2999ce27afcSJean-Philippe Brucker cmd[1] |= FIELD_PREP(CMDQ_ATC_1_SIZE, ent->atc.size); 3009ce27afcSJean-Philippe Brucker cmd[1] |= ent->atc.addr & CMDQ_ATC_1_ADDR_MASK; 3019ce27afcSJean-Philippe Brucker break; 30248ec83bcSWill Deacon case CMDQ_OP_PRI_RESP: 3037417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_0_SSV, ent->substream_valid); 3047417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_PRI_0_SSID, ent->pri.ssid); 3057417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_PRI_0_SID, ent->pri.sid); 3067417b99cSRobin Murphy cmd[1] |= FIELD_PREP(CMDQ_PRI_1_GRPID, ent->pri.grpid); 30748ec83bcSWill Deacon switch (ent->pri.resp) { 30848ec83bcSWill Deacon case PRI_RESP_DENY: 30948ec83bcSWill Deacon case PRI_RESP_FAIL: 31048ec83bcSWill Deacon case PRI_RESP_SUCC: 31148ec83bcSWill Deacon break; 31248ec83bcSWill Deacon default: 31348ec83bcSWill Deacon return -EINVAL; 31448ec83bcSWill Deacon } 3157417b99cSRobin Murphy cmd[1] |= FIELD_PREP(CMDQ_PRI_1_RESP, ent->pri.resp); 31648ec83bcSWill Deacon break; 317395ad89dSJean-Philippe Brucker case CMDQ_OP_RESUME: 318395ad89dSJean-Philippe Brucker cmd[0] |= FIELD_PREP(CMDQ_RESUME_0_SID, ent->resume.sid); 319395ad89dSJean-Philippe Brucker cmd[0] |= FIELD_PREP(CMDQ_RESUME_0_RESP, ent->resume.resp); 320395ad89dSJean-Philippe Brucker cmd[1] |= FIELD_PREP(CMDQ_RESUME_1_STAG, ent->resume.stag); 321395ad89dSJean-Philippe Brucker break; 32248ec83bcSWill Deacon case CMDQ_OP_CMD_SYNC: 323587e6c10SWill Deacon if (ent->sync.msiaddr) { 3247417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_IRQ); 325587e6c10SWill Deacon cmd[1] |= ent->sync.msiaddr & CMDQ_SYNC_1_MSIADDR_MASK; 326587e6c10SWill Deacon } else { 3277417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_SEV); 328587e6c10SWill Deacon } 3297417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSH, ARM_SMMU_SH_ISH); 3307417b99cSRobin Murphy cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIATTR, ARM_SMMU_MEMATTR_OIWB); 33148ec83bcSWill Deacon break; 33248ec83bcSWill Deacon default: 33348ec83bcSWill Deacon return -ENOENT; 33448ec83bcSWill Deacon } 33548ec83bcSWill Deacon 33648ec83bcSWill Deacon return 0; 33748ec83bcSWill Deacon } 33848ec83bcSWill Deacon 339587e6c10SWill Deacon static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct arm_smmu_device *smmu, 340587e6c10SWill Deacon u32 prod) 341587e6c10SWill Deacon { 342587e6c10SWill Deacon struct arm_smmu_queue *q = &smmu->cmdq.q; 343587e6c10SWill Deacon struct arm_smmu_cmdq_ent ent = { 344587e6c10SWill Deacon .opcode = CMDQ_OP_CMD_SYNC, 345587e6c10SWill Deacon }; 346587e6c10SWill Deacon 347587e6c10SWill Deacon /* 348587e6c10SWill Deacon * Beware that Hi16xx adds an extra 32 bits of goodness to its MSI 349587e6c10SWill Deacon * payload, so the write will zero the entire command on that platform. 350587e6c10SWill Deacon */ 351bd07a20aSBarry Song if (smmu->options & ARM_SMMU_OPT_MSIPOLL) { 352587e6c10SWill Deacon ent.sync.msiaddr = q->base_dma + Q_IDX(&q->llq, prod) * 353587e6c10SWill Deacon q->ent_dwords * 8; 354587e6c10SWill Deacon } 355587e6c10SWill Deacon 356587e6c10SWill Deacon arm_smmu_cmdq_build_cmd(cmd, &ent); 357587e6c10SWill Deacon } 358587e6c10SWill Deacon 35948ec83bcSWill Deacon static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu) 36048ec83bcSWill Deacon { 361d56d5162SBixuan Cui static const char * const cerror_str[] = { 36248ec83bcSWill Deacon [CMDQ_ERR_CERROR_NONE_IDX] = "No error", 36348ec83bcSWill Deacon [CMDQ_ERR_CERROR_ILL_IDX] = "Illegal command", 36448ec83bcSWill Deacon [CMDQ_ERR_CERROR_ABT_IDX] = "Abort on command fetch", 3659ce27afcSJean-Philippe Brucker [CMDQ_ERR_CERROR_ATC_INV_IDX] = "ATC invalidate timeout", 36648ec83bcSWill Deacon }; 36748ec83bcSWill Deacon 36848ec83bcSWill Deacon int i; 36948ec83bcSWill Deacon u64 cmd[CMDQ_ENT_DWORDS]; 37048ec83bcSWill Deacon struct arm_smmu_queue *q = &smmu->cmdq.q; 37148ec83bcSWill Deacon u32 cons = readl_relaxed(q->cons_reg); 372cbcee19aSRobin Murphy u32 idx = FIELD_GET(CMDQ_CONS_ERR, cons); 37348ec83bcSWill Deacon struct arm_smmu_cmdq_ent cmd_sync = { 37448ec83bcSWill Deacon .opcode = CMDQ_OP_CMD_SYNC, 37548ec83bcSWill Deacon }; 37648ec83bcSWill Deacon 37748ec83bcSWill Deacon dev_err(smmu->dev, "CMDQ error (cons 0x%08x): %s\n", cons, 378a0d5c04cSWill Deacon idx < ARRAY_SIZE(cerror_str) ? cerror_str[idx] : "Unknown"); 37948ec83bcSWill Deacon 38048ec83bcSWill Deacon switch (idx) { 38148ec83bcSWill Deacon case CMDQ_ERR_CERROR_ABT_IDX: 38248ec83bcSWill Deacon dev_err(smmu->dev, "retrying command fetch\n"); 38348ec83bcSWill Deacon case CMDQ_ERR_CERROR_NONE_IDX: 38448ec83bcSWill Deacon return; 3859ce27afcSJean-Philippe Brucker case CMDQ_ERR_CERROR_ATC_INV_IDX: 3869ce27afcSJean-Philippe Brucker /* 3879ce27afcSJean-Philippe Brucker * ATC Invalidation Completion timeout. CONS is still pointing 3889ce27afcSJean-Philippe Brucker * at the CMD_SYNC. Attempt to complete other pending commands 3899ce27afcSJean-Philippe Brucker * by repeating the CMD_SYNC, though we might well end up back 3909ce27afcSJean-Philippe Brucker * here since the ATC invalidation may still be pending. 3919ce27afcSJean-Philippe Brucker */ 3929ce27afcSJean-Philippe Brucker return; 393a0d5c04cSWill Deacon case CMDQ_ERR_CERROR_ILL_IDX: 394a0d5c04cSWill Deacon default: 395a0d5c04cSWill Deacon break; 39648ec83bcSWill Deacon } 39748ec83bcSWill Deacon 39848ec83bcSWill Deacon /* 39948ec83bcSWill Deacon * We may have concurrent producers, so we need to be careful 40048ec83bcSWill Deacon * not to touch any of the shadow cmdq state. 40148ec83bcSWill Deacon */ 402aea2037eSWill Deacon queue_read(cmd, Q_ENT(q, cons), q->ent_dwords); 40348ec83bcSWill Deacon dev_err(smmu->dev, "skipping command in error state:\n"); 40448ec83bcSWill Deacon for (i = 0; i < ARRAY_SIZE(cmd); ++i) 40548ec83bcSWill Deacon dev_err(smmu->dev, "\t0x%016llx\n", (unsigned long long)cmd[i]); 40648ec83bcSWill Deacon 40748ec83bcSWill Deacon /* Convert the erroneous command into a CMD_SYNC */ 40848ec83bcSWill Deacon if (arm_smmu_cmdq_build_cmd(cmd, &cmd_sync)) { 40948ec83bcSWill Deacon dev_err(smmu->dev, "failed to convert to CMD_SYNC\n"); 41048ec83bcSWill Deacon return; 41148ec83bcSWill Deacon } 41248ec83bcSWill Deacon 413aea2037eSWill Deacon queue_write(Q_ENT(q, cons), cmd, q->ent_dwords); 41448ec83bcSWill Deacon } 41548ec83bcSWill Deacon 416587e6c10SWill Deacon /* 417587e6c10SWill Deacon * Command queue locking. 418587e6c10SWill Deacon * This is a form of bastardised rwlock with the following major changes: 419587e6c10SWill Deacon * 420587e6c10SWill Deacon * - The only LOCK routines are exclusive_trylock() and shared_lock(). 421587e6c10SWill Deacon * Neither have barrier semantics, and instead provide only a control 422587e6c10SWill Deacon * dependency. 423587e6c10SWill Deacon * 424587e6c10SWill Deacon * - The UNLOCK routines are supplemented with shared_tryunlock(), which 425587e6c10SWill Deacon * fails if the caller appears to be the last lock holder (yes, this is 426587e6c10SWill Deacon * racy). All successful UNLOCK routines have RELEASE semantics. 427587e6c10SWill Deacon */ 428587e6c10SWill Deacon static void arm_smmu_cmdq_shared_lock(struct arm_smmu_cmdq *cmdq) 4292f657addSRobin Murphy { 430587e6c10SWill Deacon int val; 4312f657addSRobin Murphy 432587e6c10SWill Deacon /* 433587e6c10SWill Deacon * We can try to avoid the cmpxchg() loop by simply incrementing the 434587e6c10SWill Deacon * lock counter. When held in exclusive state, the lock counter is set 435587e6c10SWill Deacon * to INT_MIN so these increments won't hurt as the value will remain 436587e6c10SWill Deacon * negative. 437587e6c10SWill Deacon */ 438587e6c10SWill Deacon if (atomic_fetch_inc_relaxed(&cmdq->lock) >= 0) 439587e6c10SWill Deacon return; 440901510eeSZhen Lei 441587e6c10SWill Deacon do { 442587e6c10SWill Deacon val = atomic_cond_read_relaxed(&cmdq->lock, VAL >= 0); 443587e6c10SWill Deacon } while (atomic_cmpxchg_relaxed(&cmdq->lock, val, val + 1) != val); 444587e6c10SWill Deacon } 445587e6c10SWill Deacon 446587e6c10SWill Deacon static void arm_smmu_cmdq_shared_unlock(struct arm_smmu_cmdq *cmdq) 447587e6c10SWill Deacon { 448587e6c10SWill Deacon (void)atomic_dec_return_release(&cmdq->lock); 449587e6c10SWill Deacon } 450587e6c10SWill Deacon 451587e6c10SWill Deacon static bool arm_smmu_cmdq_shared_tryunlock(struct arm_smmu_cmdq *cmdq) 452587e6c10SWill Deacon { 453587e6c10SWill Deacon if (atomic_read(&cmdq->lock) == 1) 454587e6c10SWill Deacon return false; 455587e6c10SWill Deacon 456587e6c10SWill Deacon arm_smmu_cmdq_shared_unlock(cmdq); 457587e6c10SWill Deacon return true; 458587e6c10SWill Deacon } 459587e6c10SWill Deacon 460587e6c10SWill Deacon #define arm_smmu_cmdq_exclusive_trylock_irqsave(cmdq, flags) \ 461587e6c10SWill Deacon ({ \ 462587e6c10SWill Deacon bool __ret; \ 463587e6c10SWill Deacon local_irq_save(flags); \ 464587e6c10SWill Deacon __ret = !atomic_cmpxchg_relaxed(&cmdq->lock, 0, INT_MIN); \ 465587e6c10SWill Deacon if (!__ret) \ 466587e6c10SWill Deacon local_irq_restore(flags); \ 467587e6c10SWill Deacon __ret; \ 468587e6c10SWill Deacon }) 469587e6c10SWill Deacon 470587e6c10SWill Deacon #define arm_smmu_cmdq_exclusive_unlock_irqrestore(cmdq, flags) \ 471587e6c10SWill Deacon ({ \ 472587e6c10SWill Deacon atomic_set_release(&cmdq->lock, 0); \ 473587e6c10SWill Deacon local_irq_restore(flags); \ 474587e6c10SWill Deacon }) 475587e6c10SWill Deacon 476587e6c10SWill Deacon 477587e6c10SWill Deacon /* 478587e6c10SWill Deacon * Command queue insertion. 479587e6c10SWill Deacon * This is made fiddly by our attempts to achieve some sort of scalability 480587e6c10SWill Deacon * since there is one queue shared amongst all of the CPUs in the system. If 481587e6c10SWill Deacon * you like mixed-size concurrency, dependency ordering and relaxed atomics, 482587e6c10SWill Deacon * then you'll *love* this monstrosity. 483587e6c10SWill Deacon * 484587e6c10SWill Deacon * The basic idea is to split the queue up into ranges of commands that are 485587e6c10SWill Deacon * owned by a given CPU; the owner may not have written all of the commands 486587e6c10SWill Deacon * itself, but is responsible for advancing the hardware prod pointer when 487587e6c10SWill Deacon * the time comes. The algorithm is roughly: 488587e6c10SWill Deacon * 489587e6c10SWill Deacon * 1. Allocate some space in the queue. At this point we also discover 490587e6c10SWill Deacon * whether the head of the queue is currently owned by another CPU, 491587e6c10SWill Deacon * or whether we are the owner. 492587e6c10SWill Deacon * 493587e6c10SWill Deacon * 2. Write our commands into our allocated slots in the queue. 494587e6c10SWill Deacon * 495587e6c10SWill Deacon * 3. Mark our slots as valid in arm_smmu_cmdq.valid_map. 496587e6c10SWill Deacon * 497587e6c10SWill Deacon * 4. If we are an owner: 498587e6c10SWill Deacon * a. Wait for the previous owner to finish. 499587e6c10SWill Deacon * b. Mark the queue head as unowned, which tells us the range 500587e6c10SWill Deacon * that we are responsible for publishing. 501587e6c10SWill Deacon * c. Wait for all commands in our owned range to become valid. 502587e6c10SWill Deacon * d. Advance the hardware prod pointer. 503587e6c10SWill Deacon * e. Tell the next owner we've finished. 504587e6c10SWill Deacon * 505587e6c10SWill Deacon * 5. If we are inserting a CMD_SYNC (we may or may not have been an 506587e6c10SWill Deacon * owner), then we need to stick around until it has completed: 507587e6c10SWill Deacon * a. If we have MSIs, the SMMU can write back into the CMD_SYNC 508587e6c10SWill Deacon * to clear the first 4 bytes. 509587e6c10SWill Deacon * b. Otherwise, we spin waiting for the hardware cons pointer to 510587e6c10SWill Deacon * advance past our command. 511587e6c10SWill Deacon * 512587e6c10SWill Deacon * The devil is in the details, particularly the use of locking for handling 513587e6c10SWill Deacon * SYNC completion and freeing up space in the queue before we think that it is 514587e6c10SWill Deacon * full. 515587e6c10SWill Deacon */ 516587e6c10SWill Deacon static void __arm_smmu_cmdq_poll_set_valid_map(struct arm_smmu_cmdq *cmdq, 517587e6c10SWill Deacon u32 sprod, u32 eprod, bool set) 518587e6c10SWill Deacon { 519587e6c10SWill Deacon u32 swidx, sbidx, ewidx, ebidx; 520587e6c10SWill Deacon struct arm_smmu_ll_queue llq = { 521587e6c10SWill Deacon .max_n_shift = cmdq->q.llq.max_n_shift, 522587e6c10SWill Deacon .prod = sprod, 523587e6c10SWill Deacon }; 524587e6c10SWill Deacon 525587e6c10SWill Deacon ewidx = BIT_WORD(Q_IDX(&llq, eprod)); 526587e6c10SWill Deacon ebidx = Q_IDX(&llq, eprod) % BITS_PER_LONG; 527587e6c10SWill Deacon 528587e6c10SWill Deacon while (llq.prod != eprod) { 529587e6c10SWill Deacon unsigned long mask; 530587e6c10SWill Deacon atomic_long_t *ptr; 531587e6c10SWill Deacon u32 limit = BITS_PER_LONG; 532587e6c10SWill Deacon 533587e6c10SWill Deacon swidx = BIT_WORD(Q_IDX(&llq, llq.prod)); 534587e6c10SWill Deacon sbidx = Q_IDX(&llq, llq.prod) % BITS_PER_LONG; 535587e6c10SWill Deacon 536587e6c10SWill Deacon ptr = &cmdq->valid_map[swidx]; 537587e6c10SWill Deacon 538587e6c10SWill Deacon if ((swidx == ewidx) && (sbidx < ebidx)) 539587e6c10SWill Deacon limit = ebidx; 540587e6c10SWill Deacon 541587e6c10SWill Deacon mask = GENMASK(limit - 1, sbidx); 542587e6c10SWill Deacon 543587e6c10SWill Deacon /* 544587e6c10SWill Deacon * The valid bit is the inverse of the wrap bit. This means 545587e6c10SWill Deacon * that a zero-initialised queue is invalid and, after marking 546587e6c10SWill Deacon * all entries as valid, they become invalid again when we 547587e6c10SWill Deacon * wrap. 548587e6c10SWill Deacon */ 549587e6c10SWill Deacon if (set) { 550587e6c10SWill Deacon atomic_long_xor(mask, ptr); 551587e6c10SWill Deacon } else { /* Poll */ 552587e6c10SWill Deacon unsigned long valid; 553587e6c10SWill Deacon 554587e6c10SWill Deacon valid = (ULONG_MAX + !!Q_WRP(&llq, llq.prod)) & mask; 555587e6c10SWill Deacon atomic_long_cond_read_relaxed(ptr, (VAL & mask) == valid); 556587e6c10SWill Deacon } 557587e6c10SWill Deacon 558587e6c10SWill Deacon llq.prod = queue_inc_prod_n(&llq, limit - sbidx); 559587e6c10SWill Deacon } 560587e6c10SWill Deacon } 561587e6c10SWill Deacon 562587e6c10SWill Deacon /* Mark all entries in the range [sprod, eprod) as valid */ 563587e6c10SWill Deacon static void arm_smmu_cmdq_set_valid_map(struct arm_smmu_cmdq *cmdq, 564587e6c10SWill Deacon u32 sprod, u32 eprod) 565587e6c10SWill Deacon { 566587e6c10SWill Deacon __arm_smmu_cmdq_poll_set_valid_map(cmdq, sprod, eprod, true); 567587e6c10SWill Deacon } 568587e6c10SWill Deacon 569587e6c10SWill Deacon /* Wait for all entries in the range [sprod, eprod) to become valid */ 570587e6c10SWill Deacon static void arm_smmu_cmdq_poll_valid_map(struct arm_smmu_cmdq *cmdq, 571587e6c10SWill Deacon u32 sprod, u32 eprod) 572587e6c10SWill Deacon { 573587e6c10SWill Deacon __arm_smmu_cmdq_poll_set_valid_map(cmdq, sprod, eprod, false); 574587e6c10SWill Deacon } 575587e6c10SWill Deacon 576587e6c10SWill Deacon /* Wait for the command queue to become non-full */ 577587e6c10SWill Deacon static int arm_smmu_cmdq_poll_until_not_full(struct arm_smmu_device *smmu, 578587e6c10SWill Deacon struct arm_smmu_ll_queue *llq) 579587e6c10SWill Deacon { 580587e6c10SWill Deacon unsigned long flags; 581587e6c10SWill Deacon struct arm_smmu_queue_poll qp; 582587e6c10SWill Deacon struct arm_smmu_cmdq *cmdq = &smmu->cmdq; 583587e6c10SWill Deacon int ret = 0; 584587e6c10SWill Deacon 585587e6c10SWill Deacon /* 586587e6c10SWill Deacon * Try to update our copy of cons by grabbing exclusive cmdq access. If 587587e6c10SWill Deacon * that fails, spin until somebody else updates it for us. 588587e6c10SWill Deacon */ 589587e6c10SWill Deacon if (arm_smmu_cmdq_exclusive_trylock_irqsave(cmdq, flags)) { 590587e6c10SWill Deacon WRITE_ONCE(cmdq->q.llq.cons, readl_relaxed(cmdq->q.cons_reg)); 591587e6c10SWill Deacon arm_smmu_cmdq_exclusive_unlock_irqrestore(cmdq, flags); 592587e6c10SWill Deacon llq->val = READ_ONCE(cmdq->q.llq.val); 593587e6c10SWill Deacon return 0; 594587e6c10SWill Deacon } 595587e6c10SWill Deacon 596587e6c10SWill Deacon queue_poll_init(smmu, &qp); 597587e6c10SWill Deacon do { 598587e6c10SWill Deacon llq->val = READ_ONCE(smmu->cmdq.q.llq.val); 599587e6c10SWill Deacon if (!queue_full(llq)) 600587e6c10SWill Deacon break; 601587e6c10SWill Deacon 602587e6c10SWill Deacon ret = queue_poll(&qp); 603587e6c10SWill Deacon } while (!ret); 604587e6c10SWill Deacon 605587e6c10SWill Deacon return ret; 606587e6c10SWill Deacon } 607587e6c10SWill Deacon 608587e6c10SWill Deacon /* 609587e6c10SWill Deacon * Wait until the SMMU signals a CMD_SYNC completion MSI. 610587e6c10SWill Deacon * Must be called with the cmdq lock held in some capacity. 611587e6c10SWill Deacon */ 612587e6c10SWill Deacon static int __arm_smmu_cmdq_poll_until_msi(struct arm_smmu_device *smmu, 613587e6c10SWill Deacon struct arm_smmu_ll_queue *llq) 614587e6c10SWill Deacon { 615587e6c10SWill Deacon int ret = 0; 616587e6c10SWill Deacon struct arm_smmu_queue_poll qp; 617587e6c10SWill Deacon struct arm_smmu_cmdq *cmdq = &smmu->cmdq; 618587e6c10SWill Deacon u32 *cmd = (u32 *)(Q_ENT(&cmdq->q, llq->prod)); 619587e6c10SWill Deacon 620587e6c10SWill Deacon queue_poll_init(smmu, &qp); 621587e6c10SWill Deacon 622587e6c10SWill Deacon /* 623587e6c10SWill Deacon * The MSI won't generate an event, since it's being written back 624587e6c10SWill Deacon * into the command queue. 625587e6c10SWill Deacon */ 626587e6c10SWill Deacon qp.wfe = false; 627587e6c10SWill Deacon smp_cond_load_relaxed(cmd, !VAL || (ret = queue_poll(&qp))); 628587e6c10SWill Deacon llq->cons = ret ? llq->prod : queue_inc_prod_n(llq, 1); 629587e6c10SWill Deacon return ret; 630587e6c10SWill Deacon } 631587e6c10SWill Deacon 632587e6c10SWill Deacon /* 633587e6c10SWill Deacon * Wait until the SMMU cons index passes llq->prod. 634587e6c10SWill Deacon * Must be called with the cmdq lock held in some capacity. 635587e6c10SWill Deacon */ 636587e6c10SWill Deacon static int __arm_smmu_cmdq_poll_until_consumed(struct arm_smmu_device *smmu, 637587e6c10SWill Deacon struct arm_smmu_ll_queue *llq) 638587e6c10SWill Deacon { 639587e6c10SWill Deacon struct arm_smmu_queue_poll qp; 640587e6c10SWill Deacon struct arm_smmu_cmdq *cmdq = &smmu->cmdq; 641587e6c10SWill Deacon u32 prod = llq->prod; 642587e6c10SWill Deacon int ret = 0; 643587e6c10SWill Deacon 644587e6c10SWill Deacon queue_poll_init(smmu, &qp); 645587e6c10SWill Deacon llq->val = READ_ONCE(smmu->cmdq.q.llq.val); 646587e6c10SWill Deacon do { 647587e6c10SWill Deacon if (queue_consumed(llq, prod)) 648587e6c10SWill Deacon break; 649587e6c10SWill Deacon 650587e6c10SWill Deacon ret = queue_poll(&qp); 651587e6c10SWill Deacon 652587e6c10SWill Deacon /* 653587e6c10SWill Deacon * This needs to be a readl() so that our subsequent call 654587e6c10SWill Deacon * to arm_smmu_cmdq_shared_tryunlock() can fail accurately. 655587e6c10SWill Deacon * 656587e6c10SWill Deacon * Specifically, we need to ensure that we observe all 657587e6c10SWill Deacon * shared_lock()s by other CMD_SYNCs that share our owner, 658587e6c10SWill Deacon * so that a failing call to tryunlock() means that we're 659587e6c10SWill Deacon * the last one out and therefore we can safely advance 660587e6c10SWill Deacon * cmdq->q.llq.cons. Roughly speaking: 661587e6c10SWill Deacon * 662587e6c10SWill Deacon * CPU 0 CPU1 CPU2 (us) 663587e6c10SWill Deacon * 664587e6c10SWill Deacon * if (sync) 665587e6c10SWill Deacon * shared_lock(); 666587e6c10SWill Deacon * 667587e6c10SWill Deacon * dma_wmb(); 668587e6c10SWill Deacon * set_valid_map(); 669587e6c10SWill Deacon * 670587e6c10SWill Deacon * if (owner) { 671587e6c10SWill Deacon * poll_valid_map(); 672587e6c10SWill Deacon * <control dependency> 673587e6c10SWill Deacon * writel(prod_reg); 674587e6c10SWill Deacon * 675587e6c10SWill Deacon * readl(cons_reg); 676587e6c10SWill Deacon * tryunlock(); 677587e6c10SWill Deacon * 678587e6c10SWill Deacon * Requires us to see CPU 0's shared_lock() acquisition. 679587e6c10SWill Deacon */ 680587e6c10SWill Deacon llq->cons = readl(cmdq->q.cons_reg); 681587e6c10SWill Deacon } while (!ret); 682587e6c10SWill Deacon 683587e6c10SWill Deacon return ret; 684587e6c10SWill Deacon } 685587e6c10SWill Deacon 686587e6c10SWill Deacon static int arm_smmu_cmdq_poll_until_sync(struct arm_smmu_device *smmu, 687587e6c10SWill Deacon struct arm_smmu_ll_queue *llq) 688587e6c10SWill Deacon { 689bd07a20aSBarry Song if (smmu->options & ARM_SMMU_OPT_MSIPOLL) 690587e6c10SWill Deacon return __arm_smmu_cmdq_poll_until_msi(smmu, llq); 691587e6c10SWill Deacon 692587e6c10SWill Deacon return __arm_smmu_cmdq_poll_until_consumed(smmu, llq); 693587e6c10SWill Deacon } 694587e6c10SWill Deacon 695587e6c10SWill Deacon static void arm_smmu_cmdq_write_entries(struct arm_smmu_cmdq *cmdq, u64 *cmds, 696587e6c10SWill Deacon u32 prod, int n) 697587e6c10SWill Deacon { 698587e6c10SWill Deacon int i; 699587e6c10SWill Deacon struct arm_smmu_ll_queue llq = { 700587e6c10SWill Deacon .max_n_shift = cmdq->q.llq.max_n_shift, 701587e6c10SWill Deacon .prod = prod, 702587e6c10SWill Deacon }; 703587e6c10SWill Deacon 704587e6c10SWill Deacon for (i = 0; i < n; ++i) { 705587e6c10SWill Deacon u64 *cmd = &cmds[i * CMDQ_ENT_DWORDS]; 706587e6c10SWill Deacon 707587e6c10SWill Deacon prod = queue_inc_prod_n(&llq, i); 708587e6c10SWill Deacon queue_write(Q_ENT(&cmdq->q, prod), cmd, CMDQ_ENT_DWORDS); 709587e6c10SWill Deacon } 710587e6c10SWill Deacon } 711587e6c10SWill Deacon 71205cbaf4dSWill Deacon /* 71305cbaf4dSWill Deacon * This is the actual insertion function, and provides the following 71405cbaf4dSWill Deacon * ordering guarantees to callers: 71505cbaf4dSWill Deacon * 71605cbaf4dSWill Deacon * - There is a dma_wmb() before publishing any commands to the queue. 71705cbaf4dSWill Deacon * This can be relied upon to order prior writes to data structures 71805cbaf4dSWill Deacon * in memory (such as a CD or an STE) before the command. 71905cbaf4dSWill Deacon * 72005cbaf4dSWill Deacon * - On completion of a CMD_SYNC, there is a control dependency. 72105cbaf4dSWill Deacon * This can be relied upon to order subsequent writes to memory (e.g. 72205cbaf4dSWill Deacon * freeing an IOVA) after completion of the CMD_SYNC. 72305cbaf4dSWill Deacon * 72405cbaf4dSWill Deacon * - Command insertion is totally ordered, so if two CPUs each race to 72505cbaf4dSWill Deacon * insert their own list of commands then all of the commands from one 72605cbaf4dSWill Deacon * CPU will appear before any of the commands from the other CPU. 72705cbaf4dSWill Deacon */ 728587e6c10SWill Deacon static int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu, 729587e6c10SWill Deacon u64 *cmds, int n, bool sync) 730587e6c10SWill Deacon { 731587e6c10SWill Deacon u64 cmd_sync[CMDQ_ENT_DWORDS]; 732587e6c10SWill Deacon u32 prod; 733587e6c10SWill Deacon unsigned long flags; 734587e6c10SWill Deacon bool owner; 735587e6c10SWill Deacon struct arm_smmu_cmdq *cmdq = &smmu->cmdq; 736587e6c10SWill Deacon struct arm_smmu_ll_queue llq = { 737587e6c10SWill Deacon .max_n_shift = cmdq->q.llq.max_n_shift, 738587e6c10SWill Deacon }, head = llq; 739587e6c10SWill Deacon int ret = 0; 740587e6c10SWill Deacon 741587e6c10SWill Deacon /* 1. Allocate some space in the queue */ 742587e6c10SWill Deacon local_irq_save(flags); 743587e6c10SWill Deacon llq.val = READ_ONCE(cmdq->q.llq.val); 744587e6c10SWill Deacon do { 745587e6c10SWill Deacon u64 old; 746587e6c10SWill Deacon 747587e6c10SWill Deacon while (!queue_has_space(&llq, n + sync)) { 748587e6c10SWill Deacon local_irq_restore(flags); 749587e6c10SWill Deacon if (arm_smmu_cmdq_poll_until_not_full(smmu, &llq)) 7502f657addSRobin Murphy dev_err_ratelimited(smmu->dev, "CMDQ timeout\n"); 751587e6c10SWill Deacon local_irq_save(flags); 752587e6c10SWill Deacon } 753587e6c10SWill Deacon 754587e6c10SWill Deacon head.cons = llq.cons; 755587e6c10SWill Deacon head.prod = queue_inc_prod_n(&llq, n + sync) | 756587e6c10SWill Deacon CMDQ_PROD_OWNED_FLAG; 757587e6c10SWill Deacon 758587e6c10SWill Deacon old = cmpxchg_relaxed(&cmdq->q.llq.val, llq.val, head.val); 759587e6c10SWill Deacon if (old == llq.val) 760587e6c10SWill Deacon break; 761587e6c10SWill Deacon 762587e6c10SWill Deacon llq.val = old; 763587e6c10SWill Deacon } while (1); 764587e6c10SWill Deacon owner = !(llq.prod & CMDQ_PROD_OWNED_FLAG); 765587e6c10SWill Deacon head.prod &= ~CMDQ_PROD_OWNED_FLAG; 766587e6c10SWill Deacon llq.prod &= ~CMDQ_PROD_OWNED_FLAG; 767587e6c10SWill Deacon 768587e6c10SWill Deacon /* 769587e6c10SWill Deacon * 2. Write our commands into the queue 770587e6c10SWill Deacon * Dependency ordering from the cmpxchg() loop above. 771587e6c10SWill Deacon */ 772587e6c10SWill Deacon arm_smmu_cmdq_write_entries(cmdq, cmds, llq.prod, n); 773587e6c10SWill Deacon if (sync) { 774587e6c10SWill Deacon prod = queue_inc_prod_n(&llq, n); 775587e6c10SWill Deacon arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, prod); 776587e6c10SWill Deacon queue_write(Q_ENT(&cmdq->q, prod), cmd_sync, CMDQ_ENT_DWORDS); 777587e6c10SWill Deacon 778587e6c10SWill Deacon /* 779587e6c10SWill Deacon * In order to determine completion of our CMD_SYNC, we must 780587e6c10SWill Deacon * ensure that the queue can't wrap twice without us noticing. 781587e6c10SWill Deacon * We achieve that by taking the cmdq lock as shared before 782587e6c10SWill Deacon * marking our slot as valid. 783587e6c10SWill Deacon */ 784587e6c10SWill Deacon arm_smmu_cmdq_shared_lock(cmdq); 785587e6c10SWill Deacon } 786587e6c10SWill Deacon 787587e6c10SWill Deacon /* 3. Mark our slots as valid, ensuring commands are visible first */ 788587e6c10SWill Deacon dma_wmb(); 789587e6c10SWill Deacon arm_smmu_cmdq_set_valid_map(cmdq, llq.prod, head.prod); 790587e6c10SWill Deacon 791587e6c10SWill Deacon /* 4. If we are the owner, take control of the SMMU hardware */ 792587e6c10SWill Deacon if (owner) { 793587e6c10SWill Deacon /* a. Wait for previous owner to finish */ 794587e6c10SWill Deacon atomic_cond_read_relaxed(&cmdq->owner_prod, VAL == llq.prod); 795587e6c10SWill Deacon 796587e6c10SWill Deacon /* b. Stop gathering work by clearing the owned flag */ 797587e6c10SWill Deacon prod = atomic_fetch_andnot_relaxed(CMDQ_PROD_OWNED_FLAG, 798587e6c10SWill Deacon &cmdq->q.llq.atomic.prod); 799587e6c10SWill Deacon prod &= ~CMDQ_PROD_OWNED_FLAG; 800587e6c10SWill Deacon 801587e6c10SWill Deacon /* 802587e6c10SWill Deacon * c. Wait for any gathered work to be written to the queue. 803587e6c10SWill Deacon * Note that we read our own entries so that we have the control 804587e6c10SWill Deacon * dependency required by (d). 805587e6c10SWill Deacon */ 806587e6c10SWill Deacon arm_smmu_cmdq_poll_valid_map(cmdq, llq.prod, prod); 807587e6c10SWill Deacon 808587e6c10SWill Deacon /* 809587e6c10SWill Deacon * d. Advance the hardware prod pointer 810587e6c10SWill Deacon * Control dependency ordering from the entries becoming valid. 811587e6c10SWill Deacon */ 812587e6c10SWill Deacon writel_relaxed(prod, cmdq->q.prod_reg); 813587e6c10SWill Deacon 814587e6c10SWill Deacon /* 815587e6c10SWill Deacon * e. Tell the next owner we're done 816587e6c10SWill Deacon * Make sure we've updated the hardware first, so that we don't 817587e6c10SWill Deacon * race to update prod and potentially move it backwards. 818587e6c10SWill Deacon */ 819587e6c10SWill Deacon atomic_set_release(&cmdq->owner_prod, prod); 820587e6c10SWill Deacon } 821587e6c10SWill Deacon 822587e6c10SWill Deacon /* 5. If we are inserting a CMD_SYNC, we must wait for it to complete */ 823587e6c10SWill Deacon if (sync) { 824587e6c10SWill Deacon llq.prod = queue_inc_prod_n(&llq, n); 825587e6c10SWill Deacon ret = arm_smmu_cmdq_poll_until_sync(smmu, &llq); 826587e6c10SWill Deacon if (ret) { 827587e6c10SWill Deacon dev_err_ratelimited(smmu->dev, 828587e6c10SWill Deacon "CMD_SYNC timeout at 0x%08x [hwprod 0x%08x, hwcons 0x%08x]\n", 829587e6c10SWill Deacon llq.prod, 830587e6c10SWill Deacon readl_relaxed(cmdq->q.prod_reg), 831587e6c10SWill Deacon readl_relaxed(cmdq->q.cons_reg)); 832587e6c10SWill Deacon } 833587e6c10SWill Deacon 834587e6c10SWill Deacon /* 83549fbb250SJohn Garry * Try to unlock the cmdq lock. This will fail if we're the last 836587e6c10SWill Deacon * reader, in which case we can safely update cmdq->q.llq.cons 837587e6c10SWill Deacon */ 838587e6c10SWill Deacon if (!arm_smmu_cmdq_shared_tryunlock(cmdq)) { 839587e6c10SWill Deacon WRITE_ONCE(cmdq->q.llq.cons, llq.cons); 840587e6c10SWill Deacon arm_smmu_cmdq_shared_unlock(cmdq); 8412f657addSRobin Murphy } 8422f657addSRobin Murphy } 8432f657addSRobin Murphy 844587e6c10SWill Deacon local_irq_restore(flags); 845587e6c10SWill Deacon return ret; 846587e6c10SWill Deacon } 847587e6c10SWill Deacon 848587e6c10SWill Deacon static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu, 84948ec83bcSWill Deacon struct arm_smmu_cmdq_ent *ent) 85048ec83bcSWill Deacon { 85148ec83bcSWill Deacon u64 cmd[CMDQ_ENT_DWORDS]; 85248ec83bcSWill Deacon 85348ec83bcSWill Deacon if (arm_smmu_cmdq_build_cmd(cmd, ent)) { 85448ec83bcSWill Deacon dev_warn(smmu->dev, "ignoring unknown CMDQ opcode 0x%x\n", 85548ec83bcSWill Deacon ent->opcode); 856587e6c10SWill Deacon return -EINVAL; 85748ec83bcSWill Deacon } 85848ec83bcSWill Deacon 859587e6c10SWill Deacon return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, false); 86049806599SWill Deacon } 86149806599SWill Deacon 8629ce27afcSJean-Philippe Brucker static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu) 86349806599SWill Deacon { 864587e6c10SWill Deacon return arm_smmu_cmdq_issue_cmdlist(smmu, NULL, 0, true); 86548ec83bcSWill Deacon } 86648ec83bcSWill Deacon 8674ce8da45SJean-Philippe Brucker static void arm_smmu_cmdq_batch_add(struct arm_smmu_device *smmu, 8684ce8da45SJean-Philippe Brucker struct arm_smmu_cmdq_batch *cmds, 8694ce8da45SJean-Philippe Brucker struct arm_smmu_cmdq_ent *cmd) 8704ce8da45SJean-Philippe Brucker { 8714ce8da45SJean-Philippe Brucker if (cmds->num == CMDQ_BATCH_ENTRIES) { 8724ce8da45SJean-Philippe Brucker arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, false); 8734ce8da45SJean-Philippe Brucker cmds->num = 0; 8744ce8da45SJean-Philippe Brucker } 8754ce8da45SJean-Philippe Brucker arm_smmu_cmdq_build_cmd(&cmds->cmds[cmds->num * CMDQ_ENT_DWORDS], cmd); 8764ce8da45SJean-Philippe Brucker cmds->num++; 8774ce8da45SJean-Philippe Brucker } 8784ce8da45SJean-Philippe Brucker 8794ce8da45SJean-Philippe Brucker static int arm_smmu_cmdq_batch_submit(struct arm_smmu_device *smmu, 8804ce8da45SJean-Philippe Brucker struct arm_smmu_cmdq_batch *cmds) 8814ce8da45SJean-Philippe Brucker { 8824ce8da45SJean-Philippe Brucker return arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, true); 8834ce8da45SJean-Philippe Brucker } 8844ce8da45SJean-Philippe Brucker 885395ad89dSJean-Philippe Brucker static int arm_smmu_page_response(struct device *dev, 886395ad89dSJean-Philippe Brucker struct iommu_fault_event *unused, 887395ad89dSJean-Philippe Brucker struct iommu_page_response *resp) 888395ad89dSJean-Philippe Brucker { 889395ad89dSJean-Philippe Brucker struct arm_smmu_cmdq_ent cmd = {0}; 890395ad89dSJean-Philippe Brucker struct arm_smmu_master *master = dev_iommu_priv_get(dev); 891395ad89dSJean-Philippe Brucker int sid = master->streams[0].id; 892395ad89dSJean-Philippe Brucker 893395ad89dSJean-Philippe Brucker if (master->stall_enabled) { 894395ad89dSJean-Philippe Brucker cmd.opcode = CMDQ_OP_RESUME; 895395ad89dSJean-Philippe Brucker cmd.resume.sid = sid; 896395ad89dSJean-Philippe Brucker cmd.resume.stag = resp->grpid; 897395ad89dSJean-Philippe Brucker switch (resp->code) { 898395ad89dSJean-Philippe Brucker case IOMMU_PAGE_RESP_INVALID: 899395ad89dSJean-Philippe Brucker case IOMMU_PAGE_RESP_FAILURE: 900395ad89dSJean-Philippe Brucker cmd.resume.resp = CMDQ_RESUME_0_RESP_ABORT; 901395ad89dSJean-Philippe Brucker break; 902395ad89dSJean-Philippe Brucker case IOMMU_PAGE_RESP_SUCCESS: 903395ad89dSJean-Philippe Brucker cmd.resume.resp = CMDQ_RESUME_0_RESP_RETRY; 904395ad89dSJean-Philippe Brucker break; 905395ad89dSJean-Philippe Brucker default: 906395ad89dSJean-Philippe Brucker return -EINVAL; 907395ad89dSJean-Philippe Brucker } 908395ad89dSJean-Philippe Brucker } else { 909395ad89dSJean-Philippe Brucker return -ENODEV; 910395ad89dSJean-Philippe Brucker } 911395ad89dSJean-Philippe Brucker 912395ad89dSJean-Philippe Brucker arm_smmu_cmdq_issue_cmd(master->smmu, &cmd); 913395ad89dSJean-Philippe Brucker /* 914395ad89dSJean-Philippe Brucker * Don't send a SYNC, it doesn't do anything for RESUME or PRI_RESP. 915395ad89dSJean-Philippe Brucker * RESUME consumption guarantees that the stalled transaction will be 916395ad89dSJean-Philippe Brucker * terminated... at some point in the future. PRI_RESP is fire and 917395ad89dSJean-Philippe Brucker * forget. 918395ad89dSJean-Philippe Brucker */ 919395ad89dSJean-Philippe Brucker 920395ad89dSJean-Philippe Brucker return 0; 921395ad89dSJean-Philippe Brucker } 922395ad89dSJean-Philippe Brucker 92348ec83bcSWill Deacon /* Context descriptor manipulation functions */ 9243e630336SJean-Philippe Brucker void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid) 9253e630336SJean-Philippe Brucker { 9263e630336SJean-Philippe Brucker struct arm_smmu_cmdq_ent cmd = { 9279111aebfSJean-Philippe Brucker .opcode = smmu->features & ARM_SMMU_FEAT_E2H ? 9289111aebfSJean-Philippe Brucker CMDQ_OP_TLBI_EL2_ASID : CMDQ_OP_TLBI_NH_ASID, 9293e630336SJean-Philippe Brucker .tlbi.asid = asid, 9303e630336SJean-Philippe Brucker }; 9313e630336SJean-Philippe Brucker 9323e630336SJean-Philippe Brucker arm_smmu_cmdq_issue_cmd(smmu, &cmd); 9333e630336SJean-Philippe Brucker arm_smmu_cmdq_issue_sync(smmu); 9343e630336SJean-Philippe Brucker } 9353e630336SJean-Philippe Brucker 93687f42391SJean-Philippe Brucker static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain, 93787f42391SJean-Philippe Brucker int ssid, bool leaf) 93848ec83bcSWill Deacon { 93987f42391SJean-Philippe Brucker size_t i; 94087f42391SJean-Philippe Brucker unsigned long flags; 94187f42391SJean-Philippe Brucker struct arm_smmu_master *master; 942edd0351eSJean-Philippe Brucker struct arm_smmu_cmdq_batch cmds = {}; 94387f42391SJean-Philippe Brucker struct arm_smmu_device *smmu = smmu_domain->smmu; 94487f42391SJean-Philippe Brucker struct arm_smmu_cmdq_ent cmd = { 94587f42391SJean-Philippe Brucker .opcode = CMDQ_OP_CFGI_CD, 94687f42391SJean-Philippe Brucker .cfgi = { 94787f42391SJean-Philippe Brucker .ssid = ssid, 94887f42391SJean-Philippe Brucker .leaf = leaf, 94987f42391SJean-Philippe Brucker }, 95087f42391SJean-Philippe Brucker }; 95148ec83bcSWill Deacon 95287f42391SJean-Philippe Brucker spin_lock_irqsave(&smmu_domain->devices_lock, flags); 95387f42391SJean-Philippe Brucker list_for_each_entry(master, &smmu_domain->devices, domain_head) { 954cdf315f9SJean-Philippe Brucker for (i = 0; i < master->num_streams; i++) { 955cdf315f9SJean-Philippe Brucker cmd.cfgi.sid = master->streams[i].id; 956edd0351eSJean-Philippe Brucker arm_smmu_cmdq_batch_add(smmu, &cmds, &cmd); 95787f42391SJean-Philippe Brucker } 95887f42391SJean-Philippe Brucker } 95987f42391SJean-Philippe Brucker spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); 96048ec83bcSWill Deacon 961edd0351eSJean-Philippe Brucker arm_smmu_cmdq_batch_submit(smmu, &cmds); 96248ec83bcSWill Deacon } 96348ec83bcSWill Deacon 96473af06f5SJean-Philippe Brucker static int arm_smmu_alloc_cd_leaf_table(struct arm_smmu_device *smmu, 96573af06f5SJean-Philippe Brucker struct arm_smmu_l1_ctx_desc *l1_desc) 96648ec83bcSWill Deacon { 96773af06f5SJean-Philippe Brucker size_t size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3); 96873af06f5SJean-Philippe Brucker 96973af06f5SJean-Philippe Brucker l1_desc->l2ptr = dmam_alloc_coherent(smmu->dev, size, 97073af06f5SJean-Philippe Brucker &l1_desc->l2ptr_dma, GFP_KERNEL); 97173af06f5SJean-Philippe Brucker if (!l1_desc->l2ptr) { 97273af06f5SJean-Philippe Brucker dev_warn(smmu->dev, 97373af06f5SJean-Philippe Brucker "failed to allocate context descriptor table\n"); 97473af06f5SJean-Philippe Brucker return -ENOMEM; 97573af06f5SJean-Philippe Brucker } 97673af06f5SJean-Philippe Brucker return 0; 97773af06f5SJean-Philippe Brucker } 97873af06f5SJean-Philippe Brucker 97973af06f5SJean-Philippe Brucker static void arm_smmu_write_cd_l1_desc(__le64 *dst, 98073af06f5SJean-Philippe Brucker struct arm_smmu_l1_ctx_desc *l1_desc) 98173af06f5SJean-Philippe Brucker { 98273af06f5SJean-Philippe Brucker u64 val = (l1_desc->l2ptr_dma & CTXDESC_L1_DESC_L2PTR_MASK) | 98373af06f5SJean-Philippe Brucker CTXDESC_L1_DESC_V; 98473af06f5SJean-Philippe Brucker 98587e5fe5bSJean-Philippe Brucker /* See comment in arm_smmu_write_ctx_desc() */ 98673af06f5SJean-Philippe Brucker WRITE_ONCE(*dst, cpu_to_le64(val)); 98773af06f5SJean-Philippe Brucker } 98873af06f5SJean-Philippe Brucker 98973af06f5SJean-Philippe Brucker static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain, 99073af06f5SJean-Philippe Brucker u32 ssid) 99173af06f5SJean-Philippe Brucker { 99273af06f5SJean-Philippe Brucker __le64 *l1ptr; 99373af06f5SJean-Philippe Brucker unsigned int idx; 99473af06f5SJean-Philippe Brucker struct arm_smmu_l1_ctx_desc *l1_desc; 99573af06f5SJean-Philippe Brucker struct arm_smmu_device *smmu = smmu_domain->smmu; 99673af06f5SJean-Philippe Brucker struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg; 99773af06f5SJean-Philippe Brucker 99873af06f5SJean-Philippe Brucker if (smmu_domain->s1_cfg.s1fmt == STRTAB_STE_0_S1FMT_LINEAR) 99973af06f5SJean-Philippe Brucker return cdcfg->cdtab + ssid * CTXDESC_CD_DWORDS; 100073af06f5SJean-Philippe Brucker 100173af06f5SJean-Philippe Brucker idx = ssid >> CTXDESC_SPLIT; 100273af06f5SJean-Philippe Brucker l1_desc = &cdcfg->l1_desc[idx]; 100373af06f5SJean-Philippe Brucker if (!l1_desc->l2ptr) { 100473af06f5SJean-Philippe Brucker if (arm_smmu_alloc_cd_leaf_table(smmu, l1_desc)) 100573af06f5SJean-Philippe Brucker return NULL; 100673af06f5SJean-Philippe Brucker 100773af06f5SJean-Philippe Brucker l1ptr = cdcfg->cdtab + idx * CTXDESC_L1_DESC_DWORDS; 100873af06f5SJean-Philippe Brucker arm_smmu_write_cd_l1_desc(l1ptr, l1_desc); 100973af06f5SJean-Philippe Brucker /* An invalid L1CD can be cached */ 101073af06f5SJean-Philippe Brucker arm_smmu_sync_cd(smmu_domain, ssid, false); 101173af06f5SJean-Philippe Brucker } 101273af06f5SJean-Philippe Brucker idx = ssid & (CTXDESC_L2_ENTRIES - 1); 101373af06f5SJean-Philippe Brucker return l1_desc->l2ptr + idx * CTXDESC_CD_DWORDS; 101473af06f5SJean-Philippe Brucker } 101573af06f5SJean-Philippe Brucker 10163e630336SJean-Philippe Brucker int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid, 10173e630336SJean-Philippe Brucker struct arm_smmu_ctx_desc *cd) 101887f42391SJean-Philippe Brucker { 101987f42391SJean-Philippe Brucker /* 102087f42391SJean-Philippe Brucker * This function handles the following cases: 102187f42391SJean-Philippe Brucker * 102287f42391SJean-Philippe Brucker * (1) Install primary CD, for normal DMA traffic (SSID = 0). 102387f42391SJean-Philippe Brucker * (2) Install a secondary CD, for SID+SSID traffic. 102487f42391SJean-Philippe Brucker * (3) Update ASID of a CD. Atomically write the first 64 bits of the 102587f42391SJean-Philippe Brucker * CD, then invalidate the old entry and mappings. 102632784a95SJean-Philippe Brucker * (4) Quiesce the context without clearing the valid bit. Disable 102732784a95SJean-Philippe Brucker * translation, and ignore any translation fault. 102832784a95SJean-Philippe Brucker * (5) Remove a secondary CD. 102987f42391SJean-Philippe Brucker */ 103048ec83bcSWill Deacon u64 val; 103187f42391SJean-Philippe Brucker bool cd_live; 103273af06f5SJean-Philippe Brucker __le64 *cdptr; 103373af06f5SJean-Philippe Brucker 103473af06f5SJean-Philippe Brucker if (WARN_ON(ssid >= (1 << smmu_domain->s1_cfg.s1cdmax))) 103573af06f5SJean-Philippe Brucker return -E2BIG; 103673af06f5SJean-Philippe Brucker 103773af06f5SJean-Philippe Brucker cdptr = arm_smmu_get_cd_ptr(smmu_domain, ssid); 103873af06f5SJean-Philippe Brucker if (!cdptr) 103973af06f5SJean-Philippe Brucker return -ENOMEM; 104087f42391SJean-Philippe Brucker 104187f42391SJean-Philippe Brucker val = le64_to_cpu(cdptr[0]); 104287f42391SJean-Philippe Brucker cd_live = !!(val & CTXDESC_CD_0_V); 104387f42391SJean-Philippe Brucker 104432784a95SJean-Philippe Brucker if (!cd) { /* (5) */ 104587f42391SJean-Philippe Brucker val = 0; 104632784a95SJean-Philippe Brucker } else if (cd == &quiet_cd) { /* (4) */ 104732784a95SJean-Philippe Brucker val |= CTXDESC_CD_0_TCR_EPD0; 104887f42391SJean-Philippe Brucker } else if (cd_live) { /* (3) */ 104987f42391SJean-Philippe Brucker val &= ~CTXDESC_CD_0_ASID; 105087f42391SJean-Philippe Brucker val |= FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid); 105187f42391SJean-Philippe Brucker /* 105287f42391SJean-Philippe Brucker * Until CD+TLB invalidation, both ASIDs may be used for tagging 105387f42391SJean-Philippe Brucker * this substream's traffic 105487f42391SJean-Philippe Brucker */ 105587f42391SJean-Philippe Brucker } else { /* (1) and (2) */ 105687f42391SJean-Philippe Brucker cdptr[1] = cpu_to_le64(cd->ttbr & CTXDESC_CD_1_TTB0_MASK); 105787f42391SJean-Philippe Brucker cdptr[2] = 0; 105887f42391SJean-Philippe Brucker cdptr[3] = cpu_to_le64(cd->mair); 105948ec83bcSWill Deacon 106048ec83bcSWill Deacon /* 106187f42391SJean-Philippe Brucker * STE is live, and the SMMU might read dwords of this CD in any 106287f42391SJean-Philippe Brucker * order. Ensure that it observes valid values before reading 106387f42391SJean-Philippe Brucker * V=1. 106448ec83bcSWill Deacon */ 106587f42391SJean-Philippe Brucker arm_smmu_sync_cd(smmu_domain, ssid, true); 106687f42391SJean-Philippe Brucker 106787f42391SJean-Philippe Brucker val = cd->tcr | 106848ec83bcSWill Deacon #ifdef __BIG_ENDIAN 106948ec83bcSWill Deacon CTXDESC_CD_0_ENDI | 107048ec83bcSWill Deacon #endif 10713f1ce8e8SJean-Philippe Brucker CTXDESC_CD_0_R | CTXDESC_CD_0_A | 10723f1ce8e8SJean-Philippe Brucker (cd->mm ? 0 : CTXDESC_CD_0_ASET) | 107387f42391SJean-Philippe Brucker CTXDESC_CD_0_AA64 | 107487f42391SJean-Philippe Brucker FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid) | 107548ec83bcSWill Deacon CTXDESC_CD_0_V; 10769cff86fdSYisheng Xie 1077395ad89dSJean-Philippe Brucker if (smmu_domain->stall_enabled) 10789cff86fdSYisheng Xie val |= CTXDESC_CD_0_S; 107987f42391SJean-Philippe Brucker } 10809cff86fdSYisheng Xie 108187f42391SJean-Philippe Brucker /* 108287f42391SJean-Philippe Brucker * The SMMU accesses 64-bit values atomically. See IHI0070Ca 3.21.3 108387f42391SJean-Philippe Brucker * "Configuration structures and configuration invalidation completion" 108487f42391SJean-Philippe Brucker * 108587f42391SJean-Philippe Brucker * The size of single-copy atomic reads made by the SMMU is 108687f42391SJean-Philippe Brucker * IMPLEMENTATION DEFINED but must be at least 64 bits. Any single 108787f42391SJean-Philippe Brucker * field within an aligned 64-bit span of a structure can be altered 108887f42391SJean-Philippe Brucker * without first making the structure invalid. 108987f42391SJean-Philippe Brucker */ 109087f42391SJean-Philippe Brucker WRITE_ONCE(cdptr[0], cpu_to_le64(val)); 109187f42391SJean-Philippe Brucker arm_smmu_sync_cd(smmu_domain, ssid, true); 109287f42391SJean-Philippe Brucker return 0; 109348ec83bcSWill Deacon } 109448ec83bcSWill Deacon 1095a557aff0SJean-Philippe Brucker static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain) 1096a557aff0SJean-Philippe Brucker { 109773af06f5SJean-Philippe Brucker int ret; 1098a557aff0SJean-Philippe Brucker size_t l1size; 109973af06f5SJean-Philippe Brucker size_t max_contexts; 1100a557aff0SJean-Philippe Brucker struct arm_smmu_device *smmu = smmu_domain->smmu; 1101a557aff0SJean-Philippe Brucker struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg; 1102a557aff0SJean-Philippe Brucker struct arm_smmu_ctx_desc_cfg *cdcfg = &cfg->cdcfg; 110348ec83bcSWill Deacon 110473af06f5SJean-Philippe Brucker max_contexts = 1 << cfg->s1cdmax; 110587f42391SJean-Philippe Brucker 110673af06f5SJean-Philippe Brucker if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) || 110773af06f5SJean-Philippe Brucker max_contexts <= CTXDESC_L2_ENTRIES) { 110873af06f5SJean-Philippe Brucker cfg->s1fmt = STRTAB_STE_0_S1FMT_LINEAR; 110973af06f5SJean-Philippe Brucker cdcfg->num_l1_ents = max_contexts; 111073af06f5SJean-Philippe Brucker 111173af06f5SJean-Philippe Brucker l1size = max_contexts * (CTXDESC_CD_DWORDS << 3); 111273af06f5SJean-Philippe Brucker } else { 111373af06f5SJean-Philippe Brucker cfg->s1fmt = STRTAB_STE_0_S1FMT_64K_L2; 111473af06f5SJean-Philippe Brucker cdcfg->num_l1_ents = DIV_ROUND_UP(max_contexts, 111573af06f5SJean-Philippe Brucker CTXDESC_L2_ENTRIES); 111673af06f5SJean-Philippe Brucker 111773af06f5SJean-Philippe Brucker cdcfg->l1_desc = devm_kcalloc(smmu->dev, cdcfg->num_l1_ents, 111873af06f5SJean-Philippe Brucker sizeof(*cdcfg->l1_desc), 111973af06f5SJean-Philippe Brucker GFP_KERNEL); 112073af06f5SJean-Philippe Brucker if (!cdcfg->l1_desc) 112173af06f5SJean-Philippe Brucker return -ENOMEM; 112273af06f5SJean-Philippe Brucker 112373af06f5SJean-Philippe Brucker l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3); 112473af06f5SJean-Philippe Brucker } 112573af06f5SJean-Philippe Brucker 1126a557aff0SJean-Philippe Brucker cdcfg->cdtab = dmam_alloc_coherent(smmu->dev, l1size, &cdcfg->cdtab_dma, 1127a557aff0SJean-Philippe Brucker GFP_KERNEL); 1128a557aff0SJean-Philippe Brucker if (!cdcfg->cdtab) { 1129a557aff0SJean-Philippe Brucker dev_warn(smmu->dev, "failed to allocate context descriptor\n"); 113073af06f5SJean-Philippe Brucker ret = -ENOMEM; 113173af06f5SJean-Philippe Brucker goto err_free_l1; 1132a557aff0SJean-Philippe Brucker } 113373af06f5SJean-Philippe Brucker 1134a557aff0SJean-Philippe Brucker return 0; 113573af06f5SJean-Philippe Brucker 113673af06f5SJean-Philippe Brucker err_free_l1: 113773af06f5SJean-Philippe Brucker if (cdcfg->l1_desc) { 113873af06f5SJean-Philippe Brucker devm_kfree(smmu->dev, cdcfg->l1_desc); 113973af06f5SJean-Philippe Brucker cdcfg->l1_desc = NULL; 114073af06f5SJean-Philippe Brucker } 114173af06f5SJean-Philippe Brucker return ret; 1142a557aff0SJean-Philippe Brucker } 1143a557aff0SJean-Philippe Brucker 1144a557aff0SJean-Philippe Brucker static void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain) 1145a557aff0SJean-Philippe Brucker { 114673af06f5SJean-Philippe Brucker int i; 114773af06f5SJean-Philippe Brucker size_t size, l1size; 1148a557aff0SJean-Philippe Brucker struct arm_smmu_device *smmu = smmu_domain->smmu; 1149a557aff0SJean-Philippe Brucker struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg; 115073af06f5SJean-Philippe Brucker 115173af06f5SJean-Philippe Brucker if (cdcfg->l1_desc) { 115273af06f5SJean-Philippe Brucker size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3); 115373af06f5SJean-Philippe Brucker 115473af06f5SJean-Philippe Brucker for (i = 0; i < cdcfg->num_l1_ents; i++) { 115573af06f5SJean-Philippe Brucker if (!cdcfg->l1_desc[i].l2ptr) 115673af06f5SJean-Philippe Brucker continue; 115773af06f5SJean-Philippe Brucker 115873af06f5SJean-Philippe Brucker dmam_free_coherent(smmu->dev, size, 115973af06f5SJean-Philippe Brucker cdcfg->l1_desc[i].l2ptr, 116073af06f5SJean-Philippe Brucker cdcfg->l1_desc[i].l2ptr_dma); 116173af06f5SJean-Philippe Brucker } 116273af06f5SJean-Philippe Brucker devm_kfree(smmu->dev, cdcfg->l1_desc); 116373af06f5SJean-Philippe Brucker cdcfg->l1_desc = NULL; 116473af06f5SJean-Philippe Brucker 116573af06f5SJean-Philippe Brucker l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3); 116673af06f5SJean-Philippe Brucker } else { 116773af06f5SJean-Philippe Brucker l1size = cdcfg->num_l1_ents * (CTXDESC_CD_DWORDS << 3); 116873af06f5SJean-Philippe Brucker } 1169a557aff0SJean-Philippe Brucker 1170a557aff0SJean-Philippe Brucker dmam_free_coherent(smmu->dev, l1size, cdcfg->cdtab, cdcfg->cdtab_dma); 1171a557aff0SJean-Philippe Brucker cdcfg->cdtab_dma = 0; 1172a557aff0SJean-Philippe Brucker cdcfg->cdtab = NULL; 117348ec83bcSWill Deacon } 117448ec83bcSWill Deacon 11753f1ce8e8SJean-Philippe Brucker bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd) 11760299a1a8SJean-Philippe Brucker { 11773f1ce8e8SJean-Philippe Brucker bool free; 11783f1ce8e8SJean-Philippe Brucker struct arm_smmu_ctx_desc *old_cd; 11790299a1a8SJean-Philippe Brucker 11803f1ce8e8SJean-Philippe Brucker if (!cd->asid) 11813f1ce8e8SJean-Philippe Brucker return false; 11823f1ce8e8SJean-Philippe Brucker 11833f1ce8e8SJean-Philippe Brucker free = refcount_dec_and_test(&cd->refs); 11843f1ce8e8SJean-Philippe Brucker if (free) { 11853f1ce8e8SJean-Philippe Brucker old_cd = xa_erase(&arm_smmu_asid_xa, cd->asid); 11863f1ce8e8SJean-Philippe Brucker WARN_ON(old_cd != cd); 11873f1ce8e8SJean-Philippe Brucker } 11883f1ce8e8SJean-Philippe Brucker return free; 11890299a1a8SJean-Philippe Brucker } 11900299a1a8SJean-Philippe Brucker 119148ec83bcSWill Deacon /* Stream table manipulation functions */ 119248ec83bcSWill Deacon static void 119348ec83bcSWill Deacon arm_smmu_write_strtab_l1_desc(__le64 *dst, struct arm_smmu_strtab_l1_desc *desc) 119448ec83bcSWill Deacon { 119548ec83bcSWill Deacon u64 val = 0; 119648ec83bcSWill Deacon 1197ba08bdcbSRobin Murphy val |= FIELD_PREP(STRTAB_L1_DESC_SPAN, desc->span); 11981cf9e54eSRobin Murphy val |= desc->l2ptr_dma & STRTAB_L1_DESC_L2PTR_MASK; 119948ec83bcSWill Deacon 120087e5fe5bSJean-Philippe Brucker /* See comment in arm_smmu_write_ctx_desc() */ 120187e5fe5bSJean-Philippe Brucker WRITE_ONCE(*dst, cpu_to_le64(val)); 120248ec83bcSWill Deacon } 120348ec83bcSWill Deacon 120448ec83bcSWill Deacon static void arm_smmu_sync_ste_for_sid(struct arm_smmu_device *smmu, u32 sid) 120548ec83bcSWill Deacon { 120648ec83bcSWill Deacon struct arm_smmu_cmdq_ent cmd = { 120748ec83bcSWill Deacon .opcode = CMDQ_OP_CFGI_STE, 120848ec83bcSWill Deacon .cfgi = { 120948ec83bcSWill Deacon .sid = sid, 121048ec83bcSWill Deacon .leaf = true, 121148ec83bcSWill Deacon }, 121248ec83bcSWill Deacon }; 121348ec83bcSWill Deacon 121448ec83bcSWill Deacon arm_smmu_cmdq_issue_cmd(smmu, &cmd); 12152f657addSRobin Murphy arm_smmu_cmdq_issue_sync(smmu); 121648ec83bcSWill Deacon } 121748ec83bcSWill Deacon 12188be39a1aSJean-Philippe Brucker static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid, 12198be39a1aSJean-Philippe Brucker __le64 *dst) 122048ec83bcSWill Deacon { 122148ec83bcSWill Deacon /* 122248ec83bcSWill Deacon * This is hideously complicated, but we only really care about 122348ec83bcSWill Deacon * three cases at the moment: 122448ec83bcSWill Deacon * 1225beb3c6a0SWill Deacon * 1. Invalid (all zero) -> bypass/fault (init) 1226beb3c6a0SWill Deacon * 2. Bypass/fault -> translation/bypass (attach) 1227beb3c6a0SWill Deacon * 3. Translation/bypass -> bypass/fault (detach) 122848ec83bcSWill Deacon * 122948ec83bcSWill Deacon * Given that we can't update the STE atomically and the SMMU 123048ec83bcSWill Deacon * doesn't read the thing in a defined order, that leaves us 123148ec83bcSWill Deacon * with the following maintenance requirements: 123248ec83bcSWill Deacon * 123348ec83bcSWill Deacon * 1. Update Config, return (init time STEs aren't live) 123448ec83bcSWill Deacon * 2. Write everything apart from dword 0, sync, write dword 0, sync 123548ec83bcSWill Deacon * 3. Update Config, sync 123648ec83bcSWill Deacon */ 123748ec83bcSWill Deacon u64 val = le64_to_cpu(dst[0]); 123848ec83bcSWill Deacon bool ste_live = false; 12398be39a1aSJean-Philippe Brucker struct arm_smmu_device *smmu = NULL; 12408be39a1aSJean-Philippe Brucker struct arm_smmu_s1_cfg *s1_cfg = NULL; 12418be39a1aSJean-Philippe Brucker struct arm_smmu_s2_cfg *s2_cfg = NULL; 12428be39a1aSJean-Philippe Brucker struct arm_smmu_domain *smmu_domain = NULL; 124348ec83bcSWill Deacon struct arm_smmu_cmdq_ent prefetch_cmd = { 124448ec83bcSWill Deacon .opcode = CMDQ_OP_PREFETCH_CFG, 124548ec83bcSWill Deacon .prefetch = { 124648ec83bcSWill Deacon .sid = sid, 124748ec83bcSWill Deacon }, 124848ec83bcSWill Deacon }; 124948ec83bcSWill Deacon 12508be39a1aSJean-Philippe Brucker if (master) { 12518be39a1aSJean-Philippe Brucker smmu_domain = master->domain; 12528be39a1aSJean-Philippe Brucker smmu = master->smmu; 12538be39a1aSJean-Philippe Brucker } 12548be39a1aSJean-Philippe Brucker 12558be39a1aSJean-Philippe Brucker if (smmu_domain) { 12568be39a1aSJean-Philippe Brucker switch (smmu_domain->stage) { 12578be39a1aSJean-Philippe Brucker case ARM_SMMU_DOMAIN_S1: 12588be39a1aSJean-Philippe Brucker s1_cfg = &smmu_domain->s1_cfg; 12598be39a1aSJean-Philippe Brucker break; 12608be39a1aSJean-Philippe Brucker case ARM_SMMU_DOMAIN_S2: 12618be39a1aSJean-Philippe Brucker case ARM_SMMU_DOMAIN_NESTED: 12628be39a1aSJean-Philippe Brucker s2_cfg = &smmu_domain->s2_cfg; 12638be39a1aSJean-Philippe Brucker break; 12648be39a1aSJean-Philippe Brucker default: 12658be39a1aSJean-Philippe Brucker break; 12668be39a1aSJean-Philippe Brucker } 12678be39a1aSJean-Philippe Brucker } 12688be39a1aSJean-Philippe Brucker 126948ec83bcSWill Deacon if (val & STRTAB_STE_0_V) { 1270ba08bdcbSRobin Murphy switch (FIELD_GET(STRTAB_STE_0_CFG, val)) { 127148ec83bcSWill Deacon case STRTAB_STE_0_CFG_BYPASS: 127248ec83bcSWill Deacon break; 127348ec83bcSWill Deacon case STRTAB_STE_0_CFG_S1_TRANS: 127448ec83bcSWill Deacon case STRTAB_STE_0_CFG_S2_TRANS: 127548ec83bcSWill Deacon ste_live = true; 127648ec83bcSWill Deacon break; 12775bc0a116SWill Deacon case STRTAB_STE_0_CFG_ABORT: 127811f4fe9bSAnders Roxell BUG_ON(!disable_bypass); 12795bc0a116SWill Deacon break; 128048ec83bcSWill Deacon default: 128148ec83bcSWill Deacon BUG(); /* STE corruption */ 128248ec83bcSWill Deacon } 128348ec83bcSWill Deacon } 128448ec83bcSWill Deacon 1285810871c5SNate Watterson /* Nuke the existing STE_0 value, as we're going to rewrite it */ 1286beb3c6a0SWill Deacon val = STRTAB_STE_0_V; 128748ec83bcSWill Deacon 1288beb3c6a0SWill Deacon /* Bypass/fault */ 12898be39a1aSJean-Philippe Brucker if (!smmu_domain || !(s1_cfg || s2_cfg)) { 12908be39a1aSJean-Philippe Brucker if (!smmu_domain && disable_bypass) 1291ba08bdcbSRobin Murphy val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT); 1292beb3c6a0SWill Deacon else 1293ba08bdcbSRobin Murphy val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS); 1294beb3c6a0SWill Deacon 129548ec83bcSWill Deacon dst[0] = cpu_to_le64(val); 1296ba08bdcbSRobin Murphy dst[1] = cpu_to_le64(FIELD_PREP(STRTAB_STE_1_SHCFG, 1297ba08bdcbSRobin Murphy STRTAB_STE_1_SHCFG_INCOMING)); 129848ec83bcSWill Deacon dst[2] = 0; /* Nuke the VMID */ 1299704c0382SWill Deacon /* 1300704c0382SWill Deacon * The SMMU can perform negative caching, so we must sync 1301704c0382SWill Deacon * the STE regardless of whether the old value was live. 1302704c0382SWill Deacon */ 1303704c0382SWill Deacon if (smmu) 130448ec83bcSWill Deacon arm_smmu_sync_ste_for_sid(smmu, sid); 130548ec83bcSWill Deacon return; 130648ec83bcSWill Deacon } 130748ec83bcSWill Deacon 13088be39a1aSJean-Philippe Brucker if (s1_cfg) { 13099111aebfSJean-Philippe Brucker u64 strw = smmu->features & ARM_SMMU_FEAT_E2H ? 13109111aebfSJean-Philippe Brucker STRTAB_STE_1_STRW_EL2 : STRTAB_STE_1_STRW_NSEL1; 13119111aebfSJean-Philippe Brucker 131248ec83bcSWill Deacon BUG_ON(ste_live); 131348ec83bcSWill Deacon dst[1] = cpu_to_le64( 131487f42391SJean-Philippe Brucker FIELD_PREP(STRTAB_STE_1_S1DSS, STRTAB_STE_1_S1DSS_SSID0) | 1315ba08bdcbSRobin Murphy FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) | 1316ba08bdcbSRobin Murphy FIELD_PREP(STRTAB_STE_1_S1COR, STRTAB_STE_1_S1C_CACHE_WBRA) | 1317ba08bdcbSRobin Murphy FIELD_PREP(STRTAB_STE_1_S1CSH, ARM_SMMU_SH_ISH) | 13189111aebfSJean-Philippe Brucker FIELD_PREP(STRTAB_STE_1_STRW, strw)); 131948ec83bcSWill Deacon 13209cff86fdSYisheng Xie if (smmu->features & ARM_SMMU_FEAT_STALLS && 1321395ad89dSJean-Philippe Brucker !master->stall_enabled) 13226380be05SPrem Mallappa dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD); 13236380be05SPrem Mallappa 13247bc4f3faSJean-Philippe Brucker val |= (s1_cfg->cdcfg.cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) | 132587f42391SJean-Philippe Brucker FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) | 132687f42391SJean-Philippe Brucker FIELD_PREP(STRTAB_STE_0_S1CDMAX, s1_cfg->s1cdmax) | 132787f42391SJean-Philippe Brucker FIELD_PREP(STRTAB_STE_0_S1FMT, s1_cfg->s1fmt); 132848ec83bcSWill Deacon } 132948ec83bcSWill Deacon 13308be39a1aSJean-Philippe Brucker if (s2_cfg) { 133148ec83bcSWill Deacon BUG_ON(ste_live); 133248ec83bcSWill Deacon dst[2] = cpu_to_le64( 13338be39a1aSJean-Philippe Brucker FIELD_PREP(STRTAB_STE_2_S2VMID, s2_cfg->vmid) | 13348be39a1aSJean-Philippe Brucker FIELD_PREP(STRTAB_STE_2_VTCR, s2_cfg->vtcr) | 133548ec83bcSWill Deacon #ifdef __BIG_ENDIAN 133648ec83bcSWill Deacon STRTAB_STE_2_S2ENDI | 133748ec83bcSWill Deacon #endif 133848ec83bcSWill Deacon STRTAB_STE_2_S2PTW | STRTAB_STE_2_S2AA64 | 133948ec83bcSWill Deacon STRTAB_STE_2_S2R); 134048ec83bcSWill Deacon 13418be39a1aSJean-Philippe Brucker dst[3] = cpu_to_le64(s2_cfg->vttbr & STRTAB_STE_3_S2TTB_MASK); 134248ec83bcSWill Deacon 1343ba08bdcbSRobin Murphy val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S2_TRANS); 134448ec83bcSWill Deacon } 134548ec83bcSWill Deacon 13469ce27afcSJean-Philippe Brucker if (master->ats_enabled) 13479ce27afcSJean-Philippe Brucker dst[1] |= cpu_to_le64(FIELD_PREP(STRTAB_STE_1_EATS, 13489ce27afcSJean-Philippe Brucker STRTAB_STE_1_EATS_TRANS)); 13499ce27afcSJean-Philippe Brucker 135048ec83bcSWill Deacon arm_smmu_sync_ste_for_sid(smmu, sid); 1351d71e0171SWill Deacon /* See comment in arm_smmu_write_ctx_desc() */ 1352d71e0171SWill Deacon WRITE_ONCE(dst[0], cpu_to_le64(val)); 135348ec83bcSWill Deacon arm_smmu_sync_ste_for_sid(smmu, sid); 135448ec83bcSWill Deacon 135548ec83bcSWill Deacon /* It's likely that we'll want to use the new STE soon */ 13565e92946cSZhen Lei if (!(smmu->options & ARM_SMMU_OPT_SKIP_PREFETCH)) 135748ec83bcSWill Deacon arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd); 135848ec83bcSWill Deacon } 135948ec83bcSWill Deacon 1360376cdf66SJean-Philippe Brucker static void arm_smmu_init_bypass_stes(__le64 *strtab, unsigned int nent) 136148ec83bcSWill Deacon { 136248ec83bcSWill Deacon unsigned int i; 136348ec83bcSWill Deacon 136448ec83bcSWill Deacon for (i = 0; i < nent; ++i) { 13658be39a1aSJean-Philippe Brucker arm_smmu_write_strtab_ent(NULL, -1, strtab); 136648ec83bcSWill Deacon strtab += STRTAB_STE_DWORDS; 136748ec83bcSWill Deacon } 136848ec83bcSWill Deacon } 136948ec83bcSWill Deacon 137048ec83bcSWill Deacon static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid) 137148ec83bcSWill Deacon { 137248ec83bcSWill Deacon size_t size; 137348ec83bcSWill Deacon void *strtab; 137448ec83bcSWill Deacon struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg; 137548ec83bcSWill Deacon struct arm_smmu_strtab_l1_desc *desc = &cfg->l1_desc[sid >> STRTAB_SPLIT]; 137648ec83bcSWill Deacon 137748ec83bcSWill Deacon if (desc->l2ptr) 137848ec83bcSWill Deacon return 0; 137948ec83bcSWill Deacon 138048ec83bcSWill Deacon size = 1 << (STRTAB_SPLIT + ilog2(STRTAB_STE_DWORDS) + 3); 138169146e7bSZhen Lei strtab = &cfg->strtab[(sid >> STRTAB_SPLIT) * STRTAB_L1_DESC_DWORDS]; 138248ec83bcSWill Deacon 138348ec83bcSWill Deacon desc->span = STRTAB_SPLIT + 1; 138404fa26c7SWill Deacon desc->l2ptr = dmam_alloc_coherent(smmu->dev, size, &desc->l2ptr_dma, 13859bb9069cSJean-Philippe Brucker GFP_KERNEL); 138648ec83bcSWill Deacon if (!desc->l2ptr) { 138748ec83bcSWill Deacon dev_err(smmu->dev, 138848ec83bcSWill Deacon "failed to allocate l2 stream table for SID %u\n", 138948ec83bcSWill Deacon sid); 139048ec83bcSWill Deacon return -ENOMEM; 139148ec83bcSWill Deacon } 139248ec83bcSWill Deacon 139348ec83bcSWill Deacon arm_smmu_init_bypass_stes(desc->l2ptr, 1 << STRTAB_SPLIT); 139448ec83bcSWill Deacon arm_smmu_write_strtab_l1_desc(strtab, desc); 139548ec83bcSWill Deacon return 0; 139648ec83bcSWill Deacon } 139748ec83bcSWill Deacon 1398cdf315f9SJean-Philippe Brucker static struct arm_smmu_master * 1399cdf315f9SJean-Philippe Brucker arm_smmu_find_master(struct arm_smmu_device *smmu, u32 sid) 1400cdf315f9SJean-Philippe Brucker { 1401cdf315f9SJean-Philippe Brucker struct rb_node *node; 1402cdf315f9SJean-Philippe Brucker struct arm_smmu_stream *stream; 1403cdf315f9SJean-Philippe Brucker 1404cdf315f9SJean-Philippe Brucker lockdep_assert_held(&smmu->streams_mutex); 1405cdf315f9SJean-Philippe Brucker 1406cdf315f9SJean-Philippe Brucker node = smmu->streams.rb_node; 1407cdf315f9SJean-Philippe Brucker while (node) { 1408cdf315f9SJean-Philippe Brucker stream = rb_entry(node, struct arm_smmu_stream, node); 1409cdf315f9SJean-Philippe Brucker if (stream->id < sid) 1410cdf315f9SJean-Philippe Brucker node = node->rb_right; 1411cdf315f9SJean-Philippe Brucker else if (stream->id > sid) 1412cdf315f9SJean-Philippe Brucker node = node->rb_left; 1413cdf315f9SJean-Philippe Brucker else 1414cdf315f9SJean-Philippe Brucker return stream->master; 1415cdf315f9SJean-Philippe Brucker } 1416cdf315f9SJean-Philippe Brucker 1417cdf315f9SJean-Philippe Brucker return NULL; 1418cdf315f9SJean-Philippe Brucker } 1419cdf315f9SJean-Philippe Brucker 142048ec83bcSWill Deacon /* IRQ and event handlers */ 1421395ad89dSJean-Philippe Brucker static int arm_smmu_handle_evt(struct arm_smmu_device *smmu, u64 *evt) 1422395ad89dSJean-Philippe Brucker { 1423395ad89dSJean-Philippe Brucker int ret; 1424395ad89dSJean-Philippe Brucker u32 reason; 1425395ad89dSJean-Philippe Brucker u32 perm = 0; 1426395ad89dSJean-Philippe Brucker struct arm_smmu_master *master; 1427395ad89dSJean-Philippe Brucker bool ssid_valid = evt[0] & EVTQ_0_SSV; 1428395ad89dSJean-Philippe Brucker u32 sid = FIELD_GET(EVTQ_0_SID, evt[0]); 1429395ad89dSJean-Philippe Brucker struct iommu_fault_event fault_evt = { }; 1430395ad89dSJean-Philippe Brucker struct iommu_fault *flt = &fault_evt.fault; 1431395ad89dSJean-Philippe Brucker 1432395ad89dSJean-Philippe Brucker switch (FIELD_GET(EVTQ_0_ID, evt[0])) { 1433395ad89dSJean-Philippe Brucker case EVT_ID_TRANSLATION_FAULT: 1434395ad89dSJean-Philippe Brucker reason = IOMMU_FAULT_REASON_PTE_FETCH; 1435395ad89dSJean-Philippe Brucker break; 1436395ad89dSJean-Philippe Brucker case EVT_ID_ADDR_SIZE_FAULT: 1437395ad89dSJean-Philippe Brucker reason = IOMMU_FAULT_REASON_OOR_ADDRESS; 1438395ad89dSJean-Philippe Brucker break; 1439395ad89dSJean-Philippe Brucker case EVT_ID_ACCESS_FAULT: 1440395ad89dSJean-Philippe Brucker reason = IOMMU_FAULT_REASON_ACCESS; 1441395ad89dSJean-Philippe Brucker break; 1442395ad89dSJean-Philippe Brucker case EVT_ID_PERMISSION_FAULT: 1443395ad89dSJean-Philippe Brucker reason = IOMMU_FAULT_REASON_PERMISSION; 1444395ad89dSJean-Philippe Brucker break; 1445395ad89dSJean-Philippe Brucker default: 1446395ad89dSJean-Philippe Brucker return -EOPNOTSUPP; 1447395ad89dSJean-Philippe Brucker } 1448395ad89dSJean-Philippe Brucker 1449395ad89dSJean-Philippe Brucker /* Stage-2 is always pinned at the moment */ 1450395ad89dSJean-Philippe Brucker if (evt[1] & EVTQ_1_S2) 1451395ad89dSJean-Philippe Brucker return -EFAULT; 1452395ad89dSJean-Philippe Brucker 1453395ad89dSJean-Philippe Brucker if (evt[1] & EVTQ_1_RnW) 1454395ad89dSJean-Philippe Brucker perm |= IOMMU_FAULT_PERM_READ; 1455395ad89dSJean-Philippe Brucker else 1456395ad89dSJean-Philippe Brucker perm |= IOMMU_FAULT_PERM_WRITE; 1457395ad89dSJean-Philippe Brucker 1458395ad89dSJean-Philippe Brucker if (evt[1] & EVTQ_1_InD) 1459395ad89dSJean-Philippe Brucker perm |= IOMMU_FAULT_PERM_EXEC; 1460395ad89dSJean-Philippe Brucker 1461395ad89dSJean-Philippe Brucker if (evt[1] & EVTQ_1_PnU) 1462395ad89dSJean-Philippe Brucker perm |= IOMMU_FAULT_PERM_PRIV; 1463395ad89dSJean-Philippe Brucker 1464395ad89dSJean-Philippe Brucker if (evt[1] & EVTQ_1_STALL) { 1465395ad89dSJean-Philippe Brucker flt->type = IOMMU_FAULT_PAGE_REQ; 1466395ad89dSJean-Philippe Brucker flt->prm = (struct iommu_fault_page_request) { 1467395ad89dSJean-Philippe Brucker .flags = IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE, 1468395ad89dSJean-Philippe Brucker .grpid = FIELD_GET(EVTQ_1_STAG, evt[1]), 1469395ad89dSJean-Philippe Brucker .perm = perm, 1470395ad89dSJean-Philippe Brucker .addr = FIELD_GET(EVTQ_2_ADDR, evt[2]), 1471395ad89dSJean-Philippe Brucker }; 1472395ad89dSJean-Philippe Brucker 1473395ad89dSJean-Philippe Brucker if (ssid_valid) { 1474395ad89dSJean-Philippe Brucker flt->prm.flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID; 1475395ad89dSJean-Philippe Brucker flt->prm.pasid = FIELD_GET(EVTQ_0_SSID, evt[0]); 1476395ad89dSJean-Philippe Brucker } 1477395ad89dSJean-Philippe Brucker } else { 1478395ad89dSJean-Philippe Brucker flt->type = IOMMU_FAULT_DMA_UNRECOV; 1479395ad89dSJean-Philippe Brucker flt->event = (struct iommu_fault_unrecoverable) { 1480395ad89dSJean-Philippe Brucker .reason = reason, 1481395ad89dSJean-Philippe Brucker .flags = IOMMU_FAULT_UNRECOV_ADDR_VALID, 1482395ad89dSJean-Philippe Brucker .perm = perm, 1483395ad89dSJean-Philippe Brucker .addr = FIELD_GET(EVTQ_2_ADDR, evt[2]), 1484395ad89dSJean-Philippe Brucker }; 1485395ad89dSJean-Philippe Brucker 1486395ad89dSJean-Philippe Brucker if (ssid_valid) { 1487395ad89dSJean-Philippe Brucker flt->event.flags |= IOMMU_FAULT_UNRECOV_PASID_VALID; 1488395ad89dSJean-Philippe Brucker flt->event.pasid = FIELD_GET(EVTQ_0_SSID, evt[0]); 1489395ad89dSJean-Philippe Brucker } 1490395ad89dSJean-Philippe Brucker } 1491395ad89dSJean-Philippe Brucker 1492395ad89dSJean-Philippe Brucker mutex_lock(&smmu->streams_mutex); 1493395ad89dSJean-Philippe Brucker master = arm_smmu_find_master(smmu, sid); 1494395ad89dSJean-Philippe Brucker if (!master) { 1495395ad89dSJean-Philippe Brucker ret = -EINVAL; 1496395ad89dSJean-Philippe Brucker goto out_unlock; 1497395ad89dSJean-Philippe Brucker } 1498395ad89dSJean-Philippe Brucker 1499395ad89dSJean-Philippe Brucker ret = iommu_report_device_fault(master->dev, &fault_evt); 1500395ad89dSJean-Philippe Brucker if (ret && flt->type == IOMMU_FAULT_PAGE_REQ) { 1501395ad89dSJean-Philippe Brucker /* Nobody cared, abort the access */ 1502395ad89dSJean-Philippe Brucker struct iommu_page_response resp = { 1503395ad89dSJean-Philippe Brucker .pasid = flt->prm.pasid, 1504395ad89dSJean-Philippe Brucker .grpid = flt->prm.grpid, 1505395ad89dSJean-Philippe Brucker .code = IOMMU_PAGE_RESP_FAILURE, 1506395ad89dSJean-Philippe Brucker }; 1507395ad89dSJean-Philippe Brucker arm_smmu_page_response(master->dev, &fault_evt, &resp); 1508395ad89dSJean-Philippe Brucker } 1509395ad89dSJean-Philippe Brucker 1510395ad89dSJean-Philippe Brucker out_unlock: 1511395ad89dSJean-Philippe Brucker mutex_unlock(&smmu->streams_mutex); 1512395ad89dSJean-Philippe Brucker return ret; 1513395ad89dSJean-Philippe Brucker } 1514395ad89dSJean-Philippe Brucker 151548ec83bcSWill Deacon static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev) 151648ec83bcSWill Deacon { 1517395ad89dSJean-Philippe Brucker int i, ret; 151848ec83bcSWill Deacon struct arm_smmu_device *smmu = dev; 151948ec83bcSWill Deacon struct arm_smmu_queue *q = &smmu->evtq.q; 15207c288a5bSWill Deacon struct arm_smmu_ll_queue *llq = &q->llq; 1521*9cff922bSJean-Philippe Brucker static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, 1522*9cff922bSJean-Philippe Brucker DEFAULT_RATELIMIT_BURST); 152348ec83bcSWill Deacon u64 evt[EVTQ_ENT_DWORDS]; 152448ec83bcSWill Deacon 1525b4163fb3SJean-Philippe Brucker do { 152648ec83bcSWill Deacon while (!queue_remove_raw(q, evt)) { 15277417b99cSRobin Murphy u8 id = FIELD_GET(EVTQ_0_ID, evt[0]); 152848ec83bcSWill Deacon 1529395ad89dSJean-Philippe Brucker ret = arm_smmu_handle_evt(smmu, evt); 1530*9cff922bSJean-Philippe Brucker if (!ret || !__ratelimit(&rs)) 1531395ad89dSJean-Philippe Brucker continue; 1532395ad89dSJean-Philippe Brucker 153348ec83bcSWill Deacon dev_info(smmu->dev, "event 0x%02x received:\n", id); 153448ec83bcSWill Deacon for (i = 0; i < ARRAY_SIZE(evt); ++i) 153548ec83bcSWill Deacon dev_info(smmu->dev, "\t0x%016llx\n", 153648ec83bcSWill Deacon (unsigned long long)evt[i]); 153748ec83bcSWill Deacon 153848ec83bcSWill Deacon } 153948ec83bcSWill Deacon 154048ec83bcSWill Deacon /* 154148ec83bcSWill Deacon * Not much we can do on overflow, so scream and pretend we're 154248ec83bcSWill Deacon * trying harder. 154348ec83bcSWill Deacon */ 15442a8868f1SWill Deacon if (queue_sync_prod_in(q) == -EOVERFLOW) 154548ec83bcSWill Deacon dev_err(smmu->dev, "EVTQ overflow detected -- events lost\n"); 15467c288a5bSWill Deacon } while (!queue_empty(llq)); 154748ec83bcSWill Deacon 1548b4163fb3SJean-Philippe Brucker /* Sync our overflow flag, as we believe we're up to speed */ 15497c288a5bSWill Deacon llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) | 15507c288a5bSWill Deacon Q_IDX(llq, llq->cons); 1551b4163fb3SJean-Philippe Brucker return IRQ_HANDLED; 155248ec83bcSWill Deacon } 155348ec83bcSWill Deacon 1554b4163fb3SJean-Philippe Brucker static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64 *evt) 155548ec83bcSWill Deacon { 155648ec83bcSWill Deacon u32 sid, ssid; 155748ec83bcSWill Deacon u16 grpid; 155848ec83bcSWill Deacon bool ssv, last; 155948ec83bcSWill Deacon 15607417b99cSRobin Murphy sid = FIELD_GET(PRIQ_0_SID, evt[0]); 15617417b99cSRobin Murphy ssv = FIELD_GET(PRIQ_0_SSID_V, evt[0]); 15627417b99cSRobin Murphy ssid = ssv ? FIELD_GET(PRIQ_0_SSID, evt[0]) : 0; 15637417b99cSRobin Murphy last = FIELD_GET(PRIQ_0_PRG_LAST, evt[0]); 15647417b99cSRobin Murphy grpid = FIELD_GET(PRIQ_1_PRG_IDX, evt[1]); 156548ec83bcSWill Deacon 156648ec83bcSWill Deacon dev_info(smmu->dev, "unexpected PRI request received:\n"); 156748ec83bcSWill Deacon dev_info(smmu->dev, 156848ec83bcSWill Deacon "\tsid 0x%08x.0x%05x: [%u%s] %sprivileged %s%s%s access at iova 0x%016llx\n", 156948ec83bcSWill Deacon sid, ssid, grpid, last ? "L" : "", 157048ec83bcSWill Deacon evt[0] & PRIQ_0_PERM_PRIV ? "" : "un", 157148ec83bcSWill Deacon evt[0] & PRIQ_0_PERM_READ ? "R" : "", 157248ec83bcSWill Deacon evt[0] & PRIQ_0_PERM_WRITE ? "W" : "", 157348ec83bcSWill Deacon evt[0] & PRIQ_0_PERM_EXEC ? "X" : "", 15741cf9e54eSRobin Murphy evt[1] & PRIQ_1_ADDR_MASK); 157548ec83bcSWill Deacon 157648ec83bcSWill Deacon if (last) { 157748ec83bcSWill Deacon struct arm_smmu_cmdq_ent cmd = { 157848ec83bcSWill Deacon .opcode = CMDQ_OP_PRI_RESP, 157948ec83bcSWill Deacon .substream_valid = ssv, 158048ec83bcSWill Deacon .pri = { 158148ec83bcSWill Deacon .sid = sid, 158248ec83bcSWill Deacon .ssid = ssid, 158348ec83bcSWill Deacon .grpid = grpid, 158448ec83bcSWill Deacon .resp = PRI_RESP_DENY, 158548ec83bcSWill Deacon }, 158648ec83bcSWill Deacon }; 158748ec83bcSWill Deacon 158848ec83bcSWill Deacon arm_smmu_cmdq_issue_cmd(smmu, &cmd); 158948ec83bcSWill Deacon } 159048ec83bcSWill Deacon } 159148ec83bcSWill Deacon 1592b4163fb3SJean-Philippe Brucker static irqreturn_t arm_smmu_priq_thread(int irq, void *dev) 1593b4163fb3SJean-Philippe Brucker { 1594b4163fb3SJean-Philippe Brucker struct arm_smmu_device *smmu = dev; 1595b4163fb3SJean-Philippe Brucker struct arm_smmu_queue *q = &smmu->priq.q; 15967c288a5bSWill Deacon struct arm_smmu_ll_queue *llq = &q->llq; 1597b4163fb3SJean-Philippe Brucker u64 evt[PRIQ_ENT_DWORDS]; 1598b4163fb3SJean-Philippe Brucker 1599b4163fb3SJean-Philippe Brucker do { 1600b4163fb3SJean-Philippe Brucker while (!queue_remove_raw(q, evt)) 1601b4163fb3SJean-Philippe Brucker arm_smmu_handle_ppr(smmu, evt); 1602b4163fb3SJean-Philippe Brucker 16032a8868f1SWill Deacon if (queue_sync_prod_in(q) == -EOVERFLOW) 1604b4163fb3SJean-Philippe Brucker dev_err(smmu->dev, "PRIQ overflow detected -- requests lost\n"); 16057c288a5bSWill Deacon } while (!queue_empty(llq)); 1606b4163fb3SJean-Philippe Brucker 160748ec83bcSWill Deacon /* Sync our overflow flag, as we believe we're up to speed */ 16087c288a5bSWill Deacon llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) | 16097c288a5bSWill Deacon Q_IDX(llq, llq->cons); 16107c288a5bSWill Deacon queue_sync_cons_out(q); 161148ec83bcSWill Deacon return IRQ_HANDLED; 161248ec83bcSWill Deacon } 161348ec83bcSWill Deacon 161448ec83bcSWill Deacon static int arm_smmu_device_disable(struct arm_smmu_device *smmu); 161548ec83bcSWill Deacon 161648ec83bcSWill Deacon static irqreturn_t arm_smmu_gerror_handler(int irq, void *dev) 161748ec83bcSWill Deacon { 1618324ba108SPrem Mallappa u32 gerror, gerrorn, active; 161948ec83bcSWill Deacon struct arm_smmu_device *smmu = dev; 162048ec83bcSWill Deacon 162148ec83bcSWill Deacon gerror = readl_relaxed(smmu->base + ARM_SMMU_GERROR); 162248ec83bcSWill Deacon gerrorn = readl_relaxed(smmu->base + ARM_SMMU_GERRORN); 162348ec83bcSWill Deacon 1624324ba108SPrem Mallappa active = gerror ^ gerrorn; 1625324ba108SPrem Mallappa if (!(active & GERROR_ERR_MASK)) 162648ec83bcSWill Deacon return IRQ_NONE; /* No errors pending */ 162748ec83bcSWill Deacon 162848ec83bcSWill Deacon dev_warn(smmu->dev, 162948ec83bcSWill Deacon "unexpected global error reported (0x%08x), this could be serious\n", 1630324ba108SPrem Mallappa active); 163148ec83bcSWill Deacon 1632324ba108SPrem Mallappa if (active & GERROR_SFM_ERR) { 163348ec83bcSWill Deacon dev_err(smmu->dev, "device has entered Service Failure Mode!\n"); 163448ec83bcSWill Deacon arm_smmu_device_disable(smmu); 163548ec83bcSWill Deacon } 163648ec83bcSWill Deacon 1637324ba108SPrem Mallappa if (active & GERROR_MSI_GERROR_ABT_ERR) 163848ec83bcSWill Deacon dev_warn(smmu->dev, "GERROR MSI write aborted\n"); 163948ec83bcSWill Deacon 1640b4163fb3SJean-Philippe Brucker if (active & GERROR_MSI_PRIQ_ABT_ERR) 164148ec83bcSWill Deacon dev_warn(smmu->dev, "PRIQ MSI write aborted\n"); 164248ec83bcSWill Deacon 1643b4163fb3SJean-Philippe Brucker if (active & GERROR_MSI_EVTQ_ABT_ERR) 164448ec83bcSWill Deacon dev_warn(smmu->dev, "EVTQ MSI write aborted\n"); 164548ec83bcSWill Deacon 1646dce032a1SRobin Murphy if (active & GERROR_MSI_CMDQ_ABT_ERR) 164748ec83bcSWill Deacon dev_warn(smmu->dev, "CMDQ MSI write aborted\n"); 164848ec83bcSWill Deacon 1649324ba108SPrem Mallappa if (active & GERROR_PRIQ_ABT_ERR) 165048ec83bcSWill Deacon dev_err(smmu->dev, "PRIQ write aborted -- events may have been lost\n"); 165148ec83bcSWill Deacon 1652324ba108SPrem Mallappa if (active & GERROR_EVTQ_ABT_ERR) 165348ec83bcSWill Deacon dev_err(smmu->dev, "EVTQ write aborted -- events may have been lost\n"); 165448ec83bcSWill Deacon 1655324ba108SPrem Mallappa if (active & GERROR_CMDQ_ERR) 165648ec83bcSWill Deacon arm_smmu_cmdq_skip_err(smmu); 165748ec83bcSWill Deacon 165848ec83bcSWill Deacon writel(gerror, smmu->base + ARM_SMMU_GERRORN); 165948ec83bcSWill Deacon return IRQ_HANDLED; 166048ec83bcSWill Deacon } 166148ec83bcSWill Deacon 1662f935448aSGeetha Sowjanya static irqreturn_t arm_smmu_combined_irq_thread(int irq, void *dev) 1663f935448aSGeetha Sowjanya { 1664f935448aSGeetha Sowjanya struct arm_smmu_device *smmu = dev; 1665f935448aSGeetha Sowjanya 1666f935448aSGeetha Sowjanya arm_smmu_evtq_thread(irq, dev); 1667f935448aSGeetha Sowjanya if (smmu->features & ARM_SMMU_FEAT_PRI) 1668f935448aSGeetha Sowjanya arm_smmu_priq_thread(irq, dev); 1669f935448aSGeetha Sowjanya 1670f935448aSGeetha Sowjanya return IRQ_HANDLED; 1671f935448aSGeetha Sowjanya } 1672f935448aSGeetha Sowjanya 1673f935448aSGeetha Sowjanya static irqreturn_t arm_smmu_combined_irq_handler(int irq, void *dev) 1674f935448aSGeetha Sowjanya { 1675f935448aSGeetha Sowjanya arm_smmu_gerror_handler(irq, dev); 1676f935448aSGeetha Sowjanya return IRQ_WAKE_THREAD; 1677f935448aSGeetha Sowjanya } 1678f935448aSGeetha Sowjanya 16799ce27afcSJean-Philippe Brucker static void 16809ce27afcSJean-Philippe Brucker arm_smmu_atc_inv_to_cmd(int ssid, unsigned long iova, size_t size, 16819ce27afcSJean-Philippe Brucker struct arm_smmu_cmdq_ent *cmd) 16829ce27afcSJean-Philippe Brucker { 16839ce27afcSJean-Philippe Brucker size_t log2_span; 16849ce27afcSJean-Philippe Brucker size_t span_mask; 16859ce27afcSJean-Philippe Brucker /* ATC invalidates are always on 4096-bytes pages */ 16869ce27afcSJean-Philippe Brucker size_t inval_grain_shift = 12; 16879ce27afcSJean-Philippe Brucker unsigned long page_start, page_end; 16889ce27afcSJean-Philippe Brucker 16892f7e8c55SJean-Philippe Brucker /* 16902f7e8c55SJean-Philippe Brucker * ATS and PASID: 16912f7e8c55SJean-Philippe Brucker * 16922f7e8c55SJean-Philippe Brucker * If substream_valid is clear, the PCIe TLP is sent without a PASID 16932f7e8c55SJean-Philippe Brucker * prefix. In that case all ATC entries within the address range are 16942f7e8c55SJean-Philippe Brucker * invalidated, including those that were requested with a PASID! There 16952f7e8c55SJean-Philippe Brucker * is no way to invalidate only entries without PASID. 16962f7e8c55SJean-Philippe Brucker * 16972f7e8c55SJean-Philippe Brucker * When using STRTAB_STE_1_S1DSS_SSID0 (reserving CD 0 for non-PASID 16982f7e8c55SJean-Philippe Brucker * traffic), translation requests without PASID create ATC entries 16992f7e8c55SJean-Philippe Brucker * without PASID, which must be invalidated with substream_valid clear. 17002f7e8c55SJean-Philippe Brucker * This has the unpleasant side-effect of invalidating all PASID-tagged 17012f7e8c55SJean-Philippe Brucker * ATC entries within the address range. 17022f7e8c55SJean-Philippe Brucker */ 17039ce27afcSJean-Philippe Brucker *cmd = (struct arm_smmu_cmdq_ent) { 17049ce27afcSJean-Philippe Brucker .opcode = CMDQ_OP_ATC_INV, 17059ce27afcSJean-Philippe Brucker .substream_valid = !!ssid, 17069ce27afcSJean-Philippe Brucker .atc.ssid = ssid, 17079ce27afcSJean-Philippe Brucker }; 17089ce27afcSJean-Philippe Brucker 17099ce27afcSJean-Philippe Brucker if (!size) { 17109ce27afcSJean-Philippe Brucker cmd->atc.size = ATC_INV_SIZE_ALL; 17119ce27afcSJean-Philippe Brucker return; 17129ce27afcSJean-Philippe Brucker } 17139ce27afcSJean-Philippe Brucker 17149ce27afcSJean-Philippe Brucker page_start = iova >> inval_grain_shift; 17159ce27afcSJean-Philippe Brucker page_end = (iova + size - 1) >> inval_grain_shift; 17169ce27afcSJean-Philippe Brucker 17179ce27afcSJean-Philippe Brucker /* 17189ce27afcSJean-Philippe Brucker * In an ATS Invalidate Request, the address must be aligned on the 17199ce27afcSJean-Philippe Brucker * range size, which must be a power of two number of page sizes. We 17209ce27afcSJean-Philippe Brucker * thus have to choose between grossly over-invalidating the region, or 17219ce27afcSJean-Philippe Brucker * splitting the invalidation into multiple commands. For simplicity 17229ce27afcSJean-Philippe Brucker * we'll go with the first solution, but should refine it in the future 17239ce27afcSJean-Philippe Brucker * if multiple commands are shown to be more efficient. 17249ce27afcSJean-Philippe Brucker * 17259ce27afcSJean-Philippe Brucker * Find the smallest power of two that covers the range. The most 17269ce27afcSJean-Philippe Brucker * significant differing bit between the start and end addresses, 17279ce27afcSJean-Philippe Brucker * fls(start ^ end), indicates the required span. For example: 17289ce27afcSJean-Philippe Brucker * 17299ce27afcSJean-Philippe Brucker * We want to invalidate pages [8; 11]. This is already the ideal range: 17309ce27afcSJean-Philippe Brucker * x = 0b1000 ^ 0b1011 = 0b11 17319ce27afcSJean-Philippe Brucker * span = 1 << fls(x) = 4 17329ce27afcSJean-Philippe Brucker * 17339ce27afcSJean-Philippe Brucker * To invalidate pages [7; 10], we need to invalidate [0; 15]: 17349ce27afcSJean-Philippe Brucker * x = 0b0111 ^ 0b1010 = 0b1101 17359ce27afcSJean-Philippe Brucker * span = 1 << fls(x) = 16 17369ce27afcSJean-Philippe Brucker */ 17379ce27afcSJean-Philippe Brucker log2_span = fls_long(page_start ^ page_end); 17389ce27afcSJean-Philippe Brucker span_mask = (1ULL << log2_span) - 1; 17399ce27afcSJean-Philippe Brucker 17409ce27afcSJean-Philippe Brucker page_start &= ~span_mask; 17419ce27afcSJean-Philippe Brucker 17429ce27afcSJean-Philippe Brucker cmd->atc.addr = page_start << inval_grain_shift; 17439ce27afcSJean-Philippe Brucker cmd->atc.size = log2_span; 17449ce27afcSJean-Philippe Brucker } 17459ce27afcSJean-Philippe Brucker 17469e773aeeSRob Herring static int arm_smmu_atc_inv_master(struct arm_smmu_master *master) 17479ce27afcSJean-Philippe Brucker { 17489ce27afcSJean-Philippe Brucker int i; 17499e773aeeSRob Herring struct arm_smmu_cmdq_ent cmd; 17509ce27afcSJean-Philippe Brucker 17519e773aeeSRob Herring arm_smmu_atc_inv_to_cmd(0, 0, 0, &cmd); 17529ce27afcSJean-Philippe Brucker 1753cdf315f9SJean-Philippe Brucker for (i = 0; i < master->num_streams; i++) { 1754cdf315f9SJean-Philippe Brucker cmd.atc.sid = master->streams[i].id; 17559e773aeeSRob Herring arm_smmu_cmdq_issue_cmd(master->smmu, &cmd); 17569ce27afcSJean-Philippe Brucker } 17579ce27afcSJean-Philippe Brucker 17589ce27afcSJean-Philippe Brucker return arm_smmu_cmdq_issue_sync(master->smmu); 17599ce27afcSJean-Philippe Brucker } 17609ce27afcSJean-Philippe Brucker 17612f7e8c55SJean-Philippe Brucker int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid, 17622f7e8c55SJean-Philippe Brucker unsigned long iova, size_t size) 17639ce27afcSJean-Philippe Brucker { 17649e773aeeSRob Herring int i; 17659ce27afcSJean-Philippe Brucker unsigned long flags; 17669ce27afcSJean-Philippe Brucker struct arm_smmu_cmdq_ent cmd; 17679ce27afcSJean-Philippe Brucker struct arm_smmu_master *master; 17689e773aeeSRob Herring struct arm_smmu_cmdq_batch cmds = {}; 17699ce27afcSJean-Philippe Brucker 17709ce27afcSJean-Philippe Brucker if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS)) 17719ce27afcSJean-Philippe Brucker return 0; 17729ce27afcSJean-Philippe Brucker 1773cdb8a3c3SWill Deacon /* 1774cdb8a3c3SWill Deacon * Ensure that we've completed prior invalidation of the main TLBs 1775cdb8a3c3SWill Deacon * before we read 'nr_ats_masters' in case of a concurrent call to 1776cdb8a3c3SWill Deacon * arm_smmu_enable_ats(): 1777cdb8a3c3SWill Deacon * 1778cdb8a3c3SWill Deacon * // unmap() // arm_smmu_enable_ats() 1779cdb8a3c3SWill Deacon * TLBI+SYNC atomic_inc(&nr_ats_masters); 1780cdb8a3c3SWill Deacon * smp_mb(); [...] 1781cdb8a3c3SWill Deacon * atomic_read(&nr_ats_masters); pci_enable_ats() // writel() 1782cdb8a3c3SWill Deacon * 1783cdb8a3c3SWill Deacon * Ensures that we always see the incremented 'nr_ats_masters' count if 1784cdb8a3c3SWill Deacon * ATS was enabled at the PCI device before completion of the TLBI. 1785cdb8a3c3SWill Deacon */ 1786cdb8a3c3SWill Deacon smp_mb(); 1787cdb8a3c3SWill Deacon if (!atomic_read(&smmu_domain->nr_ats_masters)) 1788cdb8a3c3SWill Deacon return 0; 1789cdb8a3c3SWill Deacon 17909ce27afcSJean-Philippe Brucker arm_smmu_atc_inv_to_cmd(ssid, iova, size, &cmd); 17919ce27afcSJean-Philippe Brucker 17929ce27afcSJean-Philippe Brucker spin_lock_irqsave(&smmu_domain->devices_lock, flags); 17939e773aeeSRob Herring list_for_each_entry(master, &smmu_domain->devices, domain_head) { 17949e773aeeSRob Herring if (!master->ats_enabled) 17959e773aeeSRob Herring continue; 17969e773aeeSRob Herring 1797cdf315f9SJean-Philippe Brucker for (i = 0; i < master->num_streams; i++) { 1798cdf315f9SJean-Philippe Brucker cmd.atc.sid = master->streams[i].id; 17999e773aeeSRob Herring arm_smmu_cmdq_batch_add(smmu_domain->smmu, &cmds, &cmd); 18009e773aeeSRob Herring } 18019e773aeeSRob Herring } 18029ce27afcSJean-Philippe Brucker spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); 18039ce27afcSJean-Philippe Brucker 18049e773aeeSRob Herring return arm_smmu_cmdq_batch_submit(smmu_domain->smmu, &cmds); 18059ce27afcSJean-Philippe Brucker } 18069ce27afcSJean-Philippe Brucker 180748ec83bcSWill Deacon /* IO_PGTABLE API */ 180848ec83bcSWill Deacon static void arm_smmu_tlb_inv_context(void *cookie) 180948ec83bcSWill Deacon { 181048ec83bcSWill Deacon struct arm_smmu_domain *smmu_domain = cookie; 181148ec83bcSWill Deacon struct arm_smmu_device *smmu = smmu_domain->smmu; 181248ec83bcSWill Deacon struct arm_smmu_cmdq_ent cmd; 181348ec83bcSWill Deacon 18149662b99aSZhen Lei /* 18159662b99aSZhen Lei * NOTE: when io-pgtable is in non-strict mode, we may get here with 18169662b99aSZhen Lei * PTEs previously cleared by unmaps on the current CPU not yet visible 1817587e6c10SWill Deacon * to the SMMU. We are relying on the dma_wmb() implicit during cmd 1818587e6c10SWill Deacon * insertion to guarantee those are observed before the TLBI. Do be 1819587e6c10SWill Deacon * careful, 007. 18209662b99aSZhen Lei */ 18213e630336SJean-Philippe Brucker if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) { 18223e630336SJean-Philippe Brucker arm_smmu_tlb_inv_asid(smmu, smmu_domain->s1_cfg.cd.asid); 18233e630336SJean-Philippe Brucker } else { 18243e630336SJean-Philippe Brucker cmd.opcode = CMDQ_OP_TLBI_S12_VMALL; 18253e630336SJean-Philippe Brucker cmd.tlbi.vmid = smmu_domain->s2_cfg.vmid; 182648ec83bcSWill Deacon arm_smmu_cmdq_issue_cmd(smmu, &cmd); 18275e731073SAndrew Murray arm_smmu_cmdq_issue_sync(smmu); 18283e630336SJean-Philippe Brucker } 1829353e3cf8SWill Deacon arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0); 183048ec83bcSWill Deacon } 183148ec83bcSWill Deacon 1832eba8d2f8SJean-Philippe Brucker static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd, 1833eba8d2f8SJean-Philippe Brucker unsigned long iova, size_t size, 1834eba8d2f8SJean-Philippe Brucker size_t granule, 18352af2e72bSWill Deacon struct arm_smmu_domain *smmu_domain) 183648ec83bcSWill Deacon { 183748ec83bcSWill Deacon struct arm_smmu_device *smmu = smmu_domain->smmu; 1838eba8d2f8SJean-Philippe Brucker unsigned long end = iova + size, num_pages = 0, tg = 0; 18396a481a95SRob Herring size_t inv_range = granule; 18404ce8da45SJean-Philippe Brucker struct arm_smmu_cmdq_batch cmds = {}; 184148ec83bcSWill Deacon 18427314ca86SWill Deacon if (!size) 18437314ca86SWill Deacon return; 18447314ca86SWill Deacon 18456a481a95SRob Herring if (smmu->features & ARM_SMMU_FEAT_RANGE_INV) { 18466a481a95SRob Herring /* Get the leaf page size */ 18476a481a95SRob Herring tg = __ffs(smmu_domain->domain.pgsize_bitmap); 18486a481a95SRob Herring 18496a481a95SRob Herring /* Convert page size of 12,14,16 (log2) to 1,2,3 */ 1850eba8d2f8SJean-Philippe Brucker cmd->tlbi.tg = (tg - 10) / 2; 18516a481a95SRob Herring 18526a481a95SRob Herring /* Determine what level the granule is at */ 1853eba8d2f8SJean-Philippe Brucker cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3)); 18546a481a95SRob Herring 18556a481a95SRob Herring num_pages = size >> tg; 18566a481a95SRob Herring } 18576a481a95SRob Herring 18582af2e72bSWill Deacon while (iova < end) { 18596a481a95SRob Herring if (smmu->features & ARM_SMMU_FEAT_RANGE_INV) { 18606a481a95SRob Herring /* 18616a481a95SRob Herring * On each iteration of the loop, the range is 5 bits 18626a481a95SRob Herring * worth of the aligned size remaining. 18636a481a95SRob Herring * The range in pages is: 18646a481a95SRob Herring * 18656a481a95SRob Herring * range = (num_pages & (0x1f << __ffs(num_pages))) 18666a481a95SRob Herring */ 18676a481a95SRob Herring unsigned long scale, num; 18686a481a95SRob Herring 18696a481a95SRob Herring /* Determine the power of 2 multiple number of pages */ 18706a481a95SRob Herring scale = __ffs(num_pages); 1871eba8d2f8SJean-Philippe Brucker cmd->tlbi.scale = scale; 18726a481a95SRob Herring 18736a481a95SRob Herring /* Determine how many chunks of 2^scale size we have */ 18746a481a95SRob Herring num = (num_pages >> scale) & CMDQ_TLBI_RANGE_NUM_MAX; 1875eba8d2f8SJean-Philippe Brucker cmd->tlbi.num = num - 1; 18766a481a95SRob Herring 18776a481a95SRob Herring /* range is num * 2^scale * pgsize */ 18786a481a95SRob Herring inv_range = num << (scale + tg); 18796a481a95SRob Herring 18806a481a95SRob Herring /* Clear out the lower order bits for the next iteration */ 18816a481a95SRob Herring num_pages -= num << scale; 188248ec83bcSWill Deacon } 188348ec83bcSWill Deacon 1884eba8d2f8SJean-Philippe Brucker cmd->tlbi.addr = iova; 1885eba8d2f8SJean-Philippe Brucker arm_smmu_cmdq_batch_add(smmu, &cmds, cmd); 18866a481a95SRob Herring iova += inv_range; 18872af2e72bSWill Deacon } 18884ce8da45SJean-Philippe Brucker arm_smmu_cmdq_batch_submit(smmu, &cmds); 1889eba8d2f8SJean-Philippe Brucker } 1890eba8d2f8SJean-Philippe Brucker 1891eba8d2f8SJean-Philippe Brucker static void arm_smmu_tlb_inv_range_domain(unsigned long iova, size_t size, 1892eba8d2f8SJean-Philippe Brucker size_t granule, bool leaf, 1893eba8d2f8SJean-Philippe Brucker struct arm_smmu_domain *smmu_domain) 1894eba8d2f8SJean-Philippe Brucker { 1895eba8d2f8SJean-Philippe Brucker struct arm_smmu_cmdq_ent cmd = { 1896eba8d2f8SJean-Philippe Brucker .tlbi = { 1897eba8d2f8SJean-Philippe Brucker .leaf = leaf, 1898eba8d2f8SJean-Philippe Brucker }, 1899eba8d2f8SJean-Philippe Brucker }; 1900eba8d2f8SJean-Philippe Brucker 1901eba8d2f8SJean-Philippe Brucker if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) { 19029111aebfSJean-Philippe Brucker cmd.opcode = smmu_domain->smmu->features & ARM_SMMU_FEAT_E2H ? 19039111aebfSJean-Philippe Brucker CMDQ_OP_TLBI_EL2_VA : CMDQ_OP_TLBI_NH_VA; 1904eba8d2f8SJean-Philippe Brucker cmd.tlbi.asid = smmu_domain->s1_cfg.cd.asid; 1905eba8d2f8SJean-Philippe Brucker } else { 1906eba8d2f8SJean-Philippe Brucker cmd.opcode = CMDQ_OP_TLBI_S2_IPA; 1907eba8d2f8SJean-Philippe Brucker cmd.tlbi.vmid = smmu_domain->s2_cfg.vmid; 1908eba8d2f8SJean-Philippe Brucker } 1909eba8d2f8SJean-Philippe Brucker __arm_smmu_tlb_inv_range(&cmd, iova, size, granule, smmu_domain); 1910353e3cf8SWill Deacon 1911353e3cf8SWill Deacon /* 1912353e3cf8SWill Deacon * Unfortunately, this can't be leaf-only since we may have 1913353e3cf8SWill Deacon * zapped an entire table. 1914353e3cf8SWill Deacon */ 1915eba8d2f8SJean-Philippe Brucker arm_smmu_atc_inv_domain(smmu_domain, 0, iova, size); 191648ec83bcSWill Deacon } 191748ec83bcSWill Deacon 191851d113c3SJean-Philippe Brucker void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid, 191951d113c3SJean-Philippe Brucker size_t granule, bool leaf, 192051d113c3SJean-Philippe Brucker struct arm_smmu_domain *smmu_domain) 192151d113c3SJean-Philippe Brucker { 192251d113c3SJean-Philippe Brucker struct arm_smmu_cmdq_ent cmd = { 19239111aebfSJean-Philippe Brucker .opcode = smmu_domain->smmu->features & ARM_SMMU_FEAT_E2H ? 19249111aebfSJean-Philippe Brucker CMDQ_OP_TLBI_EL2_VA : CMDQ_OP_TLBI_NH_VA, 192551d113c3SJean-Philippe Brucker .tlbi = { 192651d113c3SJean-Philippe Brucker .asid = asid, 192751d113c3SJean-Philippe Brucker .leaf = leaf, 192851d113c3SJean-Philippe Brucker }, 192951d113c3SJean-Philippe Brucker }; 193051d113c3SJean-Philippe Brucker 193151d113c3SJean-Philippe Brucker __arm_smmu_tlb_inv_range(&cmd, iova, size, granule, smmu_domain); 193251d113c3SJean-Philippe Brucker } 193351d113c3SJean-Philippe Brucker 19343951c41aSWill Deacon static void arm_smmu_tlb_inv_page_nosync(struct iommu_iotlb_gather *gather, 19353951c41aSWill Deacon unsigned long iova, size_t granule, 1936abfd6fe0SWill Deacon void *cookie) 1937abfd6fe0SWill Deacon { 19382af2e72bSWill Deacon struct arm_smmu_domain *smmu_domain = cookie; 19392af2e72bSWill Deacon struct iommu_domain *domain = &smmu_domain->domain; 19402af2e72bSWill Deacon 19412af2e72bSWill Deacon iommu_iotlb_gather_add_page(domain, gather, iova, granule); 1942abfd6fe0SWill Deacon } 1943abfd6fe0SWill Deacon 194405aed941SWill Deacon static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size, 194505aed941SWill Deacon size_t granule, void *cookie) 194605aed941SWill Deacon { 1947eba8d2f8SJean-Philippe Brucker arm_smmu_tlb_inv_range_domain(iova, size, granule, false, cookie); 194805aed941SWill Deacon } 194905aed941SWill Deacon 1950298f7889SWill Deacon static const struct iommu_flush_ops arm_smmu_flush_ops = { 195148ec83bcSWill Deacon .tlb_flush_all = arm_smmu_tlb_inv_context, 195205aed941SWill Deacon .tlb_flush_walk = arm_smmu_tlb_inv_walk, 1953abfd6fe0SWill Deacon .tlb_add_page = arm_smmu_tlb_inv_page_nosync, 195448ec83bcSWill Deacon }; 195548ec83bcSWill Deacon 195648ec83bcSWill Deacon /* IOMMU API */ 195748ec83bcSWill Deacon static bool arm_smmu_capable(enum iommu_cap cap) 195848ec83bcSWill Deacon { 195948ec83bcSWill Deacon switch (cap) { 196048ec83bcSWill Deacon case IOMMU_CAP_CACHE_COHERENCY: 196148ec83bcSWill Deacon return true; 196248ec83bcSWill Deacon case IOMMU_CAP_NOEXEC: 196348ec83bcSWill Deacon return true; 196448ec83bcSWill Deacon default: 196548ec83bcSWill Deacon return false; 196648ec83bcSWill Deacon } 196748ec83bcSWill Deacon } 196848ec83bcSWill Deacon 196948ec83bcSWill Deacon static struct iommu_domain *arm_smmu_domain_alloc(unsigned type) 197048ec83bcSWill Deacon { 197148ec83bcSWill Deacon struct arm_smmu_domain *smmu_domain; 197248ec83bcSWill Deacon 1973beb3c6a0SWill Deacon if (type != IOMMU_DOMAIN_UNMANAGED && 1974beb3c6a0SWill Deacon type != IOMMU_DOMAIN_DMA && 1975beb3c6a0SWill Deacon type != IOMMU_DOMAIN_IDENTITY) 197648ec83bcSWill Deacon return NULL; 197748ec83bcSWill Deacon 197848ec83bcSWill Deacon /* 197948ec83bcSWill Deacon * Allocate the domain and initialise some of its data structures. 198048ec83bcSWill Deacon * We can't really do anything meaningful until we've added a 198148ec83bcSWill Deacon * master. 198248ec83bcSWill Deacon */ 198348ec83bcSWill Deacon smmu_domain = kzalloc(sizeof(*smmu_domain), GFP_KERNEL); 198448ec83bcSWill Deacon if (!smmu_domain) 198548ec83bcSWill Deacon return NULL; 198648ec83bcSWill Deacon 19879adb9594SRobin Murphy if (type == IOMMU_DOMAIN_DMA && 19889adb9594SRobin Murphy iommu_get_dma_cookie(&smmu_domain->domain)) { 19899adb9594SRobin Murphy kfree(smmu_domain); 19909adb9594SRobin Murphy return NULL; 19919adb9594SRobin Murphy } 19929adb9594SRobin Murphy 199348ec83bcSWill Deacon mutex_init(&smmu_domain->init_mutex); 19942a7e62f5SJean-Philippe Brucker INIT_LIST_HEAD(&smmu_domain->devices); 19952a7e62f5SJean-Philippe Brucker spin_lock_init(&smmu_domain->devices_lock); 199632784a95SJean-Philippe Brucker INIT_LIST_HEAD(&smmu_domain->mmu_notifiers); 19972a7e62f5SJean-Philippe Brucker 199848ec83bcSWill Deacon return &smmu_domain->domain; 199948ec83bcSWill Deacon } 200048ec83bcSWill Deacon 200148ec83bcSWill Deacon static int arm_smmu_bitmap_alloc(unsigned long *map, int span) 200248ec83bcSWill Deacon { 200348ec83bcSWill Deacon int idx, size = 1 << span; 200448ec83bcSWill Deacon 200548ec83bcSWill Deacon do { 200648ec83bcSWill Deacon idx = find_first_zero_bit(map, size); 200748ec83bcSWill Deacon if (idx == size) 200848ec83bcSWill Deacon return -ENOSPC; 200948ec83bcSWill Deacon } while (test_and_set_bit(idx, map)); 201048ec83bcSWill Deacon 201148ec83bcSWill Deacon return idx; 201248ec83bcSWill Deacon } 201348ec83bcSWill Deacon 201448ec83bcSWill Deacon static void arm_smmu_bitmap_free(unsigned long *map, int idx) 201548ec83bcSWill Deacon { 201648ec83bcSWill Deacon clear_bit(idx, map); 201748ec83bcSWill Deacon } 201848ec83bcSWill Deacon 201948ec83bcSWill Deacon static void arm_smmu_domain_free(struct iommu_domain *domain) 202048ec83bcSWill Deacon { 202148ec83bcSWill Deacon struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); 202248ec83bcSWill Deacon struct arm_smmu_device *smmu = smmu_domain->smmu; 202348ec83bcSWill Deacon 20249adb9594SRobin Murphy iommu_put_dma_cookie(domain); 202548ec83bcSWill Deacon free_io_pgtable_ops(smmu_domain->pgtbl_ops); 202648ec83bcSWill Deacon 202748ec83bcSWill Deacon /* Free the CD and ASID, if we allocated them */ 202848ec83bcSWill Deacon if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) { 202948ec83bcSWill Deacon struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg; 203048ec83bcSWill Deacon 20313f1ce8e8SJean-Philippe Brucker /* Prevent SVA from touching the CD while we're freeing it */ 20323f1ce8e8SJean-Philippe Brucker mutex_lock(&arm_smmu_asid_lock); 20330299a1a8SJean-Philippe Brucker if (cfg->cdcfg.cdtab) 2034a557aff0SJean-Philippe Brucker arm_smmu_free_cd_tables(smmu_domain); 20350299a1a8SJean-Philippe Brucker arm_smmu_free_asid(&cfg->cd); 20363f1ce8e8SJean-Philippe Brucker mutex_unlock(&arm_smmu_asid_lock); 203748ec83bcSWill Deacon } else { 203848ec83bcSWill Deacon struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg; 203948ec83bcSWill Deacon if (cfg->vmid) 204048ec83bcSWill Deacon arm_smmu_bitmap_free(smmu->vmid_map, cfg->vmid); 204148ec83bcSWill Deacon } 204248ec83bcSWill Deacon 204348ec83bcSWill Deacon kfree(smmu_domain); 204448ec83bcSWill Deacon } 204548ec83bcSWill Deacon 204648ec83bcSWill Deacon static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, 20472505ec6fSJean-Philippe Brucker struct arm_smmu_master *master, 204848ec83bcSWill Deacon struct io_pgtable_cfg *pgtbl_cfg) 204948ec83bcSWill Deacon { 205048ec83bcSWill Deacon int ret; 20510299a1a8SJean-Philippe Brucker u32 asid; 205248ec83bcSWill Deacon struct arm_smmu_device *smmu = smmu_domain->smmu; 205348ec83bcSWill Deacon struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg; 2054fb485eb1SRobin Murphy typeof(&pgtbl_cfg->arm_lpae_s1_cfg.tcr) tcr = &pgtbl_cfg->arm_lpae_s1_cfg.tcr; 205548ec83bcSWill Deacon 20563f1ce8e8SJean-Philippe Brucker refcount_set(&cfg->cd.refs, 1); 20573f1ce8e8SJean-Philippe Brucker 20583f1ce8e8SJean-Philippe Brucker /* Prevent SVA from modifying the ASID until it is written to the CD */ 20593f1ce8e8SJean-Philippe Brucker mutex_lock(&arm_smmu_asid_lock); 20603f1ce8e8SJean-Philippe Brucker ret = xa_alloc(&arm_smmu_asid_xa, &asid, &cfg->cd, 20610299a1a8SJean-Philippe Brucker XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL); 20620299a1a8SJean-Philippe Brucker if (ret) 20633f1ce8e8SJean-Philippe Brucker goto out_unlock; 206448ec83bcSWill Deacon 20652505ec6fSJean-Philippe Brucker cfg->s1cdmax = master->ssid_bits; 20662505ec6fSJean-Philippe Brucker 2067395ad89dSJean-Philippe Brucker smmu_domain->stall_enabled = master->stall_enabled; 2068395ad89dSJean-Philippe Brucker 2069a557aff0SJean-Philippe Brucker ret = arm_smmu_alloc_cd_tables(smmu_domain); 2070a557aff0SJean-Philippe Brucker if (ret) 207148ec83bcSWill Deacon goto out_free_asid; 207248ec83bcSWill Deacon 2073c0733a2cSWill Deacon cfg->cd.asid = (u16)asid; 2074d1e5f26fSRobin Murphy cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr; 2075fb485eb1SRobin Murphy cfg->cd.tcr = FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, tcr->tsz) | 2076fb485eb1SRobin Murphy FIELD_PREP(CTXDESC_CD_0_TCR_TG0, tcr->tg) | 2077fb485eb1SRobin Murphy FIELD_PREP(CTXDESC_CD_0_TCR_IRGN0, tcr->irgn) | 2078fb485eb1SRobin Murphy FIELD_PREP(CTXDESC_CD_0_TCR_ORGN0, tcr->orgn) | 2079fb485eb1SRobin Murphy FIELD_PREP(CTXDESC_CD_0_TCR_SH0, tcr->sh) | 2080fb485eb1SRobin Murphy FIELD_PREP(CTXDESC_CD_0_TCR_IPS, tcr->ips) | 2081fb485eb1SRobin Murphy CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64; 2082205577abSRobin Murphy cfg->cd.mair = pgtbl_cfg->arm_lpae_s1_cfg.mair; 2083492ddc79SJean-Philippe Brucker 2084492ddc79SJean-Philippe Brucker /* 2085492ddc79SJean-Philippe Brucker * Note that this will end up calling arm_smmu_sync_cd() before 2086492ddc79SJean-Philippe Brucker * the master has been added to the devices list for this domain. 2087492ddc79SJean-Philippe Brucker * This isn't an issue because the STE hasn't been installed yet. 2088492ddc79SJean-Philippe Brucker */ 2089492ddc79SJean-Philippe Brucker ret = arm_smmu_write_ctx_desc(smmu_domain, 0, &cfg->cd); 2090492ddc79SJean-Philippe Brucker if (ret) 2091492ddc79SJean-Philippe Brucker goto out_free_cd_tables; 2092492ddc79SJean-Philippe Brucker 20933f1ce8e8SJean-Philippe Brucker mutex_unlock(&arm_smmu_asid_lock); 209448ec83bcSWill Deacon return 0; 209548ec83bcSWill Deacon 2096492ddc79SJean-Philippe Brucker out_free_cd_tables: 2097492ddc79SJean-Philippe Brucker arm_smmu_free_cd_tables(smmu_domain); 209848ec83bcSWill Deacon out_free_asid: 20990299a1a8SJean-Philippe Brucker arm_smmu_free_asid(&cfg->cd); 21003f1ce8e8SJean-Philippe Brucker out_unlock: 21013f1ce8e8SJean-Philippe Brucker mutex_unlock(&arm_smmu_asid_lock); 210248ec83bcSWill Deacon return ret; 210348ec83bcSWill Deacon } 210448ec83bcSWill Deacon 210548ec83bcSWill Deacon static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain, 21062505ec6fSJean-Philippe Brucker struct arm_smmu_master *master, 210748ec83bcSWill Deacon struct io_pgtable_cfg *pgtbl_cfg) 210848ec83bcSWill Deacon { 2109c0733a2cSWill Deacon int vmid; 211048ec83bcSWill Deacon struct arm_smmu_device *smmu = smmu_domain->smmu; 211148ec83bcSWill Deacon struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg; 2112ac4b80e5SWill Deacon typeof(&pgtbl_cfg->arm_lpae_s2_cfg.vtcr) vtcr; 211348ec83bcSWill Deacon 211448ec83bcSWill Deacon vmid = arm_smmu_bitmap_alloc(smmu->vmid_map, smmu->vmid_bits); 2115287980e4SArnd Bergmann if (vmid < 0) 211648ec83bcSWill Deacon return vmid; 211748ec83bcSWill Deacon 2118ac4b80e5SWill Deacon vtcr = &pgtbl_cfg->arm_lpae_s2_cfg.vtcr; 2119c0733a2cSWill Deacon cfg->vmid = (u16)vmid; 212048ec83bcSWill Deacon cfg->vttbr = pgtbl_cfg->arm_lpae_s2_cfg.vttbr; 2121ac4b80e5SWill Deacon cfg->vtcr = FIELD_PREP(STRTAB_STE_2_VTCR_S2T0SZ, vtcr->tsz) | 2122ac4b80e5SWill Deacon FIELD_PREP(STRTAB_STE_2_VTCR_S2SL0, vtcr->sl) | 2123ac4b80e5SWill Deacon FIELD_PREP(STRTAB_STE_2_VTCR_S2IR0, vtcr->irgn) | 2124ac4b80e5SWill Deacon FIELD_PREP(STRTAB_STE_2_VTCR_S2OR0, vtcr->orgn) | 2125ac4b80e5SWill Deacon FIELD_PREP(STRTAB_STE_2_VTCR_S2SH0, vtcr->sh) | 2126ac4b80e5SWill Deacon FIELD_PREP(STRTAB_STE_2_VTCR_S2TG, vtcr->tg) | 2127ac4b80e5SWill Deacon FIELD_PREP(STRTAB_STE_2_VTCR_S2PS, vtcr->ps); 212848ec83bcSWill Deacon return 0; 212948ec83bcSWill Deacon } 213048ec83bcSWill Deacon 21312505ec6fSJean-Philippe Brucker static int arm_smmu_domain_finalise(struct iommu_domain *domain, 21322505ec6fSJean-Philippe Brucker struct arm_smmu_master *master) 213348ec83bcSWill Deacon { 213448ec83bcSWill Deacon int ret; 213548ec83bcSWill Deacon unsigned long ias, oas; 213648ec83bcSWill Deacon enum io_pgtable_fmt fmt; 213748ec83bcSWill Deacon struct io_pgtable_cfg pgtbl_cfg; 213848ec83bcSWill Deacon struct io_pgtable_ops *pgtbl_ops; 213948ec83bcSWill Deacon int (*finalise_stage_fn)(struct arm_smmu_domain *, 21402505ec6fSJean-Philippe Brucker struct arm_smmu_master *, 214148ec83bcSWill Deacon struct io_pgtable_cfg *); 214248ec83bcSWill Deacon struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); 214348ec83bcSWill Deacon struct arm_smmu_device *smmu = smmu_domain->smmu; 214448ec83bcSWill Deacon 2145beb3c6a0SWill Deacon if (domain->type == IOMMU_DOMAIN_IDENTITY) { 2146beb3c6a0SWill Deacon smmu_domain->stage = ARM_SMMU_DOMAIN_BYPASS; 2147beb3c6a0SWill Deacon return 0; 2148beb3c6a0SWill Deacon } 2149beb3c6a0SWill Deacon 215048ec83bcSWill Deacon /* Restrict the stage to what we can actually support */ 215148ec83bcSWill Deacon if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1)) 215248ec83bcSWill Deacon smmu_domain->stage = ARM_SMMU_DOMAIN_S2; 215348ec83bcSWill Deacon if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S2)) 215448ec83bcSWill Deacon smmu_domain->stage = ARM_SMMU_DOMAIN_S1; 215548ec83bcSWill Deacon 215648ec83bcSWill Deacon switch (smmu_domain->stage) { 215748ec83bcSWill Deacon case ARM_SMMU_DOMAIN_S1: 2158dcd189e6SRobin Murphy ias = (smmu->features & ARM_SMMU_FEAT_VAX) ? 52 : 48; 2159dcd189e6SRobin Murphy ias = min_t(unsigned long, ias, VA_BITS); 216048ec83bcSWill Deacon oas = smmu->ias; 216148ec83bcSWill Deacon fmt = ARM_64_LPAE_S1; 216248ec83bcSWill Deacon finalise_stage_fn = arm_smmu_domain_finalise_s1; 216348ec83bcSWill Deacon break; 216448ec83bcSWill Deacon case ARM_SMMU_DOMAIN_NESTED: 216548ec83bcSWill Deacon case ARM_SMMU_DOMAIN_S2: 216648ec83bcSWill Deacon ias = smmu->ias; 216748ec83bcSWill Deacon oas = smmu->oas; 216848ec83bcSWill Deacon fmt = ARM_64_LPAE_S2; 216948ec83bcSWill Deacon finalise_stage_fn = arm_smmu_domain_finalise_s2; 217048ec83bcSWill Deacon break; 217148ec83bcSWill Deacon default: 217248ec83bcSWill Deacon return -EINVAL; 217348ec83bcSWill Deacon } 217448ec83bcSWill Deacon 217548ec83bcSWill Deacon pgtbl_cfg = (struct io_pgtable_cfg) { 2176d5466357SRobin Murphy .pgsize_bitmap = smmu->pgsize_bitmap, 217748ec83bcSWill Deacon .ias = ias, 217848ec83bcSWill Deacon .oas = oas, 21794f41845bSWill Deacon .coherent_walk = smmu->features & ARM_SMMU_FEAT_COHERENCY, 2180298f7889SWill Deacon .tlb = &arm_smmu_flush_ops, 2181bdc6d973SRobin Murphy .iommu_dev = smmu->dev, 218248ec83bcSWill Deacon }; 218348ec83bcSWill Deacon 2184a250c23fSRobin Murphy if (!iommu_get_dma_strict(domain)) 21859662b99aSZhen Lei pgtbl_cfg.quirks |= IO_PGTABLE_QUIRK_NON_STRICT; 21869662b99aSZhen Lei 218748ec83bcSWill Deacon pgtbl_ops = alloc_io_pgtable_ops(fmt, &pgtbl_cfg, smmu_domain); 218848ec83bcSWill Deacon if (!pgtbl_ops) 218948ec83bcSWill Deacon return -ENOMEM; 219048ec83bcSWill Deacon 2191d5466357SRobin Murphy domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap; 21926619c913SRobin Murphy domain->geometry.aperture_end = (1UL << pgtbl_cfg.ias) - 1; 2193455eb7d3SRobin Murphy domain->geometry.force_aperture = true; 219448ec83bcSWill Deacon 21952505ec6fSJean-Philippe Brucker ret = finalise_stage_fn(smmu_domain, master, &pgtbl_cfg); 219657d72e15SJean-Philippe Brucker if (ret < 0) { 219748ec83bcSWill Deacon free_io_pgtable_ops(pgtbl_ops); 219848ec83bcSWill Deacon return ret; 219948ec83bcSWill Deacon } 220048ec83bcSWill Deacon 220157d72e15SJean-Philippe Brucker smmu_domain->pgtbl_ops = pgtbl_ops; 220257d72e15SJean-Philippe Brucker return 0; 220357d72e15SJean-Philippe Brucker } 220457d72e15SJean-Philippe Brucker 220548ec83bcSWill Deacon static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid) 220648ec83bcSWill Deacon { 220748ec83bcSWill Deacon __le64 *step; 220848ec83bcSWill Deacon struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg; 220948ec83bcSWill Deacon 221048ec83bcSWill Deacon if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) { 221148ec83bcSWill Deacon struct arm_smmu_strtab_l1_desc *l1_desc; 221248ec83bcSWill Deacon int idx; 221348ec83bcSWill Deacon 221448ec83bcSWill Deacon /* Two-level walk */ 221548ec83bcSWill Deacon idx = (sid >> STRTAB_SPLIT) * STRTAB_L1_DESC_DWORDS; 221648ec83bcSWill Deacon l1_desc = &cfg->l1_desc[idx]; 221748ec83bcSWill Deacon idx = (sid & ((1 << STRTAB_SPLIT) - 1)) * STRTAB_STE_DWORDS; 221848ec83bcSWill Deacon step = &l1_desc->l2ptr[idx]; 221948ec83bcSWill Deacon } else { 222048ec83bcSWill Deacon /* Simple linear lookup */ 222148ec83bcSWill Deacon step = &cfg->strtab[sid * STRTAB_STE_DWORDS]; 222248ec83bcSWill Deacon } 222348ec83bcSWill Deacon 222448ec83bcSWill Deacon return step; 222548ec83bcSWill Deacon } 222648ec83bcSWill Deacon 2227bcecaee4SJean-Philippe Brucker static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master) 222848ec83bcSWill Deacon { 2229563b5cbeSRobin Murphy int i, j; 22308f785154SRobin Murphy struct arm_smmu_device *smmu = master->smmu; 223148ec83bcSWill Deacon 2232cdf315f9SJean-Philippe Brucker for (i = 0; i < master->num_streams; ++i) { 2233cdf315f9SJean-Philippe Brucker u32 sid = master->streams[i].id; 223448ec83bcSWill Deacon __le64 *step = arm_smmu_get_step_for_sid(smmu, sid); 223548ec83bcSWill Deacon 2236563b5cbeSRobin Murphy /* Bridged PCI devices may end up with duplicated IDs */ 2237563b5cbeSRobin Murphy for (j = 0; j < i; j++) 2238cdf315f9SJean-Philippe Brucker if (master->streams[j].id == sid) 2239563b5cbeSRobin Murphy break; 2240563b5cbeSRobin Murphy if (j < i) 2241563b5cbeSRobin Murphy continue; 2242563b5cbeSRobin Murphy 22438be39a1aSJean-Philippe Brucker arm_smmu_write_strtab_ent(master, sid, step); 224448ec83bcSWill Deacon } 224548ec83bcSWill Deacon } 224648ec83bcSWill Deacon 2247bfff88ecSWill Deacon static bool arm_smmu_ats_supported(struct arm_smmu_master *master) 22489ce27afcSJean-Philippe Brucker { 22490b2527a6SJean-Philippe Brucker struct device *dev = master->dev; 22509ce27afcSJean-Philippe Brucker struct arm_smmu_device *smmu = master->smmu; 22510b2527a6SJean-Philippe Brucker struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); 22529ce27afcSJean-Philippe Brucker 22530b2527a6SJean-Philippe Brucker if (!(smmu->features & ARM_SMMU_FEAT_ATS)) 2254bfff88ecSWill Deacon return false; 22559ce27afcSJean-Philippe Brucker 22560b2527a6SJean-Philippe Brucker if (!(fwspec->flags & IOMMU_FWSPEC_PCI_RC_ATS)) 2257097a7df2SYueHaibing return false; 22580b2527a6SJean-Philippe Brucker 22590b2527a6SJean-Philippe Brucker return dev_is_pci(dev) && pci_ats_supported(to_pci_dev(dev)); 2260097a7df2SYueHaibing } 2261bfff88ecSWill Deacon 2262bfff88ecSWill Deacon static void arm_smmu_enable_ats(struct arm_smmu_master *master) 2263bfff88ecSWill Deacon { 2264bfff88ecSWill Deacon size_t stu; 2265bfff88ecSWill Deacon struct pci_dev *pdev; 2266bfff88ecSWill Deacon struct arm_smmu_device *smmu = master->smmu; 2267cdb8a3c3SWill Deacon struct arm_smmu_domain *smmu_domain = master->domain; 2268bfff88ecSWill Deacon 2269bfff88ecSWill Deacon /* Don't enable ATS at the endpoint if it's not enabled in the STE */ 2270bfff88ecSWill Deacon if (!master->ats_enabled) 2271bfff88ecSWill Deacon return; 22729ce27afcSJean-Philippe Brucker 22739ce27afcSJean-Philippe Brucker /* Smallest Translation Unit: log2 of the smallest supported granule */ 22749ce27afcSJean-Philippe Brucker stu = __ffs(smmu->pgsize_bitmap); 2275bfff88ecSWill Deacon pdev = to_pci_dev(master->dev); 22769ce27afcSJean-Philippe Brucker 2277cdb8a3c3SWill Deacon atomic_inc(&smmu_domain->nr_ats_masters); 2278cdb8a3c3SWill Deacon arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0); 2279bfff88ecSWill Deacon if (pci_enable_ats(pdev, stu)) 2280bfff88ecSWill Deacon dev_err(master->dev, "Failed to enable ATS (STU %zu)\n", stu); 22819ce27afcSJean-Philippe Brucker } 22829ce27afcSJean-Philippe Brucker 22839ce27afcSJean-Philippe Brucker static void arm_smmu_disable_ats(struct arm_smmu_master *master) 22849ce27afcSJean-Philippe Brucker { 2285cdb8a3c3SWill Deacon struct arm_smmu_domain *smmu_domain = master->domain; 22868dd8f005SJean-Philippe Brucker 2287bfff88ecSWill Deacon if (!master->ats_enabled) 22889ce27afcSJean-Philippe Brucker return; 22899ce27afcSJean-Philippe Brucker 2290bfff88ecSWill Deacon pci_disable_ats(to_pci_dev(master->dev)); 2291bfff88ecSWill Deacon /* 2292bfff88ecSWill Deacon * Ensure ATS is disabled at the endpoint before we issue the 2293bfff88ecSWill Deacon * ATC invalidation via the SMMU. 2294bfff88ecSWill Deacon */ 2295bfff88ecSWill Deacon wmb(); 22969e773aeeSRob Herring arm_smmu_atc_inv_master(master); 2297cdb8a3c3SWill Deacon atomic_dec(&smmu_domain->nr_ats_masters); 22989ce27afcSJean-Philippe Brucker } 22999ce27afcSJean-Philippe Brucker 2300058c59a0SJean-Philippe Brucker static int arm_smmu_enable_pasid(struct arm_smmu_master *master) 2301058c59a0SJean-Philippe Brucker { 2302058c59a0SJean-Philippe Brucker int ret; 2303058c59a0SJean-Philippe Brucker int features; 2304058c59a0SJean-Philippe Brucker int num_pasids; 2305058c59a0SJean-Philippe Brucker struct pci_dev *pdev; 2306058c59a0SJean-Philippe Brucker 2307058c59a0SJean-Philippe Brucker if (!dev_is_pci(master->dev)) 2308058c59a0SJean-Philippe Brucker return -ENODEV; 2309058c59a0SJean-Philippe Brucker 2310058c59a0SJean-Philippe Brucker pdev = to_pci_dev(master->dev); 2311058c59a0SJean-Philippe Brucker 2312058c59a0SJean-Philippe Brucker features = pci_pasid_features(pdev); 2313058c59a0SJean-Philippe Brucker if (features < 0) 2314058c59a0SJean-Philippe Brucker return features; 2315058c59a0SJean-Philippe Brucker 2316058c59a0SJean-Philippe Brucker num_pasids = pci_max_pasids(pdev); 2317058c59a0SJean-Philippe Brucker if (num_pasids <= 0) 2318058c59a0SJean-Philippe Brucker return num_pasids; 2319058c59a0SJean-Philippe Brucker 2320058c59a0SJean-Philippe Brucker ret = pci_enable_pasid(pdev, features); 2321058c59a0SJean-Philippe Brucker if (ret) { 2322058c59a0SJean-Philippe Brucker dev_err(&pdev->dev, "Failed to enable PASID\n"); 2323058c59a0SJean-Philippe Brucker return ret; 2324058c59a0SJean-Philippe Brucker } 2325058c59a0SJean-Philippe Brucker 2326058c59a0SJean-Philippe Brucker master->ssid_bits = min_t(u8, ilog2(num_pasids), 2327058c59a0SJean-Philippe Brucker master->smmu->ssid_bits); 2328058c59a0SJean-Philippe Brucker return 0; 2329058c59a0SJean-Philippe Brucker } 2330058c59a0SJean-Philippe Brucker 2331058c59a0SJean-Philippe Brucker static void arm_smmu_disable_pasid(struct arm_smmu_master *master) 2332058c59a0SJean-Philippe Brucker { 2333058c59a0SJean-Philippe Brucker struct pci_dev *pdev; 2334058c59a0SJean-Philippe Brucker 2335058c59a0SJean-Philippe Brucker if (!dev_is_pci(master->dev)) 2336058c59a0SJean-Philippe Brucker return; 2337058c59a0SJean-Philippe Brucker 2338058c59a0SJean-Philippe Brucker pdev = to_pci_dev(master->dev); 2339058c59a0SJean-Philippe Brucker 2340058c59a0SJean-Philippe Brucker if (!pdev->pasid_enabled) 2341058c59a0SJean-Philippe Brucker return; 2342058c59a0SJean-Philippe Brucker 2343058c59a0SJean-Philippe Brucker master->ssid_bits = 0; 2344058c59a0SJean-Philippe Brucker pci_disable_pasid(pdev); 2345058c59a0SJean-Philippe Brucker } 2346058c59a0SJean-Philippe Brucker 2347bcecaee4SJean-Philippe Brucker static void arm_smmu_detach_dev(struct arm_smmu_master *master) 2348bc7f2ce0SWill Deacon { 23492a7e62f5SJean-Philippe Brucker unsigned long flags; 23502a7e62f5SJean-Philippe Brucker struct arm_smmu_domain *smmu_domain = master->domain; 23512a7e62f5SJean-Philippe Brucker 23522a7e62f5SJean-Philippe Brucker if (!smmu_domain) 23538be39a1aSJean-Philippe Brucker return; 23548be39a1aSJean-Philippe Brucker 2355cdb8a3c3SWill Deacon arm_smmu_disable_ats(master); 2356cdb8a3c3SWill Deacon 23572a7e62f5SJean-Philippe Brucker spin_lock_irqsave(&smmu_domain->devices_lock, flags); 23582a7e62f5SJean-Philippe Brucker list_del(&master->domain_head); 23592a7e62f5SJean-Philippe Brucker spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); 23602a7e62f5SJean-Philippe Brucker 23618be39a1aSJean-Philippe Brucker master->domain = NULL; 2362bfff88ecSWill Deacon master->ats_enabled = false; 2363bcecaee4SJean-Philippe Brucker arm_smmu_install_ste_for_dev(master); 2364bc7f2ce0SWill Deacon } 2365bc7f2ce0SWill Deacon 236648ec83bcSWill Deacon static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev) 236748ec83bcSWill Deacon { 236848ec83bcSWill Deacon int ret = 0; 23692a7e62f5SJean-Philippe Brucker unsigned long flags; 23709b468f7dSJoerg Roedel struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); 237148ec83bcSWill Deacon struct arm_smmu_device *smmu; 237248ec83bcSWill Deacon struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); 2373b54f4260SJean-Philippe Brucker struct arm_smmu_master *master; 237448ec83bcSWill Deacon 23759b468f7dSJoerg Roedel if (!fwspec) 237648ec83bcSWill Deacon return -ENOENT; 237748ec83bcSWill Deacon 2378b7a9662fSJoerg Roedel master = dev_iommu_priv_get(dev); 23798f785154SRobin Murphy smmu = master->smmu; 23808f785154SRobin Murphy 2381f534d98bSJean-Philippe Brucker /* 2382f534d98bSJean-Philippe Brucker * Checking that SVA is disabled ensures that this device isn't bound to 2383f534d98bSJean-Philippe Brucker * any mm, and can be safely detached from its old domain. Bonds cannot 2384f534d98bSJean-Philippe Brucker * be removed concurrently since we're holding the group mutex. 2385f534d98bSJean-Philippe Brucker */ 2386f534d98bSJean-Philippe Brucker if (arm_smmu_master_sva_enabled(master)) { 2387f534d98bSJean-Philippe Brucker dev_err(dev, "cannot attach - SVA enabled\n"); 2388f534d98bSJean-Philippe Brucker return -EBUSY; 2389f534d98bSJean-Philippe Brucker } 2390f534d98bSJean-Philippe Brucker 2391bcecaee4SJean-Philippe Brucker arm_smmu_detach_dev(master); 239248ec83bcSWill Deacon 239348ec83bcSWill Deacon mutex_lock(&smmu_domain->init_mutex); 239448ec83bcSWill Deacon 239548ec83bcSWill Deacon if (!smmu_domain->smmu) { 239648ec83bcSWill Deacon smmu_domain->smmu = smmu; 23972505ec6fSJean-Philippe Brucker ret = arm_smmu_domain_finalise(domain, master); 239848ec83bcSWill Deacon if (ret) { 239948ec83bcSWill Deacon smmu_domain->smmu = NULL; 240048ec83bcSWill Deacon goto out_unlock; 240148ec83bcSWill Deacon } 240248ec83bcSWill Deacon } else if (smmu_domain->smmu != smmu) { 240348ec83bcSWill Deacon dev_err(dev, 240448ec83bcSWill Deacon "cannot attach to SMMU %s (upstream of %s)\n", 240548ec83bcSWill Deacon dev_name(smmu_domain->smmu->dev), 240648ec83bcSWill Deacon dev_name(smmu->dev)); 240748ec83bcSWill Deacon ret = -ENXIO; 240848ec83bcSWill Deacon goto out_unlock; 24092505ec6fSJean-Philippe Brucker } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 && 24102505ec6fSJean-Philippe Brucker master->ssid_bits != smmu_domain->s1_cfg.s1cdmax) { 24112505ec6fSJean-Philippe Brucker dev_err(dev, 24122505ec6fSJean-Philippe Brucker "cannot attach to incompatible domain (%u SSID bits != %u)\n", 24132505ec6fSJean-Philippe Brucker smmu_domain->s1_cfg.s1cdmax, master->ssid_bits); 24142505ec6fSJean-Philippe Brucker ret = -EINVAL; 24152505ec6fSJean-Philippe Brucker goto out_unlock; 2416395ad89dSJean-Philippe Brucker } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 && 2417395ad89dSJean-Philippe Brucker smmu_domain->stall_enabled != master->stall_enabled) { 2418395ad89dSJean-Philippe Brucker dev_err(dev, "cannot attach to stall-%s domain\n", 2419395ad89dSJean-Philippe Brucker smmu_domain->stall_enabled ? "enabled" : "disabled"); 2420395ad89dSJean-Philippe Brucker ret = -EINVAL; 2421395ad89dSJean-Philippe Brucker goto out_unlock; 242248ec83bcSWill Deacon } 242348ec83bcSWill Deacon 24248be39a1aSJean-Philippe Brucker master->domain = smmu_domain; 242548ec83bcSWill Deacon 24269ce27afcSJean-Philippe Brucker if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS) 2427bfff88ecSWill Deacon master->ats_enabled = arm_smmu_ats_supported(master); 24289ce27afcSJean-Philippe Brucker 2429bcecaee4SJean-Philippe Brucker arm_smmu_install_ste_for_dev(master); 2430cdb8a3c3SWill Deacon 2431cdb8a3c3SWill Deacon spin_lock_irqsave(&smmu_domain->devices_lock, flags); 2432cdb8a3c3SWill Deacon list_add(&master->domain_head, &smmu_domain->devices); 2433cdb8a3c3SWill Deacon spin_unlock_irqrestore(&smmu_domain->devices_lock, flags); 2434cdb8a3c3SWill Deacon 2435bfff88ecSWill Deacon arm_smmu_enable_ats(master); 2436cdb8a3c3SWill Deacon 243748ec83bcSWill Deacon out_unlock: 243848ec83bcSWill Deacon mutex_unlock(&smmu_domain->init_mutex); 243948ec83bcSWill Deacon return ret; 244048ec83bcSWill Deacon } 244148ec83bcSWill Deacon 244248ec83bcSWill Deacon static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova, 2443781ca2deSTom Murphy phys_addr_t paddr, size_t size, int prot, gfp_t gfp) 244448ec83bcSWill Deacon { 244558188afeSRobin Murphy struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; 244648ec83bcSWill Deacon 244748ec83bcSWill Deacon if (!ops) 244848ec83bcSWill Deacon return -ENODEV; 244948ec83bcSWill Deacon 2450f34ce7a7SBaolin Wang return ops->map(ops, iova, paddr, size, prot, gfp); 245148ec83bcSWill Deacon } 245248ec83bcSWill Deacon 245356f8af5eSWill Deacon static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, 245456f8af5eSWill Deacon size_t size, struct iommu_iotlb_gather *gather) 245548ec83bcSWill Deacon { 24569ce27afcSJean-Philippe Brucker struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); 24579ce27afcSJean-Philippe Brucker struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops; 245848ec83bcSWill Deacon 245948ec83bcSWill Deacon if (!ops) 246048ec83bcSWill Deacon return 0; 246148ec83bcSWill Deacon 2462353e3cf8SWill Deacon return ops->unmap(ops, iova, size, gather); 246348ec83bcSWill Deacon } 246448ec83bcSWill Deacon 246507fdef34SZhen Lei static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain) 246607fdef34SZhen Lei { 246707fdef34SZhen Lei struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); 246807fdef34SZhen Lei 246907fdef34SZhen Lei if (smmu_domain->smmu) 247007fdef34SZhen Lei arm_smmu_tlb_inv_context(smmu_domain); 247107fdef34SZhen Lei } 247207fdef34SZhen Lei 247356f8af5eSWill Deacon static void arm_smmu_iotlb_sync(struct iommu_domain *domain, 247456f8af5eSWill Deacon struct iommu_iotlb_gather *gather) 247532b12449SRobin Murphy { 24762af2e72bSWill Deacon struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); 247732b12449SRobin Murphy 24786cc7e5a9SXiang Chen if (!gather->pgsize) 24796cc7e5a9SXiang Chen return; 24806cc7e5a9SXiang Chen 2481eba8d2f8SJean-Philippe Brucker arm_smmu_tlb_inv_range_domain(gather->start, 24827060377cSWill Deacon gather->end - gather->start + 1, 24832af2e72bSWill Deacon gather->pgsize, true, smmu_domain); 248432b12449SRobin Murphy } 248532b12449SRobin Murphy 248648ec83bcSWill Deacon static phys_addr_t 248748ec83bcSWill Deacon arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova) 248848ec83bcSWill Deacon { 248958188afeSRobin Murphy struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops; 249048ec83bcSWill Deacon 2491bdf95923SSunil Goutham if (domain->type == IOMMU_DOMAIN_IDENTITY) 2492bdf95923SSunil Goutham return iova; 2493bdf95923SSunil Goutham 249448ec83bcSWill Deacon if (!ops) 249548ec83bcSWill Deacon return 0; 249648ec83bcSWill Deacon 249758188afeSRobin Murphy return ops->iova_to_phys(ops, iova); 249848ec83bcSWill Deacon } 249948ec83bcSWill Deacon 25008f785154SRobin Murphy static struct platform_driver arm_smmu_driver; 25018f785154SRobin Murphy 2502778de074SLorenzo Pieralisi static 2503778de074SLorenzo Pieralisi struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode) 250448ec83bcSWill Deacon { 250567843bbaSSuzuki K Poulose struct device *dev = driver_find_device_by_fwnode(&arm_smmu_driver.driver, 250667843bbaSSuzuki K Poulose fwnode); 25078f785154SRobin Murphy put_device(dev); 25088f785154SRobin Murphy return dev ? dev_get_drvdata(dev) : NULL; 250948ec83bcSWill Deacon } 251048ec83bcSWill Deacon 251148ec83bcSWill Deacon static bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid) 251248ec83bcSWill Deacon { 251348ec83bcSWill Deacon unsigned long limit = smmu->strtab_cfg.num_l1_ents; 251448ec83bcSWill Deacon 251548ec83bcSWill Deacon if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) 251648ec83bcSWill Deacon limit *= 1UL << STRTAB_SPLIT; 251748ec83bcSWill Deacon 251848ec83bcSWill Deacon return sid < limit; 251948ec83bcSWill Deacon } 252048ec83bcSWill Deacon 2521cdf315f9SJean-Philippe Brucker static int arm_smmu_insert_master(struct arm_smmu_device *smmu, 2522cdf315f9SJean-Philippe Brucker struct arm_smmu_master *master) 2523cdf315f9SJean-Philippe Brucker { 2524cdf315f9SJean-Philippe Brucker int i; 2525cdf315f9SJean-Philippe Brucker int ret = 0; 2526cdf315f9SJean-Philippe Brucker struct arm_smmu_stream *new_stream, *cur_stream; 2527cdf315f9SJean-Philippe Brucker struct rb_node **new_node, *parent_node = NULL; 2528cdf315f9SJean-Philippe Brucker struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev); 2529cdf315f9SJean-Philippe Brucker 2530cdf315f9SJean-Philippe Brucker master->streams = kcalloc(fwspec->num_ids, sizeof(*master->streams), 2531cdf315f9SJean-Philippe Brucker GFP_KERNEL); 2532cdf315f9SJean-Philippe Brucker if (!master->streams) 2533cdf315f9SJean-Philippe Brucker return -ENOMEM; 2534cdf315f9SJean-Philippe Brucker master->num_streams = fwspec->num_ids; 2535cdf315f9SJean-Philippe Brucker 2536cdf315f9SJean-Philippe Brucker mutex_lock(&smmu->streams_mutex); 2537cdf315f9SJean-Philippe Brucker for (i = 0; i < fwspec->num_ids; i++) { 2538cdf315f9SJean-Philippe Brucker u32 sid = fwspec->ids[i]; 2539cdf315f9SJean-Philippe Brucker 2540cdf315f9SJean-Philippe Brucker new_stream = &master->streams[i]; 2541cdf315f9SJean-Philippe Brucker new_stream->id = sid; 2542cdf315f9SJean-Philippe Brucker new_stream->master = master; 2543cdf315f9SJean-Philippe Brucker 2544cdf315f9SJean-Philippe Brucker /* 2545cdf315f9SJean-Philippe Brucker * Check the SIDs are in range of the SMMU and our stream table 2546cdf315f9SJean-Philippe Brucker */ 2547cdf315f9SJean-Philippe Brucker if (!arm_smmu_sid_in_range(smmu, sid)) { 2548cdf315f9SJean-Philippe Brucker ret = -ERANGE; 2549cdf315f9SJean-Philippe Brucker break; 2550cdf315f9SJean-Philippe Brucker } 2551cdf315f9SJean-Philippe Brucker 2552cdf315f9SJean-Philippe Brucker /* Ensure l2 strtab is initialised */ 2553cdf315f9SJean-Philippe Brucker if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) { 2554cdf315f9SJean-Philippe Brucker ret = arm_smmu_init_l2_strtab(smmu, sid); 2555cdf315f9SJean-Philippe Brucker if (ret) 2556cdf315f9SJean-Philippe Brucker break; 2557cdf315f9SJean-Philippe Brucker } 2558cdf315f9SJean-Philippe Brucker 2559cdf315f9SJean-Philippe Brucker /* Insert into SID tree */ 2560cdf315f9SJean-Philippe Brucker new_node = &(smmu->streams.rb_node); 2561cdf315f9SJean-Philippe Brucker while (*new_node) { 2562cdf315f9SJean-Philippe Brucker cur_stream = rb_entry(*new_node, struct arm_smmu_stream, 2563cdf315f9SJean-Philippe Brucker node); 2564cdf315f9SJean-Philippe Brucker parent_node = *new_node; 2565cdf315f9SJean-Philippe Brucker if (cur_stream->id > new_stream->id) { 2566cdf315f9SJean-Philippe Brucker new_node = &((*new_node)->rb_left); 2567cdf315f9SJean-Philippe Brucker } else if (cur_stream->id < new_stream->id) { 2568cdf315f9SJean-Philippe Brucker new_node = &((*new_node)->rb_right); 2569cdf315f9SJean-Philippe Brucker } else { 2570cdf315f9SJean-Philippe Brucker dev_warn(master->dev, 2571cdf315f9SJean-Philippe Brucker "stream %u already in tree\n", 2572cdf315f9SJean-Philippe Brucker cur_stream->id); 2573cdf315f9SJean-Philippe Brucker ret = -EINVAL; 2574cdf315f9SJean-Philippe Brucker break; 2575cdf315f9SJean-Philippe Brucker } 2576cdf315f9SJean-Philippe Brucker } 2577cdf315f9SJean-Philippe Brucker if (ret) 2578cdf315f9SJean-Philippe Brucker break; 2579cdf315f9SJean-Philippe Brucker 2580cdf315f9SJean-Philippe Brucker rb_link_node(&new_stream->node, parent_node, new_node); 2581cdf315f9SJean-Philippe Brucker rb_insert_color(&new_stream->node, &smmu->streams); 2582cdf315f9SJean-Philippe Brucker } 2583cdf315f9SJean-Philippe Brucker 2584cdf315f9SJean-Philippe Brucker if (ret) { 2585cdf315f9SJean-Philippe Brucker for (i--; i >= 0; i--) 2586cdf315f9SJean-Philippe Brucker rb_erase(&master->streams[i].node, &smmu->streams); 2587cdf315f9SJean-Philippe Brucker kfree(master->streams); 2588cdf315f9SJean-Philippe Brucker } 2589cdf315f9SJean-Philippe Brucker mutex_unlock(&smmu->streams_mutex); 2590cdf315f9SJean-Philippe Brucker 2591cdf315f9SJean-Philippe Brucker return ret; 2592cdf315f9SJean-Philippe Brucker } 2593cdf315f9SJean-Philippe Brucker 2594cdf315f9SJean-Philippe Brucker static void arm_smmu_remove_master(struct arm_smmu_master *master) 2595cdf315f9SJean-Philippe Brucker { 2596cdf315f9SJean-Philippe Brucker int i; 2597cdf315f9SJean-Philippe Brucker struct arm_smmu_device *smmu = master->smmu; 2598cdf315f9SJean-Philippe Brucker struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev); 2599cdf315f9SJean-Philippe Brucker 2600cdf315f9SJean-Philippe Brucker if (!smmu || !master->streams) 2601cdf315f9SJean-Philippe Brucker return; 2602cdf315f9SJean-Philippe Brucker 2603cdf315f9SJean-Philippe Brucker mutex_lock(&smmu->streams_mutex); 2604cdf315f9SJean-Philippe Brucker for (i = 0; i < fwspec->num_ids; i++) 2605cdf315f9SJean-Philippe Brucker rb_erase(&master->streams[i].node, &smmu->streams); 2606cdf315f9SJean-Philippe Brucker mutex_unlock(&smmu->streams_mutex); 2607cdf315f9SJean-Philippe Brucker 2608cdf315f9SJean-Philippe Brucker kfree(master->streams); 2609cdf315f9SJean-Philippe Brucker } 2610cdf315f9SJean-Philippe Brucker 26118f785154SRobin Murphy static struct iommu_ops arm_smmu_ops; 26128f785154SRobin Murphy 2613cefa0d55SJoerg Roedel static struct iommu_device *arm_smmu_probe_device(struct device *dev) 261448ec83bcSWill Deacon { 2615cdf315f9SJean-Philippe Brucker int ret; 261648ec83bcSWill Deacon struct arm_smmu_device *smmu; 2617b54f4260SJean-Philippe Brucker struct arm_smmu_master *master; 26189b468f7dSJoerg Roedel struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); 261948ec83bcSWill Deacon 26208f785154SRobin Murphy if (!fwspec || fwspec->ops != &arm_smmu_ops) 2621cefa0d55SJoerg Roedel return ERR_PTR(-ENODEV); 262292c1d360SWill Deacon 2623b7a9662fSJoerg Roedel if (WARN_ON_ONCE(dev_iommu_priv_get(dev))) 2624cefa0d55SJoerg Roedel return ERR_PTR(-EBUSY); 262592c1d360SWill Deacon 2626778de074SLorenzo Pieralisi smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode); 26278f785154SRobin Murphy if (!smmu) 2628cefa0d55SJoerg Roedel return ERR_PTR(-ENODEV); 262992c1d360SWill Deacon 26308f785154SRobin Murphy master = kzalloc(sizeof(*master), GFP_KERNEL); 26318f785154SRobin Murphy if (!master) 2632cefa0d55SJoerg Roedel return ERR_PTR(-ENOMEM); 26338f785154SRobin Murphy 26349ce27afcSJean-Philippe Brucker master->dev = dev; 26358f785154SRobin Murphy master->smmu = smmu; 2636f534d98bSJean-Philippe Brucker INIT_LIST_HEAD(&master->bonds); 2637b7a9662fSJoerg Roedel dev_iommu_priv_set(dev, master); 263848ec83bcSWill Deacon 2639cdf315f9SJean-Philippe Brucker ret = arm_smmu_insert_master(smmu, master); 264048ec83bcSWill Deacon if (ret) 2641a2be6218SJean-Philippe Brucker goto err_free_master; 26428f785154SRobin Murphy 2643434b73e6SJean-Philippe Brucker device_property_read_u32(dev, "pasid-num-bits", &master->ssid_bits); 2644434b73e6SJean-Philippe Brucker master->ssid_bits = min(smmu->ssid_bits, master->ssid_bits); 264589535821SJean-Philippe Brucker 2646058c59a0SJean-Philippe Brucker /* 2647058c59a0SJean-Philippe Brucker * Note that PASID must be enabled before, and disabled after ATS: 2648058c59a0SJean-Philippe Brucker * PCI Express Base 4.0r1.0 - 10.5.1.3 ATS Control Register 2649058c59a0SJean-Philippe Brucker * 2650058c59a0SJean-Philippe Brucker * Behavior is undefined if this bit is Set and the value of the PASID 2651058c59a0SJean-Philippe Brucker * Enable, Execute Requested Enable, or Privileged Mode Requested bits 2652058c59a0SJean-Philippe Brucker * are changed. 2653058c59a0SJean-Philippe Brucker */ 2654058c59a0SJean-Philippe Brucker arm_smmu_enable_pasid(master); 2655058c59a0SJean-Philippe Brucker 265689535821SJean-Philippe Brucker if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB)) 265789535821SJean-Philippe Brucker master->ssid_bits = min_t(u8, master->ssid_bits, 265889535821SJean-Philippe Brucker CTXDESC_LINEAR_CDMAX); 265989535821SJean-Philippe Brucker 2660395ad89dSJean-Philippe Brucker if ((smmu->features & ARM_SMMU_FEAT_STALLS && 2661395ad89dSJean-Philippe Brucker device_property_read_bool(dev, "dma-can-stall")) || 2662395ad89dSJean-Philippe Brucker smmu->features & ARM_SMMU_FEAT_STALL_FORCE) 2663395ad89dSJean-Philippe Brucker master->stall_enabled = true; 2664395ad89dSJean-Philippe Brucker 2665cefa0d55SJoerg Roedel return &smmu->iommu; 2666a2be6218SJean-Philippe Brucker 2667a2be6218SJean-Philippe Brucker err_free_master: 2668a2be6218SJean-Philippe Brucker kfree(master); 2669b7a9662fSJoerg Roedel dev_iommu_priv_set(dev, NULL); 2670cefa0d55SJoerg Roedel return ERR_PTR(ret); 26718f785154SRobin Murphy } 267248ec83bcSWill Deacon 2673cefa0d55SJoerg Roedel static void arm_smmu_release_device(struct device *dev) 267448ec83bcSWill Deacon { 26759b468f7dSJoerg Roedel struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); 2676b54f4260SJean-Philippe Brucker struct arm_smmu_master *master; 26778f785154SRobin Murphy 26788f785154SRobin Murphy if (!fwspec || fwspec->ops != &arm_smmu_ops) 26798f785154SRobin Murphy return; 26808f785154SRobin Murphy 2681b7a9662fSJoerg Roedel master = dev_iommu_priv_get(dev); 2682395ad89dSJean-Philippe Brucker if (WARN_ON(arm_smmu_master_sva_enabled(master))) 2683395ad89dSJean-Philippe Brucker iopf_queue_remove_device(master->smmu->evtq.iopf, dev); 2684bcecaee4SJean-Philippe Brucker arm_smmu_detach_dev(master); 2685058c59a0SJean-Philippe Brucker arm_smmu_disable_pasid(master); 2686cdf315f9SJean-Philippe Brucker arm_smmu_remove_master(master); 26878f785154SRobin Murphy kfree(master); 26888f785154SRobin Murphy iommu_fwspec_free(dev); 268948ec83bcSWill Deacon } 269048ec83bcSWill Deacon 269108d4ca2aSRobin Murphy static struct iommu_group *arm_smmu_device_group(struct device *dev) 269208d4ca2aSRobin Murphy { 269308d4ca2aSRobin Murphy struct iommu_group *group; 269408d4ca2aSRobin Murphy 269508d4ca2aSRobin Murphy /* 269608d4ca2aSRobin Murphy * We don't support devices sharing stream IDs other than PCI RID 269708d4ca2aSRobin Murphy * aliases, since the necessary ID-to-device lookup becomes rather 269808d4ca2aSRobin Murphy * impractical given a potential sparse 32-bit stream ID space. 269908d4ca2aSRobin Murphy */ 270008d4ca2aSRobin Murphy if (dev_is_pci(dev)) 270108d4ca2aSRobin Murphy group = pci_device_group(dev); 270208d4ca2aSRobin Murphy else 270308d4ca2aSRobin Murphy group = generic_device_group(dev); 270408d4ca2aSRobin Murphy 270508d4ca2aSRobin Murphy return group; 270608d4ca2aSRobin Murphy } 270708d4ca2aSRobin Murphy 27087e147547SChristoph Hellwig static int arm_smmu_enable_nesting(struct iommu_domain *domain) 270948ec83bcSWill Deacon { 271048ec83bcSWill Deacon struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain); 271148ec83bcSWill Deacon int ret = 0; 271248ec83bcSWill Deacon 271348ec83bcSWill Deacon mutex_lock(&smmu_domain->init_mutex); 27147e147547SChristoph Hellwig if (smmu_domain->smmu) 271548ec83bcSWill Deacon ret = -EPERM; 271648ec83bcSWill Deacon else 27177e147547SChristoph Hellwig smmu_domain->stage = ARM_SMMU_DOMAIN_NESTED; 271848ec83bcSWill Deacon mutex_unlock(&smmu_domain->init_mutex); 27197e147547SChristoph Hellwig 272048ec83bcSWill Deacon return ret; 272148ec83bcSWill Deacon } 272248ec83bcSWill Deacon 27238f785154SRobin Murphy static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args) 27248f785154SRobin Murphy { 27258f785154SRobin Murphy return iommu_fwspec_add_ids(dev, args->args, 1); 27268f785154SRobin Murphy } 27278f785154SRobin Murphy 272850019f09SEric Auger static void arm_smmu_get_resv_regions(struct device *dev, 272950019f09SEric Auger struct list_head *head) 273050019f09SEric Auger { 273150019f09SEric Auger struct iommu_resv_region *region; 273250019f09SEric Auger int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; 273350019f09SEric Auger 273450019f09SEric Auger region = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH, 27359d3a4de4SRobin Murphy prot, IOMMU_RESV_SW_MSI); 273650019f09SEric Auger if (!region) 273750019f09SEric Auger return; 273850019f09SEric Auger 273950019f09SEric Auger list_add_tail(®ion->list, head); 2740273df963SRobin Murphy 2741273df963SRobin Murphy iommu_dma_get_resv_regions(dev, head); 274250019f09SEric Auger } 274350019f09SEric Auger 2744f534d98bSJean-Philippe Brucker static bool arm_smmu_dev_has_feature(struct device *dev, 2745f534d98bSJean-Philippe Brucker enum iommu_dev_features feat) 2746f534d98bSJean-Philippe Brucker { 2747f534d98bSJean-Philippe Brucker struct arm_smmu_master *master = dev_iommu_priv_get(dev); 2748f534d98bSJean-Philippe Brucker 2749f534d98bSJean-Philippe Brucker if (!master) 2750f534d98bSJean-Philippe Brucker return false; 2751f534d98bSJean-Philippe Brucker 2752f534d98bSJean-Philippe Brucker switch (feat) { 2753395ad89dSJean-Philippe Brucker case IOMMU_DEV_FEAT_IOPF: 2754395ad89dSJean-Philippe Brucker return arm_smmu_master_iopf_supported(master); 2755f534d98bSJean-Philippe Brucker case IOMMU_DEV_FEAT_SVA: 2756f534d98bSJean-Philippe Brucker return arm_smmu_master_sva_supported(master); 2757f534d98bSJean-Philippe Brucker default: 2758f534d98bSJean-Philippe Brucker return false; 2759f534d98bSJean-Philippe Brucker } 2760f534d98bSJean-Philippe Brucker } 2761f534d98bSJean-Philippe Brucker 2762f534d98bSJean-Philippe Brucker static bool arm_smmu_dev_feature_enabled(struct device *dev, 2763f534d98bSJean-Philippe Brucker enum iommu_dev_features feat) 2764f534d98bSJean-Philippe Brucker { 2765f534d98bSJean-Philippe Brucker struct arm_smmu_master *master = dev_iommu_priv_get(dev); 2766f534d98bSJean-Philippe Brucker 2767f534d98bSJean-Philippe Brucker if (!master) 2768f534d98bSJean-Philippe Brucker return false; 2769f534d98bSJean-Philippe Brucker 2770f534d98bSJean-Philippe Brucker switch (feat) { 2771395ad89dSJean-Philippe Brucker case IOMMU_DEV_FEAT_IOPF: 2772395ad89dSJean-Philippe Brucker return master->iopf_enabled; 2773f534d98bSJean-Philippe Brucker case IOMMU_DEV_FEAT_SVA: 2774f534d98bSJean-Philippe Brucker return arm_smmu_master_sva_enabled(master); 2775f534d98bSJean-Philippe Brucker default: 2776f534d98bSJean-Philippe Brucker return false; 2777f534d98bSJean-Philippe Brucker } 2778f534d98bSJean-Philippe Brucker } 2779f534d98bSJean-Philippe Brucker 2780f534d98bSJean-Philippe Brucker static int arm_smmu_dev_enable_feature(struct device *dev, 2781f534d98bSJean-Philippe Brucker enum iommu_dev_features feat) 2782f534d98bSJean-Philippe Brucker { 2783395ad89dSJean-Philippe Brucker struct arm_smmu_master *master = dev_iommu_priv_get(dev); 2784395ad89dSJean-Philippe Brucker 2785f534d98bSJean-Philippe Brucker if (!arm_smmu_dev_has_feature(dev, feat)) 2786f534d98bSJean-Philippe Brucker return -ENODEV; 2787f534d98bSJean-Philippe Brucker 2788f534d98bSJean-Philippe Brucker if (arm_smmu_dev_feature_enabled(dev, feat)) 2789f534d98bSJean-Philippe Brucker return -EBUSY; 2790f534d98bSJean-Philippe Brucker 2791f534d98bSJean-Philippe Brucker switch (feat) { 2792395ad89dSJean-Philippe Brucker case IOMMU_DEV_FEAT_IOPF: 2793395ad89dSJean-Philippe Brucker master->iopf_enabled = true; 2794395ad89dSJean-Philippe Brucker return 0; 2795f534d98bSJean-Philippe Brucker case IOMMU_DEV_FEAT_SVA: 2796395ad89dSJean-Philippe Brucker return arm_smmu_master_enable_sva(master); 2797f534d98bSJean-Philippe Brucker default: 2798f534d98bSJean-Philippe Brucker return -EINVAL; 2799f534d98bSJean-Philippe Brucker } 2800f534d98bSJean-Philippe Brucker } 2801f534d98bSJean-Philippe Brucker 2802f534d98bSJean-Philippe Brucker static int arm_smmu_dev_disable_feature(struct device *dev, 2803f534d98bSJean-Philippe Brucker enum iommu_dev_features feat) 2804f534d98bSJean-Philippe Brucker { 2805395ad89dSJean-Philippe Brucker struct arm_smmu_master *master = dev_iommu_priv_get(dev); 2806395ad89dSJean-Philippe Brucker 2807f534d98bSJean-Philippe Brucker if (!arm_smmu_dev_feature_enabled(dev, feat)) 2808f534d98bSJean-Philippe Brucker return -EINVAL; 2809f534d98bSJean-Philippe Brucker 2810f534d98bSJean-Philippe Brucker switch (feat) { 2811395ad89dSJean-Philippe Brucker case IOMMU_DEV_FEAT_IOPF: 2812395ad89dSJean-Philippe Brucker if (master->sva_enabled) 2813395ad89dSJean-Philippe Brucker return -EBUSY; 2814395ad89dSJean-Philippe Brucker master->iopf_enabled = false; 2815395ad89dSJean-Philippe Brucker return 0; 2816f534d98bSJean-Philippe Brucker case IOMMU_DEV_FEAT_SVA: 2817395ad89dSJean-Philippe Brucker return arm_smmu_master_disable_sva(master); 2818f534d98bSJean-Philippe Brucker default: 2819f534d98bSJean-Philippe Brucker return -EINVAL; 2820f534d98bSJean-Philippe Brucker } 2821f534d98bSJean-Philippe Brucker } 2822f534d98bSJean-Philippe Brucker 282348ec83bcSWill Deacon static struct iommu_ops arm_smmu_ops = { 282448ec83bcSWill Deacon .capable = arm_smmu_capable, 282548ec83bcSWill Deacon .domain_alloc = arm_smmu_domain_alloc, 282648ec83bcSWill Deacon .domain_free = arm_smmu_domain_free, 282748ec83bcSWill Deacon .attach_dev = arm_smmu_attach_dev, 282848ec83bcSWill Deacon .map = arm_smmu_map, 282948ec83bcSWill Deacon .unmap = arm_smmu_unmap, 283007fdef34SZhen Lei .flush_iotlb_all = arm_smmu_flush_iotlb_all, 283132b12449SRobin Murphy .iotlb_sync = arm_smmu_iotlb_sync, 283248ec83bcSWill Deacon .iova_to_phys = arm_smmu_iova_to_phys, 2833cefa0d55SJoerg Roedel .probe_device = arm_smmu_probe_device, 2834cefa0d55SJoerg Roedel .release_device = arm_smmu_release_device, 283508d4ca2aSRobin Murphy .device_group = arm_smmu_device_group, 28367e147547SChristoph Hellwig .enable_nesting = arm_smmu_enable_nesting, 28378f785154SRobin Murphy .of_xlate = arm_smmu_of_xlate, 283850019f09SEric Auger .get_resv_regions = arm_smmu_get_resv_regions, 2839a66c5dc5SThierry Reding .put_resv_regions = generic_iommu_put_resv_regions, 2840f534d98bSJean-Philippe Brucker .dev_has_feat = arm_smmu_dev_has_feature, 2841f534d98bSJean-Philippe Brucker .dev_feat_enabled = arm_smmu_dev_feature_enabled, 2842f534d98bSJean-Philippe Brucker .dev_enable_feat = arm_smmu_dev_enable_feature, 2843f534d98bSJean-Philippe Brucker .dev_disable_feat = arm_smmu_dev_disable_feature, 284432784a95SJean-Philippe Brucker .sva_bind = arm_smmu_sva_bind, 284532784a95SJean-Philippe Brucker .sva_unbind = arm_smmu_sva_unbind, 284632784a95SJean-Philippe Brucker .sva_get_pasid = arm_smmu_sva_get_pasid, 2847395ad89dSJean-Philippe Brucker .page_response = arm_smmu_page_response, 284848ec83bcSWill Deacon .pgsize_bitmap = -1UL, /* Restricted during device attach */ 2849c0aec668SRobin Murphy .owner = THIS_MODULE, 285048ec83bcSWill Deacon }; 285148ec83bcSWill Deacon 285248ec83bcSWill Deacon /* Probing and initialisation functions */ 285348ec83bcSWill Deacon static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu, 285448ec83bcSWill Deacon struct arm_smmu_queue *q, 285586d2d921SRobin Murphy void __iomem *page, 285648ec83bcSWill Deacon unsigned long prod_off, 285748ec83bcSWill Deacon unsigned long cons_off, 2858d25f6eadSWill Deacon size_t dwords, const char *name) 285948ec83bcSWill Deacon { 2860d25f6eadSWill Deacon size_t qsz; 286148ec83bcSWill Deacon 2862d25f6eadSWill Deacon do { 286352be8637SWill Deacon qsz = ((1 << q->llq.max_n_shift) * dwords) << 3; 2864d25f6eadSWill Deacon q->base = dmam_alloc_coherent(smmu->dev, qsz, &q->base_dma, 2865d25f6eadSWill Deacon GFP_KERNEL); 2866d25f6eadSWill Deacon if (q->base || qsz < PAGE_SIZE) 2867d25f6eadSWill Deacon break; 2868d25f6eadSWill Deacon 286952be8637SWill Deacon q->llq.max_n_shift--; 2870d25f6eadSWill Deacon } while (1); 2871d25f6eadSWill Deacon 287248ec83bcSWill Deacon if (!q->base) { 2873d25f6eadSWill Deacon dev_err(smmu->dev, 2874d25f6eadSWill Deacon "failed to allocate queue (0x%zx bytes) for %s\n", 2875d25f6eadSWill Deacon qsz, name); 287648ec83bcSWill Deacon return -ENOMEM; 287748ec83bcSWill Deacon } 287848ec83bcSWill Deacon 2879d25f6eadSWill Deacon if (!WARN_ON(q->base_dma & (qsz - 1))) { 2880d25f6eadSWill Deacon dev_info(smmu->dev, "allocated %u entries for %s\n", 288152be8637SWill Deacon 1 << q->llq.max_n_shift, name); 2882d25f6eadSWill Deacon } 2883d25f6eadSWill Deacon 288486d2d921SRobin Murphy q->prod_reg = page + prod_off; 288586d2d921SRobin Murphy q->cons_reg = page + cons_off; 288648ec83bcSWill Deacon q->ent_dwords = dwords; 288748ec83bcSWill Deacon 288848ec83bcSWill Deacon q->q_base = Q_BASE_RWA; 28891cf9e54eSRobin Murphy q->q_base |= q->base_dma & Q_BASE_ADDR_MASK; 289052be8637SWill Deacon q->q_base |= FIELD_PREP(Q_BASE_LOG2SIZE, q->llq.max_n_shift); 289148ec83bcSWill Deacon 289252be8637SWill Deacon q->llq.prod = q->llq.cons = 0; 289348ec83bcSWill Deacon return 0; 289448ec83bcSWill Deacon } 289548ec83bcSWill Deacon 2896587e6c10SWill Deacon static void arm_smmu_cmdq_free_bitmap(void *data) 2897587e6c10SWill Deacon { 2898587e6c10SWill Deacon unsigned long *bitmap = data; 2899587e6c10SWill Deacon bitmap_free(bitmap); 2900587e6c10SWill Deacon } 2901587e6c10SWill Deacon 2902587e6c10SWill Deacon static int arm_smmu_cmdq_init(struct arm_smmu_device *smmu) 2903587e6c10SWill Deacon { 2904587e6c10SWill Deacon int ret = 0; 2905587e6c10SWill Deacon struct arm_smmu_cmdq *cmdq = &smmu->cmdq; 2906587e6c10SWill Deacon unsigned int nents = 1 << cmdq->q.llq.max_n_shift; 2907587e6c10SWill Deacon atomic_long_t *bitmap; 2908587e6c10SWill Deacon 2909587e6c10SWill Deacon atomic_set(&cmdq->owner_prod, 0); 2910587e6c10SWill Deacon atomic_set(&cmdq->lock, 0); 2911587e6c10SWill Deacon 2912587e6c10SWill Deacon bitmap = (atomic_long_t *)bitmap_zalloc(nents, GFP_KERNEL); 2913587e6c10SWill Deacon if (!bitmap) { 2914587e6c10SWill Deacon dev_err(smmu->dev, "failed to allocate cmdq bitmap\n"); 2915587e6c10SWill Deacon ret = -ENOMEM; 2916587e6c10SWill Deacon } else { 2917587e6c10SWill Deacon cmdq->valid_map = bitmap; 2918587e6c10SWill Deacon devm_add_action(smmu->dev, arm_smmu_cmdq_free_bitmap, bitmap); 2919587e6c10SWill Deacon } 2920587e6c10SWill Deacon 2921587e6c10SWill Deacon return ret; 2922587e6c10SWill Deacon } 2923587e6c10SWill Deacon 292448ec83bcSWill Deacon static int arm_smmu_init_queues(struct arm_smmu_device *smmu) 292548ec83bcSWill Deacon { 292648ec83bcSWill Deacon int ret; 292748ec83bcSWill Deacon 292848ec83bcSWill Deacon /* cmdq */ 292986d2d921SRobin Murphy ret = arm_smmu_init_one_queue(smmu, &smmu->cmdq.q, smmu->base, 293086d2d921SRobin Murphy ARM_SMMU_CMDQ_PROD, ARM_SMMU_CMDQ_CONS, 293186d2d921SRobin Murphy CMDQ_ENT_DWORDS, "cmdq"); 293248ec83bcSWill Deacon if (ret) 293304fa26c7SWill Deacon return ret; 293448ec83bcSWill Deacon 2935587e6c10SWill Deacon ret = arm_smmu_cmdq_init(smmu); 2936587e6c10SWill Deacon if (ret) 2937587e6c10SWill Deacon return ret; 2938587e6c10SWill Deacon 293948ec83bcSWill Deacon /* evtq */ 294086d2d921SRobin Murphy ret = arm_smmu_init_one_queue(smmu, &smmu->evtq.q, smmu->page1, 294186d2d921SRobin Murphy ARM_SMMU_EVTQ_PROD, ARM_SMMU_EVTQ_CONS, 294286d2d921SRobin Murphy EVTQ_ENT_DWORDS, "evtq"); 294348ec83bcSWill Deacon if (ret) 294404fa26c7SWill Deacon return ret; 294548ec83bcSWill Deacon 2946395ad89dSJean-Philippe Brucker if ((smmu->features & ARM_SMMU_FEAT_SVA) && 2947395ad89dSJean-Philippe Brucker (smmu->features & ARM_SMMU_FEAT_STALLS)) { 2948395ad89dSJean-Philippe Brucker smmu->evtq.iopf = iopf_queue_alloc(dev_name(smmu->dev)); 2949395ad89dSJean-Philippe Brucker if (!smmu->evtq.iopf) 2950395ad89dSJean-Philippe Brucker return -ENOMEM; 2951395ad89dSJean-Philippe Brucker } 2952395ad89dSJean-Philippe Brucker 295348ec83bcSWill Deacon /* priq */ 295448ec83bcSWill Deacon if (!(smmu->features & ARM_SMMU_FEAT_PRI)) 295548ec83bcSWill Deacon return 0; 295648ec83bcSWill Deacon 295786d2d921SRobin Murphy return arm_smmu_init_one_queue(smmu, &smmu->priq.q, smmu->page1, 295886d2d921SRobin Murphy ARM_SMMU_PRIQ_PROD, ARM_SMMU_PRIQ_CONS, 295986d2d921SRobin Murphy PRIQ_ENT_DWORDS, "priq"); 296048ec83bcSWill Deacon } 296148ec83bcSWill Deacon 296248ec83bcSWill Deacon static int arm_smmu_init_l1_strtab(struct arm_smmu_device *smmu) 296348ec83bcSWill Deacon { 296448ec83bcSWill Deacon unsigned int i; 296548ec83bcSWill Deacon struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg; 296648ec83bcSWill Deacon size_t size = sizeof(*cfg->l1_desc) * cfg->num_l1_ents; 296748ec83bcSWill Deacon void *strtab = smmu->strtab_cfg.strtab; 296848ec83bcSWill Deacon 296948ec83bcSWill Deacon cfg->l1_desc = devm_kzalloc(smmu->dev, size, GFP_KERNEL); 297048ec83bcSWill Deacon if (!cfg->l1_desc) { 297148ec83bcSWill Deacon dev_err(smmu->dev, "failed to allocate l1 stream table desc\n"); 297248ec83bcSWill Deacon return -ENOMEM; 297348ec83bcSWill Deacon } 297448ec83bcSWill Deacon 297548ec83bcSWill Deacon for (i = 0; i < cfg->num_l1_ents; ++i) { 297648ec83bcSWill Deacon arm_smmu_write_strtab_l1_desc(strtab, &cfg->l1_desc[i]); 297748ec83bcSWill Deacon strtab += STRTAB_L1_DESC_DWORDS << 3; 297848ec83bcSWill Deacon } 297948ec83bcSWill Deacon 298048ec83bcSWill Deacon return 0; 298148ec83bcSWill Deacon } 298248ec83bcSWill Deacon 298348ec83bcSWill Deacon static int arm_smmu_init_strtab_2lvl(struct arm_smmu_device *smmu) 298448ec83bcSWill Deacon { 298548ec83bcSWill Deacon void *strtab; 298648ec83bcSWill Deacon u64 reg; 2987d2e88e7cSWill Deacon u32 size, l1size; 298848ec83bcSWill Deacon struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg; 298948ec83bcSWill Deacon 2990692c4e42SNate Watterson /* Calculate the L1 size, capped to the SIDSIZE. */ 299148ec83bcSWill Deacon size = STRTAB_L1_SZ_SHIFT - (ilog2(STRTAB_L1_DESC_DWORDS) + 3); 299248ec83bcSWill Deacon size = min(size, smmu->sid_bits - STRTAB_SPLIT); 2993d2e88e7cSWill Deacon cfg->num_l1_ents = 1 << size; 2994d2e88e7cSWill Deacon 2995d2e88e7cSWill Deacon size += STRTAB_SPLIT; 2996d2e88e7cSWill Deacon if (size < smmu->sid_bits) 299748ec83bcSWill Deacon dev_warn(smmu->dev, 299848ec83bcSWill Deacon "2-level strtab only covers %u/%u bits of SID\n", 2999d2e88e7cSWill Deacon size, smmu->sid_bits); 300048ec83bcSWill Deacon 3001d2e88e7cSWill Deacon l1size = cfg->num_l1_ents * (STRTAB_L1_DESC_DWORDS << 3); 300204fa26c7SWill Deacon strtab = dmam_alloc_coherent(smmu->dev, l1size, &cfg->strtab_dma, 30039bb9069cSJean-Philippe Brucker GFP_KERNEL); 300448ec83bcSWill Deacon if (!strtab) { 300548ec83bcSWill Deacon dev_err(smmu->dev, 300648ec83bcSWill Deacon "failed to allocate l1 stream table (%u bytes)\n", 3007dc898eb8SZenghui Yu l1size); 300848ec83bcSWill Deacon return -ENOMEM; 300948ec83bcSWill Deacon } 301048ec83bcSWill Deacon cfg->strtab = strtab; 301148ec83bcSWill Deacon 301248ec83bcSWill Deacon /* Configure strtab_base_cfg for 2 levels */ 3013cbcee19aSRobin Murphy reg = FIELD_PREP(STRTAB_BASE_CFG_FMT, STRTAB_BASE_CFG_FMT_2LVL); 3014cbcee19aSRobin Murphy reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, size); 3015cbcee19aSRobin Murphy reg |= FIELD_PREP(STRTAB_BASE_CFG_SPLIT, STRTAB_SPLIT); 301648ec83bcSWill Deacon cfg->strtab_base_cfg = reg; 301748ec83bcSWill Deacon 301804fa26c7SWill Deacon return arm_smmu_init_l1_strtab(smmu); 301948ec83bcSWill Deacon } 302048ec83bcSWill Deacon 302148ec83bcSWill Deacon static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu) 302248ec83bcSWill Deacon { 302348ec83bcSWill Deacon void *strtab; 302448ec83bcSWill Deacon u64 reg; 302548ec83bcSWill Deacon u32 size; 302648ec83bcSWill Deacon struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg; 302748ec83bcSWill Deacon 302848ec83bcSWill Deacon size = (1 << smmu->sid_bits) * (STRTAB_STE_DWORDS << 3); 302904fa26c7SWill Deacon strtab = dmam_alloc_coherent(smmu->dev, size, &cfg->strtab_dma, 30309bb9069cSJean-Philippe Brucker GFP_KERNEL); 303148ec83bcSWill Deacon if (!strtab) { 303248ec83bcSWill Deacon dev_err(smmu->dev, 303348ec83bcSWill Deacon "failed to allocate linear stream table (%u bytes)\n", 303448ec83bcSWill Deacon size); 303548ec83bcSWill Deacon return -ENOMEM; 303648ec83bcSWill Deacon } 303748ec83bcSWill Deacon cfg->strtab = strtab; 303848ec83bcSWill Deacon cfg->num_l1_ents = 1 << smmu->sid_bits; 303948ec83bcSWill Deacon 304048ec83bcSWill Deacon /* Configure strtab_base_cfg for a linear table covering all SIDs */ 3041cbcee19aSRobin Murphy reg = FIELD_PREP(STRTAB_BASE_CFG_FMT, STRTAB_BASE_CFG_FMT_LINEAR); 3042cbcee19aSRobin Murphy reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, smmu->sid_bits); 304348ec83bcSWill Deacon cfg->strtab_base_cfg = reg; 304448ec83bcSWill Deacon 304548ec83bcSWill Deacon arm_smmu_init_bypass_stes(strtab, cfg->num_l1_ents); 304648ec83bcSWill Deacon return 0; 304748ec83bcSWill Deacon } 304848ec83bcSWill Deacon 304948ec83bcSWill Deacon static int arm_smmu_init_strtab(struct arm_smmu_device *smmu) 305048ec83bcSWill Deacon { 305148ec83bcSWill Deacon u64 reg; 305248ec83bcSWill Deacon int ret; 305348ec83bcSWill Deacon 305448ec83bcSWill Deacon if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) 305548ec83bcSWill Deacon ret = arm_smmu_init_strtab_2lvl(smmu); 305648ec83bcSWill Deacon else 305748ec83bcSWill Deacon ret = arm_smmu_init_strtab_linear(smmu); 305848ec83bcSWill Deacon 305948ec83bcSWill Deacon if (ret) 306048ec83bcSWill Deacon return ret; 306148ec83bcSWill Deacon 306248ec83bcSWill Deacon /* Set the strtab base address */ 30631cf9e54eSRobin Murphy reg = smmu->strtab_cfg.strtab_dma & STRTAB_BASE_ADDR_MASK; 306448ec83bcSWill Deacon reg |= STRTAB_BASE_RA; 306548ec83bcSWill Deacon smmu->strtab_cfg.strtab_base = reg; 306648ec83bcSWill Deacon 306748ec83bcSWill Deacon /* Allocate the first VMID for stage-2 bypass STEs */ 306848ec83bcSWill Deacon set_bit(0, smmu->vmid_map); 306948ec83bcSWill Deacon return 0; 307048ec83bcSWill Deacon } 307148ec83bcSWill Deacon 307248ec83bcSWill Deacon static int arm_smmu_init_structures(struct arm_smmu_device *smmu) 307348ec83bcSWill Deacon { 307448ec83bcSWill Deacon int ret; 307548ec83bcSWill Deacon 3076cdf315f9SJean-Philippe Brucker mutex_init(&smmu->streams_mutex); 3077cdf315f9SJean-Philippe Brucker smmu->streams = RB_ROOT; 3078cdf315f9SJean-Philippe Brucker 307948ec83bcSWill Deacon ret = arm_smmu_init_queues(smmu); 308048ec83bcSWill Deacon if (ret) 308148ec83bcSWill Deacon return ret; 308248ec83bcSWill Deacon 308304fa26c7SWill Deacon return arm_smmu_init_strtab(smmu); 308448ec83bcSWill Deacon } 308548ec83bcSWill Deacon 308648ec83bcSWill Deacon static int arm_smmu_write_reg_sync(struct arm_smmu_device *smmu, u32 val, 308748ec83bcSWill Deacon unsigned int reg_off, unsigned int ack_off) 308848ec83bcSWill Deacon { 308948ec83bcSWill Deacon u32 reg; 309048ec83bcSWill Deacon 309148ec83bcSWill Deacon writel_relaxed(val, smmu->base + reg_off); 309248ec83bcSWill Deacon return readl_relaxed_poll_timeout(smmu->base + ack_off, reg, reg == val, 309348ec83bcSWill Deacon 1, ARM_SMMU_POLL_TIMEOUT_US); 309448ec83bcSWill Deacon } 309548ec83bcSWill Deacon 3096dc87a98dSRobin Murphy /* GBPA is "special" */ 3097dc87a98dSRobin Murphy static int arm_smmu_update_gbpa(struct arm_smmu_device *smmu, u32 set, u32 clr) 3098dc87a98dSRobin Murphy { 3099dc87a98dSRobin Murphy int ret; 3100dc87a98dSRobin Murphy u32 reg, __iomem *gbpa = smmu->base + ARM_SMMU_GBPA; 3101dc87a98dSRobin Murphy 3102dc87a98dSRobin Murphy ret = readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE), 3103dc87a98dSRobin Murphy 1, ARM_SMMU_POLL_TIMEOUT_US); 3104dc87a98dSRobin Murphy if (ret) 3105dc87a98dSRobin Murphy return ret; 3106dc87a98dSRobin Murphy 3107dc87a98dSRobin Murphy reg &= ~clr; 3108dc87a98dSRobin Murphy reg |= set; 3109dc87a98dSRobin Murphy writel_relaxed(reg | GBPA_UPDATE, gbpa); 3110b63b3439SWill Deacon ret = readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE), 3111dc87a98dSRobin Murphy 1, ARM_SMMU_POLL_TIMEOUT_US); 3112b63b3439SWill Deacon 3113b63b3439SWill Deacon if (ret) 3114b63b3439SWill Deacon dev_err(smmu->dev, "GBPA not responding to update\n"); 3115b63b3439SWill Deacon return ret; 3116dc87a98dSRobin Murphy } 3117dc87a98dSRobin Murphy 3118166bdbd2SMarc Zyngier static void arm_smmu_free_msis(void *data) 3119166bdbd2SMarc Zyngier { 3120166bdbd2SMarc Zyngier struct device *dev = data; 3121166bdbd2SMarc Zyngier platform_msi_domain_free_irqs(dev); 3122166bdbd2SMarc Zyngier } 3123166bdbd2SMarc Zyngier 3124166bdbd2SMarc Zyngier static void arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg) 3125166bdbd2SMarc Zyngier { 3126166bdbd2SMarc Zyngier phys_addr_t doorbell; 3127166bdbd2SMarc Zyngier struct device *dev = msi_desc_to_dev(desc); 3128166bdbd2SMarc Zyngier struct arm_smmu_device *smmu = dev_get_drvdata(dev); 3129166bdbd2SMarc Zyngier phys_addr_t *cfg = arm_smmu_msi_cfg[desc->platform.msi_index]; 3130166bdbd2SMarc Zyngier 3131166bdbd2SMarc Zyngier doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo; 31321cf9e54eSRobin Murphy doorbell &= MSI_CFG0_ADDR_MASK; 3133166bdbd2SMarc Zyngier 3134166bdbd2SMarc Zyngier writeq_relaxed(doorbell, smmu->base + cfg[0]); 3135166bdbd2SMarc Zyngier writel_relaxed(msg->data, smmu->base + cfg[1]); 3136cbcee19aSRobin Murphy writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE, smmu->base + cfg[2]); 3137166bdbd2SMarc Zyngier } 3138166bdbd2SMarc Zyngier 3139166bdbd2SMarc Zyngier static void arm_smmu_setup_msis(struct arm_smmu_device *smmu) 3140166bdbd2SMarc Zyngier { 3141166bdbd2SMarc Zyngier struct msi_desc *desc; 3142166bdbd2SMarc Zyngier int ret, nvec = ARM_SMMU_MAX_MSIS; 3143166bdbd2SMarc Zyngier struct device *dev = smmu->dev; 3144166bdbd2SMarc Zyngier 3145166bdbd2SMarc Zyngier /* Clear the MSI address regs */ 3146166bdbd2SMarc Zyngier writeq_relaxed(0, smmu->base + ARM_SMMU_GERROR_IRQ_CFG0); 3147166bdbd2SMarc Zyngier writeq_relaxed(0, smmu->base + ARM_SMMU_EVTQ_IRQ_CFG0); 3148166bdbd2SMarc Zyngier 3149166bdbd2SMarc Zyngier if (smmu->features & ARM_SMMU_FEAT_PRI) 3150166bdbd2SMarc Zyngier writeq_relaxed(0, smmu->base + ARM_SMMU_PRIQ_IRQ_CFG0); 3151166bdbd2SMarc Zyngier else 3152166bdbd2SMarc Zyngier nvec--; 3153166bdbd2SMarc Zyngier 3154166bdbd2SMarc Zyngier if (!(smmu->features & ARM_SMMU_FEAT_MSI)) 3155166bdbd2SMarc Zyngier return; 3156166bdbd2SMarc Zyngier 3157940ded9cSNate Watterson if (!dev->msi_domain) { 3158940ded9cSNate Watterson dev_info(smmu->dev, "msi_domain absent - falling back to wired irqs\n"); 3159940ded9cSNate Watterson return; 3160940ded9cSNate Watterson } 3161940ded9cSNate Watterson 3162166bdbd2SMarc Zyngier /* Allocate MSIs for evtq, gerror and priq. Ignore cmdq */ 3163166bdbd2SMarc Zyngier ret = platform_msi_domain_alloc_irqs(dev, nvec, arm_smmu_write_msi_msg); 3164166bdbd2SMarc Zyngier if (ret) { 3165940ded9cSNate Watterson dev_warn(dev, "failed to allocate MSIs - falling back to wired irqs\n"); 3166166bdbd2SMarc Zyngier return; 3167166bdbd2SMarc Zyngier } 3168166bdbd2SMarc Zyngier 3169166bdbd2SMarc Zyngier for_each_msi_entry(desc, dev) { 3170166bdbd2SMarc Zyngier switch (desc->platform.msi_index) { 3171166bdbd2SMarc Zyngier case EVTQ_MSI_INDEX: 3172166bdbd2SMarc Zyngier smmu->evtq.q.irq = desc->irq; 3173166bdbd2SMarc Zyngier break; 3174166bdbd2SMarc Zyngier case GERROR_MSI_INDEX: 3175166bdbd2SMarc Zyngier smmu->gerr_irq = desc->irq; 3176166bdbd2SMarc Zyngier break; 3177166bdbd2SMarc Zyngier case PRIQ_MSI_INDEX: 3178166bdbd2SMarc Zyngier smmu->priq.q.irq = desc->irq; 3179166bdbd2SMarc Zyngier break; 3180166bdbd2SMarc Zyngier default: /* Unknown */ 3181166bdbd2SMarc Zyngier continue; 3182166bdbd2SMarc Zyngier } 3183166bdbd2SMarc Zyngier } 3184166bdbd2SMarc Zyngier 3185166bdbd2SMarc Zyngier /* Add callback to free MSIs on teardown */ 3186166bdbd2SMarc Zyngier devm_add_action(dev, arm_smmu_free_msis, dev); 3187166bdbd2SMarc Zyngier } 3188166bdbd2SMarc Zyngier 3189f935448aSGeetha Sowjanya static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu) 319048ec83bcSWill Deacon { 3191f935448aSGeetha Sowjanya int irq, ret; 319248ec83bcSWill Deacon 3193166bdbd2SMarc Zyngier arm_smmu_setup_msis(smmu); 319448ec83bcSWill Deacon 3195166bdbd2SMarc Zyngier /* Request interrupt lines */ 319648ec83bcSWill Deacon irq = smmu->evtq.q.irq; 319748ec83bcSWill Deacon if (irq) { 3198b4163fb3SJean-Philippe Brucker ret = devm_request_threaded_irq(smmu->dev, irq, NULL, 319948ec83bcSWill Deacon arm_smmu_evtq_thread, 3200b4163fb3SJean-Philippe Brucker IRQF_ONESHOT, 3201b4163fb3SJean-Philippe Brucker "arm-smmu-v3-evtq", smmu); 3202287980e4SArnd Bergmann if (ret < 0) 320348ec83bcSWill Deacon dev_warn(smmu->dev, "failed to enable evtq irq\n"); 32044c8996d7SRobin Murphy } else { 32054c8996d7SRobin Murphy dev_warn(smmu->dev, "no evtq irq - events will not be reported!\n"); 320648ec83bcSWill Deacon } 320748ec83bcSWill Deacon 320848ec83bcSWill Deacon irq = smmu->gerr_irq; 320948ec83bcSWill Deacon if (irq) { 321048ec83bcSWill Deacon ret = devm_request_irq(smmu->dev, irq, arm_smmu_gerror_handler, 321148ec83bcSWill Deacon 0, "arm-smmu-v3-gerror", smmu); 3212287980e4SArnd Bergmann if (ret < 0) 321348ec83bcSWill Deacon dev_warn(smmu->dev, "failed to enable gerror irq\n"); 32144c8996d7SRobin Murphy } else { 32154c8996d7SRobin Murphy dev_warn(smmu->dev, "no gerr irq - errors will not be reported!\n"); 321648ec83bcSWill Deacon } 321748ec83bcSWill Deacon 321848ec83bcSWill Deacon if (smmu->features & ARM_SMMU_FEAT_PRI) { 321948ec83bcSWill Deacon irq = smmu->priq.q.irq; 322048ec83bcSWill Deacon if (irq) { 3221b4163fb3SJean-Philippe Brucker ret = devm_request_threaded_irq(smmu->dev, irq, NULL, 322248ec83bcSWill Deacon arm_smmu_priq_thread, 3223b4163fb3SJean-Philippe Brucker IRQF_ONESHOT, 3224b4163fb3SJean-Philippe Brucker "arm-smmu-v3-priq", 322548ec83bcSWill Deacon smmu); 3226287980e4SArnd Bergmann if (ret < 0) 322748ec83bcSWill Deacon dev_warn(smmu->dev, 322848ec83bcSWill Deacon "failed to enable priq irq\n"); 32294c8996d7SRobin Murphy } else { 32304c8996d7SRobin Murphy dev_warn(smmu->dev, "no priq irq - PRI will be broken\n"); 3231f935448aSGeetha Sowjanya } 3232f935448aSGeetha Sowjanya } 3233f935448aSGeetha Sowjanya } 3234f935448aSGeetha Sowjanya 3235f935448aSGeetha Sowjanya static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu) 3236f935448aSGeetha Sowjanya { 3237f935448aSGeetha Sowjanya int ret, irq; 3238f935448aSGeetha Sowjanya u32 irqen_flags = IRQ_CTRL_EVTQ_IRQEN | IRQ_CTRL_GERROR_IRQEN; 3239f935448aSGeetha Sowjanya 3240f935448aSGeetha Sowjanya /* Disable IRQs first */ 3241f935448aSGeetha Sowjanya ret = arm_smmu_write_reg_sync(smmu, 0, ARM_SMMU_IRQ_CTRL, 3242f935448aSGeetha Sowjanya ARM_SMMU_IRQ_CTRLACK); 3243f935448aSGeetha Sowjanya if (ret) { 3244f935448aSGeetha Sowjanya dev_err(smmu->dev, "failed to disable irqs\n"); 3245f935448aSGeetha Sowjanya return ret; 3246f935448aSGeetha Sowjanya } 3247f935448aSGeetha Sowjanya 3248f935448aSGeetha Sowjanya irq = smmu->combined_irq; 3249f935448aSGeetha Sowjanya if (irq) { 3250f935448aSGeetha Sowjanya /* 3251657135f3SJohn Garry * Cavium ThunderX2 implementation doesn't support unique irq 3252657135f3SJohn Garry * lines. Use a single irq line for all the SMMUv3 interrupts. 3253f935448aSGeetha Sowjanya */ 3254f935448aSGeetha Sowjanya ret = devm_request_threaded_irq(smmu->dev, irq, 3255f935448aSGeetha Sowjanya arm_smmu_combined_irq_handler, 3256f935448aSGeetha Sowjanya arm_smmu_combined_irq_thread, 3257f935448aSGeetha Sowjanya IRQF_ONESHOT, 3258f935448aSGeetha Sowjanya "arm-smmu-v3-combined-irq", smmu); 3259f935448aSGeetha Sowjanya if (ret < 0) 3260f935448aSGeetha Sowjanya dev_warn(smmu->dev, "failed to enable combined irq\n"); 3261f935448aSGeetha Sowjanya } else 3262f935448aSGeetha Sowjanya arm_smmu_setup_unique_irqs(smmu); 3263f935448aSGeetha Sowjanya 3264f935448aSGeetha Sowjanya if (smmu->features & ARM_SMMU_FEAT_PRI) 3265ccd6385dSMarc Zyngier irqen_flags |= IRQ_CTRL_PRIQ_IRQEN; 326648ec83bcSWill Deacon 326748ec83bcSWill Deacon /* Enable interrupt generation on the SMMU */ 3268ccd6385dSMarc Zyngier ret = arm_smmu_write_reg_sync(smmu, irqen_flags, 326948ec83bcSWill Deacon ARM_SMMU_IRQ_CTRL, ARM_SMMU_IRQ_CTRLACK); 327048ec83bcSWill Deacon if (ret) 327148ec83bcSWill Deacon dev_warn(smmu->dev, "failed to enable irqs\n"); 327248ec83bcSWill Deacon 327348ec83bcSWill Deacon return 0; 327448ec83bcSWill Deacon } 327548ec83bcSWill Deacon 327648ec83bcSWill Deacon static int arm_smmu_device_disable(struct arm_smmu_device *smmu) 327748ec83bcSWill Deacon { 327848ec83bcSWill Deacon int ret; 327948ec83bcSWill Deacon 328048ec83bcSWill Deacon ret = arm_smmu_write_reg_sync(smmu, 0, ARM_SMMU_CR0, ARM_SMMU_CR0ACK); 328148ec83bcSWill Deacon if (ret) 328248ec83bcSWill Deacon dev_err(smmu->dev, "failed to clear cr0\n"); 328348ec83bcSWill Deacon 328448ec83bcSWill Deacon return ret; 328548ec83bcSWill Deacon } 328648ec83bcSWill Deacon 3287dc87a98dSRobin Murphy static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass) 328848ec83bcSWill Deacon { 328948ec83bcSWill Deacon int ret; 329048ec83bcSWill Deacon u32 reg, enables; 329148ec83bcSWill Deacon struct arm_smmu_cmdq_ent cmd; 329248ec83bcSWill Deacon 329348ec83bcSWill Deacon /* Clear CR0 and sync (disables SMMU and queue processing) */ 329448ec83bcSWill Deacon reg = readl_relaxed(smmu->base + ARM_SMMU_CR0); 3295b63b3439SWill Deacon if (reg & CR0_SMMUEN) { 329648ec83bcSWill Deacon dev_warn(smmu->dev, "SMMU currently enabled! Resetting...\n"); 32973f54c447SWill Deacon WARN_ON(is_kdump_kernel() && !disable_bypass); 32983f54c447SWill Deacon arm_smmu_update_gbpa(smmu, GBPA_ABORT, 0); 3299b63b3439SWill Deacon } 330048ec83bcSWill Deacon 330148ec83bcSWill Deacon ret = arm_smmu_device_disable(smmu); 330248ec83bcSWill Deacon if (ret) 330348ec83bcSWill Deacon return ret; 330448ec83bcSWill Deacon 330548ec83bcSWill Deacon /* CR1 (table and queue memory attributes) */ 3306cbcee19aSRobin Murphy reg = FIELD_PREP(CR1_TABLE_SH, ARM_SMMU_SH_ISH) | 3307cbcee19aSRobin Murphy FIELD_PREP(CR1_TABLE_OC, CR1_CACHE_WB) | 3308cbcee19aSRobin Murphy FIELD_PREP(CR1_TABLE_IC, CR1_CACHE_WB) | 3309cbcee19aSRobin Murphy FIELD_PREP(CR1_QUEUE_SH, ARM_SMMU_SH_ISH) | 3310cbcee19aSRobin Murphy FIELD_PREP(CR1_QUEUE_OC, CR1_CACHE_WB) | 3311cbcee19aSRobin Murphy FIELD_PREP(CR1_QUEUE_IC, CR1_CACHE_WB); 331248ec83bcSWill Deacon writel_relaxed(reg, smmu->base + ARM_SMMU_CR1); 331348ec83bcSWill Deacon 331448ec83bcSWill Deacon /* CR2 (random crap) */ 33159111aebfSJean-Philippe Brucker reg = CR2_PTM | CR2_RECINVSID; 33169111aebfSJean-Philippe Brucker 33179111aebfSJean-Philippe Brucker if (smmu->features & ARM_SMMU_FEAT_E2H) 33189111aebfSJean-Philippe Brucker reg |= CR2_E2H; 33199111aebfSJean-Philippe Brucker 332048ec83bcSWill Deacon writel_relaxed(reg, smmu->base + ARM_SMMU_CR2); 332148ec83bcSWill Deacon 332248ec83bcSWill Deacon /* Stream table */ 332348ec83bcSWill Deacon writeq_relaxed(smmu->strtab_cfg.strtab_base, 332448ec83bcSWill Deacon smmu->base + ARM_SMMU_STRTAB_BASE); 332548ec83bcSWill Deacon writel_relaxed(smmu->strtab_cfg.strtab_base_cfg, 332648ec83bcSWill Deacon smmu->base + ARM_SMMU_STRTAB_BASE_CFG); 332748ec83bcSWill Deacon 332848ec83bcSWill Deacon /* Command queue */ 332948ec83bcSWill Deacon writeq_relaxed(smmu->cmdq.q.q_base, smmu->base + ARM_SMMU_CMDQ_BASE); 333052be8637SWill Deacon writel_relaxed(smmu->cmdq.q.llq.prod, smmu->base + ARM_SMMU_CMDQ_PROD); 333152be8637SWill Deacon writel_relaxed(smmu->cmdq.q.llq.cons, smmu->base + ARM_SMMU_CMDQ_CONS); 333248ec83bcSWill Deacon 333348ec83bcSWill Deacon enables = CR0_CMDQEN; 333448ec83bcSWill Deacon ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0, 333548ec83bcSWill Deacon ARM_SMMU_CR0ACK); 333648ec83bcSWill Deacon if (ret) { 333748ec83bcSWill Deacon dev_err(smmu->dev, "failed to enable command queue\n"); 333848ec83bcSWill Deacon return ret; 333948ec83bcSWill Deacon } 334048ec83bcSWill Deacon 334148ec83bcSWill Deacon /* Invalidate any cached configuration */ 334248ec83bcSWill Deacon cmd.opcode = CMDQ_OP_CFGI_ALL; 334348ec83bcSWill Deacon arm_smmu_cmdq_issue_cmd(smmu, &cmd); 33442f657addSRobin Murphy arm_smmu_cmdq_issue_sync(smmu); 334548ec83bcSWill Deacon 334648ec83bcSWill Deacon /* Invalidate any stale TLB entries */ 334748ec83bcSWill Deacon if (smmu->features & ARM_SMMU_FEAT_HYP) { 334848ec83bcSWill Deacon cmd.opcode = CMDQ_OP_TLBI_EL2_ALL; 334948ec83bcSWill Deacon arm_smmu_cmdq_issue_cmd(smmu, &cmd); 335048ec83bcSWill Deacon } 335148ec83bcSWill Deacon 335248ec83bcSWill Deacon cmd.opcode = CMDQ_OP_TLBI_NSNH_ALL; 335348ec83bcSWill Deacon arm_smmu_cmdq_issue_cmd(smmu, &cmd); 33542f657addSRobin Murphy arm_smmu_cmdq_issue_sync(smmu); 335548ec83bcSWill Deacon 335648ec83bcSWill Deacon /* Event queue */ 335748ec83bcSWill Deacon writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE); 335886d2d921SRobin Murphy writel_relaxed(smmu->evtq.q.llq.prod, smmu->page1 + ARM_SMMU_EVTQ_PROD); 335986d2d921SRobin Murphy writel_relaxed(smmu->evtq.q.llq.cons, smmu->page1 + ARM_SMMU_EVTQ_CONS); 336048ec83bcSWill Deacon 336148ec83bcSWill Deacon enables |= CR0_EVTQEN; 336248ec83bcSWill Deacon ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0, 336348ec83bcSWill Deacon ARM_SMMU_CR0ACK); 336448ec83bcSWill Deacon if (ret) { 336548ec83bcSWill Deacon dev_err(smmu->dev, "failed to enable event queue\n"); 336648ec83bcSWill Deacon return ret; 336748ec83bcSWill Deacon } 336848ec83bcSWill Deacon 336948ec83bcSWill Deacon /* PRI queue */ 337048ec83bcSWill Deacon if (smmu->features & ARM_SMMU_FEAT_PRI) { 337148ec83bcSWill Deacon writeq_relaxed(smmu->priq.q.q_base, 337248ec83bcSWill Deacon smmu->base + ARM_SMMU_PRIQ_BASE); 337352be8637SWill Deacon writel_relaxed(smmu->priq.q.llq.prod, 337486d2d921SRobin Murphy smmu->page1 + ARM_SMMU_PRIQ_PROD); 337552be8637SWill Deacon writel_relaxed(smmu->priq.q.llq.cons, 337686d2d921SRobin Murphy smmu->page1 + ARM_SMMU_PRIQ_CONS); 337748ec83bcSWill Deacon 337848ec83bcSWill Deacon enables |= CR0_PRIQEN; 337948ec83bcSWill Deacon ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0, 338048ec83bcSWill Deacon ARM_SMMU_CR0ACK); 338148ec83bcSWill Deacon if (ret) { 338248ec83bcSWill Deacon dev_err(smmu->dev, "failed to enable PRI queue\n"); 338348ec83bcSWill Deacon return ret; 338448ec83bcSWill Deacon } 338548ec83bcSWill Deacon } 338648ec83bcSWill Deacon 33879ce27afcSJean-Philippe Brucker if (smmu->features & ARM_SMMU_FEAT_ATS) { 33889ce27afcSJean-Philippe Brucker enables |= CR0_ATSCHK; 33899ce27afcSJean-Philippe Brucker ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0, 33909ce27afcSJean-Philippe Brucker ARM_SMMU_CR0ACK); 33919ce27afcSJean-Philippe Brucker if (ret) { 33929ce27afcSJean-Philippe Brucker dev_err(smmu->dev, "failed to enable ATS check\n"); 33939ce27afcSJean-Philippe Brucker return ret; 33949ce27afcSJean-Philippe Brucker } 33959ce27afcSJean-Philippe Brucker } 33969ce27afcSJean-Philippe Brucker 339748ec83bcSWill Deacon ret = arm_smmu_setup_irqs(smmu); 339848ec83bcSWill Deacon if (ret) { 339948ec83bcSWill Deacon dev_err(smmu->dev, "failed to setup irqs\n"); 340048ec83bcSWill Deacon return ret; 340148ec83bcSWill Deacon } 340248ec83bcSWill Deacon 34033f54c447SWill Deacon if (is_kdump_kernel()) 34043f54c447SWill Deacon enables &= ~(CR0_EVTQEN | CR0_PRIQEN); 3405dc87a98dSRobin Murphy 3406dc87a98dSRobin Murphy /* Enable the SMMU interface, or ensure bypass */ 3407dc87a98dSRobin Murphy if (!bypass || disable_bypass) { 340848ec83bcSWill Deacon enables |= CR0_SMMUEN; 3409dc87a98dSRobin Murphy } else { 3410dc87a98dSRobin Murphy ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT); 3411b63b3439SWill Deacon if (ret) 3412dc87a98dSRobin Murphy return ret; 3413dc87a98dSRobin Murphy } 341448ec83bcSWill Deacon ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0, 341548ec83bcSWill Deacon ARM_SMMU_CR0ACK); 341648ec83bcSWill Deacon if (ret) { 341748ec83bcSWill Deacon dev_err(smmu->dev, "failed to enable SMMU interface\n"); 341848ec83bcSWill Deacon return ret; 341948ec83bcSWill Deacon } 342048ec83bcSWill Deacon 342148ec83bcSWill Deacon return 0; 342248ec83bcSWill Deacon } 342348ec83bcSWill Deacon 34242985b521SLorenzo Pieralisi static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) 342548ec83bcSWill Deacon { 342648ec83bcSWill Deacon u32 reg; 34272985b521SLorenzo Pieralisi bool coherent = smmu->features & ARM_SMMU_FEAT_COHERENCY; 342848ec83bcSWill Deacon 342948ec83bcSWill Deacon /* IDR0 */ 343048ec83bcSWill Deacon reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0); 343148ec83bcSWill Deacon 343248ec83bcSWill Deacon /* 2-level structures */ 3433cbcee19aSRobin Murphy if (FIELD_GET(IDR0_ST_LVL, reg) == IDR0_ST_LVL_2LVL) 343448ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_2_LVL_STRTAB; 343548ec83bcSWill Deacon 343648ec83bcSWill Deacon if (reg & IDR0_CD2L) 343748ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_2_LVL_CDTAB; 343848ec83bcSWill Deacon 343948ec83bcSWill Deacon /* 344048ec83bcSWill Deacon * Translation table endianness. 344148ec83bcSWill Deacon * We currently require the same endianness as the CPU, but this 344248ec83bcSWill Deacon * could be changed later by adding a new IO_PGTABLE_QUIRK. 344348ec83bcSWill Deacon */ 3444cbcee19aSRobin Murphy switch (FIELD_GET(IDR0_TTENDIAN, reg)) { 344548ec83bcSWill Deacon case IDR0_TTENDIAN_MIXED: 344648ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_TT_LE | ARM_SMMU_FEAT_TT_BE; 344748ec83bcSWill Deacon break; 344848ec83bcSWill Deacon #ifdef __BIG_ENDIAN 344948ec83bcSWill Deacon case IDR0_TTENDIAN_BE: 345048ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_TT_BE; 345148ec83bcSWill Deacon break; 345248ec83bcSWill Deacon #else 345348ec83bcSWill Deacon case IDR0_TTENDIAN_LE: 345448ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_TT_LE; 345548ec83bcSWill Deacon break; 345648ec83bcSWill Deacon #endif 345748ec83bcSWill Deacon default: 345848ec83bcSWill Deacon dev_err(smmu->dev, "unknown/unsupported TT endianness!\n"); 345948ec83bcSWill Deacon return -ENXIO; 346048ec83bcSWill Deacon } 346148ec83bcSWill Deacon 346248ec83bcSWill Deacon /* Boolean feature flags */ 346348ec83bcSWill Deacon if (IS_ENABLED(CONFIG_PCI_PRI) && reg & IDR0_PRI) 346448ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_PRI; 346548ec83bcSWill Deacon 346648ec83bcSWill Deacon if (IS_ENABLED(CONFIG_PCI_ATS) && reg & IDR0_ATS) 346748ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_ATS; 346848ec83bcSWill Deacon 346948ec83bcSWill Deacon if (reg & IDR0_SEV) 347048ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_SEV; 347148ec83bcSWill Deacon 3472bd07a20aSBarry Song if (reg & IDR0_MSI) { 347348ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_MSI; 3474bd07a20aSBarry Song if (coherent && !disable_msipolling) 3475bd07a20aSBarry Song smmu->options |= ARM_SMMU_OPT_MSIPOLL; 3476bd07a20aSBarry Song } 347748ec83bcSWill Deacon 34789111aebfSJean-Philippe Brucker if (reg & IDR0_HYP) { 347948ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_HYP; 34809111aebfSJean-Philippe Brucker if (cpus_have_cap(ARM64_HAS_VIRT_HOST_EXTN)) 34819111aebfSJean-Philippe Brucker smmu->features |= ARM_SMMU_FEAT_E2H; 34829111aebfSJean-Philippe Brucker } 348348ec83bcSWill Deacon 348448ec83bcSWill Deacon /* 34852985b521SLorenzo Pieralisi * The coherency feature as set by FW is used in preference to the ID 348648ec83bcSWill Deacon * register, but warn on mismatch. 348748ec83bcSWill Deacon */ 348848ec83bcSWill Deacon if (!!(reg & IDR0_COHACC) != coherent) 34892a22baa2SRobin Murphy dev_warn(smmu->dev, "IDR0.COHACC overridden by FW configuration (%s)\n", 349048ec83bcSWill Deacon coherent ? "true" : "false"); 349148ec83bcSWill Deacon 3492cbcee19aSRobin Murphy switch (FIELD_GET(IDR0_STALL_MODEL, reg)) { 34936380be05SPrem Mallappa case IDR0_STALL_MODEL_FORCE: 34949cff86fdSYisheng Xie smmu->features |= ARM_SMMU_FEAT_STALL_FORCE; 3495df561f66SGustavo A. R. Silva fallthrough; 34969cff86fdSYisheng Xie case IDR0_STALL_MODEL_STALL: 349748ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_STALLS; 34986380be05SPrem Mallappa } 349948ec83bcSWill Deacon 350048ec83bcSWill Deacon if (reg & IDR0_S1P) 350148ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_TRANS_S1; 350248ec83bcSWill Deacon 350348ec83bcSWill Deacon if (reg & IDR0_S2P) 350448ec83bcSWill Deacon smmu->features |= ARM_SMMU_FEAT_TRANS_S2; 350548ec83bcSWill Deacon 350648ec83bcSWill Deacon if (!(reg & (IDR0_S1P | IDR0_S2P))) { 350748ec83bcSWill Deacon dev_err(smmu->dev, "no translation support!\n"); 350848ec83bcSWill Deacon return -ENXIO; 350948ec83bcSWill Deacon } 351048ec83bcSWill Deacon 351148ec83bcSWill Deacon /* We only support the AArch64 table format at present */ 3512cbcee19aSRobin Murphy switch (FIELD_GET(IDR0_TTF, reg)) { 3513f0c453dbSWill Deacon case IDR0_TTF_AARCH32_64: 3514f0c453dbSWill Deacon smmu->ias = 40; 3515df561f66SGustavo A. R. Silva fallthrough; 3516f0c453dbSWill Deacon case IDR0_TTF_AARCH64: 3517f0c453dbSWill Deacon break; 3518f0c453dbSWill Deacon default: 351948ec83bcSWill Deacon dev_err(smmu->dev, "AArch64 table format not supported!\n"); 352048ec83bcSWill Deacon return -ENXIO; 352148ec83bcSWill Deacon } 352248ec83bcSWill Deacon 352348ec83bcSWill Deacon /* ASID/VMID sizes */ 352448ec83bcSWill Deacon smmu->asid_bits = reg & IDR0_ASID16 ? 16 : 8; 352548ec83bcSWill Deacon smmu->vmid_bits = reg & IDR0_VMID16 ? 16 : 8; 352648ec83bcSWill Deacon 352748ec83bcSWill Deacon /* IDR1 */ 352848ec83bcSWill Deacon reg = readl_relaxed(smmu->base + ARM_SMMU_IDR1); 352948ec83bcSWill Deacon if (reg & (IDR1_TABLES_PRESET | IDR1_QUEUES_PRESET | IDR1_REL)) { 353048ec83bcSWill Deacon dev_err(smmu->dev, "embedded implementation not supported\n"); 353148ec83bcSWill Deacon return -ENXIO; 353248ec83bcSWill Deacon } 353348ec83bcSWill Deacon 3534d25f6eadSWill Deacon /* Queue sizes, capped to ensure natural alignment */ 353552be8637SWill Deacon smmu->cmdq.q.llq.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT, 3536cbcee19aSRobin Murphy FIELD_GET(IDR1_CMDQS, reg)); 35372af2e72bSWill Deacon if (smmu->cmdq.q.llq.max_n_shift <= ilog2(CMDQ_BATCH_ENTRIES)) { 3538587e6c10SWill Deacon /* 35392af2e72bSWill Deacon * We don't support splitting up batches, so one batch of 35402af2e72bSWill Deacon * commands plus an extra sync needs to fit inside the command 35412af2e72bSWill Deacon * queue. There's also no way we can handle the weird alignment 35422af2e72bSWill Deacon * restrictions on the base pointer for a unit-length queue. 3543587e6c10SWill Deacon */ 35442af2e72bSWill Deacon dev_err(smmu->dev, "command queue size <= %d entries not supported\n", 35452af2e72bSWill Deacon CMDQ_BATCH_ENTRIES); 354648ec83bcSWill Deacon return -ENXIO; 354748ec83bcSWill Deacon } 354848ec83bcSWill Deacon 354952be8637SWill Deacon smmu->evtq.q.llq.max_n_shift = min_t(u32, EVTQ_MAX_SZ_SHIFT, 3550cbcee19aSRobin Murphy FIELD_GET(IDR1_EVTQS, reg)); 355152be8637SWill Deacon smmu->priq.q.llq.max_n_shift = min_t(u32, PRIQ_MAX_SZ_SHIFT, 3552cbcee19aSRobin Murphy FIELD_GET(IDR1_PRIQS, reg)); 355348ec83bcSWill Deacon 355448ec83bcSWill Deacon /* SID/SSID sizes */ 3555cbcee19aSRobin Murphy smmu->ssid_bits = FIELD_GET(IDR1_SSIDSIZE, reg); 3556cbcee19aSRobin Murphy smmu->sid_bits = FIELD_GET(IDR1_SIDSIZE, reg); 355748ec83bcSWill Deacon 3558692c4e42SNate Watterson /* 3559692c4e42SNate Watterson * If the SMMU supports fewer bits than would fill a single L2 stream 3560692c4e42SNate Watterson * table, use a linear table instead. 3561692c4e42SNate Watterson */ 3562692c4e42SNate Watterson if (smmu->sid_bits <= STRTAB_SPLIT) 3563692c4e42SNate Watterson smmu->features &= ~ARM_SMMU_FEAT_2_LVL_STRTAB; 3564692c4e42SNate Watterson 35656a481a95SRob Herring /* IDR3 */ 35666a481a95SRob Herring reg = readl_relaxed(smmu->base + ARM_SMMU_IDR3); 35676a481a95SRob Herring if (FIELD_GET(IDR3_RIL, reg)) 35686a481a95SRob Herring smmu->features |= ARM_SMMU_FEAT_RANGE_INV; 35696a481a95SRob Herring 357048ec83bcSWill Deacon /* IDR5 */ 357148ec83bcSWill Deacon reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5); 357248ec83bcSWill Deacon 357348ec83bcSWill Deacon /* Maximum number of outstanding stalls */ 3574cbcee19aSRobin Murphy smmu->evtq.max_stalls = FIELD_GET(IDR5_STALL_MAX, reg); 357548ec83bcSWill Deacon 357648ec83bcSWill Deacon /* Page sizes */ 357748ec83bcSWill Deacon if (reg & IDR5_GRAN64K) 3578d5466357SRobin Murphy smmu->pgsize_bitmap |= SZ_64K | SZ_512M; 357948ec83bcSWill Deacon if (reg & IDR5_GRAN16K) 3580d5466357SRobin Murphy smmu->pgsize_bitmap |= SZ_16K | SZ_32M; 358148ec83bcSWill Deacon if (reg & IDR5_GRAN4K) 3582d5466357SRobin Murphy smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G; 358348ec83bcSWill Deacon 3584dcd189e6SRobin Murphy /* Input address size */ 3585dcd189e6SRobin Murphy if (FIELD_GET(IDR5_VAX, reg) == IDR5_VAX_52_BIT) 3586dcd189e6SRobin Murphy smmu->features |= ARM_SMMU_FEAT_VAX; 3587dcd189e6SRobin Murphy 358848ec83bcSWill Deacon /* Output address size */ 3589cbcee19aSRobin Murphy switch (FIELD_GET(IDR5_OAS, reg)) { 359048ec83bcSWill Deacon case IDR5_OAS_32_BIT: 359148ec83bcSWill Deacon smmu->oas = 32; 359248ec83bcSWill Deacon break; 359348ec83bcSWill Deacon case IDR5_OAS_36_BIT: 359448ec83bcSWill Deacon smmu->oas = 36; 359548ec83bcSWill Deacon break; 359648ec83bcSWill Deacon case IDR5_OAS_40_BIT: 359748ec83bcSWill Deacon smmu->oas = 40; 359848ec83bcSWill Deacon break; 359948ec83bcSWill Deacon case IDR5_OAS_42_BIT: 360048ec83bcSWill Deacon smmu->oas = 42; 360148ec83bcSWill Deacon break; 360248ec83bcSWill Deacon case IDR5_OAS_44_BIT: 360348ec83bcSWill Deacon smmu->oas = 44; 360448ec83bcSWill Deacon break; 36056619c913SRobin Murphy case IDR5_OAS_52_BIT: 36066619c913SRobin Murphy smmu->oas = 52; 36076619c913SRobin Murphy smmu->pgsize_bitmap |= 1ULL << 42; /* 4TB */ 36086619c913SRobin Murphy break; 360985430968SWill Deacon default: 361085430968SWill Deacon dev_info(smmu->dev, 361185430968SWill Deacon "unknown output address size. Truncating to 48-bit\n"); 3612df561f66SGustavo A. R. Silva fallthrough; 361348ec83bcSWill Deacon case IDR5_OAS_48_BIT: 361448ec83bcSWill Deacon smmu->oas = 48; 361548ec83bcSWill Deacon } 361648ec83bcSWill Deacon 36176619c913SRobin Murphy if (arm_smmu_ops.pgsize_bitmap == -1UL) 36186619c913SRobin Murphy arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap; 36196619c913SRobin Murphy else 36206619c913SRobin Murphy arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap; 36216619c913SRobin Murphy 362248ec83bcSWill Deacon /* Set the DMA mask for our table walker */ 362348ec83bcSWill Deacon if (dma_set_mask_and_coherent(smmu->dev, DMA_BIT_MASK(smmu->oas))) 362448ec83bcSWill Deacon dev_warn(smmu->dev, 362548ec83bcSWill Deacon "failed to set DMA mask for table walker\n"); 362648ec83bcSWill Deacon 3627f0c453dbSWill Deacon smmu->ias = max(smmu->ias, smmu->oas); 362848ec83bcSWill Deacon 3629d744f9e6SJean-Philippe Brucker if (arm_smmu_sva_supported(smmu)) 3630d744f9e6SJean-Philippe Brucker smmu->features |= ARM_SMMU_FEAT_SVA; 3631d744f9e6SJean-Philippe Brucker 363248ec83bcSWill Deacon dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n", 363348ec83bcSWill Deacon smmu->ias, smmu->oas, smmu->features); 363448ec83bcSWill Deacon return 0; 363548ec83bcSWill Deacon } 363648ec83bcSWill Deacon 3637e4dadfa8SLorenzo Pieralisi #ifdef CONFIG_ACPI 3638e5b829deSLinu Cherian static void acpi_smmu_get_options(u32 model, struct arm_smmu_device *smmu) 3639e5b829deSLinu Cherian { 364099caf177Sshameer switch (model) { 364199caf177Sshameer case ACPI_IORT_SMMU_V3_CAVIUM_CN99XX: 3642e5b829deSLinu Cherian smmu->options |= ARM_SMMU_OPT_PAGE0_REGS_ONLY; 364399caf177Sshameer break; 36446948d4a7SRobin Murphy case ACPI_IORT_SMMU_V3_HISILICON_HI161X: 364599caf177Sshameer smmu->options |= ARM_SMMU_OPT_SKIP_PREFETCH; 364699caf177Sshameer break; 364799caf177Sshameer } 3648e5b829deSLinu Cherian 3649e5b829deSLinu Cherian dev_notice(smmu->dev, "option mask 0x%x\n", smmu->options); 3650e5b829deSLinu Cherian } 3651e5b829deSLinu Cherian 3652e4dadfa8SLorenzo Pieralisi static int arm_smmu_device_acpi_probe(struct platform_device *pdev, 3653e4dadfa8SLorenzo Pieralisi struct arm_smmu_device *smmu) 3654e4dadfa8SLorenzo Pieralisi { 3655e4dadfa8SLorenzo Pieralisi struct acpi_iort_smmu_v3 *iort_smmu; 3656e4dadfa8SLorenzo Pieralisi struct device *dev = smmu->dev; 3657e4dadfa8SLorenzo Pieralisi struct acpi_iort_node *node; 3658e4dadfa8SLorenzo Pieralisi 3659e4dadfa8SLorenzo Pieralisi node = *(struct acpi_iort_node **)dev_get_platdata(dev); 3660e4dadfa8SLorenzo Pieralisi 3661e4dadfa8SLorenzo Pieralisi /* Retrieve SMMUv3 specific data */ 3662e4dadfa8SLorenzo Pieralisi iort_smmu = (struct acpi_iort_smmu_v3 *)node->node_data; 3663e4dadfa8SLorenzo Pieralisi 3664e5b829deSLinu Cherian acpi_smmu_get_options(iort_smmu->model, smmu); 3665e5b829deSLinu Cherian 3666e4dadfa8SLorenzo Pieralisi if (iort_smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE) 3667e4dadfa8SLorenzo Pieralisi smmu->features |= ARM_SMMU_FEAT_COHERENCY; 3668e4dadfa8SLorenzo Pieralisi 3669e4dadfa8SLorenzo Pieralisi return 0; 3670e4dadfa8SLorenzo Pieralisi } 3671e4dadfa8SLorenzo Pieralisi #else 3672e4dadfa8SLorenzo Pieralisi static inline int arm_smmu_device_acpi_probe(struct platform_device *pdev, 3673e4dadfa8SLorenzo Pieralisi struct arm_smmu_device *smmu) 3674e4dadfa8SLorenzo Pieralisi { 3675e4dadfa8SLorenzo Pieralisi return -ENODEV; 3676e4dadfa8SLorenzo Pieralisi } 3677e4dadfa8SLorenzo Pieralisi #endif 3678e4dadfa8SLorenzo Pieralisi 36792985b521SLorenzo Pieralisi static int arm_smmu_device_dt_probe(struct platform_device *pdev, 36802985b521SLorenzo Pieralisi struct arm_smmu_device *smmu) 368148ec83bcSWill Deacon { 368248ec83bcSWill Deacon struct device *dev = &pdev->dev; 3683dc87a98dSRobin Murphy u32 cells; 36842985b521SLorenzo Pieralisi int ret = -EINVAL; 3685dc87a98dSRobin Murphy 3686dc87a98dSRobin Murphy if (of_property_read_u32(dev->of_node, "#iommu-cells", &cells)) 3687dc87a98dSRobin Murphy dev_err(dev, "missing #iommu-cells property\n"); 3688dc87a98dSRobin Murphy else if (cells != 1) 3689dc87a98dSRobin Murphy dev_err(dev, "invalid #iommu-cells value (%d)\n", cells); 3690dc87a98dSRobin Murphy else 36912985b521SLorenzo Pieralisi ret = 0; 36922985b521SLorenzo Pieralisi 36932985b521SLorenzo Pieralisi parse_driver_options(smmu); 36942985b521SLorenzo Pieralisi 36952985b521SLorenzo Pieralisi if (of_dma_is_coherent(dev->of_node)) 36962985b521SLorenzo Pieralisi smmu->features |= ARM_SMMU_FEAT_COHERENCY; 36972985b521SLorenzo Pieralisi 36982985b521SLorenzo Pieralisi return ret; 36992985b521SLorenzo Pieralisi } 37002985b521SLorenzo Pieralisi 3701e5b829deSLinu Cherian static unsigned long arm_smmu_resource_size(struct arm_smmu_device *smmu) 3702e5b829deSLinu Cherian { 3703e5b829deSLinu Cherian if (smmu->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY) 3704e5b829deSLinu Cherian return SZ_64K; 3705e5b829deSLinu Cherian else 3706e5b829deSLinu Cherian return SZ_128K; 3707e5b829deSLinu Cherian } 3708e5b829deSLinu Cherian 3709ab246774SWill Deacon static int arm_smmu_set_bus_ops(struct iommu_ops *ops) 3710ab246774SWill Deacon { 3711ab246774SWill Deacon int err; 3712ab246774SWill Deacon 3713ab246774SWill Deacon #ifdef CONFIG_PCI 3714ab246774SWill Deacon if (pci_bus_type.iommu_ops != ops) { 3715ab246774SWill Deacon err = bus_set_iommu(&pci_bus_type, ops); 3716ab246774SWill Deacon if (err) 3717ab246774SWill Deacon return err; 3718ab246774SWill Deacon } 3719ab246774SWill Deacon #endif 3720ab246774SWill Deacon #ifdef CONFIG_ARM_AMBA 3721ab246774SWill Deacon if (amba_bustype.iommu_ops != ops) { 3722ab246774SWill Deacon err = bus_set_iommu(&amba_bustype, ops); 3723ab246774SWill Deacon if (err) 3724ab246774SWill Deacon goto err_reset_pci_ops; 3725ab246774SWill Deacon } 3726ab246774SWill Deacon #endif 3727ab246774SWill Deacon if (platform_bus_type.iommu_ops != ops) { 3728ab246774SWill Deacon err = bus_set_iommu(&platform_bus_type, ops); 3729ab246774SWill Deacon if (err) 3730ab246774SWill Deacon goto err_reset_amba_ops; 3731ab246774SWill Deacon } 3732ab246774SWill Deacon 3733ab246774SWill Deacon return 0; 3734ab246774SWill Deacon 3735ab246774SWill Deacon err_reset_amba_ops: 3736ab246774SWill Deacon #ifdef CONFIG_ARM_AMBA 3737ab246774SWill Deacon bus_set_iommu(&amba_bustype, NULL); 3738ab246774SWill Deacon #endif 3739ab246774SWill Deacon err_reset_pci_ops: __maybe_unused; 3740ab246774SWill Deacon #ifdef CONFIG_PCI 3741ab246774SWill Deacon bus_set_iommu(&pci_bus_type, NULL); 3742ab246774SWill Deacon #endif 3743ab246774SWill Deacon return err; 3744ab246774SWill Deacon } 3745ab246774SWill Deacon 374652f3fab0SJean-Philippe Brucker static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t start, 374752f3fab0SJean-Philippe Brucker resource_size_t size) 374852f3fab0SJean-Philippe Brucker { 3749932bc8c7SZhen Lei struct resource res = DEFINE_RES_MEM(start, size); 375052f3fab0SJean-Philippe Brucker 375152f3fab0SJean-Philippe Brucker return devm_ioremap_resource(dev, &res); 375252f3fab0SJean-Philippe Brucker } 375352f3fab0SJean-Philippe Brucker 37542985b521SLorenzo Pieralisi static int arm_smmu_device_probe(struct platform_device *pdev) 37552985b521SLorenzo Pieralisi { 37562985b521SLorenzo Pieralisi int irq, ret; 37572985b521SLorenzo Pieralisi struct resource *res; 37589648cbc9SJoerg Roedel resource_size_t ioaddr; 37592985b521SLorenzo Pieralisi struct arm_smmu_device *smmu; 37602985b521SLorenzo Pieralisi struct device *dev = &pdev->dev; 37612985b521SLorenzo Pieralisi bool bypass; 376248ec83bcSWill Deacon 376348ec83bcSWill Deacon smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); 376448ec83bcSWill Deacon if (!smmu) { 376548ec83bcSWill Deacon dev_err(dev, "failed to allocate arm_smmu_device\n"); 376648ec83bcSWill Deacon return -ENOMEM; 376748ec83bcSWill Deacon } 376848ec83bcSWill Deacon smmu->dev = dev; 376948ec83bcSWill Deacon 3770e5b829deSLinu Cherian if (dev->of_node) { 3771e5b829deSLinu Cherian ret = arm_smmu_device_dt_probe(pdev, smmu); 3772e5b829deSLinu Cherian } else { 3773e5b829deSLinu Cherian ret = arm_smmu_device_acpi_probe(pdev, smmu); 3774e5b829deSLinu Cherian if (ret == -ENODEV) 3775e5b829deSLinu Cherian return ret; 3776e5b829deSLinu Cherian } 3777e5b829deSLinu Cherian 3778e5b829deSLinu Cherian /* Set bypass mode according to firmware probing result */ 3779e5b829deSLinu Cherian bypass = !!ret; 3780e5b829deSLinu Cherian 378148ec83bcSWill Deacon /* Base address */ 378248ec83bcSWill Deacon res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 3783322a9bbbSMasahiro Yamada if (resource_size(res) < arm_smmu_resource_size(smmu)) { 378448ec83bcSWill Deacon dev_err(dev, "MMIO region too small (%pr)\n", res); 378548ec83bcSWill Deacon return -EINVAL; 378648ec83bcSWill Deacon } 37879648cbc9SJoerg Roedel ioaddr = res->start; 378848ec83bcSWill Deacon 378952f3fab0SJean-Philippe Brucker /* 379052f3fab0SJean-Philippe Brucker * Don't map the IMPLEMENTATION DEFINED regions, since they may contain 379152f3fab0SJean-Philippe Brucker * the PMCG registers which are reserved by the PMU driver. 379252f3fab0SJean-Philippe Brucker */ 379352f3fab0SJean-Philippe Brucker smmu->base = arm_smmu_ioremap(dev, ioaddr, ARM_SMMU_REG_SZ); 379448ec83bcSWill Deacon if (IS_ERR(smmu->base)) 379548ec83bcSWill Deacon return PTR_ERR(smmu->base); 379648ec83bcSWill Deacon 379752f3fab0SJean-Philippe Brucker if (arm_smmu_resource_size(smmu) > SZ_64K) { 379852f3fab0SJean-Philippe Brucker smmu->page1 = arm_smmu_ioremap(dev, ioaddr + SZ_64K, 379952f3fab0SJean-Philippe Brucker ARM_SMMU_REG_SZ); 380052f3fab0SJean-Philippe Brucker if (IS_ERR(smmu->page1)) 380152f3fab0SJean-Philippe Brucker return PTR_ERR(smmu->page1); 380252f3fab0SJean-Philippe Brucker } else { 380352f3fab0SJean-Philippe Brucker smmu->page1 = smmu->base; 380452f3fab0SJean-Philippe Brucker } 380552f3fab0SJean-Philippe Brucker 380648ec83bcSWill Deacon /* Interrupt lines */ 3807f935448aSGeetha Sowjanya 3808f7aff1a9SJean-Philippe Brucker irq = platform_get_irq_byname_optional(pdev, "combined"); 3809f935448aSGeetha Sowjanya if (irq > 0) 3810f935448aSGeetha Sowjanya smmu->combined_irq = irq; 3811f935448aSGeetha Sowjanya else { 3812f7aff1a9SJean-Philippe Brucker irq = platform_get_irq_byname_optional(pdev, "eventq"); 381348ec83bcSWill Deacon if (irq > 0) 381448ec83bcSWill Deacon smmu->evtq.q.irq = irq; 381548ec83bcSWill Deacon 3816f7aff1a9SJean-Philippe Brucker irq = platform_get_irq_byname_optional(pdev, "priq"); 381748ec83bcSWill Deacon if (irq > 0) 381848ec83bcSWill Deacon smmu->priq.q.irq = irq; 381948ec83bcSWill Deacon 3820f7aff1a9SJean-Philippe Brucker irq = platform_get_irq_byname_optional(pdev, "gerror"); 382148ec83bcSWill Deacon if (irq > 0) 382248ec83bcSWill Deacon smmu->gerr_irq = irq; 3823f935448aSGeetha Sowjanya } 382448ec83bcSWill Deacon /* Probe the h/w */ 38252985b521SLorenzo Pieralisi ret = arm_smmu_device_hw_probe(smmu); 382648ec83bcSWill Deacon if (ret) 382748ec83bcSWill Deacon return ret; 382848ec83bcSWill Deacon 382948ec83bcSWill Deacon /* Initialise in-memory data structures */ 383048ec83bcSWill Deacon ret = arm_smmu_init_structures(smmu); 383148ec83bcSWill Deacon if (ret) 383248ec83bcSWill Deacon return ret; 383348ec83bcSWill Deacon 3834166bdbd2SMarc Zyngier /* Record our private device structure */ 3835166bdbd2SMarc Zyngier platform_set_drvdata(pdev, smmu); 3836166bdbd2SMarc Zyngier 383748ec83bcSWill Deacon /* Reset the device */ 38388f785154SRobin Murphy ret = arm_smmu_device_reset(smmu, bypass); 38398f785154SRobin Murphy if (ret) 38408f785154SRobin Murphy return ret; 38418f785154SRobin Murphy 38428f785154SRobin Murphy /* And we're up. Go go go! */ 38439648cbc9SJoerg Roedel ret = iommu_device_sysfs_add(&smmu->iommu, dev, NULL, 38449648cbc9SJoerg Roedel "smmu3.%pa", &ioaddr); 38459648cbc9SJoerg Roedel if (ret) 38469648cbc9SJoerg Roedel return ret; 38479648cbc9SJoerg Roedel 38482d471b20SRobin Murphy ret = iommu_device_register(&smmu->iommu, &arm_smmu_ops, dev); 38495c2d0218SArvind Yadav if (ret) { 38505c2d0218SArvind Yadav dev_err(dev, "Failed to register iommu\n"); 38515c2d0218SArvind Yadav return ret; 38525c2d0218SArvind Yadav } 3853778de074SLorenzo Pieralisi 3854ab246774SWill Deacon return arm_smmu_set_bus_ops(&arm_smmu_ops); 3855ec615f43SRobin Murphy } 385648ec83bcSWill Deacon 38576e8fa740SWill Deacon static int arm_smmu_device_remove(struct platform_device *pdev) 385848ec83bcSWill Deacon { 3859941a802dSWill Deacon struct arm_smmu_device *smmu = platform_get_drvdata(pdev); 386048ec83bcSWill Deacon 3861ab246774SWill Deacon arm_smmu_set_bus_ops(NULL); 3862ab246774SWill Deacon iommu_device_unregister(&smmu->iommu); 3863ab246774SWill Deacon iommu_device_sysfs_remove(&smmu->iommu); 386448ec83bcSWill Deacon arm_smmu_device_disable(smmu); 3865395ad89dSJean-Philippe Brucker iopf_queue_free(smmu->evtq.iopf); 38666e8fa740SWill Deacon 386748ec83bcSWill Deacon return 0; 386848ec83bcSWill Deacon } 386948ec83bcSWill Deacon 387048ec83bcSWill Deacon static void arm_smmu_device_shutdown(struct platform_device *pdev) 387148ec83bcSWill Deacon { 38726e8fa740SWill Deacon arm_smmu_device_remove(pdev); 38737aa8619aSNate Watterson } 38747aa8619aSNate Watterson 3875ebdd13c9SArvind Yadav static const struct of_device_id arm_smmu_of_match[] = { 387648ec83bcSWill Deacon { .compatible = "arm,smmu-v3", }, 387748ec83bcSWill Deacon { }, 387848ec83bcSWill Deacon }; 38796e8fa740SWill Deacon MODULE_DEVICE_TABLE(of, arm_smmu_of_match); 388048ec83bcSWill Deacon 388132784a95SJean-Philippe Brucker static void arm_smmu_driver_unregister(struct platform_driver *drv) 388232784a95SJean-Philippe Brucker { 388332784a95SJean-Philippe Brucker arm_smmu_sva_notifier_synchronize(); 388432784a95SJean-Philippe Brucker platform_driver_unregister(drv); 388532784a95SJean-Philippe Brucker } 388632784a95SJean-Philippe Brucker 388748ec83bcSWill Deacon static struct platform_driver arm_smmu_driver = { 388848ec83bcSWill Deacon .driver = { 388948ec83bcSWill Deacon .name = "arm-smmu-v3", 38908efda06fSMasahiro Yamada .of_match_table = arm_smmu_of_match, 3891c07b6426SPaul Gortmaker .suppress_bind_attrs = true, 389248ec83bcSWill Deacon }, 38932985b521SLorenzo Pieralisi .probe = arm_smmu_device_probe, 38946e8fa740SWill Deacon .remove = arm_smmu_device_remove, 38957aa8619aSNate Watterson .shutdown = arm_smmu_device_shutdown, 389648ec83bcSWill Deacon }; 389732784a95SJean-Philippe Brucker module_driver(arm_smmu_driver, platform_driver_register, 389832784a95SJean-Philippe Brucker arm_smmu_driver_unregister); 38996e8fa740SWill Deacon 39006e8fa740SWill Deacon MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations"); 39011ea27ee2SWill Deacon MODULE_AUTHOR("Will Deacon <will@kernel.org>"); 3902d3daf666SArd Biesheuvel MODULE_ALIAS("platform:arm-smmu-v3"); 39036e8fa740SWill Deacon MODULE_LICENSE("GPL v2"); 3904