From patchwork Tue Nov 20 07:30:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cho KyongHo X-Patchwork-Id: 1771601 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id 4D3A03FC5A for ; Tue, 20 Nov 2012 07:37:52 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TaiM9-0005Vs-GC; Tue, 20 Nov 2012 07:34:54 +0000 Received: from mailout3.samsung.com ([203.254.224.33]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TaiIL-0003CW-8F for linux-arm-kernel@lists.infradead.org; Tue, 20 Nov 2012 07:31:00 +0000 Received: from epcpsbgm2.samsung.com (epcpsbgm2 [203.254.230.27]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MDR00J6AZHR41P0@mailout3.samsung.com> for linux-arm-kernel@lists.infradead.org; Tue, 20 Nov 2012 16:30:52 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [203.254.230.50]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id EE.0E.12699.CA13BA05; Tue, 20 Nov 2012 16:30:52 +0900 (KST) X-AuditID: cbfee61b-b7f616d00000319b-47-50ab31acc6af Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 0E.0E.12699.CA13BA05; Tue, 20 Nov 2012 16:30:52 +0900 (KST) Received: from DOPULLIPCHO06 ([12.23.118.152]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MDR00BD1ZJFUY00@mmp1.samsung.com> for linux-arm-kernel@lists.infradead.org; Tue, 20 Nov 2012 16:30:52 +0900 (KST) From: Cho KyongHo To: linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 11/12] iommu/exynos: add literal name of System MMU for debugging Date: Tue, 20 Nov 2012 16:30:51 +0900 Message-id: <002501cdc6f0$f81ca550$e855eff0$%cho@samsung.com> MIME-version: 1.0 X-Mailer: Microsoft Office Outlook 12.0 Thread-index: Ac3G8Pf7K7ZNOpfFRtG+z7QLbtvIyQ== Content-language: ko DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrAIsWRmVeSWpSXmKPExsVy+t8zI901hqsDDN4fFrLY9PgaqwOjx+Yl 9QGMUVw2Kak5mWWpRfp2CVwZ/Q++MhdsNas4/eggWwPjVe0uRk4OCQETiT9nmhkhbDGJC/fW s3UxcnEICSxjlOh42c0OU/T30xcmiMQiRol/628xgSSEBJYzSRzsTQGx2QS0JFbPPc4IUiQi 0MsocaH/K1gHs8APRolt87exglQJC4RJfP+xCGwfi4CqxLZ728BW8ArYSsxYO4kJwhaU+DH5 HguIzQw0df3O40wQtrzE5jVvmbsYOYBOUpd49FcXJCwioCcxfctMZogSEYl9L95BjReQ+Db5 EAtEuazEpgPMIOdICPSzS3y5AfGAhICkxMEVN1gmMIrNQrJ5FpLNs5BsnoVkxQJGllWMoqkF yQXFSem5RnrFibnFpXnpesn5uZsYIdEivYNxVYPFIUYBDkYlHt6HCasChFgTy4orcw8xSnAw K4nwNpUDhXhTEiurUovy44tKc1KLDzH6AF0+kVlKNDkfGMl5JfGGxsYmZiamJuaWpuamOISV xHmbPVIChATSE0tSs1NTC1KLYMYxcXBKNTCqvJbr9d/enCv3WClukvXpnTcevir9Z9I6Pc1q wS5t81viu7Y+tOuZfcPcbmuD9DT/vlWHbrbu51Ob4Xo/de9bYZknKRWsTTcP2VilB9tt+Znw MyNlUu/b0HM3TNvOPFgZfT5OUM/u+0abEIOvq965cXN8NH9kvlbXRuH2+muuJ9hyyz0kPjoq sRRnJBpqMRcVJwIAhZLKwsMCAAA= X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrPIsWRmVeSWpSXmKPExsVy+t9jAd01hqsDDNo2cltsenyN1YHRY/OS +gDGqAZGm4zUxJTUIoXUvOT8lMy8dFsl7+B453hTMwNDXUNLC3MlhbzE3FRbJRefAF23zByg qUoKZYk5pUChgMTiYiV9O0wTQkPcdC1gGiN0fUOC4HqMDNBAwjrGjP4HX5kLtppVnH50kK2B 8ap2FyMnh4SAicTfT1+YIGwxiQv31rN1MXJxCAksYpT4t/4WWEJIYDmTxMHeFBCbTUBLYvXc 44wgRSICvYwSF/q/MoE4zAI/GCW2zd/GClIlLBAm8f3HIkYQm0VAVWLbvW3sIDavgK3EjLWT mCBsQYkfk++xgNjMQFPX7zzOBGHLS2xe85a5i5ED6CR1iUd/dUHCIgJ6EtO3zGSGKBGR2Pfi HeMERoFZSCbNQjJpFpJJs5C0LGBkWcUomlqQXFCclJ5rpFecmFtcmpeul5yfu4kRHIvPpHcw rmqwOMQowMGoxMP7MGFVgBBrYllxZe4hRgkOZiUR3qZyoBBvSmJlVWpRfnxRaU5q8SFGH6BH JzJLiSbnA9NEXkm8obGJmZGlkZmFkYm5OQ5hJXHeZo+UACGB9MSS1OzU1ILUIphxTBycUg2M NXeObf5bvSlcnn3Bqu0ZZvNWxZ2S3ZAyaaus2EaDquPVHtt0L+pN919V+eAE/1/H6U9YpFaI z8vSu6L1L/Xgnpybxl+i4mMd1dIOBk9/4nhi1YIpJbYrVkpsdFg0zfH8nqPxe2PuiSsJ3+tJ 4twT9Zc1h0/IrK/6GQ+f/1F+kwenyjhtNnAXKbEUZyQaajEXFScCAAwmNwnyAgAA X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121120_023057_845004_404E41EA X-CRM114-Status: GOOD ( 19.82 ) X-Spam-Score: -7.5 (-------) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-7.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [203.254.224.33 listed in list.dnswl.org] -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.7 RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.1 HDRS_LCASE Odd capitalization of message header 0.0 T_MANY_HDRS_LCASE Odd capitalization of multiple message headers Cc: 'Kukjin Kim' , prathyush.k@samsung.com, 'Joerg Roedel' , sw0312.kim@samsung.com, 'Subash Patel' , 'Sanghyun Lee' , rahul.sharma@samsung.com X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This commit adds System MMU name to the driver data of each System MMU. It is used by fault information. Signed-off-by: KyongHo Cho --- drivers/iommu/exynos-iommu.c | 100 ++++++++++++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 24 deletions(-) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 77833f5..128c811 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -150,15 +151,21 @@ enum exynos_sysmmu_inttype { SYSMMU_FAULTS_NUM }; -/* +/** + * fault handler function type + * @dev: the client device + * @mmuname: name of the System MMU that generates fault * @itype: type of fault. * @pgtable_base: the physical address of page table base. This is 0 if @itype * is SYSMMU_BUSERROR. * @fault_addr: the device (virtual) address that the System MMU tried to * translated. This is 0 if @itype is SYSMMU_BUSERROR. */ -typedef int (*sysmmu_fault_handler_t)(enum exynos_sysmmu_inttype itype, - unsigned long pgtable_base, unsigned long fault_addr); +typedef int (*sysmmu_fault_handler_t)(struct device *dev, + const char *mmuname, + enum exynos_sysmmu_inttype itype, + unsigned long pgtable_base, + unsigned long fault_addr); static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = { REG_PAGE_FAULT_ADDR, @@ -234,6 +241,7 @@ struct sysmmu_drvdata { sysmmu_fault_handler_t fault_handler; unsigned long pgtable; bool runtime_active; + const char **mmuname; void __iomem *sfrbases[0]; }; @@ -612,16 +620,18 @@ void exynos_sysmmu_set_fault_handler(struct device *dev, spin_unlock_irqrestore(&owner->lock, flags); } -static int default_fault_handler(enum exynos_sysmmu_inttype itype, - unsigned long pgtable_base, unsigned long fault_addr) +static int default_fault_handler(struct device *dev, const char *mmuname, + enum exynos_sysmmu_inttype itype, + unsigned long pgtable_base, + unsigned long fault_addr) { unsigned long *ent; if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT)) itype = SYSMMU_FAULT_UNKNOWN; - pr_err("%s occurred at 0x%lx(Page table base: 0x%lx)\n", - sysmmu_fault_name[itype], fault_addr, pgtable_base); + dev_err(dev, "%s occured at 0x%lx by '%s'(Page table base: 0x%lx)\n", + sysmmu_fault_name[itype], fault_addr, mmuname, pgtable_base); ent = section_entry(__va(pgtable_base), fault_addr); pr_err("\tLv1 entry: 0x%lx\n", *ent); @@ -642,25 +652,30 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) { /* SYSMMU is in blocked when interrupt occurred. */ struct sysmmu_drvdata *data = dev_id; - struct resource *irqres; - struct platform_device *pdev; + struct exynos_iommu_owner *owner = NULL; enum exynos_sysmmu_inttype itype; unsigned long addr = -1; - + const char *mmuname = NULL; int i, ret = -ENOSYS; - spin_lock(&data->lock); + if (data->master) + owner = data->master->archdata.iommu; + + if (owner) + spin_lock(&owner->lock); WARN_ON(!is_sysmmu_active(data)); - pdev = to_platform_device(data->sysmmu); - for (i = 0; i < (pdev->num_resources / 2); i++) { - irqres = platform_get_resource(pdev, IORESOURCE_IRQ, i); + for (i = 0; i < data->nsfrs; i++) { + struct resource *irqres; + irqres = platform_get_resource( + to_platform_device(data->sysmmu), + IORESOURCE_IRQ, i); if (irqres && ((int)irqres->start == irq)) break; } - if (i == pdev->num_resources) { + if (i == data->nsfrs) { itype = SYSMMU_FAULT_UNKNOWN; } else { itype = (enum exynos_sysmmu_inttype) @@ -672,28 +687,34 @@ static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) data->sfrbases[i] + fault_reg_offset[itype]); } - if (data->domain) - ret = report_iommu_fault(data->domain, data->master, + if (data->domain) /* owner is always set if data->domain exists */ + ret = report_iommu_fault(data->domain, owner->dev, addr, itype); if ((ret == -ENOSYS) && data->fault_handler) { unsigned long base = data->pgtable; + mmuname = (data->mmuname) ? data->mmuname[i] + : dev_name(data->sysmmu); + if (itype != SYSMMU_FAULT_UNKNOWN) base = __raw_readl( data->sfrbases[i] + REG_PT_BASE_ADDR); - ret = data->fault_handler(itype, base, addr); + ret = data->fault_handler(owner ? owner->dev : data->sysmmu, + mmuname, itype, base, addr); } if (!ret && (itype != SYSMMU_FAULT_UNKNOWN)) __raw_writel(1 << itype, data->sfrbases[i] + REG_INT_CLEAR); else - dev_dbg(data->sysmmu, "%s is not handled.\n", - sysmmu_fault_name[itype]); + dev_dbg(owner ? owner->dev : data->sysmmu, + "%s is not handled by %s\n", + sysmmu_fault_name[itype], + dev_name(data->sysmmu)); - if (itype != SYSMMU_FAULT_UNKNOWN) - sysmmu_unblock(data->sfrbases[i]); + sysmmu_unblock(data->sfrbases[i]); - spin_unlock(&data->lock); + if (owner) + spin_unlock(&owner->lock); return IRQ_HANDLED; } @@ -1049,6 +1070,30 @@ err_dev_put: return ret; } +static void __init __sysmmu_init_mmuname(struct device *sysmmu, + struct sysmmu_drvdata *drvdata) +{ + int i; + const char *mmuname; + + if (of_property_count_strings(sysmmu->of_node, "mmuname") != + drvdata->nsfrs) + return; + + drvdata->mmuname = (void *)drvdata->sfrbases + + sizeof(drvdata->sfrbases[0]) * drvdata->nsfrs; + + for (i = 0; i < drvdata->nsfrs; i++) { + if (of_property_read_string_index(sysmmu->of_node, + "mmuname", i, &mmuname)) + dev_err(sysmmu, "Failed read mmuname[%d]\n", i); + else + drvdata->mmuname[i] = kstrdup(mmuname, GFP_KERNEL); + if (!drvdata->mmuname[i]) + drvdata->mmuname[i] = "noname"; + } +} + static int __init exynos_sysmmu_probe(struct platform_device *pdev) { int i, ret; @@ -1060,9 +1105,14 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) return -ENODEV; } + ret = of_property_count_strings(pdev->dev.of_node, "mmuname"); + if (ret != (int)(pdev->num_resources / 2)) + ret = 0; + data = devm_kzalloc(dev, sizeof(*data) - + sizeof(*data->sfrbases) * (pdev->num_resources / 2), + + sizeof(*data->sfrbases) * (pdev->num_resources / 2) + + sizeof(*data->mmuname) * ret, GFP_KERNEL); if (!data) { dev_err(dev, "Not enough memory\n"); @@ -1112,6 +1162,8 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) ret = __sysmmu_setup(dev, data); if (!ret) { + __sysmmu_init_mmuname(dev, data); + data->runtime_active = !pm_runtime_enabled(dev); data->sysmmu = dev; spin_lock_init(&data->lock);