From patchwork Thu Apr 4 21:53:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 10886393 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C60231800 for ; Thu, 4 Apr 2019 21:54:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B146C28AF2 for ; Thu, 4 Apr 2019 21:54:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A553628AFB; Thu, 4 Apr 2019 21:54:21 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3308928AF2 for ; Thu, 4 Apr 2019 21:54:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730380AbfDDVxr (ORCPT ); Thu, 4 Apr 2019 17:53:47 -0400 Received: from mail.kernel.org ([198.145.29.99]:48034 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730307AbfDDVxr (ORCPT ); Thu, 4 Apr 2019 17:53:47 -0400 Received: from mail.kernel.org (unknown [104.132.0.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id B81AA217D4; Thu, 4 Apr 2019 21:53:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1554414826; bh=xjPB9a00FxHgJzIN50j1f9PNVneVM2xL4EeIQGBBIuw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=wg+Q2YHzwXMDAnonntiFd9k50Mqr57b3YWtCaOihjGoThHYMxbC0d2CRDYGTFw01J kta2yTPdE3rAyxlUPT7c5jDv92AVTFRvUGr+Bpmq9qY5XTzgQtTJk1jd3XPwMqxYhq nIhwWuMwxJhL1xeRhTglTznP0+9/TZL4h2x+tp2E= From: Stephen Boyd To: Michael Turquette , Stephen Boyd Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Miquel Raynal , Jerome Brunet , Russell King , Jeffrey Hugo , Chen-Yu Tsai , Matti Vaittinen Subject: [PATCH v3 1/7] clkdev: Hold clocks_mutex while iterating clocks list Date: Thu, 4 Apr 2019 14:53:38 -0700 Message-Id: <20190404215344.6330-2-sboyd@kernel.org> X-Mailer: git-send-email 2.21.0.392.gf8f6787159e-goog In-Reply-To: <20190404215344.6330-1-sboyd@kernel.org> References: <20190404215344.6330-1-sboyd@kernel.org> MIME-Version: 1.0 Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We recently introduced a change to support devm clk lookups. That change introduced a code-path that used clk_find() without holding the 'clocks_mutex'. Unfortunately, clk_find() iterates over the 'clocks' list and so we need to prevent the list from being modified while iterating over it by holding the mutex. Similarly, we don't need to hold the 'clocks_mutex' besides when we're dereferencing the clk_lookup pointer we find or while we're modifying/iterating the 'clocks' list. Let's ensure that we have the mutex held while iterating the list and fix the callers of clk_find() to only hold the mutex as long as they need to. This should fix this race and also nicely move clk creation outside of the 'clocks_mutex'. Fixes: 3eee6c7d119c ("clkdev: add managed clkdev lookup registration") Cc: Miquel Raynal Cc: Jerome Brunet Cc: Russell King Cc: Michael Turquette Cc: Jeffrey Hugo Cc: Chen-Yu Tsai Cc: Matti Vaittinen Signed-off-by: Stephen Boyd --- drivers/clk/clkdev.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 8c4435c53f09..db82eee8e209 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -36,7 +36,7 @@ static DEFINE_MUTEX(clocks_mutex); * Then we take the most specific entry - with the following * order of precedence: dev+con > dev only > con only. */ -static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) +static struct clk_lookup *__clk_find(const char *dev_id, const char *con_id) { struct clk_lookup *p, *cl = NULL; int match, best_found = 0, best_possible = 0; @@ -46,6 +46,8 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) if (con_id) best_possible += 1; + lockdep_assert_held(&clocks_mutex); + list_for_each_entry(p, &clocks, node) { match = 0; if (p->dev_id) { @@ -70,25 +72,37 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) return cl; } -static struct clk *__clk_get_sys(struct device *dev, const char *dev_id, - const char *con_id) +static struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id) { struct clk_lookup *cl; - struct clk *clk = NULL; + struct clk_hw *hw = ERR_PTR(-ENOENT); mutex_lock(&clocks_mutex); + cl = __clk_find(dev_id, con_id); + if (cl) + hw = cl->clk_hw; + mutex_unlock(&clocks_mutex); - cl = clk_find(dev_id, con_id); - if (!cl) - goto out; + return hw; +} - clk = clk_hw_create_clk(dev, cl->clk_hw, dev_id, con_id); - if (IS_ERR(clk)) - cl = NULL; -out: +static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) +{ + struct clk_lookup *cl; + + mutex_lock(&clocks_mutex); + cl = __clk_find(dev_id, con_id); mutex_unlock(&clocks_mutex); - return cl ? clk : ERR_PTR(-ENOENT); + return cl; +} + +static struct clk *__clk_get_sys(struct device *dev, const char *dev_id, + const char *con_id) +{ + struct clk_hw *hw = clk_find_hw(dev_id, con_id); + + return clk_hw_create_clk(dev, hw, dev_id, con_id); } struct clk *clk_get_sys(const char *dev_id, const char *con_id)