wifi: rtw89: mcc: track beacon offset and update when needed

In MCC STA+GC mode, the offset between TBTTs of remote AP and remote GO
might change. If the change is larger than tolerance, we should update
MCC after re-calculating parameters for new things. So, we track that in
rtw89_track_work() now. And, we add MCC update flow to tell FW either to
change durations of roles or to replace entire pattern according to how
MCC plans BT slot.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230908031145.20931-6-pkshih@realtek.com
This commit is contained in:
Zong-Zhe Yang 2023-09-08 11:11:42 +08:00 committed by Kalle Valo
parent 31e415e3d0
commit 5f69aabab1
5 changed files with 153 additions and 2 deletions

View File

@ -1297,7 +1297,7 @@ static int __mcc_fw_add_bt_role(struct rtw89_dev *rtwdev)
return 0;
}
static int __mcc_fw_start(struct rtw89_dev *rtwdev)
static int __mcc_fw_start(struct rtw89_dev *rtwdev, bool replace)
{
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
struct rtw89_mcc_role *ref = &mcc->role_ref;
@ -1308,6 +1308,12 @@ static int __mcc_fw_start(struct rtw89_dev *rtwdev)
struct rtw89_fw_mcc_start_req req = {};
int ret;
if (replace) {
req.old_group = mcc->group;
req.old_group_action = RTW89_FW_MCC_OLD_GROUP_ACT_REPLACE;
mcc->group = RTW89_MCC_NEXT_GROUP(mcc->group);
}
req.group = mcc->group;
switch (pattern->plan) {
@ -1376,6 +1382,47 @@ static int __mcc_fw_start(struct rtw89_dev *rtwdev)
return 0;
}
static int __mcc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_changed)
{
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
struct rtw89_mcc_config *config = &mcc->config;
struct rtw89_mcc_sync *sync = &config->sync;
struct rtw89_mcc_role *ref = &mcc->role_ref;
struct rtw89_mcc_role *aux = &mcc->role_aux;
struct rtw89_fw_mcc_duration req = {
.group = mcc->group,
.btc_in_group = false,
.start_macid = ref->rtwvif->mac_id,
.macid_x = ref->rtwvif->mac_id,
.macid_y = aux->rtwvif->mac_id,
.duration_x = ref->duration,
.duration_y = aux->duration,
.start_tsf_high = config->start_tsf >> 32,
.start_tsf_low = config->start_tsf,
};
int ret;
ret = rtw89_fw_h2c_mcc_set_duration(rtwdev, &req);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC h2c failed to set duration: %d\n", ret);
return ret;
}
if (!sync->enable || !sync_changed)
return 0;
ret = rtw89_fw_h2c_mcc_sync(rtwdev, mcc->group, sync->macid_src,
sync->macid_tgt, sync->offset);
if (ret) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC h2c failed to trigger sync: %d\n", ret);
return ret;
}
return 0;
}
static int rtw89_mcc_start(struct rtw89_dev *rtwdev)
{
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
@ -1407,7 +1454,7 @@ static int rtw89_mcc_start(struct rtw89_dev *rtwdev)
if (ret)
return ret;
ret = __mcc_fw_start(rtwdev);
ret = __mcc_fw_start(rtwdev, false);
if (ret)
return ret;
@ -1437,6 +1484,75 @@ static void rtw89_mcc_stop(struct rtw89_dev *rtwdev)
rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP);
}
static int rtw89_mcc_update(struct rtw89_dev *rtwdev)
{
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
struct rtw89_mcc_config *config = &mcc->config;
struct rtw89_mcc_config old_cfg = *config;
bool sync_changed;
int ret;
if (rtwdev->scanning)
rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC update\n");
ret = rtw89_mcc_fill_config(rtwdev);
if (ret)
return ret;
if (old_cfg.pattern.plan != RTW89_MCC_PLAN_NO_BT ||
config->pattern.plan != RTW89_MCC_PLAN_NO_BT) {
ret = __mcc_fw_start(rtwdev, true);
if (ret)
return ret;
} else {
if (memcmp(&old_cfg.sync, &config->sync, sizeof(old_cfg.sync)) == 0)
sync_changed = false;
else
sync_changed = true;
ret = __mcc_fw_set_duration_no_bt(rtwdev, sync_changed);
if (ret)
return ret;
}
return 0;
}
static void rtw89_mcc_track(struct rtw89_dev *rtwdev)
{
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
struct rtw89_mcc_config *config = &mcc->config;
struct rtw89_mcc_pattern *pattern = &config->pattern;
s16 tolerance;
u16 bcn_ofst;
u16 diff;
if (mcc->mode != RTW89_MCC_MODE_GC_STA)
return;
bcn_ofst = rtw89_mcc_get_bcn_ofst(rtwdev);
if (bcn_ofst > config->beacon_offset) {
diff = bcn_ofst - config->beacon_offset;
if (pattern->tob_aux < 0)
tolerance = -pattern->tob_aux;
else
tolerance = pattern->toa_aux;
} else {
diff = config->beacon_offset - bcn_ofst;
if (pattern->toa_aux < 0)
tolerance = -pattern->toa_aux;
else
tolerance = pattern->tob_aux;
}
if (diff <= tolerance)
return;
rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_BCN_OFFSET_CHANGE);
}
static int rtw89_mcc_upd_map_iterator(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *mcc_role,
unsigned int ordered_idx,
@ -1485,6 +1601,7 @@ void rtw89_chanctx_work(struct work_struct *work)
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
chanctx_work.work);
struct rtw89_hal *hal = &rtwdev->hal;
bool update_mcc_pattern = false;
enum rtw89_entity_mode mode;
u32 changed = 0;
int ret;
@ -1508,8 +1625,16 @@ void rtw89_chanctx_work(struct work_struct *work)
rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
break;
case RTW89_ENTITY_MODE_MCC:
if (changed & BIT(RTW89_CHANCTX_BCN_OFFSET_CHANGE))
update_mcc_pattern = true;
if (changed & BIT(RTW89_CHANCTX_REMOTE_STA_CHANGE))
rtw89_mcc_update_macid_bitmap(rtwdev);
if (update_mcc_pattern) {
ret = rtw89_mcc_update(rtwdev);
if (ret)
rtw89_warn(rtwdev, "failed to update MCC: %d\n",
ret);
}
break;
default:
break;
@ -1555,6 +1680,22 @@ void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev)
rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_CHANGE_DFLT);
}
void rtw89_chanctx_track(struct rtw89_dev *rtwdev)
{
enum rtw89_entity_mode mode;
lockdep_assert_held(&rtwdev->mutex);
mode = rtw89_get_entity_mode(rtwdev);
switch (mode) {
case RTW89_ENTITY_MODE_MCC:
rtw89_mcc_track(rtwdev);
break;
default:
break;
}
}
int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
struct ieee80211_chanctx_conf *ctx)
{

View File

@ -26,6 +26,8 @@
(RTW89_MCC_EARLY_RX_BCN_TIME + RTW89_MCC_MIN_RX_BCN_TIME)
#define RTW89_MCC_DFLT_GROUP 0
#define RTW89_MCC_NEXT_GROUP(cur) (((cur) + 1) % 4)
#define RTW89_MCC_DFLT_TX_NULL_EARLY 3
#define RTW89_MCC_DFLT_COURTESY_SLOT 3
@ -78,6 +80,7 @@ void rtw89_chanctx_work(struct work_struct *work);
void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev);
void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev,
enum rtw89_chanctx_changes change);
void rtw89_chanctx_track(struct rtw89_dev *rtwdev);
int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
struct ieee80211_chanctx_conf *ctx);
void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,

View File

@ -2722,6 +2722,7 @@ static void rtw89_track_work(struct work_struct *work)
rtw89_phy_antdiv_track(rtwdev);
rtw89_phy_ul_tb_ctrl_track(rtwdev);
rtw89_tas_track(rtwdev);
rtw89_chanctx_track(rtwdev);
if (rtwdev->lps_enabled && !rtwdev->btc.lps)
rtw89_enter_lps_track(rtwdev);

View File

@ -3789,6 +3789,7 @@ struct rtw89_chanctx_cfg {
enum rtw89_chanctx_changes {
RTW89_CHANCTX_REMOTE_STA_CHANGE,
RTW89_CHANCTX_BCN_OFFSET_CHANGE,
NUM_OF_RTW89_CHANCTX_CHANGES,
RTW89_CHANCTX_CHANGE_DFLT = NUM_OF_RTW89_CHANCTX_CHANGES,

View File

@ -2931,6 +2931,11 @@ static inline void RTW89_SET_FWCMD_ADD_MCC_COURTESY_TARGET(void *cmd, u32 val)
le32p_replace_bits((__le32 *)cmd + 3, val, GENMASK(23, 16));
}
enum rtw89_fw_mcc_old_group_actions {
RTW89_FW_MCC_OLD_GROUP_ACT_NONE = 0,
RTW89_FW_MCC_OLD_GROUP_ACT_REPLACE = 1,
};
struct rtw89_fw_mcc_start_req {
u32 group: 2;
u32 btc_in_group: 1;