From patchwork Tue Feb 6 10:54:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Brunet X-Patchwork-Id: 126983 Delivered-To: patch@linaro.org Received: by 10.46.124.24 with SMTP id x24csp2798068ljc; Tue, 6 Feb 2018 02:54:20 -0800 (PST) X-Google-Smtp-Source: AH8x226idp+EjUbhFu89p/I5kbJnukChnSZWJYPG2mFyrlZwtKASmAmalsc3UZAorDgR+Obez0u8 X-Received: by 10.98.201.69 with SMTP id k66mr2018421pfg.105.1517914460538; Tue, 06 Feb 2018 02:54:20 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1517914460; cv=none; d=google.com; s=arc-20160816; b=Z5ILCRxlyL61ol86w4WIWUHMnUPw9VDTA1X6lXbn6kgnzUdkXhHL6GlqG1xfu/9sK3 CkWvMNkTxSFCJGYLS5Yoal3kQjYGtNf0lWG4AinoaIcaAINBHbON3n5i4RmphV7Ticbq jCZMqQ/DT50IMLrOdb2KTi1YyFZinI4IQkrbWnl1/uKOkE9zrM+uwxwYpShYwrrzXmDx G7l3aFK4y2siFUcDVVz2FnnqSc5QINmAMYbJNSSygwPejOyng4kcttxAklJIJ8C03Qjy XmNZI4Mf0VjWySvmz/80IxSL8kQBI0yncvDVAzbpJXSQQLBJavN4K4zDnGY65IOHxF3Q YgTA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :dkim-signature:arc-authentication-results; bh=RjVrLiphTPM+bT6FXKwuW21cyg+7H6uho37k+GLzpRo=; b=K7soBxtnwFo4/hhBl8jwFYTL2Gwq8gjyNgZ6Kt5Rpo2EtXzY4SnSsa8Gv6WhmiSz// m8sO0pPC6DvgGVENiTZTfdjFajSvug2qOxGUWohXNFEKNo5plJuzL+SZfPepTvy7AjjN azRdeuIFPlP9g0m46T+VCQnDUz7HkWBKxcS8YZ3+3ZZwSCYevMnRjVtoMI0qutUpvHZV R2Etd9Qklbu8fxPpmhzC5JNIkYvjcQoZ5RcTI13lf8x9lxw/l62lpZX6KEdaUcsJ7Lo8 AVmo3CD4Xaal1bcj/0VNar6cRyQRFra5Sfial9a/+GGoeaBcg8gWsOS/QkcMYUrqYFRB rU4Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@baylibre-com.20150623.gappssmtp.com header.s=20150623 header.b=SGjjoZiP; 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 y186si839856pgd.706.2018.02.06.02.54.20; Tue, 06 Feb 2018 02:54:20 -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=SGjjoZiP; 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 S1752770AbeBFKyS (ORCPT + 22 others); Tue, 6 Feb 2018 05:54:18 -0500 Received: from mail-wr0-f196.google.com ([209.85.128.196]:32988 "EHLO mail-wr0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752256AbeBFKyJ (ORCPT ); Tue, 6 Feb 2018 05:54:09 -0500 Received: by mail-wr0-f196.google.com with SMTP id s5so1414593wra.0 for ; Tue, 06 Feb 2018 02:54:09 -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; bh=RjVrLiphTPM+bT6FXKwuW21cyg+7H6uho37k+GLzpRo=; b=SGjjoZiPqIA7BxKaXI4AuWJWIyeJbvrjnxWLJNZJCISVce3c8pUcj3FFupiqPCoyXM Ofp23SqbMPhksIRMAB/6pEZ6ljfbBaGf5GiiDf+V7O8OQn9mcSqRcjpPvJF0flQ9r+Hw f6OhMcBHpcSq8/LBExwAGqaiTo8Bh2p30g6lW0HHxwhcnYpwN48Nd9BLkmH74QbkBvWb 1nuqCjHsgJbs0ANcMklwLBmFtAlYJPgg4XFiBpN0GQY3XkPcjyUN8+4DVYJhwIk1oFN6 v832QFkobN3Mv2Dthte+e4OonBi78FlROpNOkdCoOx1mHNmDC5hKNsIDlit2jZjBiUg+ mTbA== 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; bh=RjVrLiphTPM+bT6FXKwuW21cyg+7H6uho37k+GLzpRo=; b=mACbJF+PYXtF/vtDk4Uqb+oBb68IVWF52lCdoNM/4rfFhWVFUpOpK49SOBO2ZwQdyH 8T0Qizu8ARmF6Wsvx67o4YaFNrRzBL4XfbXNgqF5ltFsXYRipJyZ8jwJyN/44DUYA1sw IR1VDEABoV5NfVD8Hhp1CwixSL2tP/vilw6NWnOtdiBAe60cvN/E9gJ/bPZldNjDY2gt NQQ/UUyJ47dVy5hUmwAGsMcOfy29o5myjh7gaQGH+11/2chSwIWiFB4G9VelGBKeNSk/ 9+VKjZD6p5bXWfcDB5VrE37WE7x/lWXOQ4ls80lB9fT68m5FpZY2SqRIeYXfVk6oEm/z 1nyQ== X-Gm-Message-State: APf1xPB040/SedsgqIAn1gCjpybHZn+j5a4zyyqO34IPcWzWaurRTlAI FZXVgRI02KCe632TU7KBe/maAg== X-Received: by 10.223.146.135 with SMTP id 7mr1983079wrn.123.1517914448299; Tue, 06 Feb 2018 02:54:08 -0800 (PST) Received: from boomer.baylibre.local ([90.63.244.31]) by smtp.googlemail.com with ESMTPSA id d73sm10172573wma.25.2018.02.06.02.54.07 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 06 Feb 2018 02:54:07 -0800 (PST) From: Jerome Brunet To: Stephen Boyd , Michael Turquette Cc: Jerome Brunet , linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, Neil Armstrong , Shawn Guo , Dong Aisheng Subject: [PATCH] clk: migrate the count of orphaned clocks at init Date: Tue, 6 Feb 2018 11:54:04 +0100 Message-Id: <20180206105404.13086-1-jbrunet@baylibre.com> X-Mailer: git-send-email 2.14.3 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 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);