From: Mehmet Fide <mehmet.fide@gmail.com>
To: Ping-Ke Shih <pkshih@realtek.com>
Cc: Bitterblue Smith <rtl8821cerfe2@gmail.com>,
linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org,
mehmet.fide@screeningeagle.com
Subject: [PATCH rtw-next v7 3/3] wifi: rtw88: time the countdown downloads from the TBTT
Date: Tue, 20 Oct 2026 22:47:12 +0200 [thread overview]
Message-ID: <20261020204712.3252023-4-mehmet.fide@gmail.com> (raw)
In-Reply-To: <20261020204712.3252023-1-mehmet.fide@gmail.com>
From: Mehmet Fide <mehmet.fide@screeningeagle.com>
The countdown downloads are queued one beacon interval apart, with no
relation to the TBTT. A download that runs late past the next TBTT
leaves a count out of the air.
Queue each download 10 ms after the next TBTT, read from the TSF, so it
may run late by almost a beacon interval; a later one is followed by
the next at once. A TSF jump, an IBSS merge or a reset, restarts the
schedule from the next TBTT.
A TBTT just before the start may already have sent the first count; it
is taken as the one that did, so no count is sent twice.
The USB chips raise no TBTT interrupt, so the TSF register is read. The
beaconing interface is always on port 0: rtw_core_port_switch() moves
an AP there, an IBSS runs alone.
Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---
Notes:
Changes in v7:
- new patch, from Ping-Ke's review of the countdown pacing in v6
drivers/net/wireless/realtek/rtw88/fw.c | 40 ++++++++++++++++++++---
drivers/net/wireless/realtek/rtw88/main.h | 2 +-
drivers/net/wireless/realtek/rtw88/reg.h | 1 +
3 files changed, 38 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c
index 2d81aaeed0d7..c5a106a59540 100644
--- a/drivers/net/wireless/realtek/rtw88/fw.c
+++ b/drivers/net/wireless/realtek/rtw88/fw.c
@@ -3,6 +3,7 @@
*/
#include <linux/iopoll.h>
+#include <linux/math64.h>
#include "main.h"
#include "coex.h"
@@ -1809,27 +1810,58 @@ bool rtw_fw_csa_active(struct rtw_dev *rtwdev)
return !!rtwdev->csa_vif;
}
-/* paced from the first download: a late one does not delay the next */
+#define RTW_CSA_TBTT_MARGIN_US 10000
+
+/* the beaconing interface is always on port 0 */
+static u64 rtw_fw_read_tsf(struct rtw_dev *rtwdev)
+{
+ u32 hi, lo;
+
+ do {
+ hi = rtw_read32(rtwdev, REG_TSFTR + 4);
+ lo = rtw_read32(rtwdev, REG_TSFTR);
+ } while (hi != rtw_read32(rtwdev, REG_TSFTR + 4));
+
+ return ((u64)hi << 32) | lo;
+}
+
static void rtw_fw_csa_queue(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
{
u32 interval = ieee80211_tu_to_usec(vif->bss_conf.beacon_int);
+ u64 tsf = rtw_fw_read_tsf(rtwdev);
s64 delay;
+ u32 rem;
- rtwdev->csa_due = ktime_add_us(rtwdev->csa_due, interval);
- delay = ktime_us_delta(rtwdev->csa_due, ktime_get());
+ rtwdev->csa_tbtt += interval;
+ delay = rtwdev->csa_tbtt + RTW_CSA_TBTT_MARGIN_US - tsf;
+ if (delay > interval + RTW_CSA_TBTT_MARGIN_US ||
+ delay < -(s64)interval) {
+ /* the TSF jumped: restart from the next TBTT */
+ div_u64_rem(tsf, interval, &rem);
+ rtwdev->csa_tbtt = tsf - rem + interval;
+ delay = rtwdev->csa_tbtt + RTW_CSA_TBTT_MARGIN_US - tsf;
+ }
ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->csa_beacon_work,
usecs_to_jiffies(max(delay, 0)));
}
void rtw_fw_csa_start(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
{
+ u32 interval = ieee80211_tu_to_usec(vif->bss_conf.beacon_int);
+ u32 rem;
+
lockdep_assert_held(&rtwdev->mutex);
if (rtwdev->csa_vif == vif)
return;
rtwdev->csa_vif = vif;
- rtwdev->csa_due = ktime_get();
+ rtwdev->csa_tbtt = rtw_fw_read_tsf(rtwdev);
+ div_u64_rem(rtwdev->csa_tbtt, interval, &rem);
+ rtwdev->csa_tbtt -= rem;
+ /* a TBTT that just passed may have sent the first count already */
+ if (rem < RTW_CSA_TBTT_MARGIN_US)
+ rtwdev->csa_tbtt -= interval;
rtw_fw_csa_queue(rtwdev, vif);
}
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index bc3ebfec11ae..3be0a96d1186 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -2096,7 +2096,7 @@ struct rtw_dev {
struct work_struct update_beacon_work;
struct delayed_work csa_beacon_work;
struct ieee80211_vif *csa_vif;
- ktime_t csa_due;
+ u64 csa_tbtt;
/* used to protect txqs list */
spinlock_t txq_lock;
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index afcdb66fdb9a..3ff4ae0885ef 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -506,6 +506,7 @@
#define REG_USTIME_TSF 0x055C
#define REG_BCN_MAX_ERR 0x055D
#define REG_RXTSF_OFFSET_CCK 0x055E
+#define REG_TSFTR 0x0560
#define REG_MISC_CTRL 0x0577
#define BIT_EN_FREE_CNT BIT(3)
#define BIT_DIS_SECOND_CCA (BIT(0) | BIT(1))
--
2.55.0
prev parent reply other threads:[~2026-10-20 20:47 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-20 20:47 [PATCH rtw-next v7 0/3] wifi: rtw88: channel switch in AP mode Mehmet Fide
2026-10-20 20:47 ` [PATCH rtw-next v7 1/3] wifi: rtw88: download the beacon the reserved page was built with Mehmet Fide
2026-10-20 20:47 ` [PATCH rtw-next v7 2/3] wifi: rtw88: support channel switch in AP mode Mehmet Fide
2026-10-20 20:47 ` Mehmet Fide [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261020204712.3252023-4-mehmet.fide@gmail.com \
--to=mehmet.fide@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=mehmet.fide@screeningeagle.com \
--cc=pkshih@realtek.com \
--cc=rtl8821cerfe2@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®