Loading drivers/iommu/arm-smmu.c +38 −9 Original line number Diff line number Diff line Loading @@ -935,7 +935,7 @@ static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain, static irqreturn_t arm_smmu_context_fault(int irq, void *dev) { int flags, ret; int flags, ret, tmp; u32 fsr, fsynr, resume; unsigned long iova, far; struct iommu_domain *domain = dev; Loading Loading @@ -978,6 +978,12 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0); flags = fsynr & FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ; if (fsr & FSR_TF) flags |= IOMMU_FAULT_TRANSLATION; if (fsr & FSR_PF) flags |= IOMMU_FAULT_PERMISSION; if (fsr & FSR_SS) flags |= IOMMU_FAULT_TRANSACTION_STALLED; far = readl_relaxed(cb_base + ARM_SMMU_CB_FAR_LO); #ifdef CONFIG_64BIT Loading @@ -987,7 +993,8 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) phys_soft = arm_smmu_iova_to_phys(domain, iova); frsynra = readl_relaxed(gr1_base + ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx)); if (!report_iommu_fault(domain, smmu->dev, iova, flags)) { tmp = report_iommu_fault(domain, smmu->dev, iova, flags); if (!tmp || (tmp == -EBUSY)) { dev_dbg(smmu->dev, "Context fault handled by client: iova=0x%08lx, fsr=0x%x, fsynr=0x%x, cb=%d\n", iova, fsr, fsynr, cfg->cbndx); Loading Loading @@ -1017,8 +1024,29 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) resume = RESUME_TERMINATE; } /* * If the client returns -EBUSY, do not clear FSR and do not RESUME * if stalled. This is required to keep the IOMMU client stalled on * the outstanding fault. This gives the client a chance to take any * debug action and then terminate the stalled transaction. * So, the sequence in case of stall on fault should be: * 1) Do not clear FSR or write to RESUME here * 2) Client takes any debug action * 3) Client terminates the stalled transaction and resumes the IOMMU * 4) Client clears FSR. The FSR should only be cleared after 3) and * not before so that the fault remains outstanding. This ensures * SCTLR.HUPCF has the desired effect if subsequent transactions also * need to be terminated. */ if (tmp != -EBUSY) { /* Clear the faulting FSR */ writel(fsr, cb_base + ARM_SMMU_CB_FSR); writel_relaxed(fsr, cb_base + ARM_SMMU_CB_FSR); /* * Barrier required to ensure that the FSR is cleared * before resuming SMMU operation */ wmb(); /* Retry or terminate any stalled transactions */ if (fsr & FSR_SS) { Loading @@ -1026,6 +1054,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) arm_smmu_tlb_sync_cb(smmu, cfg->cbndx); writel_relaxed(resume, cb_base + ARM_SMMU_CB_RESUME); } } arm_smmu_disable_clocks(smmu); mutex_unlock(&smmu_domain->init_mutex); Loading include/linux/iommu.h +10 −2 Original line number Diff line number Diff line Loading @@ -39,8 +39,11 @@ struct iommu_domain; struct notifier_block; /* iommu fault flags */ #define IOMMU_FAULT_READ 0x0 #define IOMMU_FAULT_WRITE 0x1 #define IOMMU_FAULT_READ (1 << 0) #define IOMMU_FAULT_WRITE (1 << 1) #define IOMMU_FAULT_TRANSLATION (1 << 2) #define IOMMU_FAULT_PERMISSION (1 << 3) #define IOMMU_FAULT_TRANSACTION_STALLED (1 << 4) typedef int (*iommu_fault_handler_t)(struct iommu_domain *, struct device *, unsigned long, int, void *); Loading Loading @@ -250,6 +253,11 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr) * Specifically, -ENOSYS is returned if a fault handler isn't installed * (though fault handlers can also return -ENOSYS, in case they want to * elicit the default behavior of the IOMMU drivers). * Client fault handler returns -EBUSY to signal to the IOMMU driver * that the client will take responsibility for any further fault * handling, including clearing fault status registers or retrying * the faulting transaction. */ static inline int report_iommu_fault(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags) Loading Loading
drivers/iommu/arm-smmu.c +38 −9 Original line number Diff line number Diff line Loading @@ -935,7 +935,7 @@ static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain, static irqreturn_t arm_smmu_context_fault(int irq, void *dev) { int flags, ret; int flags, ret, tmp; u32 fsr, fsynr, resume; unsigned long iova, far; struct iommu_domain *domain = dev; Loading Loading @@ -978,6 +978,12 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0); flags = fsynr & FSYNR0_WNR ? IOMMU_FAULT_WRITE : IOMMU_FAULT_READ; if (fsr & FSR_TF) flags |= IOMMU_FAULT_TRANSLATION; if (fsr & FSR_PF) flags |= IOMMU_FAULT_PERMISSION; if (fsr & FSR_SS) flags |= IOMMU_FAULT_TRANSACTION_STALLED; far = readl_relaxed(cb_base + ARM_SMMU_CB_FAR_LO); #ifdef CONFIG_64BIT Loading @@ -987,7 +993,8 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) phys_soft = arm_smmu_iova_to_phys(domain, iova); frsynra = readl_relaxed(gr1_base + ARM_SMMU_GR1_CBFRSYNRA(cfg->cbndx)); if (!report_iommu_fault(domain, smmu->dev, iova, flags)) { tmp = report_iommu_fault(domain, smmu->dev, iova, flags); if (!tmp || (tmp == -EBUSY)) { dev_dbg(smmu->dev, "Context fault handled by client: iova=0x%08lx, fsr=0x%x, fsynr=0x%x, cb=%d\n", iova, fsr, fsynr, cfg->cbndx); Loading Loading @@ -1017,8 +1024,29 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) resume = RESUME_TERMINATE; } /* * If the client returns -EBUSY, do not clear FSR and do not RESUME * if stalled. This is required to keep the IOMMU client stalled on * the outstanding fault. This gives the client a chance to take any * debug action and then terminate the stalled transaction. * So, the sequence in case of stall on fault should be: * 1) Do not clear FSR or write to RESUME here * 2) Client takes any debug action * 3) Client terminates the stalled transaction and resumes the IOMMU * 4) Client clears FSR. The FSR should only be cleared after 3) and * not before so that the fault remains outstanding. This ensures * SCTLR.HUPCF has the desired effect if subsequent transactions also * need to be terminated. */ if (tmp != -EBUSY) { /* Clear the faulting FSR */ writel(fsr, cb_base + ARM_SMMU_CB_FSR); writel_relaxed(fsr, cb_base + ARM_SMMU_CB_FSR); /* * Barrier required to ensure that the FSR is cleared * before resuming SMMU operation */ wmb(); /* Retry or terminate any stalled transactions */ if (fsr & FSR_SS) { Loading @@ -1026,6 +1054,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev) arm_smmu_tlb_sync_cb(smmu, cfg->cbndx); writel_relaxed(resume, cb_base + ARM_SMMU_CB_RESUME); } } arm_smmu_disable_clocks(smmu); mutex_unlock(&smmu_domain->init_mutex); Loading
include/linux/iommu.h +10 −2 Original line number Diff line number Diff line Loading @@ -39,8 +39,11 @@ struct iommu_domain; struct notifier_block; /* iommu fault flags */ #define IOMMU_FAULT_READ 0x0 #define IOMMU_FAULT_WRITE 0x1 #define IOMMU_FAULT_READ (1 << 0) #define IOMMU_FAULT_WRITE (1 << 1) #define IOMMU_FAULT_TRANSLATION (1 << 2) #define IOMMU_FAULT_PERMISSION (1 << 3) #define IOMMU_FAULT_TRANSACTION_STALLED (1 << 4) typedef int (*iommu_fault_handler_t)(struct iommu_domain *, struct device *, unsigned long, int, void *); Loading Loading @@ -250,6 +253,11 @@ extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr) * Specifically, -ENOSYS is returned if a fault handler isn't installed * (though fault handlers can also return -ENOSYS, in case they want to * elicit the default behavior of the IOMMU drivers). * Client fault handler returns -EBUSY to signal to the IOMMU driver * that the client will take responsibility for any further fault * handling, including clearing fault status registers or retrying * the faulting transaction. */ static inline int report_iommu_fault(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags) Loading