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:
parent
31e415e3d0
commit
5f69aabab1
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user