11ac.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * Marvell Wireless LAN device driver: 802.11ac
  3. *
  4. * Copyright (C) 2013, Marvell International Ltd.
  5. *
  6. * This software file (the "File") is distributed by Marvell International
  7. * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  8. * (the "License"). You may use, redistribute and/or modify this File in
  9. * accordance with the terms and conditions of the License, a copy of which
  10. * is available by writing to the Free Software Foundation, Inc.,
  11. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
  12. * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
  13. *
  14. * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  16. * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  17. * this warranty disclaimer.
  18. */
  19. #include "decl.h"
  20. #include "ioctl.h"
  21. #include "fw.h"
  22. #include "main.h"
  23. #include "11ac.h"
  24. /* This function converts the 2-bit MCS map to the highest long GI
  25. * VHT data rate.
  26. */
  27. static u16
  28. mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv,
  29. u8 bands, u16 mcs_map)
  30. {
  31. u8 i, nss, max_mcs;
  32. u16 max_rate = 0;
  33. u32 usr_vht_cap_info = 0;
  34. struct mwifiex_adapter *adapter = priv->adapter;
  35. /* tables of the MCS map to the highest data rate (in Mbps)
  36. * supported for long GI
  37. */
  38. u16 max_rate_lgi_80MHZ[8][3] = {
  39. {0x124, 0x15F, 0x186}, /* NSS = 1 */
  40. {0x249, 0x2BE, 0x30C}, /* NSS = 2 */
  41. {0x36D, 0x41D, 0x492}, /* NSS = 3 */
  42. {0x492, 0x57C, 0x618}, /* NSS = 4 */
  43. {0x5B6, 0x6DB, 0x79E}, /* NSS = 5 */
  44. {0x6DB, 0x83A, 0x0}, /* NSS = 6 */
  45. {0x7FF, 0x999, 0xAAA}, /* NSS = 7 */
  46. {0x924, 0xAF8, 0xC30} /* NSS = 8 */
  47. };
  48. u16 max_rate_lgi_160MHZ[8][3] = {
  49. {0x249, 0x2BE, 0x30C}, /* NSS = 1 */
  50. {0x492, 0x57C, 0x618}, /* NSS = 2 */
  51. {0x6DB, 0x83A, 0x0}, /* NSS = 3 */
  52. {0x924, 0xAF8, 0xC30}, /* NSS = 4 */
  53. {0xB6D, 0xDB6, 0xF3C}, /* NSS = 5 */
  54. {0xDB6, 0x1074, 0x1248}, /* NSS = 6 */
  55. {0xFFF, 0x1332, 0x1554}, /* NSS = 7 */
  56. {0x1248, 0x15F0, 0x1860} /* NSS = 8 */
  57. };
  58. if (bands & BAND_AAC)
  59. usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
  60. else
  61. usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
  62. /* find the max NSS supported */
  63. nss = 0;
  64. for (i = 0; i < 8; i++) {
  65. max_mcs = (mcs_map >> (2 * i)) & 0x3;
  66. if (max_mcs < 3)
  67. nss = i;
  68. }
  69. max_mcs = (mcs_map >> (2 * nss)) & 0x3;
  70. /* if max_mcs is 3, nss must be 0 (SS = 1). Thus, max mcs is MCS 9 */
  71. if (max_mcs >= 3)
  72. max_mcs = 2;
  73. if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) {
  74. /* support 160 MHz */
  75. max_rate = max_rate_lgi_160MHZ[nss][max_mcs];
  76. if (!max_rate)
  77. /* MCS9 is not supported in NSS6 */
  78. max_rate = max_rate_lgi_160MHZ[nss][max_mcs - 1];
  79. } else {
  80. max_rate = max_rate_lgi_80MHZ[nss][max_mcs];
  81. if (!max_rate)
  82. /* MCS9 is not supported in NSS3 */
  83. max_rate = max_rate_lgi_80MHZ[nss][max_mcs - 1];
  84. }
  85. return max_rate;
  86. }
  87. static void
  88. mwifiex_fill_vht_cap_info(struct mwifiex_private *priv,
  89. struct mwifiex_ie_types_vhtcap *vht_cap, u8 bands)
  90. {
  91. struct mwifiex_adapter *adapter = priv->adapter;
  92. if (bands & BAND_A)
  93. vht_cap->vht_cap.vht_cap_info =
  94. cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a);
  95. else
  96. vht_cap->vht_cap.vht_cap_info =
  97. cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg);
  98. }
  99. static void
  100. mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv,
  101. struct mwifiex_ie_types_vhtcap *vht_cap, u8 bands)
  102. {
  103. struct mwifiex_adapter *adapter = priv->adapter;
  104. u16 mcs_map_user, mcs_map_resp, mcs_map_result;
  105. u16 mcs_user, mcs_resp, nss, tmp;
  106. /* Fill VHT cap info */
  107. mwifiex_fill_vht_cap_info(priv, vht_cap, bands);
  108. /* rx MCS Set: find the minimum of the user rx mcs and ap rx mcs */
  109. mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support);
  110. mcs_map_resp = le16_to_cpu(vht_cap->vht_cap.supp_mcs.rx_mcs_map);
  111. mcs_map_result = 0;
  112. for (nss = 1; nss <= 8; nss++) {
  113. mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
  114. mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
  115. if ((mcs_user == NO_NSS_SUPPORT) ||
  116. (mcs_resp == NO_NSS_SUPPORT))
  117. SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
  118. else
  119. SET_VHTNSSMCS(mcs_map_result, nss,
  120. min(mcs_user, mcs_resp));
  121. }
  122. vht_cap->vht_cap.supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result);
  123. tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
  124. vht_cap->vht_cap.supp_mcs.rx_highest = cpu_to_le16(tmp);
  125. /* tx MCS Set: find the minimum of the user tx mcs and ap tx mcs */
  126. mcs_map_user = GET_DEVTXMCSMAP(adapter->usr_dot_11ac_mcs_support);
  127. mcs_map_resp = le16_to_cpu(vht_cap->vht_cap.supp_mcs.tx_mcs_map);
  128. mcs_map_result = 0;
  129. for (nss = 1; nss <= 8; nss++) {
  130. mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
  131. mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
  132. if ((mcs_user == NO_NSS_SUPPORT) ||
  133. (mcs_resp == NO_NSS_SUPPORT))
  134. SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT);
  135. else
  136. SET_VHTNSSMCS(mcs_map_result, nss,
  137. min(mcs_user, mcs_resp));
  138. }
  139. vht_cap->vht_cap.supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result);
  140. tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result);
  141. vht_cap->vht_cap.supp_mcs.tx_highest = cpu_to_le16(tmp);
  142. return;
  143. }
  144. int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv,
  145. struct mwifiex_bssdescriptor *bss_desc,
  146. u8 **buffer)
  147. {
  148. struct mwifiex_ie_types_vhtcap *vht_cap;
  149. struct mwifiex_ie_types_oper_mode_ntf *oper_ntf;
  150. struct ieee_types_oper_mode_ntf *ieee_oper_ntf;
  151. struct mwifiex_ie_types_vht_oper *vht_op;
  152. struct mwifiex_adapter *adapter = priv->adapter;
  153. u8 supp_chwd_set;
  154. u32 usr_vht_cap_info;
  155. int ret_len = 0;
  156. if (bss_desc->bss_band & BAND_A)
  157. usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a;
  158. else
  159. usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg;
  160. /* VHT Capabilities IE */
  161. if (bss_desc->bcn_vht_cap) {
  162. vht_cap = (struct mwifiex_ie_types_vhtcap *)*buffer;
  163. memset(vht_cap, 0, sizeof(*vht_cap));
  164. vht_cap->header.type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY);
  165. vht_cap->header.len =
  166. cpu_to_le16(sizeof(struct ieee80211_vht_cap));
  167. memcpy((u8 *)vht_cap + sizeof(struct mwifiex_ie_types_header),
  168. (u8 *)bss_desc->bcn_vht_cap,
  169. le16_to_cpu(vht_cap->header.len));
  170. mwifiex_fill_vht_cap_tlv(priv, vht_cap, bss_desc->bss_band);
  171. *buffer += sizeof(*vht_cap);
  172. ret_len += sizeof(*vht_cap);
  173. }
  174. /* VHT Operation IE */
  175. if (bss_desc->bcn_vht_oper) {
  176. if (priv->bss_mode == NL80211_IFTYPE_STATION) {
  177. vht_op = (struct mwifiex_ie_types_vht_oper *)*buffer;
  178. memset(vht_op, 0, sizeof(*vht_op));
  179. vht_op->header.type =
  180. cpu_to_le16(WLAN_EID_VHT_OPERATION);
  181. vht_op->header.len = cpu_to_le16(sizeof(*vht_op) -
  182. sizeof(struct mwifiex_ie_types_header));
  183. memcpy((u8 *)vht_op +
  184. sizeof(struct mwifiex_ie_types_header),
  185. (u8 *)bss_desc->bcn_vht_oper +
  186. sizeof(struct ieee_types_header),
  187. le16_to_cpu(vht_op->header.len));
  188. /* negotiate the channel width and central freq
  189. * and keep the central freq as the peer suggests
  190. */
  191. supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
  192. switch (supp_chwd_set) {
  193. case 0:
  194. vht_op->chan_width =
  195. min_t(u8, IEEE80211_VHT_CHANWIDTH_80MHZ,
  196. bss_desc->bcn_vht_oper->chan_width);
  197. break;
  198. case 1:
  199. vht_op->chan_width =
  200. min_t(u8, IEEE80211_VHT_CHANWIDTH_160MHZ,
  201. bss_desc->bcn_vht_oper->chan_width);
  202. break;
  203. case 2:
  204. vht_op->chan_width =
  205. min_t(u8, IEEE80211_VHT_CHANWIDTH_80P80MHZ,
  206. bss_desc->bcn_vht_oper->chan_width);
  207. break;
  208. default:
  209. vht_op->chan_width =
  210. IEEE80211_VHT_CHANWIDTH_USE_HT;
  211. break;
  212. }
  213. *buffer += sizeof(*vht_op);
  214. ret_len += sizeof(*vht_op);
  215. }
  216. }
  217. /* Operating Mode Notification IE */
  218. if (bss_desc->oper_mode) {
  219. ieee_oper_ntf = bss_desc->oper_mode;
  220. oper_ntf = (void *)*buffer;
  221. memset(oper_ntf, 0, sizeof(*oper_ntf));
  222. oper_ntf->header.type = cpu_to_le16(WLAN_EID_OPMODE_NOTIF);
  223. oper_ntf->header.len = cpu_to_le16(sizeof(u8));
  224. oper_ntf->oper_mode = ieee_oper_ntf->oper_mode;
  225. *buffer += sizeof(*oper_ntf);
  226. ret_len += sizeof(*oper_ntf);
  227. }
  228. return ret_len;
  229. }
  230. int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv,
  231. struct host_cmd_ds_command *cmd, u16 cmd_action,
  232. struct mwifiex_11ac_vht_cfg *cfg)
  233. {
  234. struct host_cmd_11ac_vht_cfg *vhtcfg = &cmd->params.vht_cfg;
  235. cmd->command = cpu_to_le16(HostCmd_CMD_11AC_CFG);
  236. cmd->size = cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) +
  237. S_DS_GEN);
  238. vhtcfg->action = cpu_to_le16(cmd_action);
  239. vhtcfg->band_config = cfg->band_config;
  240. vhtcfg->misc_config = cfg->misc_config;
  241. vhtcfg->cap_info = cpu_to_le32(cfg->cap_info);
  242. vhtcfg->mcs_tx_set = cpu_to_le32(cfg->mcs_tx_set);
  243. vhtcfg->mcs_rx_set = cpu_to_le32(cfg->mcs_rx_set);
  244. return 0;
  245. }
  246. /* This function initializes the BlockACK setup information for given
  247. * mwifiex_private structure for 11ac enabled networks.
  248. */
  249. void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv)
  250. {
  251. priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT;
  252. if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
  253. priv->add_ba_param.tx_win_size =
  254. MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE;
  255. priv->add_ba_param.rx_win_size =
  256. MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE;
  257. } else {
  258. priv->add_ba_param.tx_win_size =
  259. MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
  260. priv->add_ba_param.rx_win_size =
  261. MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
  262. }
  263. return;
  264. }