[Skiboot] [PATCH 2/2] SBE: Rate limit timer requests

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Thu Dec 17 17:59:29 AEDT 2020

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 at linux.vnet.ibm.com>
 hw/sbe-p9.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/hw/sbe-p9.c b/hw/sbe-p9.c
index 75dc37aaa..63ff3cc80 100644
--- a/hw/sbe-p9.c
+++ b/hw/sbe-p9.c
@@ -91,6 +91,14 @@ static struct lock sbe_timer_lock;
 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.
+ */
+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 */
+	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);
@@ -791,6 +808,11 @@ static void p9_sbe_timer_schedule(void)
+	/* 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) {

More information about the Skiboot mailing list