From patchwork Tue Aug 8 18:32:36 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: 799391 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 3xRjh43VzJz9s7g for ; Wed, 9 Aug 2017 04:33:08 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3xRjh40JsqzDqsT for ; Wed, 9 Aug 2017 04:33:08 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org 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 3xRjgn6DkczDqpt for ; Wed, 9 Aug 2017 04:32:53 +1000 (AEST) Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id v78IWbjj133132 for ; Tue, 8 Aug 2017 14:32:50 -0400 Received: from e23smtp04.au.ibm.com (e23smtp04.au.ibm.com [202.81.31.146]) by mx0a-001b2d01.pphosted.com with ESMTP id 2c7j5t1t33-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 08 Aug 2017 14:32:50 -0400 Received: from localhost by e23smtp04.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 9 Aug 2017 04:32:47 +1000 Received: from d23relay09.au.ibm.com (202.81.31.228) by e23smtp04.au.ibm.com (202.81.31.210) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 9 Aug 2017 04:32:45 +1000 Received: from d23av01.au.ibm.com (d23av01.au.ibm.com [9.190.234.96]) by d23relay09.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v78IWiFG33620006 for ; Wed, 9 Aug 2017 04:32:44 +1000 Received: from d23av01.au.ibm.com (localhost [127.0.0.1]) by d23av01.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id v78IWil8002281 for ; Wed, 9 Aug 2017 04:32:44 +1000 Received: from oc4502181600.ibm.com ([9.79.205.212]) by d23av01.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id v78IWeaI002241; Wed, 9 Aug 2017 04:32:41 +1000 From: Shilpasri G Bhat To: skiboot@lists.ozlabs.org Date: Wed, 9 Aug 2017 00:02:36 +0530 X-Mailer: git-send-email 1.8.3.1 X-TM-AS-MML: disable x-cbid: 17080818-0012-0000-0000-00000258C83A X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17080818-0013-0000-0000-00000773DAC0 Message-Id: <1502217156-31878-1-git-send-email-shilpa.bhat@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-08-08_09:, , 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-1708080302 Subject: [Skiboot] [PATCH] 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 --- TODO: - Make the dts_read_core_temp_p9() call async core/hostservices.c | 79 +++++++++++++++++++++++++++++++------------------- hw/dts.c | 32 ++++++++++++++++++-- hw/slw.c | 20 +++++++++++++ include/hostservices.h | 4 +++ include/skiboot.h | 3 ++ include/xscom.h | 12 ++++++++ 6 files changed, 118 insertions(+), 32 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/hw/dts.c b/hw/dts.c index a10df58..a19f7d3 100644 --- a/hw/dts.c +++ b/hw/dts.c @@ -20,6 +20,7 @@ #include #include #include +#include struct dts { uint8_t valid; @@ -198,16 +199,32 @@ static int dts_read_core_temp_p8(uint32_t pir, struct dts *dts) */ static int dts_read_core_temp_p9(uint32_t pir, struct dts *dts) { + struct cpu_thread *cpu = find_cpu_by_pir(pir); int32_t chip_id = pir_to_chip_id(pir); int32_t core = pir_to_core_id(pir); uint64_t dts0; struct dts temps[P9_CORE_ZONES]; int rc; + bool stopped; + + /* Check if CPU is idle */ + stopped = check_core_stopped(pir); + + /* Assert special wakeup */ + if (stopped) { + rc = hservice_set_special_wakeup(cpu); + if (rc) { + prerror("Failed to set special wakeup on %d (%d)\n", + core, rc); + return rc; + } + } + /* Read temperature */ rc = xscom_read(chip_id, XSCOM_ADDR_P9_EC(core, EC_THERM_P9_DTS_RESULT0), &dts0); if (rc) - return rc; + goto clr; dts_decode_one_dts(dts0 >> 48, &temps[P9_CORE_DTS0]); dts_decode_one_dts(dts0 >> 32, &temps[P9_CORE_DTS1]); @@ -222,7 +239,18 @@ 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; +clr: + /* Release special wakeup */ + if (stopped) { + rc = hservice_clr_special_wakeup(cpu); + if (rc) { + prerror("Failed to clear special wakeup on %d (%d)\n", + core, rc); + return rc; + } + } + + return rc; } static int dts_read_core_temp(uint32_t pir, struct dts *dts) diff --git a/hw/slw.c b/hw/slw.c index c0ab9de..32fc6d4 100644 --- a/hw/slw.c +++ b/hw/slw.c @@ -1521,3 +1521,23 @@ void slw_init(void) slw_init_chip_p9(chip); } } + +bool check_core_stopped(u32 pir) +{ + u64 val; + u32 chip_id = pir_to_chip_id(pir); + u32 core = pir_to_core_id(pir); + int rc; + + rc = xscom_read(chip_id, XSCOM_ADDR_P9_EX(core, EX_PM_SISR), &val); + if (rc) { + prerror("Failed to read Stop Interface Status Register %d\n", + rc); + return true; + } + + if (pir & 0x4) + return (!(val & EX_PM_SISR_INST_C1)); + else + return (!(val & EX_PM_SISR_INST_C0)); +} 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/skiboot.h b/include/skiboot.h index 4b7d519..c1e2aa3 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -317,4 +317,7 @@ extern int occ_sensor_group_clear(u32 group_hndl, int token); extern void occ_add_sensor_groups(struct dt_node *sg, u32 *phandles, int nr_phandles, int chipid); +/* Check if a core has entered a stop state */ +bool check_core_stopped(u32 pir); + #endif /* __SKIBOOT_H */ diff --git a/include/xscom.h b/include/xscom.h index 5a5d0b9..da72dd5 100644 --- a/include/xscom.h +++ b/include/xscom.h @@ -148,6 +148,18 @@ #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) + +/* P9 CME Local Stop Interface Status Register */ +#define EX_PM_SISR 0x1204C +#define EX_PM_SISR_INST_C0 PPC_BIT(46) +#define EX_PM_SISR_INST_C1 PPC_BIT(47) + /************* XXXX Move these P8 only registers elswhere !!! ****************/