From patchwork Mon Aug 14 07:28:01 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: 801092 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 3xW6fR6zkSz9sDB for ; Mon, 14 Aug 2017 17:28:31 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3xW6fR6CWLzDrCR for ; Mon, 14 Aug 2017 17:28:31 +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 3xW6fD6sb2zDr4x for ; Mon, 14 Aug 2017 17:28:20 +1000 (AEST) 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 v7E7NkR6013367 for ; Mon, 14 Aug 2017 03:28:18 -0400 Received: from e23smtp08.au.ibm.com (e23smtp08.au.ibm.com [202.81.31.141]) by mx0b-001b2d01.pphosted.com with ESMTP id 2cb6rg1nhc-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 14 Aug 2017 03:28:17 -0400 Received: from localhost by e23smtp08.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 14 Aug 2017 17:28:14 +1000 Received: from d23relay10.au.ibm.com (202.81.31.229) by e23smtp08.au.ibm.com (202.81.31.205) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 14 Aug 2017 17:28:12 +1000 Received: from d23av03.au.ibm.com (d23av03.au.ibm.com [9.190.234.97]) by d23relay10.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v7E7SCWb29098038 for ; Mon, 14 Aug 2017 17:28:12 +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 v7E7S3r0014444 for ; Mon, 14 Aug 2017 17:28:03 +1000 Received: from oc4502181600.ibm.com ([9.79.196.136]) by d23av03.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id v7E7RwaG014259; Mon, 14 Aug 2017 17:28:00 +1000 From: Shilpasri G Bhat To: skiboot@lists.ozlabs.org Date: Mon, 14 Aug 2017 12:58:01 +0530 X-Mailer: git-send-email 1.8.3.1 X-TM-AS-MML: disable x-cbid: 17081407-0048-0000-0000-00000258485C X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17081407-0049-0000-0000-0000480C1968 Message-Id: <1502695681-18018-1-git-send-email-shilpa.bhat@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-08-14_05:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1706020000 definitions=main-1708140119 Subject: [Skiboot] [RFC V2] sensors: dts: Assert special wakeup on idle cores while reading temperature 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: ego@linux.vnet.ibm.com MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" In P9, when a core enters a stop state, its clocks will be stopped to save power and hence we will not be able to perform a scom operation to read the DTS temperature sensor. Hence, assert a special wakeup on cores that have entered a stop state in order to successfully complete the scom operation. Signed-off-by: Shilpasri G Bhat --- Changes from V1: - Make dts_sensor_read() async call for P9 - Remove reading from Stop-Interface-Status-Register as it can be racy to decide if a core is in stop and then read DTS scom. - Issue unconditional special wakeup while reading temperature. core/hostservices.c | 79 +++++++++++++++++++++++++++++------------------- core/sensor.c | 2 +- hw/dts.c | 81 ++++++++++++++++++++++++++++++++++++++++++-------- include/dts.h | 2 +- include/hostservices.h | 4 +++ include/xscom.h | 6 ++++ 6 files changed, 130 insertions(+), 44 deletions(-) diff --git a/core/hostservices.c b/core/hostservices.c index d1f6fda..345c8c0 100644 --- a/core/hostservices.c +++ b/core/hostservices.c @@ -545,9 +545,10 @@ static void hservice_nanosleep(uint64_t i_seconds, uint64_t i_nano_seconds) nanosleep_nopoll(&ts, NULL); } -static int hservice_set_special_wakeup(struct cpu_thread *cpu) +int hservice_set_special_wakeup(struct cpu_thread *cpu) { uint64_t val, core_id, poll_target, stamp; + u64 wkup_addr, wkup_mask, pm_reg, idle_hist_reg; int rc; /* @@ -558,20 +559,36 @@ static int hservice_set_special_wakeup(struct cpu_thread *cpu) /* Grab core ID once */ core_id = pir_to_core_id(cpu->pir); + switch (proc_gen) { + case proc_gen_p8: + wkup_addr = XSCOM_ADDR_P8_EX_SLAVE(core_id, + EX_PM_SPECIAL_WAKEUP_PHYP); + wkup_mask = EX_PM_GP0_SPECIAL_WAKEUP_DONE; + pm_reg = XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_GP0); + idle_hist_reg = XSCOM_ADDR_P8_EX_SLAVE(core_id, + EX_PM_IDLE_STATE_HISTORY_PHYP); + break; + case proc_gen_p9: + wkup_addr = XSCOM_ADDR_P9_EC_SLAVE(core_id, + EC_PPM_SPECIAL_WKUP_HYP); + wkup_mask = EC_PPM_GPPMR_SPECIAL_WAKEUP_DONE; + pm_reg = XSCOM_ADDR_P9_EC_SLAVE(core_id, EC_PPM_GPPMR_SCOM); + idle_hist_reg = XSCOM_ADDR_P9_EC_SLAVE(core_id, + EC_PM_IDLE_STATE_HISTORY_PHYP); + break; + default: + return OPAL_UNSUPPORTED; + } + /* * The original HWp reads the XSCOM first but ignores the result * and error, let's do the same until I know for sure that is * not necessary */ - xscom_read(cpu->chip_id, - XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_SPECIAL_WAKEUP_PHYP), - &val); + xscom_read(cpu->chip_id, wkup_addr, &val); /* Then we write special wakeup */ - rc = xscom_write(cpu->chip_id, - XSCOM_ADDR_P8_EX_SLAVE(core_id, - EX_PM_SPECIAL_WAKEUP_PHYP), - PPC_BIT(0)); + rc = xscom_write(cpu->chip_id, wkup_addr, PPC_BIT(0)); if (rc) { prerror("HBRT: XSCOM error %d asserting special" " wakeup on 0x%x\n", rc, cpu->pir); @@ -602,14 +619,13 @@ static int hservice_set_special_wakeup(struct cpu_thread *cpu) stamp = mftb(); poll_target = stamp + msecs_to_tb(200); val = 0; - while (!(val & EX_PM_GP0_SPECIAL_WAKEUP_DONE)) { + + while (!(val & wkup_mask)) { /* Wait 1 us */ hservice_nanosleep(0, 1000); /* Read PM state */ - rc = xscom_read(cpu->chip_id, - XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_GP0), - &val); + rc = xscom_read(cpu->chip_id, pm_reg, &val); if (rc) { prerror("HBRT: XSCOM error %d reading PM state on" " 0x%x\n", rc, cpu->pir); @@ -621,7 +637,7 @@ static int hservice_set_special_wakeup(struct cpu_thread *cpu) } /* Success ? */ - if (val & EX_PM_GP0_SPECIAL_WAKEUP_DONE) { + if (val & wkup_mask) { uint64_t now = mftb(); prlog(PR_TRACE, "HBRT: Special wakeup complete after %ld us\n", tb_to_usecs(now - stamp)); @@ -639,23 +655,19 @@ static int hservice_set_special_wakeup(struct cpu_thread *cpu) prerror("HBRT: Timeout on special wakeup of 0x%0x\n", cpu->pir); prerror("HBRT: PM0 = 0x%016llx\n", val); val = -1; - xscom_read(cpu->chip_id, - XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_SPECIAL_WAKEUP_PHYP), - &val); + xscom_read(cpu->chip_id, wkup_addr, &val); prerror("HBRT: SPC_WKUP = 0x%016llx\n", val); val = -1; - xscom_read(cpu->chip_id, - XSCOM_ADDR_P8_EX_SLAVE(core_id, - EX_PM_IDLE_STATE_HISTORY_PHYP), - &val); + xscom_read(cpu->chip_id, idle_hist_reg, &val); prerror("HBRT: HISTORY = 0x%016llx\n", val); return OPAL_HARDWARE; } -static int hservice_clr_special_wakeup(struct cpu_thread *cpu) +int hservice_clr_special_wakeup(struct cpu_thread *cpu) { uint64_t val, core_id; + u64 addr; int rc; /* @@ -671,14 +683,23 @@ static int hservice_clr_special_wakeup(struct cpu_thread *cpu) * and error, let's do the same until I know for sure that is * not necessary */ - xscom_read(cpu->chip_id, - XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_SPECIAL_WAKEUP_PHYP), - &val); + switch (proc_gen) { + case proc_gen_p8: + addr = XSCOM_ADDR_P8_EX_SLAVE(core_id, + EX_PM_SPECIAL_WAKEUP_PHYP); + break; + case proc_gen_p9: + addr = XSCOM_ADDR_P9_EC_SLAVE(core_id, + EC_PPM_SPECIAL_WKUP_HYP); + break; + default: + return OPAL_UNSUPPORTED; + } + + xscom_read(cpu->chip_id, addr, &val); /* Then we write special wakeup */ - rc = xscom_write(cpu->chip_id, - XSCOM_ADDR_P8_EX_SLAVE(core_id, - EX_PM_SPECIAL_WAKEUP_PHYP), 0); + rc = xscom_write(cpu->chip_id, addr, 0); if (rc) { prerror("HBRT: XSCOM error %d deasserting" " special wakeup on 0x%x\n", rc, cpu->pir); @@ -690,9 +711,7 @@ static int hservice_clr_special_wakeup(struct cpu_thread *cpu) * "This puts an inherent delay in the propagation of the reset * transition" */ - xscom_read(cpu->chip_id, - XSCOM_ADDR_P8_EX_SLAVE(core_id, EX_PM_SPECIAL_WAKEUP_PHYP), - &val); + xscom_read(cpu->chip_id, addr, &val); return 0; } diff --git a/core/sensor.c b/core/sensor.c index 57b21bc..0e2a5ca 100644 --- a/core/sensor.c +++ b/core/sensor.c @@ -28,7 +28,7 @@ static int64_t opal_sensor_read(uint32_t sensor_hndl, int token, { switch (sensor_get_family(sensor_hndl)) { case SENSOR_DTS: - return dts_sensor_read(sensor_hndl, sensor_data); + return dts_sensor_read(sensor_hndl, token, sensor_data); case SENSOR_OCC: return occ_sensor_read(sensor_hndl, sensor_data); default: diff --git a/hw/dts.c b/hw/dts.c index a10df58..3524102 100644 --- a/hw/dts.c +++ b/hw/dts.c @@ -20,6 +20,10 @@ #include #include #include +#include +#include +#include +#include struct dts { uint8_t valid; @@ -27,6 +31,14 @@ struct dts { int16_t temp; }; +/* + * Attributes for the core temperature sensor + */ +enum { + SENSOR_DTS_ATTR_TEMP_MAX, + SENSOR_DTS_ATTR_TEMP_TRIP +}; + /* Different sensor locations */ #define P7_CT_ZONE_LSU 0 #define P7_CT_ZONE_ISU 1 @@ -196,7 +208,7 @@ static int dts_read_core_temp_p8(uint32_t pir, struct dts *dts) * Returns the temperature as the max of all zones and a global trip * attribute. */ -static int dts_read_core_temp_p9(uint32_t pir, struct dts *dts) +static int _dts_read_core_temp_p9(u32 pir, struct dts *dts) { int32_t chip_id = pir_to_chip_id(pir); int32_t core = pir_to_core_id(pir); @@ -222,7 +234,55 @@ static int dts_read_core_temp_p9(uint32_t pir, struct dts *dts) * them for the moment until we understand why. */ dts->trip = 0; - return 0; + return rc; +} + +static struct timer dts_timer; +static struct dts_async_data { + u32 *sensor_data; + u32 pir; + int token; + u8 attr; +} dts_async_data; + +static void dts_spl_wkup(struct timer *t __unused, void *data, + u64 now __unused) +{ + struct dts_async_data *async_data = data; + struct dts dts; + u32 pir; + int rc; + + pir = async_data->pir; + rc = hservice_set_special_wakeup(find_cpu_by_pir(pir)); + if (rc) { + prerror("Failed to set special wakeup on %d (%d)\n", + pir_to_core_id(pir), rc); + goto out; + } + + if (!_dts_read_core_temp_p9(pir, &dts)) { + if (async_data->attr == SENSOR_DTS_ATTR_TEMP_MAX) + *async_data->sensor_data = dts.temp; + else if (async_data->attr == SENSOR_DTS_ATTR_TEMP_TRIP) + *async_data->sensor_data = dts.trip; + } + + rc = hservice_clr_special_wakeup(find_cpu_by_pir(pir)); + if (rc) + prerror("Failed to clear special wakeup on %d (%d)\n", + pir_to_core_id(pir), rc); +out: + rc = opal_queue_msg(OPAL_MSG_ASYNC_COMP, NULL, NULL, async_data->token, + rc); + if (rc) + prerror("Failed to queue async message\n"); +} + +static int dts_read_core_temp_p9(void) +{ + schedule_timer(&dts_timer, usecs_to_tb(1)); + return OPAL_ASYNC_COMPLETION; } static int dts_read_core_temp(uint32_t pir, struct dts *dts) @@ -237,7 +297,7 @@ static int dts_read_core_temp(uint32_t pir, struct dts *dts) rc = dts_read_core_temp_p8(pir, dts); break; case proc_gen_p9: - rc = dts_read_core_temp_p9(pir, dts); + rc = dts_read_core_temp_p9(); break; default: rc = OPAL_UNSUPPORTED; @@ -303,20 +363,12 @@ enum sensor_dts_class { }; /* - * Attributes for the core temperature sensor - */ -enum { - SENSOR_DTS_ATTR_TEMP_MAX, - SENSOR_DTS_ATTR_TEMP_TRIP -}; - -/* * Extract the centaur chip id which was truncated to fit in the * resource identifier field of the sensor handler */ #define centaur_get_id(rid) (0x80000000 | ((rid) & 0x3ff)) -int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data) +int64_t dts_sensor_read(u32 sensor_hndl, int token, u32 *sensor_data) { uint8_t attr = sensor_get_attr(sensor_hndl); uint32_t rid = sensor_get_rid(sensor_hndl); @@ -330,6 +382,10 @@ int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data) switch (sensor_get_frc(sensor_hndl)) { case SENSOR_DTS_CORE_TEMP: + dts_async_data.attr = attr; + dts_async_data.pir = rid; + dts_async_data.sensor_data = sensor_data; + dts_async_data.token = token; rc = dts_read_core_temp(rid, &dts); break; case SENSOR_DTS_MEM_TEMP: @@ -431,5 +487,6 @@ bool dts_sensor_create_nodes(struct dt_node *sensors) dt_add_property_string(node, "label", "Centaur"); } + init_timer(&dts_timer, dts_spl_wkup, &dts_async_data); return true; } diff --git a/include/dts.h b/include/dts.h index b37919f..17e2e15 100644 --- a/include/dts.h +++ b/include/dts.h @@ -19,7 +19,7 @@ #include -extern int64_t dts_sensor_read(uint32_t sensor_hndl, uint32_t *sensor_data); +extern int64_t dts_sensor_read(u32 sensor_hndl, int token, u32 *sensor_data); extern bool dts_sensor_create_nodes(struct dt_node *sensors); #endif /* __DTS_H */ diff --git a/include/hostservices.h b/include/hostservices.h index d6bb3e3..82303b8 100644 --- a/include/hostservices.h +++ b/include/hostservices.h @@ -17,6 +17,8 @@ #ifndef __HOSTSERVICES_H #define __HOSTSERVICES_H +#include + bool hservices_init(void); void hservices_lid_preload(void); bool hservices_lid_preload_complete(void); @@ -39,4 +41,6 @@ void host_services_occ_base_setup(void); int find_master_and_slave_occ(uint64_t **master, uint64_t **slave, int *nr_masters, int *nr_slaves); +int hservice_clr_special_wakeup(struct cpu_thread *cpu); +int hservice_set_special_wakeup(struct cpu_thread *cpu); #endif /* __HOSTSERVICES_H */ diff --git a/include/xscom.h b/include/xscom.h index 5a5d0b9..a3ce99e 100644 --- a/include/xscom.h +++ b/include/xscom.h @@ -148,6 +148,12 @@ #define EC_PPM_SPECIAL_WKUP_FSP 0x010B #define EC_PPM_SPECIAL_WKUP_OCC 0x010C #define EC_PPM_SPECIAL_WKUP_HYP 0x010D +#define EC_PM_IDLE_STATE_HISTORY_PHYP 0x0114 +#define EC_PPM_GPPMR_SCOM 0x0100 +#define EC_PPM_GPPMR_SCOM1 0x0101 +#define EC_PPM_GPPMR_SCOM2 0x0102 + +#define EC_PPM_GPPMR_SPECIAL_WAKEUP_DONE PPC_BIT(0) /************* XXXX Move these P8 only registers elswhere !!! ****************/