Loading drivers/iommu/arm-smmu.c +43 −32 Original line number Diff line number Diff line Loading @@ -285,14 +285,22 @@ static int selftest; module_param_named(selftest, selftest, int, 0644); static int irq_count; struct arm_smmu_cf_selftest_data { struct arm_smmu_device *smmu; int cbndx; }; static DECLARE_WAIT_QUEUE_HEAD(wait_int); static irqreturn_t arm_smmu_cf_selftest(int irq, void *cb_base) static irqreturn_t arm_smmu_cf_selftest(int irq, void *data) { u32 fsr; struct irq_data *irq_data = irq_get_irq_data(irq); struct arm_smmu_cf_selftest_data *cb_data = data; struct arm_smmu_device *smmu = cb_data->smmu; int idx = cb_data->cbndx; unsigned long hwirq = ULONG_MAX; fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR); fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR); irq_count++; if (irq_data) Loading @@ -300,7 +308,7 @@ static irqreturn_t arm_smmu_cf_selftest(int irq, void *cb_base) pr_info("Interrupt (irq:%d hwirq:%ld) received, fsr:0x%x\n", irq, hwirq, fsr); writel_relaxed(fsr, cb_base + ARM_SMMU_CB_FSR); arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr); wake_up(&wait_int); return IRQ_HANDLED; Loading @@ -310,6 +318,7 @@ static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu) { int cb; int cb_count = 0; struct arm_smmu_cf_selftest_data *cb_data; if (!selftest) return; Loading @@ -319,22 +328,26 @@ static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu) if (smmu->version < ARM_SMMU_V2) return; cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL); if (!cb_data) return; cb_data->smmu = smmu; for_each_clear_bit_from(cb, smmu->context_map, smmu->num_context_banks) { int irq; int ret; void *cb_base; u32 reg; u32 reg_orig; int irq_cnt; irq = smmu->irqs[smmu->num_global_irqs + cb]; cb_base = ARM_SMMU_CB(smmu, cb); cb_data->cbndx = cb; ret = devm_request_threaded_irq(smmu->dev, irq, NULL, arm_smmu_cf_selftest, IRQF_ONESHOT | IRQF_SHARED, "arm-smmu-context-fault", cb_base); "arm-smmu-context-fault", cb_data); if (ret < 0) { dev_err(smmu->dev, "Failed to request cntx IRQ %d (%u)\n", Loading @@ -345,25 +358,26 @@ static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu) cb_count++; irq_cnt = irq_count; reg_orig = readl_relaxed(cb_base + ARM_SMMU_CB_SCTLR); reg_orig = arm_smmu_cb_read(smmu, cb, ARM_SMMU_CB_SCTLR); reg = reg_orig | SCTLR_CFIE | SCTLR_CFRE; writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR); arm_smmu_cb_write(smmu, cb, ARM_SMMU_CB_SCTLR, reg); dev_info(smmu->dev, "Testing cntx %d irq %d\n", cb, irq); /* Make sure ARM_SMMU_CB_SCTLR is configured */ wmb(); writel_relaxed(FSR_TF, cb_base + ARM_SMMU_CB_FSRRESTORE); arm_smmu_cb_write(smmu, cb, ARM_SMMU_CB_FSRRESTORE, FSR_TF); wait_event_timeout(wait_int, (irq_count > irq_cnt), msecs_to_jiffies(1000)); /* Make sure ARM_SMMU_CB_FSRRESTORE is written to */ wmb(); writel_relaxed(reg_orig, cb_base + ARM_SMMU_CB_SCTLR); devm_free_irq(smmu->dev, irq, cb_base); arm_smmu_cb_write(smmu, cb, ARM_SMMU_CB_SCTLR, reg_orig); devm_free_irq(smmu->dev, irq, cb_data); } kfree(cb_data); dev_info(smmu->dev, "Interrupt selftest completed...\n"); dev_info(smmu->dev, Loading Loading @@ -4834,30 +4848,28 @@ module_exit(arm_smmu_exit); #define TCU_HW_VERSION_HLOS1 (0x18) #define DEBUG_SID_HALT_REG 0x0 #define DEBUG_SID_HALT_VAL (0x1 << 16) #define DEBUG_SID_HALT_SID_MASK 0x3ff #define DEBUG_SID_HALT_REQ BIT(16) #define DEBUG_SID_HALT_SID GENMASK(9, 0) #define DEBUG_VA_ADDR_REG 0x8 #define DEBUG_TXN_TRIGG_REG 0x18 #define DEBUG_TXN_AXPROT_SHIFT 6 #define DEBUG_TXN_AXCACHE_SHIFT 2 #define DEBUG_TXN_AXPROT GENMASK(8, 6) #define DEBUG_TXN_AXCACHE GENMASK(5, 2) #define DEBUG_TRX_WRITE (0x1 << 1) #define DEBUG_TXN_READ (0x0 << 1) #define DEBUG_TXN_TRIGGER 0x1 #define DEBUG_TXN_TRIGGER BIT(0) #define DEBUG_SR_HALT_ACK_REG 0x20 #define DEBUG_SR_HALT_ACK_VAL (0x1 << 1) #define DEBUG_SR_ECATS_RUNNING_VAL (0x1 << 0) #define DEBUG_PAR_REG 0x28 #define DEBUG_PAR_PA_MASK ((0x1ULL << 36) - 1) #define DEBUG_PAR_PA_SHIFT 12 #define DEBUG_PAR_FAULT_VAL 0x1 #define DEBUG_PAR_PA GENMASK_ULL(47, 12) #define DEBUG_PAR_FAULT_VAL BIT(0) #define DEBUG_AXUSER_REG 0x30 #define DEBUG_AXUSER_CDMID_MASK 0xff #define DEBUG_AXUSER_CDMID_SHIFT 36 #define DEBUG_AXUSER_CDMID GENMASK_ULL(43, 36) #define DEBUG_AXUSER_CDMID_VAL 255 #define TBU_DBG_TIMEOUT_US 100 Loading Loading @@ -4943,7 +4955,7 @@ static int qsmmuv500_tbu_halt(struct qsmmuv500_tbu_device *tbu, base = tbu->base; halt = readl_relaxed(base + DEBUG_SID_HALT_REG); halt |= DEBUG_SID_HALT_VAL; halt |= DEBUG_SID_HALT_REQ; writel_relaxed(halt, base + DEBUG_SID_HALT_REG); if (!readl_poll_timeout_atomic(base + DEBUG_SR_HALT_ACK_REG, status, Loading Loading @@ -5007,7 +5019,7 @@ static void qsmmuv500_tbu_resume(struct qsmmuv500_tbu_device *tbu) base = tbu->base; val = readl_relaxed(base + DEBUG_SID_HALT_REG); val &= ~DEBUG_SID_HALT_VAL; val &= ~DEBUG_SID_HALT_REQ; writel_relaxed(val, base + DEBUG_SID_HALT_REG); tbu->halt_count = 0; Loading Loading @@ -5119,12 +5131,11 @@ static phys_addr_t qsmmuv500_iova_to_phys( redo: /* Set address and stream-id */ val = readq_relaxed(tbu->base + DEBUG_SID_HALT_REG); val &= ~DEBUG_SID_HALT_SID_MASK; val |= sid & DEBUG_SID_HALT_SID_MASK; val &= ~DEBUG_SID_HALT_SID; val |= FIELD_PREP(DEBUG_SID_HALT_SID, sid); writeq_relaxed(val, tbu->base + DEBUG_SID_HALT_REG); writeq_relaxed(iova, tbu->base + DEBUG_VA_ADDR_REG); val = (u64)(DEBUG_AXUSER_CDMID_VAL & DEBUG_AXUSER_CDMID_MASK) << DEBUG_AXUSER_CDMID_SHIFT; val = FIELD_PREP(DEBUG_AXUSER_CDMID, DEBUG_AXUSER_CDMID_VAL); writeq_relaxed(val, tbu->base + DEBUG_AXUSER_REG); /* Loading @@ -5132,9 +5143,9 @@ static phys_addr_t qsmmuv500_iova_to_phys( * Priviledged, nonsecure, data transaction * Read operation. */ val = 0xF << DEBUG_TXN_AXCACHE_SHIFT; val |= 0x3 << DEBUG_TXN_AXPROT_SHIFT; val |= DEBUG_TXN_TRIGGER; val = FIELD_PREP(DEBUG_TXN_AXCACHE, 0xF) | FIELD_PREP(DEBUG_TXN_AXPROT, 0x3) | DEBUG_TXN_TRIGGER; writeq_relaxed(val, tbu->base + DEBUG_TXN_TRIGG_REG); ret = 0; Loading Loading @@ -5176,7 +5187,7 @@ static phys_addr_t qsmmuv500_iova_to_phys( ret = -EINVAL; } phys = (val >> DEBUG_PAR_PA_SHIFT) & DEBUG_PAR_PA_MASK; phys = FIELD_GET(DEBUG_PAR_PA, val); if (ret < 0) phys = 0; Loading @@ -5184,7 +5195,7 @@ static phys_addr_t qsmmuv500_iova_to_phys( writeq_relaxed(0, tbu->base + DEBUG_TXN_TRIGG_REG); writeq_relaxed(0, tbu->base + DEBUG_VA_ADDR_REG); val = readl_relaxed(tbu->base + DEBUG_SID_HALT_REG); val &= ~DEBUG_SID_HALT_SID_MASK; val &= ~DEBUG_SID_HALT_SID; writel_relaxed(val, tbu->base + DEBUG_SID_HALT_REG); /* Loading Loading
drivers/iommu/arm-smmu.c +43 −32 Original line number Diff line number Diff line Loading @@ -285,14 +285,22 @@ static int selftest; module_param_named(selftest, selftest, int, 0644); static int irq_count; struct arm_smmu_cf_selftest_data { struct arm_smmu_device *smmu; int cbndx; }; static DECLARE_WAIT_QUEUE_HEAD(wait_int); static irqreturn_t arm_smmu_cf_selftest(int irq, void *cb_base) static irqreturn_t arm_smmu_cf_selftest(int irq, void *data) { u32 fsr; struct irq_data *irq_data = irq_get_irq_data(irq); struct arm_smmu_cf_selftest_data *cb_data = data; struct arm_smmu_device *smmu = cb_data->smmu; int idx = cb_data->cbndx; unsigned long hwirq = ULONG_MAX; fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR); fsr = arm_smmu_cb_read(smmu, idx, ARM_SMMU_CB_FSR); irq_count++; if (irq_data) Loading @@ -300,7 +308,7 @@ static irqreturn_t arm_smmu_cf_selftest(int irq, void *cb_base) pr_info("Interrupt (irq:%d hwirq:%ld) received, fsr:0x%x\n", irq, hwirq, fsr); writel_relaxed(fsr, cb_base + ARM_SMMU_CB_FSR); arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_FSR, fsr); wake_up(&wait_int); return IRQ_HANDLED; Loading @@ -310,6 +318,7 @@ static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu) { int cb; int cb_count = 0; struct arm_smmu_cf_selftest_data *cb_data; if (!selftest) return; Loading @@ -319,22 +328,26 @@ static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu) if (smmu->version < ARM_SMMU_V2) return; cb_data = kmalloc(sizeof(*cb_data), GFP_KERNEL); if (!cb_data) return; cb_data->smmu = smmu; for_each_clear_bit_from(cb, smmu->context_map, smmu->num_context_banks) { int irq; int ret; void *cb_base; u32 reg; u32 reg_orig; int irq_cnt; irq = smmu->irqs[smmu->num_global_irqs + cb]; cb_base = ARM_SMMU_CB(smmu, cb); cb_data->cbndx = cb; ret = devm_request_threaded_irq(smmu->dev, irq, NULL, arm_smmu_cf_selftest, IRQF_ONESHOT | IRQF_SHARED, "arm-smmu-context-fault", cb_base); "arm-smmu-context-fault", cb_data); if (ret < 0) { dev_err(smmu->dev, "Failed to request cntx IRQ %d (%u)\n", Loading @@ -345,25 +358,26 @@ static void arm_smmu_interrupt_selftest(struct arm_smmu_device *smmu) cb_count++; irq_cnt = irq_count; reg_orig = readl_relaxed(cb_base + ARM_SMMU_CB_SCTLR); reg_orig = arm_smmu_cb_read(smmu, cb, ARM_SMMU_CB_SCTLR); reg = reg_orig | SCTLR_CFIE | SCTLR_CFRE; writel_relaxed(reg, cb_base + ARM_SMMU_CB_SCTLR); arm_smmu_cb_write(smmu, cb, ARM_SMMU_CB_SCTLR, reg); dev_info(smmu->dev, "Testing cntx %d irq %d\n", cb, irq); /* Make sure ARM_SMMU_CB_SCTLR is configured */ wmb(); writel_relaxed(FSR_TF, cb_base + ARM_SMMU_CB_FSRRESTORE); arm_smmu_cb_write(smmu, cb, ARM_SMMU_CB_FSRRESTORE, FSR_TF); wait_event_timeout(wait_int, (irq_count > irq_cnt), msecs_to_jiffies(1000)); /* Make sure ARM_SMMU_CB_FSRRESTORE is written to */ wmb(); writel_relaxed(reg_orig, cb_base + ARM_SMMU_CB_SCTLR); devm_free_irq(smmu->dev, irq, cb_base); arm_smmu_cb_write(smmu, cb, ARM_SMMU_CB_SCTLR, reg_orig); devm_free_irq(smmu->dev, irq, cb_data); } kfree(cb_data); dev_info(smmu->dev, "Interrupt selftest completed...\n"); dev_info(smmu->dev, Loading Loading @@ -4834,30 +4848,28 @@ module_exit(arm_smmu_exit); #define TCU_HW_VERSION_HLOS1 (0x18) #define DEBUG_SID_HALT_REG 0x0 #define DEBUG_SID_HALT_VAL (0x1 << 16) #define DEBUG_SID_HALT_SID_MASK 0x3ff #define DEBUG_SID_HALT_REQ BIT(16) #define DEBUG_SID_HALT_SID GENMASK(9, 0) #define DEBUG_VA_ADDR_REG 0x8 #define DEBUG_TXN_TRIGG_REG 0x18 #define DEBUG_TXN_AXPROT_SHIFT 6 #define DEBUG_TXN_AXCACHE_SHIFT 2 #define DEBUG_TXN_AXPROT GENMASK(8, 6) #define DEBUG_TXN_AXCACHE GENMASK(5, 2) #define DEBUG_TRX_WRITE (0x1 << 1) #define DEBUG_TXN_READ (0x0 << 1) #define DEBUG_TXN_TRIGGER 0x1 #define DEBUG_TXN_TRIGGER BIT(0) #define DEBUG_SR_HALT_ACK_REG 0x20 #define DEBUG_SR_HALT_ACK_VAL (0x1 << 1) #define DEBUG_SR_ECATS_RUNNING_VAL (0x1 << 0) #define DEBUG_PAR_REG 0x28 #define DEBUG_PAR_PA_MASK ((0x1ULL << 36) - 1) #define DEBUG_PAR_PA_SHIFT 12 #define DEBUG_PAR_FAULT_VAL 0x1 #define DEBUG_PAR_PA GENMASK_ULL(47, 12) #define DEBUG_PAR_FAULT_VAL BIT(0) #define DEBUG_AXUSER_REG 0x30 #define DEBUG_AXUSER_CDMID_MASK 0xff #define DEBUG_AXUSER_CDMID_SHIFT 36 #define DEBUG_AXUSER_CDMID GENMASK_ULL(43, 36) #define DEBUG_AXUSER_CDMID_VAL 255 #define TBU_DBG_TIMEOUT_US 100 Loading Loading @@ -4943,7 +4955,7 @@ static int qsmmuv500_tbu_halt(struct qsmmuv500_tbu_device *tbu, base = tbu->base; halt = readl_relaxed(base + DEBUG_SID_HALT_REG); halt |= DEBUG_SID_HALT_VAL; halt |= DEBUG_SID_HALT_REQ; writel_relaxed(halt, base + DEBUG_SID_HALT_REG); if (!readl_poll_timeout_atomic(base + DEBUG_SR_HALT_ACK_REG, status, Loading Loading @@ -5007,7 +5019,7 @@ static void qsmmuv500_tbu_resume(struct qsmmuv500_tbu_device *tbu) base = tbu->base; val = readl_relaxed(base + DEBUG_SID_HALT_REG); val &= ~DEBUG_SID_HALT_VAL; val &= ~DEBUG_SID_HALT_REQ; writel_relaxed(val, base + DEBUG_SID_HALT_REG); tbu->halt_count = 0; Loading Loading @@ -5119,12 +5131,11 @@ static phys_addr_t qsmmuv500_iova_to_phys( redo: /* Set address and stream-id */ val = readq_relaxed(tbu->base + DEBUG_SID_HALT_REG); val &= ~DEBUG_SID_HALT_SID_MASK; val |= sid & DEBUG_SID_HALT_SID_MASK; val &= ~DEBUG_SID_HALT_SID; val |= FIELD_PREP(DEBUG_SID_HALT_SID, sid); writeq_relaxed(val, tbu->base + DEBUG_SID_HALT_REG); writeq_relaxed(iova, tbu->base + DEBUG_VA_ADDR_REG); val = (u64)(DEBUG_AXUSER_CDMID_VAL & DEBUG_AXUSER_CDMID_MASK) << DEBUG_AXUSER_CDMID_SHIFT; val = FIELD_PREP(DEBUG_AXUSER_CDMID, DEBUG_AXUSER_CDMID_VAL); writeq_relaxed(val, tbu->base + DEBUG_AXUSER_REG); /* Loading @@ -5132,9 +5143,9 @@ static phys_addr_t qsmmuv500_iova_to_phys( * Priviledged, nonsecure, data transaction * Read operation. */ val = 0xF << DEBUG_TXN_AXCACHE_SHIFT; val |= 0x3 << DEBUG_TXN_AXPROT_SHIFT; val |= DEBUG_TXN_TRIGGER; val = FIELD_PREP(DEBUG_TXN_AXCACHE, 0xF) | FIELD_PREP(DEBUG_TXN_AXPROT, 0x3) | DEBUG_TXN_TRIGGER; writeq_relaxed(val, tbu->base + DEBUG_TXN_TRIGG_REG); ret = 0; Loading Loading @@ -5176,7 +5187,7 @@ static phys_addr_t qsmmuv500_iova_to_phys( ret = -EINVAL; } phys = (val >> DEBUG_PAR_PA_SHIFT) & DEBUG_PAR_PA_MASK; phys = FIELD_GET(DEBUG_PAR_PA, val); if (ret < 0) phys = 0; Loading @@ -5184,7 +5195,7 @@ static phys_addr_t qsmmuv500_iova_to_phys( writeq_relaxed(0, tbu->base + DEBUG_TXN_TRIGG_REG); writeq_relaxed(0, tbu->base + DEBUG_VA_ADDR_REG); val = readl_relaxed(tbu->base + DEBUG_SID_HALT_REG); val &= ~DEBUG_SID_HALT_SID_MASK; val &= ~DEBUG_SID_HALT_SID; writel_relaxed(val, tbu->base + DEBUG_SID_HALT_REG); /* Loading