From patchwork Thu Feb 18 14:12:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 62187 Delivered-To: patch@linaro.org Received: by 10.112.43.199 with SMTP id y7csp610821lbl; Thu, 18 Feb 2016 06:13:53 -0800 (PST) X-Received: by 10.98.18.215 with SMTP id 84mr10298561pfs.131.1455804813538; Thu, 18 Feb 2016 06:13:33 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f63si9683783pfj.137.2016.02.18.06.13.33; Thu, 18 Feb 2016 06:13:33 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-samsung-soc-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-samsung-soc-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-samsung-soc-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756713AbcBRONc (ORCPT + 4 others); Thu, 18 Feb 2016 09:13:32 -0500 Received: from mailout4.w1.samsung.com ([210.118.77.14]:37168 "EHLO mailout4.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1425356AbcBRONa (ORCPT ); Thu, 18 Feb 2016 09:13:30 -0500 Received: from eucpsbgm2.samsung.com (unknown [203.254.199.245]) by mailout4.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0O2Q00LF8Y6BDTA0@mailout4.w1.samsung.com> for linux-samsung-soc@vger.kernel.org; Thu, 18 Feb 2016 14:13:23 +0000 (GMT) X-AuditID: cbfec7f5-f79b16d000005389-5b-56c5d1835b37 Received: from eusync4.samsung.com ( [203.254.199.214]) by eucpsbgm2.samsung.com (EUCPMTA) with SMTP id FF.10.21385.381D5C65; Thu, 18 Feb 2016 14:13:23 +0000 (GMT) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync4.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0O2Q00576Y5X95B0@eusync4.samsung.com>; Thu, 18 Feb 2016 14:13:23 +0000 (GMT) From: Marek Szyprowski To: iommu@lists.linux-foundation.org, linux-samsung-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Marek Szyprowski , Joerg Roedel , Inki Dae , Kukjin Kim , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Subject: [PATCH v2 06/13] iommu: exynos: refactor fault handling code Date: Thu, 18 Feb 2016 15:12:53 +0100 Message-id: <1455804780-9616-7-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1455804780-9616-1-git-send-email-m.szyprowski@samsung.com> References: <1455804780-9616-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrILMWRmVeSWpSXmKPExsVy+t/xa7rNF4+GGTScULLYOGM9q8Wk+xNY LBbst7bonL2B3eL1C0OL/sevmS02Pb7GajHj/D4mi7VH7rI7cHo8OTiPyWPTqk42j81L6j0m 31jO6NG3ZRWjx+dNcgFsUVw2Kak5mWWpRfp2CVwZ++ctYSl4o12xZfZX1gbG3SpdjJwcEgIm Ej+WfWOFsMUkLtxbz9bFyMUhJLCUUeLK0bVMEE4Tk8T1BWsZQarYBAwlut52sYHYIgL5Ei/2 /mUBKWIW+MUoca6znQkkISzgKrH37EewsSwCqhIzPs4Di/MKuEu0fLrCBrFOTuL/yxVgcU4B D4nNpzaALRACqvnzcCbTBEbeBYwMqxhFU0uTC4qT0nON9IoTc4tL89L1kvNzNzFCAu7rDsal x6wOMQpwMCrx8G54cSRMiDWxrLgy9xCjBAezkgjv7r1Hw4R4UxIrq1KL8uOLSnNSiw8xSnOw KInzztz1PkRIID2xJDU7NbUgtQgmy8TBKdXAGGLDUCTyODXnQ/rH5IywPE6Pt3PPXTr0YoLD jA8lbWfb9wTKeBQ9fSR6NC46+/sL0fOx7Zt2LOS7PGt9H0vr8yKJF9MrfHf7fd7UOed/m//v SVwvNWYWGcx583gR52e2/2+jtqq3Xr4jsP31o4mtDB16tjJ6izX59x9KVpsinB9ftyD3rd/v ViWW4oxEQy3mouJEAF9/YYc0AgAA Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org This patch provides a new implementation for page fault handing code. The new implementation is ready for future extensions. No functional changes have been made. Signed-off-by: Marek Szyprowski --- drivers/iommu/exynos-iommu.c | 109 ++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 68 deletions(-) -- 1.9.2 -- To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 4275222cead3..3a577a473f3c 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -148,40 +148,25 @@ static sysmmu_pte_t *page_entry(sysmmu_pte_t *sent, sysmmu_iova_t iova) lv2table_base(sent)) + lv2ent_offset(iova); } -enum exynos_sysmmu_inttype { - SYSMMU_PAGEFAULT, - SYSMMU_AR_MULTIHIT, - SYSMMU_AW_MULTIHIT, - SYSMMU_BUSERROR, - SYSMMU_AR_SECURITY, - SYSMMU_AR_ACCESS, - SYSMMU_AW_SECURITY, - SYSMMU_AW_PROTECTION, /* 7 */ - SYSMMU_FAULT_UNKNOWN, - SYSMMU_FAULTS_NUM -}; - -static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = { - REG_PAGE_FAULT_ADDR, - REG_AR_FAULT_ADDR, - REG_AW_FAULT_ADDR, - REG_DEFAULT_SLAVE_ADDR, - REG_AR_FAULT_ADDR, - REG_AR_FAULT_ADDR, - REG_AW_FAULT_ADDR, - REG_AW_FAULT_ADDR +/* + * IOMMU fault information register + */ +struct sysmmu_fault_info { + unsigned int bit; /* bit number in STATUS register */ + unsigned short addr_reg; /* register to read VA fault address */ + const char *name; /* human readable fault name */ + unsigned int type; /* fault type for report_iommu_fault */ }; -static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { - "PAGE FAULT", - "AR MULTI-HIT FAULT", - "AW MULTI-HIT FAULT", - "BUS ERROR", - "AR SECURITY PROTECTION FAULT", - "AR ACCESS PROTECTION FAULT", - "AW SECURITY PROTECTION FAULT", - "AW ACCESS PROTECTION FAULT", - "UNKNOWN FAULT" +static const struct sysmmu_fault_info sysmmu_faults[] = { + { 0, REG_PAGE_FAULT_ADDR, "PAGE", IOMMU_FAULT_READ }, + { 1, REG_AR_FAULT_ADDR, "AR MULTI-HIT", IOMMU_FAULT_READ }, + { 2, REG_AW_FAULT_ADDR, "AW MULTI-HIT", IOMMU_FAULT_WRITE }, + { 3, REG_DEFAULT_SLAVE_ADDR, "BUS ERROR", IOMMU_FAULT_READ }, + { 4, REG_AR_FAULT_ADDR, "AR SECURITY PROTECTION", IOMMU_FAULT_READ }, + { 5, REG_AR_FAULT_ADDR, "AR ACCESS PROTECTION", IOMMU_FAULT_READ }, + { 6, REG_AW_FAULT_ADDR, "AW SECURITY PROTECTION", IOMMU_FAULT_WRITE }, + { 7, REG_AW_FAULT_ADDR, "AW ACCESS PROTECTION", IOMMU_FAULT_WRITE }, }; /* @@ -299,24 +284,19 @@ static void __sysmmu_set_ptbase(struct sysmmu_drvdata *data, phys_addr_t pgd) __sysmmu_tlb_invalidate(data); } -static void show_fault_information(const char *name, - enum exynos_sysmmu_inttype itype, - phys_addr_t pgtable_base, sysmmu_iova_t fault_addr) +static void show_fault_information(struct sysmmu_drvdata *data, + const struct sysmmu_fault_info *finfo, + sysmmu_iova_t fault_addr) { sysmmu_pte_t *ent; - if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT)) - itype = SYSMMU_FAULT_UNKNOWN; - - pr_err("%s occurred at %#x by %s(Page table base: %pa)\n", - sysmmu_fault_name[itype], fault_addr, name, &pgtable_base); - - ent = section_entry(phys_to_virt(pgtable_base), fault_addr); - pr_err("\tLv1 entry: %#x\n", *ent); - + dev_err(data->sysmmu, "%s FAULT occurred at %#x (page table base: %pa)\n", + finfo->name, fault_addr, &data->pgtable); + ent = section_entry(phys_to_virt(data->pgtable), fault_addr); + dev_err(data->sysmmu, "\tLv1 entry: %#x\n", *ent); if (lv1ent_page(ent)) { ent = page_entry(ent, fault_addr); - pr_err("\t Lv2 entry: %#x\n", *ent); + dev_err(data->sysmmu, "\t Lv2 entry: %#x\n", *ent); } } @@ -324,8 +304,10 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) { /* SYSMMU is in blocked state when interrupt occurred. */ struct sysmmu_drvdata *data = dev_id; - enum exynos_sysmmu_inttype itype; - sysmmu_iova_t addr = -1; + const struct sysmmu_fault_info *finfo = sysmmu_faults; + int i, n = ARRAY_SIZE(sysmmu_faults); + unsigned int itype; + sysmmu_iova_t fault_addr = -1; int ret = -ENOSYS; WARN_ON(!is_sysmmu_active(data)); @@ -334,29 +316,20 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) clk_enable(data->clk_master); - itype = (enum exynos_sysmmu_inttype) - __ffs(__raw_readl(data->sfrbase + REG_INT_STATUS)); - if (WARN_ON(!((itype >= 0) && (itype < SYSMMU_FAULT_UNKNOWN)))) - itype = SYSMMU_FAULT_UNKNOWN; - else - addr = __raw_readl(data->sfrbase + fault_reg_offset[itype]); + itype = __ffs(__raw_readl(data->sfrbase + REG_INT_STATUS)); + for (i = 0; i < n; i++, finfo++) + if (finfo->bit == itype) + break; + /* unknown/unsupported fault */ + BUG_ON(i == n); - if (itype == SYSMMU_FAULT_UNKNOWN) { - pr_err("%s: Fault is not occurred by System MMU '%s'!\n", - __func__, dev_name(data->sysmmu)); - pr_err("%s: Please check if IRQ is correctly configured.\n", - __func__); - BUG(); - } else { - unsigned int base = - __raw_readl(data->sfrbase + REG_PT_BASE_ADDR); - show_fault_information(dev_name(data->sysmmu), - itype, base, addr); - if (data->domain) - ret = report_iommu_fault(&data->domain->domain, - data->master, addr, itype); - } + /* print debug message */ + fault_addr = __raw_readl(data->sfrbase + finfo->addr_reg); + show_fault_information(data, finfo, fault_addr); + if (data->domain) + ret = report_iommu_fault(&data->domain->domain, + data->master, fault_addr, finfo->type); /* fault is not recovered by fault handler */ BUG_ON(ret != 0);