From patchwork Mon Apr 23 11:45:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xie Yisheng X-Patchwork-Id: 10356883 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 ACC1A601BE for ; Mon, 23 Apr 2018 11:58:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 99D2028A81 for ; Mon, 23 Apr 2018 11:58:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8982D28A85; Mon, 23 Apr 2018 11:58:33 +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=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.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 E812628A81 for ; Mon, 23 Apr 2018 11:58:32 +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:References:In-Reply-To: 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: List-Owner; bh=hDLktSvSiun1/bUKK+29kAdpzzBGCxueaoJq59dYqQw=; b=Yr7m2W0LB+iXl/ CPHAdb7cqujUunh9720uPw8IpNPvn38aoCc35WrGqp+TaWidOXyvv/ht72VhMiZOHKHpVjGJxBtqu OJx83D/8gElc9TEgf78rHxX2fPiq+j9PzpOezE3qBEj135+aOGEcy9A68buPli/8J0Mk7G6ivQUln psMtTccWa+/1G30WOIRD88UWFSa6vkxMbY22Ipb/RNwcjt4MPG4Kl56kLj9VBe2GuvtLgZmxW5+LW Mqe2Yq5XrrofCM8b4bO3tLRNzqId4kEo5XG5Lzp1mkrublQ/7IWbfTVPuhS1YltAmQ1PaYyFPR1be Y6pEWBq1LfeelavMSm3w==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fAa6y-0002fC-Ll; Mon, 23 Apr 2018 11:58:24 +0000 Received: from szxga05-in.huawei.com ([45.249.212.191] helo=huawei.com) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1fAa5W-0001zr-Kv for linux-arm-kernel@lists.infradead.org; Mon, 23 Apr 2018 11:56:58 +0000 Received: from DGGEMS412-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id 50A4C9FE53BDB; Mon, 23 Apr 2018 19:56:24 +0800 (CST) Received: from linux-ibm.site (10.175.102.37) by DGGEMS412-HUB.china.huawei.com (10.3.19.212) with Microsoft SMTP Server id 14.3.361.1; Mon, 23 Apr 2018 19:56:16 +0800 From: Yisheng Xie To: , , Subject: [RFC 2/2] iommu/arm-smmu-v3: Support software retention for pm_resume Date: Mon, 23 Apr 2018 19:45:59 +0800 Message-ID: <1524483959-54940-3-git-send-email-xieyisheng1@huawei.com> X-Mailer: git-send-email 1.7.12.4 In-Reply-To: <1524483959-54940-1-git-send-email-xieyisheng1@huawei.com> References: <1524483959-54940-1-git-send-email-xieyisheng1@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.175.102.37] X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180423_045654_896413_27262579 X-CRM114-Status: GOOD ( 17.38 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yisheng Xie , liubo95@huawei.com, linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org, dingtianhong@huawei.com, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP When system suspend, hisilicon's smmu will do power gating for smmu, this time smmu's reg will be set to default value for not having hardware retention, which means need software do the retention instead. The patch is to use arm_smmu_device_reset() to restore the register of smmu. However, it need to save the msis setting at probe if smmu do not support hardware retention. Signed-off-by: Yisheng Xie --- drivers/iommu/arm-smmu-v3.c | 69 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 044df6e..6cb56d8 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -534,6 +534,11 @@ struct arm_smmu_strtab_cfg { u32 strtab_base_cfg; }; +struct arm_smmu_msi_val { + u64 doorbell; + u32 data; +}; + /* An SMMUv3 instance */ struct arm_smmu_device { struct device *dev; @@ -558,6 +563,7 @@ struct arm_smmu_device { #define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0) #define ARM_SMMU_OPT_PAGE0_REGS_ONLY (1 << 1) +#define ARM_SMMU_OPT_SW_RETENTION (1 << 2) u32 options; struct arm_smmu_cmdq cmdq; @@ -587,6 +593,8 @@ struct arm_smmu_device { u32 sync_count; + struct arm_smmu_msi_val *msi; + bool probed; bool bypass; /* IOMMU core code handle */ @@ -630,6 +638,7 @@ struct arm_smmu_option_prop { static struct arm_smmu_option_prop arm_smmu_options[] = { { ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" }, { ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium,cn9900-broken-page1-regspace"}, + { ARM_SMMU_OPT_SW_RETENTION, "hisilicon,broken-hardware-retention" }, { 0, NULL}, }; @@ -2228,7 +2237,8 @@ static void arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg) phys_addr_t doorbell; struct device *dev = msi_desc_to_dev(desc); struct arm_smmu_device *smmu = dev_get_drvdata(dev); - phys_addr_t *cfg = arm_smmu_msi_cfg[desc->platform.msi_index]; + int msi_index = desc->platform.msi_index; + phys_addr_t *cfg = arm_smmu_msi_cfg[msi_index]; doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo; doorbell &= MSI_CFG0_ADDR_MASK; @@ -2236,6 +2246,28 @@ static void arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg) writeq_relaxed(doorbell, smmu->base + cfg[0]); writel_relaxed(msg->data, smmu->base + cfg[1]); writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE, smmu->base + cfg[2]); + + if (smmu->options & ARM_SMMU_OPT_SW_RETENTION) { + smmu->msi[msi_index].doorbell = doorbell; + smmu->msi[msi_index].data = msg->data; + } +} + +static void arm_smmu_restore_msis(struct arm_smmu_device *smmu) +{ + int nevc = ARM_SMMU_MAX_MSIS - 1; + + if (!(smmu->features & ARM_SMMU_FEAT_PRI)) + nevc--; + + for (; nevc >= 0; nevc--) { + phys_addr_t *cfg = arm_smmu_msi_cfg[nevc]; + struct arm_smmu_msi_val msi_val = smmu->msi[nevc]; + + writeq_relaxed(msi_val.doorbell, smmu->base + cfg[0]); + writel_relaxed(msi_val.data, smmu->base + cfg[1]); + writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE, smmu->base + cfg[2]); + } } static void arm_smmu_setup_msis(struct arm_smmu_device *smmu) @@ -2261,6 +2293,16 @@ static void arm_smmu_setup_msis(struct arm_smmu_device *smmu) return; } + if (smmu->probed) { + BUG_ON(!(smmu->options & ARM_SMMU_OPT_SW_RETENTION)); + arm_smmu_restore_msis(smmu); + return; + } else if (smmu->options & ARM_SMMU_OPT_SW_RETENTION) { + smmu->msi = devm_kmalloc_array(dev, nvec, + sizeof(*(smmu->msi)), + GFP_KERNEL); + } + /* Allocate MSIs for evtq, gerror and priq. Ignore cmdq */ ret = platform_msi_domain_alloc_irqs(dev, nvec, arm_smmu_write_msi_msg); if (ret) { @@ -2294,6 +2336,9 @@ static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu) arm_smmu_setup_msis(smmu); + if (smmu->probed) + return; + /* Request interrupt lines */ irq = smmu->evtq.q.irq; if (irq) { @@ -2348,7 +2393,7 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu) } irq = smmu->combined_irq; - if (irq) { + if (irq && !smmu->probed) { /* * Cavium ThunderX2 implementation doesn't not support unique * irq lines. Use single irq line for all the SMMUv3 interrupts. @@ -2360,7 +2405,7 @@ static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu) "arm-smmu-v3-combined-irq", smmu); if (ret < 0) dev_warn(smmu->dev, "failed to enable combined irq\n"); - } else + } else if (!irq) arm_smmu_setup_unique_irqs(smmu); if (smmu->features & ARM_SMMU_FEAT_PRI) @@ -2882,6 +2927,9 @@ static int arm_smmu_device_probe(struct platform_device *pdev) if (ret) return ret; } + + smmu->probed = true; + return 0; } @@ -2899,6 +2947,20 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev) arm_smmu_device_remove(pdev); } +static int arm_smmu_pm_resume(struct device *dev) +{ + struct arm_smmu_device *smmu = dev_get_drvdata(dev); + + if (smmu->options & ARM_SMMU_OPT_SW_RETENTION) + return arm_smmu_device_reset(smmu); + + return 0; +} + +static const struct dev_pm_ops arm_smmu_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(NULL, arm_smmu_pm_resume) +}; + static const struct of_device_id arm_smmu_of_match[] = { { .compatible = "arm,smmu-v3", }, { }, @@ -2909,6 +2971,7 @@ static void arm_smmu_device_shutdown(struct platform_device *pdev) .driver = { .name = "arm-smmu-v3", .of_match_table = of_match_ptr(arm_smmu_of_match), + .pm = &arm_smmu_pm_ops, }, .probe = arm_smmu_device_probe, .remove = arm_smmu_device_remove,