diff options
author | Vasant Hegde <hegdevasant@linux.vnet.ibm.com> | 2018-04-23 12:15:31 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.ibm.com> | 2018-04-30 19:04:42 -0500 |
commit | 6421fc56dc289c8d14a1ce9eddbb88d3687fbb77 (patch) | |
tree | 1e62f2f3795e0476f092107d76a68b1a432e7394 /hw/slw.c | |
parent | 6739c890a2f298ed382b9557840a493fb97df44b (diff) | |
download | skiboot-6421fc56dc289c8d14a1ce9eddbb88d3687fbb77.zip skiboot-6421fc56dc289c8d14a1ce9eddbb88d3687fbb77.tar.gz skiboot-6421fc56dc289c8d14a1ce9eddbb88d3687fbb77.tar.bz2 |
Move P8 timer code to separate file
Lets move P8 timer support code from slw.c to sbe-p8.c (as suggested
by BenH). 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@kernel.crashing.org>
Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'hw/slw.c')
-rw-r--r-- | hw/slw.c | 185 |
1 files changed, 2 insertions, 183 deletions
@@ -30,6 +30,7 @@ #include <libfdt/libfdt.h> #include <opal-api.h> #include <nvram.h> +#include <sbe-p8.h> #include <p9_stop_api.H> #include <p8_pore_table_gen_api.H> @@ -44,14 +45,6 @@ static bool slw_current_le = false; enum wakeup_engine_states wakeup_engine_state = WAKEUP_ENGINE_NOT_PRESENT; bool has_deep_states = 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); @@ -1582,180 +1575,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; @@ -1772,7 +1591,7 @@ void slw_init(void) if (wakeup_engine_state == WAKEUP_ENGINE_PRESENT) slw_late_init_p8(chip); } - slw_init_timer(); + p8_sbe_init_timer(); } else if (proc_gen == proc_gen_p9) { for_each_chip(chip) { slw_init_chip_p9(chip); |