From patchwork Sat Jan 20 03:38:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?WW9uZyBXdSAo5ZC05YuHKQ==?= X-Patchwork-Id: 10176257 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 503546056F for ; Sat, 20 Jan 2018 03:40:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3F7E228765 for ; Sat, 20 Jan 2018 03:40:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3201D28802; Sat, 20 Jan 2018 03:40:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 9512C28765 for ; Sat, 20 Jan 2018 03:40:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Date:Subject:To :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=qkqbI2oepWWPuQB3gC6DUDhsOeSWpNKREXb2uzfl8OE=; b=tD2SS/mD5Ashzz dVpp3mAcbnObQPshPD2wskqHPmoe1aIApvFYXT59rKg5FQw9Fdqiyvz3ERpvIniVNRozj+3piCUZ3 psHkD57temSON/MnROCkUnpYJD9U5h8V6JVgImhIbMlDvI5oNAZLFnZDA/n81s+jOzfzGRvilyxfG 8yVktfGO40R3ErfRnmTJ034sP8WGU5m/IjTT5jsmkeOUAcPPZVOLW/VmKltnBB8l41JyD8muLYtni DHDTpfX7HJ6DiHZwyh3tyT0tCl3xbsexPLhKMY8DJLQC9Z57z7xU8lIZ78LOcGLD49HHJ6x5Y59F5 xiZJJ3VYAD8i/WwEF8jw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1eck0s-0002DV-6z; Sat, 20 Jan 2018 03:40:14 +0000 Received: from [210.61.82.183] (helo=mailgw01.mediatek.com) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1eck0Z-0000xM-Hj; Sat, 20 Jan 2018 03:39:57 +0000 X-UUID: f8315d55306d40bf9d10faece4ea0de1-20180120 Received: from mtkcas09.mediatek.inc [(172.21.101.178)] by mailgw01.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 766299799; Sat, 20 Jan 2018 11:39:26 +0800 Received: from mtkcas08.mediatek.inc (172.21.101.126) by mtkmbs03n1.mediatek.inc (172.21.101.181) with Microsoft SMTP Server (TLS) id 15.0.1210.3; Sat, 20 Jan 2018 11:39:24 +0800 Received: from localhost.localdomain (10.17.3.153) by mtkcas08.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1210.3 via Frontend Transport; Sat, 20 Jan 2018 11:39:24 +0800 From: Yong Wu To: Joerg Roedel , Matthias Brugger Subject: [PATCH] iommu/mediatek: Move attach_device after iommu-group is ready for M4Uv1 Date: Sat, 20 Jan 2018 11:38:39 +0800 Message-ID: <1516419519-25987-1-git-send-email-yong.wu@mediatek.com> X-Mailer: git-send-email 1.8.1.1.dirty MIME-Version: 1.0 X-MTK: N X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: youlin.pei@mediatek.com, arnd@arndb.de, srv_heupstream@mediatek.com, Will Deacon , linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org, Yong Wu , Tomasz Figa , Alex Williamson , linux-mediatek@lists.infradead.org, xinping.qian@mediatek.com, Bibby Hsieh , honghui.zhang@mediatek.com, Robin Murphy , linux-arm-kernel@lists.infradead.org Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+patchwork-linux-mediatek=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP In the commit 05f80300dc8b, the iommu framework has supposed all the iommu drivers have their owner iommu-group, it get rid of the FIXME workarounds while the group is NULL. But the flow of Mediatek M4U gen1 looks a bit trick that it will hang at this case: ========================================== Unable to handle kernel NULL pointer dereference at virtual address 00000030 pgd = c0004000 [00000030] *pgd=00000000 Internal error: Oops: 5 [#1] SMP ARM Modules linked in: CPU: 2 PID: 1 Comm: swapper/0 Not tainted 4.15.0-rc1-gfadad58-dirty #7 Hardware name: Mediatek Cortex-A7 (Device Tree) task: df0f8000 task.stack: df0ec000 PC is at mutex_lock+0x28/0x54 LR is at iommu_attach_device+0xa4/0xd4 pc : [] lr : [] psr: 60000013 sp : df0edbb8 ip : df0edbc8 fp : df0edbc4 r10: c114da14 r9 : df2a3e40 r8 : 00000003 r7 : df27a210 r6 : df2a90c4 r5 : 00000030 r4 : 00000000 r3 : df0f8000 r2 : fffff000 r1 : df29c610 r0 : 00000030 Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none xxx (mutex_lock) from [] (iommu_attach_device+0xa4/0xd4) (iommu_attach_device) from [] (__arm_iommu_attach_device+0x28/0x90) (__arm_iommu_attach_device) from [] (arm_iommu_attach_device+0x1c/0x30) (arm_iommu_attach_device) from [] (mtk_iommu_add_device+0xfc/0x214) (mtk_iommu_add_device) from [] (add_iommu_group+0x3c/0x68) (add_iommu_group) from [] (bus_for_each_dev+0x78/0xac) (bus_for_each_dev) from [] (bus_set_iommu+0xb0/0xec) (bus_set_iommu) from [] (mtk_iommu_probe+0x328/0x368) (mtk_iommu_probe) from [] (platform_drv_probe+0x5c/0xc0) (platform_drv_probe) from [] (driver_probe_device+0x2f4/0x4d8) (driver_probe_device) from [] (__driver_attach+0x10c/0x128) (__driver_attach) from [] (bus_for_each_dev+0x78/0xac) (bus_for_each_dev) from [] (driver_attach+0x2c/0x30) (driver_attach) from [] (bus_add_driver+0x1e0/0x278) (bus_add_driver) from [] (driver_register+0x88/0x108) (driver_register) from [] (__platform_driver_register+0x50/0x58) (__platform_driver_register) from [] (m4u_init+0x24/0x28) (m4u_init) from [] (do_one_initcall+0xf0/0x17c) (do_one_initcall) from [] (kernel_init_freeable+0x154/0x1f4) (kernel_init_freeable) from [] (kernel_init+0x18/0x124) (kernel_init) from [] (ret_from_fork+0x14/0x2c) ========================= The root cause is that "arm_iommu_attach_device" is called before "iommu_group_get_for_dev" in the interface "mtk_iommu_add_device". Thus, We adjust the sequence of this two functions. Unfortunately, there is another issue after the solution above, From the function "iommu_attach_device", Only one device in each a iommu group is allowed. In Mediatek case, there is only one m4u group, all the devices are in one group. thus it get fail at this step. In order to satisfy this requirement, a new iommu group is allocated for each a iommu consumer device. But meanwhile, we still have to use the same domain for all the iommu group. Use a global variable "mtk_domain_v1" to save the global domain. CC: Robin Murphy CC: Honghui Zhang Fixes: 05f80300dc8b ('iommu: Finish making iommu_group support mandatory') Reported-by: Ryder Lee Tested-by: Bibby Hsieh Signed-off-by: Yong Wu --- base on v4.15-rc1 --- drivers/iommu/mtk_iommu_v1.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index 542930c..da2d941 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -103,6 +103,9 @@ struct mtk_iommu_domain { struct mtk_iommu_data *data; }; +/* There is only a iommu domain in M4U gen1. */ +static struct mtk_iommu_domain *mtk_domain_v1; + static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom) { return container_of(dom, struct mtk_iommu_domain, domain); @@ -251,10 +254,15 @@ static struct iommu_domain *mtk_iommu_domain_alloc(unsigned type) if (type != IOMMU_DOMAIN_UNMANAGED) return NULL; + /* Always return the same domain. */ + if (mtk_domain_v1) + return &mtk_domain_v1->domain; + dom = kzalloc(sizeof(*dom), GFP_KERNEL); if (!dom) return NULL; + mtk_domain_v1 = dom; return &dom->domain; } @@ -418,20 +426,12 @@ static int mtk_iommu_create_mapping(struct device *dev, m4udev->archdata.iommu = mtk_mapping; } - ret = arm_iommu_attach_device(dev, mtk_mapping); - if (ret) - goto err_release_mapping; - return 0; - -err_release_mapping: - arm_iommu_release_mapping(mtk_mapping); - m4udev->archdata.iommu = NULL; - return ret; } static int mtk_iommu_add_device(struct device *dev) { + struct dma_iommu_mapping *mtk_mapping; struct of_phandle_args iommu_spec; struct of_phandle_iterator it; struct mtk_iommu_data *data; @@ -460,7 +460,9 @@ static int mtk_iommu_add_device(struct device *dev) return PTR_ERR(group); iommu_group_put(group); - return 0; + + mtk_mapping = data->dev->archdata.iommu; + return arm_iommu_attach_device(dev, mtk_mapping); } static void mtk_iommu_remove_device(struct device *dev) @@ -479,20 +481,13 @@ static void mtk_iommu_remove_device(struct device *dev) static struct iommu_group *mtk_iommu_device_group(struct device *dev) { - struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv; + struct iommu_group *group; - if (!data) - return ERR_PTR(-ENODEV); - - /* All the client devices are in the same m4u iommu-group */ - if (!data->m4u_group) { - data->m4u_group = iommu_group_alloc(); - if (IS_ERR(data->m4u_group)) - dev_err(dev, "Failed to allocate M4U IOMMU group\n"); - } else { - iommu_group_ref_get(data->m4u_group); - } - return data->m4u_group; + group = iommu_group_get(dev); + if (!group) + group = generic_device_group(dev); + + return group; } static int mtk_iommu_hw_init(const struct mtk_iommu_data *data)