rtw_vht.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  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. #ifdef CONFIG_80211AC_VHT
  23. // 20/40/80, ShortGI, MCS Rate
  24. const u16 VHT_MCS_DATA_RATE[3][2][20] =
  25. { { {13, 26, 39, 52, 78, 104, 117, 130, 156, 156,
  26. 26, 52, 78, 104, 156, 208, 234, 260, 312, 312}, // Long GI, 20MHz
  27. {14, 29, 43, 58, 87, 116, 130, 144, 173, 173,
  28. 29, 58, 87, 116, 173, 231, 260, 289, 347, 347} }, // Short GI, 20MHz
  29. { {27, 54, 81, 108, 162, 216, 243, 270, 324, 360,
  30. 54, 108, 162, 216, 324, 432, 486, 540, 648, 720}, // Long GI, 40MHz
  31. {30, 60, 90, 120, 180, 240, 270, 300,360, 400,
  32. 60, 120, 180, 240, 360, 480, 540, 600, 720, 800}}, // Short GI, 40MHz
  33. { {59, 117, 176, 234, 351, 468, 527, 585, 702, 780,
  34. 117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560}, // Long GI, 80MHz
  35. {65, 130, 195, 260, 390, 520, 585, 650, 780, 867,
  36. 130, 260, 390, 520, 780, 1040, 1170, 1300, 1560,1734} } // Short GI, 80MHz
  37. };
  38. u8 rtw_get_vht_highest_rate(_adapter *padapter, u8 *pvht_mcs_map)
  39. {
  40. u8 i, j;
  41. u8 bit_map;
  42. u8 vht_mcs_rate = 0;
  43. for(i = 0; i < 2; i++)
  44. {
  45. if(pvht_mcs_map[i] != 0xff)
  46. {
  47. for(j = 0; j < 8; j += 2)
  48. {
  49. bit_map = (pvht_mcs_map[i] >> j) & 3;
  50. if(bit_map != 3)
  51. vht_mcs_rate = MGN_VHT1SS_MCS7 + 10*j/2 + i*40 + bit_map; //VHT rate indications begin from 0x90
  52. }
  53. }
  54. }
  55. //DBG_871X("HighestVHTMCSRate is %x\n", vht_mcs_rate);
  56. return vht_mcs_rate;
  57. }
  58. u16 rtw_vht_data_rate(u8 bw, u8 short_GI, u8 vht_mcs_rate)
  59. {
  60. if(vht_mcs_rate > MGN_VHT2SS_MCS9)
  61. vht_mcs_rate = MGN_VHT2SS_MCS9;
  62. return VHT_MCS_DATA_RATE[bw][short_GI][((vht_mcs_rate - MGN_VHT1SS_MCS0)&0x3f)];
  63. }
  64. void rtw_vht_use_default_setting(_adapter *padapter)
  65. {
  66. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  67. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  68. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  69. BOOLEAN bHwLDPCSupport = _FALSE, bHwSTBCSupport = _FALSE;
  70. u8 rf_type = 0;
  71. pvhtpriv->bwmode = (pregistrypriv->bw_mode & 0xF0) >> 4;
  72. if (pvhtpriv->bwmode > CHANNEL_WIDTH_80) {
  73. pvhtpriv->sgi = TEST_FLAG(pregistrypriv->short_gi, BIT3) ? _TRUE : _FALSE;
  74. } else {
  75. pvhtpriv->sgi = TEST_FLAG(pregistrypriv->short_gi, BIT2) ? _TRUE : _FALSE;
  76. }
  77. // LDPC support
  78. rtw_hal_get_def_var(padapter, HAL_DEF_LDPC, (u8 *)&bHwLDPCSupport);
  79. CLEAR_FLAGS(pvhtpriv->ldpc_cap);
  80. if(bHwLDPCSupport)
  81. {
  82. if(TEST_FLAG(pregistrypriv->ldpc_cap, BIT0))
  83. SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX);
  84. if(TEST_FLAG(pregistrypriv->ldpc_cap, BIT1))
  85. SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX);
  86. DBG_871X("[VHT] Support LDPC = 0x%02X\n", pvhtpriv->ldpc_cap);
  87. }
  88. // STBC
  89. rtw_hal_get_def_var(padapter, HAL_DEF_TX_STBC, (u8 *)&bHwSTBCSupport);
  90. CLEAR_FLAGS(pvhtpriv->stbc_cap);
  91. if(bHwSTBCSupport)
  92. {
  93. if(TEST_FLAG(pregistrypriv->stbc_cap, BIT1))
  94. SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX);
  95. }
  96. rtw_hal_get_def_var(padapter, HAL_DEF_RX_STBC, (u8 *)&bHwSTBCSupport);
  97. if(bHwSTBCSupport)
  98. {
  99. if(TEST_FLAG(pregistrypriv->stbc_cap, BIT0))
  100. SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX);
  101. }
  102. DBG_871X("[VHT] Support STBC = 0x%02X\n", pvhtpriv->stbc_cap);
  103. pvhtpriv->ampdu_len = pregistrypriv->ampdu_factor;
  104. rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
  105. if (rf_type == RF_1T1R)
  106. pvhtpriv->vht_mcs_map[0] = 0xfe; // Only support 1SS MCS 0~9;
  107. else
  108. pvhtpriv->vht_mcs_map[0] = 0xfa; //support 1SS MCS 0~9 2SS MCS 0~9
  109. pvhtpriv->vht_mcs_map[1] = 0xff;
  110. if(pregistrypriv->vht_rate_sel == 1)
  111. {
  112. pvhtpriv->vht_mcs_map[0] = 0xfc; // support 1SS MCS 0~7
  113. }
  114. else if(pregistrypriv->vht_rate_sel == 2)
  115. {
  116. pvhtpriv->vht_mcs_map[0] = 0xfd; // Support 1SS MCS 0~8
  117. }
  118. else if(pregistrypriv->vht_rate_sel == 3)
  119. {
  120. pvhtpriv->vht_mcs_map[0] = 0xfe; // Support 1SS MCS 0~9
  121. }
  122. else if(pregistrypriv->vht_rate_sel == 4)
  123. {
  124. pvhtpriv->vht_mcs_map[0] = 0xf0; // support 1SS MCS 0~7 2SS MCS 0~7
  125. }
  126. else if(pregistrypriv->vht_rate_sel == 5)
  127. {
  128. pvhtpriv->vht_mcs_map[0] = 0xf5; // support 1SS MCS 0~8 2SS MCS 0~8
  129. }
  130. else if(pregistrypriv->vht_rate_sel == 6)
  131. {
  132. pvhtpriv->vht_mcs_map[0] = 0xfa; // support 1SS MCS 0~9 2SS MCS 0~9
  133. }
  134. else if(pregistrypriv->vht_rate_sel == 7)
  135. {
  136. pvhtpriv->vht_mcs_map[0] = 0xf8; // support 1SS MCS 0-7 2SS MCS 0~9
  137. }
  138. else if(pregistrypriv->vht_rate_sel == 8)
  139. {
  140. pvhtpriv->vht_mcs_map[0] = 0xf9; // support 1SS MCS 0-8 2SS MCS 0~9
  141. }
  142. else if(pregistrypriv->vht_rate_sel == 9)
  143. {
  144. pvhtpriv->vht_mcs_map[0] = 0xf4; // support 1SS MCS 0-7 2SS MCS 0~8
  145. }
  146. pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(padapter, pvhtpriv->vht_mcs_map);
  147. }
  148. u32 rtw_vht_rate_to_bitmap(u8 *pVHTRate)
  149. {
  150. u8 i,j , tmpRate;
  151. u32 RateBitmap = 0;
  152. for(i = j= 0; i < 4; i+=2, j+=10)
  153. {
  154. tmpRate = (pVHTRate[0] >> i) & 3;
  155. switch(tmpRate){
  156. case 2:
  157. RateBitmap = RateBitmap | (0x03ff << j);
  158. break;
  159. case 1:
  160. RateBitmap = RateBitmap | (0x01ff << j);
  161. break;
  162. case 0:
  163. RateBitmap = RateBitmap | (0x00ff << j);
  164. break;
  165. default:
  166. break;
  167. }
  168. }
  169. return RateBitmap;
  170. }
  171. void update_sta_vht_info_apmode(_adapter *padapter, PVOID psta)
  172. {
  173. struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
  174. struct vht_priv *pvhtpriv_ap = &pmlmepriv->vhtpriv;
  175. struct vht_priv *pvhtpriv_sta = &((struct sta_info *)psta)->vhtpriv;
  176. struct ht_priv *phtpriv_sta = &((struct sta_info *)psta)->htpriv;
  177. u8 cur_ldpc_cap=0, cur_stbc_cap=0, cur_beamform_cap=0;
  178. u8 *pcap_mcs;
  179. if (pvhtpriv_sta->vht_option == _FALSE) {
  180. return;
  181. }
  182. // B4 Rx LDPC
  183. if (TEST_FLAG(pvhtpriv_ap->ldpc_cap, LDPC_VHT_ENABLE_TX)) {
  184. SET_FLAG(cur_ldpc_cap, GET_VHT_CAPABILITY_ELE_RX_LDPC(pvhtpriv_sta->vht_cap) ? (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX) : 0);
  185. }
  186. pvhtpriv_sta->ldpc_cap = cur_ldpc_cap;
  187. DBG_871X("Current STA VHT LDPC = %02X\n", cur_ldpc_cap);
  188. if (pvhtpriv_sta->bwmode > pvhtpriv_ap->bwmode)
  189. pvhtpriv_sta->bwmode = pvhtpriv_ap->bwmode;
  190. if (pvhtpriv_sta->bwmode == CHANNEL_WIDTH_80) {
  191. // B5 Short GI for 80 MHz
  192. pvhtpriv_sta->sgi = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi) ? _TRUE : _FALSE;
  193. DBG_871X("Current STA ShortGI80MHz = %d\n", pvhtpriv_sta->sgi);
  194. } else if (pvhtpriv_sta->bwmode >= CHANNEL_WIDTH_160) {
  195. // B5 Short GI for 80 MHz
  196. pvhtpriv_sta->sgi = (GET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi) ? _TRUE : _FALSE;
  197. DBG_871X("Current STA ShortGI160MHz = %d\n", pvhtpriv_sta->sgi);
  198. } else {
  199. pvhtpriv_sta->sgi = phtpriv_sta->sgi;
  200. }
  201. // B8 B9 B10 Rx STBC
  202. if (TEST_FLAG(pvhtpriv_ap->stbc_cap, STBC_VHT_ENABLE_TX) &&
  203. GET_VHT_CAPABILITY_ELE_RX_STBC(pvhtpriv_sta->vht_cap))
  204. {
  205. SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
  206. }
  207. pvhtpriv_sta->stbc_cap = cur_stbc_cap;
  208. DBG_871X("Current STA VHT STBC = %02X\n", cur_stbc_cap);
  209. // B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee
  210. if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
  211. GET_VHT_CAPABILITY_ELE_SU_BFEE(pvhtpriv_sta->vht_cap))
  212. {
  213. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  214. }
  215. // B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer
  216. if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
  217. GET_VHT_CAPABILITY_ELE_SU_BFER(pvhtpriv_sta->vht_cap))
  218. {
  219. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  220. }
  221. pvhtpriv_sta->beamform_cap = cur_beamform_cap;
  222. DBG_871X("Current VHT Beamforming Setting = %02X\n", cur_beamform_cap);
  223. // B23 B24 B25 Maximum A-MPDU Length Exponent
  224. pvhtpriv_sta->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pvhtpriv_sta->vht_cap);
  225. pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pvhtpriv_sta->vht_cap);
  226. _rtw_memcpy(pvhtpriv_sta->vht_mcs_map, pcap_mcs, 2);
  227. pvhtpriv_sta->vht_highest_rate = rtw_get_vht_highest_rate(padapter, pvhtpriv_sta->vht_mcs_map);
  228. }
  229. void update_hw_vht_param(_adapter *padapter)
  230. {
  231. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  232. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  233. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  234. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  235. u8 ht_AMPDU_len;
  236. ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
  237. if(pvhtpriv->ampdu_len > ht_AMPDU_len)
  238. rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
  239. }
  240. void VHT_caps_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
  241. {
  242. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  243. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  244. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  245. struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
  246. u8 cur_ldpc_cap=0, cur_stbc_cap=0, cur_beamform_cap=0, rf_type = RF_1T1R;
  247. u8 *pcap_mcs;
  248. u8 vht_mcs[2];
  249. if(pIE==NULL) return;
  250. if(pvhtpriv->vht_option == _FALSE) return;
  251. pmlmeinfo->VHT_enable = 1;
  252. // B4 Rx LDPC
  253. if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX)) {
  254. SET_FLAG(cur_ldpc_cap, GET_VHT_CAPABILITY_ELE_RX_LDPC(pIE->data) ? (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX) : 0);
  255. }
  256. pvhtpriv->ldpc_cap = cur_ldpc_cap;
  257. DBG_871X("Current VHT LDPC Setting = %02X\n", cur_ldpc_cap);
  258. // B5 Short GI for 80 MHz
  259. pvhtpriv->sgi = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pIE->data) & pvhtpriv->sgi) ? _TRUE : _FALSE;
  260. DBG_871X("Current ShortGI80MHz = %d\n", pvhtpriv->sgi);
  261. // B8 B9 B10 Rx STBC
  262. if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX) &&
  263. GET_VHT_CAPABILITY_ELE_RX_STBC(pIE->data))
  264. {
  265. SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
  266. }
  267. pvhtpriv->stbc_cap = cur_stbc_cap;
  268. DBG_871X("Current VHT STBC Setting = %02X\n", cur_stbc_cap);
  269. // B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee
  270. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
  271. GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data))
  272. {
  273. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
  274. }
  275. // B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer
  276. if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
  277. GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data))
  278. {
  279. SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
  280. }
  281. pvhtpriv->beamform_cap = cur_beamform_cap;
  282. DBG_871X("Current VHT Beamforming Setting = %02X\n", cur_beamform_cap);
  283. // B23 B24 B25 Maximum A-MPDU Length Exponent
  284. pvhtpriv->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pIE->data);
  285. pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pIE->data);
  286. _rtw_memcpy(vht_mcs, pcap_mcs, 2);
  287. rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
  288. if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
  289. vht_mcs[0] |= 0xfc;
  290. else if (rf_type == RF_2T2R)
  291. vht_mcs[0] |= 0xf0;
  292. _rtw_memcpy(pvhtpriv->vht_mcs_map, vht_mcs, 2);
  293. pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(padapter, pvhtpriv->vht_mcs_map);
  294. }
  295. void VHT_operation_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
  296. {
  297. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  298. struct ht_priv *phtpriv = &pmlmepriv->htpriv;
  299. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  300. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  301. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  302. if(pIE==NULL) return;
  303. if(pvhtpriv->vht_option == _FALSE) return;
  304. if ((GET_VHT_OPERATION_ELE_CHL_WIDTH(pIE->data) >= 1)
  305. && ((pregistrypriv->bw_mode & 0xf0) >= CHANNEL_WIDTH_80)) {
  306. pvhtpriv->bwmode = CHANNEL_WIDTH_80;
  307. } else {
  308. pvhtpriv->bwmode = phtpriv->bwmode;
  309. }
  310. }
  311. u32 rtw_build_vht_operation_ie(_adapter *padapter, u8 *pbuf, u8 channel)
  312. {
  313. //struct registry_priv *pregistrypriv = &padapter->registrypriv;
  314. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  315. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  316. struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
  317. u8 ChnlWidth, center_freq;
  318. u32 len = 0;
  319. u8 operation[5];
  320. if (pvhtpriv->bwmode >= CHANNEL_WIDTH_80)
  321. ChnlWidth = 1;
  322. else
  323. ChnlWidth = 0;
  324. center_freq = rtw_get_center_ch(channel, pvhtpriv->bwmode, HAL_PRIME_CHNL_OFFSET_LOWER);
  325. SET_VHT_OPERATION_ELE_CHL_WIDTH(operation, ChnlWidth);
  326. //center frequency
  327. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(operation, center_freq);//Todo: need to set correct center channel
  328. SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(operation,0);
  329. SET_VHT_OPERATION_ELE_BASIC_MCS_SET(operation, 0xFFFF);
  330. pbuf = rtw_set_ie(pbuf, EID_VHTOperation, 12, operation, &len);
  331. return len;
  332. }
  333. u32 rtw_build_vht_op_mode_notify_ie(_adapter *padapter, u8 *pbuf)
  334. {
  335. //struct registry_priv *pregistrypriv = &padapter->registrypriv;
  336. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  337. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  338. u32 len = 0;
  339. u8 opmode = 0, rf_type = 0;
  340. u8 chnl_width, rx_nss;
  341. chnl_width = pvhtpriv->bwmode;
  342. rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
  343. if(rf_type == RF_1T1R)
  344. rx_nss = 1;
  345. else
  346. rx_nss = 2;
  347. SET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&opmode, chnl_width);
  348. SET_VHT_OPERATING_MODE_FIELD_RX_NSS(&opmode, (rx_nss-1));
  349. SET_VHT_OPERATING_MODE_FIELD_RX_NSS_TYPE(&opmode, 0); //Todo
  350. pbuf = rtw_set_ie(pbuf, EID_OpModeNotification, 1, &opmode, &len);
  351. return len;
  352. }
  353. u32 rtw_build_vht_cap_ie(_adapter *padapter, u8 *pbuf)
  354. {
  355. u8 bw, rf_type;
  356. u16 HighestRate;
  357. u8 *pcap, *pcap_mcs;
  358. u32 len = 0;
  359. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  360. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  361. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  362. pcap = pvhtpriv->vht_cap;
  363. _rtw_memset(pcap, 0, 32);
  364. // B2 B3 Supported Channel Width Set
  365. SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 0); //indicate we don't support neither 160M nor 80+80M bandwidth.
  366. // B4 Rx LDPC
  367. if(TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX))
  368. {
  369. SET_VHT_CAPABILITY_ELE_RX_LDPC(pcap, 1);
  370. }
  371. // B5 ShortGI for 80MHz
  372. SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pcap, pvhtpriv->sgi? 1 : 0); // We can receive Short GI of 80M
  373. // B6 ShortGI for 160MHz
  374. if (pvhtpriv->bwmode > CHANNEL_WIDTH_80) {
  375. SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pcap, pvhtpriv->sgi? 1 : 0);
  376. }
  377. // B7 Tx STBC
  378. if(TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX))
  379. {
  380. SET_VHT_CAPABILITY_ELE_TX_STBC(pcap, 1);
  381. }
  382. // B8 B9 B10 Rx STBC
  383. if(TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX))
  384. {
  385. rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
  386. if ((rf_type == RF_2T2R) || (rf_type == RF_1T2R)) {
  387. SET_VHT_CAPABILITY_ELE_RX_STBC(pcap, 2);
  388. }
  389. else if (rf_type == RF_1T1R) {
  390. SET_VHT_CAPABILITY_ELE_RX_STBC(pcap, 1);
  391. }
  392. }
  393. // B11 SU Beamformer Capable
  394. if(TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE))
  395. {
  396. SET_VHT_CAPABILITY_ELE_SU_BFER(pcap, 1);
  397. }
  398. // B12 SU Beamformee Capable
  399. if(TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE))
  400. {
  401. SET_VHT_CAPABILITY_ELE_SU_BFEE(pcap, 1);
  402. }
  403. // B13 14 15 Compressed Steering Number of Beamformer Antennas Supported
  404. SET_VHT_CAPABILITY_ELE_BFER_ANT_SUPP(pcap, 1);// TODO
  405. // B16 17 18 Number of Sounding Dimensions
  406. SET_VHT_CAPABILITY_ELE_SOUNDING_DIMENSIONS(pcap, 1);
  407. // B19 MU Beamformer Capable
  408. SET_VHT_CAPABILITY_ELE_MU_BFER(pcap, 0); //HW don't support mu bfee/bfer
  409. // B20 MU Beamformee Capable
  410. SET_VHT_CAPABILITY_ELE_MU_BFEE(pcap, 0);
  411. // B21 VHT TXOP PS
  412. SET_VHT_CAPABILITY_ELE_TXOP_PS(pcap, 0);
  413. // B22 +HTC-VHT Capable
  414. SET_VHT_CAPABILITY_ELE_HTC_VHT(pcap, 1);
  415. // B23 24 25 Maximum A-MPDU Length Exponent
  416. if (pregistrypriv->ampdu_factor != 0xFE)
  417. {
  418. SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pcap, pregistrypriv->ampdu_factor);
  419. }
  420. else
  421. {
  422. SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pcap, 7);
  423. }
  424. // B26 27 VHT Link Adaptation Capable
  425. SET_VHT_CAPABILITY_ELE_LINK_ADAPTION(pcap, 0);
  426. pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pcap);
  427. _rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
  428. pcap_mcs = GET_VHT_CAPABILITY_ELE_TX_MCS(pcap);
  429. _rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
  430. bw = (pregistrypriv->bw_mode >> 4) & 0xf;
  431. HighestRate = VHT_MCS_DATA_RATE[bw][pvhtpriv->sgi][((pvhtpriv->vht_highest_rate - MGN_VHT1SS_MCS0)&0x3f)];
  432. HighestRate = (HighestRate+1) >> 1;
  433. SET_VHT_CAPABILITY_ELE_MCS_RX_HIGHEST_RATE(pcap, HighestRate); //indicate we support highest rx rate is 600Mbps.
  434. SET_VHT_CAPABILITY_ELE_MCS_TX_HIGHEST_RATE(pcap, HighestRate); //indicate we support highest tx rate is 600Mbps.
  435. pbuf = rtw_set_ie(pbuf, EID_VHTCapability, 12, pcap, &len);
  436. return len;
  437. }
  438. u32 rtw_restructure_vht_ie(_adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len)
  439. {
  440. u32 ielen, out_len;
  441. u8 cap_len, notify_len, operation_bw, supported_chnl_width;
  442. u8 *p, *pframe;
  443. struct registry_priv *pregistrypriv = &padapter->registrypriv;
  444. struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
  445. struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
  446. rtw_vht_use_default_setting(padapter);
  447. p = rtw_get_ie(in_ie+12, EID_VHTCapability, &ielen, in_len-12);
  448. if (p && ielen>0) {
  449. supported_chnl_width = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(p+2);
  450. // VHT Capabilities element
  451. cap_len = rtw_build_vht_cap_ie(padapter, out_ie+*pout_len);
  452. *pout_len += cap_len;
  453. // Get HT BW
  454. p = rtw_get_ie(in_ie+12, _HT_EXTRA_INFO_IE_, &ielen, in_len-12);
  455. if (p && ielen>0) {
  456. struct HT_info_element *pht_info = (struct HT_info_element *)(p+2);
  457. if (pht_info->infos[0] & BIT(2))
  458. operation_bw = CHANNEL_WIDTH_40;
  459. else
  460. operation_bw = CHANNEL_WIDTH_20;
  461. }
  462. // VHT Operation element
  463. p = rtw_get_ie(in_ie+12, EID_VHTOperation, &ielen, in_len-12);
  464. if (p && ielen>0) {
  465. out_len = *pout_len;
  466. if (GET_VHT_OPERATION_ELE_CHL_WIDTH(p+2) >= 1) {
  467. if (supported_chnl_width == 2)
  468. operation_bw = CHANNEL_WIDTH_80_80;
  469. else if (supported_chnl_width == 1)
  470. operation_bw = CHANNEL_WIDTH_160;
  471. else
  472. operation_bw = CHANNEL_WIDTH_80;
  473. }
  474. pframe = rtw_set_ie(out_ie+out_len, EID_VHTOperation, ielen, p+2 , pout_len);
  475. }
  476. if (pvhtpriv->bwmode > operation_bw)
  477. pvhtpriv->bwmode = operation_bw;
  478. // Operating Mode Notification element
  479. notify_len = rtw_build_vht_op_mode_notify_ie(padapter, out_ie+*pout_len);
  480. *pout_len += notify_len;
  481. pvhtpriv->vht_option = _TRUE;
  482. }
  483. return (pvhtpriv->vht_option);
  484. }
  485. void VHTOnAssocRsp(_adapter *padapter)
  486. {
  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 ht_AMPDU_len;
  492. DBG_871X("%s\n", __FUNCTION__);
  493. if (!pmlmeinfo->HT_enable)
  494. return;
  495. if (!pmlmeinfo->VHT_enable)
  496. return;
  497. if(pvhtpriv->bwmode >= CHANNEL_WIDTH_80)
  498. pmlmeext->cur_bwmode = pvhtpriv->bwmode;
  499. ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
  500. if(pvhtpriv->ampdu_len > ht_AMPDU_len)
  501. rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
  502. rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MAX_TIME, (u8 *)(&pvhtpriv->vht_highest_rate));
  503. }
  504. #endif //CONFIG_80211AC_VHT