aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVasant Hegde <hegdevasant@linux.vnet.ibm.com>2020-12-17 12:29:29 +0530
committerVasant Hegde <hegdevasant@linux.vnet.ibm.com>2020-12-18 12:08:47 +0530
commit2e654443050acdd4deffdbb44723a847ca11e6b2 (patch)
treef6137c3758d78df6e160ee5543d16ada4f1cfd1f
parent47ab3a92298e72e44b9477a02b1312a09272a54a (diff)
downloadskiboot-2e654443050acdd4deffdbb44723a847ca11e6b2.zip
skiboot-2e654443050acdd4deffdbb44723a847ca11e6b2.tar.gz
skiboot-2e654443050acdd4deffdbb44723a847ca11e6b2.tar.bz2
SBE: Rate limit timer requests
We schedule timer and wait for `timer expiry` interrupt from SBE. If we get new timer request which is lesser than inflight timer expiry value we can update timer (essentially sending new timer chip-op and SBE takes care of stoping inflight timer and scheduling new one). SBE runs at much slower speed than host CPU. If we do continuous timer update like below then SBE will be busy with handling PSU side timer message and will not get time to handle FIFO side requests. send timer chip-op -> Got ACK -> send timer chip-op Hence this patch limits number of continuous timer update and we will restart sending timer request as soon as we get timer expiry interrupt. Rate limit value (2) is suggested by SBE team. With this patch: If our timer requests are : 2ms, 1500us, 1000us and 800us (and requests are coming after sending each message) We will schedule timer for 2ms and then update timer for 1500us and 1000us (These update happens after getting ACK interrupt from SBE) We will not send 800us request. At 1000us we get `timer expiry` and we are good to send next timer requests (At this stage both 1000us and 800us timeout happens. We will schedule next timer request with timeout value 500us (1500-1000)). Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
-rw-r--r--hw/sbe-p9.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/hw/sbe-p9.c b/hw/sbe-p9.c
index 75dc37a..63ff3cc 100644
--- a/hw/sbe-p9.c
+++ b/hw/sbe-p9.c
@@ -91,6 +91,14 @@ static struct lock sbe_timer_lock;
#define SBE_TIMER_DEFAULT_US 500
static uint64_t sbe_timer_def_tb;
+/*
+ * Rate limit continuous timer update.
+ * We can update inflight timer if new timer request is lesser than inflight
+ * one. Limit such updates so that SBE gets time to handle FIFO side requests.
+ */
+#define SBE_TIMER_UPDATE_MAX 2
+static uint32_t timer_update_cnt = 0;
+
/* Timer control message */
static struct p9_sbe_msg *timer_ctrl_msg;
@@ -530,6 +538,15 @@ static void p9_sbe_timer_response(struct p9_sbe *sbe)
sbe_timer_in_progress = false;
/* Drop lock and call timers */
unlock(&sbe->lock);
+
+ lock(&sbe_timer_lock);
+ /*
+ * Once we get timer expiry interrupt (even if its suprious interrupt)
+ * we can schedule next timer request.
+ */
+ timer_update_cnt = 0;
+ unlock(&sbe_timer_lock);
+
check_timers(true);
lock(&sbe->lock);
}
@@ -791,6 +808,11 @@ static void p9_sbe_timer_schedule(void)
return;
}
+ /* Stop sending timer update chipop until inflight timer expires */
+ if (timer_update_cnt > SBE_TIMER_UPDATE_MAX)
+ return;
+ timer_update_cnt++;
+
if (now < sbe_timer_target) {
/* Calculate how many microseconds from now, rounded up */
if ((sbe_timer_target - now) > sbe_timer_def_tb) {