mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 18:43:33 +02:00
wifi: rtw89: introduce rtw89_query_mr_chanctx_info() for multi-role chanctx info
Add Wi-Fi 7 MLO related multi-role (MR) chanctx descriptors and query function. They are designed for other components, e.g. coex, which are interested in the following info. * whether a MLD exists and how many active link * the number of AP mode and station mode respectively * how many chanctx and the number of 2/5/6 GHz respectively Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Link: https://patch.msgid.link/20250611035523.36432-2-pkshih@realtek.com
This commit is contained in:
parent
3db8563bac
commit
cbaf1110af
|
|
@ -2714,6 +2714,201 @@ void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev)
|
|||
rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_CHANGE_DFLT);
|
||||
}
|
||||
|
||||
static enum rtw89_mr_wtype __rtw89_query_mr_wtype(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
|
||||
enum rtw89_chanctx_idx chanctx_idx;
|
||||
struct ieee80211_vif *vif;
|
||||
struct rtw89_vif *rtwvif;
|
||||
unsigned int num_mld = 0;
|
||||
unsigned int num_ml = 0;
|
||||
unsigned int cnt = 0;
|
||||
u8 role_idx;
|
||||
u8 idx;
|
||||
|
||||
for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) {
|
||||
rtwvif = mgnt->active_roles[role_idx];
|
||||
if (!rtwvif)
|
||||
continue;
|
||||
|
||||
cnt++;
|
||||
|
||||
vif = rtwvif_to_vif(rtwvif);
|
||||
if (!ieee80211_vif_is_mld(vif))
|
||||
continue;
|
||||
|
||||
num_mld++;
|
||||
|
||||
for (idx = 0; idx < __RTW89_MLD_MAX_LINK_NUM; idx++) {
|
||||
chanctx_idx = mgnt->chanctx_tbl[role_idx][idx];
|
||||
if (chanctx_idx != RTW89_CHANCTX_IDLE)
|
||||
num_ml++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_mld > 1)
|
||||
goto err;
|
||||
|
||||
switch (cnt) {
|
||||
case 0:
|
||||
return RTW89_MR_WTYPE_NONE;
|
||||
case 1:
|
||||
if (!num_mld)
|
||||
return RTW89_MR_WTYPE_NONMLD;
|
||||
switch (num_ml) {
|
||||
case 1:
|
||||
return RTW89_MR_WTYPE_MLD1L1R;
|
||||
case 2:
|
||||
return RTW89_MR_WTYPE_MLD2L1R;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (!num_mld)
|
||||
return RTW89_MR_WTYPE_NONMLD_NONMLD;
|
||||
switch (num_ml) {
|
||||
case 1:
|
||||
return RTW89_MR_WTYPE_MLD1L1R_NONMLD;
|
||||
case 2:
|
||||
return RTW89_MR_WTYPE_MLD2L1R_NONMLD;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
err:
|
||||
rtw89_warn(rtwdev, "%s: unhandled cnt %u mld %u ml %u\n", __func__,
|
||||
cnt, num_mld, num_ml);
|
||||
return RTW89_MR_WTYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
static enum rtw89_mr_wmode __rtw89_query_mr_wmode(struct rtw89_dev *rtwdev,
|
||||
u8 inst_idx)
|
||||
{
|
||||
struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
|
||||
unsigned int num[NUM_NL80211_IFTYPES] = {};
|
||||
enum rtw89_chanctx_idx chanctx_idx;
|
||||
struct ieee80211_vif *vif;
|
||||
struct rtw89_vif *rtwvif;
|
||||
unsigned int cnt = 0;
|
||||
u8 role_idx;
|
||||
|
||||
if (unlikely(inst_idx >= __RTW89_MLD_MAX_LINK_NUM))
|
||||
return RTW89_MR_WMODE_UNKNOWN;
|
||||
|
||||
for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) {
|
||||
chanctx_idx = mgnt->chanctx_tbl[role_idx][inst_idx];
|
||||
if (chanctx_idx == RTW89_CHANCTX_IDLE)
|
||||
continue;
|
||||
|
||||
rtwvif = mgnt->active_roles[role_idx];
|
||||
if (unlikely(!rtwvif))
|
||||
continue;
|
||||
|
||||
vif = rtwvif_to_vif(rtwvif);
|
||||
num[vif->type]++;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
switch (cnt) {
|
||||
case 0:
|
||||
return RTW89_MR_WMODE_NONE;
|
||||
case 1:
|
||||
if (num[NL80211_IFTYPE_STATION])
|
||||
return RTW89_MR_WMODE_1CLIENT;
|
||||
if (num[NL80211_IFTYPE_AP])
|
||||
return RTW89_MR_WMODE_1AP;
|
||||
break;
|
||||
case 2:
|
||||
if (num[NL80211_IFTYPE_STATION] == 2)
|
||||
return RTW89_MR_WMODE_2CLIENTS;
|
||||
if (num[NL80211_IFTYPE_AP] == 2)
|
||||
return RTW89_MR_WMODE_2APS;
|
||||
if (num[NL80211_IFTYPE_STATION] && num[NL80211_IFTYPE_AP])
|
||||
return RTW89_MR_WMODE_1AP_1CLIENT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rtw89_warn(rtwdev, "%s: unhandled cnt %u\n", __func__, cnt);
|
||||
return RTW89_MR_WMODE_UNKNOWN;
|
||||
}
|
||||
|
||||
static enum rtw89_mr_ctxtype __rtw89_query_mr_ctxtype(struct rtw89_dev *rtwdev,
|
||||
u8 inst_idx)
|
||||
{
|
||||
struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
|
||||
DECLARE_BITMAP(map, NUM_OF_RTW89_CHANCTX) = {};
|
||||
unsigned int num[RTW89_BAND_NUM] = {};
|
||||
enum rtw89_chanctx_idx chanctx_idx;
|
||||
const struct rtw89_chan *chan;
|
||||
unsigned int cnt = 0;
|
||||
u8 role_idx;
|
||||
|
||||
if (unlikely(inst_idx >= __RTW89_MLD_MAX_LINK_NUM))
|
||||
return RTW89_MR_CTX_UNKNOWN;
|
||||
|
||||
for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) {
|
||||
chanctx_idx = mgnt->chanctx_tbl[role_idx][inst_idx];
|
||||
if (chanctx_idx == RTW89_CHANCTX_IDLE)
|
||||
continue;
|
||||
|
||||
if (__test_and_set_bit(chanctx_idx, map))
|
||||
continue;
|
||||
|
||||
chan = rtw89_chan_get(rtwdev, chanctx_idx);
|
||||
num[chan->band_type]++;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
switch (cnt) {
|
||||
case 0:
|
||||
return RTW89_MR_CTX_NONE;
|
||||
case 1:
|
||||
if (num[RTW89_BAND_2G])
|
||||
return RTW89_MR_CTX1_2GHZ;
|
||||
if (num[RTW89_BAND_5G])
|
||||
return RTW89_MR_CTX1_5GHZ;
|
||||
if (num[RTW89_BAND_6G])
|
||||
return RTW89_MR_CTX1_6GHZ;
|
||||
break;
|
||||
case 2:
|
||||
if (num[RTW89_BAND_2G] == 2)
|
||||
return RTW89_MR_CTX2_2GHZ;
|
||||
if (num[RTW89_BAND_5G] == 2)
|
||||
return RTW89_MR_CTX2_5GHZ;
|
||||
if (num[RTW89_BAND_6G] == 2)
|
||||
return RTW89_MR_CTX2_6GHZ;
|
||||
if (num[RTW89_BAND_2G] && num[RTW89_BAND_5G])
|
||||
return RTW89_MR_CTX2_2GHZ_5GHZ;
|
||||
if (num[RTW89_BAND_2G] && num[RTW89_BAND_6G])
|
||||
return RTW89_MR_CTX2_2GHZ_6GHZ;
|
||||
if (num[RTW89_BAND_5G] && num[RTW89_BAND_6G])
|
||||
return RTW89_MR_CTX2_5GHZ_6GHZ;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rtw89_warn(rtwdev, "%s: unhandled cnt %u\n", __func__, cnt);
|
||||
return RTW89_MR_CTX_UNKNOWN;
|
||||
}
|
||||
|
||||
void rtw89_query_mr_chanctx_info(struct rtw89_dev *rtwdev, u8 inst_idx,
|
||||
struct rtw89_mr_chanctx_info *info)
|
||||
{
|
||||
lockdep_assert_wiphy(rtwdev->hw->wiphy);
|
||||
|
||||
info->wtype = __rtw89_query_mr_wtype(rtwdev);
|
||||
info->wmode = __rtw89_query_mr_wmode(rtwdev, inst_idx);
|
||||
info->ctxtype = __rtw89_query_mr_ctxtype(rtwdev, inst_idx);
|
||||
}
|
||||
|
||||
void rtw89_chanctx_track(struct rtw89_dev *rtwdev)
|
||||
{
|
||||
struct rtw89_hal *hal = &rtwdev->hal;
|
||||
|
|
|
|||
|
|
@ -44,6 +44,49 @@
|
|||
|
||||
#define NUM_OF_RTW89_MCC_ROLES 2
|
||||
|
||||
enum rtw89_mr_wtype {
|
||||
RTW89_MR_WTYPE_NONE,
|
||||
RTW89_MR_WTYPE_NONMLD,
|
||||
RTW89_MR_WTYPE_MLD1L1R,
|
||||
RTW89_MR_WTYPE_MLD2L1R,
|
||||
RTW89_MR_WTYPE_MLD2L2R,
|
||||
RTW89_MR_WTYPE_NONMLD_NONMLD,
|
||||
RTW89_MR_WTYPE_MLD1L1R_NONMLD,
|
||||
RTW89_MR_WTYPE_MLD2L1R_NONMLD,
|
||||
RTW89_MR_WTYPE_MLD2L2R_NONMLD,
|
||||
RTW89_MR_WTYPE_UNKNOWN,
|
||||
};
|
||||
|
||||
enum rtw89_mr_wmode {
|
||||
RTW89_MR_WMODE_NONE,
|
||||
RTW89_MR_WMODE_1CLIENT,
|
||||
RTW89_MR_WMODE_1AP,
|
||||
RTW89_MR_WMODE_1AP_1CLIENT,
|
||||
RTW89_MR_WMODE_2CLIENTS,
|
||||
RTW89_MR_WMODE_2APS,
|
||||
RTW89_MR_WMODE_UNKNOWN,
|
||||
};
|
||||
|
||||
enum rtw89_mr_ctxtype {
|
||||
RTW89_MR_CTX_NONE,
|
||||
RTW89_MR_CTX1_2GHZ,
|
||||
RTW89_MR_CTX1_5GHZ,
|
||||
RTW89_MR_CTX1_6GHZ,
|
||||
RTW89_MR_CTX2_2GHZ,
|
||||
RTW89_MR_CTX2_5GHZ,
|
||||
RTW89_MR_CTX2_6GHZ,
|
||||
RTW89_MR_CTX2_2GHZ_5GHZ,
|
||||
RTW89_MR_CTX2_2GHZ_6GHZ,
|
||||
RTW89_MR_CTX2_5GHZ_6GHZ,
|
||||
RTW89_MR_CTX_UNKNOWN,
|
||||
};
|
||||
|
||||
struct rtw89_mr_chanctx_info {
|
||||
enum rtw89_mr_wtype wtype;
|
||||
enum rtw89_mr_wmode wmode;
|
||||
enum rtw89_mr_ctxtype ctxtype;
|
||||
};
|
||||
|
||||
enum rtw89_chanctx_pause_reasons {
|
||||
RTW89_CHANCTX_PAUSE_REASON_HW_SCAN,
|
||||
RTW89_CHANCTX_PAUSE_REASON_ROC,
|
||||
|
|
@ -120,6 +163,8 @@ void rtw89_chanctx_work(struct wiphy *wiphy, struct wiphy_work *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_query_mr_chanctx_info(struct rtw89_dev *rtwdev, u8 inst_idx,
|
||||
struct rtw89_mr_chanctx_info *info);
|
||||
void rtw89_chanctx_track(struct rtw89_dev *rtwdev);
|
||||
void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
|
||||
const struct rtw89_chanctx_pause_parm *parm);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user