Commit 7d170464 authored by Zong-Zhe Yang's avatar Zong-Zhe Yang Committed by Kalle Valo

wifi: rtw89: mcc: consider and determine BT duration

Before calculating MCC pattern, we have to determine whether to handle BT
duration in it or not. The decision will depend on the channels that Wi-Fi
roles use. And, we have three cases shown below.
1. non-2GHz + non-2GHz
2. non-2GHz + 2GHz (different band)
3. 2GHz + 2GHz (dual 2GHz)

For case (1), we don't care BT duration in MCC pattern. For case (2), we
still don't care BT duration in MCC pattern. Instead, we try to satisfy it
by modifying duration of Wi-Fi role on non-2GHz channel. For case (3), we
need to modify Wi-Fi durations and also need to handle BT duration in MCC
pattern.
Signed-off-by: default avatarZong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230831053133.24015-4-pkshih@realtek.com
parent 4dc25ef1
......@@ -703,6 +703,171 @@ static void rtw89_mcc_set_duration_gc_sta(struct rtw89_dev *rtwdev)
aux->duration = dur_aux;
}
struct rtw89_mcc_mod_dur_data {
u16 available;
struct {
u16 dur;
u16 room;
} parm[NUM_OF_RTW89_MCC_ROLES];
};
static int rtw89_mcc_mod_dur_get_iterator(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *mcc_role,
unsigned int ordered_idx,
void *data)
{
struct rtw89_mcc_mod_dur_data *p = data;
u16 min;
p->parm[ordered_idx].dur = mcc_role->duration;
if (mcc_role->is_go)
min = RTW89_MCC_MIN_GO_DURATION;
else
min = RTW89_MCC_MIN_STA_DURATION;
p->parm[ordered_idx].room = max_t(s32, p->parm[ordered_idx].dur - min, 0);
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC mod dur: chk role[%u]: dur %u, min %u, room %u\n",
ordered_idx, p->parm[ordered_idx].dur, min,
p->parm[ordered_idx].room);
p->available += p->parm[ordered_idx].room;
return 0;
}
static int rtw89_mcc_mod_dur_put_iterator(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *mcc_role,
unsigned int ordered_idx,
void *data)
{
struct rtw89_mcc_mod_dur_data *p = data;
mcc_role->duration = p->parm[ordered_idx].dur;
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC mod dur: set role[%u]: dur %u\n",
ordered_idx, p->parm[ordered_idx].dur);
return 0;
}
static void rtw89_mcc_mod_duration_dual_2ghz_with_bt(struct rtw89_dev *rtwdev)
{
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
struct rtw89_mcc_config *config = &mcc->config;
struct rtw89_mcc_mod_dur_data data = {};
u16 mcc_intvl = config->mcc_interval;
u16 bt_dur = mcc->bt_role.duration;
u16 wifi_dur;
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC mod dur (dual 2ghz): mcc_intvl %u, raw bt_dur %u\n",
mcc_intvl, bt_dur);
rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_mod_dur_get_iterator, &data);
bt_dur = clamp_t(u16, bt_dur, 1, data.available / 3);
wifi_dur = mcc_intvl - bt_dur;
if (data.parm[0].room <= data.parm[1].room) {
data.parm[0].dur -= min_t(u16, bt_dur / 2, data.parm[0].room);
data.parm[1].dur = wifi_dur - data.parm[0].dur;
} else {
data.parm[1].dur -= min_t(u16, bt_dur / 2, data.parm[1].room);
data.parm[0].dur = wifi_dur - data.parm[1].dur;
}
rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_mod_dur_put_iterator, &data);
rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC mod dur: set bt: dur %u\n", bt_dur);
mcc->bt_role.duration = bt_dur;
}
static
void rtw89_mcc_mod_duration_diff_band_with_bt(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *role_2ghz,
struct rtw89_mcc_role *role_non_2ghz)
{
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
struct rtw89_mcc_config *config = &mcc->config;
u16 dur_2ghz, dur_non_2ghz;
u16 bt_dur, mcc_intvl;
dur_2ghz = role_2ghz->duration;
dur_non_2ghz = role_non_2ghz->duration;
mcc_intvl = config->mcc_interval;
bt_dur = mcc->bt_role.duration;
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC mod dur (diff band): mcc_intvl %u, bt_dur %u\n",
mcc_intvl, bt_dur);
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC mod dur: check dur_2ghz %u, dur_non_2ghz %u\n",
dur_2ghz, dur_non_2ghz);
if (dur_non_2ghz >= bt_dur) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC mod dur: dur_non_2ghz is enough for bt\n");
return;
}
dur_non_2ghz = bt_dur;
dur_2ghz = mcc_intvl - dur_non_2ghz;
if (role_non_2ghz->limit.enable) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC mod dur: dur_non_2ghz is limited with max %u\n",
role_non_2ghz->limit.max_dur);
dur_non_2ghz = min(dur_non_2ghz, role_non_2ghz->limit.max_dur);
dur_2ghz = mcc_intvl - dur_non_2ghz;
}
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC mod dur: set dur_2ghz %u, dur_non_2ghz %u\n",
dur_2ghz, dur_non_2ghz);
role_2ghz->duration = dur_2ghz;
role_non_2ghz->duration = dur_non_2ghz;
}
static bool rtw89_mcc_duration_decision_on_bt(struct rtw89_dev *rtwdev)
{
struct rtw89_mcc_info *mcc = &rtwdev->mcc;
struct rtw89_mcc_role *ref = &mcc->role_ref;
struct rtw89_mcc_role *aux = &mcc->role_aux;
struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
if (!bt_role->duration)
return false;
if (ref->is_2ghz && aux->is_2ghz) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC dual roles are on 2GHz; consider BT duration\n");
rtw89_mcc_mod_duration_dual_2ghz_with_bt(rtwdev);
return true;
}
if (!ref->is_2ghz && !aux->is_2ghz) {
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC dual roles are not on 2GHz; ignore BT duration\n");
return false;
}
rtw89_debug(rtwdev, RTW89_DBG_CHAN,
"MCC one role is on 2GHz; modify another for BT duration\n");
if (ref->is_2ghz)
rtw89_mcc_mod_duration_diff_band_with_bt(rtwdev, ref, aux);
else
rtw89_mcc_mod_duration_diff_band_with_bt(rtwdev, aux, ref);
return false;
}
static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev,
struct rtw89_mcc_role *tgt,
struct rtw89_mcc_role *src,
......@@ -790,6 +955,7 @@ static int rtw89_mcc_fill_config(struct rtw89_dev *rtwdev)
struct rtw89_mcc_role *ref = &mcc->role_ref;
struct rtw89_mcc_role *aux = &mcc->role_aux;
struct rtw89_mcc_config *config = &mcc->config;
bool hdl_bt;
memset(config, 0, sizeof(*config));
......@@ -816,6 +982,9 @@ static int rtw89_mcc_fill_config(struct rtw89_dev *rtwdev)
return -EFAULT;
}
hdl_bt = rtw89_mcc_duration_decision_on_bt(rtwdev);
rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC handle bt: %d\n", hdl_bt);
rtw89_mcc_set_default_pattern(rtwdev);
return rtw89_mcc_fill_start_tsf(rtwdev);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment