From patchwork Thu Jul 27 19:15:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shilpasri G Bhat X-Patchwork-Id: 794553 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.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 3xJMDw3G5cz9s2G for ; Fri, 28 Jul 2017 05:17:36 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3xJMDw2Bm8zDrSk for ; Fri, 28 Jul 2017 05:17:36 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org 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 3xJMDF1xNVzDrNN for ; Fri, 28 Jul 2017 05:17:00 +1000 (AEST) Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id v6RJFMUw029619 for ; Thu, 27 Jul 2017 15:16:58 -0400 Received: from e23smtp08.au.ibm.com (e23smtp08.au.ibm.com [202.81.31.141]) by mx0a-001b2d01.pphosted.com with ESMTP id 2byh1py7da-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Thu, 27 Jul 2017 15:16:57 -0400 Received: from localhost by e23smtp08.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 28 Jul 2017 05:16:54 +1000 Received: from d23relay07.au.ibm.com (202.81.31.226) by e23smtp08.au.ibm.com (202.81.31.205) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 28 Jul 2017 05:16:53 +1000 Received: from d23av03.au.ibm.com (d23av03.au.ibm.com [9.190.234.97]) by d23relay07.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v6RJGq8G28246164 for ; Fri, 28 Jul 2017 05:16:52 +1000 Received: from d23av03.au.ibm.com (localhost [127.0.0.1]) by d23av03.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id v6RJGhSW001908 for ; Fri, 28 Jul 2017 05:16:43 +1000 Received: from oc4502181600.ibm.com ([9.195.38.136]) by d23av03.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id v6RJGSYx001557; Fri, 28 Jul 2017 05:16:40 +1000 From: Shilpasri G Bhat To: stewart@linux.vnet.ibm.com, cyrilbur@gmail.com Date: Fri, 28 Jul 2017 00:45:28 +0530 X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1501182933-756-1-git-send-email-shilpa.bhat@linux.vnet.ibm.com> References: <1501182933-756-1-git-send-email-shilpa.bhat@linux.vnet.ibm.com> X-TM-AS-MML: disable x-cbid: 17072719-0048-0000-0000-000002570BE0 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17072719-0049-0000-0000-000048099624 Message-Id: <1501182933-756-4-git-send-email-shilpa.bhat@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-07-27_11:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1706020000 definitions=main-1707270300 Subject: [Skiboot] [PATCH V9 3/8] powercap: occ: Add a generic powercap framework X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: skiboot@lists.ozlabs.org, ego@linux.vnet.ibm.com MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This patch adds a generic powercap framework and exports OCC powercap sensors using which system powercap can be set inband through OPAL-OCC command-response interface. Documentation for powercap enhanced by Stewart Smith. Signed-off-by: Shilpasri G Bhat --- Changes from V8: - Enhanced documentation. - Add compatible property "ibm,opal-powercap" - Return OPAL_PERMISSION on setting powercap-{min/max} - s/powercap-cur/powercap-current core/Makefile.inc | 2 +- core/powercap.c | 40 ++++++++ doc/device-tree/ibm,opal/power-mgt/powercap.rst | 48 ++++++++++ doc/opal-api/opal-powercap.rst | 96 +++++++++++++++++++ hw/occ.c | 119 +++++++++++++++++++++++- include/opal-api.h | 4 +- include/powercap.h | 43 +++++++++ 7 files changed, 348 insertions(+), 4 deletions(-) create mode 100644 core/powercap.c create mode 100644 doc/device-tree/ibm,opal/power-mgt/powercap.rst create mode 100644 doc/opal-api/opal-powercap.rst create mode 100644 include/powercap.h diff --git a/core/Makefile.inc b/core/Makefile.inc index b09c30c..b3c9e91 100644 --- a/core/Makefile.inc +++ b/core/Makefile.inc @@ -8,7 +8,7 @@ CORE_OBJS += pci-opal.o fast-reboot.o device.o exceptions.o trace.o affinity.o CORE_OBJS += vpd.o hostservices.o platform.o nvram.o nvram-format.o hmi.o CORE_OBJS += console-log.o ipmi.o time-utils.o pel.o pool.o errorlog.o CORE_OBJS += timer.o i2c.o rtc.o flash.o sensor.o ipmi-opal.o -CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o +CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o powercap.o ifeq ($(SKIBOOT_GCOV),1) CORE_OBJS += gcov-profiling.o diff --git a/core/powercap.c b/core/powercap.c new file mode 100644 index 0000000..50b5996 --- /dev/null +++ b/core/powercap.c @@ -0,0 +1,40 @@ +/* Copyright 2017 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +static int opal_get_powercap(u32 handle, int token __unused, u32 *pcap) +{ + if (!pcap || !opal_addr_valid(pcap)) + return OPAL_PARAMETER; + + if (powercap_get_class(handle) == POWERCAP_CLASS_OCC) + return occ_get_powercap(handle, pcap); + + return OPAL_UNSUPPORTED; +}; + +opal_call(OPAL_GET_POWERCAP, opal_get_powercap, 3); + +static int opal_set_powercap(u32 handle, int token, u32 pcap) +{ + if (powercap_get_class(handle) == POWERCAP_CLASS_OCC) + return occ_set_powercap(handle, token, pcap); + + return OPAL_UNSUPPORTED; +}; + +opal_call(OPAL_SET_POWERCAP, opal_set_powercap, 3); diff --git a/doc/device-tree/ibm,opal/power-mgt/powercap.rst b/doc/device-tree/ibm,opal/power-mgt/powercap.rst new file mode 100644 index 0000000..e47caa4 --- /dev/null +++ b/doc/device-tree/ibm,opal/power-mgt/powercap.rst @@ -0,0 +1,48 @@ +power-mgt/powercap +------------------ + +The powercap sensors are populated in this node. Each child node in +the "powercap" node represents a power-cappable component. + +For example : :: + system-powercap/ + +The OPAL_GET_POWERCAP and OPAL_SET_POWERCAP calls take a handle for +what powercap property to get/set which is defined in the child node. + +The compatible property for the linux driver which will be +"ibm,opal-powercap" + +Each child node has below properties: + +`powercap-current` + Handle to indicate the current powercap + +`powercap-min` + Minimum possible powercap + +`powercap-max` + Maximum possible powercap + +Powercap handle uses the following encoding: :: + + | Class | Reserved | Attribute | + |-------|---------------|-----------| + +Note: The format of the powercap handle is ``NOT`` ABI and may change in +the future. + +.. code-block:: dts + + power-mgt { + powercap { + compatible = "ibm,opal-powercap"; + + system-powercap { + name = "system-powercap" + powercap-current = <0x00000002> + powercap-min = <0x00000000> + powercap-max = <0x00000001> + }; + }; + } diff --git a/doc/opal-api/opal-powercap.rst b/doc/opal-api/opal-powercap.rst new file mode 100644 index 0000000..00f6866 --- /dev/null +++ b/doc/opal-api/opal-powercap.rst @@ -0,0 +1,96 @@ +.. _opal-powercap: + +OPAL_GET_POWERCAP +================== +The OPAL_GET_POWERCAP call retreives current information on the power +cap. + +For each entity that can be power capped, the device tree +binding indicates what handle should be passed for each of the power cap +properties (minimum possible, maximum possible, current powercap). + +The current power cap must be between the minimium possible and maximum +possible power cap. The minimum and maximum values are dynamic to allow +for them possibly being changed by other factors or entities +(e.g. service processor). + +The call can be asynchronus, where the token parameter is used to wait +for the completion. + +Parameters +---------- +:: + u32 handle + int token + u32 *pcap + +Returns +------- +OPAL_SUCCESS + Success + +OPAL_PARAMETER + Invalid pcap pointer + +OPAL_UNSUPPORTED + No support for reading powercap sensor + +OPAL_HARDWARE + Unable to procced due to the current hardware state + +OPAL_ASYNC_COMPLETION + Request was sent and an async completion message will be sent with + token and status of the request. + +OPAL_SET_POWERCAP +============================ +The OPAL_SET_POWERCAP call sets a power cap. + +For each entity that can be power capped, the device tree +binding indicates what handle should be passed for each of the power cap +properties (minimum possible, maximum possible, current powercap). + +The current power cap must be between the minimium possible and maximum +possible power cap. + +You cannot currently set the minimum or maximum power cap, and thus +OPAL_PERMISSION will be returned if it is attempted to set. In the +future, this may change - but for now, the correct behaviour for an +Operating System is to not attempt to set them. + +Parameters +---------- +:: + u32 handle + int token + u32 pcap + +Returns +------- +OPAL_SUCCESS + Success + +OPAL_PARAMETER + Invalid powercap requested beyond powercap limits + +OPAL_UNSUPPORTED + No support for changing the powercap + +OPAL_PERMISSION + Hardware cannot take the request + +OPAL_ASYNC_COMPLETION + Request was sent and an async completion message will be sent with + token and status of the request. + +OPAL_HARDWARE + Unable to procced due to the current hardware state + +OPAL_BUSY + Previous request in progress + +OPAL_INTERNAL_ERROR + Error in request response + +OPAL_TIMEOUT + Timeout in request completion diff --git a/hw/occ.c b/hw/occ.c index 58d9778..d286628 100644 --- a/hw/occ.c +++ b/hw/occ.c @@ -28,6 +28,7 @@ #include #include #include +#include /* OCC Communication Area for PStates */ @@ -1060,8 +1061,8 @@ static int write_occ_cmd(struct cmd_interface *chip) return OPAL_ASYNC_COMPLETION; } -static int64_t __unused opal_occ_command(struct cmd_interface *chip, int token, - struct opal_occ_cmd_data *cdata) +static int64_t opal_occ_command(struct cmd_interface *chip, int token, + struct opal_occ_cmd_data *cdata) { int rc; @@ -1213,10 +1214,13 @@ exit: unlock(&chip->queue_lock); } +static void occ_add_powercap_sensors(struct dt_node *power_mgt); + static void occ_cmd_interface_init(void) { struct occ_dynamic_data *data; struct occ_pstate_table *pdata; + struct dt_node *power_mgt; struct proc_chip *chip; int i = 0; @@ -1247,8 +1251,119 @@ static void occ_cmd_interface_init(void) &chips[i]); i++; } + + power_mgt = dt_find_by_path(dt_root, "/ibm,opal/power-mgt"); + if (!power_mgt) { + prerror("OCC: dt node /ibm,opal/power-mgt not found\n"); + return; + } + + /* Add powercap sensors to DT */ + occ_add_powercap_sensors(power_mgt); +} + +/* Powercap interface */ +enum sensor_powercap_occ_attr { + POWERCAP_OCC_MIN, + POWERCAP_OCC_MAX, + POWERCAP_OCC_CUR, +}; + +static void occ_add_powercap_sensors(struct dt_node *power_mgt) +{ + struct dt_node *pcap, *node; + u32 handle; + + pcap = dt_new(power_mgt, "powercap"); + if (!pcap) { + prerror("OCC: Failed to create powercap node\n"); + return; + } + + dt_add_property_string(pcap, "compatible", "ibm,opal-powercap"); + node = dt_new(pcap, "system-powercap"); + if (!node) { + prerror("OCC: Failed to create system powercap node\n"); + return; + } + + handle = powercap_make_handle(POWERCAP_CLASS_OCC, POWERCAP_OCC_CUR); + dt_add_property_cells(node, "powercap-current", handle); + + handle = powercap_make_handle(POWERCAP_CLASS_OCC, POWERCAP_OCC_MIN); + dt_add_property_cells(node, "powercap-min", handle); + + handle = powercap_make_handle(POWERCAP_CLASS_OCC, POWERCAP_OCC_MAX); + dt_add_property_cells(node, "powercap-max", handle); +} + +int occ_get_powercap(u32 handle, u32 *pcap) +{ + struct occ_pstate_table *pdata; + struct occ_dynamic_data *ddata; + struct proc_chip *chip; + + chip = next_chip(NULL); + pdata = get_occ_pstate_table(chip); + ddata = get_occ_dynamic_data(chip); + + if (!pdata->valid) + return OPAL_HARDWARE; + + switch (powercap_get_attr(handle)) { + case POWERCAP_OCC_MIN: + *pcap = ddata->min_pwr_cap; + break; + case POWERCAP_OCC_MAX: + *pcap = ddata->max_pwr_cap; + break; + case POWERCAP_OCC_CUR: + *pcap = ddata->cur_pwr_cap; + break; + default: + *pcap = 0; + return OPAL_UNSUPPORTED; + } + + return OPAL_SUCCESS; } +static u16 pcap_cdata; +static struct opal_occ_cmd_data pcap_data = { + .data = (u8 *)&pcap_cdata, + .cmd = OCC_CMD_SET_POWER_CAP, +}; + +int occ_set_powercap(u32 handle, int token, u32 pcap) +{ + struct occ_dynamic_data *ddata; + struct proc_chip *chip; + int i; + + if (powercap_get_attr(handle) != POWERCAP_OCC_CUR) + return OPAL_PERMISSION; + + for (i = 0; i < nr_occs; i++) + if (chips[i].occ_role == OCC_ROLE_MASTER) + break; + + if (!(*chips[i].valid)) + return OPAL_HARDWARE; + + chip = get_chip(chips[i].chip_id); + ddata = get_occ_dynamic_data(chip); + + if (pcap == ddata->cur_pwr_cap) + return OPAL_SUCCESS; + + if (pcap && (pcap > ddata->max_pwr_cap || + pcap < ddata->min_pwr_cap)) + return OPAL_PARAMETER; + + pcap_cdata = pcap; + return opal_occ_command(&chips[i], token, &pcap_data); +}; + /* CPU-OCC PState init */ /* Called after OCC init on P8 and P9 */ void occ_pstates_init(void) diff --git a/include/opal-api.h b/include/opal-api.h index d2137d6..3ad4898 100644 --- a/include/opal-api.h +++ b/include/opal-api.h @@ -208,7 +208,9 @@ #define OPAL_IMC_COUNTERS_INIT 149 #define OPAL_IMC_COUNTERS_START 150 #define OPAL_IMC_COUNTERS_STOP 151 -#define OPAL_LAST 151 +#define OPAL_GET_POWERCAP 152 +#define OPAL_SET_POWERCAP 153 +#define OPAL_LAST 153 /* Device tree flags */ diff --git a/include/powercap.h b/include/powercap.h new file mode 100644 index 0000000..ec5e126 --- /dev/null +++ b/include/powercap.h @@ -0,0 +1,43 @@ +/* Copyright 2017 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __POWERCAP_H +#define __POWERCAP_H + +#include + +enum powercap_class { + POWERCAP_CLASS_OCC, +}; + +/* + * Powercap handle is defined as u32. The first and last bytes are + * used to indicate the class and attribute. + * + * | Class | Reserved | Attribute | + * |-------|---------------|-----------| + */ + +#define powercap_make_handle(class, attr) (((class & 0xF) << 24) | (attr & 0xF)) + +#define powercap_get_class(handle) ((handle >> 24) & 0xF) +#define powercap_get_attr(handle) (handle & 0xF) + +/* Powercap OCC interface */ +int occ_get_powercap(u32 handle, u32 *pcap); +int occ_set_powercap(u32 handle, int token, u32 pcap); + +#endif /* __POWERCAP_H */