From patchwork Tue Apr 2 21:09:39 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Hansson X-Patchwork-Id: 15828 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id AC90D4C13C2 for ; Tue, 2 Apr 2013 21:10:09 +0000 (UTC) Received: from mail-qe0-f71.google.com (mail-qe0-f71.google.com [209.85.128.71]) by fiordland.canonical.com (Postfix) with ESMTP id 587FAA1A5D5 for ; Tue, 2 Apr 2013 21:10:09 +0000 (UTC) Received: by mail-qe0-f71.google.com with SMTP id 7sf1473137qeb.6 for ; Tue, 02 Apr 2013 14:10:08 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-beenthere:x-received:received-spf:x-received :x-forwarded-to:x-forwarded-for:delivered-to:x-received:received-spf :from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :mime-version:x-gm-message-state:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe :content-type; bh=M0EbfuVgLUYUK95mXbHoV/4UMkExsFLMiQNIbcaxcRo=; b=D3zzn4hdMh1xATCHRcO2zag1qaN2jGoWGdgKO92UlmM1upoKNDEV65Zs6SYzb7ZiYk f0TswkinxepzAxBLVFDws/HFSK+KMuadCO0b8VkZXhht5zmm3DNspHgwCVSLdwlc1n1v 5hvT6lS6xpmxlMUUHQOOppL5aY4LSmc7JtJvUliAAhNGPB3srM1j6GhI4RaFqaXdCHaY 5FRBr8S+9LwWoaPw/MTyzlr1clWMusPczgE032b9nvUWoNkJx9On1a8MCYdAmMRe740A 9K1xfxiMwpR/tgzvmXcWFdDhAyXwg+1v2Gi/loMZEni0AOULHpZ/m5FoA3S63fX6LGj/ s83g== X-Received: by 10.224.185.79 with SMTP id cn15mr11241038qab.4.1364937008892; Tue, 02 Apr 2013 14:10:08 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.75.6 with SMTP id y6ls614070qev.94.gmail; Tue, 02 Apr 2013 14:10:08 -0700 (PDT) X-Received: by 10.52.89.52 with SMTP id bl20mr11842772vdb.85.1364937008674; Tue, 02 Apr 2013 14:10:08 -0700 (PDT) Received: from mail-vc0-f173.google.com (mail-vc0-f173.google.com [209.85.220.173]) by mx.google.com with ESMTPS id b4si2665376vdw.5.2013.04.02.14.10.08 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 02 Apr 2013 14:10:08 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.173 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.173; Received: by mail-vc0-f173.google.com with SMTP id gd11so952584vcb.32 for ; Tue, 02 Apr 2013 14:10:08 -0700 (PDT) X-Received: by 10.220.154.199 with SMTP id p7mr14149721vcw.46.1364937008559; Tue, 02 Apr 2013 14:10:08 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.59.4.204 with SMTP id cg12csp143068ved; Tue, 2 Apr 2013 14:10:07 -0700 (PDT) X-Received: by 10.180.79.227 with SMTP id m3mr18769722wix.12.1364937006470; Tue, 02 Apr 2013 14:10:06 -0700 (PDT) Received: from eu1sys200aog107.obsmtp.com (eu1sys200aog107.obsmtp.com [207.126.144.123]) by mx.google.com with SMTP id d42si5291129eep.18.2013.04.02.14.10.03 (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 02 Apr 2013 14:10:06 -0700 (PDT) Received-SPF: neutral (google.com: 207.126.144.123 is neither permitted nor denied by best guess record for domain of ulf.hansson@stericsson.com) client-ip=207.126.144.123; Received: from beta.dmz-eu.st.com ([164.129.1.35]) (using TLSv1) by eu1sys200aob107.postini.com ([207.126.147.11]) with SMTP ID DSNKUVtJKyeRcQPvArcdZiffWMjMQxdf9M93@postini.com; Tue, 02 Apr 2013 21:10:06 UTC Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 03ADEE8; Tue, 2 Apr 2013 21:09:57 +0000 (GMT) Received: from relay1.stm.gmessaging.net (unknown [10.230.100.17]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 951DCA151; Tue, 2 Apr 2013 21:09:57 +0000 (GMT) Received: from exdcvycastm004.EQ1STM.local (alteon-source-exch [10.230.100.61]) (using TLSv1 with cipher RC4-MD5 (128/128 bits)) (Client CN "exdcvycastm004", Issuer "exdcvycastm004" (not verified)) by relay1.stm.gmessaging.net (Postfix) with ESMTPS id 976D524C07D; Tue, 2 Apr 2013 23:09:46 +0200 (CEST) Received: from steludxu1397.stericsson.com (10.230.100.153) by smtp.stericsson.com (10.230.100.2) with Microsoft SMTP Server (TLS) id 8.3.279.5; Tue, 2 Apr 2013 23:09:56 +0200 From: Ulf Hansson To: , Mike Turquette Cc: Linus Walleij , Par-Olof Hakansson , Ulf Hansson , Rajagopal Venkat Subject: [PATCH V4 3/3] clk: Fixup locking issues for clk_set_parent Date: Tue, 2 Apr 2013 23:09:39 +0200 Message-ID: <1364936979-20805-4-git-send-email-ulf.hansson@stericsson.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1364936979-20805-1-git-send-email-ulf.hansson@stericsson.com> References: <1364936979-20805-1-git-send-email-ulf.hansson@stericsson.com> MIME-Version: 1.0 X-Gm-Message-State: ALoCoQmgDqxLjUelfmYUc7RbUaCkfnt2fGXb40KATfjpKe3KBrvWGEIm0vLK9dChqf871mhfiq8N X-Original-Sender: patch@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.173 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Ulf Hansson Updating the clock tree topology must be protected with the spinlock when doing clk_set_parent, otherwise we can not handle the migration of the enable_count in a safe manner. While issuing the .set_parent callback to make the clk-hw perform the switch to the new parent, we can not hold the spinlock since it is must be allowed to be slow path. This complicates error handling, but is still possible to achieve. Signed-off-by: Ulf Hansson Cc: Rajagopal Venkat --- drivers/clk/clk.c | 67 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index c83e8e5..de6b459 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1363,31 +1363,71 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) unsigned long flags; int ret = 0; struct clk *old_parent = clk->parent; + bool migrated_enable = false; - /* migrate prepare and enable */ + /* migrate prepare */ if (clk->prepare_count) __clk_prepare(parent); - /* FIXME replace with clk_is_enabled(clk) someday */ flags = clk_enable_lock(); - if (clk->enable_count) + + /* migrate enable */ + if (clk->enable_count) { __clk_enable(parent); + migrated_enable = true; + } + + /* update the clk tree topology */ + clk_reparent(clk, parent); + clk_enable_unlock(flags); /* change clock input source */ if (parent && clk->ops->set_parent) ret = clk->ops->set_parent(clk->hw, p_index); - /* clean up old prepare and enable */ - flags = clk_enable_lock(); - if (clk->enable_count) + if (ret) { + /* + * The error handling is tricky due to that we need to release + * the spinlock while issuing the .set_parent callback. This + * means the new parent might have been enabled/disabled in + * between, which must be considered when doing rollback. + */ + flags = clk_enable_lock(); + + clk_reparent(clk, old_parent); + + if (migrated_enable && clk->enable_count) { + __clk_disable(parent); + } else if (migrated_enable && (clk->enable_count == 0)) { + __clk_disable(old_parent); + } else if (!migrated_enable && clk->enable_count) { + __clk_disable(parent); + __clk_enable(old_parent); + } + + clk_enable_unlock(flags); + + if (clk->prepare_count) + __clk_unprepare(parent); + + return ret; + } + + /* clean up enable for old parent if migration was done */ + if (migrated_enable) { + flags = clk_enable_lock(); __clk_disable(old_parent); - clk_enable_unlock(flags); + clk_enable_unlock(flags); + } + /* clean up prepare for old parent if migration was done */ if (clk->prepare_count) __clk_unprepare(old_parent); - return ret; + /* update debugfs with new clk tree topology */ + clk_debug_reparent(clk, parent); + return 0; } /** @@ -1450,14 +1490,11 @@ int clk_set_parent(struct clk *clk, struct clk *parent) /* do the re-parent */ ret = __clk_set_parent(clk, parent, p_index); - /* propagate ABORT_RATE_CHANGE if .set_parent failed */ - if (ret) { + /* propagate rate recalculation accordingly */ + if (ret) __clk_recalc_rates(clk, ABORT_RATE_CHANGE); - goto out; - } - - /* propagate rate recalculation downstream */ - __clk_reparent(clk, parent); + else + __clk_recalc_rates(clk, POST_RATE_CHANGE); out: clk_prepare_unlock();