diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/realtek/rtw89/mac.c | 44 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw89/mac.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/realtek/rtw89/reg.h | 17 |
3 files changed, 63 insertions, 0 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index d80050c2e9b3..a80690d0bf48 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -3913,6 +3913,49 @@ static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev, B_AX_TBTT_SHIFT_OFST_MASK, val); } +static void rtw89_mac_port_tsf_sync(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + struct rtw89_vif *rtwvif_src, u8 offset, + int *n_offset) +{ + u32 val, reg; + + if (rtwvif->net_type != RTW89_NET_TYPE_AP_MODE || rtwvif == rtwvif_src) + return; + + /* adjust offset randomly to avoid beacon conflict */ + offset = offset - offset / 4 + get_random_u32() % (offset / 2); + val = RTW89_PORT_OFFSET_MS_TO_32US((*n_offset)++, offset); + reg = rtw89_mac_reg_by_idx(R_AX_PORT0_TSF_SYNC + rtwvif->port * 4, + rtwvif->mac_idx); + + rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_SRC, rtwvif_src->port); + rtw89_write32_mask(rtwdev, reg, B_AX_SYNC_PORT_OFFSET_VAL, val); + rtw89_write32_set(rtwdev, reg, B_AX_SYNC_NOW); +} + +static void rtw89_mac_port_tsf_resync_all(struct rtw89_dev *rtwdev) +{ + struct rtw89_vif *src = NULL, *tmp; + u8 offset = 100, vif_aps = 0; + int n_offset = 1; + + rtw89_for_each_rtwvif(rtwdev, tmp) { + if (!src || tmp->net_type == RTW89_NET_TYPE_INFRA) + src = tmp; + if (tmp->net_type == RTW89_NET_TYPE_AP_MODE) + vif_aps++; + } + + if (vif_aps == 0) + return; + + offset /= (vif_aps + 1); + + rtw89_for_each_rtwvif(rtwdev, tmp) + rtw89_mac_port_tsf_sync(rtwdev, tmp, src, offset, &n_offset); +} + int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) { int ret; @@ -3991,6 +4034,7 @@ int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif); rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif); rtw89_mac_port_cfg_func_en(rtwdev, rtwvif); + rtw89_mac_port_tsf_resync_all(rtwdev); fsleep(BCN_ERLY_SET_DLY); rtw89_mac_port_cfg_bcn_early(rtwdev, rtwvif); diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index adb0c86a98d3..766ca6934d33 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -168,6 +168,8 @@ enum rtw89_mac_ax_l0_to_l1_event { MAC_AX_L0_TO_L1_EVENT_MAX = 15, }; +#define RTW89_PORT_OFFSET_MS_TO_32US(n, shift_ms) ((n) * (shift_ms) * 1000 / 32) + enum rtw89_mac_dbg_port_sel { /* CMAC 0 related */ RTW89_DBG_PORT_SEL_PTCL_C0 = 0, diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index f2634062f377..5324e645728b 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -2048,6 +2048,23 @@ #define B_AX_PTCL_TOP_ERR_IND BIT(1) #define B_AX_SCHEDULE_TOP_ERR_IND BIT(0) +#define R_AX_PORT0_TSF_SYNC 0xC2A0 +#define R_AX_PORT0_TSF_SYNC_C1 0xE2A0 +#define R_AX_PORT1_TSF_SYNC 0xC2A4 +#define R_AX_PORT1_TSF_SYNC_C1 0xE2A4 +#define R_AX_PORT2_TSF_SYNC 0xC2A8 +#define R_AX_PORT2_TSF_SYNC_C1 0xE2A8 +#define R_AX_PORT3_TSF_SYNC 0xC2AC +#define R_AX_PORT3_TSF_SYNC_C1 0xE2AC +#define R_AX_PORT4_TSF_SYNC 0xC2B0 +#define R_AX_PORT4_TSF_SYNC_C1 0xE2B0 +#define B_AX_SYNC_NOW BIT(30) +#define B_AX_SYNC_ONCE BIT(29) +#define B_AX_SYNC_AUTO BIT(28) +#define B_AX_SYNC_PORT_SRC GENMASK(26, 24) +#define B_AX_SYNC_PORT_OFFSET_SIGN BIT(18) +#define B_AX_SYNC_PORT_OFFSET_VAL GENMASK(17, 0) + #define R_AX_MACID_SLEEP_0 0xC2C0 #define R_AX_MACID_SLEEP_0_C1 0xE2C0 #define B_AX_MACID31_0_SLEEP_SH 0 |