rtw_vht.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2017 Realtek Corporation.
  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. *****************************************************************************/
  15. #define _RTW_VHT_C
  16. #include <drv_types.h>
  17. #include <hal_data.h>
  18. #ifdef CONFIG_80211AC_VHT
  19. const u16 _vht_max_mpdu_len[] = {
  20. 3895,
  21. 7991,
  22. 11454,
  23. 0,
  24. };
  25. const u8 _vht_sup_ch_width_set_to_bw_cap[] = {
  26. BW_CAP_80M,
  27. BW_CAP_80M | BW_CAP_160M,
  28. BW_CAP_80M | BW_CAP_160M | BW_CAP_80_80M,
  29. 0,
  30. };
  31. const char *const _vht_sup_ch_width_set_str[] = {
  32. "80MHz",
  33. "160MHz",
  34. "160MHz & 80+80MHz",
  35. "BW-RSVD",
  36. };
  37. void dump_vht_cap_ie_content(void *sel, const u8 *buf, u32 buf_len)
  38. {
  39. if (buf_len != VHT_CAP_IE_LEN) {
  40. RTW_PRINT_SEL(sel, "Invalid VHT capability IE len:%d != %d\n", buf_len, VHT_CAP_IE_LEN);
  41. return;
  42. }
  43. RTW_PRINT_SEL(sel, "cap_info:%02x %02x %02x %02x: MAX_MPDU_LEN:%u %s%s%s%s%s RX-STBC:%u MAX_AMPDU_LEN:%u\n"
  44. , *(buf), *(buf + 1), *(buf + 2), *(buf + 3)
  45. , vht_max_mpdu_len(GET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(buf))
  46. , vht_sup_ch_width_set_str(GET_VHT_CAPABILITY_ELE_CHL_WIDTH(buf))
  47. , GET_VHT_CAPABILITY_ELE_RX_LDPC(buf) ? " RX-LDPC" : ""
  48. , GET_VHT_CAPABILITY_ELE_SHORT_GI80M(buf) ? " SGI-80" : ""
  49. , GET_VHT_CAPABILITY_ELE_SHORT_GI160M(buf) ? " SGI-160" : ""
  50. , GET_VHT_CAPABILITY_ELE_TX_STBC(buf) ? " TX-STBC" : ""
  51. , GET_VHT_CAPABILITY_ELE_RX_STBC(buf)
  52. , VHT_MAX_AMPDU_LEN(GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(buf))
  53. );
  54. }
  55. void dump_vht_cap_ie(void *sel, const u8 *ie, u32 ie_len)
  56. {
  57. const u8 *vht_cap_ie;
  58. sint vht_cap_ielen;
  59. vht_cap_ie = rtw_get_ie(ie, WLAN_EID_VHT_CAPABILITY, &vht_cap_ielen, ie_len);
  60. if (!ie || vht_cap_ie != ie)
  61. return;
  62. dump_vht_cap_ie_content(sel, vht_cap_ie + 2, vht_cap_ielen);
  63. }
  64. const char *const _vht_op_ch_width_str[] = {
  65. "20 or 40MHz",
  66. "80MHz",
  67. "160MHz",
  68. "80+80MHz",
  69. "BW-RSVD",
  70. };
  71. void dump_vht_op_ie_content(void *sel, const u8 *buf, u32 buf_len)
  72. {
  73. if (buf_len != VHT_OP_IE_LEN) {
  74. RTW_PRINT_SEL(sel, "Invalid VHT operation IE len:%d != %d\n", buf_len, VHT_OP_IE_LEN);
  75. return;
  76. }
  77. RTW_PRINT_SEL(sel, "%s, ch0:%u, ch1:%u\n"
  78. , vht_op_ch_width_str(GET_VHT_OPERATION_ELE_CHL_WIDTH(buf))
  79. , GET_VHT_OPERATION_ELE_CENTER_FREQ1(buf)
  80. , GET_VHT_OPERATION_ELE_CENTER_FREQ2(buf)
  81. );
  82. }
  83. void dump_vht_op_ie(void *sel, const u8 *ie, u32 ie_len)
  84. {
  85. const u8 *vht_op_ie;
  86. sint vht_op_ielen;
  87. vht_op_ie = rtw_get_ie(ie, WLAN_EID_VHT_OPERATION, &vht_op_ielen, ie_len);
  88. if (!ie || vht_op_ie != ie)
  89. return;
  90. dump_vht_op_ie_content(sel, vht_op_ie + 2, vht_op_ielen);
  91. }
  92. /* 20/40/80, ShortGI, MCS Rate */
  93. const u16 VHT_MCS_DATA_RATE[3][2][30] = {
  94. { {
  95. 13, 26, 39, 52, 78, 104, 117, 130, 156, 156,
  96. 26, 52, 78, 104, 156, 208, 234, 260, 312, 312,
  97. 39, 78, 117, 156, 234, 312, 351, 390, 468, 520
  98. }, /* Long GI, 20MHz */
  99. {
  100. 14, 29, 43, 58, 87, 116, 130, 144, 173, 173,
  101. 29, 58, 87, 116, 173, 231, 260, 289, 347, 347,
  102. 43, 87, 130, 173, 260, 347, 390, 433, 520, 578
  103. }
  104. }, /* Short GI, 20MHz */
  105. { {
  106. 27, 54, 81, 108, 162, 216, 243, 270, 324, 360,
  107. 54, 108, 162, 216, 324, 432, 486, 540, 648, 720,
  108. 81, 162, 243, 324, 486, 648, 729, 810, 972, 1080
  109. }, /* Long GI, 40MHz */
  110. {
  111. 30, 60, 90, 120, 180, 240, 270, 300, 360, 400,
  112. 60, 120, 180, 240, 360, 480, 540, 600, 720, 800,
  113. 90, 180, 270, 360, 540, 720, 810, 900, 1080, 1200
  114. }
  115. }, /* Short GI, 40MHz */
  116. { {
  117. 59, 117, 176, 234, 351, 468, 527, 585, 702, 780,
  118. 117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560,
  119. 176, 351, 527, 702, 1053, 1404, 1580, 1755, 2106, 2340
  120. }, /* Long GI, 80MHz */
  121. {
  122. 65, 130, 195, 260, 390, 520, 585, 650, 780, 867,
  123. 130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1734,
  124. 195, 390, 585, 780, 1170, 1560, 1755, 1950, 2340, 2600
  125. }
  126. } /* Short GI, 80MHz */
  127. };
  128. u8 rtw_get_vht_highest_rate(u8 *pvht_mcs_map)
  129. {
  130. u8 i, j;
  131. u8 bit_map;
  132. u8 vht_mcs_rate = 0;
  133. for (i = 0; i < 2; i++) {
  134. if (pvht_mcs_map[i] != 0xff) {
  135. for (j = 0; j < 8; j += 2) {
  136. bit_map = (pvht_mcs_map[i] >> j) & 3;
  137. if (bit_map != 3)
  138. vht_mcs_rate = MGN_VHT1SS_MCS7 + 10 * j / 2 + i * 40 + bit_map; /* VHT rate indications begin from 0x90 */
  139. }
  140. }
  141. }
  142. /* RTW_INFO("HighestVHTMCSRate is %x\n", vht_mcs_rate); */
  143. return vht_mcs_rate;
  144. }
  145. u8 rtw_vht_mcsmap_to_nss(u8 *pvht_mcs_map)
  146. {
  147. u8 i, j;
  148. u8 bit_map;
  149. u8 nss = 0;
  150. for (i = 0; i < 2; i++) {
  151. if (pvht_mcs_map[i] != 0xff) {
  152. for (j = 0; j < 8; j += 2) {
  153. bit_map = (pvht_mcs_map[i] >> j) & 3;
  154. if (bit_map != 3)
  155. nss++;
  156. }
  157. }
  158. }
  159. /* RTW_INFO("%s : %dSS\n", __FUNCTION__, nss); */
  160. return nss;
  161. }
  162. void rtw_vht_nss_to_mcsmap(u8 nss, u8 *target_mcs_map, u8 *cur_mcs_map)
  163. {
  164. u8 i, j;
  165. u8 cur_rate, target_rate;
  166. for (i = 0; i < 2; i++) {
  167. target_mcs_map[i] = 0;
  168. for (j = 0; j < 8; j += 2) {
  169. cur_rate = (cur_mcs_map[i] >> j) & 3;
  170. if (cur_rate == 3) /* 0x3 indicates not supported that num of SS */
  171. target_rate = 3;
  172. else if (nss <= ((j / 2) + i * 4))
  173. target_rate = 3;
  174. else
  175. target_rate = cur_rate;
  176. target_mcs_map[i] |= (target_rate << j);
  177. }
  178. }
  179. /* RTW_INFO("%s : %dSS\n", __FUNCTION__, nss); */
  180. }
  181. u16 rtw_vht_mcs_to_data_rate(u8 bw, u8 short_GI, u8 vht_mcs_rate)
  182. {
  183. if (vht_mcs_rate > MGN_VHT3SS_MCS9)
  184. vht_mcs_rate = MGN_VHT3SS_MCS9;
  185. /* 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)); */
  186. return VHT_MCS_DATA_RATE[bw][short_GI][((vht_mcs_rate - MGN_VHT1SS_MCS0) & 0x3f)];
  187. }
  188. void rtw_vht_use_default_setting(_adapter *padapter)
  189. {
  190. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  191. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  192. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  193. BOOLEAN bHwLDPCSupport = _FALSE, bHwSTBCSupport = _FALSE;
  194. #ifdef CONFIG_BEAMFORMING
  195. BOOLEAN bHwSupportBeamformer = _FALSE, bHwSupportBeamformee = _FALSE;
  196. u8 mu_bfer, mu_bfee;
  197. #endif /* CONFIG_BEAMFORMING */
  198. u8 rf_type = 0;
  199. u8 tx_nss, rx_nss;
  200. struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
  201. struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
  202. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  203. pvhtpriv->sgi_80m = TEST_FLAG(pregistrypriv->short_gi, BIT2) ? _TRUE : _FALSE;
  204. /* LDPC support */
  205. rtw_hal_get_def_var(padapter, HAL_DEF_RX_LDPC, (u8 *)&bHwLDPCSupport);
  206. CLEAR_FLAGS(pvhtpriv->ldpc_cap);
  207. if (bHwLDPCSupport) {
  208. if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT0))
  209. SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX);
  210. }
  211. rtw_hal_get_def_var(padapter, HAL_DEF_TX_LDPC, (u8 *)&bHwLDPCSupport);
  212. if (bHwLDPCSupport) {
  213. if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT1))
  214. SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX);
  215. }
  216. if (pvhtpriv->ldpc_cap)
  217. RTW_INFO("[VHT] Support LDPC = 0x%02X\n", pvhtpriv->ldpc_cap);
  218. /* STBC */
  219. rtw_hal_get_def_var(padapter, HAL_DEF_TX_STBC, (u8 *)&bHwSTBCSupport);
  220. CLEAR_FLAGS(pvhtpriv->stbc_cap);
  221. if (bHwSTBCSupport) {
  222. if (TEST_FLAG(pregistrypriv->stbc_cap, BIT1))
  223. SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX);
  224. }
  225. rtw_hal_get_def_var(padapter, HAL_DEF_RX_STBC, (u8 *)&bHwSTBCSupport);
  226. if (bHwSTBCSupport) {
  227. if (TEST_FLAG(pregistrypriv->stbc_cap, BIT0))
  228. SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX);
  229. }
  230. if (pvhtpriv->stbc_cap)
  231. RTW_INFO("[VHT] Support STBC = 0x%02X\n", pvhtpriv->stbc_cap);
  232. /* Beamforming setting */
  233. CLEAR_FLAGS(pvhtpriv->beamform_cap);
  234. #ifdef CONFIG_BEAMFORMING
  235. #ifdef RTW_BEAMFORMING_VERSION_2
  236. /* only enable beamforming in STA client mode */
  237. if (MLME_IS_STA(padapter) && !MLME_IS_GC(padapter)
  238. && !MLME_IS_ADHOC(padapter)
  239. && !MLME_IS_MESH(padapter))
  240. #endif
  241. {
  242. rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMER,
  243. (u8 *)&bHwSupportBeamformer);
  244. rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMEE,
  245. (u8 *)&bHwSupportBeamformee);
  246. mu_bfer = _FALSE;
  247. mu_bfee = _FALSE;
  248. rtw_hal_get_def_var(padapter, HAL_DEF_VHT_MU_BEAMFORMER, &mu_bfer);
  249. rtw_hal_get_def_var(padapter, HAL_DEF_VHT_MU_BEAMFORMEE, &mu_bfee);
  250. if (TEST_FLAG(pregistrypriv->beamform_cap, BIT0) && bHwSupportBeamformer) {
  251. #ifdef CONFIG_CONCURRENT_MODE
  252. if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
  253. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  254. RTW_INFO("[VHT] CONCURRENT AP Support Beamformer\n");
  255. if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(2))
  256. && (_TRUE == mu_bfer)) {
  257. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
  258. RTW_INFO("[VHT] Support MU-MIMO AP\n");
  259. }
  260. } else
  261. RTW_INFO("[VHT] CONCURRENT not AP ;not allow Support Beamformer\n");
  262. #else
  263. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  264. RTW_INFO("[VHT] Support Beamformer\n");
  265. if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(2))
  266. && (_TRUE == mu_bfer)
  267. && ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
  268. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
  269. RTW_INFO("[VHT] Support MU-MIMO AP\n");
  270. }
  271. #endif
  272. }
  273. if (TEST_FLAG(pregistrypriv->beamform_cap, BIT1) && bHwSupportBeamformee) {
  274. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  275. RTW_INFO("[VHT] Support Beamformee\n");
  276. if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(3))
  277. && (_TRUE == mu_bfee)
  278. && ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)) {
  279. SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
  280. RTW_INFO("[VHT] Support MU-MIMO STA\n");
  281. }
  282. }
  283. }
  284. #endif /* CONFIG_BEAMFORMING */
  285. pvhtpriv->ampdu_len = pregistrypriv->ampdu_factor;
  286. rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
  287. tx_nss = rtw_min(rf_type_to_rf_tx_cnt(rf_type), hal_spec->tx_nss_num);
  288. rx_nss = rtw_min(rf_type_to_rf_rx_cnt(rf_type), hal_spec->rx_nss_num);
  289. /* for now, vhtpriv.vht_mcs_map comes from RX NSS */
  290. rtw_vht_nss_to_mcsmap(rx_nss, pvhtpriv->vht_mcs_map, pregistrypriv->vht_rx_mcs_map);
  291. pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
  292. }
  293. u64 rtw_vht_mcs_map_to_bitmap(u8 *mcs_map, u8 nss)
  294. {
  295. u8 i, j, tmp;
  296. u64 bitmap = 0;
  297. u8 bits_nss = nss * 2;
  298. for (i = j = 0; i < bits_nss; i += 2, j += 10) {
  299. /* every two bits means single sptial stream */
  300. tmp = (mcs_map[i / 8] >> i) & 3;
  301. switch (tmp) {
  302. case 2:
  303. bitmap = bitmap | (0x03ff << j);
  304. break;
  305. case 1:
  306. bitmap = bitmap | (0x01ff << j);
  307. break;
  308. case 0:
  309. bitmap = bitmap | (0x00ff << j);
  310. break;
  311. default:
  312. break;
  313. }
  314. }
  315. RTW_INFO("vht_mcs_map=%02x %02x, nss=%u => bitmap=%016llx\n"
  316. , mcs_map[0], mcs_map[1], nss, bitmap);
  317. return bitmap;
  318. }
  319. #ifdef CONFIG_BEAMFORMING
  320. void update_sta_vht_info_apmode_bf_cap(_adapter *padapter, struct sta_info *psta)
  321. {
  322. struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  323. struct vht_priv *pvhtpriv_ap = &pmlmepriv->vhtpriv;
  324. struct vht_priv *pvhtpriv_sta = &psta->vhtpriv;
  325. u16 cur_beamform_cap = 0;
  326. /* B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee */
  327. if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
  328. GET_VHT_CAPABILITY_ELE_SU_BFEE(pvhtpriv_sta->vht_cap)) {
  329. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  330. /*Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP*/
  331. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pvhtpriv_sta->vht_cap) << 8);
  332. }
  333. /* B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer */
  334. if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
  335. GET_VHT_CAPABILITY_ELE_SU_BFER(pvhtpriv_sta->vht_cap)) {
  336. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  337. /*Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM*/
  338. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pvhtpriv_sta->vht_cap) << 12);
  339. }
  340. if (cur_beamform_cap)
  341. RTW_INFO("Current STA(%d) VHT Beamforming Setting = %02X\n", psta->cmn.aid, cur_beamform_cap);
  342. pvhtpriv_sta->beamform_cap = cur_beamform_cap;
  343. psta->cmn.bf_info.vht_beamform_cap = cur_beamform_cap;
  344. }
  345. #endif
  346. void update_sta_vht_info_apmode(_adapter *padapter, PVOID sta)
  347. {
  348. struct sta_info *psta = (struct sta_info *)sta;
  349. struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  350. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  351. struct vht_priv *pvhtpriv_ap = &pmlmepriv->vhtpriv;
  352. struct vht_priv *pvhtpriv_sta = &psta->vhtpriv;
  353. u8 cur_ldpc_cap = 0, cur_stbc_cap = 0;
  354. s8 bw_mode = -1;
  355. u8 *pcap_mcs;
  356. if (pvhtpriv_sta->vht_option == _FALSE)
  357. return;
  358. if (pvhtpriv_sta->op_present) {
  359. switch (GET_VHT_OPERATION_ELE_CHL_WIDTH(pvhtpriv_sta->vht_op)) {
  360. case 1: /* 80MHz */
  361. case 2: /* 160MHz */
  362. case 3: /* 80+80 */
  363. bw_mode = CHANNEL_WIDTH_80; /* only support up to 80MHz for now */
  364. break;
  365. }
  366. }
  367. if (pvhtpriv_sta->notify_present)
  368. bw_mode = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&pvhtpriv_sta->vht_op_mode_notify);
  369. else if (MLME_IS_AP(padapter)) {
  370. /* for VHT client without Operating Mode Notify IE; minimal 80MHz */
  371. if (bw_mode < CHANNEL_WIDTH_80)
  372. bw_mode = CHANNEL_WIDTH_80;
  373. }
  374. if (bw_mode != -1)
  375. psta->cmn.bw_mode = bw_mode; /* update bw_mode only if get value from VHT IEs */
  376. psta->cmn.ra_info.is_vht_enable = _TRUE;
  377. /* B4 Rx LDPC */
  378. if (TEST_FLAG(pvhtpriv_ap->ldpc_cap, LDPC_VHT_ENABLE_TX) &&
  379. GET_VHT_CAPABILITY_ELE_RX_LDPC(pvhtpriv_sta->vht_cap)) {
  380. SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
  381. RTW_INFO("Current STA(%d) VHT LDPC = %02X\n", psta->cmn.aid, cur_ldpc_cap);
  382. }
  383. pvhtpriv_sta->ldpc_cap = cur_ldpc_cap;
  384. if (psta->cmn.bw_mode > pmlmeext->cur_bwmode)
  385. psta->cmn.bw_mode = pmlmeext->cur_bwmode;
  386. if (psta->cmn.bw_mode == CHANNEL_WIDTH_80) {
  387. /* B5 Short GI for 80 MHz */
  388. pvhtpriv_sta->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi_80m) ? _TRUE : _FALSE;
  389. /* RTW_INFO("Current STA ShortGI80MHz = %d\n", pvhtpriv_sta->sgi_80m); */
  390. } else if (psta->cmn.bw_mode >= CHANNEL_WIDTH_160) {
  391. /* B5 Short GI for 80 MHz */
  392. pvhtpriv_sta->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi_80m) ? _TRUE : _FALSE;
  393. /* RTW_INFO("Current STA ShortGI160MHz = %d\n", pvhtpriv_sta->sgi_80m); */
  394. }
  395. /* B8 B9 B10 Rx STBC */
  396. if (TEST_FLAG(pvhtpriv_ap->stbc_cap, STBC_VHT_ENABLE_TX) &&
  397. GET_VHT_CAPABILITY_ELE_RX_STBC(pvhtpriv_sta->vht_cap)) {
  398. SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
  399. RTW_INFO("Current STA(%d) VHT STBC = %02X\n", psta->cmn.aid, cur_stbc_cap);
  400. }
  401. pvhtpriv_sta->stbc_cap = cur_stbc_cap;
  402. #ifdef CONFIG_BEAMFORMING
  403. update_sta_vht_info_apmode_bf_cap(padapter, psta);
  404. #endif
  405. /* B23 B24 B25 Maximum A-MPDU Length Exponent */
  406. pvhtpriv_sta->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pvhtpriv_sta->vht_cap);
  407. pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pvhtpriv_sta->vht_cap);
  408. _rtw_memcpy(pvhtpriv_sta->vht_mcs_map, pcap_mcs, 2);
  409. pvhtpriv_sta->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv_sta->vht_mcs_map);
  410. }
  411. void update_hw_vht_param(_adapter *padapter)
  412. {
  413. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  414. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  415. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  416. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  417. u8 ht_AMPDU_len;
  418. ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
  419. if (pvhtpriv->ampdu_len > ht_AMPDU_len)
  420. rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
  421. }
  422. #ifdef ROKU_PRIVATE
  423. u8 VHT_get_ss_from_map(u8 *vht_mcs_map)
  424. {
  425. u8 i, j;
  426. u8 ss = 0;
  427. for (i = 0; i < 2; i++) {
  428. if (vht_mcs_map[i] != 0xff) {
  429. for (j = 0; j < 8; j += 2) {
  430. if (((vht_mcs_map[i] >> j) & 0x03) == 0x03)
  431. break;
  432. ss++;
  433. }
  434. }
  435. }
  436. return ss;
  437. }
  438. void VHT_caps_handler_infra_ap(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
  439. {
  440. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  441. struct vht_priv_infra_ap *pvhtpriv = &pmlmepriv->vhtpriv_infra_ap;
  442. u8 cur_stbc_cap_infra_ap = 0;
  443. u16 cur_beamform_cap_infra_ap = 0;
  444. u8 *pcap_mcs;
  445. u8 *pcap_mcs_tx;
  446. u8 Rx_ss = 0, Tx_ss = 0;
  447. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  448. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  449. if (pIE == NULL)
  450. return;
  451. pmlmeinfo->ht_vht_received |= BIT(1);
  452. pvhtpriv->ldpc_cap_infra_ap = GET_VHT_CAPABILITY_ELE_RX_LDPC(pIE->data);
  453. if (GET_VHT_CAPABILITY_ELE_RX_STBC(pIE->data))
  454. SET_FLAG(cur_stbc_cap_infra_ap, STBC_VHT_ENABLE_RX);
  455. if (GET_VHT_CAPABILITY_ELE_TX_STBC(pIE->data))
  456. SET_FLAG(cur_stbc_cap_infra_ap, STBC_VHT_ENABLE_TX);
  457. pvhtpriv->stbc_cap_infra_ap = cur_stbc_cap_infra_ap;
  458. /*store ap info for channel bandwidth*/
  459. pvhtpriv->channel_width_infra_ap = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(pIE->data);
  460. /*check B11: SU Beamformer Capable and B12: SU Beamformee B19: MU Beamformer B20:MU Beamformee*/
  461. if (GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data))
  462. SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  463. if (GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data))
  464. SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  465. if (GET_VHT_CAPABILITY_ELE_MU_BFER(pIE->data))
  466. SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
  467. if (GET_VHT_CAPABILITY_ELE_MU_BFEE(pIE->data))
  468. SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
  469. pvhtpriv->beamform_cap_infra_ap = cur_beamform_cap_infra_ap;
  470. /*store information about vht_mcs_set*/
  471. pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pIE->data);
  472. pcap_mcs_tx = GET_VHT_CAPABILITY_ELE_TX_MCS(pIE->data);
  473. _rtw_memcpy(pvhtpriv->vht_mcs_map_infra_ap, pcap_mcs, 2);
  474. _rtw_memcpy(pvhtpriv->vht_mcs_map_tx_infra_ap, pcap_mcs_tx, 2);
  475. Rx_ss = VHT_get_ss_from_map(pvhtpriv->vht_mcs_map_infra_ap);
  476. Tx_ss = VHT_get_ss_from_map(pvhtpriv->vht_mcs_map_tx_infra_ap);
  477. if (Rx_ss >= Tx_ss) {
  478. pvhtpriv->number_of_streams_infra_ap = Rx_ss;
  479. } else{
  480. pvhtpriv->number_of_streams_infra_ap = Tx_ss;
  481. }
  482. }
  483. #endif /* ROKU_PRIVATE */
  484. void VHT_caps_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
  485. {
  486. struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
  487. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  488. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  489. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  490. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  491. u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, rf_type = RF_1T1R, tx_nss = 0;
  492. u16 cur_beamform_cap = 0;
  493. u8 *pcap_mcs;
  494. if (pIE == NULL)
  495. return;
  496. if (pvhtpriv->vht_option == _FALSE)
  497. return;
  498. pmlmeinfo->VHT_enable = 1;
  499. /* B4 Rx LDPC */
  500. if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX) &&
  501. GET_VHT_CAPABILITY_ELE_RX_LDPC(pIE->data)) {
  502. SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
  503. RTW_INFO("Current VHT LDPC Setting = %02X\n", cur_ldpc_cap);
  504. }
  505. pvhtpriv->ldpc_cap = cur_ldpc_cap;
  506. /* B5 Short GI for 80 MHz */
  507. pvhtpriv->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pIE->data) & pvhtpriv->sgi_80m) ? _TRUE : _FALSE;
  508. /* RTW_INFO("Current ShortGI80MHz = %d\n", pvhtpriv->sgi_80m); */
  509. /* B8 B9 B10 Rx STBC */
  510. if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX) &&
  511. GET_VHT_CAPABILITY_ELE_RX_STBC(pIE->data)) {
  512. SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
  513. RTW_INFO("Current VHT STBC Setting = %02X\n", cur_stbc_cap);
  514. }
  515. pvhtpriv->stbc_cap = cur_stbc_cap;
  516. #ifdef CONFIG_BEAMFORMING
  517. #ifdef RTW_BEAMFORMING_VERSION_2
  518. /*
  519. * B11 SU Beamformer Capable,
  520. * the target supports Beamformer and we are Beamformee
  521. */
  522. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)
  523. && GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data)) {
  524. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  525. /* Shift to BEAMFORMING_VHT_BEAMFORMEE_STS_CAP */
  526. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pIE->data) << 8);
  527. /*
  528. * B19 MU Beamformer Capable,
  529. * the target supports Beamformer and we are Beamformee
  530. */
  531. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)
  532. && GET_VHT_CAPABILITY_ELE_MU_BFER(pIE->data))
  533. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
  534. }
  535. /*
  536. * B12 SU Beamformee Capable,
  537. * the target supports Beamformee and we are Beamformer
  538. */
  539. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)
  540. && GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data)) {
  541. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  542. /* Shit to BEAMFORMING_VHT_BEAMFORMER_SOUND_DIM */
  543. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pIE->data) << 12);
  544. /*
  545. * B20 MU Beamformee Capable,
  546. * the target supports Beamformee and we are Beamformer
  547. */
  548. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)
  549. && GET_VHT_CAPABILITY_ELE_MU_BFEE(pIE->data))
  550. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
  551. }
  552. pvhtpriv->beamform_cap = cur_beamform_cap;
  553. RTW_INFO("Current VHT Beamforming Setting=0x%04X\n", cur_beamform_cap);
  554. #else /* !RTW_BEAMFORMING_VERSION_2 */
  555. /* B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee */
  556. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
  557. GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data)) {
  558. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  559. /*Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP*/
  560. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pIE->data) << 8);
  561. }
  562. /* B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer */
  563. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
  564. GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data)) {
  565. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  566. /*Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM*/
  567. SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pIE->data) << 12);
  568. }
  569. pvhtpriv->beamform_cap = cur_beamform_cap;
  570. if (cur_beamform_cap)
  571. RTW_INFO("Current VHT Beamforming Setting = %02X\n", cur_beamform_cap);
  572. #endif /* !RTW_BEAMFORMING_VERSION_2 */
  573. #endif /* CONFIG_BEAMFORMING */
  574. /* B23 B24 B25 Maximum A-MPDU Length Exponent */
  575. pvhtpriv->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pIE->data);
  576. pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pIE->data);
  577. rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
  578. tx_nss = rtw_min(rf_type_to_rf_tx_cnt(rf_type), hal_spec->tx_nss_num);
  579. rtw_vht_nss_to_mcsmap(tx_nss, pvhtpriv->vht_mcs_map, pcap_mcs);
  580. pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
  581. }
  582. void VHT_operation_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
  583. {
  584. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  585. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  586. if (pIE == NULL)
  587. return;
  588. if (pvhtpriv->vht_option == _FALSE)
  589. return;
  590. }
  591. void rtw_process_vht_op_mode_notify(_adapter *padapter, u8 *pframe, PVOID sta)
  592. {
  593. struct sta_info *psta = (struct sta_info *)sta;
  594. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  595. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  596. struct registry_priv *regsty = adapter_to_regsty(padapter);
  597. u8 target_bw;
  598. u8 target_rxss, current_rxss;
  599. u8 update_ra = _FALSE;
  600. u8 tx_nss = 0, rf_type = RF_1T1R;
  601. struct hal_spec_t *hal_spec = GET_HAL_SPEC(padapter);
  602. if (pvhtpriv->vht_option == _FALSE)
  603. return;
  604. target_bw = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(pframe);
  605. rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
  606. tx_nss = rtw_min(rf_type_to_rf_tx_cnt(rf_type), hal_spec->tx_nss_num);
  607. target_rxss = rtw_min(tx_nss, (GET_VHT_OPERATING_MODE_FIELD_RX_NSS(pframe) + 1));
  608. if (target_bw != psta->cmn.bw_mode) {
  609. if (hal_is_bw_support(padapter, target_bw)
  610. && REGSTY_IS_BW_5G_SUPPORT(regsty, target_bw)
  611. ) {
  612. update_ra = _TRUE;
  613. psta->cmn.bw_mode = target_bw;
  614. }
  615. }
  616. current_rxss = rtw_vht_mcsmap_to_nss(psta->vhtpriv.vht_mcs_map);
  617. if (target_rxss != current_rxss) {
  618. u8 vht_mcs_map[2] = {};
  619. update_ra = _TRUE;
  620. rtw_vht_nss_to_mcsmap(target_rxss, vht_mcs_map, psta->vhtpriv.vht_mcs_map);
  621. _rtw_memcpy(psta->vhtpriv.vht_mcs_map, vht_mcs_map, 2);
  622. rtw_hal_update_sta_ra_info(padapter, psta);
  623. }
  624. if (update_ra)
  625. rtw_dm_ra_mask_wk_cmd(padapter, (u8 *)psta);
  626. }
  627. u32 rtw_build_vht_operation_ie(_adapter *padapter, u8 *pbuf, u8 channel)
  628. {
  629. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  630. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  631. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  632. /* struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; */
  633. u8 ChnlWidth, center_freq, bw_mode;
  634. u32 len = 0;
  635. u8 operation[5];
  636. _rtw_memset(operation, 0, 5);
  637. bw_mode = REGSTY_BW_5G(pregistrypriv); /* TODO: control op bw with other info */
  638. if (hal_chk_bw_cap(padapter, BW_CAP_80M | BW_CAP_160M)
  639. && REGSTY_BW_5G(pregistrypriv) >= CHANNEL_WIDTH_80
  640. ) {
  641. center_freq = rtw_get_center_ch(channel, bw_mode, HAL_PRIME_CHNL_OFFSET_LOWER);
  642. ChnlWidth = 1;
  643. } else {
  644. center_freq = 0;
  645. ChnlWidth = 0;
  646. }
  647. SET_VHT_OPERATION_ELE_CHL_WIDTH(operation, ChnlWidth);
  648. /* center frequency */
  649. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(operation, center_freq);/* Todo: need to set correct center channel */
  650. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(operation, 0);
  651. _rtw_memcpy(operation + 3, pvhtpriv->vht_mcs_map, 2);
  652. rtw_set_ie(pbuf, EID_VHTOperation, 5, operation, &len);
  653. return len;
  654. }
  655. u32 rtw_build_vht_op_mode_notify_ie(_adapter *padapter, u8 *pbuf, u8 bw)
  656. {
  657. /* struct registry_priv *pregistrypriv = &padapter->registrypriv; */
  658. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  659. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  660. u32 len = 0;
  661. u8 opmode = 0;
  662. u8 chnl_width, rx_nss;
  663. chnl_width = bw;
  664. rx_nss = rtw_vht_mcsmap_to_nss(pvhtpriv->vht_mcs_map);
  665. SET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&opmode, chnl_width);
  666. SET_VHT_OPERATING_MODE_FIELD_RX_NSS(&opmode, (rx_nss - 1));
  667. SET_VHT_OPERATING_MODE_FIELD_RX_NSS_TYPE(&opmode, 0); /* Todo */
  668. pvhtpriv->vht_op_mode_notify = opmode;
  669. pbuf = rtw_set_ie(pbuf, EID_OpModeNotification, 1, &opmode, &len);
  670. return len;
  671. }
  672. u32 rtw_build_vht_cap_ie(_adapter *padapter, u8 *pbuf)
  673. {
  674. u8 bw, rf_num, rx_stbc_nss = 0;
  675. u16 HighestRate;
  676. u8 *pcap, *pcap_mcs;
  677. u32 len = 0;
  678. u32 rx_packet_offset, max_recvbuf_sz;
  679. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  680. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  681. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  682. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  683. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  684. pcap = pvhtpriv->vht_cap;
  685. _rtw_memset(pcap, 0, 32);
  686. /* B0 B1 Maximum MPDU Length */
  687. rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
  688. rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
  689. RTW_DBG("%s, line%d, Available RX buf size = %d bytes\n", __FUNCTION__, __LINE__, max_recvbuf_sz - rx_packet_offset);
  690. if ((max_recvbuf_sz - rx_packet_offset) >= 11454) {
  691. SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, 2);
  692. RTW_INFO("%s, line%d, Set MAX MPDU len = 11454 bytes\n", __FUNCTION__, __LINE__);
  693. } else if ((max_recvbuf_sz - rx_packet_offset) >= 7991) {
  694. SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, 1);
  695. RTW_INFO("%s, line%d, Set MAX MPDU len = 7991 bytes\n", __FUNCTION__, __LINE__);
  696. } else if ((max_recvbuf_sz - rx_packet_offset) >= 3895) {
  697. SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, 0);
  698. RTW_INFO("%s, line%d, Set MAX MPDU len = 3895 bytes\n", __FUNCTION__, __LINE__);
  699. } else
  700. RTW_ERR("%s, line%d, Error!! Available RX buf size < 3895 bytes\n", __FUNCTION__, __LINE__);
  701. /* B2 B3 Supported Channel Width Set */
  702. if (hal_chk_bw_cap(padapter, BW_CAP_160M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) {
  703. if (hal_chk_bw_cap(padapter, BW_CAP_80_80M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_80_80))
  704. SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 2);
  705. else
  706. SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 1);
  707. } else
  708. SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 0);
  709. /* B4 Rx LDPC */
  710. if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX)) {
  711. SET_VHT_CAPABILITY_ELE_RX_LDPC(pcap, 1);
  712. RTW_INFO("[VHT] Declare supporting RX LDPC\n");
  713. }
  714. /* B5 ShortGI for 80MHz */
  715. SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pcap, pvhtpriv->sgi_80m ? 1 : 0); /* We can receive Short GI of 80M */
  716. if (pvhtpriv->sgi_80m)
  717. RTW_INFO("[VHT] Declare supporting SGI 80MHz\n");
  718. /* B6 ShortGI for 160MHz */
  719. /* SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pcap, pvhtpriv->sgi_80m? 1 : 0); */
  720. /* B7 Tx STBC */
  721. if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX)) {
  722. SET_VHT_CAPABILITY_ELE_TX_STBC(pcap, 1);
  723. RTW_INFO("[VHT] Declare supporting TX STBC\n");
  724. }
  725. /* B8 B9 B10 Rx STBC */
  726. if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX)) {
  727. rtw_hal_get_def_var(padapter, HAL_DEF_RX_STBC, (u8 *)(&rx_stbc_nss));
  728. SET_VHT_CAPABILITY_ELE_RX_STBC(pcap, rx_stbc_nss);
  729. RTW_INFO("[VHT] Declare supporting RX STBC = %d\n", rx_stbc_nss);
  730. }
  731. #ifdef CONFIG_BEAMFORMING
  732. /* B11 SU Beamformer Capable */
  733. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
  734. SET_VHT_CAPABILITY_ELE_SU_BFER(pcap, 1);
  735. RTW_INFO("[VHT] Declare supporting SU Bfer\n");
  736. /* B16 17 18 Number of Sounding Dimensions */
  737. rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num);
  738. SET_VHT_CAPABILITY_ELE_SOUNDING_DIMENSIONS(pcap, rf_num);
  739. /* B19 MU Beamformer Capable */
  740. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {
  741. SET_VHT_CAPABILITY_ELE_MU_BFER(pcap, 1);
  742. RTW_INFO("[VHT] Declare supporting MU Bfer\n");
  743. }
  744. }
  745. /* B12 SU Beamformee Capable */
  746. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
  747. SET_VHT_CAPABILITY_ELE_SU_BFEE(pcap, 1);
  748. RTW_INFO("[VHT] Declare supporting SU Bfee\n");
  749. rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num);
  750. /* IOT action suggested by Yu Chen 2017/3/3 */
  751. #ifdef CONFIG_80211AC_VHT
  752. if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM) &&
  753. !pvhtpriv->ap_is_mu_bfer)
  754. rf_num = (rf_num >= 2 ? 2 : rf_num);
  755. #endif
  756. /* B13 14 15 Compressed Steering Number of Beamformer Antennas Supported */
  757. SET_VHT_CAPABILITY_ELE_BFER_ANT_SUPP(pcap, rf_num);
  758. /* B20 SU Beamformee Capable */
  759. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) {
  760. SET_VHT_CAPABILITY_ELE_MU_BFEE(pcap, 1);
  761. RTW_INFO("[VHT] Declare supporting MU Bfee\n");
  762. }
  763. }
  764. #endif/*CONFIG_BEAMFORMING*/
  765. /* B21 VHT TXOP PS */
  766. SET_VHT_CAPABILITY_ELE_TXOP_PS(pcap, 0);
  767. /* B22 +HTC-VHT Capable */
  768. SET_VHT_CAPABILITY_ELE_HTC_VHT(pcap, 1);
  769. /* B23 24 25 Maximum A-MPDU Length Exponent */
  770. if (pregistrypriv->ampdu_factor != 0xFE)
  771. SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pcap, pregistrypriv->ampdu_factor);
  772. else
  773. SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pcap, 7);
  774. /* B26 27 VHT Link Adaptation Capable */
  775. SET_VHT_CAPABILITY_ELE_LINK_ADAPTION(pcap, 0);
  776. pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pcap);
  777. _rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
  778. pcap_mcs = GET_VHT_CAPABILITY_ELE_TX_MCS(pcap);
  779. _rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
  780. /* find the largest bw supported by both registry and hal */
  781. bw = hal_largest_bw(padapter, REGSTY_BW_5G(pregistrypriv));
  782. HighestRate = VHT_MCS_DATA_RATE[bw][pvhtpriv->sgi_80m][((pvhtpriv->vht_highest_rate - MGN_VHT1SS_MCS0) & 0x3f)];
  783. HighestRate = (HighestRate + 1) >> 1;
  784. SET_VHT_CAPABILITY_ELE_MCS_RX_HIGHEST_RATE(pcap, HighestRate); /* indicate we support highest rx rate is 600Mbps. */
  785. SET_VHT_CAPABILITY_ELE_MCS_TX_HIGHEST_RATE(pcap, HighestRate); /* indicate we support highest tx rate is 600Mbps. */
  786. pbuf = rtw_set_ie(pbuf, EID_VHTCapability, 12, pcap, &len);
  787. return len;
  788. }
  789. u32 rtw_restructure_vht_ie(_adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len)
  790. {
  791. struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
  792. RT_CHANNEL_INFO *chset = rfctl->channel_set;
  793. u32 ielen;
  794. u8 max_bw;
  795. u8 oper_ch, oper_bw = CHANNEL_WIDTH_20, oper_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  796. u8 *out_vht_op_ie, *ht_op_ie, *vht_cap_ie, *vht_op_ie;
  797. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  798. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  799. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  800. rtw_vht_use_default_setting(padapter);
  801. ht_op_ie = rtw_get_ie(in_ie + 12, WLAN_EID_HT_OPERATION, &ielen, in_len - 12);
  802. if (!ht_op_ie || ielen != HT_OP_IE_LEN)
  803. goto exit;
  804. vht_cap_ie = rtw_get_ie(in_ie + 12, EID_VHTCapability, &ielen, in_len - 12);
  805. if (!vht_cap_ie || ielen != VHT_CAP_IE_LEN)
  806. goto exit;
  807. vht_op_ie = rtw_get_ie(in_ie + 12, EID_VHTOperation, &ielen, in_len - 12);
  808. if (!vht_op_ie || ielen != VHT_OP_IE_LEN)
  809. goto exit;
  810. /* VHT Capabilities element */
  811. *pout_len += rtw_build_vht_cap_ie(padapter, out_ie + *pout_len);
  812. /* VHT Operation element */
  813. out_vht_op_ie = out_ie + *pout_len;
  814. rtw_set_ie(out_vht_op_ie, EID_VHTOperation, VHT_OP_IE_LEN, vht_op_ie + 2 , pout_len);
  815. /* get primary channel from HT_OP_IE */
  816. oper_ch = GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2);
  817. /* find the largest bw supported by both registry and hal */
  818. max_bw = hal_largest_bw(padapter, REGSTY_BW_5G(pregistrypriv));
  819. if (max_bw >= CHANNEL_WIDTH_40) {
  820. /* get bw offset form HT_OP_IE */
  821. if (GET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2)) {
  822. switch (GET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2)) {
  823. case SCA:
  824. oper_bw = CHANNEL_WIDTH_40;
  825. oper_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
  826. break;
  827. case SCB:
  828. oper_bw = CHANNEL_WIDTH_40;
  829. oper_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
  830. break;
  831. }
  832. }
  833. if (oper_bw == CHANNEL_WIDTH_40) {
  834. switch (GET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2)) {
  835. case 1: /* 80MHz */
  836. case 2: /* 160MHz */
  837. case 3: /* 80+80 */
  838. oper_bw = CHANNEL_WIDTH_80; /* only support up to 80MHz for now */
  839. break;
  840. }
  841. oper_bw = rtw_min(oper_bw, max_bw);
  842. /* try downgrage bw to fit in channel plan setting */
  843. while (!rtw_chset_is_chbw_valid(chset, oper_ch, oper_bw, oper_offset)
  844. || (IS_DFS_SLAVE_WITH_RD(rfctl)
  845. && !rtw_odm_dfs_domain_unknown(rfctl_to_dvobj(rfctl))
  846. && rtw_chset_is_chbw_non_ocp(chset, oper_ch, oper_bw, oper_offset))
  847. ) {
  848. oper_bw--;
  849. if (oper_bw == CHANNEL_WIDTH_20) {
  850. oper_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
  851. break;
  852. }
  853. }
  854. }
  855. }
  856. rtw_warn_on(!rtw_chset_is_chbw_valid(chset, oper_ch, oper_bw, oper_offset));
  857. if (IS_DFS_SLAVE_WITH_RD(rfctl) && !rtw_odm_dfs_domain_unknown(rfctl_to_dvobj(rfctl)))
  858. rtw_warn_on(rtw_chset_is_chbw_non_ocp(chset, oper_ch, oper_bw, oper_offset));
  859. /* update VHT_OP_IE */
  860. if (oper_bw < CHANNEL_WIDTH_80) {
  861. SET_VHT_OPERATION_ELE_CHL_WIDTH(out_vht_op_ie + 2, 0);
  862. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(out_vht_op_ie + 2, 0);
  863. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(out_vht_op_ie + 2, 0);
  864. } else if (oper_bw == CHANNEL_WIDTH_80) {
  865. u8 cch = rtw_get_center_ch(oper_ch, oper_bw, oper_offset);
  866. SET_VHT_OPERATION_ELE_CHL_WIDTH(out_vht_op_ie + 2, 1);
  867. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(out_vht_op_ie + 2, cch);
  868. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(out_vht_op_ie + 2, 0);
  869. } else {
  870. RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(padapter), oper_bw);
  871. rtw_warn_on(1);
  872. }
  873. /* Operating Mode Notification element */
  874. *pout_len += rtw_build_vht_op_mode_notify_ie(padapter, out_ie + *pout_len, oper_bw);
  875. pvhtpriv->vht_option = _TRUE;
  876. exit:
  877. return pvhtpriv->vht_option;
  878. }
  879. void VHTOnAssocRsp(_adapter *padapter)
  880. {
  881. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  882. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  883. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  884. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  885. u8 ht_AMPDU_len;
  886. RTW_INFO("%s\n", __FUNCTION__);
  887. if (!pmlmeinfo->HT_enable)
  888. return;
  889. if (!pmlmeinfo->VHT_enable)
  890. return;
  891. ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
  892. if (pvhtpriv->ampdu_len > ht_AMPDU_len)
  893. rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
  894. rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MAX_TIME, (u8 *)(&pvhtpriv->vht_highest_rate));
  895. }
  896. void rtw_vht_ies_attach(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
  897. {
  898. struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  899. u8 cap_len, operation_len;
  900. uint len = 0;
  901. sint ie_len = 0;
  902. u8 *p = NULL;
  903. p = rtw_get_ie(pnetwork->IEs + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len,
  904. (pnetwork->IELength - _BEACON_IE_OFFSET_));
  905. if (p && ie_len > 0)
  906. return;
  907. rtw_vht_use_default_setting(padapter);
  908. /* VHT Operation mode notifiy bit in Extended IE (127) */
  909. SET_EXT_CAPABILITY_ELE_OP_MODE_NOTIF(pmlmepriv->ext_capab_ie_data, 1);
  910. pmlmepriv->ext_capab_ie_len = 10;
  911. rtw_set_ie(pnetwork->IEs + pnetwork->IELength, EID_EXTCapability, 8, pmlmepriv->ext_capab_ie_data, &len);
  912. pnetwork->IELength += pmlmepriv->ext_capab_ie_len;
  913. /* VHT Capabilities element */
  914. cap_len = rtw_build_vht_cap_ie(padapter, pnetwork->IEs + pnetwork->IELength);
  915. pnetwork->IELength += cap_len;
  916. /* VHT Operation element */
  917. operation_len = rtw_build_vht_operation_ie(padapter, pnetwork->IEs + pnetwork->IELength,
  918. pnetwork->Configuration.DSConfig);
  919. pnetwork->IELength += operation_len;
  920. rtw_check_for_vht20(padapter, pnetwork->IEs + _BEACON_IE_OFFSET_, pnetwork->IELength - _BEACON_IE_OFFSET_);
  921. pmlmepriv->vhtpriv.vht_option = _TRUE;
  922. }
  923. void rtw_vht_ies_detach(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
  924. {
  925. struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  926. rtw_remove_bcn_ie(padapter, pnetwork, EID_EXTCapability);
  927. rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTCapability);
  928. rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTOperation);
  929. pmlmepriv->vhtpriv.vht_option = _FALSE;
  930. }
  931. void rtw_check_for_vht20(_adapter *adapter, u8 *ies, int ies_len)
  932. {
  933. u8 ht_ch, ht_bw, ht_offset;
  934. u8 vht_ch, vht_bw, vht_offset;
  935. rtw_ies_get_chbw(ies, ies_len, &ht_ch, &ht_bw, &ht_offset, 1, 0);
  936. rtw_ies_get_chbw(ies, ies_len, &vht_ch, &vht_bw, &vht_offset, 1, 1);
  937. if (ht_bw == CHANNEL_WIDTH_20 && vht_bw >= CHANNEL_WIDTH_80) {
  938. u8 *vht_op_ie;
  939. int vht_op_ielen;
  940. RTW_INFO(FUNC_ADPT_FMT" vht80 is not allowed without ht40\n", FUNC_ADPT_ARG(adapter));
  941. vht_op_ie = rtw_get_ie(ies, EID_VHTOperation, &vht_op_ielen, ies_len);
  942. if (vht_op_ie && vht_op_ielen) {
  943. RTW_INFO(FUNC_ADPT_FMT" switch to vht20\n", FUNC_ADPT_ARG(adapter));
  944. SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 0);
  945. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0);
  946. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);
  947. }
  948. }
  949. }
  950. #endif /* CONFIG_80211AC_VHT */