@@ -1216,7 +1216,7 @@ static void slw_dump_timer_ffdc(void)
*/
void slw_update_timer_expiry(uint64_t new_target)
{
- uint64_t count, gen, gen2, req, now = mftb();
+ uint64_t count, gen, gen2, req, iter1, iter2, now = mftb();
int64_t rc;
if (!slw_has_timer || new_target == slw_timer_target)
@@ -1238,9 +1238,9 @@ void slw_update_timer_expiry(uint64_t new_target)
prlog(PR_TRACE, "SLW: TMR expiry: 0x%llx, req: %016llx\n", count, req);
- do {
+ for(iter2 = 0;; iter2++) {
/* Grab generation and spin if odd */
- for (;;) {
+ for (iter1 = 0;; iter1++) {
rc = xscom_read(slw_timer_chip, 0xE0006, &gen);
if (rc) {
prerror("SLW: Error %lld reading tmr gen "
@@ -1250,7 +1250,8 @@ void slw_update_timer_expiry(uint64_t new_target)
if (!(gen & 1))
break;
if (tb_compare(now + msecs_to_tb(1), mftb()) == TB_ABEFOREB) {
- prerror("SLW: Stuck with odd generation !\n");
+ prerror("SLW: Stuck with odd generation"
+ " for %lld iterations !\n", iter1);
slw_has_timer = false;
slw_dump_timer_ffdc();
return;
@@ -1270,7 +1271,22 @@ void slw_update_timer_expiry(uint64_t new_target)
" count\n", rc);
return;
}
- } while(gen != gen2);
+
+ /* Generation didn't change, bail out */
+ if (gen == gen2)
+ break;
+
+ if (iter2 > 100) {
+ prerror("SLW: %lld changes of generation in a loop, giving up !\n",
+ iter2);
+ slw_has_timer = false;
+ slw_dump_timer_ffdc();
+ return;
+ }
+
+ /* Timestamp */
+ now = mftb();
+ }
/* Check if the timer is working. If at least 1ms has elapsed
* since the last call to this function, check that the gen
Print the number of iterations trying to obtain an "even" value off the SLW. Don't account the time spent trying to get identical generations in the delay to get even values. Finally, add a max retry of 100 for generation changes happening in the loop and display the interation counts in all cases. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> --- hw/slw.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-)