From patchwork Tue Apr 18 08:53:30 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasant Hegde X-Patchwork-Id: 751740 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 3w6f8k5DTFz9ryv for ; Tue, 18 Apr 2017 18:55:02 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3w6f8k4TczzDqBQ for ; Tue, 18 Apr 2017 18:55:02 +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 3w6f7y2lGszDq9L for ; Tue, 18 Apr 2017 18:54:22 +1000 (AEST) Received: from pps.filterd (m0098417.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v3I8regD024931 for ; Tue, 18 Apr 2017 04:54:14 -0400 Received: from e28smtp07.in.ibm.com (e28smtp07.in.ibm.com [125.16.236.7]) by mx0a-001b2d01.pphosted.com with ESMTP id 29w0kh0336-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 18 Apr 2017 04:54:14 -0400 Received: from localhost by e28smtp07.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 18 Apr 2017 14:23:40 +0530 Received: from d28relay10.in.ibm.com (9.184.220.161) by e28smtp07.in.ibm.com (192.168.1.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 18 Apr 2017 14:23:38 +0530 Received: from d28av03.in.ibm.com (d28av03.in.ibm.com [9.184.220.65]) by d28relay10.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v3I8qDkG18743548 for ; Tue, 18 Apr 2017 14:22:13 +0530 Received: from d28av03.in.ibm.com (localhost [127.0.0.1]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id v3I8rZDO000557 for ; Tue, 18 Apr 2017 14:23:36 +0530 Received: from hegdevasant.in.ibm.com ([9.109.223.130]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id v3I8rY0Y000529; Tue, 18 Apr 2017 14:23:35 +0530 From: Vasant Hegde To: skiboot@lists.ozlabs.org Date: Tue, 18 Apr 2017 14:23:30 +0530 X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170418085332.9558-1-hegdevasant@linux.vnet.ibm.com> References: <20170418085332.9558-1-hegdevasant@linux.vnet.ibm.com> X-TM-AS-MML: disable x-cbid: 17041808-0024-0000-0000-000003CD42A5 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17041808-0025-0000-0000-0000114C054D Message-Id: <20170418085332.9558-4-hegdevasant@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-04-18_06:, , 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-1702020001 definitions=main-1704180074 Subject: [Skiboot] [PATCH v4 3/5] Move P8 timer code to separate file 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: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Lets move P8 timer support code from slw.c to sbe-p8.c (as suggested by Ben). There is a difference between timer support in P8 and P9. Hence I think it makes sense to name it as sbe-p8.c Note that this is pure code movement and renaming functions/variables. No functionality changes. Suggested-by: Benjamin Herrenschmidt Signed-off-by: Vasant Hegde --- core/interrupts.c | 5 +- core/timer.c | 9 +-- hw/Makefile.inc | 1 + hw/sbe-p8.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ hw/slw.c | 185 +------------------------------------------------ include/sbe-p8.h | 29 ++++++++ include/skiboot.h | 6 -- 7 files changed, 243 insertions(+), 195 deletions(-) create mode 100644 hw/sbe-p8.c create mode 100644 include/sbe-p8.h diff --git a/core/interrupts.c b/core/interrupts.c index 006d555..ce1df95 100644 --- a/core/interrupts.c +++ b/core/interrupts.c @@ -25,6 +25,7 @@ #include #include #include +#include /* ICP registers */ #define ICP_XIRR 0x4 /* 32-bit access */ @@ -456,8 +457,8 @@ static int64_t opal_handle_interrupt(uint32_t isn, __be64 *outstanding_event_mas /* Run it */ is->ops->interrupt(is, isn); - /* Check timers if SLW timer isn't working */ - if (!slw_timer_ok()) + /* Check timers if SBE timer isn't working */ + if (!sbe_p8_timer_ok()) check_timers(true); /* Update output events */ diff --git a/core/timer.c b/core/timer.c index 7548996..2b4c921 100644 --- a/core/timer.c +++ b/core/timer.c @@ -4,6 +4,7 @@ #include #include #include +#include #ifdef __TEST__ #define this_cpu() ((void *)-1) @@ -106,7 +107,7 @@ static void __schedule_timer_at(struct timer *t, uint64_t when) /* Pick up the next timer and upddate the SBE HW timer */ lt = list_top(&timer_list, struct timer, link); if (lt) - slw_update_timer_expiry(lt->target); + sbe_p8_update_timer_expiry(lt->target); } void schedule_timer_at(struct timer *t, uint64_t when) @@ -163,7 +164,7 @@ static void __check_poll_timers(uint64_t now) * arbitrarily 1us. */ if (t->running) { - slw_update_timer_expiry(now + usecs_to_tb(1)); + sbe_p8_update_timer_expiry(now + usecs_to_tb(1)); break; } @@ -253,7 +254,7 @@ void late_init_timers(void) * * If a platform quirk exists, use that, else use the default. * - * If we have an SLW timer facility, we run this 10 times slower, + * If we have an SBE timer facility, we run this 10 times slower, * we could possibly completely get rid of it. * * We use a value in milliseconds, we don't want this to ever be @@ -261,7 +262,7 @@ void late_init_timers(void) */ if (platform.heartbeat_time) { heartbeat = platform.heartbeat_time(); - } else if (slw_timer_ok() || fsp_present()) { + } else if (sbe_p8_timer_ok() || fsp_present()) { heartbeat = HEARTBEAT_DEFAULT_MS * 10; } diff --git a/hw/Makefile.inc b/hw/Makefile.inc index b0a8b7c..1c48ab9 100644 --- a/hw/Makefile.inc +++ b/hw/Makefile.inc @@ -7,6 +7,7 @@ HW_OBJS += p7ioc.o p7ioc-inits.o p7ioc-phb.o HW_OBJS += phb3.o sfc-ctrl.o fake-rtc.o bt.o p8-i2c.o prd.o HW_OBJS += dts.o lpc-rtc.o npu.o npu-hw-procedures.o xive.o phb4.o HW_OBJS += fake-nvram.o lpc-mbox.o npu2.o npu2-hw-procedures.o +HW_OBJS += sbe-p8.o HW=hw/built-in.o # FIXME hack this for now diff --git a/hw/sbe-p8.c b/hw/sbe-p8.c new file mode 100644 index 0000000..6edb117 --- /dev/null +++ b/hw/sbe-p8.c @@ -0,0 +1,203 @@ +/* Copyright 2013-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 +#include +#include +#include +#include + +/* SLW timer related stuff */ +static bool sbe_has_timer; +static uint64_t sbe_timer_inc; +static uint64_t sbe_timer_target; +static uint32_t sbe_timer_chip; +static uint64_t sbe_last_gen; +static uint64_t sbe_last_gen_stamp; + +static void sbe_p8_dump_timer_ffdc(void) +{ + uint64_t i, val; + int64_t rc; + + static const uint32_t dump_regs[] = { + 0xe0000, 0xe0001, 0xe0002, 0xe0003, + 0xe0004, 0xe0005, 0xe0006, 0xe0007, + 0xe0008, 0xe0009, 0xe000a, 0xe000b, + 0xe000c, 0xe000d, 0xe000e, 0xe000f, + 0xe0010, 0xe0011, 0xe0012, 0xe0013, + 0xe0014, 0xe0015, 0xe0016, 0xe0017, + 0xe0018, 0xe0019, + 0x5001c, + 0x50038, 0x50039, 0x5003a, 0x5003b + }; + + /** + * @fwts-label SLWRegisterDump + * @fwts-advice An error condition occurred in sleep/winkle + * engines timer state machine. Dumping debug information to + * root-cause. OPAL/skiboot may be stuck on some operation that + * requires SLW timer state machine (e.g. core powersaving) + */ + prlog(PR_DEBUG, "SLW: Register state:\n"); + + for (i = 0; i < ARRAY_SIZE(dump_regs); i++) { + uint32_t reg = dump_regs[i]; + rc = xscom_read(sbe_timer_chip, reg, &val); + if (rc) { + prlog(PR_DEBUG, "SLW: XSCOM error %lld reading" + " reg 0x%x\n", rc, reg); + break; + } + prlog(PR_DEBUG, "SLW: %5x = %016llx\n", reg, val); + } +} + +/* This is called with the timer lock held, so there is no + * issue with re-entrancy or concurrence + */ +void sbe_p8_update_timer_expiry(uint64_t new_target) +{ + uint64_t count, gen, gen2, req, now = mftb(); + int64_t rc; + + if (!sbe_has_timer || new_target == sbe_timer_target) + return; + + sbe_timer_target = new_target; + + /* Calculate how many increments from now, rounded up */ + if (now < new_target) + count = (new_target - now + sbe_timer_inc - 1) / sbe_timer_inc; + else + count = 1; + + /* Max counter is 24-bit */ + if (count > 0xffffff) + count = 0xffffff; + /* Fabricate update request */ + req = (1ull << 63) | (count << 32); + + prlog(PR_TRACE, "SLW: TMR expiry: 0x%llx, req: %016llx\n", count, req); + + do { + /* Grab generation and spin if odd */ + _xscom_lock(); + for (;;) { + rc = _xscom_read(sbe_timer_chip, 0xE0006, &gen, false); + if (rc) { + prerror("SLW: Error %lld reading tmr gen " + " count\n", rc); + _xscom_unlock(); + return; + } + if (!(gen & 1)) + break; + if (tb_compare(now + msecs_to_tb(1), mftb()) == TB_ABEFOREB) { + /** + * @fwts-label SLWTimerStuck + * @fwts-advice The SLeep/Winkle Engine (SLW) + * failed to increment the generation number + * within our timeout period (it *should* have + * done so within ~10us, not >1ms. OPAL uses + * the SLW timer to schedule some operations, + * but can fall back to the (much less frequent + * OPAL poller, which although does not affect + * functionality, runs *much* less frequently. + * This could have the effect of slow I2C + * operations (for example). It may also mean + * that you *had* an increase in jitter, due + * to slow interactions with SLW. + * This error may also occur if the machine + * is connected to via soft FSI. + */ + prerror("SLW: timer stuck, falling back to OPAL pollers. You will likely have slower I2C and may have experienced increased jitter.\n"); + prlog(PR_DEBUG, "SLW: Stuck with odd generation !\n"); + _xscom_unlock(); + sbe_has_timer = false; + sbe_p8_dump_timer_ffdc(); + return; + } + } + + rc = _xscom_write(sbe_timer_chip, 0x5003A, req, false); + if (rc) { + prerror("SLW: Error %lld writing tmr request\n", rc); + _xscom_unlock(); + return; + } + + /* Re-check gen count */ + rc = _xscom_read(sbe_timer_chip, 0xE0006, &gen2, false); + if (rc) { + prerror("SLW: Error %lld re-reading tmr gen " + " count\n", rc); + _xscom_unlock(); + return; + } + _xscom_unlock(); + } while(gen != gen2); + + /* Check if the timer is working. If at least 1ms has elapsed + * since the last call to this function, check that the gen + * count has changed + */ + if (tb_compare(sbe_last_gen_stamp + msecs_to_tb(1), now) + == TB_ABEFOREB) { + if (sbe_last_gen == gen) { + prlog(PR_ERR, + "SLW: Timer appears to not be running !\n"); + sbe_has_timer = false; + sbe_p8_dump_timer_ffdc(); + } + sbe_last_gen = gen; + sbe_last_gen_stamp = mftb(); + } + + prlog(PR_TRACE, "SLW: gen: %llx\n", gen); +} + +bool sbe_p8_timer_ok(void) +{ + return sbe_has_timer; +} + +void sbe_p8_init_timer(void) +{ + struct dt_node *np; + int64_t rc; + uint32_t tick_us; + + np = dt_find_compatible_node(dt_root, NULL, "ibm,power8-sbe-timer"); + if (!np) + return; + + sbe_timer_chip = dt_get_chip_id(np); + tick_us = dt_prop_get_u32(np, "tick-time-us"); + sbe_timer_inc = usecs_to_tb(tick_us); + sbe_timer_target = ~0ull; + + rc = xscom_read(sbe_timer_chip, 0xE0006, &sbe_last_gen); + if (rc) { + prerror("SLW: Error %lld reading tmr gen count\n", rc); + return; + } + sbe_last_gen_stamp = mftb(); + + prlog(PR_INFO, "SLW: Timer facility on chip %d, resolution %dus\n", + sbe_timer_chip, tick_us); + sbe_has_timer = true; +} diff --git a/hw/slw.c b/hw/slw.c index 6503fa7..a32526a 100644 --- a/hw/slw.c +++ b/hw/slw.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef __HAVE_LIBPORE__ #include @@ -41,14 +42,6 @@ static uint32_t slw_saved_reset[MAX_RESET_PATCH_SIZE]; static bool slw_current_le = false; #endif /* __HAVE_LIBPORE__ */ -/* SLW timer related stuff */ -static bool slw_has_timer; -static uint64_t slw_timer_inc; -static uint64_t slw_timer_target; -static uint32_t slw_timer_chip; -static uint64_t slw_last_gen; -static uint64_t slw_last_gen_stamp; - DEFINE_LOG_ENTRY(OPAL_RC_SLW_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_SLW, OPAL_PLATFORM_FIRMWARE, OPAL_PREDICTIVE_ERR_GENERAL, OPAL_NA); @@ -1358,180 +1351,6 @@ int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val) opal_call(OPAL_SLW_SET_REG, opal_slw_set_reg, 3); #endif /* __HAVE_LIBPORE__ */ -static void slw_dump_timer_ffdc(void) -{ - uint64_t i, val; - int64_t rc; - - static const uint32_t dump_regs[] = { - 0xe0000, 0xe0001, 0xe0002, 0xe0003, - 0xe0004, 0xe0005, 0xe0006, 0xe0007, - 0xe0008, 0xe0009, 0xe000a, 0xe000b, - 0xe000c, 0xe000d, 0xe000e, 0xe000f, - 0xe0010, 0xe0011, 0xe0012, 0xe0013, - 0xe0014, 0xe0015, 0xe0016, 0xe0017, - 0xe0018, 0xe0019, - 0x5001c, - 0x50038, 0x50039, 0x5003a, 0x5003b - }; - - /** - * @fwts-label SLWRegisterDump - * @fwts-advice An error condition occurred in sleep/winkle - * engines timer state machine. Dumping debug information to - * root-cause. OPAL/skiboot may be stuck on some operation that - * requires SLW timer state machine (e.g. core powersaving) - */ - prlog(PR_DEBUG, "SLW: Register state:\n"); - - for (i = 0; i < ARRAY_SIZE(dump_regs); i++) { - uint32_t reg = dump_regs[i]; - rc = xscom_read(slw_timer_chip, reg, &val); - if (rc) { - prlog(PR_DEBUG, "SLW: XSCOM error %lld reading" - " reg 0x%x\n", rc, reg); - break; - } - prlog(PR_DEBUG, "SLW: %5x = %016llx\n", reg, val); - } -} - -/* This is called with the timer lock held, so there is no - * issue with re-entrancy or concurrence - */ -void slw_update_timer_expiry(uint64_t new_target) -{ - uint64_t count, gen, gen2, req, now = mftb(); - int64_t rc; - - if (!slw_has_timer || new_target == slw_timer_target) - return; - - slw_timer_target = new_target; - - /* Calculate how many increments from now, rounded up */ - if (now < new_target) - count = (new_target - now + slw_timer_inc - 1) / slw_timer_inc; - else - count = 1; - - /* Max counter is 24-bit */ - if (count > 0xffffff) - count = 0xffffff; - /* Fabricate update request */ - req = (1ull << 63) | (count << 32); - - prlog(PR_TRACE, "SLW: TMR expiry: 0x%llx, req: %016llx\n", count, req); - - do { - /* Grab generation and spin if odd */ - _xscom_lock(); - for (;;) { - rc = _xscom_read(slw_timer_chip, 0xE0006, &gen, false); - if (rc) { - prerror("SLW: Error %lld reading tmr gen " - " count\n", rc); - _xscom_unlock(); - return; - } - if (!(gen & 1)) - break; - if (tb_compare(now + msecs_to_tb(1), mftb()) == TB_ABEFOREB) { - /** - * @fwts-label SLWTimerStuck - * @fwts-advice The SLeep/Winkle Engine (SLW) - * failed to increment the generation number - * within our timeout period (it *should* have - * done so within ~10us, not >1ms. OPAL uses - * the SLW timer to schedule some operations, - * but can fall back to the (much less frequent - * OPAL poller, which although does not affect - * functionality, runs *much* less frequently. - * This could have the effect of slow I2C - * operations (for example). It may also mean - * that you *had* an increase in jitter, due - * to slow interactions with SLW. - * This error may also occur if the machine - * is connected to via soft FSI. - */ - prerror("SLW: timer stuck, falling back to OPAL pollers. You will likely have slower I2C and may have experienced increased jitter.\n"); - prlog(PR_DEBUG, "SLW: Stuck with odd generation !\n"); - _xscom_unlock(); - slw_has_timer = false; - slw_dump_timer_ffdc(); - return; - } - } - - rc = _xscom_write(slw_timer_chip, 0x5003A, req, false); - if (rc) { - prerror("SLW: Error %lld writing tmr request\n", rc); - _xscom_unlock(); - return; - } - - /* Re-check gen count */ - rc = _xscom_read(slw_timer_chip, 0xE0006, &gen2, false); - if (rc) { - prerror("SLW: Error %lld re-reading tmr gen " - " count\n", rc); - _xscom_unlock(); - return; - } - _xscom_unlock(); - } while(gen != gen2); - - /* Check if the timer is working. If at least 1ms has elapsed - * since the last call to this function, check that the gen - * count has changed - */ - if (tb_compare(slw_last_gen_stamp + msecs_to_tb(1), now) - == TB_ABEFOREB) { - if (slw_last_gen == gen) { - prlog(PR_ERR, - "SLW: Timer appears to not be running !\n"); - slw_has_timer = false; - slw_dump_timer_ffdc(); - } - slw_last_gen = gen; - slw_last_gen_stamp = mftb(); - } - - prlog(PR_TRACE, "SLW: gen: %llx\n", gen); -} - -bool slw_timer_ok(void) -{ - return slw_has_timer; -} - -static void slw_init_timer(void) -{ - struct dt_node *np; - int64_t rc; - uint32_t tick_us; - - np = dt_find_compatible_node(dt_root, NULL, "ibm,power8-sbe-timer"); - if (!np) - return; - - slw_timer_chip = dt_get_chip_id(np); - tick_us = dt_prop_get_u32(np, "tick-time-us"); - slw_timer_inc = usecs_to_tb(tick_us); - slw_timer_target = ~0ull; - - rc = xscom_read(slw_timer_chip, 0xE0006, &slw_last_gen); - if (rc) { - prerror("SLW: Error %lld reading tmr gen count\n", rc); - return; - } - slw_last_gen_stamp = mftb(); - - prlog(PR_INFO, "SLW: Timer facility on chip %d, resolution %dus\n", - slw_timer_chip, tick_us); - slw_has_timer = true; -} - void slw_init(void) { struct proc_chip *chip; @@ -1539,7 +1358,7 @@ void slw_init(void) if (proc_gen == proc_gen_p8) { for_each_chip(chip) slw_init_chip(chip); - slw_init_timer(); + sbe_p8_init_timer(); } else if (proc_gen == proc_gen_p9) { for_each_chip(chip) slw_init_chip_p9(chip); diff --git a/include/sbe-p8.h b/include/sbe-p8.h new file mode 100644 index 0000000..a30cb34 --- /dev/null +++ b/include/sbe-p8.h @@ -0,0 +1,29 @@ +/* Copyright 2013-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 __SBE_P8_H +#define __SBE_P8_H + +/* P8 SBE update timer function */ +extern void sbe_p8_update_timer_expiry(uint64_t new_target); + +/* Is SBE timer available ? */ +extern bool sbe_p8_timer_ok(void); + +/* Initialize SBE timer */ +extern void sbe_p8_init_timer(void); + +#endif /* __SBE_P8_H */ diff --git a/include/skiboot.h b/include/skiboot.h index 2b1f8a5..eb05951 100644 --- a/include/skiboot.h +++ b/include/skiboot.h @@ -284,12 +284,6 @@ extern void *create_dtb(const struct dt_node *root, bool exclusive); /* SLW reinit function for switching core settings */ extern int64_t slw_reinit(uint64_t flags); -/* SLW update timer function */ -extern void slw_update_timer_expiry(uint64_t new_target); - -/* Is SLW timer available ? */ -extern bool slw_timer_ok(void); - /* Patch SPR in SLW image */ extern int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val);