[Skiboot] [PATCH v5 3/5] Move P8 timer code to separate file
Vasant Hegde
hegdevasant at linux.vnet.ibm.com
Sun Jul 23 21:30:48 AEST 2017
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 <benh at kernel.crashing.org>
Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
core/interrupts.c | 5 +-
core/timer.c | 9 +--
hw/Makefile.inc | 2 +-
hw/sbe-p8.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/slw.c | 185 +------------------------------------------------
include/sbe-p8.h | 28 ++++++++
include/skiboot.h | 6 --
7 files changed, 242 insertions(+), 196 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 9161960..439e1fb 100644
--- a/core/interrupts.c
+++ b/core/interrupts.c
@@ -25,6 +25,7 @@
#include <device.h>
#include <ccan/str/str.h>
#include <timer.h>
+#include <sbe-p8.h>
/* ICP registers */
#define ICP_XIRR 0x4 /* 32-bit access */
@@ -468,8 +469,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 4b5925f..cb4d07b 100644
--- a/core/timer.c
+++ b/core/timer.c
@@ -4,6 +4,7 @@
#include <fsp.h>
#include <device.h>
#include <opal.h>
+#include <sbe-p8.h>
#ifdef __TEST__
#define this_cpu() ((void *)-1)
@@ -109,7 +110,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)
@@ -166,7 +167,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;
}
@@ -256,7 +257,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
@@ -264,7 +265,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 f22f0e8..0c1786d 100644
--- a/hw/Makefile.inc
+++ b/hw/Makefile.inc
@@ -7,7 +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 += phys-map.o sbe-p9.o capp.o
+HW_OBJS += phys-map.o sbe-p8.o sbe-p9.o capp.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 <device.h>
+#include <sbe-p8.h>
+#include <skiboot.h>
+#include <timebase.h>
+#include <xscom.h>
+
+/* 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 c0ab9de..9bced3d 100644
--- a/hw/slw.c
+++ b/hw/slw.c
@@ -29,6 +29,7 @@
#include <errorlog.h>
#include <libfdt/libfdt.h>
#include <opal-api.h>
+#include <sbe-p8.h>
#include <p8_pore_table_gen_api.H>
#include <sbe_xip_image.h>
@@ -39,14 +40,6 @@ static uint32_t slw_saved_reset[MAX_RESET_PATCH_SIZE];
static bool slw_current_le = false;
-/* 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);
@@ -1334,180 +1327,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);
-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;
@@ -1515,7 +1334,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..b0b617d
--- /dev/null
+++ b/include/sbe-p8.h
@@ -0,0 +1,28 @@
+/* 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 1a153b0..3f4a87a 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -286,12 +286,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);
--
2.9.3
More information about the Skiboot
mailing list