-
Notifications
You must be signed in to change notification settings - Fork 134
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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>
- Loading branch information
1 parent
6739c89
commit 6421fc5
Showing
8 changed files
with
243 additions
and
197 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
/* Copyright 2013-2018 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 p8_sbe_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 p8_sbe_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; | ||
p8_sbe_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; | ||
p8_sbe_dump_timer_ffdc(); | ||
} | ||
sbe_last_gen = gen; | ||
sbe_last_gen_stamp = mftb(); | ||
} | ||
|
||
prlog(PR_TRACE, "SLW: gen: %llx\n", gen); | ||
} | ||
|
||
bool p8_sbe_timer_ok(void) | ||
{ | ||
return sbe_has_timer; | ||
} | ||
|
||
void p8_sbe_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; | ||
} |
Oops, something went wrong.