From patchwork Wed Feb 14 13:43:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 128344 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp622239ljc; Wed, 14 Feb 2018 05:44:02 -0800 (PST) X-Google-Smtp-Source: AH8x224R183d9IkS7ZZxgQ7XLivBznvf+4PAaSxtIJPIiG/ry/gUx6mxzfXAH7dT/WrsZhTc8LHA X-Received: by 10.99.189.82 with SMTP id d18mr3976703pgp.172.1518615842558; Wed, 14 Feb 2018 05:44:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1518615842; cv=none; d=google.com; s=arc-20160816; b=Vg/5qlASF92cSwyL6iwd3RuCzCOYlgZoUxlZ6cXyCWJk3h5vTSKn7SVkBujAByrlxH iwXuiFvHSQDEnKGl3gPivwhl97HN2CC5TY99HREKNdAgZ12VYrodpDpBWIhvRw92vGHi zMeArVkcjaEgiSJTvu8hk02SIVejOgYW1a5NjeuWiUoGo4TYHIg1gQuNUCn9ICmLQ/hD K3pbalNytd2keaaSXC/3tujLOaPboWqxMqG2q9Fmxi8AGavMXI1chFaEhO83LN0Am2LQ rBukbhrlKvExBlaDh6HSOd+Dg2cCcLdQft17w9qDKjNx7WjSFj6v4QWb4Z4raZagYSMp BWdg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=RjVrLiphTPM+bT6FXKwuW21cyg+7H6uho37k+GLzpRo=; b=vnPF8r8bl3qnCyQOrxXSDdZyQaRjH7O23H/vWiu6hR1iACiyf73dkJqnszOuVtaC/s SNgXC7ASR2Soc6PKt1/hKnOA5WFRBE26fZcLu0kCjyd48smziMmFwx5gAsiBsJFF1u34 SeXR62jFqa4qDo+pdgiOzeDIUDcFCtfkWHG6qR0vJvBP5BqL1TSKPBj/GTL+vy7QHqEq 5QFO5p4kXELphMptspWuGTd1TcEVrQy76NeS5N9a5tpIZYeOhDj6gpqxAf9TT250u/9t rUYbzopT/M/Y1BuwRQZM8asuh+W7/V0Drao4ZM/4Jbf88weswsCshSm21qZi+h3bYVT9 H06w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=0aWZ23TT; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t5si1091316pgf.93.2018.02.14.05.44.02; Wed, 14 Feb 2018 05:44:02 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=0aWZ23TT; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1030416AbeBNNn4 (ORCPT + 28 others); Wed, 14 Feb 2018 08:43:56 -0500 Received: from mail-wr0-f193.google.com ([209.85.128.193]:36522 "EHLO mail-wr0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1030372AbeBNNnu (ORCPT ); Wed, 14 Feb 2018 08:43:50 -0500 Received: by mail-wr0-f193.google.com with SMTP id u15so643196wrg.3 for ; Wed, 14 Feb 2018 05:43:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=RjVrLiphTPM+bT6FXKwuW21cyg+7H6uho37k+GLzpRo=; b=0aWZ23TTZZm88XH8UqvN0hL/Dgam9nDl2nIu5RBQsIwU9Vr/VdWlE0Kul03f2OMdjy mBZqguBG2Kh8w5kDrKFfplOJmmShp9HJYI+3thcmBd6cHQ9f5eXfI6IZPdwFdNxX6Eg+ 9RP3mXe+J98I5Mol2Nnf1SYmGXU9qYRJqXoK14Xzz8/vlfyv3tswGd0DWOAVrDQx7llf eXWl/1eVHoE6lnq0fkVUq0CDNldXOrYutJZZH1Jh9YoGcPc8w996NgbzVYtKimleSmdT CE8er3P1wwpf8gTdcd2QY3k8+A+0KkTI+05J/E38PD8tsdtw4dE0fkdzEwUtapv7XSTf MfEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=RjVrLiphTPM+bT6FXKwuW21cyg+7H6uho37k+GLzpRo=; b=htje6hO67GT8r4AGdExKG0FGR4udLyHkKF1NIdy2mTeHvQzO7xd+mdedgoSOlVcXuT WyHT4irsI3jcLr065sViUEFBVH4MMwqsJ9DQ34BCD2fhLqyLXDYyqaCgRW8/KhvOmUr9 b1nI7AyOr1VsOrG9uBmvb6llgt7MvSuOjScVKkBGfCDPWN6MVsMxEf/AXoHST+vyz7Ev kKg6s+Ld3vNUz9F3AuKjP2IKRfwlb2PtWT48Xzo657GIsnUW5GeoJqo4j/GvoJo77mhF ydrQD9DbhI5EY7wuGOrgJa2WCv5WhQxTINEGRGVG0qsjkuGORXo0RsNStWU15AOQNleM D1hA== X-Gm-Message-State: APf1xPAJD7J2M2aic6O/M2vxammiPY/NZeoabfpeQW8vHCs9CzdSGgeo Zwu7pSxcZaWFQ1qEjcn2UCtAuA== X-Received: by 10.223.186.83 with SMTP id t19mr4382315wrg.252.1518615829316; Wed, 14 Feb 2018 05:43:49 -0800 (PST) Received: from boomer.lan (cag06-3-82-243-161-21.fbx.proxad.net. [82.243.161.21]) by smtp.googlemail.com with ESMTPSA id k5sm6337694wmg.47.2018.02.14.05.43.48 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 14 Feb 2018 05:43:48 -0800 (PST) From: Jerome Brunet To: Michael Turquette , Stephen Boyd Cc: Jerome Brunet , linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, Stephen Boyd , Shawn Guo , Dong Aisheng Subject: [PATCH v2 4/8] clk: migrate the count of orphaned clocks at init Date: Wed, 14 Feb 2018 14:43:36 +0100 Message-Id: <20180214134340.17242-5-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180214134340.17242-1-jbrunet@baylibre.com> References: <20180214134340.17242-1-jbrunet@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The orphan clocks reparents should migrate any existing count from the orphan clock to its new acestor clocks, otherwise we may have inconsistent counts in the tree and end-up with gated critical clocks Assuming we have two clocks, A and B. * Clock A has CLK_IS_CRITICAL flag set. * Clock B is an ancestor of A which can gate. Clock B gate is left enabled by the bootloader. Step 1: Clock A is registered. Since it is a critical clock, it is enabled. The clock being still an orphan, no parent are enabled. Step 2: Clock B is registered and reparented to clock A (potentially through several other clocks). We are now in situation where the enable count of clock A is 1 while the enable count of its ancestors is 0, which is not good. Step 3: in lateinit, clk_disable_unused() is called, the enable_count of clock B being 0, clock B is gated and and critical clock A actually gets disabled. This situation was found while adding fdiv_clk gates to the meson8b platform. These clocks parent clk81 critical clock, which is the mother of all peripheral clocks in this system. Because of the issue described here, the system is crashing when clk_disable_unused() is called. The situation is solved by reverting commit f8f8f1d04494 ("clk: Don't touch hardware when reparenting during registration"). To avoid breaking again the situation described in this commit description, enabling critical clock should be done before walking the orphan list. This way, a parent critical clock may not be accidentally disabled due to the CLK_OPS_PARENT_ENABLE mechanism. Fixes: f8f8f1d04494 ("clk: Don't touch hardware when reparenting during registration") Cc: Stephen Boyd Cc: Shawn Guo Cc: Dong Aisheng Signed-off-by: Jerome Brunet --- drivers/clk/clk.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) -- 2.14.3 Tested-by: Marek Szyprowski Tested-by: Heiko Stuebner diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index a4b4e4d6df5e..cca05ea2c058 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2969,23 +2969,38 @@ static int __clk_core_init(struct clk_core *core) rate = 0; core->rate = core->req_rate = rate; + /* + * Enable CLK_IS_CRITICAL clocks so newly added critical clocks + * don't get accidentally disabled when walking the orphan tree and + * reparenting clocks + */ + if (core->flags & CLK_IS_CRITICAL) { + unsigned long flags; + + clk_core_prepare(core); + + flags = clk_enable_lock(); + clk_core_enable(core); + clk_enable_unlock(flags); + } + /* * walk the list of orphan clocks and reparent any that newly finds a * parent. */ hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) { struct clk_core *parent = __clk_init_parent(orphan); - unsigned long flags; /* - * we could call __clk_set_parent, but that would result in a - * redundant call to the .set_rate op, if it exists + * We need to use __clk_set_parent_before() and _after() to + * to properly migrate any prepare/enable count of the orphan + * clock. This is important for CLK_IS_CRITICAL clocks, which + * are enabled during init but might not have a parent yet. */ if (parent) { /* update the clk tree topology */ - flags = clk_enable_lock(); - clk_reparent(orphan, parent); - clk_enable_unlock(flags); + __clk_set_parent_before(orphan, parent); + __clk_set_parent_after(orphan, parent, NULL); __clk_recalc_accuracies(orphan); __clk_recalc_rates(orphan, 0); } @@ -3002,16 +3017,6 @@ static int __clk_core_init(struct clk_core *core) if (core->ops->init) core->ops->init(core->hw); - if (core->flags & CLK_IS_CRITICAL) { - unsigned long flags; - - clk_core_prepare(core); - - flags = clk_enable_lock(); - clk_core_enable(core); - clk_enable_unlock(flags); - } - kref_init(&core->ref); out: clk_pm_runtime_put(core);