11ac.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. sizeof(struct ieee_types_header),
  170. le16_to_cpu(vht_cap->header.len));
  171. mwifiex_fill_vht_cap_tlv(priv, vht_cap, bss_desc->bss_band);
  172. *buffer += sizeof(*vht_cap);
  173. ret_len += sizeof(*vht_cap);
  174. }
  175. /* VHT Operation IE */
  176. if (bss_desc->bcn_vht_oper) {
  177. if (priv->bss_mode == HostCmd_BSS_MODE_IBSS) {
  178. vht_op = (struct mwifiex_ie_types_vht_oper *)*buffer;
  179. memset(vht_op, 0, sizeof(*vht_op));
  180. vht_op->header.type =
  181. cpu_to_le16(WLAN_EID_VHT_OPERATION);
  182. vht_op->header.len = cpu_to_le16(sizeof(*vht_op) -
  183. sizeof(struct mwifiex_ie_types_header));
  184. memcpy((u8 *)vht_op +
  185. sizeof(struct mwifiex_ie_types_header),
  186. (u8 *)bss_desc->bcn_vht_oper +
  187. sizeof(struct ieee_types_header),
  188. le16_to_cpu(vht_op->header.len));
  189. /* negotiate the channel width and central freq
  190. * and keep the central freq as the peer suggests
  191. */
  192. supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
  193. switch (supp_chwd_set) {
  194. case 0:
  195. vht_op->chan_width =
  196. min_t(u8, IEEE80211_VHT_CHANWIDTH_80MHZ,
  197. bss_desc->bcn_vht_oper->chan_width);
  198. break;
  199. case 1:
  200. vht_op->chan_width =
  201. min_t(u8, IEEE80211_VHT_CHANWIDTH_160MHZ,
  202. bss_desc->bcn_vht_oper->chan_width);
  203. break;
  204. case 2:
  205. vht_op->chan_width =
  206. min_t(u8, IEEE80211_VHT_CHANWIDTH_80P80MHZ,
  207. bss_desc->bcn_vht_oper->chan_width);
  208. break;
  209. default:
  210. vht_op->chan_width =
  211. IEEE80211_VHT_CHANWIDTH_USE_HT;
  212. break;
  213. }
  214. *buffer += sizeof(*vht_op);
  215. ret_len += sizeof(*vht_op);
  216. }
  217. }
  218. /* Operating Mode Notification IE */
  219. if (bss_desc->oper_mode) {
  220. ieee_oper_ntf = bss_desc->oper_mode;
  221. oper_ntf = (void *)*buffer;
  222. memset(oper_ntf, 0, sizeof(*oper_ntf));
  223. oper_ntf->header.type = cpu_to_le16(WLAN_EID_OPMODE_NOTIF);
  224. oper_ntf->header.len = cpu_to_le16(sizeof(u8));
  225. oper_ntf->oper_mode = ieee_oper_ntf->oper_mode;
  226. *buffer += sizeof(*oper_ntf);
  227. ret_len += sizeof(*oper_ntf);
  228. }
  229. return ret_len;
  230. }