rtw_vht.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17. *
  18. *
  19. ******************************************************************************/
  20. #define _RTW_VHT_C
  21. #include <drv_types.h>
  22. #include <hal_data.h>
  23. #ifdef CONFIG_80211AC_VHT
  24. /* 20/40/80, ShortGI, MCS Rate */
  25. const u16 VHT_MCS_DATA_RATE[3][2][30] = {
  26. { {
  27. 13, 26, 39, 52, 78, 104, 117, 130, 156, 156,
  28. 26, 52, 78, 104, 156, 208, 234, 260, 312, 312,
  29. 39, 78, 117, 156, 234, 312, 351, 390, 468, 520
  30. }, /* Long GI, 20MHz */
  31. {
  32. 14, 29, 43, 58, 87, 116, 130, 144, 173, 173,
  33. 29, 58, 87, 116, 173, 231, 260, 289, 347, 347,
  34. 43, 87, 130, 173, 260, 347, 390, 433, 520, 578
  35. }
  36. }, /* Short GI, 20MHz */
  37. { {
  38. 27, 54, 81, 108, 162, 216, 243, 270, 324, 360,
  39. 54, 108, 162, 216, 324, 432, 486, 540, 648, 720,
  40. 81, 162, 243, 324, 486, 648, 729, 810, 972, 1080
  41. }, /* Long GI, 40MHz */
  42. {
  43. 30, 60, 90, 120, 180, 240, 270, 300, 360, 400,
  44. 60, 120, 180, 240, 360, 480, 540, 600, 720, 800,
  45. 90, 180, 270, 360, 540, 720, 810, 900, 1080, 1200
  46. }
  47. }, /* Short GI, 40MHz */
  48. { {
  49. 59, 117, 176, 234, 351, 468, 527, 585, 702, 780,
  50. 117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560,
  51. 176, 351, 527, 702, 1053, 1404, 1580, 1755, 2106, 2340
  52. }, /* Long GI, 80MHz */
  53. {
  54. 65, 130, 195, 260, 390, 520, 585, 650, 780, 867,
  55. 130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1734,
  56. 195, 390, 585, 780, 1170, 1560, 1755, 1950, 2340, 2600
  57. }
  58. } /* Short GI, 80MHz */
  59. };
  60. u8 rtw_get_vht_highest_rate(u8 *pvht_mcs_map)
  61. {
  62. u8 i, j;
  63. u8 bit_map;
  64. u8 vht_mcs_rate = 0;
  65. for (i = 0; i < 2; i++) {
  66. if (pvht_mcs_map[i] != 0xff) {
  67. for (j = 0; j < 8; j += 2) {
  68. bit_map = (pvht_mcs_map[i] >> j) & 3;
  69. if (bit_map != 3)
  70. vht_mcs_rate = MGN_VHT1SS_MCS7 + 10 * j / 2 + i * 40 + bit_map; /* VHT rate indications begin from 0x90 */
  71. }
  72. }
  73. }
  74. /* RTW_INFO("HighestVHTMCSRate is %x\n", vht_mcs_rate); */
  75. return vht_mcs_rate;
  76. }
  77. u8 rtw_vht_mcsmap_to_nss(u8 *pvht_mcs_map)
  78. {
  79. u8 i, j;
  80. u8 bit_map;
  81. u8 nss = 0;
  82. for (i = 0; i < 2; i++) {
  83. if (pvht_mcs_map[i] != 0xff) {
  84. for (j = 0; j < 8; j += 2) {
  85. bit_map = (pvht_mcs_map[i] >> j) & 3;
  86. if (bit_map != 3)
  87. nss++;
  88. }
  89. }
  90. }
  91. /* RTW_INFO("%s : %dSS\n", __FUNCTION__, nss); */
  92. return nss;
  93. }
  94. void rtw_vht_nss_to_mcsmap(u8 nss, u8 *target_mcs_map, u8 *cur_mcs_map)
  95. {
  96. u8 i, j;
  97. u8 cur_rate, target_rate;
  98. for (i = 0; i < 2; i++) {
  99. target_mcs_map[i] = 0;
  100. for (j = 0; j < 8; j += 2) {
  101. cur_rate = (cur_mcs_map[i] >> j) & 3;
  102. if (cur_rate == 3) /* 0x3 indicates not supported that num of SS */
  103. target_rate = 3;
  104. else if (nss <= ((j / 2) + i * 4))
  105. target_rate = 3;
  106. else
  107. target_rate = cur_rate;
  108. target_mcs_map[i] |= (target_rate << j);
  109. }
  110. }
  111. /* RTW_INFO("%s : %dSS\n", __FUNCTION__, nss); */
  112. }
  113. u16 rtw_vht_mcs_to_data_rate(u8 bw, u8 short_GI, u8 vht_mcs_rate)
  114. {
  115. if (vht_mcs_rate > MGN_VHT3SS_MCS9)
  116. vht_mcs_rate = MGN_VHT3SS_MCS9;
  117. /* RTW_INFO("bw=%d, short_GI=%d, ((vht_mcs_rate - MGN_VHT1SS_MCS0)&0x3f)=%d\n", bw, short_GI, ((vht_mcs_rate - MGN_VHT1SS_MCS0)&0x3f)); */
  118. return VHT_MCS_DATA_RATE[bw][short_GI][((vht_mcs_rate - MGN_VHT1SS_MCS0) & 0x3f)];
  119. }
  120. void rtw_vht_use_default_setting(_adapter *padapter)
  121. {
  122. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  123. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  124. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  125. BOOLEAN bHwLDPCSupport = _FALSE, bHwSTBCSupport = _FALSE;
  126. #ifdef CONFIG_BEAMFORMING
  127. BOOLEAN bHwSupportBeamformer = _FALSE, bHwSupportBeamformee = _FALSE;
  128. u8 mu_bfer, mu_bfee;
  129. #endif /* CONFIG_BEAMFORMING */
  130. u8 rf_type = 0;
  131. u8 tx_nss, rx_nss;
  132. struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
  133. struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
  134. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  135. pvhtpriv->sgi_80m = TEST_FLAG(pregistrypriv->short_gi, BIT2) ? _TRUE : _FALSE;
  136. /* LDPC support */
  137. rtw_hal_get_def_var(padapter, HAL_DEF_RX_LDPC, (u8 *)&bHwLDPCSupport);
  138. CLEAR_FLAGS(pvhtpriv->ldpc_cap);
  139. if (bHwLDPCSupport) {
  140. if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT0))
  141. SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX);
  142. }
  143. rtw_hal_get_def_var(padapter, HAL_DEF_TX_LDPC, (u8 *)&bHwLDPCSupport);
  144. if (bHwLDPCSupport) {
  145. if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT1))
  146. SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX);
  147. }
  148. if (pvhtpriv->ldpc_cap)
  149. RTW_INFO("[VHT] Support LDPC = 0x%02X\n", pvhtpriv->ldpc_cap);
  150. /* STBC */
  151. rtw_hal_get_def_var(padapter, HAL_DEF_TX_STBC, (u8 *)&bHwSTBCSupport);
  152. CLEAR_FLAGS(pvhtpriv->stbc_cap);
  153. if (bHwSTBCSupport) {
  154. if (TEST_FLAG(pregistrypriv->stbc_cap, BIT1))
  155. SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX);
  156. }
  157. rtw_hal_get_def_var(padapter, HAL_DEF_RX_STBC, (u8 *)&bHwSTBCSupport);
  158. if (bHwSTBCSupport) {
  159. if (TEST_FLAG(pregistrypriv->stbc_cap, BIT0))
  160. SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX);
  161. }
  162. if (pvhtpriv->stbc_cap)
  163. RTW_INFO("[VHT] Support STBC = 0x%02X\n", pvhtpriv->stbc_cap);
  164. /* Beamforming setting */
  165. CLEAR_FLAGS(pvhtpriv->beamform_cap);
  166. #ifdef CONFIG_BEAMFORMING
  167. rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMER, (u8 *)&bHwSupportBeamformer);
  168. rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMEE, (u8 *)&bHwSupportBeamformee);
  169. mu_bfer = _FALSE;
  170. mu_bfee = _FALSE;
  171. rtw_hal_get_def_var(padapter, HAL_DEF_VHT_MU_BEAMFORMER, &mu_bfer);
  172. rtw_hal_get_def_var(padapter, HAL_DEF_VHT_MU_BEAMFORMEE, &mu_bfee);
  173. if (TEST_FLAG(pregistrypriv->beamform_cap, BIT0) && bHwSupportBeamformer) {
  174. #ifdef CONFIG_CONCURRENT_MODE
  175. if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
  176. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  177. RTW_INFO("[VHT] CONCURRENT AP Support Beamformer\n");
  178. if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(2))
  179. && (_TRUE == mu_bfer)) {
  180. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
  181. RTW_INFO("[VHT] Support MU-MIMO AP\n");
  182. }
  183. } else
  184. RTW_INFO("[VHT] CONCURRENT not AP ;not allow Support Beamformer\n");
  185. #else
  186. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  187. RTW_INFO("[VHT] Support Beamformer\n");
  188. if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(2))
  189. && (_TRUE == mu_bfer)
  190. && ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
  191. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
  192. RTW_INFO("[VHT] Support MU-MIMO AP\n");
  193. }
  194. #endif
  195. }
  196. if (TEST_FLAG(pregistrypriv->beamform_cap, BIT1) && bHwSupportBeamformee) {
  197. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  198. RTW_INFO("[VHT] Support Beamformee\n");
  199. if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(3))
  200. && (_TRUE == mu_bfee)
  201. && ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)) {
  202. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
  203. RTW_INFO("[VHT] Support MU-MIMO STA\n");
  204. }
  205. }
  206. #endif /* CONFIG_BEAMFORMING */
  207. pvhtpriv->ampdu_len = pregistrypriv->ampdu_factor;
  208. rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
  209. tx_nss = rtw_min(rf_type_to_rf_tx_cnt(rf_type), hal_spec->tx_nss_num);
  210. rx_nss = rtw_min(rf_type_to_rf_rx_cnt(rf_type), hal_spec->rx_nss_num);
  211. /* for now, vhtpriv.vht_mcs_map comes from RX NSS */
  212. rtw_vht_nss_to_mcsmap(rx_nss, pvhtpriv->vht_mcs_map, pregistrypriv->vht_rx_mcs_map);
  213. pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
  214. }
  215. u64 rtw_vht_mcs_map_to_bitmap(u8 *mcs_map, u8 nss)
  216. {
  217. u8 i, j, tmp;
  218. u64 bitmap = 0;
  219. u8 bits_nss = nss * 2;
  220. for (i = j = 0; i < bits_nss; i += 2, j += 10) {
  221. /* every two bits means single sptial stream */
  222. tmp = (mcs_map[i / 8] >> i) & 3;
  223. switch (tmp) {
  224. case 2:
  225. bitmap = bitmap | (0x03ff << j);
  226. break;
  227. case 1:
  228. bitmap = bitmap | (0x01ff << j);
  229. break;
  230. case 0:
  231. bitmap = bitmap | (0x00ff << j);
  232. break;
  233. default:
  234. break;
  235. }
  236. }
  237. RTW_INFO("vht_mcs_map=%02x %02x, nss=%u => bitmap=%016llx\n"
  238. , mcs_map[0], mcs_map[1], nss, bitmap);
  239. return bitmap;
  240. }
  241. void update_sta_vht_info_apmode(_adapter *padapter, PVOID sta)
  242. {
  243. struct sta_info *psta = (struct sta_info *)sta;
  244. struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  245. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  246. struct vht_priv *pvhtpriv_ap = &pmlmepriv->vhtpriv;
  247. struct vht_priv *pvhtpriv_sta = &psta->vhtpriv;
  248. struct ht_priv *phtpriv_sta = &psta->htpriv;
  249. u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, bw_mode = 0;
  250. u16 cur_beamform_cap = 0;
  251. u8 *pcap_mcs;
  252. if (pvhtpriv_sta->vht_option == _FALSE)
  253. return;
  254. bw_mode = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&pvhtpriv_sta->vht_op_mode_notify);
  255. /* if (bw_mode > psta->bw_mode) */
  256. psta->bw_mode = bw_mode;
  257. /* B4 Rx LDPC */
  258. if (TEST_FLAG(pvhtpriv_ap->ldpc_cap, LDPC_VHT_ENABLE_TX) &&
  259. GET_VHT_CAPABILITY_ELE_RX_LDPC(pvhtpriv_sta->vht_cap)) {
  260. SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
  261. RTW_INFO("Current STA(%d) VHT LDPC = %02X\n", psta->aid, cur_ldpc_cap);
  262. }
  263. pvhtpriv_sta->ldpc_cap = cur_ldpc_cap;
  264. if (psta->bw_mode > pmlmeext->cur_bwmode)
  265. psta->bw_mode = pmlmeext->cur_bwmode;
  266. if (psta->bw_mode == CHANNEL_WIDTH_80) {
  267. /* B5 Short GI for 80 MHz */
  268. pvhtpriv_sta->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi_80m) ? _TRUE : _FALSE;
  269. /* RTW_INFO("Current STA ShortGI80MHz = %d\n", pvhtpriv_sta->sgi_80m); */
  270. } else if (psta->bw_mode >= CHANNEL_WIDTH_160) {
  271. /* B5 Short GI for 80 MHz */
  272. pvhtpriv_sta->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi_80m) ? _TRUE : _FALSE;
  273. /* RTW_INFO("Current STA ShortGI160MHz = %d\n", pvhtpriv_sta->sgi_80m); */
  274. }
  275. /* B8 B9 B10 Rx STBC */
  276. if (TEST_FLAG(pvhtpriv_ap->stbc_cap, STBC_VHT_ENABLE_TX) &&
  277. GET_VHT_CAPABILITY_ELE_RX_STBC(pvhtpriv_sta->vht_cap)) {
  278. SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
  279. RTW_INFO("Current STA(%d) VHT STBC = %02X\n", psta->aid, cur_stbc_cap);
  280. }
  281. pvhtpriv_sta->stbc_cap = cur_stbc_cap;
  282. #ifdef CONFIG_BEAMFORMING
  283. /* B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee */
  284. if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
  285. GET_VHT_CAPABILITY_ELE_SU_BFEE(pvhtpriv_sta->vht_cap)) {
  286. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  287. /*Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP*/
  288. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pvhtpriv_sta->vht_cap) << 8);
  289. }
  290. /* B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer */
  291. if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
  292. GET_VHT_CAPABILITY_ELE_SU_BFER(pvhtpriv_sta->vht_cap)) {
  293. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  294. /*Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM*/
  295. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pvhtpriv_sta->vht_cap) << 12);
  296. }
  297. pvhtpriv_sta->beamform_cap = cur_beamform_cap;
  298. if (cur_beamform_cap)
  299. RTW_INFO("Current STA(%d) VHT Beamforming Setting = %02X\n", psta->aid, cur_beamform_cap);
  300. #endif
  301. /* B23 B24 B25 Maximum A-MPDU Length Exponent */
  302. pvhtpriv_sta->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pvhtpriv_sta->vht_cap);
  303. pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pvhtpriv_sta->vht_cap);
  304. _rtw_memcpy(pvhtpriv_sta->vht_mcs_map, pcap_mcs, 2);
  305. pvhtpriv_sta->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv_sta->vht_mcs_map);
  306. }
  307. void update_hw_vht_param(_adapter *padapter)
  308. {
  309. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  310. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  311. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  312. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  313. u8 ht_AMPDU_len;
  314. ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
  315. if (pvhtpriv->ampdu_len > ht_AMPDU_len)
  316. rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
  317. }
  318. void VHT_caps_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
  319. {
  320. struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
  321. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  322. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  323. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  324. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  325. u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, rf_type = RF_1T1R, tx_nss = 0;
  326. u16 cur_beamform_cap = 0;
  327. u8 *pcap_mcs;
  328. if (pIE == NULL)
  329. return;
  330. if (pvhtpriv->vht_option == _FALSE)
  331. return;
  332. pmlmeinfo->VHT_enable = 1;
  333. /* B4 Rx LDPC */
  334. if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX) &&
  335. GET_VHT_CAPABILITY_ELE_RX_LDPC(pIE->data)) {
  336. SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
  337. RTW_INFO("Current VHT LDPC Setting = %02X\n", cur_ldpc_cap);
  338. }
  339. pvhtpriv->ldpc_cap = cur_ldpc_cap;
  340. /* B5 Short GI for 80 MHz */
  341. pvhtpriv->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pIE->data) & pvhtpriv->sgi_80m) ? _TRUE : _FALSE;
  342. /* RTW_INFO("Current ShortGI80MHz = %d\n", pvhtpriv->sgi_80m); */
  343. /* B8 B9 B10 Rx STBC */
  344. if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX) &&
  345. GET_VHT_CAPABILITY_ELE_RX_STBC(pIE->data)) {
  346. SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
  347. RTW_INFO("Current VHT STBC Setting = %02X\n", cur_stbc_cap);
  348. }
  349. pvhtpriv->stbc_cap = cur_stbc_cap;
  350. #ifdef CONFIG_BEAMFORMING
  351. #ifdef RTW_BEAMFORMING_VERSION_2
  352. /*
  353. * B11 SU Beamformer Capable,
  354. * the target supports Beamformer and we are Beamformee
  355. */
  356. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)
  357. && GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data)) {
  358. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  359. /* Shift to BEAMFORMING_VHT_BEAMFORMEE_STS_CAP */
  360. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pIE->data) << 8);
  361. /*
  362. * B19 MU Beamformer Capable,
  363. * the target supports Beamformer and we are Beamformee
  364. */
  365. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)
  366. && GET_VHT_CAPABILITY_ELE_MU_BFER(pIE->data))
  367. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
  368. }
  369. /*
  370. * B12 SU Beamformee Capable,
  371. * the target supports Beamformee and we are Beamformer
  372. */
  373. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)
  374. && GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data)) {
  375. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  376. /* Shit to BEAMFORMING_VHT_BEAMFORMER_SOUND_DIM */
  377. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pIE->data) << 12);
  378. /*
  379. * B20 MU Beamformee Capable,
  380. * the target supports Beamformee and we are Beamformer
  381. */
  382. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)
  383. && GET_VHT_CAPABILITY_ELE_MU_BFEE(pIE->data))
  384. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
  385. }
  386. pvhtpriv->beamform_cap = cur_beamform_cap;
  387. RTW_INFO("Current VHT Beamforming Setting=0x%04X\n", cur_beamform_cap);
  388. #else /* !RTW_BEAMFORMING_VERSION_2 */
  389. /* B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee */
  390. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
  391. GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data)) {
  392. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  393. /*Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP*/
  394. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pIE->data) << 8);
  395. }
  396. /* B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer */
  397. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
  398. GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data)) {
  399. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  400. /*Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM*/
  401. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pIE->data) << 12);
  402. }
  403. pvhtpriv->beamform_cap = cur_beamform_cap;
  404. if (cur_beamform_cap)
  405. RTW_INFO("Current VHT Beamforming Setting = %02X\n", cur_beamform_cap);
  406. #endif /* !RTW_BEAMFORMING_VERSION_2 */
  407. #endif /* CONFIG_BEAMFORMING */
  408. /* B23 B24 B25 Maximum A-MPDU Length Exponent */
  409. pvhtpriv->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pIE->data);
  410. pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pIE->data);
  411. rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
  412. tx_nss = rtw_min(rf_type_to_rf_tx_cnt(rf_type), hal_spec->tx_nss_num);
  413. rtw_vht_nss_to_mcsmap(tx_nss, pvhtpriv->vht_mcs_map, pcap_mcs);
  414. pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
  415. }
  416. void VHT_operation_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
  417. {
  418. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  419. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  420. if (pIE == NULL)
  421. return;
  422. if (pvhtpriv->vht_option == _FALSE)
  423. return;
  424. }
  425. void rtw_process_vht_op_mode_notify(_adapter *padapter, u8 *pframe, PVOID sta)
  426. {
  427. struct sta_info *psta = (struct sta_info *)sta;
  428. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  429. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  430. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  431. struct registry_priv *regsty = adapter_to_regsty(padapter);
  432. u8 target_bw;
  433. u8 target_rxss, current_rxss;
  434. u8 update_ra = _FALSE;
  435. if (pvhtpriv->vht_option == _FALSE)
  436. return;
  437. target_bw = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(pframe);
  438. target_rxss = (GET_VHT_OPERATING_MODE_FIELD_RX_NSS(pframe) + 1);
  439. if (target_bw != psta->bw_mode) {
  440. if (hal_is_bw_support(padapter, target_bw)
  441. && REGSTY_IS_BW_5G_SUPPORT(regsty, target_bw)
  442. ) {
  443. update_ra = _TRUE;
  444. psta->bw_mode = target_bw;
  445. }
  446. }
  447. current_rxss = rtw_vht_mcsmap_to_nss(psta->vhtpriv.vht_mcs_map);
  448. if (target_rxss != current_rxss) {
  449. u8 vht_mcs_map[2] = {};
  450. update_ra = _TRUE;
  451. rtw_vht_nss_to_mcsmap(target_rxss, vht_mcs_map, psta->vhtpriv.vht_mcs_map);
  452. _rtw_memcpy(psta->vhtpriv.vht_mcs_map, vht_mcs_map, 2);
  453. rtw_hal_update_sta_rate_mask(padapter, psta);
  454. }
  455. if (update_ra)
  456. rtw_dm_ra_mask_wk_cmd(padapter, (u8 *)psta);
  457. }
  458. u32 rtw_build_vht_operation_ie(_adapter *padapter, u8 *pbuf, u8 channel)
  459. {
  460. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  461. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  462. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  463. /* struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; */
  464. u8 ChnlWidth, center_freq, bw_mode;
  465. u32 len = 0;
  466. u8 operation[5];
  467. _rtw_memset(operation, 0, 5);
  468. bw_mode = REGSTY_BW_5G(pregistrypriv); /* TODO: control op bw with other info */
  469. if (hal_chk_bw_cap(padapter, BW_CAP_80M | BW_CAP_160M)
  470. && REGSTY_BW_5G(pregistrypriv) >= CHANNEL_WIDTH_80
  471. ) {
  472. center_freq = rtw_get_center_ch(channel, bw_mode, HAL_PRIME_CHNL_OFFSET_LOWER);
  473. ChnlWidth = 1;
  474. } else {
  475. center_freq = 0;
  476. ChnlWidth = 0;
  477. }
  478. SET_VHT_OPERATION_ELE_CHL_WIDTH(operation, ChnlWidth);
  479. /* center frequency */
  480. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(operation, center_freq);/* Todo: need to set correct center channel */
  481. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(operation, 0);
  482. _rtw_memcpy(operation + 3, pvhtpriv->vht_mcs_map, 2);
  483. rtw_set_ie(pbuf, EID_VHTOperation, 5, operation, &len);
  484. return len;
  485. }
  486. u32 rtw_build_vht_op_mode_notify_ie(_adapter *padapter, u8 *pbuf, u8 bw)
  487. {
  488. /* struct registry_priv *pregistrypriv = &padapter->registrypriv; */
  489. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  490. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  491. u32 len = 0;
  492. u8 opmode = 0;
  493. u8 chnl_width, rx_nss;
  494. chnl_width = bw;
  495. rx_nss = rtw_vht_mcsmap_to_nss(pvhtpriv->vht_mcs_map);
  496. SET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&opmode, chnl_width);
  497. SET_VHT_OPERATING_MODE_FIELD_RX_NSS(&opmode, (rx_nss - 1));
  498. SET_VHT_OPERATING_MODE_FIELD_RX_NSS_TYPE(&opmode, 0); /* Todo */
  499. pvhtpriv->vht_op_mode_notify = opmode;
  500. pbuf = rtw_set_ie(pbuf, EID_OpModeNotification, 1, &opmode, &len);
  501. return len;
  502. }
  503. u32 rtw_build_vht_cap_ie(_adapter *padapter, u8 *pbuf)
  504. {
  505. u8 bw, rf_type, rf_num, rx_stbc_nss = 0;
  506. u16 HighestRate;
  507. u8 *pcap, *pcap_mcs;
  508. u32 len = 0;
  509. u32 rx_packet_offset, max_recvbuf_sz;
  510. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  511. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  512. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  513. pcap = pvhtpriv->vht_cap;
  514. _rtw_memset(pcap, 0, 32);
  515. /* B0 B1 Maximum MPDU Length */
  516. rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
  517. rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
  518. RTW_DBG("%s, line%d, Available RX buf size = %d bytes\n.", __FUNCTION__, __LINE__, max_recvbuf_sz - rx_packet_offset);
  519. if ((max_recvbuf_sz - rx_packet_offset) >= 11454) {
  520. SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, 2);
  521. RTW_INFO("%s, line%d, Set MAX MPDU len = 11454 bytes\n.", __FUNCTION__, __LINE__);
  522. } else if ((max_recvbuf_sz - rx_packet_offset) >= 7991) {
  523. SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, 1);
  524. RTW_INFO("%s, line%d, Set MAX MPDU len = 7991 bytes\n.", __FUNCTION__, __LINE__);
  525. } else if ((max_recvbuf_sz - rx_packet_offset) >= 3895) {
  526. SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, 0);
  527. RTW_INFO("%s, line%d, Set MAX MPDU len = 3895 bytes\n.", __FUNCTION__, __LINE__);
  528. } else
  529. RTW_ERR("%s, line%d, Error!! Available RX buf size < 3895 bytes\n.", __FUNCTION__, __LINE__);
  530. /* B2 B3 Supported Channel Width Set */
  531. if (hal_chk_bw_cap(padapter, BW_CAP_160M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) {
  532. if (hal_chk_bw_cap(padapter, BW_CAP_80_80M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_80_80))
  533. SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 2);
  534. else
  535. SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 1);
  536. } else
  537. SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 0);
  538. /* B4 Rx LDPC */
  539. if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX)) {
  540. SET_VHT_CAPABILITY_ELE_RX_LDPC(pcap, 1);
  541. RTW_INFO("[VHT] Declare supporting RX LDPC\n");
  542. }
  543. /* B5 ShortGI for 80MHz */
  544. SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pcap, pvhtpriv->sgi_80m ? 1 : 0); /* We can receive Short GI of 80M */
  545. if (pvhtpriv->sgi_80m)
  546. RTW_INFO("[VHT] Declare supporting SGI 80MHz\n");
  547. /* B6 ShortGI for 160MHz */
  548. /* SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pcap, pvhtpriv->sgi_80m? 1 : 0); */
  549. /* B7 Tx STBC */
  550. if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX)) {
  551. SET_VHT_CAPABILITY_ELE_TX_STBC(pcap, 1);
  552. RTW_INFO("[VHT] Declare supporting TX STBC\n");
  553. }
  554. /* B8 B9 B10 Rx STBC */
  555. if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX)) {
  556. rtw_hal_get_def_var(padapter, HAL_DEF_RX_STBC, (u8 *)(&rx_stbc_nss));
  557. SET_VHT_CAPABILITY_ELE_RX_STBC(pcap, rx_stbc_nss);
  558. RTW_INFO("[VHT] Declare supporting RX STBC = %d\n", rx_stbc_nss);
  559. }
  560. /* B11 SU Beamformer Capable */
  561. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
  562. SET_VHT_CAPABILITY_ELE_SU_BFER(pcap, 1);
  563. RTW_INFO("[VHT] Declare supporting SU Bfer\n");
  564. /* B16 17 18 Number of Sounding Dimensions */
  565. rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num);
  566. SET_VHT_CAPABILITY_ELE_SOUNDING_DIMENSIONS(pcap, rf_num);
  567. /* B19 MU Beamformer Capable */
  568. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {
  569. SET_VHT_CAPABILITY_ELE_MU_BFER(pcap, 1);
  570. RTW_INFO("[VHT] Declare supporting MU Bfer\n");
  571. }
  572. }
  573. /* B12 SU Beamformee Capable */
  574. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
  575. SET_VHT_CAPABILITY_ELE_SU_BFEE(pcap, 1);
  576. RTW_INFO("[VHT] Declare supporting SU Bfee\n");
  577. /* B13 14 15 Compressed Steering Number of Beamformer Antennas Supported */
  578. rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num);
  579. SET_VHT_CAPABILITY_ELE_BFER_ANT_SUPP(pcap, rf_num);
  580. /* B20 SU Beamformee Capable */
  581. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) {
  582. SET_VHT_CAPABILITY_ELE_MU_BFEE(pcap, 1);
  583. RTW_INFO("[VHT] Declare supporting MU Bfee\n");
  584. }
  585. }
  586. /* B21 VHT TXOP PS */
  587. SET_VHT_CAPABILITY_ELE_TXOP_PS(pcap, 0);
  588. /* B22 +HTC-VHT Capable */
  589. SET_VHT_CAPABILITY_ELE_HTC_VHT(pcap, 1);
  590. /* B23 24 25 Maximum A-MPDU Length Exponent */
  591. if (pregistrypriv->ampdu_factor != 0xFE)
  592. SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pcap, pregistrypriv->ampdu_factor);
  593. else
  594. SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pcap, 7);
  595. /* B26 27 VHT Link Adaptation Capable */
  596. SET_VHT_CAPABILITY_ELE_LINK_ADAPTION(pcap, 0);
  597. pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pcap);
  598. _rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
  599. pcap_mcs = GET_VHT_CAPABILITY_ELE_TX_MCS(pcap);
  600. _rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
  601. /* find the largest bw supported by both registry and hal */
  602. bw = hal_largest_bw(padapter, REGSTY_BW_5G(pregistrypriv));
  603. HighestRate = VHT_MCS_DATA_RATE[bw][pvhtpriv->sgi_80m][((pvhtpriv->vht_highest_rate - MGN_VHT1SS_MCS0) & 0x3f)];
  604. HighestRate = (HighestRate + 1) >> 1;
  605. SET_VHT_CAPABILITY_ELE_MCS_RX_HIGHEST_RATE(pcap, HighestRate); /* indicate we support highest rx rate is 600Mbps. */
  606. SET_VHT_CAPABILITY_ELE_MCS_TX_HIGHEST_RATE(pcap, HighestRate); /* indicate we support highest tx rate is 600Mbps. */
  607. pbuf = rtw_set_ie(pbuf, EID_VHTCapability, 12, pcap, &len);
  608. return len;
  609. }
  610. u32 rtw_restructure_vht_ie(_adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len)
  611. {
  612. u32 ielen = 0, out_len = 0;
  613. u8 cap_len = 0, notify_len = 0, notify_bw = 0, operation_bw = 0, supported_chnl_width = 0;
  614. u8 *p, *pframe;
  615. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  616. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  617. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  618. rtw_vht_use_default_setting(padapter);
  619. p = rtw_get_ie(in_ie + 12, EID_VHTCapability, &ielen, in_len - 12);
  620. if (p && ielen > 0) {
  621. supported_chnl_width = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(p + 2);
  622. /* VHT Capabilities element */
  623. cap_len = rtw_build_vht_cap_ie(padapter, out_ie + *pout_len);
  624. *pout_len += cap_len;
  625. /* Get HT BW */
  626. p = rtw_get_ie(in_ie + 12, _HT_EXTRA_INFO_IE_, &ielen, in_len - 12);
  627. if (p && ielen > 0) {
  628. struct HT_info_element *pht_info = (struct HT_info_element *)(p + 2);
  629. if (pht_info->infos[0] & BIT(2))
  630. operation_bw = CHANNEL_WIDTH_40;
  631. else
  632. operation_bw = CHANNEL_WIDTH_20;
  633. }
  634. /* VHT Operation element */
  635. p = rtw_get_ie(in_ie + 12, EID_VHTOperation, &ielen, in_len - 12);
  636. if (p && ielen > 0) {
  637. out_len = *pout_len;
  638. if (GET_VHT_OPERATION_ELE_CHL_WIDTH(p + 2) >= 1) {
  639. if (supported_chnl_width == 2)
  640. operation_bw = CHANNEL_WIDTH_80_80;
  641. else if (supported_chnl_width == 1)
  642. operation_bw = CHANNEL_WIDTH_160;
  643. else
  644. operation_bw = CHANNEL_WIDTH_80;
  645. }
  646. pframe = rtw_set_ie(out_ie + out_len, EID_VHTOperation, ielen, p + 2 , pout_len);
  647. }
  648. /* find the largest bw supported by both registry and hal */
  649. notify_bw = hal_largest_bw(padapter, REGSTY_BW_5G(pregistrypriv));
  650. if (notify_bw > operation_bw)
  651. notify_bw = operation_bw;
  652. /* Operating Mode Notification element */
  653. notify_len = rtw_build_vht_op_mode_notify_ie(padapter, out_ie + *pout_len, notify_bw);
  654. *pout_len += notify_len;
  655. pvhtpriv->vht_option = _TRUE;
  656. }
  657. return pvhtpriv->vht_option;
  658. }
  659. void VHTOnAssocRsp(_adapter *padapter)
  660. {
  661. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  662. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  663. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  664. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  665. u8 ht_AMPDU_len;
  666. RTW_INFO("%s\n", __FUNCTION__);
  667. if (!pmlmeinfo->HT_enable)
  668. return;
  669. if (!pmlmeinfo->VHT_enable)
  670. return;
  671. ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
  672. if (pvhtpriv->ampdu_len > ht_AMPDU_len)
  673. rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
  674. rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MAX_TIME, (u8 *)(&pvhtpriv->vht_highest_rate));
  675. }
  676. #endif /* CONFIG_80211AC_VHT */