1 /** @file mlan_11ac.c
2  *
3  *  @brief This file defines the private and adapter data
4  *  structures and declares global function prototypes used
5  *  in MLAN module.
6  *
7  *  Copyright 2008-2024 NXP
8  *
9  *  SPDX-License-Identifier: BSD-3-Clause
10  *
11  */
12 
13 #include <mlan_api.h>
14 
15 /* Additional WMSDK header files */
16 #include <wmerrno.h>
17 #include <osa.h>
18 
19 /* Always keep this include at the end of all include files */
20 #include <mlan_remap_mem_operations.h>
21 
22 /********************************************************
23    Local Variables
24 ********************************************************/
25 
26 /********************************************************
27    Global Variables
28 ********************************************************/
29 
30 /********************************************************
31    Local Functions
32 ********************************************************/
33 #if CONFIG_11AC
34 /**
35  *  @brief determine the center frquency center index for bandwidth
36  *         of 80 MHz and 160 MHz
37  *
38  *  @param pmpriv       A pointer to mlan_private structure
39  *  @param band         band
40  *  @param pri_chan     primary channel
41  *  @param chan_bw      channel bandwidth
42  *
43  *  @return             channel center frequency center, if found; O, otherwise
44  */
45 
wlan_get_center_freq_idx(IN mlan_private * pmpriv,IN t_u8 band,IN t_u32 pri_chan,IN t_u8 chan_bw)46 t_u8 wlan_get_center_freq_idx(IN mlan_private *pmpriv, IN t_u8 band, IN t_u32 pri_chan, IN t_u8 chan_bw)
47 {
48     t_u8 center_freq_idx = 0;
49 
50     if ((band & BAND_AAC) != 0U)
51     {
52         switch (pri_chan)
53         {
54             case 36:
55             case 40:
56             case 44:
57             case 48:
58                 if (chan_bw == (t_u8)CHANNEL_BW_80MHZ)
59                 {
60                     center_freq_idx = 42;
61                 }
62                 break;
63             case 52:
64             case 56:
65             case 60:
66             case 64:
67                 if (chan_bw == (t_u8)CHANNEL_BW_80MHZ)
68                 {
69                     center_freq_idx = 58;
70                 }
71                 else if (chan_bw == (t_u8)CHANNEL_BW_160MHZ)
72                 {
73                     center_freq_idx = 50;
74                 }
75                 else
76                 {
77                     /* Do nothing */
78                 }
79                 break;
80             case 100:
81             case 104:
82             case 108:
83             case 112:
84                 if (chan_bw == (t_u8)CHANNEL_BW_80MHZ)
85                 {
86                     center_freq_idx = 106;
87                 }
88                 break;
89             case 116:
90             case 120:
91             case 124:
92             case 128:
93                 if (chan_bw == (t_u8)CHANNEL_BW_80MHZ)
94                 {
95                     center_freq_idx = 122;
96                 }
97                 else if (chan_bw == (t_u8)CHANNEL_BW_160MHZ)
98                 {
99                     center_freq_idx = 114;
100                 }
101                 else
102                 {
103                     /* Do nothing */
104                 }
105                 break;
106             case 132:
107             case 136:
108             case 140:
109             case 144:
110                 if (chan_bw == (t_u8)CHANNEL_BW_80MHZ)
111                 {
112                     center_freq_idx = 138;
113                 }
114                 break;
115             case 149:
116             case 153:
117             case 157:
118             case 161:
119                 if (chan_bw == (t_u8)CHANNEL_BW_80MHZ)
120                 {
121                     center_freq_idx = 155;
122                 }
123                 break;
124             case 165:
125             case 169:
126             case 173:
127             case 177:
128                 if (chan_bw == (t_u8)CHANNEL_BW_80MHZ)
129                 {
130                     center_freq_idx = 171;
131                 }
132                 break;
133             case 184:
134             case 188:
135             case 192:
136             case 196:
137                 if (chan_bw == (t_u8)CHANNEL_BW_80MHZ)
138                 {
139                     center_freq_idx = 190;
140                 }
141                 break;
142             default: /* error. go to the default */
143                 center_freq_idx = 42;
144                 break;
145         }
146     }
147     return center_freq_idx;
148 }
149 #endif
150 
151 /**
152  *  @brief This function gets the bitmap of nss which supports VHT mcs
153  *
154  *  @param mcs_map_set  VHT mcs map
155  *
156  *  @return             The bitmap of supported nss
157  */
wlan_get_nss_vht_mcs(t_u16 mcs_map_set)158 static t_u8 wlan_get_nss_vht_mcs(t_u16 mcs_map_set)
159 {
160     t_u8 nss, nss_map = 0;
161     for (nss = 1; nss <= 8U; nss++)
162     {
163         if (GET_VHTNSSMCS(mcs_map_set, nss) != NO_NSS_SUPPORT)
164         {
165             nss_map |= 1U << (nss - 1U);
166         }
167     }
168     PRINTM(MCMND, "Supported nss bit map:0x%02x\n", nss_map);
169     return nss_map;
170 }
171 
172 /**
173  *  @brief This function gets the number of nss which supports VHT mcs
174  *
175  *  @param mcs_map_set  VHT mcs map
176  *
177  *  @return             Number of supported nss
178  */
wlan_get_nss_num_vht_mcs(t_u16 mcs_map_set)179 static t_u8 wlan_get_nss_num_vht_mcs(t_u16 mcs_map_set)
180 {
181     t_u8 nss, nss_num = 0;
182     for (nss = 1; nss <= 8U; nss++)
183     {
184         if (GET_VHTNSSMCS(mcs_map_set, nss) != NO_NSS_SUPPORT)
185         {
186             nss_num++;
187         }
188     }
189     PRINTM(MCMND, "Supported nss:%d\n", nss_num);
190     return nss_num;
191 }
192 
193 /**
194  *  @brief This function fills the cap info
195  *
196  *  @param priv         A pointer to mlan_private structure
197  *  @param pht_cap      A pointer to MrvlIETypes_HTCap_t structure
198  *  @param bands        Band configuration
199  *
200  *  @return             N/A
201  */
wlan_fill_cap_info(mlan_private * priv,VHT_capa_t * vht_cap,t_u16 bands)202 static void wlan_fill_cap_info(mlan_private *priv, VHT_capa_t *vht_cap, t_u16 bands)
203 {
204     mlan_adapter *pmadapter = priv->adapter;
205     t_u32 usr_dot_11ac_dev_cap;
206 
207     ENTER();
208 
209 #if CONFIG_5GHz_SUPPORT
210     if ((bands & BAND_A) != 0U)
211     {
212         usr_dot_11ac_dev_cap = pmadapter->usr_dot_11ac_dev_cap_a;
213     }
214     else
215 #endif
216     {
217         usr_dot_11ac_dev_cap = pmadapter->usr_dot_11ac_dev_cap_bg;
218     }
219 
220     vht_cap->vht_cap_info = usr_dot_11ac_dev_cap;
221 #ifdef RW610
222     if (GET_VHTCAP_MAXMPDULEN(vht_cap->vht_cap_info) != 0U)
223         RESET_11ACMAXMPDULEN(vht_cap->vht_cap_info);
224 #endif
225 
226     LEAVE();
227 }
228 
229 #if CONFIG_11AC
230 /**
231  *  @brief Set/get 11ac configuration
232  *
233  *  @param pmadapter    A pointer to mlan_adapter structure
234  *  @param pioctl_req   A pointer to ioctl request buffer
235  *
236  *  @return     MLAN_STATUS_PENDING --success, otherwise fail
237  */
238 
wlan_11ac_ioctl_vhtcfg(IN mlan_private * pmpriv,IN t_u8 action,IN mlan_ds_11ac_vht_cfg * vht_cfg)239 mlan_status wlan_11ac_ioctl_vhtcfg(IN mlan_private *pmpriv, IN t_u8 action, IN mlan_ds_11ac_vht_cfg *vht_cfg)
240 {
241     mlan_status ret         = MLAN_STATUS_SUCCESS;
242     mlan_adapter *pmadapter = pmpriv->adapter;
243     t_u16 cmd_action        = 0;
244     t_u32 usr_vht_cap_info  = 0;
245     t_u32 cfg_value         = 0;
246     t_u32 hw_value          = 0;
247     t_u8 nss                = 0;
248     t_u16 no_nss_support    = NO_NSS_SUPPORT;
249 
250     ENTER();
251 
252 #define VHT_CAP_INFO_BIT_FIELDS                                                                                \
253     (MBIT(4) | MBIT(5) | MBIT(6) | MBIT(7) | MBIT(11) | MBIT(12) | MBIT(19) | MBIT(20) | MBIT(21) | MBIT(22) | \
254      MBIT(28) | MBIT(29))
255 
256     if (action == (t_u8)MLAN_ACT_SET)
257     {
258         /** SET operation */
259         /** validate the user input and correct it if necessary */
260         if (pmpriv->bss_role == MLAN_BSS_ROLE_STA)
261         {
262             if (vht_cfg->txrx == 3U)
263             {
264                 PRINTM(MERROR, "Configuration of VHT capabilities for TX/RX 3 is not supported in STA mode!\n");
265                 return MLAN_STATUS_FAILURE;
266             }
267         }
268         if (pmpriv->bss_role == MLAN_BSS_ROLE_UAP)
269         {
270             if (vht_cfg->txrx != 3U)
271             {
272                 PRINTM(MERROR, "Configuration of VHT capabilities for TX/RX %d is not supported in UAP mode!\n",
273                        vht_cfg->txrx);
274 
275                 return MLAN_STATUS_FAILURE;
276             }
277         }
278         /** set bit fileds */
279         usr_vht_cap_info = VHT_CAP_INFO_BIT_FIELDS & vht_cfg->vht_cap_info & pmadapter->hw_dot_11ac_dev_cap;
280         /** set MAX MPDU LEN field (bit 0 - bit 1) */
281         cfg_value = GET_VHTCAP_MAXMPDULEN(vht_cfg->vht_cap_info);
282         hw_value  = GET_VHTCAP_MAXMPDULEN(pmadapter->hw_dot_11ac_dev_cap);
283         SET_VHTCAP_MAXMPDULEN(usr_vht_cap_info, MIN(cfg_value, hw_value));
284         /** set CHAN Width Set field (bit 2 - bit 3) */
285         cfg_value = GET_VHTCAP_CHWDSET(vht_cfg->vht_cap_info);
286         hw_value  = GET_VHTCAP_CHWDSET(pmadapter->hw_dot_11ac_dev_cap);
287         SET_VHTCAP_CHWDSET(usr_vht_cap_info, MIN(cfg_value, hw_value));
288         /** set Rx STBC field (bit 8 - bit 10) */
289         cfg_value = GET_VHTCAP_RXSTBC(vht_cfg->vht_cap_info);
290         hw_value  = GET_VHTCAP_RXSTBC(pmadapter->hw_dot_11ac_dev_cap);
291         SET_VHTCAP_RXSTBC(usr_vht_cap_info, MIN(cfg_value, hw_value));
292         /** set Steering Number of BFer Ant (bit 13 - bit 15) */
293         cfg_value = GET_VHTCAP_SNBFERANT(vht_cfg->vht_cap_info);
294         hw_value  = GET_VHTCAP_SNBFERANT(pmadapter->hw_dot_11ac_dev_cap);
295         SET_VHTCAP_SNBFERANT(usr_vht_cap_info, MIN(cfg_value, hw_value));
296         /** set Number of Sounding Dimension (bit 16 - bit 18) */
297         cfg_value = GET_VHTCAP_NUMSNDDM(vht_cfg->vht_cap_info);
298         hw_value  = GET_VHTCAP_NUMSNDDM(pmadapter->hw_dot_11ac_dev_cap);
299         SET_VHTCAP_NUMSNDDM(usr_vht_cap_info, MIN(cfg_value, hw_value));
300         /** set Number of Max AMPDU Length Exponent (bit 23 - bit 25) */
301         cfg_value = GET_VHTCAP_MAXAMPDULENEXP(vht_cfg->vht_cap_info);
302         hw_value  = GET_VHTCAP_MAXAMPDULENEXP(pmadapter->hw_dot_11ac_dev_cap);
303         SET_VHTCAP_MAXAMPDULENEXP(usr_vht_cap_info, MIN(cfg_value, hw_value));
304         /** set VHT Link Adaptation Capable (bit 26 - bit 27) */
305         cfg_value = GET_VHTCAP_LINKADPCAP(vht_cfg->vht_cap_info);
306         hw_value  = GET_VHTCAP_LINKADPCAP(pmadapter->hw_dot_11ac_dev_cap);
307         SET_VHTCAP_LINKADPCAP(usr_vht_cap_info, MIN(cfg_value, hw_value));
308         /** update the user setting if it is beyond the hw capabiliteis */
309         vht_cfg->vht_cap_info = usr_vht_cap_info;
310         PRINTM(MINFO, "Set: vht cap info  0x%x\n", usr_vht_cap_info);
311 
312         /** update the RX MCS map */
313         if ((vht_cfg->txrx & MLAN_RADIO_RX) != 0U)
314         {
315             /* use the previous user value */
316             if (vht_cfg->vht_rx_mcs == 0xffffffffU)
317             {
318                 vht_cfg->vht_rx_mcs = GET_VHTMCS(pmadapter->usr_dot_11ac_mcs_support);
319             }
320             for (nss = 1; nss <= 8U; nss++)
321             {
322                 cfg_value = GET_VHTNSSMCS(vht_cfg->vht_rx_mcs, nss);
323                 hw_value  = GET_DEVNSSRXMCS(pmadapter->hw_dot_11ac_mcs_support, nss);
324                 if ((hw_value == NO_NSS_SUPPORT) || (cfg_value == NO_NSS_SUPPORT))
325                 {
326                     SET_VHTNSSMCS(vht_cfg->vht_rx_mcs, nss, no_nss_support);
327                 }
328                 else
329                 {
330                     SET_VHTNSSMCS(vht_cfg->vht_rx_mcs, nss, MIN(cfg_value, hw_value));
331                 }
332             }
333             PRINTM(MINFO, "Set: vht rx mcs set 0x%08x\n", vht_cfg->vht_rx_mcs);
334             /* use the previous user value */
335             if (vht_cfg->vht_tx_mcs == 0xffffffffU)
336             {
337                 vht_cfg->vht_tx_mcs = GET_VHTMCS(pmadapter->usr_dot_11ac_mcs_support >> 16);
338             }
339             for (nss = 1; nss <= 8U; nss++)
340             {
341                 cfg_value = GET_VHTNSSMCS(vht_cfg->vht_tx_mcs, nss);
342                 hw_value  = GET_DEVNSSTXMCS(pmadapter->hw_dot_11ac_mcs_support, nss);
343                 if ((hw_value == NO_NSS_SUPPORT) || (cfg_value == NO_NSS_SUPPORT))
344                 {
345                     SET_VHTNSSMCS(vht_cfg->vht_tx_mcs, nss, no_nss_support);
346                 }
347                 else
348                 {
349                     SET_VHTNSSMCS(vht_cfg->vht_tx_mcs, nss, MIN(cfg_value, hw_value));
350                 }
351             }
352 
353             PRINTM(MINFO, "Set: vht tx mcs set 0x%08x\n", vht_cfg->vht_tx_mcs);
354             if (!vht_cfg->skip_usr_11ac_mcs_cfg)
355             {
356                 RESET_DEVRXMCSMAP(pmadapter->usr_dot_11ac_mcs_support);
357                 pmadapter->usr_dot_11ac_mcs_support |= GET_VHTMCS(vht_cfg->vht_rx_mcs);
358                 RESET_DEVTXMCSMAP(pmadapter->usr_dot_11ac_mcs_support);
359                 pmadapter->usr_dot_11ac_mcs_support |= (GET_VHTMCS(vht_cfg->vht_tx_mcs) << 16);
360                 PRINTM(MINFO, "Set: vht mcs set 0x%08x\n", pmadapter->usr_dot_11ac_mcs_support);
361             }
362             else
363             {
364                 PRINTM(MINFO, "Skipped user 11ac mcs configuration\n");
365                 vht_cfg->skip_usr_11ac_mcs_cfg = MFALSE;
366             }
367         }
368     }
369 
370     if (pmpriv->bss_role == MLAN_BSS_ROLE_STA)
371     {
372         if ((vht_cfg->txrx & MLAN_RADIO_RX) != 0U)
373         {
374             /* maximum VHT configuration used in association */
375 
376             if (action == (t_u8)MLAN_ACT_SET)
377             {
378                 if (vht_cfg->band == BAND_SELECT_BG)
379                 {
380                     pmadapter->usr_dot_11ac_dev_cap_bg = usr_vht_cap_info;
381                 }
382 #if CONFIG_5GHz_SUPPORT
383                 else if (vht_cfg->band == BAND_SELECT_A)
384                 {
385                     pmadapter->usr_dot_11ac_dev_cap_a = usr_vht_cap_info;
386                 }
387 #endif
388                 else
389                 {
390                     pmadapter->usr_dot_11ac_dev_cap_bg = usr_vht_cap_info;
391 #if CONFIG_5GHz_SUPPORT
392                     pmadapter->usr_dot_11ac_dev_cap_a = usr_vht_cap_info;
393 #endif
394                 }
395                 pmadapter->usr_dot_11ac_bw = (t_u8)vht_cfg->bwcfg;
396             }
397             else
398             {
399                 /** GET operation */
400                 if (vht_cfg->band == BAND_SELECT_BG)
401                 {
402                     vht_cfg->vht_cap_info = pmadapter->usr_dot_11ac_dev_cap_bg;
403                     PRINTM(MINFO, "Get: vht cap info for 2.4GHz 0x%x\n", pmadapter->usr_dot_11ac_dev_cap_bg);
404                 }
405 #if CONFIG_5GHz_SUPPORT
406                 else if (vht_cfg->band == BAND_SELECT_A)
407                 {
408                     vht_cfg->vht_cap_info = pmadapter->usr_dot_11ac_dev_cap_a;
409                     PRINTM(MINFO, "Get: vht cap info for 5GHz 0x%x\n", pmadapter->usr_dot_11ac_dev_cap_a);
410                 }
411 #endif
412                 else
413                 {
414                     PRINTM(MINFO, "Get: invalid band selection for vht cap info\n");
415                     ret = MLAN_STATUS_FAILURE;
416                 }
417                 vht_cfg->bwcfg      = pmadapter->usr_dot_11ac_bw;
418                 vht_cfg->vht_rx_mcs = GET_DEVRXMCSMAP(pmadapter->usr_dot_11ac_mcs_support);
419                 vht_cfg->vht_tx_mcs = GET_DEVTXMCSMAP(pmadapter->usr_dot_11ac_mcs_support);
420                 vht_cfg->vht_rx_max_rate =
421                     wlan_convert_mcsmap_to_maxrate(pmpriv, (t_u8)vht_cfg->band, (t_u16)vht_cfg->vht_rx_mcs);
422                 vht_cfg->vht_tx_max_rate =
423                     wlan_convert_mcsmap_to_maxrate(pmpriv, (t_u8)vht_cfg->band, (t_u16)vht_cfg->vht_tx_mcs);
424             }
425             LEAVE();
426             return ret;
427         }
428     }
429 
430     if (action == (t_u8)MLAN_ACT_SET)
431     {
432         cmd_action = HostCmd_ACT_GEN_SET;
433     }
434     else
435     {
436         cmd_action = HostCmd_ACT_GEN_GET;
437     }
438 
439     /* Send request to firmware */
440     ret = wlan_prepare_cmd(pmpriv, HostCmd_CMD_11AC_CFG, cmd_action, 0, NULL, (t_void *)vht_cfg);
441     if (ret == MLAN_STATUS_SUCCESS)
442     {
443         ret = MLAN_STATUS_PENDING;
444     }
445 
446     LEAVE();
447     return ret;
448 }
449 #endif
450 
451 #if 0
452 /**
453  *  @brief Get/Set Operating Mode Notification cfg
454  *
455  *  @param pmadapter    A pointer to mlan_adapter structure
456  *  @param pioctl_req   A pointer to ioctl request buffer
457  *
458  *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
459  */
460 static mlan_status wlan_11ac_ioctl_opermodecfg(
461     IN pmlan_adapter    pmadapter,
462     IN pmlan_ioctl_req  pioctl_req)
463 {
464     mlan_private *pmpriv = pmadapter->priv[pioctl_req->bss_index];
465     t_u8 hw_bw_160or8080 = 0;
466     t_u8 hw_rx_nss = 0;
467 
468     ENTER();
469 
470     cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
471     if (pioctl_req->action == MLAN_ACT_GET) {
472         cfg->param.opermode_cfg.bw = pmpriv->usr_dot_11ac_opermode_bw;
473         cfg->param.opermode_cfg.nss = pmpriv->usr_dot_11ac_opermode_nss;
474     } else if (pioctl_req->action == MLAN_ACT_SET) {
475         hw_bw_160or8080 = GET_VHTCAP_CHWDSET(pmadapter->hw_dot_11ac_dev_cap);
476         hw_rx_nss = wlan_get_nss_num_vht_mcs(GET_DEVRXMCSMAP(pmadapter->hw_dot_11ac_mcs_support));
477         if ((((cfg->param.opermode_cfg.bw - 1) > BW_80MHZ) && !hw_bw_160or8080) ||
478             (cfg->param.opermode_cfg.nss > hw_rx_nss)) {
479             PRINTM(MERROR, "bw or nss NOT supported. HW support bw_160or8080=%d rx_nss=%d.\n",
480                 hw_bw_160or8080, hw_rx_nss);
481             LEAVE();
482             return MLAN_STATUS_FAILURE;
483         }
484         pmpriv->usr_dot_11ac_opermode_bw = cfg->param.opermode_cfg.bw;
485         pmpriv->usr_dot_11ac_opermode_nss = cfg->param.opermode_cfg.nss;
486     }
487 
488     LEAVE();
489     return MLAN_STATUS_SUCCESS;
490 }
491 
492 /**
493  *  @brief Get supported MCS set
494  *
495  *  @param pmadapter    A pointer to mlan_adapter structure
496  *  @param pioctl_req   A pointer to ioctl request buffer
497  *
498  *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
499  */
500 static mlan_status wlan_11ac_ioctl_supported_mcs_set(
501     IN pmlan_adapter    pmadapter,
502     IN pmlan_ioctl_req  pioctl_req)
503 {
504     /*mlan_ds_11ac_cfg *cfg= MNULL;*/
505     /*int rx_mcs_supp;*/
506     /*t_u8 mcs_set[NUM_MCS_SUPP];*/
507 
508     ENTER();
509 #if 0
510     if (pioctl_req->action == MLAN_ACT_SET) {
511         PRINTM(MERROR, "Set operation is not supported\n");
512         pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
513         LEAVE();
514         return MLAN_STATUS_FAILURE;
515     }
516     rx_mcs_supp = GET_11ACRXMCSSUPP(pmadapter->usr_dot_11ac_mcs_support);
517     /* Set MCS */
518     (void)__memset(pmadapter, (t_u8 *) mcs_set, 0xff, rx_mcs_supp);
519     /* Clear all the other values */
520     (void)__memset(pmadapter, (t_u8 *) &mcs_set[rx_mcs_supp], 0,
521                  NUM_MCS_FIELD - rx_mcs_supp);
522     /* Set MCS32 with 40MHz support */
523     if (ISSUPP_CHANWIDTH80(pmadapter->usr_dot_11ac_dev_cap_bg)
524 #if CONFIG_5GHz_SUPPORT
525         || ISSUPP_CHANWIDTH80(pmadapter->usr_dot_11ac_dev_cap_a)
526 #endif
527         )
528         SETHT_MCS32(mcs_set);
529 
530     cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
531     (void)__memcpy(pmadapter, cfg->param.supported_mcs_set, mcs_set, NUM_MCS_SUPP);
532 
533 #endif
534     LEAVE();
535     return MLAN_STATUS_SUCCESS;
536 }
537 
538 /********************************************************
539 			Global Functions
540 ********************************************************/
541 
542 /**
543  *  @brief This function prints the 802.11ac device capability
544  *
545  *  @param pmadapter     A pointer to mlan_adapter structure
546  *  @param cap           Capability value
547  *
548  *  @return        N/A
549  */
550 void wlan_show_dot11acdevcap(pmlan_adapter pmadapter, t_u32 cap)
551 {
552     ENTER();
553 
554     switch (GET_VHTCAP_MAXMPDULEN(cap)) {
555         case 0x0:
556             PRINTM(MINFO, "GET_HW_SPEC: Maximum MSDU length = 3895 octets\n");
557             break;
558         case 0x1:
559             PRINTM(MINFO, "GET_HW_SPEC: Maximum MSDU length = 7991 octets\n");
560             break;
561         case 0x2:
562             PRINTM(MINFO, "GET_HW_SPEC: Maximum MSDU length = 11454 octets\n");
563             break;
564         default:
565             PRINTM(MINFO, "Unsupport value\n");
566             break;
567     }
568 
569     PRINTM(MINFO, "GET_HW_SPEC: HTC-VHT %s\n",
570            (ISSUPP_11ACVHTHTCVHT(cap) ? "supported" : "not supported"));
571     PRINTM(MINFO, "GET_HW_SPEC: VHT TXOP PS %s\n",
572            (ISSUPP_11ACVHTTXOPPS(cap) ? "supported" : "not supported"));
573     PRINTM(MINFO, "GET_HW_SPEC: MU RX beamformee %s\n",
574            (ISSUPP_11ACMURXBEAMFORMEE(cap) ? "supported" : "not supported"));
575     PRINTM(MINFO, "GET_HW_SPEC: MU TX beamformee %s\n",
576            (ISSUPP_11ACMUTXBEAMFORMEE(cap) ? "supported" : "not supported"));
577     PRINTM(MINFO, "GET_HW_SPEC: SU RX Beamformee %s\n",
578            (ISSUPP_11ACSUBEAMFORMEE(cap) ? "supported" : "not supported"));
579     PRINTM(MINFO, "GET_HW_SPEC: SU TX Beamformer %s\n",
580            (ISSUPP_11ACSUBEAMFORMER(cap) ? "supported" : "not supported"));
581     PRINTM(MINFO, "GET_HW_SPEC: Rx STBC %s\n",
582            (ISSUPP_11ACRXSTBC(cap) ? "supported" : "not supported"));
583     PRINTM(MINFO, "GET_HW_SPEC: Tx STBC %s\n",
584            (ISSUPP_11ACTXSTBC(cap) ? "supported" : "not supported"));
585     PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 160MHz BW\n",
586            (ISSUPP_11ACSGI160(cap) ? "supported" : "not supported"));
587     PRINTM(MINFO, "GET_HW_SPEC: Short GI %s for 80MHz BW\n",
588            (ISSUPP_11ACSGI80(cap) ? "supported" : "not supported"));
589     PRINTM(MINFO, "GET_HW_SPEC: LDPC coding %s\n",
590            (ISSUPP_11ACLDPC(cap) ? "supported" : "not supported"));
591     PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160/80+80 MHz %s\n",
592            (ISSUPP_11ACBW8080(cap) ? "supported" : "not supported"));
593     PRINTM(MINFO, "GET_HW_SPEC: Channel BW 20/40/80/160 MHz %s\n",
594            (ISSUPP_11ACBW160(cap) ? "supported" : "not supported"));
595 
596     LEAVE();
597     return;
598 }
599 
600 /**
601  *  @brief This function prints the 802.11ac device MCS
602  *
603  *  @param pmadapter A pointer to mlan_adapter structure
604  *  @param support   Support value
605  *
606  *  @return        N/A
607  */
608 void wlan_show_dot11acmcssupport(pmlan_adapter pmadapter, t_u32 support)
609 {
610     ENTER();
611 
612     PRINTM(MINFO, "GET_HW_SPEC: MCSs for %2dx%2d MIMO\n", GET_DEVRXMCSMAP(support),
613                         GET_DEVTXMCSMAP(support));
614 
615     LEAVE();
616     return;
617 }
618 
619 #endif
620 
621 /**
622  *  @brief This function converts the 2-bit MCS map to the highest long GI
623  *  VHT PPDU data rate
624  *
625  *  @param priv         A pointer to mlan_private structure
626  *  @param bands        Supported bands
627  *  @param mcs_map      2-bit MCS map
628  *
629  *  @return             the max data rate for long GI
630  */
wlan_convert_mcsmap_to_maxrate(mlan_private * priv,t_u8 bands,t_u16 mcs_map)631 t_u16 wlan_convert_mcsmap_to_maxrate(mlan_private *priv, t_u8 bands, t_u16 mcs_map)
632 {
633     mlan_adapter *pmadapter = priv->adapter;
634     t_u8 i;
635     t_u8 nss;
636     t_u8 max_mcs;
637     t_u16 max_rate         = 0;
638     t_u32 usr_vht_cap_info = 0;
639     t_u32 usr_dot_11n_dev_cap;
640 
641     /* tables of the MCS map to the highest data rate (in Mbps)
642      * supported for long GI */
643     t_u16 max_rate_lgi_20MHZ[8][3] = {
644         {0x41, 0x4E, 0x0},     /* NSS = 1 */
645         {0x82, 0x9C, 0x0},     /* NSS = 2 */
646         {0xC3, 0xEA, 0x104},   /* NSS = 3 */
647         {0x104, 0x138, 0x0},   /* NSS = 4 */
648         {0x145, 0x186, 0x0},   /* NSS = 5 */
649         {0x186, 0x1D4, 0x208}, /* NSS = 6 */
650         {0x1C7, 0x222, 0x0},   /* NSS = 7 */
651         {0x208, 0x270, 0x0}    /* NSS = 8 */
652     };
653 
654     t_u16 max_rate_lgi_40MHZ[8][3] = {
655         {0x87, 0xA2, 0xB4},    /* NSS = 1 */
656         {0x10E, 0x144, 0x168}, /* NSS = 2 */
657         {0x195, 0x1E6, 0x21C}, /* NSS = 3 */
658         {0x21C, 0x288, 0x2D0}, /* NSS = 4 */
659         {0x2A3, 0x32A, 0x384}, /* NSS = 5 */
660         {0x32A, 0x3CC, 0x438}, /* NSS = 6 */
661         {0x3B1, 0x46E, 0x4EC}, /* NSS = 7 */
662         {0x438, 0x510, 0x5A0}  /* NSS = 8 */
663     };
664 
665     t_u16 max_rate_lgi_80MHZ[8][3] = {
666         {0x124, 0x15F, 0x186}, /* NSS = 1 */
667         {0x249, 0x2BE, 0x30C}, /* NSS = 2 */
668         {0x36D, 0x41D, 0x492}, /* NSS = 3 */
669         {0x492, 0x57C, 0x618}, /* NSS = 4 */
670         {0x5B6, 0x6DB, 0x79E}, /* NSS = 5 */
671         {0x6DB, 0x83A, 0x0},   /* NSS = 6 */
672         {0x7FF, 0x999, 0xAAA}, /* NSS = 7 */
673         {0x924, 0xAF8, 0xC30}  /* NSS = 8 */
674     };
675     t_u16 max_rate_lgi_160MHZ[8][3] = {
676         {0x249, 0x2BE, 0x30C},   /* NSS = 1 */
677         {0x492, 0x57C, 0x618},   /* NSS = 2 */
678         {0x6DB, 0x83A, 0x0},     /* NSS = 3 */
679         {0x924, 0xAF8, 0xC30},   /* NSS = 4 */
680         {0xB6D, 0xDB6, 0xF3C},   /* NSS = 5 */
681         {0xDB6, 0x1074, 0x1248}, /* NSS = 6 */
682         {0xFFF, 0x1332, 0x1554}, /* NSS = 7 */
683         {0x1248, 0x15F0, 0x1860} /* NSS = 8 */
684     };
685 
686 #if CONFIG_5GHz_SUPPORT
687     if ((bands & BAND_AAC) != 0U)
688     {
689         usr_vht_cap_info    = pmadapter->usr_dot_11ac_dev_cap_a;
690         usr_dot_11n_dev_cap = pmadapter->usr_dot_11n_dev_cap_a;
691     }
692     else
693     {
694 #endif
695         usr_vht_cap_info    = pmadapter->usr_dot_11ac_dev_cap_bg;
696         usr_dot_11n_dev_cap = pmadapter->usr_dot_11n_dev_cap_bg;
697 #if CONFIG_5GHz_SUPPORT
698     }
699 #endif
700 
701     /* find the max NSS supported */
702     nss = 0;
703     for (i = 0; i < 8U; i++)
704     {
705         max_mcs = (t_u8)((mcs_map >> (2U * i)) & 0x3U);
706         if (max_mcs < 3U)
707         {
708             nss = i;
709         }
710     }
711 
712     max_mcs = (t_u8)((mcs_map >> (2U * nss)) & 0x3U);
713     /* if max_mcs is 3, nss must be 0 (SS = 1). Thus, max mcs is MCS 9*/
714     if (max_mcs >= 3U)
715     {
716         max_mcs = (t_u8)2U;
717     }
718 
719     if (GET_VHTCAP_CHWDSET(usr_vht_cap_info) != 0U)
720     {
721         /* support 160 MHz */
722         max_rate = max_rate_lgi_160MHZ[nss][max_mcs];
723         if (max_mcs >= 1U && max_rate == 0U)
724         {
725             /* MCS9 is not supported in NSS6 */
726             max_rate = max_rate_lgi_160MHZ[nss][max_mcs - 1U];
727         }
728     }
729     else
730     {
731         if (pmadapter->usr_dot_11ac_bw == BW_FOLLOW_VHTCAP)
732         {
733             max_rate = max_rate_lgi_80MHZ[nss][max_mcs];
734             if (max_mcs >= 1U && max_rate == 0U)
735             {
736                 /* MCS9 is not supported in NSS3 */
737                 max_rate = max_rate_lgi_80MHZ[nss][max_mcs - 1U];
738             }
739         }
740         else
741         {
742             if (ISSUPP_CHANWIDTH40(usr_dot_11n_dev_cap) != 0U)
743             {
744                 max_rate = max_rate_lgi_40MHZ[nss][max_mcs];
745             }
746             else
747             {
748                 max_rate = max_rate_lgi_20MHZ[nss][max_mcs];
749                 /* MCS9 is not supported in NSS1/2/4/5/7/8 */
750                 if (max_mcs >= 1U && max_rate == 0U)
751                 {
752                     max_rate = max_rate_lgi_20MHZ[nss][max_mcs - 1U];
753                 }
754             }
755         }
756     }
757     PRINTM(MCMND, "max_rate=%dM\n", max_rate);
758     return max_rate;
759 }
760 
761 /**
762  *  @brief This function fills the VHT cap tlv out put format is LE, not CPU
763  *
764  *  @param priv         A pointer to mlan_private structure
765  *  @param pvht_cap      A pointer to MrvlIETypes_HTCap_t structure
766  *  @param bands        Band configuration
767  *  @param flag         TREU--pvht_cap has the setting for resp
768  *                      MFALSE -- pvht_cap is clean
769  *  @return             N/A
770  */
wlan_fill_vht_cap_tlv(mlan_private * priv,MrvlIETypes_VHTCap_t * pvht_cap,t_u16 bands,t_u8 flag)771 void wlan_fill_vht_cap_tlv(mlan_private *priv, MrvlIETypes_VHTCap_t *pvht_cap, t_u16 bands, t_u8 flag)
772 {
773     mlan_adapter *pmadapter = priv->adapter;
774     t_u16 mcs_map_user      = 0;
775     t_u16 mcs_map_resp      = 0;
776     t_u32 mcs_map_result    = 0U;
777     t_u16 mcs_user          = 0;
778     t_u16 mcs_resp          = 0;
779     t_u16 nss;
780     t_u16 no_nss_support = NO_NSS_SUPPORT;
781 
782     ENTER();
783 
784     /* Fill VHT cap info */
785     wlan_fill_cap_info(priv, &pvht_cap->vht_cap, bands);
786     pvht_cap->vht_cap.vht_cap_info = wlan_cpu_to_le32(pvht_cap->vht_cap.vht_cap_info);
787 
788     /* Fill VHT MCS Set */
789     /* rx MCS Set, find the minimum of the user rx mcs and ap rx mcs*/
790     mcs_map_resp = mcs_map_user = (t_u16)GET_DEVRXMCSMAP(pmadapter->usr_dot_11ac_mcs_support);
791     if (flag != 0U)
792     {
793         mcs_map_resp = wlan_le16_to_cpu(pvht_cap->vht_cap.mcs_sets.rx_mcs_map);
794     }
795     mcs_map_result = 0U;
796     for (nss = 1; nss <= 8U; nss++)
797     {
798         mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
799         mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
800         if ((mcs_user == NO_NSS_SUPPORT) || (mcs_resp == NO_NSS_SUPPORT))
801         {
802             SET_VHTNSSMCS(mcs_map_result, nss, no_nss_support);
803         }
804         else
805         {
806             SET_VHTNSSMCS(mcs_map_result, nss, MIN(mcs_user, mcs_resp));
807         }
808     }
809     /* rx MCS map */
810     pvht_cap->vht_cap.mcs_sets.rx_mcs_map = wlan_cpu_to_le16(mcs_map_result);
811 
812     /* rx highest rate */
813     pvht_cap->vht_cap.mcs_sets.rx_max_rate = wlan_convert_mcsmap_to_maxrate(priv, (t_u8)bands, (t_u16)mcs_map_result);
814     pvht_cap->vht_cap.mcs_sets.rx_max_rate = wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.rx_max_rate);
815 
816     /* tx MCS Set find the minimum of the user tx mcs and ap tx mcs */
817     mcs_map_resp = mcs_map_user = (t_u16)GET_DEVTXMCSMAP(pmadapter->usr_dot_11ac_mcs_support);
818     if (flag != 0U)
819     {
820         mcs_map_resp = wlan_le16_to_cpu(pvht_cap->vht_cap.mcs_sets.tx_mcs_map);
821     }
822     mcs_map_result = 0U;
823     for (nss = 1; nss <= 8U; nss++)
824     {
825         mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
826         mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
827         if ((mcs_user == NO_NSS_SUPPORT) || (mcs_resp == NO_NSS_SUPPORT))
828         {
829             SET_VHTNSSMCS(mcs_map_result, nss, no_nss_support);
830         }
831         else
832         {
833             SET_VHTNSSMCS(mcs_map_result, nss, MIN(mcs_user, mcs_resp));
834         }
835     }
836 
837     /* tx MCS map */
838     pvht_cap->vht_cap.mcs_sets.tx_mcs_map = wlan_cpu_to_le16(mcs_map_result);
839     /* tx highest rate */
840     pvht_cap->vht_cap.mcs_sets.tx_max_rate = wlan_convert_mcsmap_to_maxrate(priv, (t_u8)bands, (t_u16)mcs_map_result);
841     pvht_cap->vht_cap.mcs_sets.tx_max_rate = wlan_cpu_to_le16(pvht_cap->vht_cap.mcs_sets.tx_max_rate);
842 
843     LEAVE();
844     return;
845 }
846 
847 #if 0
848 /**
849  *  @brief This function fills the VHT cap tlv out put format is CPU
850  *
851  *  @param priv         A pointer to mlan_private structure
852  *  @param pvht_cap      A pointer to MrvlIETypes_HTCap_t structure
853  *  @param bands        Band configuration
854  *
855  *  @return             N/A
856  */
857 void wlan_fill_vht_cap_ie(mlan_private *priv,
858         IEEEtypes_VHTCap_t *pvht_cap, t_u16 bands)
859 {
860     ENTER();
861 
862     pvht_cap->ieee_hdr.element_id = VHT_CAPABILITY;
863     pvht_cap->ieee_hdr.len = sizeof(VHT_capa_t);
864 
865     /* Fill VHT cap info */
866     wlan_fill_cap_info(priv, &pvht_cap->vht_cap, bands);
867 
868     /* rx MCS map */
869     pvht_cap->vht_cap.mcs_sets.rx_mcs_map =
870         GET_DEVRXMCSMAP(priv->usr_dot_11ac_mcs_support);
871 
872     /* rx highest rate */
873     pvht_cap->vht_cap.mcs_sets.rx_max_rate =
874         wlan_convert_mcsmap_to_maxrate(priv, bands, pvht_cap->vht_cap.mcs_sets.rx_mcs_map);
875 
876     /* tx MCS map */
877     pvht_cap->vht_cap.mcs_sets.tx_mcs_map = GET_DEVTXMCSMAP(priv->usr_dot_11ac_mcs_support);
878     /* tx highest rate */
879     pvht_cap->vht_cap.mcs_sets.tx_max_rate =
880         wlan_convert_mcsmap_to_maxrate(priv, bands,pvht_cap->vht_cap.mcs_sets.tx_mcs_map);
881 
882     LEAVE();
883     return;
884 }
885 
886 #ifdef HOST_TDLS_SUPPORT
887 /*
888  *  @brief This function check if AP is in 11ac mode
889  *
890  *  @param priv         A pointer to mlan_private structure
891  *
892  *  @return             MTRUE/MFALSE
893  */
894 t_u8 wlan_is_ap_in_11ac_mode(mlan_private *priv)
895 {
896     BSSDescriptor_t *pbss_desc;
897     IEEEtypes_VHTOprat_t *vht_oprat = MNULL;
898     pbss_desc = &priv->curr_bss_params.bss_descriptor;
899 #ifdef ENABLE_SAVE_SCAN_RESP
900     vht_oprat = pbss_desc->pvht_oprat;
901     if(!pbss_desc->pvht_cap)
902 #else
903     vht_oprat = &pbss_desc->vht_oprat;
904     if(pbss_desc->vht_cap.ieee_hdr.element_id != VHT_CAPABILITY)
905 #endif
906         return MFALSE;
907     if(vht_oprat && (vht_oprat->ieee_hdr.element_id == VHT_OPERATION)) {
908         if(vht_oprat->chan_width == VHT_OPER_CHWD_20_40MHZ)
909             return MFALSE;
910         else
911             return MTRUE;
912     }
913     else
914         return MFALSE;
915 }
916 
917 
918 /**
919  *  @brief This function fills the VHTOperation ie out put format is CPU
920  *
921  *  @param priv         A pointer to mlan_private structure
922  *  @param vht_oprat    A pointer to IEEEtypes_VHTOprat_t structure
923  *  @param sta_ptr      A pointer to sta_node
924  *
925  *  @return             N/A
926  */
927 void wlan_fill_tdls_vht_oprat_ie(mlan_private *priv, IEEEtypes_VHTOprat_t *vht_oprat, sta_node *sta_ptr)
928 {
929     t_u8                    supp_chwd_set;
930     t_u8                    peer_supp_chwd_set;
931     t_u8                    ap_supp_chwd_set;
932     t_u32                   usr_vht_cap_info;
933 
934     t_u16 mcs_map_user = 0;
935     t_u16 mcs_map_resp = 0;
936     t_u16 mcs_map_result = 0;
937     t_u16 mcs_user = 0;
938     t_u16 mcs_resp = 0;
939     t_u16 nss;
940     t_u16 no_nss_support = NO_NSS_SUPPORT;
941     t_u8  chan_bw = 0;
942     BSSDescriptor_t *pbss_desc;
943     IEEEtypes_VHTCap_t *pvht_cap = &sta_ptr->vht_cap;
944     IEEEtypes_VHTCap_t *ap_vht_cap = MNULL;
945     ENTER();
946 
947     pbss_desc = &priv->curr_bss_params.bss_descriptor;
948 
949      /* Check if AP is in 11ac mode */
950      if(MFALSE == wlan_is_ap_in_11ac_mode(priv)){
951         if(sta_ptr->ExtCap.ieee_hdr.element_id != EXT_CAPABILITY){
952             PRINTM(MMSG,"No Peer's Ext_cap info\n");
953             return;
954         }
955         if(!ISSUPP_EXTCAP_TDLS_WIDER_BANDWIDTH(sta_ptr->ExtCap.ext_cap)){
956             PRINTM(MMSG,"Peer don't support Wider Bandwitch in Ext_cap\n");
957             return;
958         }
959     }
960     else{
961 #ifdef ENABLE_SAVE_SCAN_RESP
962         ap_vht_cap = pbss_desc->pvht_cap;
963 #else
964         ap_vht_cap = &pbss_desc->vht_cap;
965 #endif
966     }
967 
968     vht_oprat->ieee_hdr.element_id = VHT_OPERATION;
969     vht_oprat->ieee_hdr.len = sizeof(IEEEtypes_VHTOprat_t) - sizeof(IEEEtypes_Header_t);
970 
971 #if CONFIG_5GHz_SUPPORT
972     if (pbss_desc->bss_band & BAND_A)
973         usr_vht_cap_info= priv->usr_dot_11ac_dev_cap_a;
974     else
975 #endif
976     usr_vht_cap_info = priv->usr_dot_11ac_dev_cap_bg;
977 
978     /* find the minmum bandwith between AP/TDLS peers */
979     supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info);
980     peer_supp_chwd_set = GET_VHTCAP_CHWDSET(pvht_cap->vht_cap.vht_cap_info);
981     supp_chwd_set = MIN(supp_chwd_set, peer_supp_chwd_set);
982 
983     /* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */
984     if(ap_vht_cap && !ISSUPP_EXTCAP_TDLS_WIDER_BANDWIDTH(sta_ptr->ExtCap.ext_cap)){
985         ap_supp_chwd_set = GET_VHTCAP_CHWDSET(ap_vht_cap->vht_cap.vht_cap_info);
986         supp_chwd_set = MIN(supp_chwd_set, ap_supp_chwd_set);
987     }
988     switch(supp_chwd_set){
989         case VHT_CAP_CHWD_80MHZ:
990             vht_oprat->chan_width = VHT_OPER_CHWD_80MHZ;
991             break;
992         case VHT_CAP_CHWD_160MHZ:
993             vht_oprat->chan_width = VHT_OPER_CHWD_160MHZ;
994             break;
995         case VHT_CAP_CHWD_80_80MHZ:
996             vht_oprat->chan_width = VHT_OPER_CHWD_80_80MHZ;
997             break;
998 
999     }
1000 
1001     /* Fill BASIC VHT MCS and NSS Set */
1002     /* rx MCS Set, find the minimum of the user rx mcs and peer rx mcs*/
1003     mcs_map_user = GET_DEVRXMCSMAP(priv->usr_dot_11ac_mcs_support);
1004     mcs_map_resp = pvht_cap->vht_cap.mcs_sets.rx_mcs_map;
1005     mcs_map_result = 0;
1006     for (nss = 1; nss <= 8; nss++) {
1007         mcs_user = GET_VHTNSSMCS(mcs_map_user, nss);
1008         mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss);
1009         if ((mcs_user == NO_NSS_SUPPORT) || (mcs_resp == NO_NSS_SUPPORT))
1010             SET_VHTNSSMCS(mcs_map_result, nss, no_nss_support);
1011         else
1012             SET_VHTNSSMCS(mcs_map_result, nss, MIN(mcs_user, mcs_resp));
1013     }
1014     /* Basic MCS map */
1015     vht_oprat->basic_MCS_map = mcs_map_result;
1016     switch(vht_oprat->chan_width){
1017         case VHT_OPER_CHWD_80MHZ:
1018             chan_bw = CHANNEL_BW_80MHZ;
1019             break;
1020         case VHT_OPER_CHWD_160MHZ:
1021             chan_bw = CHANNEL_BW_160MHZ;
1022             break;
1023         case VHT_OPER_CHWD_80_80MHZ:
1024             chan_bw = CHANNEL_BW_80MHZ;
1025             break;
1026     }
1027     vht_oprat->chan_center_freq_1 = wlan_get_center_freq_idx(priv,BAND_AAC,pbss_desc->channel, chan_bw);
1028 
1029     LEAVE();
1030     return;
1031 }
1032 #endif
1033 #endif
1034 
1035 /**
1036  *  @brief This function append the 802_11AC tlv
1037  *
1038  *  @param pmpriv       A pointer to mlan_private structure
1039  *  @param pbss_desc    A pointer to BSSDescriptor_t structure
1040  *  @param ppbuffer     A Pointer to command buffer pointer
1041  *
1042  *  @return bytes added to the buffer
1043  */
wlan_cmd_append_11ac_tlv(mlan_private * pmpriv,BSSDescriptor_t * pbss_desc,t_u8 ** ppbuffer)1044 int wlan_cmd_append_11ac_tlv(mlan_private *pmpriv, BSSDescriptor_t *pbss_desc, t_u8 **ppbuffer)
1045 {
1046     pmlan_adapter pmadapter = pmpriv->adapter;
1047     MrvlIETypes_VHTCap_t *pvht_cap;
1048     MrvlIETypes_OperModeNtf_t *pmrvl_oper_mode;
1049     t_u16 mcs_map_user = 0;
1050     t_u16 nss;
1051 #ifdef ADHOC_11N
1052     MrvlIETypes_VHTOprat_t *pvht_op;
1053     t_u8 supp_chwd_set;
1054     t_u32 usr_vht_cap_info;
1055 #endif
1056     int ret_len = 0;
1057 
1058     ENTER();
1059 
1060     /* Null Checks */
1061     if (ppbuffer == MNULL)
1062     {
1063         LEAVE();
1064         return 0;
1065     }
1066     if (*ppbuffer == MNULL)
1067     {
1068         LEAVE();
1069         return 0;
1070     }
1071     /* VHT Capabilities IE */
1072     if (pbss_desc->pvht_cap != MNULL && wlan_get_nss_vht_mcs(pbss_desc->pvht_cap->vht_cap.mcs_sets.rx_mcs_map) != 0U)
1073     {
1074         pvht_cap = (MrvlIETypes_VHTCap_t *)(void *)*ppbuffer;
1075         (void)__memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
1076         pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
1077         pvht_cap->header.len  = (t_u16)sizeof(VHT_capa_t);
1078         (void)__memcpy(pmadapter, (t_u8 *)pvht_cap + sizeof(MrvlIEtypesHeader_t),
1079                        (t_u8 *)pbss_desc->pvht_cap + sizeof(IEEEtypes_Header_t), pvht_cap->header.len);
1080 
1081         wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pbss_desc->bss_band, (t_u8)MTRUE);
1082         if (wlan_use_non_default_ht_vht_cap(pbss_desc))
1083         {
1084             /* Indicate 3 STS in VHT cap info */
1085             pvht_cap->vht_cap.vht_cap_info = ((pvht_cap->vht_cap.vht_cap_info & (~(0x7 << 13))) | (0x2 << 13));
1086         }
1087 
1088         HEXDUMP("VHT_CAPABILITIES IE", (t_u8 *)pvht_cap, sizeof(MrvlIETypes_VHTCap_t));
1089         *ppbuffer += sizeof(MrvlIETypes_VHTCap_t);
1090         ret_len += (int)sizeof(MrvlIETypes_VHTCap_t);
1091         pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
1092     }
1093     else
1094     {
1095         LEAVE();
1096         return 0;
1097     }
1098 
1099     /* Operating Mode Notification IE */
1100     pmrvl_oper_mode = (MrvlIETypes_OperModeNtf_t *)(void *)*ppbuffer;
1101     (void)__memset(pmadapter, pmrvl_oper_mode, 0, sizeof(MrvlIETypes_OperModeNtf_t));
1102     pmrvl_oper_mode->header.type = wlan_cpu_to_le16(OPER_MODE_NTF);
1103     pmrvl_oper_mode->header.len  = (t_u16)sizeof(t_u8);
1104 
1105     if (pmadapter->usr_dot_11ac_opermode_bw != 0U || pmadapter->usr_dot_11ac_opermode_nss != 0U)
1106     {
1107         pmrvl_oper_mode->oper_mode |= (pmadapter->usr_dot_11ac_opermode_nss - 1U) << 4U;
1108         pmrvl_oper_mode->oper_mode |= pmadapter->usr_dot_11ac_opermode_bw - 1U;
1109         if ((pbss_desc->bss_band & BAND_G) != 0U)
1110         {
1111             if (!(IS_OPER_MODE_20M(pmrvl_oper_mode->oper_mode)))
1112             {
1113                 if ((pbss_desc->pht_cap->ht_cap.ht_cap_info & MBIT(1)) != 0U)
1114                 {
1115                     SET_OPER_MODE_40M(pmrvl_oper_mode->oper_mode);
1116                 }
1117                 else
1118                 {
1119                     SET_OPER_MODE_20M(pmrvl_oper_mode->oper_mode);
1120                 }
1121             }
1122         }
1123     }
1124     else
1125     {
1126         /** set default bandwidth:80M*/
1127         SET_OPER_MODE_80M(pmrvl_oper_mode->oper_mode);
1128 
1129         mcs_map_user = (t_u16)GET_DEVRXMCSMAP(pmadapter->usr_dot_11ac_mcs_support);
1130         nss          = wlan_get_nss_num_vht_mcs(mcs_map_user);
1131         pmrvl_oper_mode->oper_mode |= (t_u8)(nss - 1U) << 4U;
1132 
1133         switch (pbss_desc->curr_bandwidth)
1134         {
1135             case BW_20MHZ:
1136                 SET_OPER_MODE_20M(pmrvl_oper_mode->oper_mode);
1137                 break;
1138             case BW_40MHZ:
1139                 SET_OPER_MODE_40M(pmrvl_oper_mode->oper_mode);
1140                 break;
1141             case BW_80MHZ:
1142             default:
1143                 PRINTM(MINFO, "Unexpected bandwidth.\n");
1144                 break;
1145         }
1146     }
1147     HEXDUMP("OPER MODE NTF IE", (t_u8 *)pmrvl_oper_mode, sizeof(MrvlIETypes_OperModeNtf_t));
1148     *ppbuffer += sizeof(MrvlIETypes_OperModeNtf_t);
1149     ret_len += (int)sizeof(MrvlIETypes_OperModeNtf_t);
1150     pmrvl_oper_mode->header.len = wlan_cpu_to_le16(pmrvl_oper_mode->header.len);
1151 
1152     LEAVE();
1153     return ret_len;
1154 }
1155 
1156 #if 0
1157 /**
1158  *  @brief 11ac configuration handler
1159  *
1160  *  @param pmadapter    A pointer to mlan_adapter structure
1161  *  @param pioctl_req   A pointer to ioctl request buffer
1162  *
1163  *  @return     MLAN_STATUS_SUCCESS --success, otherwise fail
1164  */
1165 mlan_status wlan_11ac_cfg_ioctl(pmlan_adapter pmadapter, pmlan_ioctl_req pioctl_req)
1166 {
1167     mlan_status status = MLAN_STATUS_SUCCESS;
1168     mlan_ds_11ac_cfg *cfg = MNULL;
1169 
1170     ENTER();
1171 
1172     if (pioctl_req->buf_len < sizeof(mlan_ds_11ac_cfg)) {
1173         PRINTM(MINFO, "MLAN bss IOCTL length is too short.\n");
1174         pioctl_req->data_read_written = 0;
1175         pioctl_req->buf_len_needed = sizeof(mlan_ds_11ac_cfg);
1176         pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
1177         LEAVE();
1178         return MLAN_STATUS_RESOURCE;
1179     }
1180     cfg = (mlan_ds_11ac_cfg *)pioctl_req->pbuf;
1181     switch (cfg->sub_command) {
1182         case MLAN_OID_11AC_VHT_CFG:
1183             status = wlan_11ac_ioctl_vhtcfg(pmadapter, pioctl_req);
1184             break;
1185         case MLAN_OID_11AC_CFG_SUPPORTED_MCS_SET:
1186             status = wlan_11ac_ioctl_supported_mcs_set(pmadapter, pioctl_req);
1187             break;
1188         case MLAN_OID_11AC_OPERMODE_CFG:
1189             status = wlan_11ac_ioctl_opermodecfg(pmadapter, pioctl_req);
1190             break;
1191         default:
1192             pioctl_req->status_code = MLAN_ERROR_IOCTL_INVALID;
1193             status = MLAN_STATUS_FAILURE;
1194             break;
1195     }
1196     LEAVE();
1197     return status;
1198 }
1199 #endif
1200 
1201 /**
1202  *  @brief This function prepares 11ac cfg command
1203  *
1204  *  @param pmpriv       A pointer to mlan_private structure
1205  *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
1206  *  @param cmd_action   the action: GET or SET
1207  *  @param pdata_buf    A pointer to data buffer
1208  *  @return         MLAN_STATUS_SUCCESS
1209  */
wlan_cmd_11ac_cfg(IN pmlan_private pmpriv,IN HostCmd_DS_COMMAND * cmd,IN t_u16 cmd_action,IN t_void * pdata_buf)1210 mlan_status wlan_cmd_11ac_cfg(IN pmlan_private pmpriv,
1211                               IN HostCmd_DS_COMMAND *cmd,
1212                               IN t_u16 cmd_action,
1213                               IN t_void *pdata_buf)
1214 {
1215     HostCmd_DS_11AC_CFG *vhtcfg   = &cmd->params.vhtcfg;
1216     mlan_ds_11ac_vht_cfg *vht_cfg = (mlan_ds_11ac_vht_cfg *)pdata_buf;
1217 
1218     ENTER();
1219     cmd->command = wlan_cpu_to_le16(HostCmd_CMD_11AC_CFG);
1220     cmd->size    = wlan_cpu_to_le16(sizeof(HostCmd_DS_11AC_CFG) + S_DS_GEN);
1221     if (pmpriv->bss_type == MLAN_BSS_TYPE_UAP)
1222     {
1223         cmd->seq_num = (t_u16)(0x01U) << 12;
1224     }
1225     vhtcfg->action      = wlan_cpu_to_le16(cmd_action);
1226     vhtcfg->band_config = (t_u8)(vht_cfg->band & 0xFFU);
1227     vhtcfg->misc_config = (t_u8)(vht_cfg->txrx & 0x3U);
1228     if (vhtcfg->misc_config != 2U)
1229     {
1230         vhtcfg->misc_config |= (t_u8)(vht_cfg->bwcfg << 2);
1231     }
1232 
1233     vhtcfg->vht_cap_info = wlan_cpu_to_le32(vht_cfg->vht_cap_info);
1234     vht_cfg->vht_rx_mcs  = wlan_cpu_to_le32(vht_cfg->vht_rx_mcs);
1235     (void)__memcpy(pmpriv->adapter, &vhtcfg->vht_supp_mcs_set[0], &vht_cfg->vht_rx_mcs, sizeof(t_u32));
1236     vht_cfg->vht_tx_mcs = wlan_cpu_to_le32(vht_cfg->vht_tx_mcs);
1237     (void)__memcpy(pmpriv->adapter, &vhtcfg->vht_supp_mcs_set[4], &vht_cfg->vht_tx_mcs, sizeof(t_u32));
1238     LEAVE();
1239     return MLAN_STATUS_SUCCESS;
1240 }
1241 
1242 #if 0
1243 /**
1244  *  @brief This function handles the command response of 11ac cfg
1245  *
1246  *  @param pmpriv       A pointer to mlan_private structure
1247  *  @param resp         A pointer to HostCmd_DS_COMMAND
1248  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
1249  *
1250  *  @return        MLAN_STATUS_SUCCESS
1251  */
1252 mlan_status wlan_ret_11ac_cfg(
1253     IN  pmlan_private        pmpriv,
1254     IN  HostCmd_DS_COMMAND   *resp,
1255     IN  mlan_ioctl_req       *pioctl_buf)
1256 {
1257     pmlan_adapter        pmadapter = pmpriv->adapter;
1258     mlan_ds_11ac_cfg    *cfg = MNULL;
1259     HostCmd_DS_11AC_CFG *vhtcfg = &resp->params.vhtcfg;
1260 
1261     ENTER();
1262     if (pioctl_buf && (wlan_le16_to_cpu(vhtcfg->action) == HostCmd_ACT_GEN_GET)) {
1263         cfg = (mlan_ds_11ac_cfg *)pioctl_buf->pbuf;
1264         cfg->param.vht_cfg.band = vhtcfg->band_config;
1265         cfg->param.vht_cfg.txrx = vhtcfg->misc_config & 0x03;
1266         if (cfg->param.vht_cfg.txrx & 0x1)
1267             cfg->param.vht_cfg.bwcfg = (vhtcfg->misc_config & 0x04) >> 2;
1268         else
1269             cfg->param.vht_cfg.bwcfg = 0;
1270 
1271         cfg->param.vht_cfg.vht_cap_info = wlan_le32_to_cpu(vhtcfg->vht_cap_info);
1272         (void)__memcpy(pmadapter, &cfg->param.vht_cfg.vht_rx_mcs,
1273                           &vhtcfg->vht_supp_mcs_set[0], sizeof(t_u32));
1274         cfg->param.vht_cfg.vht_rx_mcs =
1275             wlan_le32_to_cpu(cfg->param.vht_cfg.vht_rx_mcs);
1276         (void)__memcpy(pmadapter, &cfg->param.vht_cfg.vht_tx_mcs,
1277                           &vhtcfg->vht_supp_mcs_set[4], sizeof(t_u32));
1278         cfg->param.vht_cfg.vht_tx_mcs =
1279             wlan_le32_to_cpu(cfg->param.vht_cfg.vht_tx_mcs);
1280         cfg->param.vht_cfg.vht_rx_max_rate =
1281 			wlan_convert_mcsmap_to_maxrate(pmpriv,cfg->param.vht_cfg.band,cfg->param.vht_cfg.vht_rx_mcs);
1282         cfg->param.vht_cfg.vht_tx_max_rate =
1283 			wlan_convert_mcsmap_to_maxrate(pmpriv, cfg->param.vht_cfg.band,cfg->param.vht_cfg.vht_tx_mcs);
1284     }
1285     LEAVE();
1286     return MLAN_STATUS_SUCCESS;
1287 }
1288 
1289 
1290 void wlan_update_11ac_cap(mlan_private * pmpriv){
1291 
1292     mlan_adapter* pmadapter = pmpriv->adapter;
1293 
1294     pmpriv->usr_dot_11ac_mcs_support = pmadapter->hw_dot_11ac_mcs_support;
1295     pmpriv->usr_dot_11ac_dev_cap_bg =
1296 		pmadapter->hw_dot_11ac_dev_cap & ~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
1297 #if CONFIG_5GHz_SUPPORT
1298     pmpriv->usr_dot_11ac_dev_cap_a =
1299 		pmadapter->hw_dot_11ac_dev_cap & ~DEFALUT_11AC_CAP_BEAMFORMING_RESET_MASK;
1300 #endif
1301     pmpriv->usr_dot_11ac_bw = BW_FOLLOW_VHTCAP;
1302 }
1303 #endif
1304 
1305 /**
1306  *  @brief This function check if 11AC is allowed in bandcfg
1307  *
1308  *  @param pmpriv       A pointer to mlan_private structure
1309  *  @param bss_band     bss band
1310  *
1311  *  @return 0--not allowed, other value allowed
1312  */
wlan_11ac_bandconfig_allowed(mlan_private * pmpriv,t_u16 bss_band)1313 t_u8 wlan_11ac_bandconfig_allowed(mlan_private *pmpriv, t_u16 bss_band)
1314 {
1315     if (pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
1316     {
1317         if ((bss_band & BAND_G) != 0U)
1318         {
1319             return (t_u8)(pmpriv->adapter->adhoc_start_band & BAND_GAC);
1320         }
1321 #if CONFIG_5GHz_SUPPORT
1322         else if ((bss_band & BAND_A) != 0U)
1323         {
1324             return (t_u8)(pmpriv->adapter->adhoc_start_band & BAND_AAC);
1325         }
1326         else
1327         { /* Do Nothing */
1328         }
1329 #endif
1330     }
1331     else
1332     {
1333         if ((bss_band & BAND_G) != 0U)
1334         {
1335             return (t_u8)(pmpriv->config_bands & BAND_GAC);
1336         }
1337 #if CONFIG_5GHz_SUPPORT
1338         else if ((bss_band & BAND_A) != 0U)
1339         {
1340             return (t_u8)(pmpriv->config_bands & BAND_AAC);
1341         }
1342         else
1343         { /* Do Nothing */
1344         }
1345 #endif
1346     }
1347     return 0;
1348 }
1349