From patchwork Wed Oct 12 18:16:08 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Caesar Wang X-Patchwork-Id: 9373659 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 7B8C3607FD for ; Wed, 12 Oct 2016 18:16:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 68CA32841E for ; Wed, 12 Oct 2016 18:16:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5B11B29155; Wed, 12 Oct 2016 18:16:43 +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=-3.7 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id A65472841E for ; Wed, 12 Oct 2016 18:16:41 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1buO52-0001Kw-Eo; Wed, 12 Oct 2016 18:16:40 +0000 Received: from mail-pa0-f66.google.com ([209.85.220.66]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1buO4x-0001IM-2D for linux-rockchip@lists.infradead.org; Wed, 12 Oct 2016 18:16:38 +0000 Received: by mail-pa0-f66.google.com with SMTP id hh10so3633408pac.0 for ; Wed, 12 Oct 2016 11:16:13 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=FvR572/tsM+eldFrLsI3OuSV0ckox7lccYHjs37pWWQ=; b=KzmzoTO+ecHdyxwPe73SrRSSPoAtk/sh2pHZ37qOnqZ4rK9oQ6QVVBAln4dGQzjsx8 YryKEZ3/3sQ+dAJd8/aq/iRILPCC4hnaZR5nCnP8gOpH2FoRopiuto5LKkZrBAnAPYDu 4nM1FIN26fVo6PMZuDwVDIm9k0puddUm7xVVPD6fBq4LkjmDFjFeChfedexB8yNBoeqc TIjHXeE1zPljC39ill57uggH6iZRH6dA0YlTfonY2x+YWfjRuqXgni5sGfH5OcQh43OW Qv8yKr5cKx465eD8M5+0HPPy5H9+xZDvhWYWYSGQ4mzaPKdknCyjJq6S6q7Rf9lnM7y9 PuqQ== X-Gm-Message-State: AA6/9RnRuI+Xtva/EwdtnyGcJS6rbp6zQ9OTXbw4LE2lXFcKTW3yQtYY14kL7q7yyvhbDw== X-Received: by 10.66.219.201 with SMTP id pq9mr3138662pac.32.1476296173484; Wed, 12 Oct 2016 11:16:13 -0700 (PDT) Received: from nb.corp.google.com ([172.22.52.163]) by smtp.gmail.com with ESMTPSA id a23sm13350731pfc.59.2016.10.12.11.16.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 12 Oct 2016 11:16:12 -0700 (PDT) From: Caesar Wang To: khilman@linaro.org, heiko@sntech.de Subject: [PATCH v2] soc: rockchip: avoid infinite loop for power domain Date: Thu, 13 Oct 2016 02:16:08 +0800 Message-Id: <1476296168-29154-1-git-send-email-wxt@rock-chips.com> X-Mailer: git-send-email 1.9.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161012_111635_182153_3DEB31E1 X-CRM114-Status: GOOD ( 14.95 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-rockchip@lists.infradead.org, zhangqing@rock-chips.com, linux-kernel@vger.kernel.org, Caesar Wang , tfiga@chromium.org MIME-Version: 1.0 Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+patchwork-linux-rockchip=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP In some cases, we have met the infinite loop in rockchip_pmu_set_idle_request() or rockchip_do_pmu_set_power_domain(). As the crosbug.com/p/57351 reported, the boot hangs right after this [1.629163] bootconsole [uart8250] disabled [1.639286] [drm:drm_core_init] Initialized drm 1.1.0 20060810 [1.645926] [drm:drm_get_platform_dev] Initialized vgem 1.0.0 20120112.. [1.654558] iommu: Adding device ff8f0000.vop to group 0 [1.660569] iommu: Adding device ff900000.vop to group 1 This patch adds the error message and timeout to avoid infinite loop if it fails to get the ack. Signed-off-by: Caesar Wang --- Changes in v2: - As the Tomasz & Heiko feedback on http://crosreview.com/395589: * Also, need the timeout for rockchip_do_set_power_domain. * s/target_on/is_on, s/target_idle/is_idle. * unsigned int instear of u32. drivers/soc/rockchip/pm_domains.c | 48 +++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c index 7acd151..260fbcc 100644 --- a/drivers/soc/rockchip/pm_domains.c +++ b/drivers/soc/rockchip/pm_domains.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -105,12 +106,24 @@ static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd) return (val & pd_info->idle_mask) == pd_info->idle_mask; } +static unsigned int rockchip_pmu_read_ack(struct rockchip_pmu *pmu) +{ + unsigned int val; + + regmap_read(pmu->regmap, pmu->info->ack_offset, &val); + return val; +} + static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, bool idle) { const struct rockchip_domain_info *pd_info = pd->info; + struct generic_pm_domain *genpd = &pd->genpd; struct rockchip_pmu *pmu = pd->pmu; unsigned int val; + unsigned int target_ack; + bool is_idle; + int ret; if (pd_info->req_mask == 0) return 0; @@ -120,12 +133,26 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd, dsb(sy); - do { - regmap_read(pmu->regmap, pmu->info->ack_offset, &val); - } while ((val & pd_info->ack_mask) != (idle ? pd_info->ack_mask : 0)); + /* Wait util idle_ack = 1 */ + target_ack = idle ? pd_info->ack_mask : 0; + ret = readx_poll_timeout_atomic(rockchip_pmu_read_ack, pmu, val, + (val & pd_info->ack_mask) == target_ack, + 0, 10000); + if (ret) { + dev_err(pmu->dev, + "failed to get ack on domain '%s', val=0x%x\n", + genpd->name, val); + return ret; + } - while (rockchip_pmu_domain_is_idle(pd) != idle) - cpu_relax(); + ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd, + is_idle, is_idle == idle, 0, 10000); + if (ret) { + dev_err(pmu->dev, + "failed to set idle on domain '%s', val=%d\n", + genpd->name, is_idle); + return ret; + } return 0; } @@ -198,6 +225,8 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, bool on) { struct rockchip_pmu *pmu = pd->pmu; + struct generic_pm_domain *genpd = &pd->genpd; + bool is_on; if (pd->info->pwr_mask == 0) return; @@ -207,8 +236,13 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, dsb(sy); - while (rockchip_pmu_domain_is_on(pd) != on) - cpu_relax(); + if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on, + is_on == on, 0, 10000)) { + dev_err(pmu->dev, + "failed to set domain '%s', val=%d\n", + genpd->name, is_on); + return; + } } static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)