From patchwork Wed Apr 3 19:17:12 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Soren Brinkmann X-Patchwork-Id: 2389161 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) by patchwork2.kernel.org (Postfix) with ESMTP id F1861DFB79 for ; Wed, 3 Apr 2013 19:19:42 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UNTDh-0000HG-G8 for patchwork-linux-arm@patchwork.kernel.org; Wed, 03 Apr 2013 19:19:41 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UNTBj-0001bp-5e; Wed, 03 Apr 2013 19:17:39 +0000 Received: from ch1ehsobe003.messaging.microsoft.com ([216.32.181.183] helo=ch1outboundpool.messaging.microsoft.com) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UNTBg-0001bS-CQ for linux-arm-kernel@lists.infradead.org; Wed, 03 Apr 2013 19:17:37 +0000 Received: from mail96-ch1-R.bigfish.com (10.43.68.246) by CH1EHSOBE013.bigfish.com (10.43.70.63) with Microsoft SMTP Server id 14.1.225.23; Wed, 3 Apr 2013 19:17:28 +0000 Received: from mail96-ch1 (localhost [127.0.0.1]) by mail96-ch1-R.bigfish.com (Postfix) with ESMTP id 7C7C13801F9; Wed, 3 Apr 2013 19:17:28 +0000 (UTC) X-Forefront-Antispam-Report: CIP:149.199.60.83; KIP:(null); UIP:(null); IPV:NLI; H:xsj-gw1; RD:unknown-60-83.xilinx.com; EFVD:NLI X-SpamScore: 1 X-BigFish: VPS1(zzzz1f42h1fc6h1ee6h1de0h1fdah1202h1e76h1d1ah1d2ahzz8275bhz2fh95h668h839hd24hf0ah119dh1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h14ddh1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1b0ah906i1155h) Received-SPF: pass (mail96-ch1: domain of xilinx.com designates 149.199.60.83 as permitted sender) client-ip=149.199.60.83; envelope-from=soren.brinkmann@xilinx.com; helo=xsj-gw1 ; helo=xsj-gw1 ; Received: from mail96-ch1 (localhost.localdomain [127.0.0.1]) by mail96-ch1 (MessageSwitch) id 1365016647529254_7678; Wed, 3 Apr 2013 19:17:27 +0000 (UTC) Received: from CH1EHSMHS018.bigfish.com (snatpool3.int.messaging.microsoft.com [10.43.68.226]) by mail96-ch1.bigfish.com (Postfix) with ESMTP id 74BA880045; Wed, 3 Apr 2013 19:17:27 +0000 (UTC) Received: from xsj-gw1 (149.199.60.83) by CH1EHSMHS018.bigfish.com (10.43.70.18) with Microsoft SMTP Server id 14.1.225.23; Wed, 3 Apr 2013 19:17:26 +0000 Received: from unknown-38-66.xilinx.com ([149.199.38.66] helo=xsj-smtp1.xilinx.com) by xsj-gw1 with esmtp (Exim 4.63) (envelope-from ) id 1UNTBV-0001F8-UR; Wed, 03 Apr 2013 12:17:25 -0700 From: Soren Brinkmann To: Mike Turquette , Russell King Subject: [PATCH] clk: Properly handle notifier return values Date: Wed, 3 Apr 2013 12:17:12 -0700 X-Mailer: git-send-email 1.8.2 X-RCIS-Action: ALLOW MIME-Version: 1.0 Message-ID: X-OriginatorOrg: xilinx.com X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130403_151736_786754_18004978 X-CRM114-Status: GOOD ( 13.03 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [216.32.181.183 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Soren Brinkmann , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Notifiers may return NOTIFY_(OK|DONE|STOP|BAD). The CCF uses an inconsistent mix of checking against NOTIFY_STOP or NOTIFY_BAD. This inconsistency leaves errors undetected in some cases: clk_set_parent() calls __clk_speculate_rates(), which stops when it hits a NOTIFIER_BAD (STOP is ignored), and passes this value back to the caller. clk_set_parent() compares this return value against NOTIFY_STOP only, ignoring NOTIFY_BAD returns. Use NOTIFY_STOP_MASK to detect a negative notifier return value and document all four return value options. Signed-off-by: Soren Brinkmann --- drivers/clk/clk.c | 10 +++++----- include/linux/clk.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index ed87b24..68bd38c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -876,16 +876,16 @@ static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate) else new_rate = parent_rate; - /* abort the rate change if a driver returns NOTIFY_BAD */ + /* abort rate change if a driver returns NOTIFY_BAD or NOTIFY_STOP */ if (clk->notifier_count) ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate); - if (ret == NOTIFY_BAD) + if (ret & NOTIFY_STOP_MASK) goto out; hlist_for_each_entry(child, &clk->children, child_node) { ret = __clk_speculate_rates(child, new_rate); - if (ret == NOTIFY_BAD) + if (ret & NOTIFY_STOP_MASK) break; } @@ -978,7 +978,7 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even if (clk->notifier_count) { ret = __clk_notify(clk, event, clk->rate, clk->new_rate); - if (ret == NOTIFY_BAD) + if (ret & NOTIFY_STOP_MASK) fail_clk = clk; } @@ -1296,7 +1296,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) ret = __clk_speculate_rates(clk, parent->rate); /* abort if a driver objects */ - if (ret == NOTIFY_STOP) + if (ret & NOTIFY_STOP_MASK) goto out; /* only re-parent if the clock is not in use */ diff --git a/include/linux/clk.h b/include/linux/clk.h index b3ac22d..9a6d045 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -28,16 +28,16 @@ struct clk; * PRE_RATE_CHANGE - called immediately before the clk rate is changed, * to indicate that the rate change will proceed. Drivers must * immediately terminate any operations that will be affected by the - * rate change. Callbacks may either return NOTIFY_DONE or - * NOTIFY_STOP. + * rate change. Callbacks may either return NOTIFY_DONE, NOTIFY_OK, + * NOTIFY_STOP or NOTIFY_BAD. * * ABORT_RATE_CHANGE: called if the rate change failed for some reason * after PRE_RATE_CHANGE. In this case, all registered notifiers on * the clk will be called with ABORT_RATE_CHANGE. Callbacks must - * always return NOTIFY_DONE. + * always return NOTIFY_DONE or NOTIFY_OK. * * POST_RATE_CHANGE - called after the clk rate change has successfully - * completed. Callbacks must always return NOTIFY_DONE. + * completed. Callbacks must always return NOTIFY_DONE or NOTIFY_OK. * */ #define PRE_RATE_CHANGE BIT(0)