From patchwork Thu Dec 3 10:06:50 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sekhar Nori X-Patchwork-Id: 64473 Received: from arroyo.ext.ti.com (arroyo.ext.ti.com [192.94.94.40]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nB3A9l7d022843 for ; Thu, 3 Dec 2009 10:09:48 GMT Received: from dlep35.itg.ti.com ([157.170.170.118]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id nB3A7uXt022536 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 3 Dec 2009 04:07:56 -0600 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep35.itg.ti.com (8.13.7/8.13.7) with ESMTP id nB3A7upd006185; Thu, 3 Dec 2009 04:07:56 -0600 (CST) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id C9E968062A; Thu, 3 Dec 2009 04:07:29 -0600 (CST) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dbdp31.itg.ti.com (dbdp31.itg.ti.com [172.24.170.98]) by linux.omap.com (Postfix) with ESMTP id A2C728062B for ; Thu, 3 Dec 2009 04:06:57 -0600 (CST) Received: from psplinux051.india.ti.com (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id nB3A6t3b014187; Thu, 3 Dec 2009 15:36:55 +0530 (IST) Received: from psplinux051.india.ti.com (localhost [127.0.0.1]) by psplinux051.india.ti.com (8.13.1/8.13.1) with ESMTP id nB3A6sFV004908; Thu, 3 Dec 2009 15:36:54 +0530 Received: (from a0875516@localhost) by psplinux051.india.ti.com (8.13.1/8.13.1/Submit) id nB3A6sw3004905; Thu, 3 Dec 2009 15:36:54 +0530 From: Sekhar Nori To: davinci-linux-open-source@linux.davincidsp.com Subject: [PATCH 1/5] davinci: clock framework: remove spinlock usage Date: Thu, 3 Dec 2009 15:36:50 +0530 Message-Id: <1259834814-4817-2-git-send-email-nsekhar@ti.com> X-Mailer: git-send-email 1.6.2.4 In-Reply-To: <1259834814-4817-1-git-send-email-nsekhar@ti.com> References: <1259834814-4817-1-git-send-email-nsekhar@ti.com> X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: davinci-linux-open-source-bounces@linux.davincidsp.com Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 542bfdb..6ff3411 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -722,9 +722,9 @@ static __init void davinci_dm646x_evm_irq_init(void) void __init dm646x_board_setup_refclk(struct clk *clk) { if (machine_is_davinci_dm6467tevm()) - clk->rate = DM6467T_EVM_REF_FREQ; + atomic_set(&clk->rate, DM6467T_EVM_REF_FREQ); else - clk->rate = DM646X_EVM_REF_FREQ; + atomic_set(&clk->rate, DM646X_EVM_REF_FREQ); } MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM") diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index baece65..df884c8 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -28,7 +28,6 @@ static LIST_HEAD(clocks); static DEFINE_MUTEX(clocks_mutex); -static DEFINE_SPINLOCK(clockfw_lock); static unsigned psc_domain(struct clk *clk) { @@ -41,15 +40,16 @@ static void __clk_enable(struct clk *clk) { if (clk->parent) __clk_enable(clk->parent); - if (clk->usecount++ == 0 && (clk->flags & CLK_PSC)) + if (atomic_read(&clk->usecount) == 0 && (clk->flags & CLK_PSC)) davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 1); + atomic_inc(&clk->usecount); } static void __clk_disable(struct clk *clk) { - if (WARN_ON(clk->usecount == 0)) + if (WARN_ON(atomic_read(&clk->usecount) == 0)) return; - if (--clk->usecount == 0 && !(clk->flags & CLK_PLL)) + if (atomic_dec_and_test(&clk->usecount) && !(clk->flags & CLK_PLL)) davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0); if (clk->parent) __clk_disable(clk->parent); @@ -57,14 +57,10 @@ static void __clk_disable(struct clk *clk) int clk_enable(struct clk *clk) { - unsigned long flags; - if (clk == NULL || IS_ERR(clk)) return -EINVAL; - spin_lock_irqsave(&clockfw_lock, flags); __clk_enable(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); return 0; } @@ -72,14 +68,10 @@ EXPORT_SYMBOL(clk_enable); void clk_disable(struct clk *clk) { - unsigned long flags; - if (clk == NULL || IS_ERR(clk)) return; - spin_lock_irqsave(&clockfw_lock, flags); __clk_disable(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); } EXPORT_SYMBOL(clk_disable); @@ -88,7 +80,7 @@ unsigned long clk_get_rate(struct clk *clk) if (clk == NULL || IS_ERR(clk)) return -EINVAL; - return clk->rate; + return atomic_read(&clk->rate); } EXPORT_SYMBOL(clk_get_rate); @@ -100,7 +92,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate) if (clk->round_rate) return clk->round_rate(clk, rate); - return clk->rate; + return atomic_read(&clk->rate); } EXPORT_SYMBOL(clk_round_rate); @@ -111,28 +103,27 @@ static void propagate_rate(struct clk *root) list_for_each_entry(clk, &root->children, childnode) { if (clk->recalc) - clk->rate = clk->recalc(clk); + atomic_set(&clk->rate, clk->recalc(clk)); propagate_rate(clk); } } int clk_set_rate(struct clk *clk, unsigned long rate) { - unsigned long flags; int ret = -EINVAL; if (clk == NULL || IS_ERR(clk)) return ret; - spin_lock_irqsave(&clockfw_lock, flags); if (clk->set_rate) ret = clk->set_rate(clk, rate); if (ret == 0) { if (clk->recalc) - clk->rate = clk->recalc(clk); + atomic_set(&clk->rate, clk->recalc(clk)); + mutex_lock(&clocks_mutex); propagate_rate(clk); + mutex_unlock(&clocks_mutex); } - spin_unlock_irqrestore(&clockfw_lock, flags); return ret; } @@ -140,26 +131,22 @@ EXPORT_SYMBOL(clk_set_rate); int clk_set_parent(struct clk *clk, struct clk *parent) { - unsigned long flags; - if (clk == NULL || IS_ERR(clk)) return -EINVAL; /* Cannot change parent on enabled clock */ - if (WARN_ON(clk->usecount)) + if (WARN_ON(atomic_read(&clk->usecount))) return -EINVAL; mutex_lock(&clocks_mutex); clk->parent = parent; list_del_init(&clk->childnode); list_add(&clk->childnode, &clk->parent->children); - mutex_unlock(&clocks_mutex); - spin_lock_irqsave(&clockfw_lock, flags); if (clk->recalc) - clk->rate = clk->recalc(clk); + atomic_set(&clk->rate, clk->recalc(clk)); propagate_rate(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); + mutex_unlock(&clocks_mutex); return 0; } @@ -170,7 +157,7 @@ int clk_register(struct clk *clk) if (clk == NULL || IS_ERR(clk)) return -EINVAL; - if (WARN(clk->parent && !clk->parent->rate, + if (WARN(clk->parent && !atomic_read(&clk->parent->rate), "CLK: %s parent %s has no rate!\n", clk->name, clk->parent->name)) return -EINVAL; @@ -184,16 +171,16 @@ int clk_register(struct clk *clk) mutex_unlock(&clocks_mutex); /* If rate is already set, use it */ - if (clk->rate) + if (atomic_read(&clk->rate)) return 0; /* Else, see if there is a way to calculate it */ if (clk->recalc) - clk->rate = clk->recalc(clk); + atomic_set(&clk->rate, clk->recalc(clk)); /* Otherwise, default to parent rate */ else if (clk->parent) - clk->rate = clk->parent->rate; + atomic_set(&clk->rate, atomic_read(&clk->parent->rate)); return 0; } @@ -219,9 +206,9 @@ static int __init clk_disable_unused(void) { struct clk *ck; - spin_lock_irq(&clockfw_lock); + mutex_lock(&clocks_mutex); list_for_each_entry(ck, &clocks, node) { - if (ck->usecount > 0) + if (atomic_read(&ck->usecount) > 0) continue; if (!(ck->flags & CLK_PSC)) continue; @@ -233,7 +220,7 @@ static int __init clk_disable_unused(void) pr_info("Clocks: disable unused %s\n", ck->name); davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, 0); } - spin_unlock_irq(&clockfw_lock); + mutex_unlock(&clocks_mutex); return 0; } @@ -244,7 +231,7 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) { u32 v, plldiv; struct pll_data *pll; - unsigned long rate = clk->rate; + unsigned long rate = atomic_read(&clk->rate); /* If this is the PLL base clock, no more calculations needed */ if (clk->pll_data) @@ -253,7 +240,7 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) if (WARN_ON(!clk->parent)) return rate; - rate = clk->parent->rate; + rate = atomic_read(&clk->parent->rate); /* Otherwise, the parent must be a PLL */ if (WARN_ON(!clk->parent->pll_data)) @@ -281,9 +268,9 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) static unsigned long clk_leafclk_recalc(struct clk *clk) { if (WARN_ON(!clk->parent)) - return clk->rate; + return atomic_read(&clk->rate); - return clk->parent->rate; + return atomic_read(&clk->parent->rate); } static unsigned long clk_pllclk_recalc(struct clk *clk) @@ -291,11 +278,11 @@ static unsigned long clk_pllclk_recalc(struct clk *clk) u32 ctrl, mult = 1, prediv = 1, postdiv = 1; u8 bypass; struct pll_data *pll = clk->pll_data; - unsigned long rate = clk->rate; + unsigned long rate = atomic_read(&clk->rate); pll->base = IO_ADDRESS(pll->phys_base); ctrl = __raw_readl(pll->base + PLLCTL); - rate = pll->input_rate = clk->parent->rate; + rate = pll->input_rate = atomic_read(&clk->parent->rate); if (ctrl & PLLCTL_PLLEN) { bypass = 0; @@ -333,8 +320,8 @@ static unsigned long clk_pllclk_recalc(struct clk *clk) rate /= postdiv; } - pr_debug("PLL%d: input = %lu MHz [ ", - pll->num, clk->parent->rate / 1000000); + pr_debug("PLL%d: input = %u MHz [ ", + pll->num, atomic_read(&clk->parent->rate) / 1000000); if (bypass) pr_debug("bypass "); if (prediv > 1) @@ -452,7 +439,7 @@ int __init davinci_clk_init(struct davinci_clk *clocks) } if (clk->recalc) - clk->rate = clk->recalc(clk); + atomic_set(&clk->rate, clk->recalc(clk)); if (clk->lpsc) clk->flags |= CLK_PSC; @@ -514,7 +501,8 @@ dump_clock(struct seq_file *s, unsigned nest, struct clk *parent) min(i, (unsigned)(sizeof(buf) - 1 - nest))); seq_printf(s, "%s users=%2d %-3s %9ld Hz\n", - buf, parent->usecount, state, clk_get_rate(parent)); + buf, atomic_read(&parent->usecount), state, + clk_get_rate(parent)); /* REVISIT show device associations too */ /* cost is now small, but not linear... */ diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index c92d77a..796a568 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -67,8 +67,8 @@ struct clk { struct list_head node; struct module *owner; const char *name; - unsigned long rate; - u8 usecount; + atomic_t rate; + atomic_t usecount; u8 lpsc; u8 gpsc; u32 flags; diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index b22b5cf..d1961d2 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -43,7 +43,7 @@ static struct pll_data pll0_data = { static struct clk ref_clk = { .name = "ref_clk", - .rate = DA830_REF_FREQ, + .rate = ATOMIC_INIT(DA830_REF_FREQ), }; static struct clk pll0_clk = { diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 717806c..62f8c22 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -54,7 +54,7 @@ static struct pll_data pll0_data = { static struct clk ref_clk = { .name = "ref_clk", - .rate = DA850_REF_FREQ, + .rate = ATOMIC_INIT(DA850_REF_FREQ), }; static struct clk pll0_clk = { @@ -1024,7 +1024,7 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long armrate) static int da850_round_armrate(struct clk *clk, unsigned long rate) { - return clk->rate; + return atomic_read(&clk->rate); } #endif diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index dedf4d4..2244e8c 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -55,7 +55,7 @@ static struct pll_data pll2_data = { static struct clk ref_clk = { .name = "ref_clk", /* FIXME -- crystal rate is board-specific */ - .rate = DM355_REF_FREQ, + .rate = ATOMIC_INIT(DM355_REF_FREQ), }; static struct clk pll1_clk = { @@ -314,7 +314,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, /* REVISIT: why cant' this be disabled? */ + .usecount = ATOMIC_INIT(1), /* REVISIT: why cant' this be disabled? */ }; static struct clk timer3_clk = { diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 2ec619e..cc3bae4 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -52,7 +52,7 @@ static struct pll_data pll2_data = { static struct clk ref_clk = { .name = "ref_clk", - .rate = DM365_REF_FREQ, + .rate = ATOMIC_INIT(DM365_REF_FREQ), }; static struct clk pll1_clk = { @@ -358,7 +358,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, + .usecount = ATOMIC_INIT(1), }; static struct clk timer3_clk = { diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 2cd0081..e65e29e 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -47,7 +47,7 @@ static struct pll_data pll2_data = { static struct clk ref_clk = { .name = "ref_clk", - .rate = DM644X_REF_FREQ, + .rate = ATOMIC_INIT(DM644X_REF_FREQ), }; static struct clk pll1_clk = { @@ -131,7 +131,7 @@ static struct clk dsp_clk = { .parent = &pll1_sysclk1, .lpsc = DAVINCI_LPSC_GEM, .flags = PSC_DSP, - .usecount = 1, /* REVISIT how to disable? */ + .usecount = ATOMIC_INIT(1), /* REVISIT how to disable? */ }; static struct clk arm_clk = { @@ -146,7 +146,7 @@ static struct clk vicp_clk = { .parent = &pll1_sysclk2, .lpsc = DAVINCI_LPSC_IMCOP, .flags = PSC_DSP, - .usecount = 1, /* REVISIT how to disable? */ + .usecount = ATOMIC_INIT(1), /* REVISIT how to disable? */ }; static struct clk vpss_master_clk = { @@ -274,7 +274,7 @@ static struct clk timer2_clk = { .name = "timer2", .parent = &pll1_aux_clk, .lpsc = DAVINCI_LPSC_TIMER2, - .usecount = 1, /* REVISIT: why cant' this be disabled? */ + .usecount = ATOMIC_INIT(1), /* REVISIT: why cant' this be disabled? */ }; struct davinci_clk dm644x_clks[] = { diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 515d3ed..6f80616 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -60,7 +60,7 @@ static struct clk ref_clk = { static struct clk aux_clkin = { .name = "aux_clkin", - .rate = DM646X_AUX_FREQ, + .rate = ATOMIC_INIT(DM646X_AUX_FREQ), }; static struct clk pll1_clk = { @@ -158,7 +158,7 @@ static struct clk dsp_clk = { .parent = &pll1_sysclk1, .lpsc = DM646X_LPSC_C64X_CPU, .flags = PSC_DSP, - .usecount = 1, /* REVISIT how to disable? */ + .usecount = ATOMIC_INIT(1), /* REVISIT how to disable? */ }; static struct clk arm_clk = { @@ -262,14 +262,14 @@ static struct clk pwm0_clk = { .name = "pwm0", .parent = &pll1_sysclk3, .lpsc = DM646X_LPSC_PWM0, - .usecount = 1, /* REVIST: disabling hangs system */ + .usecount = ATOMIC_INIT(1), /* REVIST: disabling hangs system */ }; static struct clk pwm1_clk = { .name = "pwm1", .parent = &pll1_sysclk3, .lpsc = DM646X_LPSC_PWM1, - .usecount = 1, /* REVIST: disabling hangs system */ + .usecount = ATOMIC_INIT(1), /* REVIST: disabling hangs system */ }; static struct clk timer0_clk = { diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index 04a3cb7..a9a4d08 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -64,6 +65,9 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, void __iomem *psc_base; struct davinci_soc_info *soc_info = &davinci_soc_info; u32 next_state = enable ? 0x3 : 0x2; /* 0x3 enables, 0x2 disables */ + /* Protect against simultaneous enable/disable of PSCs */ + DEFINE_SPINLOCK(lock); + unsigned long flags; if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { pr_warning("PSC: Bad psc data: 0x%x[%d]\n", @@ -73,6 +77,7 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, psc_base = soc_info->psc_bases[ctlr]; + spin_lock_irqsave(&lock, flags); mdctl = __raw_readl(psc_base + MDCTL + 4 * id); mdctl &= ~MDSTAT_STATE_MASK; mdctl |= next_state; @@ -111,4 +116,5 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, do { mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); } while (!((mdstat & MDSTAT_STATE_MASK) == next_state)); + spin_unlock_irqrestore(&lock, flags); }