From patchwork Wed Dec 13 06:57:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gautham R Shenoy X-Patchwork-Id: 847806 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yxSrY5FtKz9s74 for ; Wed, 13 Dec 2017 18:25:01 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3yxSrY35vbzDrnJ for ; Wed, 13 Dec 2017 18:25:01 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=ego@linux.vnet.ibm.com; receiver=) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3yxSFQ0rY0zDqC2 for ; Wed, 13 Dec 2017 17:58:01 +1100 (AEDT) Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id vBD6tItS085858 for ; Wed, 13 Dec 2017 01:57:59 -0500 Received: from e16.ny.us.ibm.com (e16.ny.us.ibm.com [129.33.205.206]) by mx0a-001b2d01.pphosted.com with ESMTP id 2etrs7xygn-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Wed, 13 Dec 2017 01:57:59 -0500 Received: from localhost by e16.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 13 Dec 2017 01:57:58 -0500 Received: from b01cxnp22033.gho.pok.ibm.com (9.57.198.23) by e16.ny.us.ibm.com (146.89.104.203) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 13 Dec 2017 01:57:56 -0500 Received: from b01ledav001.gho.pok.ibm.com (b01ledav001.gho.pok.ibm.com [9.57.199.106]) by b01cxnp22033.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id vBD6vtfv36044948; Wed, 13 Dec 2017 06:57:55 GMT Received: from b01ledav001.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6B1C928046; Wed, 13 Dec 2017 01:57:22 -0500 (EST) Received: from sofia.ibm.com (unknown [9.124.35.100]) by b01ledav001.gho.pok.ibm.com (Postfix) with ESMTP id EDDB628041; Wed, 13 Dec 2017 01:57:21 -0500 (EST) Received: by sofia.ibm.com (Postfix, from userid 1000) id E2C852E30D6; Wed, 13 Dec 2017 12:27:52 +0530 (IST) From: "Gautham R. Shenoy" To: Shilpasri G Bhat , viresh.kumar@linaro.org, rjw@rjwysocki.net, huntbag@linux.vnet.ibm.com, akshay.adiga@linux.vnet.ibm.com, Michael Ellerman , Vaidyanathan Srinivasan , Balbir Singh Subject: [v3 PATCH 1/3] powernv-cpufreq: Add helper to extract pstate from PMSR Date: Wed, 13 Dec 2017 12:27:39 +0530 X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1513148261-21097-1-git-send-email-ego@linux.vnet.ibm.com> References: <1513148261-21097-1-git-send-email-ego@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 17121306-0024-0000-0000-000003008E48 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008197; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000244; SDB=6.00959491; UDB=6.00485256; IPR=6.00739513; BA=6.00005740; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00018516; XFM=3.00000015; UTC=2017-12-13 06:57:58 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17121306-0025-0000-0000-0000464D03A8 Message-Id: <1513148261-21097-2-git-send-email-ego@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-12-13_02:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1712130099 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.24 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Gautham R. Shenoy" , linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" From: "Gautham R. Shenoy" On POWERNV platform, the fields for pstates in the Power Management Status Register (PMSR) and the Power Management Control Register (PMCR) are 8-bits wide. On POWER8 the pstates are negatively numbered while on POWER9 they are positively numbered. The device-tree exports pstates as 32-bit entries. The device-tree implementation sign-extends the 8-bit pstate values to obtain the corresponding 32-bit entry. Eg: On POWER8, a pstate value 0x82 [-126] is represented in the device-tree as 0xfffffff82 while on POWER9, the same value 0x82 [130] is represented in the device-tree as 0x00000082. The powernv-cpufreq driver implementation represents pstates using the integer type. In multiple places in the driver, the code interprets the pstates extracted from the PMSR as a signed byte and assigns it to a integer variable to get the sign-extention. On POWER9 platforms which have greater than 128 pstates, this results in the driver performing incorrect sign-extention, and thereby treating a legitimate pstate (say 130) as an invalid pstates (since it is interpreted as -126). This patch fixes the issue by implementing a helper function to extract Pstates from PMSR register, and correctly sign-extend it to be consistent with the values provided by the device-tree. Signed-off-by: Gautham R. Shenoy Acked-by: Balbir Singh --- drivers/cpufreq/powernv-cpufreq.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index b6d7c4c..f46b60f 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -41,11 +41,9 @@ #define POWERNV_MAX_PSTATES 256 #define PMSR_PSAFE_ENABLE (1UL << 30) #define PMSR_SPR_EM_DISABLE (1UL << 31) -#define PMSR_MAX(x) ((x >> 32) & 0xFF) +#define MAX_PSTATE_SHIFT 32 #define LPSTATE_SHIFT 48 #define GPSTATE_SHIFT 56 -#define GET_LPSTATE(x) (((x) >> LPSTATE_SHIFT) & 0xFF) -#define GET_GPSTATE(x) (((x) >> GPSTATE_SHIFT) & 0xFF) #define MAX_RAMP_DOWN_TIME 5120 /* @@ -94,6 +92,7 @@ struct global_pstate_info { }; static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; +u32 pstate_sign_prefix; static bool rebooting, throttled, occ_reset; static const char * const throttle_reason[] = { @@ -148,6 +147,20 @@ enum throttle_reason_type { bool wof_enabled; } powernv_pstate_info; +static inline int extract_pstate(u64 pmsr_val, unsigned int shift) +{ + int ret = ((pmsr_val >> shift) & 0xFF); + + if (!ret) + return ret; + + return (pstate_sign_prefix | ret); +} + +#define extract_local_pstate(x) extract_pstate(x, LPSTATE_SHIFT) +#define extract_global_pstate(x) extract_pstate(x, GPSTATE_SHIFT) +#define extract_max_pstate(x) extract_pstate(x, MAX_PSTATE_SHIFT) + /* Use following macros for conversions between pstate_id and index */ static inline int idx_to_pstate(unsigned int i) { @@ -278,6 +291,9 @@ static int init_powernv_pstates(void) powernv_pstate_info.nr_pstates = nr_pstates; pr_debug("NR PStates %d\n", nr_pstates); + + pstate_sign_prefix = pstate_min & ~0xFF; + for (i = 0; i < nr_pstates; i++) { u32 id = be32_to_cpu(pstate_ids[i]); u32 freq = be32_to_cpu(pstate_freqs[i]); @@ -438,17 +454,10 @@ struct powernv_smp_call_data { static void powernv_read_cpu_freq(void *arg) { unsigned long pmspr_val; - s8 local_pstate_id; struct powernv_smp_call_data *freq_data = arg; pmspr_val = get_pmspr(SPRN_PMSR); - - /* - * The local pstate id corresponds bits 48..55 in the PMSR. - * Note: Watch out for the sign! - */ - local_pstate_id = (pmspr_val >> 48) & 0xFF; - freq_data->pstate_id = local_pstate_id; + freq_data->pstate_id = extract_local_pstate(pmspr_val); freq_data->freq = pstate_id_to_freq(freq_data->pstate_id); pr_debug("cpu %d pmsr %016lX pstate_id %d frequency %d kHz\n", @@ -522,7 +531,7 @@ static void powernv_cpufreq_throttle_check(void *data) chip = this_cpu_read(chip_info); /* Check for Pmax Capping */ - pmsr_pmax = (s8)PMSR_MAX(pmsr); + pmsr_pmax = extract_max_pstate(pmsr); pmsr_pmax_idx = pstate_to_idx(pmsr_pmax); if (pmsr_pmax_idx != powernv_pstate_info.max) { if (chip->throttled) @@ -645,8 +654,8 @@ void gpstate_timer_handler(struct timer_list *t) * value. Hence, read from PMCR to get correct data. */ val = get_pmspr(SPRN_PMCR); - freq_data.gpstate_id = (s8)GET_GPSTATE(val); - freq_data.pstate_id = (s8)GET_LPSTATE(val); + freq_data.gpstate_id = extract_global_pstate(val); + freq_data.pstate_id = extract_local_pstate(val); if (freq_data.gpstate_id == freq_data.pstate_id) { reset_gpstates(policy); spin_unlock(&gpstates->gpstate_lock); From patchwork Wed Dec 13 06:57:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gautham R Shenoy X-Patchwork-Id: 847802 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yxSnS6L22z9s74 for ; Wed, 13 Dec 2017 18:22:20 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3yxSnS3PmhzDqXs for ; Wed, 13 Dec 2017 18:22:20 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=ego@linux.vnet.ibm.com; receiver=) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3yxSFR0BxQzDrS0 for ; Wed, 13 Dec 2017 17:58:02 +1100 (AEDT) Received: from pps.filterd (m0098393.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id vBD6tIJt063938 for ; Wed, 13 Dec 2017 01:58:00 -0500 Received: from e18.ny.us.ibm.com (e18.ny.us.ibm.com [129.33.205.208]) by mx0a-001b2d01.pphosted.com with ESMTP id 2etrs9exx0-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Wed, 13 Dec 2017 01:58:00 -0500 Received: from localhost by e18.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 13 Dec 2017 01:57:59 -0500 Received: from b01cxnp23034.gho.pok.ibm.com (9.57.198.29) by e18.ny.us.ibm.com (146.89.104.205) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 13 Dec 2017 01:57:56 -0500 Received: from b01ledav001.gho.pok.ibm.com (b01ledav001.gho.pok.ibm.com [9.57.199.106]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id vBD6vt3246792868; Wed, 13 Dec 2017 06:57:55 GMT Received: from b01ledav001.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7340F28048; Wed, 13 Dec 2017 01:57:22 -0500 (EST) Received: from sofia.ibm.com (unknown [9.124.35.100]) by b01ledav001.gho.pok.ibm.com (Postfix) with ESMTP id 019882803E; Wed, 13 Dec 2017 01:57:22 -0500 (EST) Received: by sofia.ibm.com (Postfix, from userid 1000) id EC19A2E310F; Wed, 13 Dec 2017 12:27:52 +0530 (IST) From: "Gautham R. Shenoy" To: Shilpasri G Bhat , viresh.kumar@linaro.org, rjw@rjwysocki.net, huntbag@linux.vnet.ibm.com, akshay.adiga@linux.vnet.ibm.com, Michael Ellerman , Vaidyanathan Srinivasan , Balbir Singh Subject: [v3 PATCH 2/3] powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous pstates Date: Wed, 13 Dec 2017 12:27:40 +0530 X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1513148261-21097-1-git-send-email-ego@linux.vnet.ibm.com> References: <1513148261-21097-1-git-send-email-ego@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 17121306-0044-0000-0000-000003BD8D96 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008197; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000244; SDB=6.00959492; UDB=6.00485256; IPR=6.00739513; BA=6.00005740; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00018516; XFM=3.00000015; UTC=2017-12-13 06:57:58 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17121306-0045-0000-0000-000007ECCE54 Message-Id: <1513148261-21097-3-git-send-email-ego@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-12-13_02:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1712130099 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.24 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Gautham R. Shenoy" , linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" From: "Gautham R. Shenoy" The code in powernv-cpufreq, makes the following two assumptions which are not guaranteed by the device-tree bindings: 1) Pstate ids are continguous: This is used in pstate_to_idx() to obtain the reverse map from a pstate to it's corresponding entry into the cpufreq frequency table. 2) Every Pstate should always lie between the max and the min pstates that are explicitly reported in the device tree: This is used to determine whether a pstate reported by the PMSR is out of bounds. Both these assumptions are unwarranted and can change on future platforms. In this patch, we maintain the reverse map from a pstate to it's index in the cpufreq frequency table and use this in pstate_to_idx(). This does away with the assumptions (1) mentioned above, and will work with non continguous pstate ids. If no entry exists for a particular pstate, then such a pstate is treated as being out of bounds. This gets rid of assumption (2). On all the existing platforms, where the pstates are 8-bit long values, the new implementation of pstate_to_idx() takes constant time. Signed-off-by: Gautham R. Shenoy --- drivers/cpufreq/powernv-cpufreq.c | 85 +++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index f46b60f..8e3dbca 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,8 @@ #include #include -#define POWERNV_MAX_PSTATES 256 +#define POWERNV_MAX_PSTATES_ORDER 8 +#define POWERNV_MAX_PSTATES (1UL << (POWERNV_MAX_PSTATES_ORDER)) #define PMSR_PSAFE_ENABLE (1UL << 30) #define PMSR_SPR_EM_DISABLE (1UL << 31) #define MAX_PSTATE_SHIFT 32 @@ -92,6 +94,27 @@ struct global_pstate_info { }; static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1]; + +DEFINE_HASHTABLE(pstate_revmap, POWERNV_MAX_PSTATES_ORDER); +/** + * struct pstate_idx_revmap_data: Entry in the hashmap pstate_revmap + * indexed by a function of pstate id. + * + * @pstate_id: pstate id for this entry. + * + * @cpufreq_table_idx: Index into the powernv_freqs + * cpufreq_frequency_table for frequency + * corresponding to pstate_id. + * + * @hentry: hlist_node that hooks this entry into the pstate_revmap + * hashtable + */ +struct pstate_idx_revmap_data { + int pstate_id; + unsigned int cpufreq_table_idx; + struct hlist_node hentry; +}; + u32 pstate_sign_prefix; static bool rebooting, throttled, occ_reset; @@ -161,39 +184,47 @@ static inline int extract_pstate(u64 pmsr_val, unsigned int shift) #define extract_global_pstate(x) extract_pstate(x, GPSTATE_SHIFT) #define extract_max_pstate(x) extract_pstate(x, MAX_PSTATE_SHIFT) -/* Use following macros for conversions between pstate_id and index */ +/* Use following functions for conversions between pstate_id and index */ + +/** + * idx_to_pstate : Returns the pstate id corresponding to the + * frequency in the cpufreq frequency table + * powernv_freqs indexed by @i. + * + * If @i is out of bound, this will return the pstate + * corresponding to the nominal frequency. + */ static inline int idx_to_pstate(unsigned int i) { if (unlikely(i >= powernv_pstate_info.nr_pstates)) { - pr_warn_once("index %u is out of bound\n", i); + pr_warn_once("idx_to_pstate: index %u is out of bound\n", i); return powernv_freqs[powernv_pstate_info.nominal].driver_data; } return powernv_freqs[i].driver_data; } -static inline unsigned int pstate_to_idx(int pstate) +/** + * pstate_to_idx : Returns the index in the cpufreq frequencytable + * powernv_freqs for the frequency whose corresponding + * pstate id is @pstate. + * + * If no frequency corresponding to @pstate is found, + * this will return the index of the nominal + * frequency. + */ +static unsigned int pstate_to_idx(int pstate) { - int min = powernv_freqs[powernv_pstate_info.min].driver_data; - int max = powernv_freqs[powernv_pstate_info.max].driver_data; + unsigned int key = pstate % POWERNV_MAX_PSTATES; + struct pstate_idx_revmap_data *revmap_data; - if (min > 0) { - if (unlikely((pstate < max) || (pstate > min))) { - pr_warn_once("pstate %d is out of bound\n", pstate); - return powernv_pstate_info.nominal; - } - } else { - if (unlikely((pstate > max) || (pstate < min))) { - pr_warn_once("pstate %d is out of bound\n", pstate); - return powernv_pstate_info.nominal; - } + hash_for_each_possible(pstate_revmap, revmap_data, hentry, key) { + if (revmap_data->pstate_id == pstate) + return revmap_data->cpufreq_table_idx; } - /* - * abs() is deliberately used so that is works with - * both monotonically increasing and decreasing - * pstate values - */ - return abs(pstate - idx_to_pstate(powernv_pstate_info.max)); + + pr_warn_once("pstate_to_idx: pstate %d not found\n", pstate); + return powernv_pstate_info.nominal; } static inline void reset_gpstates(struct cpufreq_policy *policy) @@ -297,11 +328,21 @@ static int init_powernv_pstates(void) for (i = 0; i < nr_pstates; i++) { u32 id = be32_to_cpu(pstate_ids[i]); u32 freq = be32_to_cpu(pstate_freqs[i]); + struct pstate_idx_revmap_data *revmap_data; + unsigned int key; pr_debug("PState id %d freq %d MHz\n", id, freq); powernv_freqs[i].frequency = freq * 1000; /* kHz */ powernv_freqs[i].driver_data = id; + revmap_data = (struct pstate_idx_revmap_data *) + kmalloc(sizeof(*revmap_data), GFP_KERNEL); + + revmap_data->pstate_id = id; + revmap_data->cpufreq_table_idx = i; + key = id % POWERNV_MAX_PSTATES; + hash_add(pstate_revmap, &revmap_data->hentry, key); + if (id == pstate_max) powernv_pstate_info.max = i; else if (id == pstate_nominal) From patchwork Wed Dec 13 06:57:41 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gautham R Shenoy X-Patchwork-Id: 847796 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yxShp4ZJFz9s74 for ; Wed, 13 Dec 2017 18:18:18 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3yxShp324rzDrVC for ; Wed, 13 Dec 2017 18:18:18 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=linux.vnet.ibm.com (client-ip=148.163.158.5; helo=mx0a-001b2d01.pphosted.com; envelope-from=ego@linux.vnet.ibm.com; receiver=) Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3yxSFP16lDzDrX8 for ; Wed, 13 Dec 2017 17:58:00 +1100 (AEDT) Received: from pps.filterd (m0098419.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id vBD6tXti011309 for ; Wed, 13 Dec 2017 01:57:58 -0500 Received: from e32.co.us.ibm.com (e32.co.us.ibm.com [32.97.110.150]) by mx0b-001b2d01.pphosted.com with ESMTP id 2etxmbj5vx-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Wed, 13 Dec 2017 01:57:58 -0500 Received: from localhost by e32.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 12 Dec 2017 23:57:57 -0700 Received: from b03cxnp08028.gho.boulder.ibm.com (9.17.130.20) by e32.co.us.ibm.com (192.168.1.132) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 12 Dec 2017 23:57:55 -0700 Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp08028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id vBD6vtNZ65798328; Tue, 12 Dec 2017 23:57:55 -0700 Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 27A1BC6043; Tue, 12 Dec 2017 23:57:55 -0700 (MST) Received: from sofia.ibm.com (unknown [9.124.35.100]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTP id D4DE6C603C; Tue, 12 Dec 2017 23:57:54 -0700 (MST) Received: by sofia.ibm.com (Postfix, from userid 1000) id 01E762E3110; Wed, 13 Dec 2017 12:27:52 +0530 (IST) From: "Gautham R. Shenoy" To: Shilpasri G Bhat , viresh.kumar@linaro.org, rjw@rjwysocki.net, huntbag@linux.vnet.ibm.com, akshay.adiga@linux.vnet.ibm.com, Michael Ellerman , Vaidyanathan Srinivasan , Balbir Singh Subject: [v3 PATCH 3/3] powernv-cpufreq: Treat pstates as opaque 8-bit values Date: Wed, 13 Dec 2017 12:27:41 +0530 X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1513148261-21097-1-git-send-email-ego@linux.vnet.ibm.com> References: <1513148261-21097-1-git-send-email-ego@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 17121306-0004-0000-0000-0000135F3859 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008197; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000244; SDB=6.00959491; UDB=6.00485256; IPR=6.00739513; BA=6.00005740; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00018516; XFM=3.00000015; UTC=2017-12-13 06:57:57 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17121306-0005-0000-0000-0000853F3AE9 Message-Id: <1513148261-21097-4-git-send-email-ego@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-12-13_02:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1011 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1712130099 X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.24 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Gautham R. Shenoy" , linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" From: "Gautham R. Shenoy" On POWER8 and POWER9, the PMSR and the PMCR registers define pstates to be 8-bit wide values. The device-tree exports pstates as 32-bit wide values of which the lower byte is the actual pstate. The current implementation in the kernel treats pstates as integer type, since it used to use the sign of the pstate for performing some boundary-checks. This is no longer required after the patch "powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous pstates". So, in this patch, we modify the powernv-cpufreq driver to uniformly treat pstates as opaque 8-bit values obtained from the device-tree or the PMCR. This simplifies the extract_pstate() helper function since we no longer no longer require to worry about the sign-extentions. Signed-off-by: Gautham R. Shenoy --- drivers/cpufreq/powernv-cpufreq.c | 47 ++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 8e3dbca..8a4e2ce 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c @@ -110,12 +110,11 @@ struct global_pstate_info { * hashtable */ struct pstate_idx_revmap_data { - int pstate_id; + u8 pstate_id; unsigned int cpufreq_table_idx; struct hlist_node hentry; }; -u32 pstate_sign_prefix; static bool rebooting, throttled, occ_reset; static const char * const throttle_reason[] = { @@ -170,14 +169,9 @@ enum throttle_reason_type { bool wof_enabled; } powernv_pstate_info; -static inline int extract_pstate(u64 pmsr_val, unsigned int shift) +static inline u8 extract_pstate(u64 pmsr_val, unsigned int shift) { - int ret = ((pmsr_val >> shift) & 0xFF); - - if (!ret) - return ret; - - return (pstate_sign_prefix | ret); + return ((pmsr_val >> shift) & 0xFF); } #define extract_local_pstate(x) extract_pstate(x, LPSTATE_SHIFT) @@ -194,7 +188,7 @@ static inline int extract_pstate(u64 pmsr_val, unsigned int shift) * If @i is out of bound, this will return the pstate * corresponding to the nominal frequency. */ -static inline int idx_to_pstate(unsigned int i) +static inline u8 idx_to_pstate(unsigned int i) { if (unlikely(i >= powernv_pstate_info.nr_pstates)) { pr_warn_once("idx_to_pstate: index %u is out of bound\n", i); @@ -213,7 +207,7 @@ static inline int idx_to_pstate(unsigned int i) * this will return the index of the nominal * frequency. */ -static unsigned int pstate_to_idx(int pstate) +static unsigned int pstate_to_idx(u8 pstate) { unsigned int key = pstate % POWERNV_MAX_PSTATES; struct pstate_idx_revmap_data *revmap_data; @@ -223,7 +217,7 @@ static unsigned int pstate_to_idx(int pstate) return revmap_data->cpufreq_table_idx; } - pr_warn_once("pstate_to_idx: pstate %d not found\n", pstate); + pr_warn_once("pstate_to_idx: pstate 0x%x not found\n", pstate); return powernv_pstate_info.nominal; } @@ -291,7 +285,7 @@ static int init_powernv_pstates(void) powernv_pstate_info.wof_enabled = true; next: - pr_info("cpufreq pstate min %d nominal %d max %d\n", pstate_min, + pr_info("cpufreq pstate min 0x%x nominal 0x%x max 0x%x\n", pstate_min, pstate_nominal, pstate_max); pr_info("Workload Optimized Frequency is %s in the platform\n", (powernv_pstate_info.wof_enabled) ? "enabled" : "disabled"); @@ -323,8 +317,6 @@ static int init_powernv_pstates(void) powernv_pstate_info.nr_pstates = nr_pstates; pr_debug("NR PStates %d\n", nr_pstates); - pstate_sign_prefix = pstate_min & ~0xFF; - for (i = 0; i < nr_pstates; i++) { u32 id = be32_to_cpu(pstate_ids[i]); u32 freq = be32_to_cpu(pstate_freqs[i]); @@ -333,14 +325,14 @@ static int init_powernv_pstates(void) pr_debug("PState id %d freq %d MHz\n", id, freq); powernv_freqs[i].frequency = freq * 1000; /* kHz */ - powernv_freqs[i].driver_data = id; + powernv_freqs[i].driver_data = id & 0xFF; revmap_data = (struct pstate_idx_revmap_data *) kmalloc(sizeof(*revmap_data), GFP_KERNEL); - revmap_data->pstate_id = id; + revmap_data->pstate_id = id & 0xFF; revmap_data->cpufreq_table_idx = i; - key = id % POWERNV_MAX_PSTATES; + key = (revmap_data->pstate_id) % POWERNV_MAX_PSTATES; hash_add(pstate_revmap, &revmap_data->hentry, key); if (id == pstate_max) @@ -364,14 +356,13 @@ static int init_powernv_pstates(void) } /* Returns the CPU frequency corresponding to the pstate_id. */ -static unsigned int pstate_id_to_freq(int pstate_id) +static unsigned int pstate_id_to_freq(u8 pstate_id) { int i; i = pstate_to_idx(pstate_id); if (i >= powernv_pstate_info.nr_pstates || i < 0) { - pr_warn("PState id %d outside of PState table, " - "reporting nominal id %d instead\n", + pr_warn("PState id 0x%x outside of PState table, reporting nominal id 0x%x instead\n", pstate_id, idx_to_pstate(powernv_pstate_info.nominal)); i = powernv_pstate_info.nominal; } @@ -477,8 +468,8 @@ static inline void set_pmspr(unsigned long sprn, unsigned long val) */ struct powernv_smp_call_data { unsigned int freq; - int pstate_id; - int gpstate_id; + u8 pstate_id; + u8 gpstate_id; }; /* @@ -501,9 +492,9 @@ static void powernv_read_cpu_freq(void *arg) freq_data->pstate_id = extract_local_pstate(pmspr_val); freq_data->freq = pstate_id_to_freq(freq_data->pstate_id); - pr_debug("cpu %d pmsr %016lX pstate_id %d frequency %d kHz\n", - raw_smp_processor_id(), pmspr_val, freq_data->pstate_id, - freq_data->freq); + pr_debug("cpu %d pmsr %016lX pstate_id 0x%x frequency %d kHz\n", + raw_smp_processor_id(), pmspr_val, freq_data->pstate_id, + freq_data->freq); } /* @@ -565,7 +556,7 @@ static void powernv_cpufreq_throttle_check(void *data) struct chip *chip; unsigned int cpu = smp_processor_id(); unsigned long pmsr; - int pmsr_pmax; + u8 pmsr_pmax; unsigned int pmsr_pmax_idx; pmsr = get_pmspr(SPRN_PMSR); @@ -579,7 +570,7 @@ static void powernv_cpufreq_throttle_check(void *data) goto next; chip->throttled = true; if (pmsr_pmax_idx > powernv_pstate_info.nominal) { - pr_warn_once("CPU %d on Chip %u has Pmax(%d) reduced below nominal frequency(%d)\n", + pr_warn_once("CPU %d on Chip %u has Pmax(0x%x) reduced below that of nominal frequency(0x%x)\n", cpu, chip->id, pmsr_pmax, idx_to_pstate(powernv_pstate_info.nominal)); chip->throttle_sub_turbo++;