/******************************************************************************
|
*
|
* Copyright(c) 2007 - 2017 Realtek Corporation.
|
*
|
* This program is free software; you can redistribute it and/or modify it
|
* under the terms of version 2 of the GNU General Public License as
|
* published by the Free Software Foundation.
|
*
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
* more details.
|
*
|
*****************************************************************************/
|
#define _RTW_HE_C
|
|
#include <drv_types.h>
|
|
#ifdef CONFIG_80211AX_HE
|
|
/* for now cover BW 20/40/80/160 bounded in 2SS */
|
const u16 HE_MCS_DATA_RATE[CHANNEL_WIDTH_MAX][MAX_HE_GI_TYPE][MAX_HE_MCS_INDEX] = {
|
{ /* 20M */
|
{ /* 3.2us */
|
14, 29, 43, 58, 87, 117, 131, 146, 175, 195, 219, 243,
|
29, 58, 87, 117, 175, 234, 263, 292, 351, 390, 438, 487,
|
},
|
{ /* 1.6us */
|
16, 32, 48, 65, 97, 130, 146, 162, 195, 216, 243, 270,
|
32, 65, 97, 130, 195, 260, 292, 325, 390, 433, 487, 541,
|
},
|
{ /* 0.8us */
|
17, 34, 51, 68, 103, 137, 154, 172, 206, 229, 258, 286,
|
34, 68, 103, 137, 206, 275, 309, 344, 413, 458, 516, 573,
|
}
|
},
|
{ /* 40M */
|
{ /* 3.2us */
|
29, 58, 87, 117, 175, 234, 263, 292, 351, 390, 438, 487,
|
58, 117, 175, 234, 351, 468, 526, 585, 702, 780, 877, 975,
|
},
|
{ /* 1.6us */
|
32, 65, 97, 130, 195, 260, 292, 325, 390, 433, 487, 541,
|
65, 130, 195, 260, 390, 520, 585, 650, 780, 866, 975, 1083,
|
},
|
{ /* 0.8us */
|
34, 68, 103, 138, 206, 275, 309, 344, 413, 458, 516, 573,
|
68, 137, 206, 275, 413, 550, 619, 688, 825, 917, 1032, 1147,
|
}
|
},
|
{ /* 80M */
|
{ /* 3.2us */
|
61, 122, 183, 245, 367, 490, 551, 612, 735, 816, 918, 1020,
|
122, 245, 367, 490, 735, 980, 1102, 1225, 1470, 1633, 1839, 2041,
|
},
|
{ /* 1.6us */
|
68, 136, 204, 272, 408, 544, 612, 680, 816, 907, 1020, 1134,
|
136, 272, 408, 544, 816, 1088, 1225, 1361, 1633, 1814, 2041, 2268,
|
},
|
{ /* 0.8us */
|
72, 144, 216, 288, 432, 576, 648, 720, 864, 960, 1080, 1200,
|
144, 288, 432, 576, 864, 1153, 1297, 1441, 1729, 1921, 2161, 2402,
|
}
|
},
|
{ /* 160M */
|
{ /* 3.2us */
|
123, 245, 368, 490, 735, 980, 1103, 1225, 1470, 1633, 1838, 2042,
|
245, 490, 735, 980, 1470, 1960, 2205, 2450, 2940, 3267, 3675, 4083,
|
},
|
{ /* 1.6us */
|
136, 272, 408, 544, 817, 1089, 1225, 1361, 1633, 1815, 2042, 2269,
|
272, 544, 817, 1089, 1633, 2178, 2450, 2722, 3267, 3630, 4083, 4537,
|
},
|
{ /* 0.8us */
|
144, 288, 432, 576, 865, 1153, 1297, 1441, 1729, 1922, 2162, 2402,
|
288, 576, 865, 1153, 1729, 2306, 2594, 2882, 3459, 3843, 4324, 4804,
|
}
|
}
|
};
|
|
u16 rtw_he_mcs_to_data_rate(u8 bw, u8 guard_int, u8 he_mcs_rate)
|
{
|
u8 gi = 2; /* use 0.8us GI since 2XLTF_0.8us GI is mandatory in HE */
|
u8 mcs_idx = he_mcs_rate - MGN_HE1SS_MCS0;
|
|
return HE_MCS_DATA_RATE[bw][gi][mcs_idx];
|
}
|
|
u8 rtw_he_get_highest_rate(u8 *he_mcs_map)
|
{
|
u8 i, j;
|
u8 bit_map;
|
u8 he_mcs_rate = 0;
|
|
/* currently only consider the BW 80M */
|
for (i = 0; i < 2; i++) {
|
if (he_mcs_map[i] != 0xff) {
|
/* max to 4SS, each SS contains 2 bit */
|
for (j = 0; j < 8; j += 2) {
|
bit_map = (he_mcs_map[i] >> j) & 3;
|
|
if (bit_map != 3)
|
he_mcs_rate = MGN_HE1SS_MCS7 + 12 * j / 2 + i * 48 + 2 * bit_map;
|
}
|
}
|
}
|
|
/*RTW_INFO("####### HighestHEMCSRate is %x\n", he_mcs_rate);*/
|
return he_mcs_rate;
|
}
|
|
void rtw_he_use_default_setting(_adapter *padapter, struct _ADAPTER_LINK *padapter_link)
|
{
|
struct link_mlme_priv *pmlmepriv = &padapter_link->mlmepriv;
|
struct protocol_cap_t *role_cap = &(padapter_link->wrlink->protocol_cap);
|
struct he_priv *phepriv = &pmlmepriv->hepriv;
|
|
phepriv->he_highest_rate = rtw_he_get_highest_rate(role_cap->he_rx_mcs);
|
}
|
|
void rtw_he_set_asoc_cap_supp_mcs(_adapter *padapter, struct rtw_phl_stainfo_t *phl_sta, u8 *ele_start, u8 supp_mcs_len)
|
{
|
struct rtw_wifi_role_t *wrole = padapter->phl_role;
|
struct protocol_cap_t *role_cap = &(phl_sta->rlink->protocol_cap);
|
int nss = 0, nss_tx = 0, nss_rx = 0;
|
u8 mcs_from_role = HE_MSC_NOT_SUPP;
|
u8 mcs_from_ie = HE_MSC_NOT_SUPP;
|
u8 mcs_val_rx = HE_MSC_NOT_SUPP;
|
u8 mcs_val_tx = HE_MSC_NOT_SUPP;
|
struct registry_priv *pregistrypriv = &padapter->registrypriv;
|
|
_rtw_memset(phl_sta->asoc_cap.he_rx_mcs, HE_MSC_NOT_SUPP_BYTE, HE_CAP_ELE_SUPP_MCS_LEN_RX_80M);
|
_rtw_memset(phl_sta->asoc_cap.he_tx_mcs, HE_MSC_NOT_SUPP_BYTE, HE_CAP_ELE_SUPP_MCS_LEN_TX_80M);
|
_rtw_memset(phl_sta->asoc_cap.he_rx_mcs + 2, HE_MSC_NOT_SUPP_BYTE, HE_CAP_ELE_SUPP_MCS_LEN_RX_160M);
|
_rtw_memset(phl_sta->asoc_cap.he_tx_mcs + 2, HE_MSC_NOT_SUPP_BYTE, HE_CAP_ELE_SUPP_MCS_LEN_TX_160M);
|
_rtw_memset(phl_sta->asoc_cap.he_rx_mcs + 4, HE_MSC_NOT_SUPP_BYTE, HE_CAP_ELE_SUPP_MCS_LEN_RX_80M_80M);
|
_rtw_memset(phl_sta->asoc_cap.he_tx_mcs + 4, HE_MSC_NOT_SUPP_BYTE, HE_CAP_ELE_SUPP_MCS_LEN_TX_80M_80M);
|
|
/* only deal with <= 80MHz & 160M now (ToDo 80M+80M)*/
|
for (nss = 1; nss <= 8; nss++) {
|
|
mcs_val_rx = HE_MSC_NOT_SUPP;
|
mcs_val_tx = HE_MSC_NOT_SUPP;
|
|
switch (nss) {
|
case 1:
|
mcs_from_role = GET_HE_CAP_MCS_1SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_LESS_THAN_80MHZ_1SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_1SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_LESS_THAN_80MHZ_1SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_1SS(phl_sta->asoc_cap.he_rx_mcs, mcs_val_rx);
|
SET_HE_CAP_MCS_1SS(phl_sta->asoc_cap.he_tx_mcs, mcs_val_tx);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) &&
|
((phl_sta->chandef.band == BAND_ON_5G && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) ||
|
(phl_sta->chandef.band == BAND_ON_6G && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)))
|
) {
|
mcs_from_role = GET_HE_CAP_MCS_1SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_160MHZ_1SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_1SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_160MHZ_1SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_1SS(phl_sta->asoc_cap.he_rx_mcs + 2, mcs_val_rx);
|
SET_HE_CAP_MCS_1SS(phl_sta->asoc_cap.he_tx_mcs + 2, mcs_val_tx);
|
}
|
break;
|
case 2:
|
mcs_from_role = GET_HE_CAP_MCS_2SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_LESS_THAN_80MHZ_2SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_2SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_LESS_THAN_80MHZ_2SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_2SS(phl_sta->asoc_cap.he_rx_mcs, mcs_val_rx);
|
SET_HE_CAP_MCS_2SS(phl_sta->asoc_cap.he_tx_mcs, mcs_val_tx);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) &&
|
((phl_sta->chandef.band == BAND_ON_5G && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) ||
|
(phl_sta->chandef.band == BAND_ON_6G && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)))
|
) {
|
mcs_from_role = GET_HE_CAP_MCS_2SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_160MHZ_2SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_2SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_160MHZ_2SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_2SS(phl_sta->asoc_cap.he_rx_mcs + 2, mcs_val_rx);
|
SET_HE_CAP_MCS_2SS(phl_sta->asoc_cap.he_tx_mcs + 2, mcs_val_tx);
|
}
|
break;
|
case 3:
|
mcs_from_role = GET_HE_CAP_MCS_3SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_LESS_THAN_80MHZ_3SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_3SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_LESS_THAN_80MHZ_3SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_3SS(phl_sta->asoc_cap.he_rx_mcs, mcs_val_rx);
|
SET_HE_CAP_MCS_3SS(phl_sta->asoc_cap.he_tx_mcs, mcs_val_tx);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) &&
|
((phl_sta->chandef.band == BAND_ON_5G && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) ||
|
(phl_sta->chandef.band == BAND_ON_6G && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)))
|
) {
|
mcs_from_role = GET_HE_CAP_MCS_3SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_160MHZ_3SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_3SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_160MHZ_3SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_3SS(phl_sta->asoc_cap.he_rx_mcs + 2, mcs_val_rx);
|
SET_HE_CAP_MCS_3SS(phl_sta->asoc_cap.he_tx_mcs + 2, mcs_val_tx);
|
}
|
break;
|
case 4:
|
mcs_from_role = GET_HE_CAP_MCS_4SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_LESS_THAN_80MHZ_4SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_4SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_LESS_THAN_80MHZ_4SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_4SS(phl_sta->asoc_cap.he_rx_mcs, mcs_val_rx);
|
SET_HE_CAP_MCS_4SS(phl_sta->asoc_cap.he_tx_mcs, mcs_val_tx);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) &&
|
((phl_sta->chandef.band == BAND_ON_5G && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) ||
|
(phl_sta->chandef.band == BAND_ON_6G && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)))
|
) {
|
mcs_from_role = GET_HE_CAP_MCS_4SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_160MHZ_4SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_4SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_160MHZ_4SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_4SS(phl_sta->asoc_cap.he_rx_mcs + 2, mcs_val_rx);
|
SET_HE_CAP_MCS_4SS(phl_sta->asoc_cap.he_tx_mcs + 2, mcs_val_tx);
|
}
|
break;
|
case 5:
|
mcs_from_role = GET_HE_CAP_MCS_5SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_LESS_THAN_80MHZ_5SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_5SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_LESS_THAN_80MHZ_5SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_5SS(phl_sta->asoc_cap.he_rx_mcs, mcs_val_rx);
|
SET_HE_CAP_MCS_5SS(phl_sta->asoc_cap.he_tx_mcs, mcs_val_tx);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) &&
|
((phl_sta->chandef.band == BAND_ON_5G && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) ||
|
(phl_sta->chandef.band == BAND_ON_6G && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)))
|
) {
|
mcs_from_role = GET_HE_CAP_MCS_5SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_160MHZ_5SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_5SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_160MHZ_5SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_5SS(phl_sta->asoc_cap.he_rx_mcs + 2, mcs_val_rx);
|
SET_HE_CAP_MCS_5SS(phl_sta->asoc_cap.he_tx_mcs + 2, mcs_val_tx);
|
}
|
break;
|
case 6:
|
mcs_from_role = GET_HE_CAP_MCS_6SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_LESS_THAN_80MHZ_6SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_6SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_LESS_THAN_80MHZ_6SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_6SS(phl_sta->asoc_cap.he_rx_mcs, mcs_val_rx);
|
SET_HE_CAP_MCS_6SS(phl_sta->asoc_cap.he_tx_mcs, mcs_val_tx);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) &&
|
((phl_sta->chandef.band == BAND_ON_5G && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) ||
|
(phl_sta->chandef.band == BAND_ON_6G && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)))
|
) {
|
mcs_from_role = GET_HE_CAP_MCS_6SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_160MHZ_6SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_6SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_160MHZ_6SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_6SS(phl_sta->asoc_cap.he_rx_mcs + 2, mcs_val_rx);
|
SET_HE_CAP_MCS_6SS(phl_sta->asoc_cap.he_tx_mcs + 2, mcs_val_tx);
|
}
|
break;
|
case 7:
|
mcs_from_role = GET_HE_CAP_MCS_7SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_LESS_THAN_80MHZ_7SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_7SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_LESS_THAN_80MHZ_7SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_7SS(phl_sta->asoc_cap.he_rx_mcs, mcs_val_rx);
|
SET_HE_CAP_MCS_7SS(phl_sta->asoc_cap.he_tx_mcs, mcs_val_tx);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) &&
|
((phl_sta->chandef.band == BAND_ON_5G && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) ||
|
(phl_sta->chandef.band == BAND_ON_6G && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)))
|
) {
|
mcs_from_role = GET_HE_CAP_MCS_7SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_160MHZ_7SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_7SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_160MHZ_7SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_7SS(phl_sta->asoc_cap.he_rx_mcs + 2, mcs_val_rx);
|
SET_HE_CAP_MCS_7SS(phl_sta->asoc_cap.he_tx_mcs + 2, mcs_val_tx);
|
}
|
break;
|
case 8:
|
mcs_from_role = GET_HE_CAP_MCS_8SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_LESS_THAN_80MHZ_8SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_8SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_LESS_THAN_80MHZ_8SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_8SS(phl_sta->asoc_cap.he_rx_mcs, mcs_val_rx);
|
SET_HE_CAP_MCS_8SS(phl_sta->asoc_cap.he_tx_mcs, mcs_val_tx);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) &&
|
((phl_sta->chandef.band == BAND_ON_5G && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) ||
|
(phl_sta->chandef.band == BAND_ON_6G && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)))
|
) {
|
mcs_from_role = GET_HE_CAP_MCS_8SS(role_cap->he_tx_mcs);
|
mcs_from_ie = GET_HE_CAP_RX_MCS_160MHZ_8SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_rx = (mcs_from_role < mcs_from_ie) ? mcs_from_role : mcs_from_ie;
|
|
mcs_from_role = GET_HE_CAP_MCS_8SS(role_cap->he_rx_mcs);
|
mcs_from_ie = GET_HE_CAP_TX_MCS_160MHZ_8SS(ele_start);
|
if ((mcs_from_role != HE_MSC_NOT_SUPP) && (mcs_from_ie != HE_MSC_NOT_SUPP))
|
mcs_val_tx = mcs_from_ie;
|
|
SET_HE_CAP_MCS_8SS(phl_sta->asoc_cap.he_rx_mcs + 2, mcs_val_rx);
|
SET_HE_CAP_MCS_8SS(phl_sta->asoc_cap.he_tx_mcs + 2, mcs_val_tx);
|
}
|
break;
|
}
|
|
if (mcs_val_rx != HE_MSC_NOT_SUPP)
|
nss_rx++;
|
|
if (mcs_val_tx != HE_MSC_NOT_SUPP)
|
nss_tx++;
|
}
|
|
phl_sta->asoc_cap.nss_rx = nss_rx;
|
phl_sta->asoc_cap.nss_tx = nss_tx;
|
}
|
|
static void rtw_he_set_asoc_cap_ppe_thre(_adapter *padapter, struct rtw_phl_stainfo_t *phl_sta, u8 *ele_start)
|
{
|
u8 nsts, rumsk, i, j, offset, shift;
|
u16 ppe8, ppe16;
|
|
if (phl_sta->asoc_cap.pkt_padding != 3)
|
return;
|
|
nsts = GET_HE_CAP_PPE_NSTS(ele_start);
|
rumsk = GET_HE_CAP_PPE_PU_IDX_BITMASK(ele_start);
|
shift = 7;
|
|
for (i = 0; i <= nsts; i ++) {
|
for (j = 0; j < 4; j++) {
|
if (rumsk & (BIT(0) << j)) {
|
offset = shift / 8;
|
ppe16 = LE_BITS_TO_2BYTE(ele_start + offset, shift % 8, 3);
|
shift += 3;
|
offset = shift / 8;
|
ppe8 = LE_BITS_TO_2BYTE(ele_start + offset, shift % 8, 3);
|
shift += 3;
|
phl_sta->asoc_cap.ppe_thr[i][j] = ((ppe16 & 0x07) | ((ppe8 & 0x07) << 3));
|
} else {
|
phl_sta->asoc_cap.ppe_thr[i][j] = 0;
|
}
|
}
|
}
|
}
|
|
static void update_sta_he_mac_cap_apmode(_adapter *padapter, struct rtw_phl_stainfo_t *phl_sta, u8 *ele_start)
|
{
|
/* CONFIG_80211AX_HE_TODO - we may need to refer to role_cap when setting some of asoc_cap */
|
#if 0
|
struct rtw_wifi_role_t *wrole = padapter->phl_role;
|
struct protocol_cap_t *role_cap = &(wrole->protocol_cap);
|
#endif
|
|
phl_sta->asoc_cap.htc_rx = GET_HE_MAC_CAP_HTC_HE_SUPPORT(ele_start);
|
phl_sta->asoc_cap.twt = GET_HE_MAC_CAP_TWT_REQUESTER_SUPPORT(ele_start);
|
phl_sta->asoc_cap.twt |= ((GET_HE_MAC_CAP_TWT_RESPONDER_SUPPORT(ele_start)) << 1);
|
phl_sta->asoc_cap.trig_padding = GET_HE_MAC_CAP_TRI_FRAME_PADDING_DUR(ele_start);
|
phl_sta->asoc_cap.all_ack = GET_HE_MAC_CAP_ALL_ACK_SUPPORT(ele_start);
|
phl_sta->asoc_cap.a_ctrl = GET_HE_MAC_CAP_TRS_SUPPORT(ele_start);
|
phl_sta->asoc_cap.a_ctrl |= ((GET_HE_MAC_CAP_BRS_SUPPORT(ele_start)) << 1);
|
phl_sta->asoc_cap.twt |= ((GET_HE_MAC_CAP_BC_TWT_SUPPORT(ele_start)) << 2);
|
phl_sta->asoc_cap.a_ctrl |= ((GET_HE_MAC_CAP_OM_CTRL_SUPPORT(ele_start)) << 2);
|
phl_sta->asoc_cap.twt |= ((GET_HE_MAC_CAP_FLEX_TWT_SCHED_SUPPORT(ele_start)) << 3);
|
phl_sta->asoc_cap.twt |= ((GET_HE_MAC_CAP_PSR_RESPONDER(ele_start)) << 4);
|
phl_sta->asoc_cap.ops = GET_HE_MAC_CAP_OPS_SUPPORT(ele_start);
|
phl_sta->asoc_cap.amsdu_in_ampdu =
|
GET_HE_MAC_CAP_AMSDU_NOT_UNDER_BA_IN_ACK_EN_AMPDU(ele_start);
|
phl_sta->asoc_cap.twt |= ((GET_HE_MAC_CAP_HE_SUB_CH_SELECTIVE_TX(ele_start)) << 5);
|
phl_sta->asoc_cap.ht_vht_trig_rx =
|
GET_HE_MAC_CAP_HT_VHT_TRIG_FRAME_RX(ele_start);
|
}
|
|
static void update_sta_he_phy_cap_apmode(_adapter *padapter, struct rtw_phl_stainfo_t *phl_sta, u8 *ele_start, u8 *supp_mcs_len)
|
{
|
struct rtw_wifi_role_t *wrole = padapter->phl_role;
|
struct rtw_wifi_role_link_t *rlink = phl_sta->rlink;
|
struct protocol_cap_t *role_cap = &(rlink->protocol_cap);
|
struct role_link_cap_t *cap = &(rlink->cap);
|
|
if (phl_sta->chandef.band == BAND_ON_24G) {
|
if (GET_HE_PHY_CAP_SUPPORT_CHAN_WIDTH_SET(ele_start) & BIT(0))
|
phl_sta->chandef.bw = (rlink->chandef.bw < CHANNEL_WIDTH_40) ?
|
rlink->chandef.bw : CHANNEL_WIDTH_40;
|
} else if ((phl_sta->chandef.band == BAND_ON_5G) || (phl_sta->chandef.band == BAND_ON_6G)) {
|
if (GET_HE_PHY_CAP_SUPPORT_CHAN_WIDTH_SET(ele_start) & BIT(1))
|
phl_sta->chandef.bw = (rlink->chandef.bw < CHANNEL_WIDTH_80) ?
|
rlink->chandef.bw : CHANNEL_WIDTH_80;
|
if (GET_HE_PHY_CAP_SUPPORT_CHAN_WIDTH_SET(ele_start) & BIT(2)) {
|
phl_sta->chandef.bw = (rlink->chandef.bw < CHANNEL_WIDTH_160) ?
|
rlink->chandef.bw : CHANNEL_WIDTH_160;
|
*supp_mcs_len += 4;
|
}
|
if (GET_HE_PHY_CAP_SUPPORT_CHAN_WIDTH_SET(ele_start) & BIT(3))
|
*supp_mcs_len += 4;
|
}
|
|
phl_sta->asoc_cap.he_ldpc = (GET_HE_PHY_CAP_LDPC_IN_PAYLOAD(ele_start) & role_cap->he_ldpc);
|
|
if (role_cap->ltf_gi) {
|
if (phl_sta->asoc_cap.er_su) {
|
phl_sta->asoc_cap.ltf_gi = (BIT(RTW_GILTF_2XHE16) |
|
BIT(RTW_GILTF_2XHE08) | BIT(RTW_GILTF_1XHE16) |
|
(GET_HE_PHY_CAP_NDP_4X_LTF_3_POINT_2_GI(ele_start) ?
|
BIT(RTW_GILTF_LGI_4XHE32) : 0) |
|
(GET_HE_PHY_CAP_ERSU_PPDU_4X_LTF_0_POINT_8_GI(ele_start) ?
|
BIT(RTW_GILTF_SGI_4XHE08) : 0) |
|
(GET_HE_PHY_CAP_ERSU_PPDU_1X_LTF_0_POINT_8_GI(ele_start) ?
|
BIT(RTW_GILTF_1XHE08) : 0));
|
} else {
|
phl_sta->asoc_cap.ltf_gi = (BIT(RTW_GILTF_2XHE16) |
|
BIT(RTW_GILTF_2XHE08) | BIT(RTW_GILTF_1XHE16) |
|
(GET_HE_PHY_CAP_NDP_4X_LTF_3_POINT_2_GI(ele_start) ?
|
BIT(RTW_GILTF_LGI_4XHE32) : 0) |
|
(GET_HE_PHY_CAP_SU_MU_PPDU_4X_LTF_0_POINT_8_GI(ele_start) ?
|
BIT(RTW_GILTF_SGI_4XHE08) : 0) |
|
(GET_HE_PHY_CAP_SU_PPDU_1X_LTF_0_POINT_8_GI(ele_start) ?
|
BIT(RTW_GILTF_1XHE08) : 0));
|
}
|
}
|
|
phl_sta->asoc_cap.stbc_he_tx = GET_HE_PHY_CAP_STBC_TX_LESS_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.stbc_he_rx = (GET_HE_PHY_CAP_STBC_RX_LESS_THAN_80MHZ(ele_start) & role_cap->stbc_he_tx);
|
phl_sta->asoc_cap.doppler_tx = GET_HE_PHY_CAP_DOPPLER_TX(ele_start);
|
phl_sta->asoc_cap.doppler_rx = (GET_HE_PHY_CAP_DOPPLER_RX(ele_start) & role_cap->doppler_tx);
|
|
phl_sta->asoc_cap.dcm_max_const_tx =
|
GET_HE_PHY_CAP_DCM_MAX_CONSTELLATION_TX(ele_start);
|
if (phl_sta->asoc_cap.dcm_max_const_tx > role_cap->dcm_max_const_rx)
|
phl_sta->asoc_cap.dcm_max_const_tx = role_cap->dcm_max_const_rx;
|
|
phl_sta->asoc_cap.dcm_max_nss_tx = (GET_HE_PHY_CAP_DCM_MAX_NSS_TX(ele_start) & role_cap->dcm_max_nss_rx);
|
|
phl_sta->asoc_cap.dcm_max_const_rx =
|
GET_HE_PHY_CAP_DCM_MAX_CONSTELLATION_RX(ele_start);
|
if (phl_sta->asoc_cap.dcm_max_const_rx > role_cap->dcm_max_const_tx)
|
phl_sta->asoc_cap.dcm_max_const_rx = role_cap->dcm_max_const_tx;
|
|
phl_sta->asoc_cap.dcm_max_nss_rx = (GET_HE_PHY_CAP_DCM_MAX_NSS_RX(ele_start) & role_cap->dcm_max_nss_tx);
|
|
phl_sta->asoc_cap.partial_bw_su_er =
|
GET_HE_PHY_CAP_RX_PARTIAL_BW_SU_IN_20MHZ_MUPPDU(ele_start);
|
phl_sta->asoc_cap.he_su_bfmr = GET_HE_PHY_CAP_SU_BFER(ele_start);
|
phl_sta->asoc_cap.he_su_bfme = GET_HE_PHY_CAP_SU_BFEE(ele_start);
|
phl_sta->asoc_cap.he_mu_bfmr = GET_HE_PHY_CAP_MU_BFER(ele_start);
|
phl_sta->asoc_cap.bfme_sts =
|
GET_HE_PHY_CAP_BFEE_STS_LESS_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.bfme_sts_greater_80mhz =
|
GET_HE_PHY_CAP_BFEE_STS_GREATER_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.num_snd_dim =
|
GET_HE_PHY_CAP_NUM_SND_DIMEN_LESS_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.num_snd_dim_greater_80mhz =
|
GET_HE_PHY_CAP_NUM_SND_DIMEN_GREATER_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.ng_16_su_fb = GET_HE_PHY_CAP_NG_16_SU_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.ng_16_mu_fb = GET_HE_PHY_CAP_NG_16_MU_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.cb_sz_su_fb =
|
GET_HE_PHY_CAP_CODEBOOK_4_2_SU_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.cb_sz_mu_fb =
|
GET_HE_PHY_CAP_CODEBOOK_7_5_MU_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.trig_su_bfm_fb =
|
GET_HE_PHY_CAP_TRIG_SUBF_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.trig_mu_bfm_fb =
|
GET_HE_PHY_CAP_TRIG_MUBF_PARTIAL_BW_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.trig_cqi_fb = GET_HE_PHY_CAP_TRIG_CQI_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.partial_bw_su_er =
|
GET_HE_PHY_CAP_PARTIAL_BW_EXT_RANGE(ele_start);
|
phl_sta->asoc_cap.pwr_bst_factor =
|
GET_HE_PHY_CAP_PWR_BOOST_FACTOR_SUPPORT(ele_start);
|
phl_sta->asoc_cap.max_nc = GET_HE_PHY_CAP_MAX_NC(ele_start);
|
phl_sta->asoc_cap.stbc_tx_greater_80mhz =
|
(GET_HE_PHY_CAP_STBC_TX_GREATER_THAN_80MHZ(ele_start) & role_cap->stbc_rx_greater_80mhz);
|
phl_sta->asoc_cap.stbc_rx_greater_80mhz =
|
(GET_HE_PHY_CAP_STBC_RX_GREATER_THAN_80MHZ(ele_start) & role_cap->stbc_tx_greater_80mhz);
|
phl_sta->asoc_cap.dcm_max_ru = GET_HE_PHY_CAP_DCM_MAX_RU(ele_start);
|
phl_sta->asoc_cap.long_sigb_symbol =
|
GET_HE_PHY_CAP_LONGER_THAN_16_HESIGB_OFDM_SYM(ele_start);
|
phl_sta->asoc_cap.non_trig_cqi_fb =
|
GET_HE_PHY_CAP_NON_TRIGGER_CQI_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.tx_1024q_ru =
|
(GET_HE_PHY_CAP_TX_1024_QAM_LESS_THAN_242_TONE_RU(ele_start) & role_cap->rx_1024q_ru);
|
phl_sta->asoc_cap.rx_1024q_ru =
|
(GET_HE_PHY_CAP_RX_1024_QAM_LESS_THAN_242_TONE_RU(ele_start) & role_cap->tx_1024q_ru);
|
phl_sta->asoc_cap.fbw_su_using_mu_cmprs_sigb =
|
GET_HE_PHY_CAP_RX_FULLBW_SU_USE_MUPPDU_CMP_SIGB(ele_start);
|
phl_sta->asoc_cap.fbw_su_using_mu_non_cmprs_sigb =
|
GET_HE_PHY_CAP_RX_FULLBW_SU_USE_MUPPDU_NONCMP_SIGB(ele_start);
|
|
if (GET_HE_PHY_CAP_PPE_THRESHOLD_PRESENT(ele_start))
|
phl_sta->asoc_cap.pkt_padding = 3;
|
else
|
phl_sta->asoc_cap.pkt_padding = GET_HE_PHY_CAP_NOMINAL_PACKET_PADDING(ele_start);
|
}
|
|
static void update_sta_he_supp_mcs_apmode(_adapter *padapter, struct rtw_phl_stainfo_t *phl_sta, u8 *ele_start, u8 supp_mcs_len)
|
{
|
rtw_he_set_asoc_cap_supp_mcs(padapter, phl_sta, ele_start, supp_mcs_len);
|
}
|
|
static void update_sta_he_ppe_thre_apmode(_adapter *padapter, struct rtw_phl_stainfo_t *phl_sta, u8 *ele_start)
|
{
|
rtw_he_set_asoc_cap_ppe_thre(padapter, phl_sta, ele_start);
|
}
|
|
void update_sta_he_info_apmode(_adapter *padapter, void *sta)
|
{
|
struct sta_info *psta = (struct sta_info *)sta;
|
struct rtw_phl_stainfo_t *phl_sta = psta->phl_sta;
|
struct he_priv *phepriv_sta = &psta->hepriv;
|
u8 *ele_start = NULL;
|
u8 supp_mcs_len = 4;
|
|
if (phepriv_sta->he_option == _FALSE)
|
return;
|
|
ele_start = &(phepriv_sta->he_cap[1]);
|
update_sta_he_mac_cap_apmode(padapter, phl_sta, ele_start);
|
|
ele_start += HE_CAP_ELE_MAC_CAP_LEN;
|
update_sta_he_phy_cap_apmode(padapter, phl_sta, ele_start, &supp_mcs_len);
|
|
ele_start += HE_CAP_ELE_PHY_CAP_LEN;
|
update_sta_he_supp_mcs_apmode(padapter, phl_sta, ele_start, supp_mcs_len);
|
|
ele_start += supp_mcs_len;
|
update_sta_he_ppe_thre_apmode(padapter, phl_sta, ele_start);
|
}
|
|
#if CONFIG_IEEE80211_BAND_6GHZ
|
void update_sta_6ghz_info_apmode(_adapter *padapter, void *sta)
|
{
|
struct sta_info *psta = (struct sta_info *)sta;
|
struct rtw_phl_stainfo_t *phl_sta = psta->phl_sta;
|
struct ampdu_priv *ampdu_priv_sta = &psta->ampdu_priv;
|
|
/* 6G = HE only = AMPDU always */
|
if (phl_sta->chandef.band == BAND_ON_6G)
|
ampdu_priv_sta->ampdu_enable = _TRUE;
|
}
|
#endif
|
|
void HE_mac_caps_handler(_adapter *padapter, struct rtw_phl_stainfo_t *phl_sta, u8 *ele_start)
|
{
|
phl_sta->asoc_cap.htc_rx = GET_HE_MAC_CAP_HTC_HE_SUPPORT(ele_start);
|
phl_sta->asoc_cap.twt = GET_HE_MAC_CAP_TWT_REQUESTER_SUPPORT(ele_start);
|
phl_sta->asoc_cap.twt |= ((GET_HE_MAC_CAP_TWT_RESPONDER_SUPPORT(ele_start)) << 1);
|
phl_sta->asoc_cap.trig_padding = GET_HE_MAC_CAP_TRI_FRAME_PADDING_DUR(ele_start);
|
phl_sta->asoc_cap.all_ack = GET_HE_MAC_CAP_ALL_ACK_SUPPORT(ele_start);
|
phl_sta->asoc_cap.a_ctrl = GET_HE_MAC_CAP_TRS_SUPPORT(ele_start);
|
phl_sta->asoc_cap.a_ctrl |= ((GET_HE_MAC_CAP_BRS_SUPPORT(ele_start)) << 1);
|
phl_sta->asoc_cap.twt |= ((GET_HE_MAC_CAP_BC_TWT_SUPPORT(ele_start)) << 2);
|
phl_sta->asoc_cap.a_ctrl |= ((GET_HE_MAC_CAP_OM_CTRL_SUPPORT(ele_start)) << 2);
|
phl_sta->asoc_cap.twt |= ((GET_HE_MAC_CAP_FLEX_TWT_SCHED_SUPPORT(ele_start)) << 3);
|
phl_sta->asoc_cap.twt |= ((GET_HE_MAC_CAP_PSR_RESPONDER(ele_start)) << 4);
|
phl_sta->asoc_cap.ops = GET_HE_MAC_CAP_OPS_SUPPORT(ele_start);
|
phl_sta->asoc_cap.amsdu_in_ampdu =
|
GET_HE_MAC_CAP_AMSDU_NOT_UNDER_BA_IN_ACK_EN_AMPDU(ele_start);
|
phl_sta->asoc_cap.twt |= ((GET_HE_MAC_CAP_HE_SUB_CH_SELECTIVE_TX(ele_start)) << 5);
|
phl_sta->asoc_cap.ht_vht_trig_rx =
|
GET_HE_MAC_CAP_HT_VHT_TRIG_FRAME_RX(ele_start);
|
}
|
|
void HE_phy_caps_handler(_adapter *padapter, struct rtw_phl_stainfo_t *phl_sta, u8 *ele_start, u8 *supp_mcs_len)
|
{
|
struct rtw_wifi_role_t *wrole = padapter->phl_role;
|
struct rtw_wifi_role_link_t *rlink = phl_sta->rlink;
|
struct protocol_cap_t *role_cap = &(phl_sta->rlink->protocol_cap);
|
|
if (phl_sta->chandef.band == BAND_ON_24G) {
|
if (GET_HE_PHY_CAP_SUPPORT_CHAN_WIDTH_SET(ele_start) & BIT(0))
|
phl_sta->chandef.bw = (rlink->chandef.bw < CHANNEL_WIDTH_40) ?
|
rlink->chandef.bw : CHANNEL_WIDTH_40;
|
} else if ((phl_sta->chandef.band == BAND_ON_5G) || (phl_sta->chandef.band == BAND_ON_6G)) {
|
if (GET_HE_PHY_CAP_SUPPORT_CHAN_WIDTH_SET(ele_start) & BIT(1))
|
phl_sta->chandef.bw = (rlink->chandef.bw < CHANNEL_WIDTH_80) ?
|
rlink->chandef.bw : CHANNEL_WIDTH_80;
|
if (GET_HE_PHY_CAP_SUPPORT_CHAN_WIDTH_SET(ele_start) & BIT(2)) {
|
phl_sta->chandef.bw = (rlink->chandef.bw < CHANNEL_WIDTH_160) ?
|
rlink->chandef.bw : CHANNEL_WIDTH_160;
|
*supp_mcs_len += 4;
|
}
|
if (GET_HE_PHY_CAP_SUPPORT_CHAN_WIDTH_SET(ele_start) & BIT(3))
|
*supp_mcs_len += 4;
|
}
|
phl_sta->asoc_cap.he_ldpc = (GET_HE_PHY_CAP_LDPC_IN_PAYLOAD(ele_start) & role_cap->he_ldpc);
|
if (role_cap->ltf_gi) {
|
if (phl_sta->asoc_cap.er_su) {
|
phl_sta->asoc_cap.ltf_gi = (BIT(RTW_GILTF_2XHE16) |
|
BIT(RTW_GILTF_2XHE08) | BIT(RTW_GILTF_1XHE16) |
|
(GET_HE_PHY_CAP_NDP_4X_LTF_3_POINT_2_GI(ele_start) ?
|
BIT(RTW_GILTF_LGI_4XHE32) : 0) |
|
(GET_HE_PHY_CAP_ERSU_PPDU_4X_LTF_0_POINT_8_GI(ele_start) ?
|
BIT(RTW_GILTF_SGI_4XHE08) : 0) |
|
(GET_HE_PHY_CAP_ERSU_PPDU_1X_LTF_0_POINT_8_GI(ele_start) ?
|
BIT(RTW_GILTF_1XHE08) : 0));
|
} else {
|
phl_sta->asoc_cap.ltf_gi = (BIT(RTW_GILTF_2XHE16) |
|
BIT(RTW_GILTF_2XHE08) | BIT(RTW_GILTF_1XHE16) |
|
(GET_HE_PHY_CAP_NDP_4X_LTF_3_POINT_2_GI(ele_start) ?
|
BIT(RTW_GILTF_LGI_4XHE32) : 0) |
|
(GET_HE_PHY_CAP_SU_MU_PPDU_4X_LTF_0_POINT_8_GI(ele_start) ?
|
BIT(RTW_GILTF_SGI_4XHE08) : 0) |
|
(GET_HE_PHY_CAP_SU_PPDU_1X_LTF_0_POINT_8_GI(ele_start) ?
|
BIT(RTW_GILTF_1XHE08) : 0));
|
}
|
}
|
phl_sta->asoc_cap.stbc_he_tx = GET_HE_PHY_CAP_STBC_TX_LESS_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.stbc_he_rx = (GET_HE_PHY_CAP_STBC_RX_LESS_THAN_80MHZ(ele_start) & role_cap->stbc_he_tx);
|
phl_sta->asoc_cap.doppler_tx = GET_HE_PHY_CAP_DOPPLER_TX(ele_start);
|
phl_sta->asoc_cap.doppler_rx = (GET_HE_PHY_CAP_DOPPLER_RX(ele_start) & role_cap->doppler_tx);
|
phl_sta->asoc_cap.dcm_max_const_tx =
|
GET_HE_PHY_CAP_DCM_MAX_CONSTELLATION_TX(ele_start);
|
phl_sta->asoc_cap.dcm_max_nss_tx = GET_HE_PHY_CAP_DCM_MAX_NSS_TX(ele_start);
|
phl_sta->asoc_cap.dcm_max_const_rx =
|
GET_HE_PHY_CAP_DCM_MAX_CONSTELLATION_RX(ele_start);
|
phl_sta->asoc_cap.dcm_max_nss_rx = GET_HE_PHY_CAP_DCM_MAX_NSS_RX(ele_start);
|
phl_sta->asoc_cap.partial_bw_su_er =
|
GET_HE_PHY_CAP_RX_PARTIAL_BW_SU_IN_20MHZ_MUPPDU(ele_start);
|
phl_sta->asoc_cap.he_su_bfmr = GET_HE_PHY_CAP_SU_BFER(ele_start);
|
phl_sta->asoc_cap.he_su_bfme = GET_HE_PHY_CAP_SU_BFEE(ele_start);
|
phl_sta->asoc_cap.he_mu_bfmr = GET_HE_PHY_CAP_MU_BFER(ele_start);
|
phl_sta->asoc_cap.bfme_sts =
|
GET_HE_PHY_CAP_BFEE_STS_LESS_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.bfme_sts_greater_80mhz =
|
GET_HE_PHY_CAP_BFEE_STS_GREATER_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.num_snd_dim =
|
GET_HE_PHY_CAP_NUM_SND_DIMEN_LESS_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.num_snd_dim_greater_80mhz =
|
GET_HE_PHY_CAP_NUM_SND_DIMEN_GREATER_THAN_80MHZ(ele_start);
|
|
RTW_INFO("%s: HE STA assoc_cap:\n", __func__);
|
RTW_INFO("- SU BFer: %d\n", phl_sta->asoc_cap.he_su_bfmr);
|
RTW_INFO("- SU BFee: %d\n", phl_sta->asoc_cap.he_su_bfme);
|
RTW_INFO("- MU BFer: %d\n", phl_sta->asoc_cap.he_mu_bfmr);
|
RTW_INFO("- BFee STS: %d\n", phl_sta->asoc_cap.bfme_sts);
|
RTW_INFO("- BFee STS(>80MHz): %d\n", phl_sta->asoc_cap.bfme_sts_greater_80mhz);
|
RTW_INFO("- BFer SND DIM number: %d\n", phl_sta->asoc_cap.num_snd_dim);
|
RTW_INFO("- BFer SND DIM number(>80MHz): %d\n", phl_sta->asoc_cap.num_snd_dim_greater_80mhz);
|
|
phl_sta->asoc_cap.ng_16_su_fb = GET_HE_PHY_CAP_NG_16_SU_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.ng_16_mu_fb = GET_HE_PHY_CAP_NG_16_MU_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.cb_sz_su_fb =
|
GET_HE_PHY_CAP_CODEBOOK_4_2_SU_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.cb_sz_mu_fb =
|
GET_HE_PHY_CAP_CODEBOOK_7_5_MU_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.trig_su_bfm_fb =
|
GET_HE_PHY_CAP_TRIG_SUBF_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.trig_mu_bfm_fb =
|
GET_HE_PHY_CAP_TRIG_MUBF_PARTIAL_BW_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.trig_cqi_fb = GET_HE_PHY_CAP_TRIG_CQI_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.partial_bw_su_er =
|
GET_HE_PHY_CAP_PARTIAL_BW_EXT_RANGE(ele_start);
|
phl_sta->asoc_cap.pwr_bst_factor =
|
GET_HE_PHY_CAP_PWR_BOOST_FACTOR_SUPPORT(ele_start);
|
phl_sta->asoc_cap.max_nc = GET_HE_PHY_CAP_MAX_NC(ele_start);
|
phl_sta->asoc_cap.stbc_tx_greater_80mhz =
|
GET_HE_PHY_CAP_STBC_TX_GREATER_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.stbc_rx_greater_80mhz =
|
GET_HE_PHY_CAP_STBC_RX_GREATER_THAN_80MHZ(ele_start);
|
phl_sta->asoc_cap.dcm_max_ru = GET_HE_PHY_CAP_DCM_MAX_RU(ele_start);
|
phl_sta->asoc_cap.long_sigb_symbol =
|
GET_HE_PHY_CAP_LONGER_THAN_16_HESIGB_OFDM_SYM(ele_start);
|
phl_sta->asoc_cap.non_trig_cqi_fb =
|
GET_HE_PHY_CAP_NON_TRIGGER_CQI_FEEDBACK(ele_start);
|
phl_sta->asoc_cap.tx_1024q_ru =
|
GET_HE_PHY_CAP_TX_1024_QAM_LESS_THAN_242_TONE_RU(ele_start);
|
phl_sta->asoc_cap.rx_1024q_ru =
|
GET_HE_PHY_CAP_RX_1024_QAM_LESS_THAN_242_TONE_RU(ele_start);
|
phl_sta->asoc_cap.fbw_su_using_mu_cmprs_sigb =
|
GET_HE_PHY_CAP_RX_FULLBW_SU_USE_MUPPDU_CMP_SIGB(ele_start);
|
phl_sta->asoc_cap.fbw_su_using_mu_non_cmprs_sigb =
|
GET_HE_PHY_CAP_RX_FULLBW_SU_USE_MUPPDU_NONCMP_SIGB(ele_start);
|
|
if (GET_HE_PHY_CAP_PPE_THRESHOLD_PRESENT(ele_start))
|
phl_sta->asoc_cap.pkt_padding = 3;
|
else
|
phl_sta->asoc_cap.pkt_padding = GET_HE_PHY_CAP_NOMINAL_PACKET_PADDING(ele_start);
|
}
|
|
void HE_supp_mcs_handler(_adapter *padapter, struct rtw_phl_stainfo_t *phl_sta, u8 *ele_start, u8 supp_mcs_len)
|
{
|
struct _ADAPTER_LINK *padapter_link = GET_LINK(padapter, phl_sta->rlink->id);
|
struct link_mlme_priv *pmlmepriv = &padapter_link->mlmepriv;
|
struct he_priv *phepriv = &pmlmepriv->hepriv;
|
|
rtw_he_set_asoc_cap_supp_mcs(padapter, phl_sta, ele_start, supp_mcs_len);
|
phepriv->he_highest_rate = rtw_he_get_highest_rate(phl_sta->asoc_cap.he_rx_mcs);
|
}
|
|
void HE_ppe_thre_handler(_adapter *padapter, struct rtw_phl_stainfo_t *phl_sta, u8 *ele_start)
|
{
|
rtw_he_set_asoc_cap_ppe_thre(padapter, phl_sta, ele_start);
|
}
|
|
void HE_caps_handler(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, PNDIS_802_11_VARIABLE_IEs pIE)
|
{
|
struct rtw_wifi_role_t *wrole = padapter->phl_role;
|
struct link_mlme_priv *pmlmepriv = &padapter_link->mlmepriv;
|
struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv;
|
struct sta_priv *pstapriv = &padapter->stapriv;
|
struct he_priv *phepriv = &pmlmepriv->hepriv;
|
struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
|
struct sta_info *psta = NULL;
|
struct rtw_phl_stainfo_t *phl_sta = NULL;
|
u8 *ele_start = (&(pIE->data[0]) + 1);
|
u8 supp_mcs_len = 4;
|
|
if (pIE == NULL)
|
return;
|
|
if (phepriv->he_option == _FALSE)
|
return;
|
|
psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
|
if (psta == NULL)
|
return;
|
if (psta->phl_sta == NULL)
|
return;
|
|
phl_sta = psta->phl_sta;
|
|
/* HE MAC Caps */
|
HE_mac_caps_handler(padapter, phl_sta, ele_start);
|
ele_start += HE_CAP_ELE_MAC_CAP_LEN;
|
|
/* HE PHY Caps */
|
HE_phy_caps_handler(padapter, phl_sta, ele_start, &supp_mcs_len);
|
ele_start += HE_CAP_ELE_PHY_CAP_LEN;
|
|
/* HE Supp MCS Set */
|
HE_supp_mcs_handler(padapter, phl_sta, ele_start, supp_mcs_len);
|
ele_start += supp_mcs_len;
|
|
/* HE PPE Thresholds */
|
HE_ppe_thre_handler(padapter, phl_sta, ele_start);
|
|
pmlmeinfo->HE_enable = 1;
|
}
|
|
void HE_operation_handler(_adapter *padapter,
|
struct _ADAPTER_LINK *padapter_link,
|
PNDIS_802_11_VARIABLE_IEs pIE)
|
{
|
struct link_mlme_priv *pmlmepriv = &padapter_link->mlmepriv;
|
struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv;
|
struct sta_priv *pstapriv = &padapter->stapriv;
|
struct he_priv *phepriv = &pmlmepriv->hepriv;
|
struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
|
struct sta_info *psta = NULL;
|
struct rtw_phl_stainfo_t *phl_sta = NULL;
|
u8 *ele_start = (&(pIE->data[0]) + 1);
|
struct dvobj_priv *d;
|
void *phl;
|
u8 pre_bsscolor = 0;
|
u16 pre_rts_th = 0;
|
|
if (pIE == NULL)
|
return;
|
|
if (phepriv->he_option == _FALSE)
|
return;
|
|
d = adapter_to_dvobj(padapter);
|
phl = GET_PHL_INFO(d);
|
|
psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
|
if (psta == NULL)
|
return;
|
if (psta->phl_sta == NULL)
|
return;
|
|
phl_sta = psta->phl_sta;
|
phl_sta->tf_trs = _TRUE;
|
|
phl_sta->asoc_cap.er_su = !GET_HE_OP_PARA_ER_SU_DISABLE(ele_start);
|
if (!GET_HE_OP_BSS_COLOR_INFO_BSS_COLOR_DISABLE(ele_start)) {
|
|
pre_bsscolor = phl_sta->asoc_cap.bsscolor;
|
phl_sta->asoc_cap.bsscolor = GET_HE_OP_BSS_COLOR_INFO_BSS_COLOR(ele_start);
|
|
/* rx thread & assoc timer callback, use cmd no_wait */
|
if (pre_bsscolor != phl_sta->asoc_cap.bsscolor) {
|
RTW_INFO("%s, Update BSS Color = %d\n", __func__, phl_sta->asoc_cap.bsscolor);
|
#ifdef CONFIG_CMD_DISP
|
rtw_phl_cmd_wrole_change(phl,
|
padapter->phl_role,
|
padapter_link->wrlink,
|
WR_CHG_BSS_COLOR,
|
(u8 *)&phl_sta->asoc_cap.bsscolor,
|
sizeof(phl_sta->asoc_cap.bsscolor),
|
PHL_CMD_NO_WAIT,
|
0);
|
#else
|
/* role change here, but no implementation for not CMD_DISP case */
|
#endif
|
}
|
}
|
|
pre_rts_th = phl_sta->asoc_cap.rts_th;
|
phl_sta->asoc_cap.rts_th =
|
GET_HE_OP_PARA_TXOP_DUR_RTS_THRESHOLD(ele_start);
|
|
if ((phl_sta->asoc_cap.rts_th > 0) &&
|
(phl_sta->asoc_cap.rts_th != TXOP_DUR_RTS_TH_DISABLED)) {
|
struct rtw_rts_threshold val = {0};
|
|
/* time preference */
|
val.rts_len_th = 0xffff;
|
/* IE field unit 32us, parameter unit 1us */
|
val.rts_time_th = phl_sta->asoc_cap.rts_th * 32;
|
/* rx thread & assoc timer callback, use cmd no_wait */
|
if (pre_rts_th != phl_sta->asoc_cap.rts_th) {
|
RTW_INFO("%s, Update TXOP Duration RTS Threshold =%d\n", __func__, phl_sta->asoc_cap.rts_th);
|
#ifdef CONFIG_CMD_DISP
|
rtw_phl_cmd_wrole_change(phl,
|
padapter->phl_role,
|
padapter_link->wrlink,
|
WR_CHG_RTS_TH,
|
(u8 *)&val,
|
sizeof(struct rtw_rts_threshold),
|
PHL_CMD_NO_WAIT,
|
0);
|
#else
|
/* role change here, but no implementation for not CMD_DISP case */
|
#endif
|
}
|
}
|
}
|
|
void HE_mu_edca_handler(_adapter *padapter,
|
struct _ADAPTER_LINK *padapter_link,
|
PNDIS_802_11_VARIABLE_IEs pIE, u8 first)
|
{
|
struct link_mlme_priv *pmlmepriv = &padapter_link->mlmepriv;
|
struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv;
|
struct sta_priv *pstapriv = &padapter->stapriv;
|
struct he_priv *phepriv = &pmlmepriv->hepriv;
|
struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
|
struct sta_info *psta = NULL;
|
struct rtw_phl_stainfo_t *phl_sta = NULL;
|
u8 *ele_start = (&(pIE->data[0]) + 1);
|
struct dvobj_priv *d;
|
void *phl;
|
struct rtw_mu_edca_param edca = {0};
|
u8 pre_cnt = 0, cur_cnt = 0;
|
u8 i = 0;
|
|
if (pIE == NULL)
|
return;
|
|
if (phepriv->he_option == _FALSE)
|
return;
|
|
d = adapter_to_dvobj(padapter);
|
phl = GET_PHL_INFO(d);
|
if (!phl)
|
return;
|
|
psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
|
if (psta == NULL)
|
return;
|
if (psta->phl_sta == NULL)
|
return;
|
|
phl_sta = psta->phl_sta;
|
|
pre_cnt = phepriv->pre_he_muedca_cnt;
|
cur_cnt = GET_HE_MU_EDCA_QOS_INFO_UPDATE_CNT(ele_start);
|
if (cur_cnt != pre_cnt || first == _TRUE) {
|
phepriv->pre_he_muedca_cnt = cur_cnt;
|
phl_sta->asoc_cap.mu_edca[0].ac =
|
GET_HE_MU_EDCA_BE_ACI(ele_start);
|
phl_sta->asoc_cap.mu_edca[0].aifsn =
|
GET_HE_MU_EDCA_BE_AIFSN(ele_start);
|
phl_sta->asoc_cap.mu_edca[0].cw =
|
GET_HE_MU_EDCA_BE_ECW_MIN_MAX(ele_start);
|
phl_sta->asoc_cap.mu_edca[0].timer =
|
GET_HE_MU_EDCA_BE_TIMER(ele_start);
|
phl_sta->asoc_cap.mu_edca[1].ac =
|
GET_HE_MU_EDCA_BK_ACI(ele_start);
|
phl_sta->asoc_cap.mu_edca[1].aifsn =
|
GET_HE_MU_EDCA_BK_AIFSN(ele_start);
|
phl_sta->asoc_cap.mu_edca[1].cw =
|
GET_HE_MU_EDCA_BK_ECW_MIN_MAX(ele_start);
|
phl_sta->asoc_cap.mu_edca[1].timer =
|
GET_HE_MU_EDCA_BK_TIMER(ele_start);
|
phl_sta->asoc_cap.mu_edca[2].ac =
|
GET_HE_MU_EDCA_VI_ACI(ele_start);
|
phl_sta->asoc_cap.mu_edca[2].aifsn =
|
GET_HE_MU_EDCA_VI_AIFSN(ele_start);
|
phl_sta->asoc_cap.mu_edca[2].cw =
|
GET_HE_MU_EDCA_VI_ECW_MIN_MAX(ele_start);
|
phl_sta->asoc_cap.mu_edca[2].timer =
|
GET_HE_MU_EDCA_VI_TIMER(ele_start);
|
phl_sta->asoc_cap.mu_edca[3].ac =
|
GET_HE_MU_EDCA_VO_ACI(ele_start);
|
phl_sta->asoc_cap.mu_edca[3].aifsn =
|
GET_HE_MU_EDCA_VO_AIFSN(ele_start);
|
phl_sta->asoc_cap.mu_edca[3].cw =
|
GET_HE_MU_EDCA_VO_ECW_MIN_MAX(ele_start);
|
phl_sta->asoc_cap.mu_edca[3].timer =
|
GET_HE_MU_EDCA_VO_TIMER(ele_start);
|
for (i = 0; i < 4; i++) {
|
#ifdef CONFIG_CMD_DISP
|
rtw_phl_cmd_wrole_change(phl,
|
padapter->phl_role,
|
padapter_link->wrlink,
|
WR_CHG_MU_EDCA_PARAM,
|
(u8 *)&phl_sta->asoc_cap.mu_edca[i],
|
sizeof(struct rtw_mu_edca_param),
|
PHL_CMD_NO_WAIT,
|
0);
|
#endif
|
RTW_INFO("%s, Update HE MU EDCA AC(%d) aifsn(%d) cw(0x%x) timer(0x%x)\n",
|
__func__,
|
phl_sta->asoc_cap.mu_edca[i].ac,
|
phl_sta->asoc_cap.mu_edca[i].aifsn,
|
phl_sta->asoc_cap.mu_edca[i].cw,
|
phl_sta->asoc_cap.mu_edca[i].timer);
|
}
|
|
if (first) {
|
#ifdef CONFIG_CMD_DISP
|
rtw_phl_cmd_wrole_change(phl,
|
padapter->phl_role,
|
padapter_link->wrlink,
|
WR_CHG_MU_EDCA_CFG,
|
(u8 *)&first,
|
sizeof(first),
|
PHL_CMD_NO_WAIT,
|
0);
|
#else
|
/* role change here, but no implementation for not CMD_DISP case */
|
#endif
|
}
|
}
|
}
|
|
void HE_6g_bandcap_handler(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, PNDIS_802_11_VARIABLE_IEs pIE)
|
{
|
struct link_mlme_priv *pmlmepriv = &padapter_link->mlmepriv;
|
struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv;
|
struct sta_priv *pstapriv = &padapter->stapriv;
|
struct he_priv *phepriv = &pmlmepriv->hepriv;
|
struct registry_priv *pregistrypriv = &padapter->registrypriv;
|
struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);
|
struct sta_info *psta = NULL;
|
struct rtw_phl_stainfo_t *phl_sta = NULL;
|
u8 *ele_start = (&(pIE->data[0]) + 1);
|
|
if (pIE == NULL)
|
return;
|
|
if (phepriv->he_option == _FALSE)
|
return;
|
|
psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
|
if (psta == NULL)
|
return;
|
if (psta->phl_sta == NULL)
|
return;
|
|
phl_sta = psta->phl_sta;
|
|
phl_sta->asoc_cap.ampdu_density = GET_HE_6G_BAND_CAP_MIN_MPDU_SPACING(ele_start);
|
phl_sta->asoc_cap.ampdu_len_exp = GET_HE_6G_BAND_CAP_MAX_AMPDU_LEN_EXP(ele_start);
|
phl_sta->asoc_cap.max_amsdu_len = GET_HE_6G_BAND_CAP_MAX_MPDU_LEN(ele_start);
|
phl_sta->asoc_cap.sm_ps = GET_HE_6G_BAND_CAP_SM_PS(ele_start);
|
|
pmlmeinfo->SM_PS = phl_sta->asoc_cap.sm_ps;
|
if (pmlmeinfo->SM_PS == SM_PS_STATIC)
|
RTW_WARN("%s(): SM_PS_STATIC\n", __FUNCTION__);
|
|
phepriv->mpdu_min_spacing = GET_HE_6G_BAND_CAP_MIN_MPDU_SPACING(ele_start);
|
}
|
|
static int rtw_build_he_mac_caps(struct protocol_cap_t *proto_cap, u8 *pbuf)
|
{
|
/* Set HE MAC Capabilities Information */
|
|
int info_len = HE_CAP_ELE_MAC_CAP_LEN;
|
|
if (proto_cap->htc_rx)
|
SET_HE_MAC_CAP_HTC_HE_SUPPORT(pbuf, 1);
|
|
if (proto_cap->twt & BIT(0))
|
SET_HE_MAC_CAP_TWT_REQUESTER_SUPPORT(pbuf, 1);
|
|
if (proto_cap->twt & BIT(1))
|
SET_HE_MAC_CAP_TWT_RESPONDER_SUPPORT(pbuf, 1);
|
|
if (proto_cap->trig_padding)
|
SET_HE_MAC_CAP_TRI_FRAME_PADDING_DUR(pbuf,
|
proto_cap->trig_padding);
|
|
if (proto_cap->all_ack)
|
SET_HE_MAC_CAP_ALL_ACK_SUPPORT(pbuf, 1);
|
|
if (proto_cap->htc_rx && (proto_cap->a_ctrl & BIT(0)))
|
SET_HE_MAC_CAP_TRS_SUPPORT(pbuf, 1);
|
|
if (proto_cap->a_ctrl & BIT(1))
|
SET_HE_MAC_CAP_BRS_SUPPORT(pbuf, 1);
|
|
if (proto_cap->twt & BIT(2))
|
SET_HE_MAC_CAP_BC_TWT_SUPPORT(pbuf, 1);
|
|
if (proto_cap->htc_rx && (proto_cap->a_ctrl & BIT(2)))
|
SET_HE_MAC_CAP_OM_CTRL_SUPPORT(pbuf, 1);
|
|
SET_HE_MAC_CAP_MAX_AMPDU_LEN_EXP_EXT(pbuf, 2);
|
|
if (proto_cap->twt & BIT(3))
|
SET_HE_MAC_CAP_FLEX_TWT_SCHED_SUPPORT(pbuf, 1);
|
|
if (proto_cap->twt & BIT(4))
|
SET_HE_MAC_CAP_PSR_RESPONDER(pbuf, 1);
|
|
if (proto_cap->ops)
|
SET_HE_MAC_CAP_OPS_SUPPORT(pbuf, 1);
|
|
if (proto_cap->amsdu_in_ampdu)
|
SET_HE_MAC_CAP_AMSDU_NOT_UNDER_BA_IN_ACK_EN_AMPDU(pbuf, 1);
|
|
if (proto_cap->twt & BIT(5))
|
SET_HE_MAC_CAP_HE_SUB_CH_SELECTIVE_TX(pbuf, 1);
|
|
if (proto_cap->ht_vht_trig_rx)
|
SET_HE_MAC_CAP_HT_VHT_TRIG_FRAME_RX(pbuf, 1);
|
|
return info_len;
|
}
|
|
static int rtw_build_he_phy_caps(_adapter *padapter, struct protocol_cap_t *proto_cap, u8 *pbuf, enum band_type band)
|
{
|
/* struct rtw_chan_def *chan_def = &(wrole->chandef); */
|
/* Set HE PHY Capabilities Information */
|
struct registry_priv *pregistrypriv = &padapter->registrypriv;
|
int info_len = HE_CAP_ELE_PHY_CAP_LEN;
|
u8 bw_cap = 0;
|
|
if (band == BAND_ON_24G) {
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_40M) && REGSTY_IS_BW_2G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_40))
|
bw_cap |= BIT(0);
|
} else if (band == BAND_ON_5G) {
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_40M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_40))
|
bw_cap |= BIT(1);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_80M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_80))
|
bw_cap |= BIT(1);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160))
|
bw_cap |= BIT(2);
|
} else if (band == BAND_ON_6G) {
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_40M) && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_40))
|
bw_cap |= BIT(1);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_80M) && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_80))
|
bw_cap |= BIT(1);
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160))
|
bw_cap |= BIT(2);
|
}
|
|
SET_HE_PHY_CAP_SUPPORT_CHAN_WIDTH_SET(pbuf, bw_cap);
|
|
SET_HE_PHY_CAP_DEVICE_CLASS(pbuf, HE_DEV_CLASS_A);
|
|
if (proto_cap->he_ldpc)
|
SET_HE_PHY_CAP_LDPC_IN_PAYLOAD(pbuf, 1);
|
|
if (padapter->registrypriv.wifi_spec == 1)
|
SET_HE_PHY_CAP_SU_PPDU_1X_LTF_0_POINT_8_GI(pbuf, 0);
|
else
|
SET_HE_PHY_CAP_SU_PPDU_1X_LTF_0_POINT_8_GI(pbuf, 1);
|
|
if (proto_cap->he_rx_ndp_4x32) {
|
SET_HE_PHY_CAP_NDP_4X_LTF_3_POINT_2_GI(pbuf, 1);
|
RTW_DBG("NDP_4x32 is set.\n");;
|
}
|
|
if (proto_cap->stbc_he_tx)
|
SET_HE_PHY_CAP_STBC_TX_LESS_THAN_80MHZ(pbuf, 1);
|
|
if (proto_cap->stbc_he_rx)
|
SET_HE_PHY_CAP_STBC_RX_LESS_THAN_80MHZ(pbuf, 1);
|
|
if (proto_cap->doppler_tx)
|
SET_HE_PHY_CAP_DOPPLER_TX(pbuf, 1);
|
|
if (proto_cap->doppler_rx)
|
SET_HE_PHY_CAP_DOPPLER_RX(pbuf, 1);
|
|
if (proto_cap->dcm_max_const_tx)
|
SET_HE_PHY_CAP_DCM_MAX_CONSTELLATION_TX(pbuf,
|
proto_cap->dcm_max_const_tx);
|
|
if (proto_cap->dcm_max_nss_tx)
|
SET_HE_PHY_CAP_DCM_MAX_NSS_TX(pbuf, 1);
|
|
if (proto_cap->dcm_max_const_rx)
|
SET_HE_PHY_CAP_DCM_MAX_CONSTELLATION_RX(pbuf,
|
proto_cap->dcm_max_const_rx);
|
|
if (proto_cap->dcm_max_nss_rx)
|
SET_HE_PHY_CAP_DCM_MAX_NSS_RX(pbuf, 1);
|
|
if (proto_cap->partial_bw_su_in_mu)
|
SET_HE_PHY_CAP_RX_PARTIAL_BW_SU_IN_20MHZ_MUPPDU(pbuf, 1);
|
|
if (proto_cap->he_su_bfmr)
|
SET_HE_PHY_CAP_SU_BFER(pbuf, 1);
|
|
if (proto_cap->he_su_bfme)
|
SET_HE_PHY_CAP_SU_BFEE(pbuf, 1);
|
|
if (proto_cap->he_mu_bfmr)
|
SET_HE_PHY_CAP_MU_BFER(pbuf, 1);
|
|
if (proto_cap->bfme_sts)
|
SET_HE_PHY_CAP_BFEE_STS_LESS_THAN_80MHZ(pbuf,
|
proto_cap->bfme_sts);
|
|
if (proto_cap->bfme_sts_greater_80mhz)
|
SET_HE_PHY_CAP_BFEE_STS_GREATER_THAN_80MHZ(pbuf,
|
proto_cap->bfme_sts_greater_80mhz);
|
|
if (proto_cap->num_snd_dim)
|
SET_HE_PHY_CAP_NUM_SND_DIMEN_LESS_THAN_80MHZ(pbuf,
|
proto_cap->num_snd_dim);
|
|
if (proto_cap->num_snd_dim_greater_80mhz)
|
SET_HE_PHY_CAP_NUM_SND_DIMEN_GREATER_THAN_80MHZ(pbuf,
|
proto_cap->num_snd_dim_greater_80mhz);
|
|
if (proto_cap->ng_16_su_fb)
|
SET_HE_PHY_CAP_NG_16_SU_FEEDBACK(pbuf, 1);
|
|
if (proto_cap->ng_16_mu_fb)
|
SET_HE_PHY_CAP_NG_16_MU_FEEDBACK(pbuf, 1);
|
|
if (proto_cap->cb_sz_su_fb)
|
SET_HE_PHY_CAP_CODEBOOK_4_2_SU_FEEDBACK(pbuf, 1);
|
|
if (proto_cap->cb_sz_mu_fb)
|
SET_HE_PHY_CAP_CODEBOOK_7_5_MU_FEEDBACK(pbuf, 1);
|
|
if (proto_cap->trig_su_bfm_fb)
|
SET_HE_PHY_CAP_TRIG_SUBF_FEEDBACK(pbuf, 1);
|
|
if (proto_cap->trig_mu_bfm_fb)
|
SET_HE_PHY_CAP_TRIG_MUBF_PARTIAL_BW_FEEDBACK(pbuf, 1);
|
|
if (proto_cap->trig_cqi_fb)
|
SET_HE_PHY_CAP_TRIG_CQI_FEEDBACK(pbuf, 1);
|
|
if (proto_cap->partial_bw_su_er)
|
SET_HE_PHY_CAP_PARTIAL_BW_EXT_RANGE(pbuf, 1);
|
|
if (proto_cap->pwr_bst_factor)
|
SET_HE_PHY_CAP_PWR_BOOST_FACTOR_SUPPORT(pbuf, 1);
|
|
SET_HE_PHY_CAP_SU_MU_PPDU_4X_LTF_0_POINT_8_GI(pbuf, 1);
|
|
if (proto_cap->max_nc)
|
SET_HE_PHY_CAP_MAX_NC(pbuf, proto_cap->max_nc);
|
|
if (proto_cap->stbc_tx_greater_80mhz)
|
SET_HE_PHY_CAP_STBC_TX_GREATER_THAN_80MHZ(pbuf, 1);
|
|
if (proto_cap->stbc_rx_greater_80mhz)
|
SET_HE_PHY_CAP_STBC_RX_GREATER_THAN_80MHZ(pbuf, 1);
|
|
SET_HE_PHY_CAP_ERSU_PPDU_4X_LTF_0_POINT_8_GI(pbuf, 1);
|
SET_HE_PHY_CAP_ERSU_PPDU_1X_LTF_0_POINT_8_GI(pbuf, 1);
|
|
if (proto_cap->dcm_max_ru)
|
SET_HE_PHY_CAP_DCM_MAX_RU(pbuf, proto_cap->dcm_max_ru);
|
|
if (proto_cap->long_sigb_symbol)
|
SET_HE_PHY_CAP_LONGER_THAN_16_HESIGB_OFDM_SYM(pbuf, 1);
|
|
if (proto_cap->non_trig_cqi_fb)
|
SET_HE_PHY_CAP_NON_TRIGGER_CQI_FEEDBACK(pbuf, 1);
|
|
if (proto_cap->tx_1024q_ru)
|
SET_HE_PHY_CAP_TX_1024_QAM_LESS_THAN_242_TONE_RU(pbuf, 1);
|
|
if (proto_cap->rx_1024q_ru)
|
SET_HE_PHY_CAP_RX_1024_QAM_LESS_THAN_242_TONE_RU(pbuf, 1);
|
|
if (proto_cap->fbw_su_using_mu_cmprs_sigb)
|
SET_HE_PHY_CAP_RX_FULLBW_SU_USE_MUPPDU_CMP_SIGB(pbuf, 1);
|
|
if (proto_cap->fbw_su_using_mu_non_cmprs_sigb)
|
SET_HE_PHY_CAP_RX_FULLBW_SU_USE_MUPPDU_NONCMP_SIGB(pbuf, 1);
|
|
if (proto_cap->pkt_padding)
|
SET_HE_PHY_CAP_NOMINAL_PACKET_PADDING(pbuf,
|
proto_cap->pkt_padding);
|
|
return info_len;
|
}
|
|
static int rtw_build_he_supp_mcs(_adapter *padapter, struct protocol_cap_t *proto_cap, u8 *pbuf, enum band_type band)
|
{
|
|
/* struct rtw_chan_def *chan_def = &(wrole->chandef); */
|
|
/* Set HE Supported MCS and NSS Set */
|
struct registry_priv *pregistrypriv = &padapter->registrypriv;
|
int info_len = 4;
|
|
_rtw_memset(pbuf, HE_MSC_NOT_SUPP_BYTE, info_len);
|
|
_rtw_memcpy(pbuf, proto_cap->he_rx_mcs, HE_CAP_ELE_SUPP_MCS_LEN_RX_80M);
|
|
_rtw_memcpy(pbuf + 2, proto_cap->he_tx_mcs, HE_CAP_ELE_SUPP_MCS_LEN_TX_80M);
|
|
if (rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_160M) &&
|
((band == BAND_ON_5G && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) ||
|
(band == BAND_ON_6G && REGSTY_IS_BW_6G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)))
|
) {
|
_rtw_memcpy(pbuf + 4, proto_cap->he_rx_mcs + 2, HE_CAP_ELE_SUPP_MCS_LEN_RX_160M);
|
|
_rtw_memcpy(pbuf + 6, proto_cap->he_tx_mcs + 2, HE_CAP_ELE_SUPP_MCS_LEN_TX_160M);
|
|
info_len += 4;
|
}
|
return info_len;
|
}
|
|
static int rtw_build_he_ppe_thre(struct protocol_cap_t *proto_cap, u8 *pbuf)
|
{
|
/* Set HE PPE Thresholds (optional) */
|
|
int info_len = 0;
|
|
return info_len;
|
}
|
|
u32 rtw_get_dft_he_cap_ie(_adapter *padapter, struct phy_cap_t *phy_cap,
|
struct protocol_cap_t *proto_cap, u8 *pbuf, enum band_type band)
|
{
|
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
|
struct he_priv *phepriv = &pmlmepriv->dev_hepriv;
|
u32 he_cap_total_len = 0, len = 0;
|
u8* pcap_start = phepriv->he_cap;
|
u8* pcap = pcap_start;
|
|
_rtw_memset(pcap, 0, HE_CAP_ELE_MAX_LEN);
|
|
/* Ele ID Extension */
|
*pcap++ = WLAN_EID_EXTENSION_HE_CAPABILITY;
|
|
/* HE MAC Caps */
|
pcap += rtw_build_he_mac_caps(proto_cap, pcap);
|
|
/* HE PHY Caps */
|
pcap += rtw_build_he_phy_caps(padapter, proto_cap, pcap, band);
|
|
/* HE Supported MCS and NSS Set */
|
pcap += rtw_build_he_supp_mcs(padapter, proto_cap, pcap, band);
|
|
/* HE PPE Thresholds (optional) */
|
pcap += rtw_build_he_ppe_thre(proto_cap, pcap);
|
|
he_cap_total_len = (pcap - pcap_start);
|
|
pbuf = rtw_set_ie(pbuf, WLAN_EID_EXTENSION, he_cap_total_len, pcap_start, &len);
|
|
return len;
|
}
|
|
u32 rtw_build_he_cap_ie(_adapter *padapter,
|
struct _ADAPTER_LINK *padapter_link,
|
u8 *pbuf, enum band_type band)
|
{
|
struct rtw_wifi_role_t *wrole = padapter->phl_role;
|
struct link_mlme_priv *pmlmepriv = &padapter_link->mlmepriv;
|
struct protocol_cap_t *proto_cap = &(padapter_link->wrlink->protocol_cap);
|
struct he_priv *phepriv = &pmlmepriv->hepriv;
|
u32 he_cap_total_len = 0, len = 0;
|
u8* pcap_start = phepriv->he_cap;
|
u8* pcap = pcap_start;
|
|
_rtw_memset(pcap, 0, HE_CAP_ELE_MAX_LEN);
|
|
/* Ele ID Extension */
|
*pcap++ = WLAN_EID_EXTENSION_HE_CAPABILITY;
|
|
/* HE MAC Caps */
|
pcap += rtw_build_he_mac_caps(proto_cap, pcap);
|
|
/* HE PHY Caps */
|
pcap += rtw_build_he_phy_caps(padapter, proto_cap, pcap, band);
|
|
/* HE Supported MCS and NSS Set */
|
pcap += rtw_build_he_supp_mcs(padapter, proto_cap, pcap, band);
|
|
/* HE PPE Thresholds (optional) */
|
pcap += rtw_build_he_ppe_thre(proto_cap, pcap);
|
|
he_cap_total_len = (pcap - pcap_start);
|
|
pbuf = rtw_set_ie(pbuf, WLAN_EID_EXTENSION, he_cap_total_len, pcap_start, &len);
|
|
return len;
|
}
|
|
u32 rtw_build_he_6g_band_cap_ie_by_proto(_adapter *padapter, enum role_type role_type,
|
struct protocol_cap_t *proto_cap, u8 *pbuf)
|
{
|
/* pbuf[-2] = 0xff
|
* pbuf[-1] = 0x03
|
* pbuf[0] = 59
|
* pbuf[1-2] = he_6g_cap
|
*
|
* This function fills pbuf[0...2], but not guarantee values of
|
* pbuf[-2...-1]
|
*/
|
u8 ant_pat;
|
|
if (rtw_phl_is_ap_category(role_type))
|
ant_pat = 1;
|
else
|
ant_pat = 0;
|
|
*pbuf++ = WLAN_EID_EXT_HE_6G_CAP;
|
SET_HE_6G_BAND_CAP_MAX_AMPDU_LEN_EXP(pbuf, proto_cap->ampdu_len_exp);
|
SET_HE_6G_BAND_CAP_MAX_MPDU_LEN(pbuf, proto_cap->max_amsdu_len);
|
SET_HE_6G_BAND_CAP_SM_PS(pbuf, proto_cap->sm_ps);
|
SET_HE_6G_BAND_CAP_RX_ANT_PATTERN(pbuf, ant_pat);
|
SET_HE_6G_BAND_CAP_TX_ANT_PATTERN(pbuf, ant_pat);
|
|
return HE_6G_BAND_CAP_MAX_LEN + 2;
|
}
|
|
u32 rtw_build_he_6g_band_cap_ie(_adapter *padapter,
|
struct _ADAPTER_LINK *padapter_link,
|
u8 *pbuf)
|
{
|
struct protocol_cap_t *proto_cap = &(padapter_link->wrlink->protocol_cap);
|
enum role_type role_type = PHL_RTYPE_NONE;
|
|
if (padapter->phl_role)
|
role_type = padapter->phl_role->type;
|
|
return rtw_build_he_6g_band_cap_ie_by_proto(padapter, role_type, proto_cap, pbuf);
|
}
|
|
u32 rtw_restructure_he_ie(_adapter *padapter,
|
struct _ADAPTER_LINK *padapter_link,
|
u8 *in_ie, u8 *out_ie, uint in_len,
|
uint *pout_len, enum band_type band)
|
{
|
struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv);
|
struct he_priv *phepriv = &pmlmepriv->hepriv;
|
u32 ielen;
|
u8 *out_he_op_ie, *he_cap_ie, *he_op_ie;
|
u8 he_cap_eid_ext = WLAN_EID_EXTENSION_HE_CAPABILITY;
|
u8 he_op_eid_ext = WLAN_EID_EXTENSION_HE_OPERATION;
|
#if CONFIG_IEEE80211_BAND_6GHZ
|
u8 *he_6g_bcap_ie;
|
u8 he_6g_bcap_eid_ext = WLAN_EID_EXT_HE_6G_CAP;
|
#endif
|
|
rtw_he_use_default_setting(padapter, padapter_link);
|
|
he_cap_ie = rtw_get_ie_ex(in_ie + 12, in_len - 12, WLAN_EID_EXTENSION, &he_cap_eid_ext, 1, NULL, &ielen);
|
if (!he_cap_ie || (ielen > (HE_CAP_ELE_MAX_LEN + 2)))
|
goto exit;
|
*pout_len += rtw_build_he_cap_ie(padapter, padapter_link, out_ie + *pout_len, band);
|
|
he_op_ie = rtw_get_ie_ex(in_ie + 12, in_len - 12, WLAN_EID_EXTENSION, &he_op_eid_ext, 1, out_ie + *pout_len, &ielen);
|
if (!he_op_ie || (ielen > (HE_OPER_ELE_MAX_LEN + 2)))
|
goto exit;
|
*pout_len += ielen;
|
|
phepriv->he_option = _TRUE;
|
|
#if CONFIG_IEEE80211_BAND_6GHZ
|
he_6g_bcap_ie = rtw_get_ie_ex(in_ie + 12, in_len - 12, WLAN_EID_EXTENSION, &he_6g_bcap_eid_ext, 1, out_ie + *pout_len, &ielen);
|
if (!he_6g_bcap_ie || (ielen > (HE_6G_BAND_CAP_MAX_LEN + 2)))
|
goto exit;
|
*pout_len += rtw_build_he_6g_band_cap_ie(padapter, padapter_link, out_ie + *pout_len + 2);
|
#endif
|
|
exit:
|
return phepriv->he_option;
|
}
|
|
static int rtw_build_he_oper_params(_adapter *padapter, u8 *pbuf, bool he_6g_op_present)
|
{
|
/* Set HE Operation Parameters */
|
|
int info_len = HE_OPER_PARAMS_LEN;
|
|
SET_HE_OP_PARA_DEFAULT_PE_DUR(pbuf, 0x4);
|
SET_HE_OP_PARA_TXOP_DUR_RTS_THRESHOLD(pbuf, 0x3ff);
|
#if CONFIG_IEEE80211_BAND_6GHZ
|
if (he_6g_op_present)
|
SET_HE_OP_PARA_6GHZ_OP_INFO_PRESENT(pbuf, 0x1);
|
#endif
|
|
return info_len;
|
}
|
|
static int rtw_build_he_oper_bss_color_info(_adapter *padapter,
|
struct _ADAPTER_LINK *padapter_link,
|
u8 *pbuf)
|
{
|
/* Set BSS Color Information */
|
int info_len = HE_OPER_BSS_COLOR_INFO_LEN;
|
struct rtw_wifi_role_t *wrole = padapter->phl_role;
|
struct protocol_cap_t *proto_cap = &(padapter_link->wrlink->protocol_cap);
|
|
SET_HE_OP_BSS_COLOR_INFO_BSS_COLOR(pbuf, proto_cap->bsscolor);
|
|
return info_len;
|
}
|
|
static int rtw_build_he_oper_basic_mcs_set(_adapter *padapter, u8 *pbuf)
|
{
|
/* Set Basic HE-MCS and NSS Set */
|
|
int info_len = HE_OPER_BASIC_MCS_LEN;
|
|
_rtw_memset(pbuf, HE_MSC_NOT_SUPP_BYTE, info_len);
|
|
SET_HE_OP_BASIC_MCS_1SS(pbuf, HE_MCS_SUPP_MSC0_TO_MSC11);
|
SET_HE_OP_BASIC_MCS_2SS(pbuf, HE_MCS_SUPP_MSC0_TO_MSC11);
|
|
return info_len;
|
}
|
|
static int rtw_build_vht_oper_info(_adapter *padapter, u8 *pbuf)
|
{
|
/* Set VHT Operation Information (optional) */
|
|
int info_len = 0;
|
|
return info_len;
|
}
|
|
static int rtw_build_max_cohost_bssid_ind(_adapter *padapter, u8 *pbuf)
|
{
|
/* Set Max Co-Hosted BSSID Indicator (optional) */
|
|
int info_len = 0;
|
|
return info_len;
|
}
|
|
static int rtw_build_6g_oper_info(_adapter *padapter, struct _ADAPTER_LINK *padapter_link,
|
u8 *pbuf, struct rtw_chan_def *chandef)
|
{
|
struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv;
|
int info_len = 5;
|
|
/* Set 6GHz Operation Information */
|
SET_HE_OP_INFO_PRIMARY_CHAN(pbuf, chandef->chan);
|
|
if (!chandef->center_freq1)
|
SET_HE_OP_INFO_CENTER_FREQ_0(pbuf, chandef->chan);
|
else
|
SET_HE_OP_INFO_CENTER_FREQ_0(pbuf, chandef->center_freq1);
|
SET_HE_OP_INFO_CENTER_FREQ_1(pbuf, chandef->center_freq2);
|
SET_HE_OP_INFO_CHAN_WIDTH(pbuf, chandef->bw);
|
SET_HE_OP_INFO_MIN_RATE(pbuf, 0x6);
|
|
/* Set 6GHz Operation Information (optional) */
|
return info_len;
|
}
|
|
u32 rtw_build_he_operation_ie(_adapter *padapter,
|
struct _ADAPTER_LINK *padapter_link,
|
u8 *pbuf, struct rtw_chan_def *chandef)
|
{
|
struct link_mlme_priv *pmlmepriv = &padapter_link->mlmepriv;
|
struct he_priv *phepriv = &pmlmepriv->hepriv;
|
u32 he_oper_total_len = 0, len = 0;
|
u8* poper_start = phepriv->he_op;
|
u8* poper = poper_start;
|
bool he_6g_op_present = false;
|
|
if (chandef->band == BAND_ON_6G)
|
he_6g_op_present = true;
|
|
_rtw_memset(poper, 0, HE_OPER_ELE_MAX_LEN);
|
|
/* Ele ID Extension */
|
*poper++ = WLAN_EID_EXTENSION_HE_OPERATION;
|
|
/* HE Oper Params */
|
poper += rtw_build_he_oper_params(padapter, poper, he_6g_op_present);
|
|
/* BSS Color Info */
|
poper += rtw_build_he_oper_bss_color_info(padapter, padapter_link, poper);
|
|
/* Basic MCS and NSS Set */
|
poper += rtw_build_he_oper_basic_mcs_set(padapter, poper);
|
|
/* VHT Oper Info */
|
poper += rtw_build_vht_oper_info(padapter, poper);
|
|
/* Max Co-Hosted BSSID Indicator */
|
poper += rtw_build_max_cohost_bssid_ind(padapter, poper);
|
|
#if CONFIG_IEEE80211_BAND_6GHZ
|
/* 6G Oper Info */
|
if (he_6g_op_present)
|
poper += rtw_build_6g_oper_info(padapter, padapter_link, poper, chandef);
|
#endif
|
|
he_oper_total_len = (poper - poper_start);
|
|
pbuf = rtw_set_ie(pbuf, WLAN_EID_EXTENSION, he_oper_total_len, poper_start, &len);
|
|
return len;
|
}
|
|
void HEOnAssocRsp(_adapter *padapter)
|
{
|
struct _ADAPTER_LINK *padapter_link = GET_PRIMARY_LINK(padapter);
|
struct link_mlme_priv *pmlmepriv = &padapter_link->mlmepriv;
|
struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
|
struct link_mlme_ext_priv *pmlmeext = &padapter_link->mlmeextpriv;
|
struct link_mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
|
u8 ht_AMPDU_len;
|
|
if (!pmlmeinfo->VHT_enable)
|
return;
|
|
if (!pmlmeinfo->HE_enable)
|
return;
|
|
RTW_INFO("%s\n", __FUNCTION__);
|
|
/* AMPDU related settings here ? */
|
}
|
|
void rtw_he_ies_attach(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, WLAN_BSSID_EX *pnetwork, enum band_type band)
|
{
|
struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv);
|
u8 he_cap_eid_ext = WLAN_EID_EXTENSION_HE_CAPABILITY;
|
u8 cap_len, operation_len;
|
uint len = 0;
|
sint ie_len = 0;
|
u8 *p = NULL;
|
|
p = rtw_get_ie_ex(pnetwork->IEs + _BEACON_IE_OFFSET_, pnetwork->IELength - _BEACON_IE_OFFSET_,
|
WLAN_EID_EXTENSION, &he_cap_eid_ext, 1, NULL, &ie_len);
|
if (p && ie_len > 0)
|
return;
|
|
rtw_he_use_default_setting(padapter, padapter_link);
|
cap_len = rtw_build_he_cap_ie(padapter, padapter_link, pnetwork->IEs + pnetwork->IELength, band);
|
|
pnetwork->IELength += cap_len;
|
|
operation_len = rtw_build_he_operation_ie(padapter, padapter_link, pnetwork->IEs + pnetwork->IELength,
|
&padapter_link->mlmeextpriv.chandef);
|
pnetwork->IELength += operation_len;
|
|
pmlmepriv->hepriv.he_option = _TRUE;
|
}
|
|
void rtw_he_ies_detach(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, WLAN_BSSID_EX *pnetwork)
|
{
|
struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv);
|
u8 he_cap_eid_ext = WLAN_EID_EXTENSION_HE_CAPABILITY;
|
u8 he_op_eid_ext = WLAN_EID_EXTENSION_HE_OPERATION;
|
|
rtw_remove_bcn_ie_ex(padapter, pnetwork, WLAN_EID_EXTENSION, &he_cap_eid_ext, 1);
|
rtw_remove_bcn_ie_ex(padapter, pnetwork, WLAN_EID_EXTENSION, &he_op_eid_ext, 1);
|
|
pmlmepriv->hepriv.he_option = _FALSE;
|
}
|
|
u8 rtw_he_htc_en(_adapter *padapter, struct sta_info *psta)
|
{
|
struct rtw_wifi_role_t *wrole = padapter->phl_role;
|
|
if (rtw_phl_is_ap_category(wrole->type))
|
return 0;
|
|
return 1;
|
}
|
|
void rtw_he_fill_htc(_adapter *padapter, struct pkt_attrib *pattrib, u32 *phtc_buf)
|
{
|
struct link_mlme_priv *pmlmepriv = &pattrib->adapter_link->mlmepriv;
|
struct rtw_he_actrl_om *cur_om_info = &(pmlmepriv->hepriv.om_info);
|
|
SET_HE_VAR_HTC(phtc_buf);
|
SET_HE_VAR_HTC_CID_CAS(phtc_buf);
|
|
/* CONFIG_80211AX_HE_TODO */
|
|
if ((pattrib->type == WIFI_DATA_TYPE &&
|
cur_om_info->actrl_om_normal_tx &&
|
cur_om_info->actrl_om_normal_tx_cnt != 0) ||
|
pattrib->type == WIFI_MGT_TYPE) {
|
|
SET_HE_VAR_HTC_CID_OM(phtc_buf);
|
SET_HE_VAR_HTC_OM_RX_NSS(phtc_buf, cur_om_info->om_actrl_ele.rx_nss);
|
SET_HE_VAR_HTC_OM_CH_WIDTH(phtc_buf, cur_om_info->om_actrl_ele.channel_width);
|
SET_HE_VAR_HTC_OM_UL_MU_DIS(phtc_buf, cur_om_info->om_actrl_ele.ul_mu_disable);
|
SET_HE_VAR_HTC_OM_TX_NSTS(phtc_buf, cur_om_info->om_actrl_ele.tx_nsts);
|
SET_HE_VAR_HTC_OM_ER_SU_DIS(phtc_buf, cur_om_info->om_actrl_ele.er_su_disable);
|
SET_HE_VAR_HTC_OM_DL_MU_MIMO_RR(phtc_buf, cur_om_info->om_actrl_ele.dl_mu_mimo_rr);
|
SET_HE_VAR_HTC_OM_UL_MU_DATA_DIS(phtc_buf, cur_om_info->om_actrl_ele.ul_mu_data_disable);
|
if (cur_om_info->actrl_om_normal_tx_cnt) {
|
/*RTW_INFO("%s, cur_om_info->actrl_om_normal_tx_cnt=%d\n", __func__, cur_om_info->actrl_om_normal_tx_cnt);*/
|
cur_om_info->actrl_om_normal_tx_cnt --;
|
}
|
}
|
|
}
|
|
void rtw_he_set_om_info(_adapter *padapter, struct _ADAPTER_LINK *alink, u8 om_mask, struct rtw_he_actrl_om *om_info)
|
{
|
struct link_mlme_priv *pmlmepriv = &(alink->mlmepriv);
|
struct rtw_he_actrl_om *cur_om_info = &(pmlmepriv->hepriv.om_info);
|
|
if (om_mask & OM_RX_NSS)
|
cur_om_info->om_actrl_ele.rx_nss = om_info->om_actrl_ele.rx_nss;
|
|
if (om_mask & OM_CH_BW)
|
cur_om_info->om_actrl_ele.channel_width= om_info->om_actrl_ele.channel_width;
|
|
if (om_mask & OM_UL_MU_DIS)
|
cur_om_info->om_actrl_ele.ul_mu_disable= om_info->om_actrl_ele.ul_mu_disable;
|
|
if (om_mask & OM_TX_NSTS)
|
cur_om_info->om_actrl_ele.tx_nsts= om_info->om_actrl_ele.tx_nsts;
|
|
if (om_mask & OM_ER_SU_DIS)
|
cur_om_info->om_actrl_ele.er_su_disable= om_info->om_actrl_ele.er_su_disable;
|
|
if (om_mask & OM_DL_MU_RR)
|
cur_om_info->om_actrl_ele.dl_mu_mimo_rr= om_info->om_actrl_ele.dl_mu_mimo_rr;
|
|
if (om_mask & OM_UL_MU_DATA_DIS)
|
cur_om_info->om_actrl_ele.ul_mu_data_disable= om_info->om_actrl_ele.ul_mu_data_disable;
|
|
cur_om_info->actrl_om_normal_tx = om_info->actrl_om_normal_tx;
|
cur_om_info->actrl_om_normal_tx_cnt = om_info->actrl_om_normal_tx_cnt;
|
#if 0
|
RTW_INFO("%s, cur_om_info->om_actrl_ele.rx_nss = %d\n", __func__, cur_om_info->om_actrl_ele.rx_nss);
|
RTW_INFO("%s, cur_om_info->om_actrl_ele.channel_width = %d\n", __func__, cur_om_info->om_actrl_ele.channel_width);
|
RTW_INFO("%s, cur_om_info->om_actrl_ele.ul_mu_disable = %d\n", __func__, cur_om_info->om_actrl_ele.ul_mu_disable);
|
RTW_INFO("%s, cur_om_info->om_actrl_ele.tx_nsts = %d\n", __func__, cur_om_info->om_actrl_ele.tx_nsts);
|
RTW_INFO("%s, cur_om_info->om_actrl_ele.er_su_disable = %d\n", __func__, cur_om_info->om_actrl_ele.er_su_disable);
|
RTW_INFO("%s, cur_om_info->om_actrl_ele.dl_mu_mimo_rr = %d\n", __func__, cur_om_info->om_actrl_ele.dl_mu_mimo_rr);
|
RTW_INFO("%s, cur_om_info->om_actrl_ele.ul_mu_data_disable = %d\n", __func__, cur_om_info->om_actrl_ele.ul_mu_data_disable);
|
RTW_INFO("%s, cur_om_info->actrl_om_normal_tx = %d\n", __func__, cur_om_info->actrl_om_normal_tx);
|
RTW_INFO("%s, cur_om_info->actrl_om_normal_tx_cnt = %d\n", __func__, cur_om_info->actrl_om_normal_tx_cnt);
|
#endif
|
}
|
|
void rtw_he_init_om_info(_adapter *padapter, struct _ADAPTER_LINK *padapter_link)
|
{
|
struct rtw_wifi_role_t *wrole = padapter->phl_role;
|
struct link_mlme_priv *pmlmepriv = &(padapter_link->mlmepriv);
|
struct rtw_wifi_role_link_t *rlink = padapter_link->wrlink;
|
struct protocol_cap_t *proto_cap = &(rlink->protocol_cap);
|
struct rtw_he_actrl_om *cur_om_info = &(pmlmepriv->hepriv.om_info);
|
|
cur_om_info->om_actrl_ele.rx_nss = proto_cap->nss_rx - 1;
|
|
switch (rlink->chandef.bw) {
|
case CHANNEL_WIDTH_20:
|
cur_om_info->om_actrl_ele.channel_width = 0;
|
break;
|
case CHANNEL_WIDTH_40:
|
cur_om_info->om_actrl_ele.channel_width = 1;
|
break;
|
case CHANNEL_WIDTH_80:
|
cur_om_info->om_actrl_ele.channel_width = 2;
|
break;
|
case CHANNEL_WIDTH_160:
|
case CHANNEL_WIDTH_80_80:
|
cur_om_info->om_actrl_ele.channel_width = 3;
|
break;
|
default:
|
RTW_WARN("%s, HE OM control not support CH BW (%d), set to 0 (20M)\n", __func__, rlink->chandef.bw);
|
cur_om_info->om_actrl_ele.channel_width = 0;
|
break;
|
}
|
|
cur_om_info->om_actrl_ele.ul_mu_disable = _FALSE;
|
cur_om_info->om_actrl_ele.tx_nsts = proto_cap->nss_tx - 1;
|
cur_om_info->om_actrl_ele.er_su_disable = _FALSE;
|
cur_om_info->om_actrl_ele.dl_mu_mimo_rr = _FALSE;
|
cur_om_info->om_actrl_ele.ul_mu_data_disable = _FALSE;
|
cur_om_info->actrl_om_normal_tx = _FALSE;
|
cur_om_info->actrl_om_normal_tx_cnt = 0;
|
|
}
|
|
void rtw_update_he_ies(_adapter *padapter, struct _ADAPTER_LINK *padapter_link, WLAN_BSSID_EX *pnetwork,
|
struct rtw_chan_def *chandef)
|
{
|
u8 he_cap_ie_len;
|
u8 he_cap_ie[255];
|
u8 he_cap_eid_ext = WLAN_EID_EXTENSION_HE_CAPABILITY;
|
u8 he_op_ie_len;
|
u8 he_op_ie[255];
|
u8 he_op_eid_ext = WLAN_EID_EXTENSION_HE_OPERATION;
|
|
RTW_INFO("Don't setting HE capability/operation IE from hostap, builded by driver temporarily\n");
|
rtw_he_use_default_setting(padapter, padapter_link);
|
|
rtw_remove_bcn_ie_ex(padapter, pnetwork, WLAN_EID_EXTENSION, &he_cap_eid_ext, 1);
|
he_cap_ie_len = rtw_build_he_cap_ie(padapter, padapter_link, he_cap_ie, chandef->band);
|
rtw_add_bcn_ie_ex(padapter, pnetwork, he_cap_eid_ext, he_cap_ie + 2, he_cap_ie_len - 2);
|
|
rtw_remove_bcn_ie_ex(padapter, pnetwork, WLAN_EID_EXTENSION, &he_op_eid_ext, 1);
|
he_op_ie_len = rtw_build_he_operation_ie(padapter, padapter_link, he_op_ie, chandef);
|
rtw_add_bcn_ie_ex(padapter, pnetwork, he_op_eid_ext, he_op_ie + 2, he_op_ie_len - 2);
|
}
|
|
void rtw_update_probe_rsp_he_cap_and_op(struct _ADAPTER *a, u8 *ies, sint *ies_len, enum band_type band)
|
{
|
struct _ADAPTER_LINK *a_link = GET_PRIMARY_LINK(a);
|
u8 cur_he_cap_ie[255], cur_he_op_ie[255];
|
uint cur_he_cap_ie_len, cur_he_op_ie_len;
|
u8 *he_cap_ie, *he_op_ie;
|
uint ie_len;
|
u8 he_cap_eid_ext = WLAN_EID_EXTENSION_HE_CAPABILITY;
|
u8 he_op_eid_ext = WLAN_EID_EXTENSION_HE_OPERATION;
|
|
he_cap_ie = rtw_get_ie_ex(ies, *ies_len, WLAN_EID_EXTENSION,
|
&he_cap_eid_ext, 1, NULL, &ie_len);
|
if (he_cap_ie) {
|
cur_he_cap_ie_len = rtw_build_he_cap_ie(a, a_link, cur_he_cap_ie, band);
|
rtw_ies_update_ie_ex(ies, ies_len, 0, WLAN_EID_EXTENSION_HE_CAPABILITY,
|
cur_he_cap_ie, cur_he_cap_ie_len);
|
}
|
|
he_op_ie = rtw_get_ie_ex(ies, *ies_len, WLAN_EID_EXTENSION,
|
&he_op_eid_ext, 1, NULL, &ie_len);
|
if (he_op_ie) {
|
cur_he_op_ie_len = rtw_build_he_operation_ie(a, a_link,
|
cur_he_op_ie, &a_link->mlmeextpriv.chandef);
|
rtw_ies_update_ie_ex(ies, ies_len, 0, WLAN_EID_EXTENSION_HE_OPERATION,
|
cur_he_op_ie, cur_he_op_ie_len);
|
}
|
}
|
|
void rtw_he_om_ctrl_trx_ss(_adapter *adapter, struct _ADAPTER_LINK *alink,
|
struct sta_info *sta, u8 final_ss, bool need_update_ra)
|
{
|
struct rtw_he_actrl_om om_info = {0};
|
u8 om_mask;
|
|
om_mask = OM_RX_NSS | OM_TX_NSTS;
|
|
RTW_INFO("%s, issue qos null data to update OMI rxnss\n", __func__);
|
if (alink->mlmeextpriv.chandef.bw == CHANNEL_WIDTH_160 ||
|
alink->mlmeextpriv.chandef.bw == CHANNEL_WIDTH_80_80)
|
/* 11ax D8 9.2.4.6a.2 OM Control */
|
/* 160/80+80 */
|
om_info.om_actrl_ele.rx_nss = final_ss;
|
else
|
/* 20/40/80 */
|
om_info.om_actrl_ele.rx_nss = final_ss - 1;
|
|
om_info.om_actrl_ele.tx_nsts = final_ss - 1;
|
|
rtw_he_set_om_info(adapter, alink, om_mask, &om_info);
|
issue_qos_nulldata(adapter, alink, NULL, 0, 0, 3, 10, _TRUE);
|
|
if (need_update_ra)
|
rtw_phl_cmd_change_stainfo(adapter_to_dvobj(adapter)->phl,
|
sta->phl_sta,
|
STA_CHG_RAMASK,
|
NULL,
|
0,
|
PHL_CMD_DIRECTLY,
|
0);
|
|
}
|
|
int rtw_he_om_ctrl_ulmu_dis(_adapter *padapter, struct _ADAPTER_LINK *alink)
|
{
|
struct rtw_he_actrl_om om_info = {0};
|
u8 om_mask = 0;
|
|
om_mask = om_mask | OM_UL_MU_DIS;
|
om_info.om_actrl_ele.ul_mu_disable = _TRUE;
|
|
rtw_he_set_om_info(padapter, alink, om_mask, &om_info);
|
return issue_qos_nulldata(padapter, alink, NULL, 0, 0, 3, 10, _TRUE);
|
}
|
|
void rtw_process_he_triggerframe(_adapter *padapter,
|
union recv_frame *precv_frame)
|
{
|
|
void *phl;
|
|
struct sta_info *psta = NULL;
|
struct rtw_phl_stainfo_t *phl_sta = NULL;
|
struct dvobj_priv *d = adapter_to_dvobj(padapter);
|
u8 *trigger_frame = precv_frame->u.hdr.rx_data;
|
u16 trigger_length = precv_frame->u.hdr.len;
|
struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
|
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
|
struct _ADAPTER_LINK *padapter_link = precv_frame->u.hdr.adapter_link;
|
struct wlan_network *cur_network = &(padapter_link->mlmepriv.cur_network);
|
struct sta_priv *pstapriv = &padapter->stapriv;
|
u16 aid = 0;
|
u8 *user_info;
|
u16 remain_length = 0;
|
u8 trigger_type = 0;
|
bool ra_is_bc = _FALSE;
|
u8 trigger_bw = 0;
|
u16 trigger_rua = 0;
|
phl = GET_PHL_INFO(d);
|
|
|
if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _FALSE)
|
return;
|
|
/* check length */
|
if (trigger_length < TRIGGER_FRAME_MIN_LENGTH) {
|
RTW_INFO("%s [T_Frame]TRIGGER_FRAME_MIN_LENGTH(%d) trigger_length=%d\n",
|
__func__,
|
TRIGGER_FRAME_MIN_LENGTH,
|
trigger_length);
|
return;
|
}
|
|
/* Check TA : from connected AP*/
|
if(_rtw_memcmp(get_addr2_ptr(trigger_frame), cur_network->network.MacAddress, ETH_ALEN) == _FALSE) {
|
RTW_INFO("%s [T_Frame] Trigger Frame error, not from connected AP\n", __func__);
|
return;
|
}
|
|
/* parsing trigger frame sub-type*/
|
trigger_type = GET_TRIGGER_FRAME_TYPE(trigger_frame);
|
trigger_bw = GET_TRIGGER_FRAME_COM_INFO_BW(trigger_frame);
|
switch (trigger_type) {
|
case TRIGGER_FRAME_T_BASIC:
|
case TRIGGER_FRAME_T_MUBAR:
|
{
|
#ifdef RTW_WKARD_TRIGGER_FRAME_PARSER
|
user_info = trigger_frame + 24;
|
remain_length = trigger_length - 24;
|
/*ToDo CONFIG_RTW_MLD: tigger frame is BC, need check*/
|
psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(trigger_frame));
|
if (psta == NULL)
|
break;
|
|
phl_sta = psta->phl_sta;
|
if(phl_sta == NULL)
|
break;
|
|
/* start from User Info */
|
while (remain_length >= TRIGGER_FRAME_BASIC_USER_INFO_SZ) {
|
aid = GET_TRIGGER_FRAME_USER_INFO_AID12(user_info);
|
trigger_rua = GET_TRIGGER_FRAME_USER_INFO_RUA(user_info);
|
RTW_DBG("%s [T_Frame] aid=0x%x, UL MCS=0x%x, RU_alloc=0x%x, BW=0x%x \n",
|
__func__, aid, GET_TRIGGER_FRAME_USER_INFO_UL_MCS(user_info), trigger_rua, trigger_bw);
|
if ((aid == phl_sta->aid) && (aid != 0)) {
|
phl_sta->stats.rx_tf_cnt++;
|
RTW_DBG("%s [T_Frame]phl_sta->stats.rx_tf_cnt(%d)\n",
|
__func__,
|
phl_sta->stats.rx_tf_cnt);
|
#ifdef RTW_WKARD_TRIGGER_PWR_DIFF_LARGE
|
if (trigger_bw == TRIGGER_UL_BW_80_80_160 && (trigger_rua >> 1) <= RTW_HE_RU106_8) {
|
phl_sta->flag_pwr_diff_large = true;
|
RTW_DBG("%s, phl_sta->flag_pwr_diff_large=%d\n", __func__, phl_sta->flag_pwr_diff_large);
|
}
|
#endif
|
break;
|
}
|
if (aid == 0xfff) {
|
/* padding content, break it */
|
break;
|
}
|
/* shift to next user info */
|
user_info += TRIGGER_FRAME_BASIC_USER_INFO_SZ;
|
remain_length -= TRIGGER_FRAME_BASIC_USER_INFO_SZ;
|
}
|
#endif /*RTW_WKARD_TRIGGER_FRAME_PARSER*/
|
}
|
break;
|
case TRIGGER_FRAME_T_BFRP:
|
/* fall through */
|
case TRIGGER_FRAME_T_MURTS:
|
/* fall through */
|
case TRIGGER_FRAME_T_BSRP:
|
/* fall through */
|
case TRIGGER_FRAME_T_GCR_MUBAR:
|
/* fall through */
|
case TRIGGER_FRAME_T_BQRP:
|
/* fall through */
|
case TRIGGER_FRAME_T_NFRP:
|
/* fall through */
|
case TRIGGER_FRAME_T_RSVD:
|
break;
|
}
|
}
|
|
#endif /* CONFIG_80211AX_HE */
|