From patchwork Wed Apr 20 09:32:38 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shilpasri G Bhat X-Patchwork-Id: 8887601 Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id F0AD79F1D3 for ; Wed, 20 Apr 2016 09:43:22 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0C3D42024C for ; Wed, 20 Apr 2016 09:43:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F24EE20165 for ; Wed, 20 Apr 2016 09:43:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933297AbcDTJnE (ORCPT ); Wed, 20 Apr 2016 05:43:04 -0400 Received: from e28smtp05.in.ibm.com ([125.16.236.5]:51514 "EHLO e28smtp05.in.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932122AbcDTJnB (ORCPT ); Wed, 20 Apr 2016 05:43:01 -0400 Received: from localhost by e28smtp05.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 20 Apr 2016 15:02:48 +0530 Received: from d28relay03.in.ibm.com (9.184.220.60) by e28smtp05.in.ibm.com (192.168.1.135) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 20 Apr 2016 15:02:47 +0530 X-IBM-Helo: d28relay03.in.ibm.com X-IBM-MailFrom: shilpa.bhat@linux.vnet.ibm.com X-IBM-RcptTo: linux-kernel@vger.kernel.org;linux-pm@vger.kernel.org Received: from d28av05.in.ibm.com (d28av05.in.ibm.com [9.184.220.67]) by d28relay03.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u3K9WkDk51839212; Wed, 20 Apr 2016 15:02:46 +0530 Received: from d28av05.in.ibm.com (localhost [127.0.0.1]) by d28av05.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u3K9Wh3R015922; Wed, 20 Apr 2016 15:02:46 +0530 Received: from localhost.in.ibm.com ([9.77.202.60]) by d28av05.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u3K9WekS015745; Wed, 20 Apr 2016 15:02:40 +0530 From: Shilpasri G Bhat To: rjw@rjwysocki.net, viresh.kumar@linaro.org Cc: linux-pm@vger.kernel.org, linuxppc-dev@ozlabs.org, linux-kernel@vger.kernel.org, Shilpasri G Bhat Subject: [PATCH] cpufreq: powernv: Fixes initialization of chip and chip mask Date: Wed, 20 Apr 2016 15:02:38 +0530 Message-Id: <1461144758-17810-1-git-send-email-shilpa.bhat@linux.vnet.ibm.com> X-Mailer: git-send-email 1.9.3 X-TM-AS-MML: disable x-cbid: 16042009-0017-0000-0000-00001E22EF48 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP commit 735366fc4077 ("cpufreq: powernv: Call throttle_check() on receiving OCC_THROTTLE") used cpumask_of_node() as the chip mask. But this mask contains only online cpus. This breaks a setup where cpufreq is initialized with few offline cores and made online later. So this patch fixes this bug by scanning all the possible cpus and sets the cpu in the chip mask. It also fixes the chip discovery with non-contiguous cpu mask. This patch creates a list of chips 'powernv_chip_list' to replace the chip array for cleaner initialization. Signed-off-by: Shilpasri G Bhat Reviewed-by: Gautham R. Shenoy --- drivers/cpufreq/powernv-cpufreq.c | 80 +++++++++++++++++++++++---------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 39ac78c..0581a59 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -64,7 +64,9 @@ enum throttle_reason_type { OCC_MAX_REASON }; -static struct chip { +static LIST_HEAD(powernv_chip_list); + +struct chip { unsigned int id; bool throttled; bool restore; @@ -74,9 +76,9 @@ static struct chip { int throttle_turbo; int throttle_sub_turbo; int reason[OCC_MAX_REASON]; -} *chips; + struct list_head list; +}; -static int nr_chips; static DEFINE_PER_CPU(struct chip *, chip_info); /* @@ -528,12 +530,22 @@ out: put_online_cpus(); } +static inline struct chip *find_chip(unsigned int id) +{ + struct chip *chip; + + list_for_each_entry(chip, &powernv_chip_list, list) + if (chip->id == id) + return chip; + return NULL; +} + static int powernv_cpufreq_occ_msg(struct notifier_block *nb, unsigned long msg_type, void *_msg) { struct opal_msg *msg = _msg; struct opal_occ_msg omsg; - int i; + struct chip *chip; if (msg_type != OPAL_MSG_OCC) return 0; @@ -569,28 +581,27 @@ static int powernv_cpufreq_occ_msg(struct notifier_block *nb, throttled = false; pr_info("OCC Active, CPU frequency is no longer throttled\n"); - for (i = 0; i < nr_chips; i++) { - chips[i].restore = true; - schedule_work(&chips[i].throttle); + list_for_each_entry(chip, &powernv_chip_list, list) { + chip->restore = true; + schedule_work(&chip->throttle); } return 0; } - for (i = 0; i < nr_chips; i++) - if (chips[i].id == omsg.chip) - break; - + chip = find_chip(omsg.chip); + if (!chip) + return -EINVAL; if (omsg.throttle_status >= 0 && omsg.throttle_status <= OCC_MAX_THROTTLE_STATUS) { - chips[i].throttle_reason = omsg.throttle_status; - chips[i].reason[omsg.throttle_status]++; + chip->throttle_reason = omsg.throttle_status; + chip->reason[omsg.throttle_status]++; } if (!omsg.throttle_status) - chips[i].restore = true; + chip->restore = true; - schedule_work(&chips[i].throttle); + schedule_work(&chip->throttle); } return 0; } @@ -622,37 +633,42 @@ static struct cpufreq_driver powernv_cpufreq_driver = { static int init_chip_info(void) { - unsigned int chip[256]; - unsigned int cpu, i; + unsigned int cpu; unsigned int prev_chip_id = UINT_MAX; + struct chip *chip = NULL; for_each_possible_cpu(cpu) { unsigned int id = cpu_to_chip_id(cpu); if (prev_chip_id != id) { prev_chip_id = id; - chip[nr_chips++] = id; + chip = find_chip(id); } + if (!chip) { + chip = kzalloc(sizeof(struct chip), GFP_KERNEL); + if (!chip) + goto out; + chip->id = id; + INIT_WORK(&chip->throttle, powernv_cpufreq_work_fn); + INIT_LIST_HEAD(&chip->list); + list_add(&chip->list, &powernv_chip_list); + } + cpumask_set_cpu(cpu, &chip->mask); + per_cpu(chip_info, cpu) = chip; } - - chips = kcalloc(nr_chips, sizeof(struct chip), GFP_KERNEL); - if (!chips) - return -ENOMEM; - - for (i = 0; i < nr_chips; i++) { - chips[i].id = chip[i]; - cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i])); - INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn); - for_each_cpu(cpu, &chips[i].mask) - per_cpu(chip_info, cpu) = &chips[i]; - } - return 0; +out: + list_for_each_entry(chip, &powernv_chip_list, list) + kfree(chip); + return -ENOMEM; } static inline void clean_chip_info(void) { - kfree(chips); + struct chip *chip; + + list_for_each_entry(chip, &powernv_chip_list, list) + kfree(chip); } static inline void unregister_all_notifiers(void)