fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bts/+/42855?usp=email )
Change subject: osmo-bts-trx: fix spurious clock skew shutdown after self-compensation ......................................................................
osmo-bts-trx: fix spurious clock skew shutdown after self-compensation
When the BTS runs ahead of the transceiver (elapsed_fn < 0), trx_sched_clock() reschedules the timerfd to deliberately delay the next FN. osmo_timerfd_schedule() resets the timerfd and discards any accumulated expirations, but last_fn_timer.tv was left pointing at the previous callback. The next trx_fn_timer_cb() then measures elapsed_us all the way back to that previous callback - spanning the deliberate delay (or any OS stall that preceded us) - and falsely trips the "PC clock skew too high" check, shutting the BTS down for no good reason.
Advance last_fn_timer.tv to the projected firing time of the rescheduled timer so that the next callback measures roughly one FN interval, as expected.
Change-Id: Icdb7db8abe70258ae008d9514b6608bd74bb2881 AI-Assisted: yes (Claude) Related: OS#6794 --- M src/osmo-bts-trx/scheduler_trx.c 1 file changed, 10 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/55/42855/1
diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c index 105ad38..a12ac3f 100644 --- a/src/osmo-bts-trx/scheduler_trx.c +++ b/src/osmo-bts-trx/scheduler_trx.c @@ -603,13 +603,20 @@ /* too many frames have been processed already */ if (elapsed_fn < 0) { struct timespec first = interval; - /* set clock to the time or last FN should have been - * transmitted. */ + /* set clock to the time our next FN has to be transmitted */ first.tv_nsec += (0 - elapsed_fn) * GSM_TDMA_FN_DURATION_nS; normalize_timespec(&first); LOGP(DL1C, LOGL_NOTICE, "We were %d FN faster than TRX, compensating\n", -elapsed_fn); - /* set time to the time our next FN has to be transmitted */ osmo_timerfd_schedule(&tcs->fn_timer_ofd, &first, &interval); + /* Advance last_fn_timer.tv to the projected firing time of the rescheduled + * timer (shifted back one interval). osmo_timerfd_schedule() resets the + * timerfd, discarding any accumulated expirations, so without this update + * trx_fn_timer_cb() would measure elapsed_us all the way back to the previous + * callback — spanning the deliberate delay or any OS stall that preceded us — + * and falsely trip the clock skew threshold. */ + tcs->last_fn_timer.tv = tv_now; + tcs->last_fn_timer.tv.tv_nsec += (0 - elapsed_fn) * GSM_TDMA_FN_DURATION_nS; + normalize_timespec(&tcs->last_fn_timer.tv); return 0; }