From patchwork Fri May 27 02:39:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nishanth Menon X-Patchwork-Id: 822542 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p4R2dU7A014915 for ; Fri, 27 May 2011 02:39:44 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758667Ab1E0Cjn (ORCPT ); Thu, 26 May 2011 22:39:43 -0400 Received: from na3sys009aog112.obsmtp.com ([74.125.149.207]:53811 "EHLO na3sys009aog112.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753349Ab1E0Cjn (ORCPT ); Thu, 26 May 2011 22:39:43 -0400 Received: from mail-yi0-f52.google.com ([209.85.218.52]) (using TLSv1) by na3sys009aob112.postini.com ([74.125.148.12]) with SMTP ID DSNKTd8O7gawGYS0lsLMOUyuABbh6Ue6yjck@postini.com; Thu, 26 May 2011 19:39:43 PDT Received: by mail-yi0-f52.google.com with SMTP id 10so758232yih.25 for ; Thu, 26 May 2011 19:39:42 -0700 (PDT) Received: by 10.236.184.41 with SMTP id r29mr2328109yhm.0.1306463982410; Thu, 26 May 2011 19:39:42 -0700 (PDT) Received: from localhost (dragon.ti.com [192.94.94.33]) by mx.google.com with ESMTPS id i46sm111470yhk.6.2011.05.26.19.39.40 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 26 May 2011 19:39:41 -0700 (PDT) From: Nishanth Menon To: linux-omap Cc: Kevin , Nishanth Menon Subject: [PM-WIP_CPUFREQ][PATCH v4 4/4] OMAP2+: cpufreq: fix freq_table leak Date: Thu, 26 May 2011 19:39:20 -0700 Message-Id: <1306463960-27340-5-git-send-email-nm@ti.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1306463960-27340-1-git-send-email-nm@ti.com> References: <1306463960-27340-1-git-send-email-nm@ti.com> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 27 May 2011 02:39:44 +0000 (UTC) We use a single frequency table for multiple CPUs. But, with OMAP4, since we have multiple CPUs, the cpu_init call for CPU1 causes freq_table previously allocated for CPU0 to be overwritten. In addition, we dont free the table on exit path. We solve this by maintaining an atomic type counter to ensure just a single table exists at a given time. Signed-off-by: Nishanth Menon --- NOTE: Depends on: http://marc.info/?t=130630947000002&r=1&w=2 arch/arm/mach-omap2/omap2plus-cpufreq.c | 16 ++++++++++++++-- 1 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c index 40b2a7c..e101737 100644 --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c @@ -39,6 +39,7 @@ #include static struct cpufreq_frequency_table *freq_table; +static atomic_t freq_table_users = ATOMIC_INIT(0); static struct clk *mpu_clk; static char *mpu_clk_name; static struct device *mpu_dev; @@ -153,6 +154,12 @@ skip_lpj: return ret; } +static inline void freq_table_free(void) +{ + if (atomic_dec_and_test(&freq_table_users)) + opp_free_cpufreq_table(mpu_dev, &freq_table); +} + static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) { int result = 0; @@ -168,7 +175,9 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) } policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu); - result = opp_init_cpufreq_table(mpu_dev, &freq_table); + + if (atomic_inc_return(&freq_table_users) == 1) + result = opp_init_cpufreq_table(mpu_dev, &freq_table); if (result) { dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n", @@ -180,7 +189,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) if (!result) cpufreq_frequency_table_get_attr(freq_table, policy->cpu); else - goto fail_ck; + goto fail_table; policy->min = policy->cpuinfo.min_freq; policy->max = policy->cpuinfo.max_freq; @@ -204,6 +213,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) return 0; +fail_table: + freq_table_free(); fail_ck: clk_put(mpu_clk); return result; @@ -211,6 +222,7 @@ fail_ck: static int omap_cpu_exit(struct cpufreq_policy *policy) { + freq_table_free(); clk_put(mpu_clk); return 0; }