aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2025-01-14 21:46:47 +1000
committerReza Arbab <arbab@linux.ibm.com>2025-01-24 12:26:16 -0600
commitc7c569f9cb477fc5587907da4cc8b2bfaa8181b4 (patch)
tree81a5d0414eb1d71cbd02eb5ff6ef9569a0d6b76f
parentf1841f0c5b21dc581f26678a370ef9912bfbfa49 (diff)
downloadskiboot-c7c569f9cb477fc5587907da4cc8b2bfaa8181b4.zip
skiboot-c7c569f9cb477fc5587907da4cc8b2bfaa8181b4.tar.gz
skiboot-c7c569f9cb477fc5587907da4cc8b2bfaa8181b4.tar.bz2
hw/sbe-p9: Change SBE lagging detection
Disabling the SBE timer entirely is counter-productive: the SBE interrupt can be delayed for a number of reasons including booting or OS bugs, and there is no other timer to replace it. If the SBE timer is detected to be lagging, increase polling rate until it fires but keep it running. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Reza Arbab <arbab@linux.ibm.com>
-rw-r--r--core/interrupts.c2
-rw-r--r--core/test/run-timer.c5
-rw-r--r--core/timer.c4
-rw-r--r--hw/sbe-p8.c3
-rw-r--r--hw/sbe-p9.c16
-rw-r--r--hw/sbe.c8
-rw-r--r--include/sbe.h4
7 files changed, 31 insertions, 11 deletions
diff --git a/core/interrupts.c b/core/interrupts.c
index 03a37b2..667ab76 100644
--- a/core/interrupts.c
+++ b/core/interrupts.c
@@ -501,7 +501,7 @@ static int64_t opal_handle_interrupt(uint32_t isn, __be64 *outstanding_event_mas
/* Run it */
is->ops->interrupt(is, isn);
- /* Check timers if SBE timer isn't working */
+ /* Check timers if SBE timer isn't working well */
if (!sbe_timer_ok())
check_timers(true);
diff --git a/core/test/run-timer.c b/core/test/run-timer.c
index 4e540ca..a9b6c85 100644
--- a/core/test/run-timer.c
+++ b/core/test/run-timer.c
@@ -66,6 +66,11 @@ bool sbe_timer_ok(void)
return true;
}
+bool sbe_timer_present(void)
+{
+ return true;
+}
+
int main(void)
{
unsigned int i;
diff --git a/core/timer.c b/core/timer.c
index 6655a8c..b8a0249 100644
--- a/core/timer.c
+++ b/core/timer.c
@@ -54,7 +54,7 @@ static inline void this_cpu_set_running_timer(bool running)
static inline void update_timer_expiry(uint64_t target)
{
- if (sbe_timer_ok())
+ if (sbe_timer_present())
sbe_update_timer_expiry(target);
}
@@ -313,7 +313,7 @@ void late_init_timers(void)
*/
if (platform.heartbeat_time) {
heartbeat = platform.heartbeat_time();
- } else if (sbe_timer_ok()) {
+ } else if (sbe_timer_present()) {
heartbeat = HEARTBEAT_DEFAULT_MS * 10;
}
diff --git a/hw/sbe-p8.c b/hw/sbe-p8.c
index c2cf5d2..2d82e7d 100644
--- a/hw/sbe-p8.c
+++ b/hw/sbe-p8.c
@@ -121,6 +121,7 @@ void p8_sbe_update_timer_expiry(uint64_t new_target)
prlog(PR_DEBUG, "SLW: Stuck with odd generation !\n");
_xscom_unlock();
sbe_has_timer = false;
+ sbe_timer_good = false;
p8_sbe_dump_timer_ffdc();
return;
}
@@ -154,6 +155,7 @@ void p8_sbe_update_timer_expiry(uint64_t new_target)
prlog(PR_ERR,
"SLW: Timer appears to not be running !\n");
sbe_has_timer = false;
+ sbe_timer_good = false;
p8_sbe_dump_timer_ffdc();
}
sbe_last_gen = gen;
@@ -191,4 +193,5 @@ void p8_sbe_init_timer(void)
prlog(PR_INFO, "SLW: Timer facility on chip %d, resolution %dus\n",
sbe_timer_chip, tick_us);
sbe_has_timer = true;
+ sbe_timer_good = true;
}
diff --git a/hw/sbe-p9.c b/hw/sbe-p9.c
index 3d9e622..ec2ad3d 100644
--- a/hw/sbe-p9.c
+++ b/hw/sbe-p9.c
@@ -538,6 +538,10 @@ static void p9_sbe_timer_response(struct p9_sbe *sbe)
if (sbe->chip_id != sbe_default_chip_id)
return;
+ if (!sbe_timer_good) {
+ sbe_timer_good = true;
+ prlog_once(PR_WARNING, "Lagging timer fired, decreasing polling rate.\n");
+ }
sbe_timer_in_progress = false;
/* Drop lock and call timers */
unlock(&sbe->lock);
@@ -686,19 +690,16 @@ static void p9_sbe_timer_poll(struct p9_sbe *sbe)
if (sbe->chip_id != sbe_default_chip_id)
return;
- if (!sbe_has_timer || !sbe_timer_in_progress)
+ if (!sbe_timer_good || !sbe_timer_in_progress)
return;
if (tb_compare(mftb(), sbe_last_gen_stamp + msecs_to_tb(10))
!= TB_AAFTERB)
return;
- prlog(PR_ERR, "Timer stuck, falling back to OPAL pollers.\n");
- prlog(PR_ERR, "You will likely have slower I2C and may have "
- "experienced increased jitter.\n");
- p9_sbe_reg_dump(sbe->chip_id);
- sbe_has_timer = false;
- sbe_timer_in_progress = false;
+ sbe_timer_good = false;
+
+ prlog_once(PR_WARNING, "Timer is lagging, increasing polling rate.\n");
}
static void p9_sbe_timeout_poll_one(struct p9_sbe *sbe)
@@ -960,6 +961,7 @@ static void p9_sbe_timer_init(void)
assert(timer_ctrl_msg);
init_lock(&sbe_timer_lock);
sbe_has_timer = true;
+ sbe_timer_good = true;
sbe_timer_target = ~0ull;
sbe_last_gen_stamp = ~0ull;
sbe_timer_def_tb = usecs_to_tb(SBE_TIMER_DEFAULT_US);
diff --git a/hw/sbe.c b/hw/sbe.c
index 8595816..56927bf 100644
--- a/hw/sbe.c
+++ b/hw/sbe.c
@@ -13,10 +13,11 @@
#include <stdbool.h>
bool sbe_has_timer = false;
+bool sbe_timer_good = false;
void sbe_update_timer_expiry(uint64_t target)
{
- assert(sbe_timer_ok);
+ assert(sbe_has_timer);
if (proc_gen == proc_gen_p9 || proc_gen == proc_gen_p10)
p9_sbe_update_timer_expiry(target);
@@ -29,5 +30,10 @@ void sbe_update_timer_expiry(uint64_t target)
bool sbe_timer_ok(void)
{
+ return sbe_timer_good;
+}
+
+bool sbe_timer_present(void)
+{
return sbe_has_timer;
}
diff --git a/include/sbe.h b/include/sbe.h
index 24d21fa..d5f844b 100644
--- a/include/sbe.h
+++ b/include/sbe.h
@@ -10,8 +10,12 @@
extern void sbe_update_timer_expiry(uint64_t target);
/* Is SBE timer available ? */
+extern bool sbe_timer_present(void);
+
+/* Is SBE timer keeping good time ? */
extern bool sbe_timer_ok(void);
extern bool sbe_has_timer;
+extern bool sbe_timer_good;
#endif /* __SBE_P9_H */