• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2019 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define  _IOCTL_CFG80211_C_
16 
17 #include <drv_types.h>
18 #include <hal_data.h>
19 #include <linux/ktime.h>
20 #ifdef CONFIG_RTL8822CS_WIFI_HDF
21 #include "wifi_mac80211_ops.h"
22 #include "hdf_wifi_event.h"
23 
24 extern struct ieee80211_channel *GetChannelByFreq(const struct wiphy *wiphy, uint16_t center_freq);
25 extern void WifiScanFree(struct cfg80211_scan_request **request);
26 
WifiScanSetChannel(const struct wiphy * wiphy,const struct WlanScanRequest * params,struct cfg80211_scan_request * request)27 int32_t WifiScanSetChannel(const struct wiphy *wiphy, const struct WlanScanRequest *params, \
28     struct cfg80211_scan_request *request)
29 {
30     int32_t loop;
31     int32_t count = 0;
32     enum Ieee80211Band band = IEEE80211_BAND_2GHZ;
33     struct ieee80211_channel *chan = NULL;
34 
35     int32_t channelTotal = ieee80211_get_num_supported_channels((struct wiphy *)wiphy);
36 
37     if ((params->freqs == NULL) || (params->freqsCount == 0)) {
38         for (band = IEEE80211_BAND_2GHZ; band <= IEEE80211_BAND_5GHZ; band++) {
39             if (wiphy->bands[band] == NULL) {
40                 HDF_LOGE("%s: wiphy->bands[band] = NULL!\n", __func__);
41                 continue;
42             }
43 
44             for (loop = 0; loop < (int32_t)wiphy->bands[band]->n_channels; loop++) {
45                 if (count >= channelTotal) {
46                     break;
47                 }
48 
49                 chan = &wiphy->bands[band]->channels[loop];
50                 if ((chan->flags & WIFI_CHAN_DISABLED) != 0) {
51                     continue;
52                 }
53 
54                 request->channels[count++] = chan;
55             }
56         }
57     } else {
58         for (loop = 0; loop < params->freqsCount; loop++) {
59             chan = GetChannelByFreq(wiphy, (uint16_t)(params->freqs[loop]));
60             if (chan == NULL) {
61                 HDF_LOGE("%s: freq not found!freq=%d!\n", __func__, params->freqs[loop]);
62                 continue;
63             }
64 
65             if (count >= channelTotal) {
66                 break;
67             }
68 
69             request->channels[count++] = chan;
70         }
71     }
72 
73     if (count == 0) {
74         HDF_LOGE("%s: invalid freq info!\n", __func__);
75         return HDF_FAILURE;
76     }
77     request->n_channels = count;
78 
79     return HDF_SUCCESS;
80 }
81 #endif
82 
83 #ifdef CONFIG_IOCTL_CFG80211
84 
85 #ifndef DBG_RTW_CFG80211_STA_PARAM
86 #define DBG_RTW_CFG80211_STA_PARAM 0
87 #endif
88 
89 #ifndef DBG_RTW_CFG80211_MESH_CONF
90 #define DBG_RTW_CFG80211_MESH_CONF 0
91 #endif
92 
93 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
94 #define STATION_INFO_INACTIVE_TIME    BIT(NL80211_STA_INFO_INACTIVE_TIME)
95 #define STATION_INFO_RX_BYTES        BIT(NL80211_STA_INFO_RX_BYTES)
96 #define STATION_INFO_TX_BYTES        BIT(NL80211_STA_INFO_TX_BYTES)
97 #define STATION_INFO_LLID            BIT(NL80211_STA_INFO_LLID)
98 #define STATION_INFO_PLID            BIT(NL80211_STA_INFO_PLID)
99 #define STATION_INFO_PLINK_STATE    BIT(NL80211_STA_INFO_PLINK_STATE)
100 #define STATION_INFO_SIGNAL            BIT(NL80211_STA_INFO_SIGNAL)
101 #define STATION_INFO_TX_BITRATE        BIT(NL80211_STA_INFO_TX_BITRATE)
102 #define STATION_INFO_RX_PACKETS        BIT(NL80211_STA_INFO_RX_PACKETS)
103 #define STATION_INFO_TX_PACKETS        BIT(NL80211_STA_INFO_TX_PACKETS)
104 #define STATION_INFO_TX_RETRIES        BIT(NL80211_STA_INFO_TX_RETRIES)
105 #define STATION_INFO_TX_FAILED        BIT(NL80211_STA_INFO_TX_FAILED)
106 #define STATION_INFO_RX_BITRATE        BIT(NL80211_STA_INFO_RX_BITRATE)
107 #define STATION_INFO_LOCAL_PM        BIT(NL80211_STA_INFO_LOCAL_PM)
108 #define STATION_INFO_PEER_PM        BIT(NL80211_STA_INFO_PEER_PM)
109 #define STATION_INFO_NONPEER_PM        BIT(NL80211_STA_INFO_NONPEER_PM)
110 #define STATION_INFO_RX_BYTES64        BIT(NL80211_STA_INFO_RX_BYTES64)
111 #define STATION_INFO_TX_BYTES64        BIT(NL80211_STA_INFO_TX_BYTES64)
112 #define STATION_INFO_ASSOC_REQ_IES    0
113 #endif /* Linux kernel >= 4.0.0 */
114 
115 #define RTW_MAX_MGMT_TX_CNT (8)
116 #define RTW_MAX_MGMT_TX_MS_GAS (500)
117 
118 #define RTW_SCAN_IE_LEN_MAX      2304
119 #define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 5000 /* ms */
120 #define RTW_MAX_NUM_PMKIDS 4
121 
122 #define RTW_CH_MAX_2G_CHANNEL               14      /* Max channel in 2G band */
123 
124 #ifdef CONFIG_WAPI_SUPPORT
125 
126 #ifndef WLAN_CIPHER_SUITE_SMS4
127 #define WLAN_CIPHER_SUITE_SMS4          0x00147201
128 #endif
129 
130 #ifndef WLAN_AKM_SUITE_WAPI_PSK
131 #define WLAN_AKM_SUITE_WAPI_PSK         0x000FAC04
132 #endif
133 
134 #ifndef WLAN_AKM_SUITE_WAPI_CERT
135 #define WLAN_AKM_SUITE_WAPI_CERT        0x000FAC12
136 #endif
137 
138 #ifndef NL80211_WAPI_VERSION_1
139 #define NL80211_WAPI_VERSION_1          (1 << 2)
140 #endif
141 
142 #endif /* CONFIG_WAPI_SUPPORT */
143 
144 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 12))
145 #ifdef CONFIG_RTW_80211R
146 #define WLAN_AKM_SUITE_FT_8021X        0x000FAC03
147 #define WLAN_AKM_SUITE_FT_PSK        0x000FAC04
148 #define WLAN_AKM_SUITE_FT_OVER_SAE    0x000FAC09
149 #define WLAN_AKM_SUITE_FT_FILS_SHA256    0x000FAC16
150 #endif
151 #endif
152 
153 #define WIFI_CIPHER_SUITE_GCMP        0x000FAC08
154 #define WIFI_CIPHER_SUITE_GCMP_256    0x000FAC09
155 #define WIFI_CIPHER_SUITE_CCMP_256    0x000FAC0A
156 #define WIFI_CIPHER_SUITE_BIP_GMAC_128    0x000FAC0B
157 #define WIFI_CIPHER_SUITE_BIP_GMAC_256    0x000FAC0C
158 #define WIFI_CIPHER_SUITE_BIP_CMAC_256    0x000FAC0D
159 
160 /*
161  * If customer need, defining this flag will make driver
162  * always return -EBUSY at the condition of scan deny.
163  */
164 /* #define CONFIG_NOTIFY_SCAN_ABORT_WITH_BUSY */
165 
166 static const u32 rtw_cipher_suites[] = {
167     WLAN_CIPHER_SUITE_WEP40,
168     WLAN_CIPHER_SUITE_WEP104,
169     WLAN_CIPHER_SUITE_TKIP,
170     WLAN_CIPHER_SUITE_CCMP,
171 #ifdef CONFIG_WAPI_SUPPORT
172     WLAN_CIPHER_SUITE_SMS4,
173 #endif /* CONFIG_WAPI_SUPPORT */
174 #ifdef CONFIG_IEEE80211W
175     WLAN_CIPHER_SUITE_AES_CMAC,
176     WIFI_CIPHER_SUITE_GCMP,
177     WIFI_CIPHER_SUITE_GCMP_256,
178     WIFI_CIPHER_SUITE_CCMP_256,
179     WIFI_CIPHER_SUITE_BIP_GMAC_128,
180     WIFI_CIPHER_SUITE_BIP_GMAC_256,
181     WIFI_CIPHER_SUITE_BIP_CMAC_256,
182 #endif /* CONFIG_IEEE80211W */
183 };
184 
185 #define RATETAB_ENT(_rate, _rateid, _flags) \
186     {                                \
187         .bitrate    = (_rate),                \
188         .hw_value    = (_rateid),                \
189         .flags        = (_flags),                \
190     }
191 
192 #define CHAN2G(_channel, _freq, _flags) {            \
193         .band            = NL80211_BAND_2GHZ,        \
194         .center_freq        = (_freq),            \
195         .hw_value        = (_channel),            \
196         .flags            = (_flags),            \
197         .max_antenna_gain    = 0,                \
198         .max_power        = 0,                \
199     }
200 
201 #define CHAN5G(_channel, _flags) {                \
202         .band            = NL80211_BAND_5GHZ,        \
203         .center_freq        = 5000 + (5 * (_channel)),    \
204         .hw_value        = (_channel),            \
205         .flags            = (_flags),            \
206         .max_antenna_gain    = 0,                \
207         .max_power        = 0,                \
208     }
209 
210 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
211 /* if wowlan is not supported, kernel generate a disconnect at each suspend
212  * cf: /net/wireless/sysfs.c, so register a stub wowlan.
213  * Moreover wowlan has to be enabled via a the nl80211_set_wowlan callback.
214  * (from user space, e.g. iw phy0 wowlan enable)
215  */
216 static const struct wiphy_wowlan_support wowlan_stub = {
217     .flags = WIPHY_WOWLAN_ANY,
218     .n_patterns = 0,
219     .pattern_max_len = 0,
220     .pattern_min_len = 0,
221 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
222     .max_pkt_offset = 0,
223 #endif
224 };
225 #endif
226 
227 static struct ieee80211_rate rtw_rates[] = {
228     RATETAB_ENT(10,  0x1,   0),
229     RATETAB_ENT(20,  0x2,   0),
230     RATETAB_ENT(55,  0x4,   0),
231     RATETAB_ENT(110, 0x8,   0),
232     RATETAB_ENT(60,  0x10,  0),
233     RATETAB_ENT(90,  0x20,  0),
234     RATETAB_ENT(120, 0x40,  0),
235     RATETAB_ENT(180, 0x80,  0),
236     RATETAB_ENT(240, 0x100, 0),
237     RATETAB_ENT(360, 0x200, 0),
238     RATETAB_ENT(480, 0x400, 0),
239     RATETAB_ENT(540, 0x800, 0),
240 };
241 
242 #define rtw_a_rates        (rtw_rates + 4)
243 #define RTW_A_RATES_NUM    8
244 #define rtw_g_rates        (rtw_rates + 0)
245 #define RTW_G_RATES_NUM    12
246 
247 /* from center_ch_2g */
248 static struct ieee80211_channel rtw_2ghz_channels[MAX_CHANNEL_NUM_2G] = {
249     CHAN2G(1, 2412, 0),
250     CHAN2G(2, 2417, 0),
251     CHAN2G(3, 2422, 0),
252     CHAN2G(4, 2427, 0),
253     CHAN2G(5, 2432, 0),
254     CHAN2G(6, 2437, 0),
255     CHAN2G(7, 2442, 0),
256     CHAN2G(8, 2447, 0),
257     CHAN2G(9, 2452, 0),
258     CHAN2G(10, 2457, 0),
259     CHAN2G(11, 2462, 0),
260     CHAN2G(12, 2467, 0),
261     CHAN2G(13, 2472, 0),
262     CHAN2G(14, 2484, 0),
263 };
264 
265 /* from center_ch_5g_20m */
266 static struct ieee80211_channel rtw_5ghz_a_channels[MAX_CHANNEL_NUM_5G] = {
267     CHAN5G(36, 0),    CHAN5G(40, 0),    CHAN5G(44, 0),    CHAN5G(48, 0),
268 
269     CHAN5G(52, 0),    CHAN5G(56, 0),    CHAN5G(60, 0),    CHAN5G(64, 0),
270 
271     CHAN5G(100, 0),    CHAN5G(104, 0),    CHAN5G(108, 0),    CHAN5G(112, 0),
272     CHAN5G(116, 0),    CHAN5G(120, 0),    CHAN5G(124, 0),    CHAN5G(128, 0),
273     CHAN5G(132, 0),    CHAN5G(136, 0),    CHAN5G(140, 0),    CHAN5G(144, 0),
274 
275     CHAN5G(149, 0),    CHAN5G(153, 0),    CHAN5G(157, 0),    CHAN5G(161, 0),
276     CHAN5G(165, 0),    CHAN5G(169, 0),    CHAN5G(173, 0),    CHAN5G(177, 0),
277 };
278 
279 enum nl80211_band _rtw_band_to_nl80211_band[] = {
280     [BAND_ON_2_4G] =    NL80211_BAND_2GHZ,
281     [BAND_ON_5G] =        NL80211_BAND_5GHZ,
282 #if CONFIG_IEEE80211_BAND_6GHZ
283     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
284     [BAND_ON_6G] =        NL80211_BAND_6GHZ,
285     #else
286     [BAND_ON_6G] =        NUM_NL80211_BANDS,
287     #endif
288 #endif
289 };
290 
291 BAND_TYPE _nl80211_band_to_rtw_band[] = {
292     [NL80211_BAND_2GHZ] =    BAND_ON_2_4G,
293     [NL80211_BAND_5GHZ] =    BAND_ON_5G,
294 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
295     [NL80211_BAND_60GHZ] = BAND_MAX,
296 #endif
297 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
298     #if CONFIG_IEEE80211_BAND_6GHZ
299     [NL80211_BAND_6GHZ] =    BAND_ON_6G,
300     #else
301     [NL80211_BAND_6GHZ] =    BAND_MAX,
302     #endif
303 #endif
304 };
305 
306 
307 static int rtw_cfg80211_set_assocresp_ies(struct net_device *net, const u8 *buf, int len);
308 
309 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
rtw_chbw_to_cfg80211_chan_def(struct wiphy * wiphy,struct cfg80211_chan_def * chdef,u8 ch,u8 bw,u8 offset,u8 ht)310 static u8 rtw_chbw_to_cfg80211_chan_def(struct wiphy *wiphy, struct cfg80211_chan_def *chdef, u8 ch, u8 bw, u8 offset, u8 ht)
311 {
312     int freq, cfreq;
313     struct ieee80211_channel *chan;
314     u8 ret = _FAIL;
315 
316     _rtw_memset(chdef, 0, sizeof(*chdef));
317 
318     freq = rtw_ch2freq(ch);
319     if (!freq)
320         goto exit;
321 
322     cfreq = rtw_get_center_ch(ch, bw, offset);
323     if (!cfreq)
324         goto exit;
325     cfreq = rtw_ch2freq(cfreq);
326     if (!cfreq)
327         goto exit;
328 
329     chan = ieee80211_get_channel(wiphy, freq);
330     if (!chan)
331         goto exit;
332 
333     if (bw == CHANNEL_WIDTH_20)
334         chdef->width = ht ? NL80211_CHAN_WIDTH_20 : NL80211_CHAN_WIDTH_20_NOHT;
335     else if (bw == CHANNEL_WIDTH_40)
336         chdef->width = NL80211_CHAN_WIDTH_40;
337     else if (bw == CHANNEL_WIDTH_80)
338         chdef->width = NL80211_CHAN_WIDTH_80;
339     else if (bw == CHANNEL_WIDTH_160)
340         chdef->width = NL80211_CHAN_WIDTH_160;
341 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
342     else if (bw == CHANNEL_WIDTH_5)
343         chdef->width = NL80211_CHAN_WIDTH_5;
344     else if (bw == CHANNEL_WIDTH_10)
345         chdef->width = NL80211_CHAN_WIDTH_10;
346 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) */
347     else {
348         rtw_warn_on(1);
349         goto exit;
350     }
351 
352     chdef->chan = chan;
353     chdef->center_freq1 = cfreq;
354 
355     ret = _SUCCESS;
356 
357 exit:
358     return ret;
359 }
360 
nl80211_chan_width_str(enum nl80211_chan_width cwidth)361 static const char *nl80211_chan_width_str(enum nl80211_chan_width cwidth)
362 {
363     switch (cwidth) {
364     case NL80211_CHAN_WIDTH_20_NOHT:
365         return "20_NOHT";
366     case NL80211_CHAN_WIDTH_20:
367         return "20";
368     case NL80211_CHAN_WIDTH_40:
369         return "40";
370     case NL80211_CHAN_WIDTH_80:
371         return "80";
372     case NL80211_CHAN_WIDTH_80P80:
373         return "80+80";
374     case NL80211_CHAN_WIDTH_160:
375         return "160";
376 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
377     case NL80211_CHAN_WIDTH_5:
378         return "5";
379     case NL80211_CHAN_WIDTH_10:
380         return "10";
381 #endif
382     default:
383         return "INVALID";
384     };
385 }
386 
rtw_get_chbw_from_cfg80211_chan_def(struct cfg80211_chan_def * chdef,u8 * ht,u8 * ch,u8 * bw,u8 * offset)387 static void rtw_get_chbw_from_cfg80211_chan_def(struct cfg80211_chan_def *chdef, u8 *ht, u8 *ch, u8 *bw, u8 *offset)
388 {
389     int pri_freq;
390     struct ieee80211_channel *chan = chdef->chan;
391 
392     pri_freq = rtw_ch2freq(chan->hw_value);
393     if (!pri_freq) {
394         RTW_INFO("invalid channel:%d\n", chan->hw_value);
395         rtw_warn_on(1);
396         *ch = 0;
397         return;
398     }
399 
400     switch (chdef->width) {
401     case NL80211_CHAN_WIDTH_20_NOHT:
402         *ht = 0;
403         *bw = CHANNEL_WIDTH_20;
404         *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
405         *ch = chan->hw_value;
406         break;
407     case NL80211_CHAN_WIDTH_20:
408         *ht = 1;
409         *bw = CHANNEL_WIDTH_20;
410         *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
411         *ch = chan->hw_value;
412         break;
413     case NL80211_CHAN_WIDTH_40:
414         *ht = 1;
415         *bw = CHANNEL_WIDTH_40;
416         *offset = pri_freq > chdef->center_freq1 ? HAL_PRIME_CHNL_OFFSET_UPPER : HAL_PRIME_CHNL_OFFSET_LOWER;
417         if (rtw_get_offset_by_chbw(chan->hw_value, *bw, offset))
418             *ch = chan->hw_value;
419         break;
420     case NL80211_CHAN_WIDTH_80:
421         *ht = 1;
422         *bw = CHANNEL_WIDTH_80;
423         if (rtw_get_offset_by_chbw(chan->hw_value, *bw, offset))
424             *ch = chan->hw_value;
425         break;
426     case NL80211_CHAN_WIDTH_160:
427         *ht = 1;
428         *bw = CHANNEL_WIDTH_160;
429         if (rtw_get_offset_by_chbw(chan->hw_value, *bw, offset))
430             *ch = chan->hw_value;
431         break;
432     case NL80211_CHAN_WIDTH_80P80:
433     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
434     case NL80211_CHAN_WIDTH_5:
435     case NL80211_CHAN_WIDTH_10:
436     #endif
437     default:
438         *ht = 0;
439         *bw = CHANNEL_WIDTH_20;
440         *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
441         RTW_INFO("unsupported cwidth:%s\n", nl80211_chan_width_str(chdef->width));
442         rtw_warn_on(1);
443     };
444 }
445 
446 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
nl80211_channel_type_str(enum nl80211_channel_type ctype)447 static const char *nl80211_channel_type_str(enum nl80211_channel_type ctype)
448 {
449     switch (ctype) {
450     case NL80211_CHAN_NO_HT:
451         return "NO_HT";
452     case NL80211_CHAN_HT20:
453         return "HT20";
454     case NL80211_CHAN_HT40MINUS:
455         return "HT40-";
456     case NL80211_CHAN_HT40PLUS:
457         return "HT40+";
458     default:
459         return "INVALID";
460     };
461 }
462 
rtw_chbw_to_nl80211_channel_type(u8 ch,u8 bw,u8 offset,u8 ht)463 static enum nl80211_channel_type rtw_chbw_to_nl80211_channel_type(u8 ch, u8 bw, u8 offset, u8 ht)
464 {
465     rtw_warn_on(!ht && (bw >= CHANNEL_WIDTH_40 || offset != HAL_PRIME_CHNL_OFFSET_DONT_CARE));
466 
467     if (!ht)
468         return NL80211_CHAN_NO_HT;
469     if (bw >= CHANNEL_WIDTH_40) {
470         if (offset == HAL_PRIME_CHNL_OFFSET_UPPER)
471             return NL80211_CHAN_HT40MINUS;
472         else if (offset == HAL_PRIME_CHNL_OFFSET_LOWER)
473             return NL80211_CHAN_HT40PLUS;
474         else
475             rtw_warn_on(1);
476     }
477     return NL80211_CHAN_HT20;
478 }
479 
rtw_get_chbw_from_nl80211_channel_type(struct ieee80211_channel * chan,enum nl80211_channel_type ctype,u8 * ht,u8 * ch,u8 * bw,u8 * offset)480 static void rtw_get_chbw_from_nl80211_channel_type(struct ieee80211_channel *chan, enum nl80211_channel_type ctype, u8 *ht, u8 *ch, u8 *bw, u8 *offset)
481 {
482     int pri_freq;
483 
484     pri_freq = rtw_ch2freq(chan->hw_value);
485     if (!pri_freq) {
486         RTW_INFO("invalid channel:%d\n", chan->hw_value);
487         rtw_warn_on(1);
488         *ch = 0;
489         return;
490     }
491     *ch = chan->hw_value;
492 
493     switch (ctype) {
494     case NL80211_CHAN_NO_HT:
495         *ht = 0;
496         *bw = CHANNEL_WIDTH_20;
497         *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
498         break;
499     case NL80211_CHAN_HT20:
500         *ht = 1;
501         *bw = CHANNEL_WIDTH_20;
502         *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
503         break;
504     case NL80211_CHAN_HT40MINUS:
505         *ht = 1;
506         *bw = CHANNEL_WIDTH_40;
507         *offset = HAL_PRIME_CHNL_OFFSET_UPPER;
508         break;
509     case NL80211_CHAN_HT40PLUS:
510         *ht = 1;
511         *bw = CHANNEL_WIDTH_40;
512         *offset = HAL_PRIME_CHNL_OFFSET_LOWER;
513         break;
514     default:
515         *ht = 0;
516         *bw = CHANNEL_WIDTH_20;
517         *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
518         RTW_INFO("unsupported ctype:%s\n", nl80211_channel_type_str(ctype));
519         rtw_warn_on(1);
520     };
521 }
522 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) */
523 
524 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
rtw_cfg80211_allow_ch_switch_notify(_adapter * adapter)525 bool rtw_cfg80211_allow_ch_switch_notify(_adapter *adapter)
526 {
527 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
528     if ((!MLME_IS_AP(adapter))
529 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
530         && (!MLME_IS_ADHOC(adapter))
531         && (!MLME_IS_ADHOC_MASTER(adapter))
532         && (!MLME_IS_MESH(adapter))
533 #elif defined(CONFIG_RTW_MESH)
534         && (!MLME_IS_MESH(adapter))
535 #endif
536         )
537         return 0;
538 #endif
539     return 1;
540 }
541 
rtw_cfg80211_ch_switch_notify(_adapter * adapter,u8 ch,u8 bw,u8 offset,u8 ht,bool started)542 u8 rtw_cfg80211_ch_switch_notify(_adapter *adapter, u8 ch, u8 bw, u8 offset,
543     u8 ht, bool started)
544 {
545     struct wiphy *wiphy = adapter_to_wiphy(adapter);
546     u8 ret = _SUCCESS;
547 
548 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
549     struct cfg80211_chan_def chdef = {};
550 
551     ret = rtw_chbw_to_cfg80211_chan_def(wiphy, &chdef, ch, bw, offset, ht);
552     if (ret != _SUCCESS)
553         goto exit;
554 
555 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
556     if (started) {
557 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0))
558 
559         /* --- cfg80211_ch_switch_started_notfiy() ---
560          *  A new parameter, bool quiet, is added from Linux kernel v5.11,
561          *  to see if block-tx was requested by the AP. since currently,
562          *  the API is used for station before connected in rtw_chk_start_clnt_join()
563          *  the quiet is set to false here first. May need to refine it if
564          *  called by others with block-tx.
565          */
566 
567         cfg80211_ch_switch_started_notify(adapter->pnetdev, &chdef, 0, false);
568 #else
569         cfg80211_ch_switch_started_notify(adapter->pnetdev, &chdef, 0);
570 #endif
571         goto exit;
572     }
573 #endif
574 
575     if (!rtw_cfg80211_allow_ch_switch_notify(adapter))
576         goto exit;
577 
578     cfg80211_ch_switch_notify(adapter->pnetdev, &chdef);
579 
580 #else
581     int freq = rtw_ch2freq(ch);
582     enum nl80211_channel_type ctype;
583 
584     if (!rtw_cfg80211_allow_ch_switch_notify(adapter))
585         goto exit;
586 
587     if (!freq) {
588         ret = _FAIL;
589         goto exit;
590     }
591 
592     ctype = rtw_chbw_to_nl80211_channel_type(ch, bw, offset, ht);
593     cfg80211_ch_switch_notify(adapter->pnetdev, freq, ctype);
594 #endif
595 
596 exit:
597     return ret;
598 }
599 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
600 
rtw_2g_channels_init(struct ieee80211_channel * channels)601 void rtw_2g_channels_init(struct ieee80211_channel *channels)
602 {
603     _rtw_memcpy((void *)channels, (void *)rtw_2ghz_channels, sizeof(rtw_2ghz_channels));
604 }
605 
rtw_5g_channels_init(struct ieee80211_channel * channels)606 void rtw_5g_channels_init(struct ieee80211_channel *channels)
607 {
608     _rtw_memcpy((void *)channels, (void *)rtw_5ghz_a_channels, sizeof(rtw_5ghz_a_channels));
609 }
610 
rtw_2g_rates_init(struct ieee80211_rate * rates)611 void rtw_2g_rates_init(struct ieee80211_rate *rates)
612 {
613     _rtw_memcpy(rates, rtw_g_rates,
614         sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM
615     );
616 }
617 
rtw_5g_rates_init(struct ieee80211_rate * rates)618 void rtw_5g_rates_init(struct ieee80211_rate *rates)
619 {
620     _rtw_memcpy(rates, rtw_a_rates,
621         sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM
622     );
623 }
624 
rtw_spt_band_alloc(BAND_TYPE band)625 struct ieee80211_supported_band *rtw_spt_band_alloc(BAND_TYPE band)
626 {
627     struct ieee80211_supported_band *spt_band = NULL;
628     int n_channels, n_bitrates;
629 
630     if (rtw_band_to_nl80211_band(band) == NUM_NL80211_BANDS)
631         goto exit;
632 
633     if (band == BAND_ON_2_4G) {
634         n_channels = MAX_CHANNEL_NUM_2G;
635         n_bitrates = RTW_G_RATES_NUM;
636     } else if (band == BAND_ON_5G) {
637         n_channels = MAX_CHANNEL_NUM_5G;
638         n_bitrates = RTW_A_RATES_NUM;
639     } else
640         goto exit;
641 
642     spt_band = (struct ieee80211_supported_band *)rtw_zmalloc(
643         sizeof(struct ieee80211_supported_band)
644         + sizeof(struct ieee80211_channel) * n_channels
645         + sizeof(struct ieee80211_rate) * n_bitrates
646     );
647     if (!spt_band)
648         goto exit;
649 
650     spt_band->channels = (struct ieee80211_channel *)(((u8 *)spt_band) + sizeof(struct ieee80211_supported_band));
651     spt_band->bitrates = (struct ieee80211_rate *)(((u8 *)spt_band->channels) + sizeof(struct ieee80211_channel) * n_channels);
652     spt_band->band = rtw_band_to_nl80211_band(band);
653     spt_band->n_channels = n_channels;
654     spt_band->n_bitrates = n_bitrates;
655 
656 exit:
657     return spt_band;
658 }
659 
rtw_spt_band_free(struct ieee80211_supported_band * spt_band)660 void rtw_spt_band_free(struct ieee80211_supported_band *spt_band)
661 {
662     u32 size = 0;
663 
664     if (!spt_band)
665         return;
666 
667     if (spt_band->band == NL80211_BAND_2GHZ) {
668         size = sizeof(struct ieee80211_supported_band)
669             + sizeof(struct ieee80211_channel) * MAX_CHANNEL_NUM_2G
670             + sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM;
671     } else if (spt_band->band == NL80211_BAND_5GHZ) {
672         size = sizeof(struct ieee80211_supported_band)
673             + sizeof(struct ieee80211_channel) * MAX_CHANNEL_NUM_5G
674             + sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM;
675     } else {
676 
677     }
678     rtw_mfree((u8 *)spt_band, size);
679 }
680 
681 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
682 static const struct ieee80211_txrx_stypes
683     rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
684     [NL80211_IFTYPE_ADHOC] = {
685         .tx = 0xffff,
686         .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
687     },
688     [NL80211_IFTYPE_STATION] = {
689         .tx = 0xffff,
690         .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
691         BIT(IEEE80211_STYPE_AUTH >> 4) |
692         BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
693     },
694     [NL80211_IFTYPE_AP] = {
695         .tx = 0xffff,
696         .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
697         BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
698         BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
699         BIT(IEEE80211_STYPE_DISASSOC >> 4) |
700         BIT(IEEE80211_STYPE_AUTH >> 4) |
701         BIT(IEEE80211_STYPE_DEAUTH >> 4) |
702         BIT(IEEE80211_STYPE_ACTION >> 4)
703     },
704     [NL80211_IFTYPE_AP_VLAN] = {
705         /* copy AP */
706         .tx = 0xffff,
707         .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
708         BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
709         BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
710         BIT(IEEE80211_STYPE_DISASSOC >> 4) |
711         BIT(IEEE80211_STYPE_AUTH >> 4) |
712         BIT(IEEE80211_STYPE_DEAUTH >> 4) |
713         BIT(IEEE80211_STYPE_ACTION >> 4)
714     },
715     [NL80211_IFTYPE_P2P_CLIENT] = {
716         .tx = 0xffff,
717         .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
718         BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
719     },
720     [NL80211_IFTYPE_P2P_GO] = {
721         .tx = 0xffff,
722         .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
723         BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
724         BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
725         BIT(IEEE80211_STYPE_DISASSOC >> 4) |
726         BIT(IEEE80211_STYPE_AUTH >> 4) |
727         BIT(IEEE80211_STYPE_DEAUTH >> 4) |
728         BIT(IEEE80211_STYPE_ACTION >> 4)
729     },
730 #if defined(RTW_DEDICATED_P2P_DEVICE)
731     [NL80211_IFTYPE_P2P_DEVICE] = {
732         .tx = 0xffff,
733         .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
734             BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
735     },
736 #endif
737 #if defined(CONFIG_RTW_MESH)
738     [NL80211_IFTYPE_MESH_POINT] = {
739         .tx = 0xffff,
740         .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
741             | BIT(IEEE80211_STYPE_AUTH >> 4)
742     },
743 #endif
744 
745 };
746 #endif
747 
nl80211_iftype_to_rtw_network_type(enum nl80211_iftype type)748 NDIS_802_11_NETWORK_INFRASTRUCTURE nl80211_iftype_to_rtw_network_type(enum nl80211_iftype type)
749 {
750     switch (type) {
751     case NL80211_IFTYPE_ADHOC:
752         return Ndis802_11IBSS;
753 
754     #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
755     case NL80211_IFTYPE_P2P_CLIENT:
756     #endif
757     case NL80211_IFTYPE_STATION:
758         return Ndis802_11Infrastructure;
759 
760 #ifdef CONFIG_AP_MODE
761     #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
762     case NL80211_IFTYPE_P2P_GO:
763     #endif
764     case NL80211_IFTYPE_AP:
765         return Ndis802_11APMode;
766 #endif
767 
768 #ifdef CONFIG_RTW_MESH
769     case NL80211_IFTYPE_MESH_POINT:
770         return Ndis802_11_mesh;
771 #endif
772 
773 #ifdef CONFIG_WIFI_MONITOR
774     case NL80211_IFTYPE_MONITOR:
775         return Ndis802_11Monitor;
776 #endif /* CONFIG_WIFI_MONITOR */
777 
778     default:
779         return Ndis802_11InfrastructureMax;
780     }
781 }
782 
nl80211_iftype_to_rtw_mlme_state(enum nl80211_iftype type)783 u32 nl80211_iftype_to_rtw_mlme_state(enum nl80211_iftype type)
784 {
785     switch (type) {
786     case NL80211_IFTYPE_ADHOC:
787         return WIFI_ADHOC_STATE;
788 
789     #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
790     case NL80211_IFTYPE_P2P_CLIENT:
791     #endif
792     case NL80211_IFTYPE_STATION:
793         return WIFI_STATION_STATE;
794 
795 #ifdef CONFIG_AP_MODE
796     #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
797     case NL80211_IFTYPE_P2P_GO:
798     #endif
799     case NL80211_IFTYPE_AP:
800         return WIFI_AP_STATE;
801 #endif
802 
803 #ifdef CONFIG_RTW_MESH
804     case NL80211_IFTYPE_MESH_POINT:
805         return WIFI_MESH_STATE;
806 #endif
807 
808     case NL80211_IFTYPE_MONITOR:
809         return WIFI_MONITOR_STATE;
810 
811     default:
812         return WIFI_NULL_STATE;
813     }
814 }
815 
rtw_cfg80211_sync_iftype(_adapter * adapter)816 static int rtw_cfg80211_sync_iftype(_adapter *adapter)
817 {
818     struct wireless_dev *rtw_wdev = adapter->rtw_wdev;
819 
820     if (!(nl80211_iftype_to_rtw_mlme_state(rtw_wdev->iftype) & MLME_STATE(adapter))) {
821         /* iftype and mlme state is not syc */
822         NDIS_802_11_NETWORK_INFRASTRUCTURE network_type;
823 
824         network_type = nl80211_iftype_to_rtw_network_type(rtw_wdev->iftype);
825         if (network_type != Ndis802_11InfrastructureMax) {
826             if (rtw_pwr_wakeup(adapter) == _FAIL) {
827                 RTW_WARN(FUNC_ADPT_FMT" call rtw_pwr_wakeup fail\n", FUNC_ADPT_ARG(adapter));
828                 return _FAIL;
829             }
830 
831             rtw_set_802_11_infrastructure_mode(adapter, network_type, 0);
832             rtw_setopmode_cmd(adapter, network_type, RTW_CMDF_WAIT_ACK);
833         } else {
834             rtw_warn_on(1);
835             RTW_WARN(FUNC_ADPT_FMT" iftype:%u is not support\n", FUNC_ADPT_ARG(adapter), rtw_wdev->iftype);
836             return _FAIL;
837         }
838     }
839 
840     return _SUCCESS;
841 }
842 
rtw_get_systime_us(void)843 static u64 rtw_get_systime_us(void)
844 {
845 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0))
846     return ktime_to_us(ktime_get_boottime());
847 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
848     struct timespec ts;
849     get_monotonic_boottime(&ts);
850     return ((u64)ts.tv_sec * 1000000) + ts.tv_nsec / 1000;
851 #else
852     struct timeval tv;
853     do_gettimeofday(&tv);
854     return ((u64)tv.tv_sec * 1000000) + tv.tv_usec;
855 #endif
856 }
857 
858 /* Try to remove non target BSS's SR to reduce PBC overlap rate */
rtw_cfg80211_clear_wps_sr_of_non_target_bss(_adapter * padapter,struct wlan_network * pnetwork,struct cfg80211_ssid * req_ssid)859 static int rtw_cfg80211_clear_wps_sr_of_non_target_bss(_adapter *padapter, struct wlan_network *pnetwork, struct cfg80211_ssid *req_ssid)
860 {
861     int ret = 0;
862     u8 *psr = NULL, sr = 0;
863     NDIS_802_11_SSID *pssid = &pnetwork->network.Ssid;
864     u32 wpsielen = 0;
865     u8 *wpsie = NULL;
866 
867     if (pssid->SsidLength == req_ssid->ssid_len
868         && _rtw_memcmp(pssid->Ssid, req_ssid->ssid, req_ssid->ssid_len) == _TRUE)
869         goto exit;
870 
871     wpsie = rtw_get_wps_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_
872         , pnetwork->network.IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen);
873     if (wpsie && wpsielen > 0)
874         psr = rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_SELECTED_REGISTRAR, &sr, NULL);
875 
876     if (psr && sr) {
877         if (0)
878             RTW_INFO("clear sr of non target bss:%s("MAC_FMT")\n"
879                 , pssid->Ssid, MAC_ARG(pnetwork->network.MacAddress));
880         *psr = 0; /* clear sr */
881         ret = 1;
882     }
883 
884 exit:
885     return ret;
886 }
887 
888 #define MAX_BSSINFO_LEN 1000
rtw_cfg80211_inform_bss(_adapter * padapter,struct wlan_network * pnetwork)889 struct cfg80211_bss *rtw_cfg80211_inform_bss(_adapter *padapter, struct wlan_network *pnetwork)
890 {
891     struct ieee80211_channel *notify_channel;
892     struct cfg80211_bss *bss = NULL;
893     /* struct ieee80211_supported_band *band;       */
894     u16 channel;
895     u32 freq;
896     u64 notify_timestamp;
897     u16 notify_capability;
898     u16 notify_interval;
899     u8 *notify_ie;
900     size_t notify_ielen;
901     s32 notify_signal;
902     /* u8 buf[MAX_BSSINFO_LEN]; */
903 
904     u8 *pbuf;
905     size_t buf_size = MAX_BSSINFO_LEN;
906     size_t len, bssinf_len = 0;
907     struct rtw_ieee80211_hdr *pwlanhdr;
908     unsigned short *fctrl;
909     u8    bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
910 
911     struct wireless_dev *wdev = padapter->rtw_wdev;
912     struct wiphy *wiphy = wdev->wiphy;
913     struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
914 
915     pbuf = rtw_zmalloc(buf_size);
916     if (pbuf == NULL) {
917         RTW_INFO("%s pbuf allocate failed  !!\n", __FUNCTION__);
918         return bss;
919     }
920 
921     /* RTW_INFO("%s\n", __func__); */
922 
923     bssinf_len = pnetwork->network.IELength + sizeof(struct rtw_ieee80211_hdr_3addr);
924     if (bssinf_len > buf_size) {
925         RTW_INFO("%s IE Length too long > %zu byte\n", __FUNCTION__, buf_size);
926         goto exit;
927     }
928 
929 #ifndef CONFIG_WAPI_SUPPORT
930     {
931         u16 wapi_len = 0;
932 
933         if (rtw_get_wapi_ie(pnetwork->network.IEs, pnetwork->network.IELength, NULL, &wapi_len) > 0) {
934             if (wapi_len > 0) {
935                 RTW_INFO("%s, no support wapi!\n", __FUNCTION__);
936                 goto exit;
937             }
938         }
939     }
940 #endif /* !CONFIG_WAPI_SUPPORT */
941 
942     channel = pnetwork->network.Configuration.DSConfig;
943     freq = rtw_ch2freq(channel);
944     notify_channel = ieee80211_get_channel(wiphy, freq);
945 
946     if (0)
947         notify_timestamp = le64_to_cpu(*(u64 *)rtw_get_timestampe_from_ie(pnetwork->network.IEs));
948     else
949         notify_timestamp = rtw_get_systime_us();
950 
951     notify_interval = le16_to_cpu(*(u16 *)rtw_get_beacon_interval_from_ie(pnetwork->network.IEs));
952     notify_capability = le16_to_cpu(*(u16 *)rtw_get_capability_from_ie(pnetwork->network.IEs));
953 
954     notify_ie = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
955     notify_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
956 
957     /* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM: signal strength in mBm (100*dBm) */
958     if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE &&
959         is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
960         notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength); /* dbm */
961     } else {
962         notify_signal = 100 * translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength); /* dbm */
963     }
964 
965 #if 0
966     RTW_INFO("bssid: "MAC_FMT"\n", MAC_ARG(pnetwork->network.MacAddress));
967     RTW_INFO("Channel: %d(%d)\n", channel, freq);
968     RTW_INFO("Capability: %X\n", notify_capability);
969     RTW_INFO("Beacon interval: %d\n", notify_interval);
970     RTW_INFO("Signal: %d\n", notify_signal);
971     RTW_INFO("notify_timestamp: %llu\n", notify_timestamp);
972 #endif
973 
974     /* pbuf = buf; */
975 
976     pwlanhdr = (struct rtw_ieee80211_hdr *)pbuf;
977     fctrl = &(pwlanhdr->frame_ctl);
978     *(fctrl) = 0;
979 
980     SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
981     /* pmlmeext->mgnt_seq++; */
982 
983     if (pnetwork->network.Reserved[0] == BSS_TYPE_BCN) { /* WIFI_BEACON */
984         _rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
985         set_frame_sub_type(pbuf, WIFI_BEACON);
986     } else {
987         _rtw_memcpy(pwlanhdr->addr1, adapter_mac_addr(padapter), ETH_ALEN);
988         set_frame_sub_type(pbuf, WIFI_PROBERSP);
989     }
990 
991     _rtw_memcpy(pwlanhdr->addr2, pnetwork->network.MacAddress, ETH_ALEN);
992     _rtw_memcpy(pwlanhdr->addr3, pnetwork->network.MacAddress, ETH_ALEN);
993 
994 
995     /* pbuf += sizeof(struct rtw_ieee80211_hdr_3addr); */
996     len = sizeof(struct rtw_ieee80211_hdr_3addr);
997     _rtw_memcpy((pbuf + len), pnetwork->network.IEs, pnetwork->network.IELength);
998     *((u64 *)(pbuf + len)) = cpu_to_le64(notify_timestamp);
999 
1000     len += pnetwork->network.IELength;
1001 
1002     #if defined(CONFIG_P2P) && 0
1003     if(rtw_get_p2p_ie(pnetwork->network.IEs+12, pnetwork->network.IELength-12, NULL, NULL))
1004         RTW_INFO("%s, got p2p_ie\n", __func__);
1005     #endif
1006 
1007     bss = cfg80211_inform_bss_frame(wiphy, notify_channel, (struct ieee80211_mgmt *)pbuf,
1008                     len, notify_signal, GFP_ATOMIC);
1009 
1010     if (unlikely(!bss)) {
1011         RTW_INFO(FUNC_ADPT_FMT" bss NULL\n", FUNC_ADPT_ARG(padapter));
1012         goto exit;
1013     }
1014 
1015 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38))
1016 #ifndef COMPAT_KERNEL_RELEASE
1017     /* patch for cfg80211, update beacon ies to information_elements */
1018     if (pnetwork->network.Reserved[0] == BSS_TYPE_BCN) { /* WIFI_BEACON */
1019 
1020         if (bss->len_information_elements != bss->len_beacon_ies) {
1021             bss->information_elements = bss->beacon_ies;
1022             bss->len_information_elements =  bss->len_beacon_ies;
1023         }
1024     }
1025 #endif /* COMPAT_KERNEL_RELEASE */
1026 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38) */
1027 
1028 #if 0
1029     {
1030         if (bss->information_elements == bss->proberesp_ies) {
1031             if (bss->len_information_elements !=  bss->len_proberesp_ies)
1032                 RTW_INFO("error!, len_information_elements != bss->len_proberesp_ies\n");
1033         } else if (bss->len_information_elements <  bss->len_beacon_ies) {
1034             bss->information_elements = bss->beacon_ies;
1035             bss->len_information_elements =  bss->len_beacon_ies;
1036         }
1037     }
1038 #endif
1039 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
1040     cfg80211_put_bss(wiphy, bss);
1041 #else
1042     cfg80211_put_bss(bss);
1043 #endif
1044 
1045 exit:
1046     if (pbuf)
1047         rtw_mfree(pbuf, buf_size);
1048     return bss;
1049 
1050 }
1051 
1052 /*
1053     Check the given bss is valid by kernel API cfg80211_get_bss()
1054     @padapter : the given adapter
1055 
1056     return _TRUE if bss is valid,  _FALSE for not found.
1057 */
rtw_cfg80211_check_bss(_adapter * padapter)1058 int rtw_cfg80211_check_bss(_adapter *padapter)
1059 {
1060     WLAN_BSSID_EX  *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);
1061     struct cfg80211_bss *bss = NULL;
1062     struct ieee80211_channel *notify_channel = NULL;
1063     u32 freq;
1064 
1065     if (!(pnetwork) || !(padapter->rtw_wdev))
1066         return _FALSE;
1067 
1068     freq = rtw_ch2freq(pnetwork->Configuration.DSConfig);
1069     notify_channel = ieee80211_get_channel(padapter->rtw_wdev->wiphy, freq);
1070     bss = cfg80211_get_bss(padapter->rtw_wdev->wiphy, notify_channel,
1071             pnetwork->MacAddress, pnetwork->Ssid.Ssid,
1072             pnetwork->Ssid.SsidLength,
1073 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1074             pnetwork->InfrastructureMode == Ndis802_11Infrastructure?IEEE80211_BSS_TYPE_ESS:IEEE80211_BSS_TYPE_IBSS,
1075             IEEE80211_PRIVACY(pnetwork->Privacy));
1076 #else
1077             pnetwork->InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS, pnetwork->InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS);
1078 #endif
1079 
1080 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
1081     cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss);
1082 #else
1083     cfg80211_put_bss(bss);
1084 #endif
1085 
1086     return bss != NULL;
1087 }
1088 
rtw_cfg80211_ibss_indicate_connect(_adapter * padapter)1089 void rtw_cfg80211_ibss_indicate_connect(_adapter *padapter)
1090 {
1091     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1092     struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
1093     struct wireless_dev *pwdev = padapter->rtw_wdev;
1094 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
1095     struct wiphy *wiphy = pwdev->wiphy;
1096     int freq = 2412;
1097     struct ieee80211_channel *notify_channel;
1098 #endif
1099 
1100     RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
1101 
1102     if (pwdev->iftype != NL80211_IFTYPE_ADHOC)
1103         return;
1104 
1105     if (!rtw_cfg80211_check_bss(padapter)) {
1106         WLAN_BSSID_EX  *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);
1107         struct wlan_network *scanned = pmlmepriv->cur_network_scanned;
1108 
1109         if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) {
1110 
1111             _rtw_memcpy(&cur_network->network, pnetwork, sizeof(WLAN_BSSID_EX));
1112             if (cur_network) {
1113                 if (!rtw_cfg80211_inform_bss(padapter, cur_network))
1114                     RTW_INFO(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));
1115                 else
1116                     RTW_INFO(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter));
1117             } else {
1118                 RTW_INFO("cur_network is not exist!!!\n");
1119                 return ;
1120             }
1121         } else {
1122             if (scanned == NULL)
1123                 rtw_warn_on(1);
1124 
1125             if (_rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE
1126                 && _rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE
1127             ) {
1128                 if (!rtw_cfg80211_inform_bss(padapter, scanned))
1129                     RTW_INFO(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));
1130                 else {
1131                     /* RTW_INFO(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter)); */
1132                 }
1133             } else {
1134                 RTW_INFO("scanned & pnetwork compare fail\n");
1135                 rtw_warn_on(1);
1136             }
1137         }
1138 
1139         if (!rtw_cfg80211_check_bss(padapter))
1140             RTW_PRINT(FUNC_ADPT_FMT" BSS not found !!\n", FUNC_ADPT_ARG(padapter));
1141     }
1142     /* notify cfg80211 that device joined an IBSS */
1143 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
1144     freq = rtw_ch2freq(cur_network->network.Configuration.DSConfig);
1145     if (1)
1146         RTW_INFO("chan: %d, freq: %d\n", cur_network->network.Configuration.DSConfig, freq);
1147     notify_channel = ieee80211_get_channel(wiphy, freq);
1148     cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, notify_channel, GFP_ATOMIC);
1149 #else
1150     cfg80211_ibss_joined(padapter->pnetdev, cur_network->network.MacAddress, GFP_ATOMIC);
1151 #endif
1152 }
1153 
rtw_cfg80211_indicate_connect(_adapter * padapter)1154 void rtw_cfg80211_indicate_connect(_adapter *padapter)
1155 {
1156     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1157     struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
1158     struct wireless_dev *pwdev = padapter->rtw_wdev;
1159     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
1160     _irqL irqL;
1161 #ifdef CONFIG_P2P
1162     struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
1163 #endif
1164 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
1165     struct cfg80211_roam_info roam_info ={};
1166 #endif
1167 
1168     RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
1169     if (pwdev->iftype != NL80211_IFTYPE_STATION
1170         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
1171         && pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT
1172         #endif
1173     )
1174         return;
1175 
1176     if (!MLME_IS_STA(padapter))
1177         return;
1178 
1179 #ifdef CONFIG_P2P
1180     if (pwdinfo->driver_interface == DRIVER_CFG80211) {
1181         #if !RTW_P2P_GROUP_INTERFACE
1182         if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
1183             rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
1184             rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
1185             rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
1186             RTW_INFO("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
1187         }
1188         #endif
1189     }
1190 #endif /* CONFIG_P2P */
1191 
1192     if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) != _TRUE) {
1193         WLAN_BSSID_EX  *pnetwork = &(padapter->mlmeextpriv.mlmext_info.network);
1194         struct wlan_network *scanned = pmlmepriv->cur_network_scanned;
1195 
1196         /* RTW_INFO(FUNC_ADPT_FMT" BSS not found\n", FUNC_ADPT_ARG(padapter)); */
1197 
1198         if (scanned == NULL) {
1199             rtw_warn_on(1);
1200             goto check_bss;
1201         }
1202 
1203         if (_rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE
1204             && _rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE
1205         ) {
1206             if (!rtw_cfg80211_inform_bss(padapter, scanned))
1207                 RTW_INFO(FUNC_ADPT_FMT" inform fail !!\n", FUNC_ADPT_ARG(padapter));
1208             else {
1209                 /* RTW_INFO(FUNC_ADPT_FMT" inform success !!\n", FUNC_ADPT_ARG(padapter)); */
1210             }
1211         } else {
1212             RTW_INFO("scanned: %s("MAC_FMT"), cur: %s("MAC_FMT")\n",
1213                 scanned->network.Ssid.Ssid, MAC_ARG(scanned->network.MacAddress),
1214                 pnetwork->Ssid.Ssid, MAC_ARG(pnetwork->MacAddress)
1215             );
1216             rtw_warn_on(1);
1217         }
1218     }
1219 
1220 check_bss:
1221     if (!rtw_cfg80211_check_bss(padapter))
1222         RTW_PRINT(FUNC_ADPT_FMT" BSS not found !!\n", FUNC_ADPT_ARG(padapter));
1223 
1224     _enter_critical_bh(&pwdev_priv->connect_req_lock, &irqL);
1225 
1226     if (rtw_to_roam(padapter) > 0) {
1227         #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE)
1228         struct wiphy *wiphy = pwdev->wiphy;
1229         struct ieee80211_channel *notify_channel;
1230         u32 freq;
1231         u16 channel = cur_network->network.Configuration.DSConfig;
1232 
1233         freq = rtw_ch2freq(channel);
1234         notify_channel = ieee80211_get_channel(wiphy, freq);
1235         #endif
1236 
1237         #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
1238         roam_info.bssid = cur_network->network.MacAddress;
1239         roam_info.req_ie = pmlmepriv->assoc_req + sizeof(struct rtw_ieee80211_hdr_3addr) + 2;
1240         roam_info.req_ie_len = pmlmepriv->assoc_req_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 2;
1241         roam_info.resp_ie = pmlmepriv->assoc_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6;
1242         roam_info.resp_ie_len = pmlmepriv->assoc_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6;
1243 
1244         cfg80211_roamed(padapter->pnetdev, &roam_info, GFP_ATOMIC);
1245         #else
1246         cfg80211_roamed(padapter->pnetdev
1247             #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) || defined(COMPAT_KERNEL_RELEASE)
1248             , notify_channel
1249             #endif
1250             , cur_network->network.MacAddress
1251             , pmlmepriv->assoc_req + sizeof(struct rtw_ieee80211_hdr_3addr) + 2
1252             , pmlmepriv->assoc_req_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 2
1253             , pmlmepriv->assoc_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6
1254             , pmlmepriv->assoc_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6
1255             , GFP_ATOMIC);
1256         #endif /*LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)*/
1257 
1258         RTW_INFO(FUNC_ADPT_FMT" call cfg80211_roamed\n", FUNC_ADPT_ARG(padapter));
1259 
1260 #ifdef CONFIG_RTW_80211R
1261         if (rtw_ft_roam(padapter))
1262             rtw_ft_set_status(padapter, RTW_FT_ASSOCIATED_STA);
1263 #endif
1264     } else {
1265         #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)
1266         RTW_INFO("pwdev->sme_state(b)=%d\n", pwdev->sme_state);
1267         #endif
1268 
1269 #ifdef CONFIG_RTL8822CS_WIFI_HDF
1270         if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) != _TRUE){
1271 
1272             struct ConnetResult connectResult;
1273             memcpy(connectResult.bssid, cur_network->network.MacAddress, 6);
1274             connectResult.statusCode = WLAN_STATUS_SUCCESS;
1275             connectResult.rspIe = pmlmepriv->assoc_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6;
1276             connectResult.reqIe = pmlmepriv->assoc_req + sizeof(struct rtw_ieee80211_hdr_3addr) + 2;
1277             connectResult.reqIeLen = pmlmepriv->assoc_req_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 2;
1278             connectResult.rspIeLen = pmlmepriv->assoc_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6;
1279             connectResult.connectStatus = 0;
1280             connectResult.freq = rtw_ch2freq(cur_network->network.Configuration.DSConfig);
1281             HdfWifiEventConnectResult(get_rtl_netdev(),&connectResult);
1282         }
1283 #else
1284         if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) != _TRUE)
1285             rtw_cfg80211_connect_result(pwdev, cur_network->network.MacAddress
1286                 , pmlmepriv->assoc_req + sizeof(struct rtw_ieee80211_hdr_3addr) + 2
1287                 , pmlmepriv->assoc_req_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 2
1288                 , pmlmepriv->assoc_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6
1289                 , pmlmepriv->assoc_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6
1290                 , WLAN_STATUS_SUCCESS, GFP_ATOMIC);
1291 #endif
1292         #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)
1293         RTW_INFO("pwdev->sme_state(a)=%d\n", pwdev->sme_state);
1294         #endif
1295     }
1296 
1297     rtw_wdev_free_connect_req(pwdev_priv);
1298 
1299     _exit_critical_bh(&pwdev_priv->connect_req_lock, &irqL);
1300 }
1301 
rtw_cfg80211_indicate_disconnect(_adapter * padapter,u16 reason,u8 locally_generated)1302 void rtw_cfg80211_indicate_disconnect(_adapter *padapter, u16 reason, u8 locally_generated)
1303 {
1304     struct wireless_dev *pwdev = padapter->rtw_wdev;
1305     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
1306     _irqL irqL;
1307 #ifdef CONFIG_P2P
1308     struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
1309 #endif
1310 
1311     RTW_INFO(FUNC_ADPT_FMT" ,reason = %d\n", FUNC_ADPT_ARG(padapter), reason);
1312 
1313     /*always replace privated definitions with wifi reserved value 0*/
1314     if (WLAN_REASON_IS_PRIVATE(reason))
1315         reason = 0;
1316 
1317     if (pwdev->iftype != NL80211_IFTYPE_STATION
1318         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
1319         && pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT
1320         #endif
1321     )
1322         return;
1323 
1324     if (!MLME_IS_STA(padapter))
1325         return;
1326 
1327 #ifdef CONFIG_P2P
1328     if (pwdinfo->driver_interface == DRIVER_CFG80211) {
1329         if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
1330             rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
1331 
1332             #if RTW_P2P_GROUP_INTERFACE
1333             #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
1334             if (pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
1335             #endif
1336             #endif
1337                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
1338 
1339             RTW_INFO("%s, role=%d, p2p_state=%d, pre_p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
1340         }
1341     }
1342 #endif /* CONFIG_P2P */
1343 
1344     _enter_critical_bh(&pwdev_priv->connect_req_lock, &irqL);
1345 
1346     if (padapter->ndev_unregistering || !rtw_wdev_not_indic_disco(pwdev_priv)) {
1347         #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) || defined(COMPAT_KERNEL_RELEASE)
1348         RTW_INFO("pwdev->sme_state(b)=%d\n", pwdev->sme_state);
1349 
1350         if (pwdev->sme_state == CFG80211_SME_CONNECTING) {
1351             RTW_INFO(FUNC_ADPT_FMT" call cfg80211_connect_result, reason:%d\n", FUNC_ADPT_ARG(padapter), reason);
1352             rtw_cfg80211_connect_result(pwdev, NULL, NULL, 0, NULL, 0,
1353                 reason?reason:WLAN_STATUS_UNSPECIFIED_FAILURE,
1354                 GFP_ATOMIC);
1355         } else if (pwdev->sme_state == CFG80211_SME_CONNECTED) {
1356             RTW_INFO(FUNC_ADPT_FMT" call cfg80211_disconnected, reason:%d\n", FUNC_ADPT_ARG(padapter), reason);
1357             rtw_cfg80211_disconnected(pwdev, reason, NULL, 0, locally_generated, GFP_ATOMIC);
1358         }
1359 
1360         RTW_INFO("pwdev->sme_state(a)=%d\n", pwdev->sme_state);
1361         #else
1362         if (pwdev_priv->connect_req) {
1363             RTW_INFO(FUNC_ADPT_FMT" call cfg80211_connect_result, reason:%d\n", FUNC_ADPT_ARG(padapter), reason);
1364             rtw_cfg80211_connect_result(pwdev, NULL, NULL, 0, NULL, 0,
1365                 reason?reason:WLAN_STATUS_UNSPECIFIED_FAILURE,
1366                 GFP_ATOMIC);
1367         } else {
1368             RTW_INFO(FUNC_ADPT_FMT" call cfg80211_disconnected, reason:%d\n", FUNC_ADPT_ARG(padapter), reason);
1369             rtw_cfg80211_disconnected(pwdev, reason, NULL, 0, locally_generated, GFP_ATOMIC);
1370         }
1371         #endif
1372     }
1373 
1374     rtw_wdev_free_connect_req(pwdev_priv);
1375 
1376     _exit_critical_bh(&pwdev_priv->connect_req_lock, &irqL);
1377 }
1378 
1379 
1380 #ifdef CONFIG_AP_MODE
rtw_cfg80211_ap_set_encryption(struct net_device * dev,struct ieee_param * param)1381 static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_param *param)
1382 {
1383     int ret = 0;
1384     u32 wep_key_idx, wep_key_len;
1385     struct sta_info *psta = NULL, *pbcmc_sta = NULL;
1386     _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1387     struct security_priv *psecuritypriv = &(padapter->securitypriv);
1388     struct sta_priv *pstapriv = &padapter->stapriv;
1389 
1390     RTW_INFO("%s\n", __FUNCTION__);
1391 
1392     param->u.crypt.err = 0;
1393     param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
1394 
1395     if (is_broadcast_mac_addr(param->sta_addr)) {
1396         if (param->u.crypt.idx >= WEP_KEYS
1397             #ifdef CONFIG_IEEE80211W
1398             && param->u.crypt.idx > BIP_MAX_KEYID
1399             #endif
1400         ) {
1401             ret = -EINVAL;
1402             goto exit;
1403         }
1404     } else {
1405         psta = rtw_get_stainfo(pstapriv, param->sta_addr);
1406         if (!psta) {
1407             ret = -EINVAL;
1408             RTW_INFO(FUNC_ADPT_FMT", sta "MAC_FMT" not found\n"
1409                 , FUNC_ADPT_ARG(padapter), MAC_ARG(param->sta_addr));
1410             goto exit;
1411         }
1412     }
1413 
1414     if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
1415         /* todo:clear default encryption keys */
1416 
1417         RTW_INFO("clear default encryption keys, keyid=%d\n", param->u.crypt.idx);
1418 
1419         goto exit;
1420     }
1421 
1422 
1423     if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
1424         RTW_INFO("r871x_set_encryption, crypt.alg = WEP\n");
1425 
1426         wep_key_idx = param->u.crypt.idx;
1427         wep_key_len = param->u.crypt.key_len;
1428 
1429         RTW_INFO("r871x_set_encryption, wep_key_idx=%d, len=%d\n", wep_key_idx, wep_key_len);
1430 
1431         if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
1432             ret = -EINVAL;
1433             goto exit;
1434         }
1435 
1436         if (wep_key_len > 0)
1437             wep_key_len = wep_key_len <= 5 ? 5 : 13;
1438 
1439         if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
1440             /* wep default key has not been set, so use this key index as default key. */
1441 
1442             psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1443             psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1444             psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
1445             psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
1446 
1447             if (wep_key_len == 13) {
1448                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
1449                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
1450             }
1451 
1452             psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
1453         }
1454 
1455         _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);
1456 
1457         psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
1458 
1459         rtw_ap_set_wep_key(padapter, param->u.crypt.key, wep_key_len, wep_key_idx, 1);
1460 
1461         goto exit;
1462 
1463     }
1464 
1465     if (!psta) { /* group key */
1466         if (param->u.crypt.set_tx == 0) { /* group key, TX only */
1467             if (strcmp(param->u.crypt.alg, "WEP") == 0) {
1468                 RTW_INFO(FUNC_ADPT_FMT" set WEP TX GTK idx:%u, len:%u\n"
1469                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1470                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1471                 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
1472                 if (param->u.crypt.key_len == 13)
1473                     psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
1474 
1475             } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
1476                 RTW_INFO(FUNC_ADPT_FMT" set TKIP TX GTK idx:%u, len:%u\n"
1477                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1478                 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
1479                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1480                 /* set mic key */
1481                 _rtw_memcpy(psecuritypriv->dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
1482                 _rtw_memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
1483                 psecuritypriv->busetkipkey = _TRUE;
1484 
1485             } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
1486                 RTW_INFO(FUNC_ADPT_FMT" set CCMP TX GTK idx:%u, len:%u\n"
1487                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1488                 psecuritypriv->dot118021XGrpPrivacy = _AES_;
1489                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,  param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1490 
1491             } else if (strcmp(param->u.crypt.alg, "GCMP") == 0) {
1492                 RTW_INFO(FUNC_ADPT_FMT" set GCMP TX GTK idx:%u, len:%u\n"
1493                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1494                 psecuritypriv->dot118021XGrpPrivacy = _GCMP_;
1495                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
1496                     param->u.crypt.key,
1497                     (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1498 
1499             } else if (strcmp(param->u.crypt.alg, "GCMP_256") == 0) {
1500                 RTW_INFO(FUNC_ADPT_FMT" set GCMP_256 TX GTK idx:%u, len:%u\n"
1501                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1502                 psecuritypriv->dot118021XGrpPrivacy = _GCMP_256_;
1503                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
1504                     param->u.crypt.key,
1505                     (param->u.crypt.key_len > 32 ? 32 : param->u.crypt.key_len));
1506 
1507             } else if (strcmp(param->u.crypt.alg, "CCMP_256") == 0) {
1508                 RTW_INFO(FUNC_ADPT_FMT" set CCMP_256 TX GTK idx:%u, len:%u\n"
1509                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1510                 psecuritypriv->dot118021XGrpPrivacy = _CCMP_256_;
1511                 _rtw_memcpy(psecuritypriv->dot118021XGrpKey[param->u.crypt.idx].skey,
1512                     param->u.crypt.key,
1513                     (param->u.crypt.key_len > 32 ? 32: param->u.crypt.key_len));
1514 
1515             #ifdef CONFIG_IEEE80211W
1516             } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
1517                 psecuritypriv->dot11wCipher = _BIP_CMAC_128_;
1518                 RTW_INFO(FUNC_ADPT_FMT" set TX CMAC-128 IGTK idx:%u, len:%u\n"
1519                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1520                 _rtw_memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1521                 padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
1522                 psecuritypriv->dot11wBIPtxpn.val = RTW_GET_LE64(param->u.crypt.seq);
1523                 padapter->securitypriv.binstallBIPkey = _TRUE;
1524                 goto exit;
1525             } else if (strcmp(param->u.crypt.alg, "BIP_GMAC_128") == 0) {
1526                 RTW_INFO(FUNC_ADPT_FMT" set TX GMAC-128 IGTK idx:%u, len:%u\n"
1527                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1528                 psecuritypriv->dot11wCipher = _BIP_GMAC_128_;
1529                 _rtw_memcpy(psecuritypriv->dot11wBIPKey[param->u.crypt.idx].skey,
1530                     param->u.crypt.key, param->u.crypt.key_len);
1531                 psecuritypriv->dot11wBIPKeyid = param->u.crypt.idx;
1532                 psecuritypriv->dot11wBIPtxpn.val = RTW_GET_LE64(param->u.crypt.seq);
1533                 psecuritypriv->binstallBIPkey = _TRUE;
1534                 goto exit;
1535             } else if (strcmp(param->u.crypt.alg, "BIP_GMAC_256") == 0) {
1536                 RTW_INFO(FUNC_ADPT_FMT" set TX GMAC-256 IGTK idx:%u, len:%u\n"
1537                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1538                 psecuritypriv->dot11wCipher = _BIP_GMAC_256_;
1539                 _rtw_memcpy(psecuritypriv->dot11wBIPKey[param->u.crypt.idx].skey,
1540                     param->u.crypt.key, param->u.crypt.key_len);
1541                 padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
1542                 psecuritypriv->dot11wBIPtxpn.val = RTW_GET_LE64(param->u.crypt.seq);
1543                 padapter->securitypriv.binstallBIPkey = _TRUE;
1544                 goto exit;
1545             } else if (strcmp(param->u.crypt.alg, "BIP_CMAC_256") == 0) {
1546                 RTW_INFO(FUNC_ADPT_FMT" set TX CMAC-256 IGTK idx:%u, len:%u\n"
1547                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1548                 psecuritypriv->dot11wCipher = _BIP_CMAC_256_;
1549                 _rtw_memcpy(psecuritypriv->dot11wBIPKey[param->u.crypt.idx].skey,
1550                     param->u.crypt.key, param->u.crypt.key_len);
1551                 psecuritypriv->dot11wBIPKeyid = param->u.crypt.idx;
1552                 psecuritypriv->dot11wBIPtxpn.val = RTW_GET_LE64(param->u.crypt.seq);
1553                 psecuritypriv->binstallBIPkey = _TRUE;
1554                 goto exit;
1555             #endif /* CONFIG_IEEE80211W */
1556 
1557             } else if (strcmp(param->u.crypt.alg, "none") == 0) {
1558                 RTW_INFO(FUNC_ADPT_FMT" clear group key, idx:%u\n"
1559                     , FUNC_ADPT_ARG(padapter), param->u.crypt.idx);
1560                 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
1561             } else {
1562                 RTW_WARN(FUNC_ADPT_FMT" set group key, not support\n"
1563                     , FUNC_ADPT_ARG(padapter));
1564                 goto exit;
1565             }
1566 
1567             psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
1568             pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
1569             if (pbcmc_sta) {
1570                 pbcmc_sta->dot11txpn.val = RTW_GET_LE64(param->u.crypt.seq);
1571                 pbcmc_sta->ieee8021x_blocked = _FALSE;
1572                 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy; /* rx will use bmc_sta's dot118021XPrivacy             */
1573             }
1574             psecuritypriv->binstallGrpkey = _TRUE;
1575             psecuritypriv->dot11PrivacyAlgrthm = psecuritypriv->dot118021XGrpPrivacy;/* !!! */
1576 
1577             rtw_ap_set_group_key(padapter, param->u.crypt.key, psecuritypriv->dot118021XGrpPrivacy, param->u.crypt.idx);
1578         }
1579 
1580         goto exit;
1581 
1582     }
1583 
1584     if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
1585         if (param->u.crypt.set_tx == 1) {
1586             /* pairwise key */
1587             if (param->u.crypt.key_len == 32)
1588                 _rtw_memcpy(psta->dot118021x_UncstKey.skey,
1589                         param->u.crypt.key,
1590                         (param->u.crypt.key_len > 32 ? 32 : param->u.crypt.key_len));
1591             else
1592                 _rtw_memcpy(psta->dot118021x_UncstKey.skey,
1593                         param->u.crypt.key,
1594                         (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1595 
1596             if (strcmp(param->u.crypt.alg, "WEP") == 0) {
1597                 RTW_INFO(FUNC_ADPT_FMT" set WEP PTK of "MAC_FMT" idx:%u, len:%u\n"
1598                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1599                     , param->u.crypt.idx, param->u.crypt.key_len);
1600                 psta->dot118021XPrivacy = _WEP40_;
1601                 if (param->u.crypt.key_len == 13)
1602                     psta->dot118021XPrivacy = _WEP104_;
1603 
1604             } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
1605                 RTW_INFO(FUNC_ADPT_FMT" set TKIP PTK of "MAC_FMT" idx:%u, len:%u\n"
1606                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1607                     , param->u.crypt.idx, param->u.crypt.key_len);
1608                 psta->dot118021XPrivacy = _TKIP_;
1609                 /* set mic key */
1610                 _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
1611                 _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
1612                 psecuritypriv->busetkipkey = _TRUE;
1613 
1614             } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
1615                 RTW_INFO(FUNC_ADPT_FMT" set CCMP PTK of "MAC_FMT" idx:%u, len:%u\n"
1616                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1617                     , param->u.crypt.idx, param->u.crypt.key_len);
1618                 psta->dot118021XPrivacy = _AES_;
1619 
1620             } else if (strcmp(param->u.crypt.alg, "GCMP") == 0) {
1621                 RTW_INFO(FUNC_ADPT_FMT" set GCMP PTK of "MAC_FMT" idx:%u, len:%u\n"
1622                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1623                     , param->u.crypt.idx, param->u.crypt.key_len);
1624                 psta->dot118021XPrivacy = _GCMP_;
1625 
1626             } else if (strcmp(param->u.crypt.alg, "GCMP_256") == 0) {
1627                 RTW_INFO(FUNC_ADPT_FMT" set GCMP_256 PTK of "MAC_FMT" idx:%u, len:%u\n"
1628                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1629                     , param->u.crypt.idx, param->u.crypt.key_len);
1630                 psta->dot118021XPrivacy = _GCMP_256_;
1631 
1632             } else if (strcmp(param->u.crypt.alg, "CCMP_256") == 0) {
1633                 RTW_INFO(FUNC_ADPT_FMT" set CCMP_256 PTK of "MAC_FMT" idx:%u, len:%u\n"
1634                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1635                     , param->u.crypt.idx, param->u.crypt.key_len);
1636                 psta->dot118021XPrivacy = _CCMP_256_;
1637 
1638             } else if (strcmp(param->u.crypt.alg, "none") == 0) {
1639                 RTW_INFO(FUNC_ADPT_FMT" clear pairwise key of "MAC_FMT" idx:%u\n"
1640                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1641                     , param->u.crypt.idx);
1642                 psta->dot118021XPrivacy = _NO_PRIVACY_;
1643             } else {
1644                 RTW_WARN(FUNC_ADPT_FMT" set pairwise key of "MAC_FMT", not support\n"
1645                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));
1646                 goto exit;
1647             }
1648 
1649             psta->dot11txpn.val = RTW_GET_LE64(param->u.crypt.seq);
1650             psta->dot11rxpn.val = RTW_GET_LE64(param->u.crypt.seq);
1651             psta->ieee8021x_blocked = _FALSE;
1652 
1653             if (psta->dot118021XPrivacy != _NO_PRIVACY_) {
1654                 psta->bpairwise_key_installed = _TRUE;
1655 
1656                 /* WPA2 key-handshake has completed */
1657                 if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK)
1658                     psta->state &= (~WIFI_UNDER_KEY_HANDSHAKE);
1659             }
1660 
1661             rtw_ap_set_pairwise_key(padapter, psta);
1662         } else {
1663             /* peer's group key, RX only */
1664             #ifdef CONFIG_RTW_MESH
1665             if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
1666                 RTW_INFO(FUNC_ADPT_FMT" set CCMP GTK of "MAC_FMT", idx:%u, len:%u\n"
1667                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1668                     , param->u.crypt.idx, param->u.crypt.key_len);
1669                 psta->group_privacy = _AES_;
1670                 _rtw_memcpy(psta->gtk.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1671                 psta->gtk_bmp |= BIT(param->u.crypt.idx);
1672                 psta->gtk_pn.val = RTW_GET_LE64(param->u.crypt.seq);
1673 
1674             } else if (strcmp(param->u.crypt.alg, "GCMP") == 0) {
1675                 RTW_INFO(FUNC_ADPT_FMT" set GCMP GTK of "MAC_FMT", idx:%u, len:%u\n"
1676                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1677                     , param->u.crypt.idx, param->u.crypt.key_len);
1678                 psta->group_privacy = _GCMP_;
1679                 _rtw_memcpy(psta->gtk.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1680                 psta->gtk_bmp |= BIT(param->u.crypt.idx);
1681                 psta->gtk_pn.val = RTW_GET_LE64(param->u.crypt.seq);
1682 
1683             } else if (strcmp(param->u.crypt.alg, "CCMP_256") == 0) {
1684                 RTW_INFO(FUNC_ADPT_FMT" set CCMP_256 GTK of "MAC_FMT", idx:%u, len:%u\n"
1685                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1686                     , param->u.crypt.idx, param->u.crypt.key_len);
1687                 psta->group_privacy = _CCMP_256_;
1688                 _rtw_memcpy(psta->gtk.skey, param->u.crypt.key, (param->u.crypt.key_len > 32 ? 32 : param->u.crypt.key_len));
1689                 psta->gtk_bmp |= BIT(param->u.crypt.idx);
1690                 psta->gtk_pn.val = RTW_GET_LE64(param->u.crypt.seq);
1691 
1692             } else if (strcmp(param->u.crypt.alg, "GCMP_256") == 0) {
1693                 RTW_INFO(FUNC_ADPT_FMT" set GCMP_256 GTK of "MAC_FMT", idx:%u, len:%u\n"
1694                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1695                     , param->u.crypt.idx, param->u.crypt.key_len);
1696                 psta->group_privacy = _GCMP_256_;
1697                 _rtw_memcpy(psta->gtk.skey, param->u.crypt.key, (param->u.crypt.key_len > 32 ? 32 : param->u.crypt.key_len));
1698                 psta->gtk_bmp |= BIT(param->u.crypt.idx);
1699                 psta->gtk_pn.val = RTW_GET_LE64(param->u.crypt.seq);
1700 
1701             #ifdef CONFIG_IEEE80211W
1702             } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
1703                 RTW_INFO(FUNC_ADPT_FMT" set CMAC-128 IGTK of "MAC_FMT", idx:%u, len:%u\n"
1704                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1705                     , param->u.crypt.idx, param->u.crypt.key_len);
1706                 psta->dot11wCipher = _BIP_CMAC_128_;
1707                 _rtw_memcpy(psta->igtk.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1708                 psta->igtk_bmp |= BIT(param->u.crypt.idx);
1709                 psta->igtk_id = param->u.crypt.idx;
1710                 psta->igtk_pn.val = RTW_GET_LE64(param->u.crypt.seq);
1711                 goto exit;
1712 
1713             } else if (strcmp(param->u.crypt.alg, "BIP_GMAC_128") == 0) {
1714                 RTW_INFO(FUNC_ADPT_FMT" set GMAC-128 IGTK of "MAC_FMT", idx:%u, len:%u\n"
1715                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1716                     , param->u.crypt.idx, param->u.crypt.key_len);
1717                 psta->dot11wCipher = _BIP_GMAC_128_;
1718                 _rtw_memcpy(psta->igtk.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1719                 psta->igtk_bmp |= BIT(param->u.crypt.idx);
1720                 psta->igtk_id = param->u.crypt.idx;
1721                 psta->igtk_pn.val = RTW_GET_LE64(param->u.crypt.seq);
1722                 goto exit;
1723 
1724             } else if (strcmp(param->u.crypt.alg, "BIP_CMAC_256") == 0) {
1725                 RTW_INFO(FUNC_ADPT_FMT" set CMAC-256 IGTK of "MAC_FMT", idx:%u, len:%u\n"
1726                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1727                     , param->u.crypt.idx, param->u.crypt.key_len);
1728                 psta->dot11wCipher = _BIP_CMAC_256_;
1729                 _rtw_memcpy(psta->igtk.skey, param->u.crypt.key, (param->u.crypt.key_len > 32 ? 32 : param->u.crypt.key_len));
1730                 psta->igtk_bmp |= BIT(param->u.crypt.idx);
1731                 psta->igtk_id = param->u.crypt.idx;
1732                 psta->igtk_pn.val = RTW_GET_LE64(param->u.crypt.seq);
1733                 goto exit;
1734 
1735             } else if (strcmp(param->u.crypt.alg, "BIP_GMAC_256") == 0) {
1736                 RTW_INFO(FUNC_ADPT_FMT" set GMAC-256 IGTK of "MAC_FMT", idx:%u, len:%u\n"
1737                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1738                     , param->u.crypt.idx, param->u.crypt.key_len);
1739                 psta->dot11wCipher = _BIP_GMAC_256_;
1740                 _rtw_memcpy(psta->igtk.skey, param->u.crypt.key, (param->u.crypt.key_len > 32 ? 32 : param->u.crypt.key_len));
1741                 psta->igtk_bmp |= BIT(param->u.crypt.idx);
1742                 psta->igtk_id = param->u.crypt.idx;
1743                 psta->igtk_pn.val = RTW_GET_LE64(param->u.crypt.seq);
1744                 goto exit;
1745             #endif /* CONFIG_IEEE80211W */
1746 
1747             } else if (strcmp(param->u.crypt.alg, "none") == 0) {
1748                 RTW_INFO(FUNC_ADPT_FMT" clear group key of "MAC_FMT", idx:%u\n"
1749                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr)
1750                     , param->u.crypt.idx);
1751                 psta->group_privacy = _NO_PRIVACY_;
1752                 psta->gtk_bmp &= ~BIT(param->u.crypt.idx);
1753             } else
1754             #endif /* CONFIG_RTW_MESH */
1755             {
1756                 RTW_WARN(FUNC_ADPT_FMT" set group key of "MAC_FMT", not support\n"
1757                     , FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));
1758                 goto exit;
1759             }
1760 
1761             #ifdef CONFIG_RTW_MESH
1762             rtw_ap_set_sta_key(padapter, psta->cmn.mac_addr, psta->group_privacy
1763                 , param->u.crypt.key, param->u.crypt.idx, 1);
1764             #endif
1765         }
1766 
1767     }
1768 
1769 exit:
1770     return ret;
1771 }
1772 #endif /* CONFIG_AP_MODE */
1773 
rtw_cfg80211_set_encryption(struct net_device * dev,struct ieee_param * param)1774 static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param *param)
1775 {
1776     int ret = 0;
1777     u32 wep_key_idx, wep_key_len;
1778     _adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
1779     struct mlme_priv    *pmlmepriv = &padapter->mlmepriv;
1780     struct security_priv *psecuritypriv = &padapter->securitypriv;
1781 #ifdef CONFIG_P2P
1782     struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1783 #endif /* CONFIG_P2P */
1784 
1785     RTW_INFO("%s\n", __func__);
1786 
1787     param->u.crypt.err = 0;
1788     param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
1789 
1790     if (is_broadcast_mac_addr(param->sta_addr)) {
1791         if (param->u.crypt.idx >= WEP_KEYS
1792             #ifdef CONFIG_IEEE80211W
1793             && param->u.crypt.idx > BIP_MAX_KEYID
1794             #endif
1795         ) {
1796             ret = -EINVAL;
1797             goto exit;
1798         }
1799     } else {
1800 #ifdef CONFIG_WAPI_SUPPORT
1801         if (strcmp(param->u.crypt.alg, "SMS4"))
1802 #endif
1803         {
1804             ret = -EINVAL;
1805             goto exit;
1806         }
1807     }
1808 
1809     if (strcmp(param->u.crypt.alg, "WEP") == 0) {
1810         RTW_INFO("wpa_set_encryption, crypt.alg = WEP\n");
1811 
1812         wep_key_idx = param->u.crypt.idx;
1813         wep_key_len = param->u.crypt.key_len;
1814 
1815         if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
1816             ret = -EINVAL;
1817             goto exit;
1818         }
1819 
1820         if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
1821             /* wep default key has not been set, so use this key index as default key. */
1822 
1823             wep_key_len = wep_key_len <= 5 ? 5 : 13;
1824 
1825             psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1826             psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
1827             psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
1828 
1829             if (wep_key_len == 13) {
1830                 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
1831                 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
1832             }
1833 
1834             psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
1835         }
1836 
1837         _rtw_memcpy(&(psecuritypriv->dot11DefKey[wep_key_idx].skey[0]), param->u.crypt.key, wep_key_len);
1838 
1839         psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
1840 
1841         rtw_set_key(padapter, psecuritypriv, wep_key_idx, 0, _TRUE);
1842 
1843         goto exit;
1844     }
1845 
1846     if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) { /* 802_1x */
1847         struct sta_info *psta, *pbcmc_sta;
1848         struct sta_priv *pstapriv = &padapter->stapriv;
1849 
1850         /* RTW_INFO("%s, : dot11AuthAlgrthm == dot11AuthAlgrthm_8021X\n", __func__); */
1851 
1852         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == _TRUE) { /* sta mode */
1853 #ifdef CONFIG_RTW_80211R
1854             if (rtw_ft_roam(padapter))
1855                 psta = rtw_get_stainfo(pstapriv, pmlmepriv->assoc_bssid);
1856             else
1857 #endif
1858                 psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
1859             if (psta == NULL) {
1860                 /* DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
1861                 RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);
1862             } else {
1863                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
1864                 if (strcmp(param->u.crypt.alg, "none") != 0)
1865                     psta->ieee8021x_blocked = _FALSE;
1866 
1867                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
1868                     (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
1869                     psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1870 
1871                 if (param->u.crypt.set_tx == 1) { /* pairwise key */
1872                     RTW_INFO(FUNC_ADPT_FMT" set %s PTK idx:%u, len:%u\n"
1873                         , FUNC_ADPT_ARG(padapter), param->u.crypt.alg, param->u.crypt.idx, param->u.crypt.key_len);
1874 
1875                     if (strcmp(param->u.crypt.alg, "GCMP_256") == 0
1876                         || strcmp(param->u.crypt.alg, "CCMP_256") == 0) {
1877                         _rtw_memcpy(psta->dot118021x_UncstKey.skey,
1878                             param->u.crypt.key,
1879                             ((param->u.crypt.key_len > 32) ?
1880                                 32 : param->u.crypt.key_len));
1881                     } else
1882                         _rtw_memcpy(psta->dot118021x_UncstKey.skey,
1883                             param->u.crypt.key,
1884                             (param->u.crypt.key_len > 16 ?
1885                                 16 : param->u.crypt.key_len));
1886 
1887                     if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
1888                         _rtw_memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
1889                         _rtw_memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
1890                         padapter->securitypriv.busetkipkey = _FALSE;
1891                     }
1892                     psta->dot11txpn.val = RTW_GET_LE64(param->u.crypt.seq);
1893                     psta->dot11rxpn.val = RTW_GET_LE64(param->u.crypt.seq);
1894                     psta->bpairwise_key_installed = _TRUE;
1895                     #ifdef CONFIG_RTW_80211R
1896                     psta->ft_pairwise_key_installed = _TRUE;
1897                     #endif
1898                     rtw_setstakey_cmd(padapter, psta, UNICAST_KEY, _TRUE);
1899 
1900                 } else { /* group key */
1901                     if (strcmp(param->u.crypt.alg, "TKIP") == 0
1902                         || strcmp(param->u.crypt.alg, "CCMP") == 0
1903                         || strcmp(param->u.crypt.alg, "GCMP") == 0) {
1904                         RTW_INFO(FUNC_ADPT_FMT" set %s GTK idx:%u, len:%u\n"
1905                             , FUNC_ADPT_ARG(padapter), param->u.crypt.alg, param->u.crypt.idx, param->u.crypt.key_len);
1906                         _rtw_memcpy(padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey,
1907                             param->u.crypt.key,
1908                             (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1909 
1910                         if (strcmp(param->u.crypt.alg, "TKIP") == 0 && param->u.crypt.key_len >= 32) {
1911                             _rtw_memcpy(padapter->securitypriv.dot118021XGrptxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[16]), 8);
1912                             _rtw_memcpy(padapter->securitypriv.dot118021XGrprxmickey[param->u.crypt.idx].skey, &(param->u.crypt.key[24]), 8);
1913                         }
1914 
1915                         padapter->securitypriv.binstallGrpkey = _TRUE;
1916                         if (param->u.crypt.idx < 4)
1917                             _rtw_memcpy(padapter->securitypriv.iv_seq[param->u.crypt.idx], param->u.crypt.seq, 8);
1918                         padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
1919                         rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, _TRUE);
1920                     } else if (strcmp(param->u.crypt.alg, "GCMP_256") == 0
1921                         || strcmp(param->u.crypt.alg, "CCMP_256") == 0) {
1922                         RTW_INFO(FUNC_ADPT_FMT" set %s GTK idx:%u, len:%u\n"
1923                             , FUNC_ADPT_ARG(padapter), param->u.crypt.alg, param->u.crypt.idx, param->u.crypt.key_len);
1924                         _rtw_memcpy(
1925                             padapter->securitypriv.dot118021XGrpKey[param->u.crypt.idx].skey,
1926                             param->u.crypt.key,
1927                             (param->u.crypt.key_len > 32 ? 32 : param->u.crypt.key_len));
1928                         padapter->securitypriv.binstallGrpkey = _TRUE;
1929                         padapter->securitypriv.dot118021XGrpKeyid = param->u.crypt.idx;
1930                         rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, _TRUE);
1931                     #ifdef CONFIG_IEEE80211W
1932                     } else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
1933                         psecuritypriv->dot11wCipher = _BIP_CMAC_128_;
1934                         RTW_INFO(FUNC_ADPT_FMT" set CMAC-128 IGTK idx:%u, len:%u\n"
1935                             , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1936                         _rtw_memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey,
1937                             param->u.crypt.key,
1938                             (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1939                         psecuritypriv->dot11wBIPKeyid = param->u.crypt.idx;
1940                         psecuritypriv->dot11wBIPrxpn.val = RTW_GET_LE64(param->u.crypt.seq);
1941                         psecuritypriv->binstallBIPkey = _TRUE;
1942                     } else if (strcmp(param->u.crypt.alg, "BIP_GMAC_128") == 0) {
1943                         psecuritypriv->dot11wCipher = _BIP_GMAC_128_;
1944                         RTW_INFO(FUNC_ADPT_FMT" set GMAC-128 IGTK idx:%u, len:%u\n"
1945                             , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1946                         _rtw_memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey,
1947                             param->u.crypt.key,
1948                             (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
1949                         psecuritypriv->dot11wBIPKeyid = param->u.crypt.idx;
1950                         psecuritypriv->dot11wBIPrxpn.val = RTW_GET_LE64(param->u.crypt.seq);
1951                         psecuritypriv->binstallBIPkey = _TRUE;
1952                     } else if (strcmp(param->u.crypt.alg, "BIP_GMAC_256") == 0) {
1953                         psecuritypriv->dot11wCipher = _BIP_GMAC_256_;
1954                         RTW_INFO(FUNC_ADPT_FMT" set GMAC-256 IGTK idx:%u, len:%u\n"
1955                             , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1956                         _rtw_memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey,
1957                             param->u.crypt.key,
1958                             (param->u.crypt.key_len > 32 ? 32 : param->u.crypt.key_len));
1959                         psecuritypriv->dot11wBIPKeyid = param->u.crypt.idx;
1960                         psecuritypriv->dot11wBIPrxpn.val = RTW_GET_LE64(param->u.crypt.seq);
1961                         psecuritypriv->binstallBIPkey = _TRUE;
1962                     } else if (strcmp(param->u.crypt.alg, "BIP_CMAC_256") == 0) {
1963                         psecuritypriv->dot11wCipher = _BIP_CMAC_256_;
1964                         RTW_INFO(FUNC_ADPT_FMT" set CMAC-256 IGTK idx:%u, len:%u\n"
1965                             , FUNC_ADPT_ARG(padapter), param->u.crypt.idx, param->u.crypt.key_len);
1966                         _rtw_memcpy(psecuritypriv->dot11wBIPKey[param->u.crypt.idx].skey,
1967                             param->u.crypt.key, param->u.crypt.key_len);
1968                         psecuritypriv->dot11wBIPKeyid = param->u.crypt.idx;
1969                         psecuritypriv->dot11wBIPrxpn.val = RTW_GET_LE64(param->u.crypt.seq);
1970                         psecuritypriv->binstallBIPkey = _TRUE;
1971                     #endif /* CONFIG_IEEE80211W */
1972 
1973                     }
1974 
1975 #ifdef CONFIG_P2P
1976                     if (pwdinfo->driver_interface == DRIVER_CFG80211) {
1977                         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
1978                             rtw_p2p_set_state(pwdinfo, P2P_STATE_PROVISIONING_DONE);
1979                     }
1980 #endif /* CONFIG_P2P */
1981 
1982                     /* WPA/WPA2 key-handshake has completed */
1983                     clr_fwstate(pmlmepriv, WIFI_UNDER_KEY_HANDSHAKE);
1984 
1985                 }
1986             }
1987 
1988             pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
1989             if (pbcmc_sta == NULL) {
1990                 /* DEBUG_ERR( ("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
1991             } else {
1992                 /* Jeff: don't disable ieee8021x_blocked while clearing key */
1993                 if (strcmp(param->u.crypt.alg, "none") != 0)
1994                     pbcmc_sta->ieee8021x_blocked = _FALSE;
1995 
1996                 if ((padapter->securitypriv.ndisencryptstatus == Ndis802_11Encryption2Enabled) ||
1997                     (padapter->securitypriv.ndisencryptstatus ==  Ndis802_11Encryption3Enabled))
1998                     pbcmc_sta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1999             }
2000         } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { /* adhoc mode */
2001         }
2002     }
2003 
2004     #ifdef CONFIG_WAPI_SUPPORT
2005     if (strcmp(param->u.crypt.alg, "SMS4") == 0)
2006         rtw_wapi_set_set_encryption(padapter, param);
2007     #endif
2008 
2009 exit:
2010 
2011     RTW_INFO("%s, ret=%d\n", __func__, ret);
2012 
2013 
2014     return ret;
2015 }
2016 
2017 #ifndef CONFIG_RTL8822CS_WIFI_HDF
2018 static
2019 #endif
cfg80211_rtw_add_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index,bool pairwise,const u8 * mac_addr,struct key_params * params)2020 int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev
2021     , u8 key_index
2022 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
2023     , bool pairwise
2024 #endif
2025     , const u8 *mac_addr, struct key_params *params)
2026 {
2027     char *alg_name;
2028     u32 param_len;
2029     struct ieee_param *param = NULL;
2030     int ret = 0;
2031     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
2032     struct wireless_dev *rtw_wdev = padapter->rtw_wdev;
2033     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2034 #ifdef CONFIG_TDLS
2035     struct sta_info *ptdls_sta;
2036 #endif /* CONFIG_TDLS */
2037 
2038     if (mac_addr)
2039         RTW_INFO(FUNC_NDEV_FMT" adding key for %pM\n", FUNC_NDEV_ARG(ndev), mac_addr);
2040     RTW_INFO(FUNC_NDEV_FMT" cipher=0x%x\n", FUNC_NDEV_ARG(ndev), params->cipher);
2041     RTW_INFO(FUNC_NDEV_FMT" key_len=%d, key_index=%d\n", FUNC_NDEV_ARG(ndev), params->key_len, key_index);
2042 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
2043     RTW_INFO(FUNC_NDEV_FMT" pairwise=%d\n", FUNC_NDEV_ARG(ndev), pairwise);
2044 #endif
2045 
2046     if (rtw_cfg80211_sync_iftype(padapter) != _SUCCESS) {
2047         ret = -ENOTSUPP;
2048         goto addkey_end;
2049     }
2050 
2051     param_len = sizeof(struct ieee_param) + params->key_len;
2052     param = rtw_malloc(param_len);
2053     if (param == NULL)
2054         return -1;
2055 
2056     _rtw_memset(param, 0, param_len);
2057 
2058     param->cmd = IEEE_CMD_SET_ENCRYPTION;
2059     _rtw_memset(param->sta_addr, 0xff, ETH_ALEN);
2060 
2061     switch (params->cipher) {
2062     case IW_AUTH_CIPHER_NONE:
2063         /* todo: remove key */
2064         /* remove = 1;     */
2065         alg_name = "none";
2066         break;
2067     case WLAN_CIPHER_SUITE_WEP40:
2068     case WLAN_CIPHER_SUITE_WEP104:
2069         alg_name = "WEP";
2070         break;
2071     case WLAN_CIPHER_SUITE_TKIP:
2072         alg_name = "TKIP";
2073         break;
2074     case WLAN_CIPHER_SUITE_CCMP:
2075         alg_name = "CCMP";
2076         break;
2077     case WIFI_CIPHER_SUITE_GCMP:
2078         alg_name = "GCMP";
2079         break;
2080     case WIFI_CIPHER_SUITE_GCMP_256:
2081         alg_name = "GCMP_256";
2082         break;
2083     case WIFI_CIPHER_SUITE_CCMP_256:
2084         alg_name = "CCMP_256";
2085         break;
2086 #ifdef CONFIG_IEEE80211W
2087     case WLAN_CIPHER_SUITE_AES_CMAC:
2088         alg_name = "BIP";
2089         break;
2090     case WIFI_CIPHER_SUITE_BIP_GMAC_128:
2091         alg_name = "BIP_GMAC_128";
2092         break;
2093     case WIFI_CIPHER_SUITE_BIP_GMAC_256:
2094         alg_name = "BIP_GMAC_256";
2095         break;
2096     case WIFI_CIPHER_SUITE_BIP_CMAC_256:
2097         alg_name = "BIP_CMAC_256";
2098         break;
2099 #endif /* CONFIG_IEEE80211W */
2100 #ifdef CONFIG_WAPI_SUPPORT
2101     case WLAN_CIPHER_SUITE_SMS4:
2102         alg_name = "SMS4";
2103         if (pairwise == NL80211_KEYTYPE_PAIRWISE) {
2104             if (key_index != 0 && key_index != 1) {
2105                 ret = -ENOTSUPP;
2106                 goto addkey_end;
2107             }
2108             _rtw_memcpy((void *)param->sta_addr, (void *)mac_addr, ETH_ALEN);
2109         } else
2110             RTW_INFO("mac_addr is null\n");
2111         RTW_INFO("rtw_wx_set_enc_ext: SMS4 case\n");
2112         break;
2113 #endif
2114 
2115     default:
2116         ret = -ENOTSUPP;
2117         goto addkey_end;
2118     }
2119 
2120     strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
2121 
2122 
2123     if (!mac_addr || is_broadcast_ether_addr(mac_addr)
2124         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
2125         || !pairwise
2126         #endif
2127     ) {
2128         param->u.crypt.set_tx = 0; /* for wpa/wpa2 group key */
2129     } else {
2130         param->u.crypt.set_tx = 1; /* for wpa/wpa2 pairwise key */
2131     }
2132 
2133     param->u.crypt.idx = key_index;
2134 
2135     if (params->seq_len && params->seq) {
2136         _rtw_memcpy(param->u.crypt.seq, (u8 *)params->seq, params->seq_len);
2137         RTW_INFO(FUNC_NDEV_FMT" seq_len:%u, seq:0x%llx\n", FUNC_NDEV_ARG(ndev)
2138             , params->seq_len, RTW_GET_LE64(param->u.crypt.seq));
2139     }
2140 
2141     if (params->key_len && params->key) {
2142         param->u.crypt.key_len = params->key_len;
2143         _rtw_memcpy(param->u.crypt.key, (u8 *)params->key, params->key_len);
2144     }
2145 
2146     if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) {
2147 #ifdef CONFIG_TDLS
2148         if (rtw_tdls_is_driver_setup(padapter) == _FALSE && mac_addr) {
2149             ptdls_sta = rtw_get_stainfo(&padapter->stapriv, (void *)mac_addr);
2150             if (ptdls_sta != NULL && ptdls_sta->tdls_sta_state) {
2151                 _rtw_memcpy(ptdls_sta->tpk.tk, params->key, params->key_len);
2152                 rtw_tdls_set_key(padapter, ptdls_sta);
2153                 goto addkey_end;
2154             }
2155         }
2156 #endif /* CONFIG_TDLS */
2157         ret = rtw_cfg80211_set_encryption(ndev, param);
2158     } else if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
2159 #ifdef CONFIG_AP_MODE
2160         if (mac_addr)
2161             _rtw_memcpy(param->sta_addr, (void *)mac_addr, ETH_ALEN);
2162 
2163         ret = rtw_cfg80211_ap_set_encryption(ndev, param);
2164 #endif
2165     } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE
2166         || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE
2167     ) {
2168         /* RTW_INFO("@@@@@@@@@@ fw_state=0x%x, iftype=%d\n", pmlmepriv->fw_state, rtw_wdev->iftype); */
2169         ret = rtw_cfg80211_set_encryption(ndev, param);
2170     } else
2171         RTW_INFO("error! fw_state=0x%x, iftype=%d\n", pmlmepriv->fw_state, rtw_wdev->iftype);
2172 
2173 
2174 addkey_end:
2175     if (param)
2176         rtw_mfree(param, param_len);
2177 
2178     return ret;
2179 
2180 }
2181 
cfg80211_rtw_get_key(struct wiphy * wiphy,struct net_device * ndev,u8 keyid,bool pairwise,const u8 * mac_addr,void * cookie,void (* callback)(void * cookie,struct key_params *))2182 static int cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev
2183     , u8 keyid
2184 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
2185     , bool pairwise
2186 #endif
2187     , const u8 *mac_addr, void *cookie
2188     , void (*callback)(void *cookie, struct key_params *))
2189 {
2190 #define GET_KEY_PARAM_FMT_S " keyid=%d"
2191 #define GET_KEY_PARAM_ARG_S , keyid
2192 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
2193     #define GET_KEY_PARAM_FMT_2_6_37 ", pairwise=%d"
2194     #define GET_KEY_PARAM_ARG_2_6_37 , pairwise
2195 #else
2196     #define GET_KEY_PARAM_FMT_2_6_37 ""
2197     #define GET_KEY_PARAM_ARG_2_6_37
2198 #endif
2199 #define GET_KEY_PARAM_FMT_E ", addr=%pM"
2200 #define GET_KEY_PARAM_ARG_E , mac_addr
2201 
2202     _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
2203     struct security_priv *sec = &adapter->securitypriv;
2204     struct sta_priv *stapriv = &adapter->stapriv;
2205     struct sta_info *sta = NULL;
2206     u32 cipher = _NO_PRIVACY_;
2207     union Keytype *key = NULL;
2208     u8 key_len = 0;
2209     u64 *pn = NULL;
2210     u8 pn_len = 0;
2211     u8 pn_val[8] = {0};
2212 
2213     struct key_params params;
2214     int ret = -ENOENT;
2215 
2216     if (keyid >= WEP_KEYS
2217         #ifdef CONFIG_IEEE80211W
2218         && keyid > BIP_MAX_KEYID
2219         #endif
2220     )
2221         goto exit;
2222 
2223     if (!mac_addr || is_broadcast_ether_addr(mac_addr)
2224         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
2225         || (MLME_IS_STA(adapter) && !pairwise)
2226         #endif
2227     ) {
2228         /* WEP key, TX GTK/IGTK, RX GTK/IGTK(for STA mode) */
2229         if (is_wep_enc(sec->dot118021XGrpPrivacy)) {
2230             if (keyid >= WEP_KEYS)
2231                 goto exit;
2232             if (!(sec->key_mask & BIT(keyid)))
2233                 goto exit;
2234             cipher = sec->dot118021XGrpPrivacy;
2235             key = &sec->dot11DefKey[keyid];
2236         } else {
2237             if (keyid < WEP_KEYS) {
2238                 if (sec->binstallGrpkey != _TRUE)
2239                     goto exit;
2240                 cipher = sec->dot118021XGrpPrivacy;
2241                 key = &sec->dot118021XGrpKey[keyid];
2242                 sta = rtw_get_bcmc_stainfo(adapter);
2243                 if (sta)
2244                     pn = &sta->dot11txpn.val;
2245             #ifdef CONFIG_IEEE80211W
2246             } else if (keyid <= BIP_MAX_KEYID) {
2247                 if (SEC_IS_BIP_KEY_INSTALLED(sec) != _TRUE)
2248                     goto exit;
2249                 cipher = sec->dot11wCipher;
2250                 key = &sec->dot11wBIPKey[keyid];
2251                 pn = &sec->dot11wBIPtxpn.val;
2252             #endif
2253             }
2254         }
2255     } else {
2256         /* Pairwise key, RX GTK/IGTK for specific peer */
2257         sta = rtw_get_stainfo(stapriv, mac_addr);
2258         if (!sta)
2259             goto exit;
2260 
2261         if (keyid < WEP_KEYS && pairwise) {
2262             if (sta->bpairwise_key_installed != _TRUE)
2263                 goto exit;
2264             cipher = sta->dot118021XPrivacy;
2265             key = &sta->dot118021x_UncstKey;
2266         #ifdef CONFIG_RTW_MESH
2267         } else if (keyid < WEP_KEYS && !pairwise) {
2268             if (!(sta->gtk_bmp & BIT(keyid)))
2269                 goto exit;
2270             cipher = sta->group_privacy;
2271             key = &sta->gtk;
2272         #ifdef CONFIG_IEEE80211W
2273         } else if (keyid <= BIP_MAX_KEYID && !pairwise) {
2274             if (!(sta->igtk_bmp & BIT(keyid)))
2275                 goto exit;
2276             cipher = sta->dot11wCipher;
2277             key = &sta->igtk;
2278             pn = &sta->igtk_pn.val;
2279         #endif
2280         #endif /* CONFIG_RTW_MESH */
2281         }
2282     }
2283 
2284     if (!key)
2285         goto exit;
2286 
2287     if (cipher == _WEP40_) {
2288         cipher = WLAN_CIPHER_SUITE_WEP40;
2289         key_len = sec->dot11DefKeylen[keyid];
2290     } else if (cipher == _WEP104_) {
2291         cipher = WLAN_CIPHER_SUITE_WEP104;
2292         key_len = sec->dot11DefKeylen[keyid];
2293     } else if (cipher == _TKIP_ || cipher == _TKIP_WTMIC_) {
2294         cipher = WLAN_CIPHER_SUITE_TKIP;
2295         key_len = 16;
2296     } else if (cipher == _AES_) {
2297         cipher = WLAN_CIPHER_SUITE_CCMP;
2298         key_len = 16;
2299 #ifdef CONFIG_WAPI_SUPPORT
2300     } else if (cipher == _SMS4_) {
2301         cipher = WLAN_CIPHER_SUITE_SMS4;
2302         key_len = 16;
2303 #endif
2304     } else if (cipher == _GCMP_) {
2305         cipher = WIFI_CIPHER_SUITE_GCMP;
2306         key_len = 16;
2307     } else if (cipher == _CCMP_256_) {
2308         cipher = WIFI_CIPHER_SUITE_CCMP_256;
2309         key_len = 32;
2310     } else if (cipher == _GCMP_256_) {
2311         cipher = WIFI_CIPHER_SUITE_GCMP_256;
2312         key_len = 32;
2313     #ifdef CONFIG_IEEE80211W
2314     } else if (cipher == _BIP_CMAC_128_) {
2315         cipher = WLAN_CIPHER_SUITE_AES_CMAC;
2316         key_len = 16;
2317     } else if (cipher == _BIP_GMAC_128_) {
2318         cipher = WIFI_CIPHER_SUITE_BIP_GMAC_128;
2319         key_len = 16;
2320     } else if (cipher == _BIP_GMAC_256_) {
2321         cipher = WIFI_CIPHER_SUITE_BIP_GMAC_256;
2322         key_len = 32;
2323     } else if (cipher == _BIP_CMAC_256_) {
2324         cipher = WIFI_CIPHER_SUITE_BIP_CMAC_256;
2325         key_len = 32;
2326     #endif
2327     } else {
2328         RTW_WARN(FUNC_NDEV_FMT" unknown cipher:%u\n", FUNC_NDEV_ARG(ndev), cipher);
2329         rtw_warn_on(1);
2330         goto exit;
2331     }
2332 
2333     if (pn) {
2334         *((u64 *)pn_val) = cpu_to_le64(*pn);
2335         pn_len = 6;
2336     }
2337 
2338     ret = 0;
2339 
2340 exit:
2341     RTW_INFO(FUNC_NDEV_FMT
2342         GET_KEY_PARAM_FMT_S
2343         GET_KEY_PARAM_FMT_2_6_37
2344         GET_KEY_PARAM_FMT_E
2345         " ret %d\n", FUNC_NDEV_ARG(ndev)
2346         GET_KEY_PARAM_ARG_S
2347         GET_KEY_PARAM_ARG_2_6_37
2348         GET_KEY_PARAM_ARG_E
2349         , ret);
2350     if (pn)
2351         RTW_INFO(FUNC_NDEV_FMT " seq:0x%llx\n", FUNC_NDEV_ARG(ndev), *pn);
2352 
2353     if (ret == 0) {
2354         _rtw_memset(&params, 0, sizeof(params));
2355 
2356         params.cipher = cipher;
2357         params.key = key->skey;
2358         params.key_len = key_len;
2359         if (pn) {
2360             params.seq = pn_val;
2361             params.seq_len = pn_len;
2362         }
2363 
2364         callback(cookie, &params);
2365     }
2366 
2367     return ret;
2368 }
2369 
2370 #ifndef CONFIG_RTL8822CS_WIFI_HDF
2371 static
2372 #endif
cfg80211_rtw_del_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index,bool pairwise,const u8 * mac_addr)2373 int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
2374 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
2375                 u8 key_index, bool pairwise, const u8 *mac_addr)
2376 #else    /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */
2377                 u8 key_index, const u8 *mac_addr)
2378 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) */
2379 {
2380     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
2381     struct security_priv *psecuritypriv = &padapter->securitypriv;
2382 
2383     RTW_INFO(FUNC_NDEV_FMT" key_index=%d, addr=%pM\n", FUNC_NDEV_ARG(ndev), key_index, mac_addr);
2384 
2385     if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
2386         /* clear the flag of wep default key set. */
2387         psecuritypriv->bWepDefaultKeyIdxSet = 0;
2388     }
2389 
2390     return 0;
2391 }
2392 
2393 #ifndef CONFIG_RTL8822CS_WIFI_HDF
2394 static
2395 #endif
cfg80211_rtw_set_default_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index,bool unicast,bool multicast)2396 int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
2397     struct net_device *ndev, u8 key_index
2398     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
2399     , bool unicast, bool multicast
2400     #endif
2401 )
2402 {
2403     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
2404     struct security_priv *psecuritypriv = &padapter->securitypriv;
2405 
2406 #define SET_DEF_KEY_PARAM_FMT " key_index=%d"
2407 #define SET_DEF_KEY_PARAM_ARG , key_index
2408 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
2409     #define SET_DEF_KEY_PARAM_FMT_2_6_38 ", unicast=%d, multicast=%d"
2410     #define SET_DEF_KEY_PARAM_ARG_2_6_38 , unicast, multicast
2411 #else
2412     #define SET_DEF_KEY_PARAM_FMT_2_6_38 ""
2413     #define SET_DEF_KEY_PARAM_ARG_2_6_38
2414 #endif
2415 
2416     RTW_INFO(FUNC_NDEV_FMT
2417         SET_DEF_KEY_PARAM_FMT
2418         SET_DEF_KEY_PARAM_FMT_2_6_38
2419         "\n", FUNC_NDEV_ARG(ndev)
2420         SET_DEF_KEY_PARAM_ARG
2421         SET_DEF_KEY_PARAM_ARG_2_6_38
2422     );
2423 
2424     if ((key_index < WEP_KEYS) && ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) || (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_))) { /* set wep default key */
2425         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
2426 
2427         psecuritypriv->dot11PrivacyKeyIndex = key_index;
2428 
2429         psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
2430         psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
2431         if (psecuritypriv->dot11DefKeylen[key_index] == 13) {
2432             psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
2433             psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
2434         }
2435 
2436         psecuritypriv->bWepDefaultKeyIdxSet = 1; /* set the flag to represent that wep default key has been set */
2437     }
2438 
2439     return 0;
2440 
2441 }
2442 
2443 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
cfg80211_rtw_set_default_mgmt_key(struct wiphy * wiphy,struct net_device * ndev,u8 key_index)2444 int cfg80211_rtw_set_default_mgmt_key(struct wiphy *wiphy,
2445     struct net_device *ndev, u8 key_index)
2446 {
2447 #define SET_DEF_KEY_PARAM_FMT " key_index=%d"
2448 #define SET_DEF_KEY_PARAM_ARG , key_index
2449 
2450     RTW_INFO(FUNC_NDEV_FMT
2451         SET_DEF_KEY_PARAM_FMT
2452         "\n", FUNC_NDEV_ARG(ndev)
2453         SET_DEF_KEY_PARAM_ARG
2454     );
2455 
2456     return 0;
2457 }
2458 #endif
2459 
2460 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
cfg80211_rtw_set_rekey_data(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_gtk_rekey_data * data)2461 static int cfg80211_rtw_set_rekey_data(struct wiphy *wiphy,
2462     struct net_device *ndev,
2463     struct cfg80211_gtk_rekey_data *data)
2464 {
2465     /*int i;*/
2466     struct sta_info *psta;
2467     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
2468     struct mlme_priv   *pmlmepriv = &padapter->mlmepriv;
2469     struct sta_priv *pstapriv = &padapter->stapriv;
2470     struct security_priv *psecuritypriv = &(padapter->securitypriv);
2471 
2472     psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
2473     if (psta == NULL) {
2474         RTW_INFO("%s, : Obtain Sta_info fail\n", __func__);
2475         return -1;
2476     }
2477 
2478     _rtw_memcpy(psta->kek, data->kek, NL80211_KEK_LEN);
2479     /*printk("\ncfg80211_rtw_set_rekey_data KEK:");
2480     for(i=0;i<NL80211_KEK_LEN; i++)
2481         printk(" %02x ", psta->kek[i]);*/
2482     _rtw_memcpy(psta->kck, data->kck, NL80211_KCK_LEN);
2483     /*printk("\ncfg80211_rtw_set_rekey_data KCK:");
2484     for(i=0;i<NL80211_KCK_LEN; i++)
2485         printk(" %02x ", psta->kck[i]);*/
2486     _rtw_memcpy(psta->replay_ctr, data->replay_ctr, NL80211_REPLAY_CTR_LEN);
2487     psecuritypriv->binstallKCK_KEK = _TRUE;
2488     /*printk("\nREPLAY_CTR: ");
2489     for(i=0;i<RTW_REPLAY_CTR_LEN; i++)
2490         printk(" %02x ", psta->replay_ctr[i]);*/
2491 
2492     return 0;
2493 }
2494 #endif /*CONFIG_GTK_OL*/
2495 
2496 #ifdef CONFIG_RTW_MESH
2497 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
rtw_mesh_ps_to_nl80211_mesh_power_mode(u8 ps)2498 static enum nl80211_mesh_power_mode rtw_mesh_ps_to_nl80211_mesh_power_mode(u8 ps)
2499 {
2500     if (ps == RTW_MESH_PS_UNKNOWN)
2501         return NL80211_MESH_POWER_UNKNOWN;
2502     if (ps == RTW_MESH_PS_ACTIVE)
2503         return NL80211_MESH_POWER_ACTIVE;
2504     if (ps == RTW_MESH_PS_LSLEEP)
2505         return NL80211_MESH_POWER_LIGHT_SLEEP;
2506     if (ps == RTW_MESH_PS_DSLEEP)
2507         return NL80211_MESH_POWER_DEEP_SLEEP;
2508 
2509     rtw_warn_on(1);
2510     return NL80211_MESH_POWER_UNKNOWN;
2511 }
2512 #endif
2513 
2514 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
rtw_plink_state_to_nl80211_plink_state(u8 plink_state)2515 enum nl80211_plink_state rtw_plink_state_to_nl80211_plink_state(u8 plink_state)
2516 {
2517     if (plink_state == RTW_MESH_PLINK_UNKNOWN)
2518         return NUM_NL80211_PLINK_STATES;
2519     if (plink_state == RTW_MESH_PLINK_LISTEN)
2520         return NL80211_PLINK_LISTEN;
2521     if (plink_state == RTW_MESH_PLINK_OPN_SNT)
2522         return NL80211_PLINK_OPN_SNT;
2523     if (plink_state == RTW_MESH_PLINK_OPN_RCVD)
2524         return NL80211_PLINK_OPN_RCVD;
2525     if (plink_state == RTW_MESH_PLINK_CNF_RCVD)
2526         return NL80211_PLINK_CNF_RCVD;
2527     if (plink_state == RTW_MESH_PLINK_ESTAB)
2528         return NL80211_PLINK_ESTAB;
2529     if (plink_state == RTW_MESH_PLINK_HOLDING)
2530         return NL80211_PLINK_HOLDING;
2531     if (plink_state == RTW_MESH_PLINK_BLOCKED)
2532         return NL80211_PLINK_BLOCKED;
2533 
2534     rtw_warn_on(1);
2535     return NUM_NL80211_PLINK_STATES;
2536 }
2537 
nl80211_plink_state_to_rtw_plink_state(enum nl80211_plink_state plink_state)2538 u8 nl80211_plink_state_to_rtw_plink_state(enum nl80211_plink_state plink_state)
2539 {
2540     if (plink_state == NL80211_PLINK_LISTEN)
2541         return RTW_MESH_PLINK_LISTEN;
2542     if (plink_state == NL80211_PLINK_OPN_SNT)
2543         return RTW_MESH_PLINK_OPN_SNT;
2544     if (plink_state == NL80211_PLINK_OPN_RCVD)
2545         return RTW_MESH_PLINK_OPN_RCVD;
2546     if (plink_state == NL80211_PLINK_CNF_RCVD)
2547         return RTW_MESH_PLINK_CNF_RCVD;
2548     if (plink_state == NL80211_PLINK_ESTAB)
2549         return RTW_MESH_PLINK_ESTAB;
2550     if (plink_state == NL80211_PLINK_HOLDING)
2551         return RTW_MESH_PLINK_HOLDING;
2552     if (plink_state == NL80211_PLINK_BLOCKED)
2553         return RTW_MESH_PLINK_BLOCKED;
2554 
2555     rtw_warn_on(1);
2556     return RTW_MESH_PLINK_UNKNOWN;
2557 }
2558 #endif
2559 
rtw_cfg80211_fill_mesh_only_sta_info(struct mesh_plink_ent * plink,struct sta_info * sta,struct station_info * sinfo)2560 static void rtw_cfg80211_fill_mesh_only_sta_info(struct mesh_plink_ent *plink, struct sta_info *sta, struct station_info *sinfo)
2561 {
2562     sinfo->filled |= STATION_INFO_LLID;
2563     sinfo->llid = plink->llid;
2564     sinfo->filled |= STATION_INFO_PLID;
2565     sinfo->plid = plink->plid;
2566     sinfo->filled |= STATION_INFO_PLINK_STATE;
2567     sinfo->plink_state = rtw_plink_state_to_nl80211_plink_state(plink->plink_state);
2568     if (!sta && plink->scanned) {
2569         sinfo->filled |= STATION_INFO_SIGNAL;
2570         sinfo->signal = translate_percentage_to_dbm(plink->scanned->network.PhyInfo.SignalStrength);
2571         sinfo->filled |= STATION_INFO_INACTIVE_TIME;
2572         if (plink->plink_state == RTW_MESH_PLINK_UNKNOWN)
2573             sinfo->inactive_time = 0 - 1;
2574         else
2575             sinfo->inactive_time = rtw_get_passing_time_ms(plink->scanned->last_scanned);
2576     }
2577 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
2578     if (sta) {
2579         sinfo->filled |= STATION_INFO_LOCAL_PM;
2580         sinfo->local_pm = rtw_mesh_ps_to_nl80211_mesh_power_mode(sta->local_mps);
2581         sinfo->filled |= STATION_INFO_PEER_PM;
2582         sinfo->peer_pm = rtw_mesh_ps_to_nl80211_mesh_power_mode(sta->peer_mps);
2583         sinfo->filled |= STATION_INFO_NONPEER_PM;
2584         sinfo->nonpeer_pm = rtw_mesh_ps_to_nl80211_mesh_power_mode(sta->nonpeer_mps);
2585     }
2586 #endif
2587 }
2588 #endif /* CONFIG_RTW_MESH */
2589 
rtw_desc_rate_to_nss_mcs(u8 rate_idx,u8 sgi,u8 * nss,u8 * mcs)2590 static void rtw_desc_rate_to_nss_mcs(u8 rate_idx, u8 sgi, u8 *nss, u8 *mcs)
2591 {
2592     u8 mcs_in = 0, nss_in = 0;
2593 
2594     if ((DESC_RATEMCS0 <= rate_idx) &&
2595        (rate_idx <= DESC_RATEMCS31)) {
2596         mcs_in = rate_idx - DESC_RATEMCS0;
2597     } else if ((DESC_RATEVHTSS1MCS0 <= rate_idx) &&
2598            (rate_idx <= DESC_RATEVHTSS4MCS9)) {
2599         mcs_in = (rate_idx - DESC_RATEVHTSS1MCS0) % 10;
2600         nss_in = ((rate_idx - DESC_RATEVHTSS1MCS0) / 10) + 1;
2601     }
2602 
2603     if (nss)
2604         *nss = nss_in;
2605     if (mcs)
2606         *mcs = mcs_in;
2607 }
2608 
sta_set_rate_info(_adapter * adapter,struct rate_info * rinfo,u8 rtw_rate_idx,u8 sgi,u8 bw)2609 static void sta_set_rate_info(_adapter *adapter, struct rate_info *rinfo,
2610                   u8 rtw_rate_idx, u8 sgi, u8 bw)
2611 {
2612     u8 mcs = 0;
2613     u8 nss = 0;
2614 
2615     rinfo->flags = 0;
2616     rtw_desc_rate_to_nss_mcs(rtw_rate_idx, sgi, &nss, &mcs);
2617 
2618     if (sgi)
2619         rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
2620 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
2621     if (nss) {
2622         rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
2623         rinfo->bw = bw == CHANNEL_WIDTH_160 ? RATE_INFO_BW_160 :
2624                 bw == CHANNEL_WIDTH_80 ? RATE_INFO_BW_80 :
2625                 bw == CHANNEL_WIDTH_40 ? RATE_INFO_BW_40 : RATE_INFO_BW_20;
2626         rinfo->nss = nss;
2627         rinfo->mcs = mcs;
2628     } else if (mcs) {
2629         rinfo->flags |= RATE_INFO_FLAGS_MCS;
2630         rinfo->bw = bw ? RATE_INFO_BW_40 : RATE_INFO_BW_20;
2631         rinfo->mcs = mcs;
2632     }
2633 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
2634     if (nss) {
2635         rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
2636         rinfo->flags |= bw == CHANNEL_WIDTH_160 ? RATE_INFO_FLAGS_160_MHZ_WIDTH :
2637                 bw == CHANNEL_WIDTH_80 ? RATE_INFO_FLAGS_80_MHZ_WIDTH :
2638                 bw == CHANNEL_WIDTH_40 ? RATE_INFO_FLAGS_40_MHZ_WIDTH : 0;
2639         rinfo->nss = nss;
2640         rinfo->mcs = mcs;
2641     } else if (mcs) {
2642         rinfo->flags |= RATE_INFO_FLAGS_MCS;
2643         rinfo->flags |= bw ? RATE_INFO_FLAGS_40_MHZ_WIDTH : 0;
2644         rinfo->mcs = mcs;
2645     }
2646 #else
2647     if (nss) {
2648         rinfo->legacy = 0;
2649         RTW_INFO("Cannot report VHT rate in current kernel version\n");
2650     } else if (mcs) {
2651         rinfo->flags |= RATE_INFO_FLAGS_MCS;
2652         rinfo->flags |= bw ? RATE_INFO_FLAGS_40_MHZ_WIDTH : 0;
2653         rinfo->mcs = mcs;
2654     }
2655 #endif
2656     if (nss == 0 && mcs == 0)
2657         rinfo->legacy = rtw_desc_rate_to_bitrate(0, rtw_rate_idx, 0);
2658 }
2659 
cfg80211_rtw_get_station(struct wiphy * wiphy,struct net_device * ndev,u8 * mac,struct station_info * sinfo)2660 static int cfg80211_rtw_get_station(struct wiphy *wiphy,
2661     struct net_device *ndev,
2662 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
2663     u8 *mac,
2664 #else
2665     const u8 *mac,
2666 #endif
2667     struct station_info *sinfo)
2668 {
2669     int ret = 0;
2670     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
2671     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2672     struct sta_info *psta = NULL;
2673     struct sta_priv *pstapriv = &padapter->stapriv;
2674 #ifdef CONFIG_RTW_MESH
2675     struct mesh_plink_ent *plink = NULL;
2676 #endif
2677 
2678     sinfo->filled = 0;
2679 
2680     if (!mac) {
2681         RTW_INFO(FUNC_NDEV_FMT" mac==%p\n", FUNC_NDEV_ARG(ndev), mac);
2682         ret = -ENOENT;
2683         goto exit;
2684     }
2685 
2686     psta = rtw_get_stainfo(pstapriv, mac);
2687 #ifdef CONFIG_RTW_MESH
2688     if (MLME_IS_MESH(padapter)) {
2689         if (psta)
2690             plink = psta->plink;
2691         if (!plink)
2692             plink = rtw_mesh_plink_get(padapter, mac);
2693     }
2694 #endif /* CONFIG_RTW_MESH */
2695 
2696     if ((!MLME_IS_MESH(padapter) && !psta)
2697         #ifdef CONFIG_RTW_MESH
2698         || (MLME_IS_MESH(padapter) && !plink)
2699         #endif
2700     ) {
2701         RTW_INFO(FUNC_NDEV_FMT" no sta info for mac="MAC_FMT"\n"
2702             , FUNC_NDEV_ARG(ndev), MAC_ARG(mac));
2703         ret = -ENOENT;
2704         goto exit;
2705     }
2706 
2707 #ifdef CONFIG_DEBUG_CFG80211
2708     RTW_INFO(FUNC_NDEV_FMT" mac="MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(mac));
2709 #endif
2710 
2711     /* for infra./P2PClient mode */
2712     if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
2713         && check_fwstate(pmlmepriv, WIFI_ASOC_STATE)
2714     ) {
2715         struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
2716 
2717         if (_rtw_memcmp((u8 *)mac, cur_network->network.MacAddress, ETH_ALEN) == _FALSE) {
2718             RTW_INFO("%s, mismatch bssid="MAC_FMT"\n", __func__, MAC_ARG(cur_network->network.MacAddress));
2719             ret = -ENOENT;
2720             goto exit;
2721         }
2722 
2723         sinfo->filled |= STATION_INFO_SIGNAL;
2724         sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);
2725 
2726         sinfo->filled |= STATION_INFO_TX_BITRATE;
2727         sinfo->txrate.legacy = rtw_get_cur_max_rate(padapter);
2728     }
2729 
2730     if (psta) {
2731         u8 rtw_rate_idx, sgi, bw;
2732 
2733         if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _FALSE
2734             || check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _FALSE
2735         ) {
2736             sinfo->filled |= STATION_INFO_SIGNAL;
2737             sinfo->signal = translate_percentage_to_dbm(psta->cmn.rssi_stat.rssi);
2738         }
2739         sinfo->filled |= STATION_INFO_INACTIVE_TIME;
2740         sinfo->inactive_time = rtw_get_passing_time_ms(psta->sta_stats.last_rx_time);
2741         sinfo->filled |= STATION_INFO_RX_PACKETS;
2742         sinfo->rx_packets = sta_rx_data_pkts(psta);
2743         sinfo->filled |= STATION_INFO_TX_PACKETS;
2744         sinfo->tx_packets = psta->sta_stats.tx_pkts;
2745 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
2746         sinfo->filled |= STATION_INFO_RX_BYTES64;
2747         sinfo->filled |= STATION_INFO_TX_BYTES64;
2748 #else
2749         sinfo->filled |= STATION_INFO_RX_BYTES;
2750         sinfo->filled |= STATION_INFO_TX_BYTES;
2751 #endif
2752         sinfo->rx_bytes = psta->sta_stats.rx_bytes;
2753         sinfo->tx_bytes = psta->sta_stats.tx_bytes;
2754 
2755         /* Although according to cfg80211.h struct station_info */
2756         /* @txrate: current unicast bitrate from this station */
2757         /* We still report sinfo->txrate as bitrate to this station */
2758         sinfo->filled |= STATION_INFO_TX_BITRATE;
2759         rtw_rate_idx = rtw_get_current_tx_rate(padapter, psta);
2760         sgi = rtw_get_current_tx_sgi(padapter, psta);
2761         bw = psta->cmn.bw_mode;
2762         sta_set_rate_info(padapter, &sinfo->txrate, rtw_rate_idx, sgi, bw);
2763 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
2764         /* Although @rxrate: current unicast bitrate to this station */
2765         /* We report sinfo->rxrate as bitrate from this station */
2766         sinfo->filled |= STATION_INFO_RX_BITRATE;
2767         rtw_rate_idx = psta->curr_rx_rate & 0x7f;
2768         sgi = (psta->curr_rx_rate & 0x80) >> 7;
2769         bw = psta->cmn.bw_mode;
2770         sta_set_rate_info(padapter, &sinfo->rxrate, rtw_rate_idx, sgi, bw);
2771 #endif
2772 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
2773         if (rtw_get_sta_tx_stat(padapter, psta->cmn.mac_id, psta->cmn.mac_addr) != RTW_NOT_SUPPORT) {
2774             sinfo->filled |= STATION_INFO_TX_FAILED;
2775             sinfo->filled |= STATION_INFO_TX_RETRIES;
2776             sinfo->tx_failed = psta->sta_stats.tx_fail_cnt_sum;
2777             sinfo->tx_retries = psta->sta_stats.tx_retry_cnt_sum;
2778         }
2779 #endif
2780     }
2781 
2782 #ifdef CONFIG_RTW_MESH
2783     if (MLME_IS_MESH(padapter))
2784         rtw_cfg80211_fill_mesh_only_sta_info(plink, psta, sinfo);
2785 #endif
2786 
2787 exit:
2788     return ret;
2789 }
2790 
2791 extern int netdev_open(struct net_device *pnetdev);
2792 
2793 #if 0
2794 enum nl80211_iftype {
2795     NL80211_IFTYPE_UNSPECIFIED,
2796     NL80211_IFTYPE_ADHOC, /* 1 */
2797     NL80211_IFTYPE_STATION, /* 2 */
2798     NL80211_IFTYPE_AP, /* 3 */
2799     NL80211_IFTYPE_AP_VLAN,
2800     NL80211_IFTYPE_WDS,
2801     NL80211_IFTYPE_MONITOR, /* 6 */
2802     NL80211_IFTYPE_MESH_POINT,
2803     NL80211_IFTYPE_P2P_CLIENT, /* 8 */
2804     NL80211_IFTYPE_P2P_GO, /* 9 */
2805     /* keep last */
2806     NUM_NL80211_IFTYPES,
2807     NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1
2808 };
2809 #endif
2810 #ifndef CONFIG_RTL8822CS_WIFI_HDF
2811 static
2812 #endif
cfg80211_rtw_change_iface(struct wiphy * wiphy,struct net_device * ndev,enum nl80211_iftype type,u32 * flags,struct vif_params * params)2813 int cfg80211_rtw_change_iface(struct wiphy *wiphy,
2814                      struct net_device *ndev,
2815                      enum nl80211_iftype type,
2816 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
2817                      u32 *flags,
2818 #endif
2819                      struct vif_params *params)
2820 {
2821     enum nl80211_iftype old_type;
2822     NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
2823     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
2824     struct wireless_dev *rtw_wdev = padapter->rtw_wdev;
2825     struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2826 #ifdef CONFIG_P2P
2827     struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
2828 #endif
2829 #ifdef CONFIG_MONITOR_MODE_XMIT
2830     struct mlme_priv    *pmlmepriv = &(padapter->mlmepriv);
2831 #endif
2832     int ret = 0;
2833     u8 change = _FALSE;
2834 
2835     RTW_INFO(FUNC_NDEV_FMT" type=%d, hw_port:%d\n", FUNC_NDEV_ARG(ndev), type, padapter->hw_port);
2836 
2837     if (adapter_to_dvobj(padapter)->processing_dev_remove == _TRUE) {
2838         ret = -EPERM;
2839         goto exit;
2840     }
2841 
2842 
2843     RTW_INFO(FUNC_NDEV_FMT" call netdev_open\n", FUNC_NDEV_ARG(ndev));
2844     if (netdev_open(ndev) != 0) {
2845         RTW_INFO(FUNC_NDEV_FMT" call netdev_open fail\n", FUNC_NDEV_ARG(ndev));
2846         ret = -EPERM;
2847         goto exit;
2848     }
2849 
2850 
2851     if (_FAIL == rtw_pwr_wakeup(padapter)) {
2852         RTW_INFO(FUNC_NDEV_FMT" call rtw_pwr_wakeup fail\n", FUNC_NDEV_ARG(ndev));
2853         ret = -EPERM;
2854         goto exit;
2855     }
2856 
2857     old_type = rtw_wdev->iftype;
2858     RTW_INFO(FUNC_NDEV_FMT" old_iftype=%d, new_iftype=%d\n",
2859         FUNC_NDEV_ARG(ndev), old_type, type);
2860 
2861     if (old_type != type) {
2862         change = _TRUE;
2863         pmlmeext->action_public_rxseq = 0xffff;
2864         pmlmeext->action_public_dialog_token = 0xff;
2865     }
2866 
2867     /* initial default type */
2868     ndev->type = ARPHRD_ETHER;
2869 
2870     /*
2871      * Disable Power Save in moniter mode,
2872      * and enable it after leaving moniter mode.
2873      */
2874     if (type == NL80211_IFTYPE_MONITOR) {
2875         rtw_ps_deny(padapter, PS_DENY_MONITOR_MODE);
2876         LeaveAllPowerSaveMode(padapter);
2877     } else if (old_type == NL80211_IFTYPE_MONITOR) {
2878         /* driver in moniter mode in last time */
2879         rtw_ps_deny_cancel(padapter, PS_DENY_MONITOR_MODE);
2880     }
2881 
2882     switch (type) {
2883     case NL80211_IFTYPE_ADHOC:
2884         networkType = Ndis802_11IBSS;
2885         break;
2886 
2887     case NL80211_IFTYPE_STATION:
2888         networkType = Ndis802_11Infrastructure;
2889         #ifdef CONFIG_P2P
2890         if (change && pwdinfo->driver_interface == DRIVER_CFG80211) {
2891             #if !RTW_P2P_GROUP_INTERFACE
2892             if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)
2893                 || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)
2894             ) {
2895                 /* it means remove GC/GO and change mode from GC/GO to station(P2P DEVICE) */
2896                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
2897             }
2898             #endif
2899         }
2900         #endif /* CONFIG_P2P */
2901         break;
2902 
2903     case NL80211_IFTYPE_AP:
2904         networkType = Ndis802_11APMode;
2905         #ifdef CONFIG_P2P
2906         if (change && pwdinfo->driver_interface == DRIVER_CFG80211) {
2907             #if !RTW_P2P_GROUP_INTERFACE
2908             if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
2909                 /* it means P2P Group created, we will be GO and change mode from  P2P DEVICE to AP(GO) */
2910                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
2911             }
2912             #endif
2913         }
2914         #endif /* CONFIG_P2P */
2915         break;
2916 
2917 #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
2918     case NL80211_IFTYPE_P2P_CLIENT:
2919         networkType = Ndis802_11Infrastructure;
2920         if (change && pwdinfo->driver_interface == DRIVER_CFG80211) {
2921             if (!rtw_p2p_enable(padapter, P2P_ROLE_CLIENT)) {
2922                 ret = -EOPNOTSUPP;
2923                 goto exit;
2924             }
2925         }
2926         break;
2927 
2928     case NL80211_IFTYPE_P2P_GO:
2929         networkType = Ndis802_11APMode;
2930         if (change && pwdinfo->driver_interface == DRIVER_CFG80211) {
2931             if (!rtw_p2p_enable(padapter, P2P_ROLE_GO)) {
2932                 ret = -EOPNOTSUPP;
2933                 goto exit;
2934             }
2935         }
2936         break;
2937 #endif /* defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)) */
2938 
2939 #ifdef CONFIG_RTW_MESH
2940     case NL80211_IFTYPE_MESH_POINT:
2941         networkType = Ndis802_11_mesh;
2942         break;
2943 #endif
2944 
2945 #ifdef CONFIG_WIFI_MONITOR
2946     case NL80211_IFTYPE_MONITOR:
2947         networkType = Ndis802_11Monitor;
2948 
2949 #ifdef CONFIG_CUSTOMER_ALIBABA_GENERAL
2950         ndev->type = ARPHRD_IEEE80211; /* IEEE 802.11 : 801 */
2951 #else
2952         ndev->type = ARPHRD_IEEE80211_RADIOTAP; /* IEEE 802.11 + radiotap header : 803 */
2953 #endif
2954         break;
2955 #endif /* CONFIG_WIFI_MONITOR */
2956     default:
2957         ret = -EOPNOTSUPP;
2958         goto exit;
2959     }
2960 
2961     rtw_wdev->iftype = type;
2962 
2963     if (rtw_set_802_11_infrastructure_mode(padapter, networkType, 0) == _FALSE) {
2964         rtw_wdev->iftype = old_type;
2965         ret = -EPERM;
2966         goto exit;
2967     }
2968 
2969     rtw_setopmode_cmd(padapter, networkType, RTW_CMDF_WAIT_ACK);
2970 #ifdef CONFIG_MONITOR_MODE_XMIT
2971     if (check_fwstate(pmlmepriv, WIFI_MONITOR_STATE) == _TRUE)
2972         rtw_indicate_connect(padapter);
2973 #endif
2974 
2975     #if defined(CONFIG_RTW_WDS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
2976     if (params->use_4addr != -1) {
2977         RTW_INFO(FUNC_NDEV_FMT" use_4addr=%d\n"
2978             , FUNC_NDEV_ARG(ndev), params->use_4addr);
2979         adapter_set_use_wds(padapter, params->use_4addr);
2980     }
2981     #endif
2982 
2983 exit:
2984 
2985     RTW_INFO(FUNC_NDEV_FMT" ret:%d\n", FUNC_NDEV_ARG(ndev), ret);
2986     return ret;
2987 }
2988 
rtw_cfg80211_indicate_scan_done(_adapter * adapter,bool aborted)2989 void rtw_cfg80211_indicate_scan_done(_adapter *adapter, bool aborted)
2990 {
2991     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
2992     _irqL    irqL;
2993 
2994 #if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE)
2995     struct cfg80211_scan_info info;
2996 
2997     memset(&info, 0, sizeof(info));
2998     info.aborted = aborted;
2999 #endif
3000 
3001     _enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
3002     if (pwdev_priv->scan_request != NULL) {
3003         #ifdef CONFIG_DEBUG_CFG80211
3004         RTW_INFO("%s with scan req\n", __FUNCTION__);
3005         #endif
3006 
3007         /* avoid WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); */
3008         if (pwdev_priv->scan_request->wiphy != pwdev_priv->rtw_wdev->wiphy)
3009             RTW_INFO("error wiphy compare\n");
3010         else {
3011 #if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE)
3012 #ifdef CONFIG_RTL8822CS_WIFI_HDF
3013             HdfWifiEventScanDone(get_rtl_netdev(), info.aborted);
3014             WifiScanFree(&pwdev_priv->scan_request);
3015 #else
3016             cfg80211_scan_done(pwdev_priv->scan_request, &info);
3017 #endif
3018 #else
3019             cfg80211_scan_done(pwdev_priv->scan_request, aborted);
3020 #endif
3021         }
3022 
3023         pwdev_priv->scan_request = NULL;
3024     } else {
3025         #ifdef CONFIG_DEBUG_CFG80211
3026         RTW_INFO("%s without scan req\n", __FUNCTION__);
3027         #endif
3028     }
3029     _exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
3030 }
3031 
rtw_cfg80211_wait_scan_req_empty(_adapter * adapter,u32 timeout_ms)3032 u32 rtw_cfg80211_wait_scan_req_empty(_adapter *adapter, u32 timeout_ms)
3033 {
3034     struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);
3035     u8 empty = _FALSE;
3036     systime start;
3037     u32 pass_ms;
3038 
3039     start = rtw_get_current_time();
3040 
3041     while (rtw_get_passing_time_ms(start) <= timeout_ms) {
3042 
3043         if (RTW_CANNOT_RUN(adapter))
3044             break;
3045 
3046         if (!wdev_priv->scan_request) {
3047             empty = _TRUE;
3048             break;
3049         }
3050 
3051         rtw_msleep_os(10);
3052     }
3053 
3054     pass_ms = rtw_get_passing_time_ms(start);
3055 
3056     if (empty == _FALSE && pass_ms > timeout_ms) {
3057         RTW_PRINT(FUNC_ADPT_FMT" pass_ms:%u, timeout\n"
3058             , FUNC_ADPT_ARG(adapter), pass_ms);
3059         rtw_cfg80211_indicate_scan_done(adapter, _TRUE);
3060     }
3061 
3062     return pass_ms;
3063 }
3064 
rtw_cfg80211_unlink_bss(_adapter * padapter,struct wlan_network * pnetwork)3065 void rtw_cfg80211_unlink_bss(_adapter *padapter, struct wlan_network *pnetwork)
3066 {
3067     struct wireless_dev *pwdev = padapter->rtw_wdev;
3068     struct wiphy *wiphy = pwdev->wiphy;
3069     struct cfg80211_bss *bss = NULL;
3070     WLAN_BSSID_EX select_network = pnetwork->network;
3071 
3072     bss = cfg80211_get_bss(wiphy, NULL/*notify_channel*/,
3073         select_network.MacAddress, select_network.Ssid.Ssid,
3074         select_network.Ssid.SsidLength,
3075 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
3076         select_network.InfrastructureMode == Ndis802_11Infrastructure?IEEE80211_BSS_TYPE_ESS:IEEE80211_BSS_TYPE_IBSS,
3077         IEEE80211_PRIVACY(select_network.Privacy));
3078 #else
3079         select_network.InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS,
3080         select_network.InfrastructureMode == Ndis802_11Infrastructure?WLAN_CAPABILITY_ESS:WLAN_CAPABILITY_IBSS);
3081 #endif
3082 
3083     if (bss) {
3084         cfg80211_unlink_bss(wiphy, bss);
3085         RTW_INFO("%s(): cfg80211_unlink %s!!\n", __func__, select_network.Ssid.Ssid);
3086 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
3087         cfg80211_put_bss(padapter->rtw_wdev->wiphy, bss);
3088 #else
3089         cfg80211_put_bss(bss);
3090 #endif
3091     }
3092     return;
3093 }
3094 
3095 /* if target wps scan ongoing, target_ssid is filled */
rtw_cfg80211_is_target_wps_scan(struct cfg80211_scan_request * scan_req,struct cfg80211_ssid * target_ssid)3096 int rtw_cfg80211_is_target_wps_scan(struct cfg80211_scan_request *scan_req, struct cfg80211_ssid *target_ssid)
3097 {
3098     int ret = 0;
3099 
3100     if (scan_req->n_ssids != 1
3101         || scan_req->ssids[0].ssid_len == 0
3102         || scan_req->n_channels != 1
3103     )
3104         goto exit;
3105 
3106     /* under target WPS scan */
3107     _rtw_memcpy(target_ssid, scan_req->ssids, sizeof(struct cfg80211_ssid));
3108     ret = 1;
3109 
3110 exit:
3111     return ret;
3112 }
3113 
_rtw_cfg80211_surveydone_event_callback(_adapter * padapter,struct cfg80211_scan_request * scan_req)3114 static void _rtw_cfg80211_surveydone_event_callback(_adapter *padapter, struct cfg80211_scan_request *scan_req)
3115 {
3116     struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
3117     RT_CHANNEL_INFO *chset = rfctl->channel_set;
3118     _irqL    irqL;
3119     _list                    *plist, *phead;
3120     struct    mlme_priv    *pmlmepriv = &(padapter->mlmepriv);
3121     _queue                *queue    = &(pmlmepriv->scanned_queue);
3122     struct    wlan_network    *pnetwork = NULL;
3123     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
3124     struct cfg80211_ssid target_ssid;
3125     u8 target_wps_scan = 0;
3126     u8 ch;
3127 
3128 #ifdef CONFIG_DEBUG_CFG80211
3129     RTW_INFO("%s\n", __func__);
3130 #endif
3131 
3132     if (scan_req)
3133         target_wps_scan = rtw_cfg80211_is_target_wps_scan(scan_req, &target_ssid);
3134     else {
3135         _enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
3136         if (pwdev_priv->scan_request != NULL)
3137             target_wps_scan = rtw_cfg80211_is_target_wps_scan(pwdev_priv->scan_request, &target_ssid);
3138         _exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
3139     }
3140 
3141     _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
3142 
3143     phead = get_list_head(queue);
3144     plist = get_next(phead);
3145 
3146     while (1) {
3147         if (rtw_end_of_queue_search(phead, plist) == _TRUE)
3148             break;
3149 
3150         pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
3151         ch = pnetwork->network.Configuration.DSConfig;
3152 
3153         /* report network only if the current channel set contains the channel to which this network belongs */
3154         if (rtw_chset_search_ch(chset, ch) >= 0
3155             && rtw_mlme_band_check(padapter, ch) == _TRUE
3156             && _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))
3157             && (!IS_DFS_SLAVE_WITH_RD(rfctl)
3158                 || rtw_rfctl_dfs_domain_unknown(rfctl)
3159                 || !rtw_chset_is_ch_non_ocp(chset, ch))
3160         ) {
3161             if (target_wps_scan)
3162                 rtw_cfg80211_clear_wps_sr_of_non_target_bss(padapter, pnetwork, &target_ssid);
3163             rtw_cfg80211_inform_bss(padapter, pnetwork);
3164         }
3165 #if 0
3166         /* check ralink testbed RSN IE length */
3167         {
3168             if (_rtw_memcmp(pnetwork->network.Ssid.Ssid, "Ralink_11n_AP", 13)) {
3169                 uint ie_len = 0;
3170                 u8 *p = NULL;
3171                 p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pnetwork->network.IELength - _BEACON_IE_OFFSET_));
3172                 RTW_INFO("ie_len=%d\n", ie_len);
3173             }
3174         }
3175 #endif
3176         plist = get_next(plist);
3177 
3178     }
3179 
3180     _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
3181 }
3182 
rtw_cfg80211_surveydone_event_callback(_adapter * padapter)3183 inline void rtw_cfg80211_surveydone_event_callback(_adapter *padapter)
3184 {
3185     _rtw_cfg80211_surveydone_event_callback(padapter, NULL);
3186 }
3187 
rtw_cfg80211_set_probe_req_wpsp2pie(_adapter * padapter,char * buf,int len)3188 static int rtw_cfg80211_set_probe_req_wpsp2pie(_adapter *padapter, char *buf, int len)
3189 {
3190     int ret = 0;
3191     uint wps_ielen = 0;
3192     u8 *wps_ie;
3193     u32    p2p_ielen = 0;
3194     u8 *p2p_ie;
3195     u32    wfd_ielen = 0;
3196     u8 *wfd_ie;
3197     struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3198 
3199 #ifdef CONFIG_DEBUG_CFG80211
3200     RTW_INFO("%s, ielen=%d\n", __func__, len);
3201 #endif
3202 
3203     if (len > 0) {
3204         wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen);
3205         if (wps_ie) {
3206             #ifdef CONFIG_DEBUG_CFG80211
3207             RTW_INFO("probe_req_wps_ielen=%d\n", wps_ielen);
3208             #endif
3209 
3210             if (pmlmepriv->wps_probe_req_ie) {
3211                 u32 free_len = pmlmepriv->wps_probe_req_ie_len;
3212                 pmlmepriv->wps_probe_req_ie_len = 0;
3213                 rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);
3214                 pmlmepriv->wps_probe_req_ie = NULL;
3215             }
3216 
3217             pmlmepriv->wps_probe_req_ie = rtw_malloc(wps_ielen);
3218             if (pmlmepriv->wps_probe_req_ie == NULL) {
3219                 RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
3220                 return -EINVAL;
3221 
3222             }
3223             _rtw_memcpy(pmlmepriv->wps_probe_req_ie, wps_ie, wps_ielen);
3224             pmlmepriv->wps_probe_req_ie_len = wps_ielen;
3225         }
3226 
3227         /* buf += wps_ielen; */
3228         /* len -= wps_ielen; */
3229 
3230         #ifdef CONFIG_P2P
3231         p2p_ie = rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen);
3232         if (p2p_ie) {
3233             struct wifidirect_info *wdinfo = &padapter->wdinfo;
3234             u32 attr_contentlen = 0;
3235             u8 listen_ch_attr[5];
3236 
3237             #ifdef CONFIG_DEBUG_CFG80211
3238             RTW_INFO("probe_req_p2p_ielen=%d\n", p2p_ielen);
3239             #endif
3240 
3241             if (pmlmepriv->p2p_probe_req_ie) {
3242                 u32 free_len = pmlmepriv->p2p_probe_req_ie_len;
3243                 pmlmepriv->p2p_probe_req_ie_len = 0;
3244                 rtw_mfree(pmlmepriv->p2p_probe_req_ie, free_len);
3245                 pmlmepriv->p2p_probe_req_ie = NULL;
3246             }
3247 
3248             pmlmepriv->p2p_probe_req_ie = rtw_malloc(p2p_ielen);
3249             if (pmlmepriv->p2p_probe_req_ie == NULL) {
3250                 RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
3251                 return -EINVAL;
3252 
3253             }
3254             _rtw_memcpy(pmlmepriv->p2p_probe_req_ie, p2p_ie, p2p_ielen);
3255             pmlmepriv->p2p_probe_req_ie_len = p2p_ielen;
3256 
3257             attr_contentlen = sizeof(listen_ch_attr);
3258             if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, (u8 *)listen_ch_attr, (uint *) &attr_contentlen)) {
3259                 if (wdinfo->listen_channel !=  listen_ch_attr[4]) {
3260                     RTW_INFO(FUNC_ADPT_FMT" listen channel - country:%c%c%c, class:%u, ch:%u\n",
3261                         FUNC_ADPT_ARG(padapter), listen_ch_attr[0], listen_ch_attr[1], listen_ch_attr[2],
3262                         listen_ch_attr[3], listen_ch_attr[4]);
3263                     wdinfo->listen_channel = listen_ch_attr[4];
3264                 }
3265             }
3266         }
3267         #endif /* CONFIG_P2P */
3268 
3269         #ifdef CONFIG_WFD
3270         wfd_ie = rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen);
3271         if (wfd_ie) {
3272             #ifdef CONFIG_DEBUG_CFG80211
3273             RTW_INFO("probe_req_wfd_ielen=%d\n", wfd_ielen);
3274             #endif
3275 
3276             if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_PROBE_REQ_IE, wfd_ie, wfd_ielen) != _SUCCESS)
3277                 return -EINVAL;
3278         }
3279         #endif /* CONFIG_WFD */
3280 
3281         #ifdef CONFIG_RTW_MBO
3282         rtw_mbo_update_ie_data(padapter, buf, len);
3283         #endif
3284     }
3285 
3286     return ret;
3287 
3288 }
3289 
3290 #ifdef CONFIG_CONCURRENT_MODE
rtw_cfg80211_scan_via_buddy(_adapter * padapter,struct cfg80211_scan_request * request)3291 u8 rtw_cfg80211_scan_via_buddy(_adapter *padapter, struct cfg80211_scan_request *request)
3292 {
3293     int i;
3294     u8 ret = _FALSE;
3295     _adapter *iface = NULL;
3296     _irqL    irqL;
3297     struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3298     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
3299     struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3300 
3301     for (i = 0; i < dvobj->iface_nums; i++) {
3302         struct mlme_priv *buddy_mlmepriv;
3303         struct rtw_wdev_priv *buddy_wdev_priv;
3304 
3305         iface = dvobj->padapters[i];
3306         if (iface == NULL)
3307             continue;
3308 
3309         if (iface == padapter)
3310             continue;
3311 
3312         if (rtw_is_adapter_up(iface) == _FALSE)
3313             continue;
3314 
3315         buddy_mlmepriv = &iface->mlmepriv;
3316         if (!check_fwstate(buddy_mlmepriv, WIFI_UNDER_SURVEY))
3317             continue;
3318 
3319         buddy_wdev_priv = adapter_wdev_data(iface);
3320         _enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
3321         _enter_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);
3322         if (buddy_wdev_priv->scan_request) {
3323             pmlmepriv->scanning_via_buddy_intf = _TRUE;
3324             _enter_critical_bh(&pmlmepriv->lock, &irqL);
3325             set_fwstate(pmlmepriv, WIFI_UNDER_SURVEY);
3326             _exit_critical_bh(&pmlmepriv->lock, &irqL);
3327             pwdev_priv->scan_request = request;
3328             ret = _TRUE;
3329         }
3330         _exit_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);
3331         _exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
3332 
3333         if (ret == _TRUE)
3334             goto exit;
3335     }
3336 
3337 exit:
3338     return ret;
3339 }
3340 
rtw_cfg80211_indicate_scan_done_for_buddy(_adapter * padapter,bool bscan_aborted)3341 void rtw_cfg80211_indicate_scan_done_for_buddy(_adapter *padapter, bool bscan_aborted)
3342 {
3343     int i;
3344     _adapter *iface = NULL;
3345     _irqL    irqL;
3346     struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3347     struct mlme_priv *mlmepriv;
3348     struct rtw_wdev_priv *wdev_priv;
3349     bool indicate_buddy_scan;
3350 
3351     for (i = 0; i < dvobj->iface_nums; i++) {
3352         iface = dvobj->padapters[i];
3353         if ((iface) && rtw_is_adapter_up(iface)) {
3354 
3355             if (iface == padapter)
3356                 continue;
3357 
3358             mlmepriv = &(iface->mlmepriv);
3359             wdev_priv = adapter_wdev_data(iface);
3360 
3361             indicate_buddy_scan = _FALSE;
3362             _enter_critical_bh(&wdev_priv->scan_req_lock, &irqL);
3363             if (mlmepriv->scanning_via_buddy_intf == _TRUE) {
3364                 mlmepriv->scanning_via_buddy_intf = _FALSE;
3365                 clr_fwstate(mlmepriv, WIFI_UNDER_SURVEY);
3366                 if (wdev_priv->scan_request)
3367                     indicate_buddy_scan = _TRUE;
3368             }
3369             _exit_critical_bh(&wdev_priv->scan_req_lock, &irqL);
3370 
3371             if (indicate_buddy_scan == _TRUE) {
3372                 rtw_cfg80211_surveydone_event_callback(iface);
3373                 rtw_indicate_scan_done(iface, bscan_aborted);
3374             }
3375 
3376         }
3377     }
3378 }
3379 #endif /* CONFIG_CONCURRENT_MODE */
3380 
3381 #ifndef CONFIG_RTL8822CS_WIFI_HDF
3382 static
3383 #endif
cfg80211_rtw_scan(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_scan_request * request)3384 int cfg80211_rtw_scan(struct wiphy *wiphy
3385     #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
3386     , struct net_device *ndev
3387     #endif
3388     , struct cfg80211_scan_request *request)
3389 {
3390     int i;
3391     u8 _status = _FALSE;
3392     int ret = 0;
3393     struct sitesurvey_parm parm;
3394     _irqL    irqL;
3395     u8 survey_times = 3;
3396     u8 survey_times_for_one_ch = 6;
3397     struct cfg80211_ssid *ssids = request->ssids;
3398     int social_channel = 0, j = 0;
3399     bool need_indicate_scan_done = _FALSE;
3400     bool ps_denied = _FALSE;
3401     u8 ssc_chk;
3402     _adapter *padapter;
3403     struct wireless_dev *wdev;
3404     struct rtw_wdev_priv *pwdev_priv;
3405     struct mlme_priv *pmlmepriv = NULL;
3406 #ifdef CONFIG_P2P
3407     struct wifidirect_info *pwdinfo;
3408 #endif /* CONFIG_P2P */
3409 
3410 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
3411     wdev = request->wdev;
3412     #if defined(RTW_DEDICATED_P2P_DEVICE)
3413     if (wdev == wiphy_to_pd_wdev(wiphy))
3414         padapter = wiphy_to_adapter(wiphy);
3415     else
3416     #endif
3417     if (wdev_to_ndev(wdev))
3418         padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
3419     else {
3420         ret = -EINVAL;
3421         goto exit;
3422     }
3423 #else
3424     if (ndev == NULL) {
3425         ret = -EINVAL;
3426         goto exit;
3427     }
3428     padapter = (_adapter *)rtw_netdev_priv(ndev);
3429     wdev = ndev_to_wdev(ndev);
3430 #endif
3431 
3432     pwdev_priv = adapter_wdev_data(padapter);
3433     pmlmepriv = &padapter->mlmepriv;
3434 #ifdef CONFIG_P2P
3435     pwdinfo = &(padapter->wdinfo);
3436 #endif /* CONFIG_P2P */
3437 
3438     RTW_INFO(FUNC_ADPT_FMT"%s\n", FUNC_ADPT_ARG(padapter)
3439         , wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : "");
3440 
3441 #ifdef CONFIG_RTW_SCAN_RAND
3442 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
3443     if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
3444         get_random_mask_addr(pwdev_priv->pno_mac_addr, request->mac_addr,
3445                      request->mac_addr_mask);
3446         print_hex_dump(KERN_DEBUG, "random mac_addr: ",
3447             DUMP_PREFIX_OFFSET, 16, 1, pwdev_priv->pno_mac_addr, ETH_ALEN, 1);
3448     }
3449     else
3450         memset(pwdev_priv->pno_mac_addr, 0xFF, ETH_ALEN);
3451 
3452 #endif
3453 #endif
3454 
3455 
3456 #if 1
3457     ssc_chk = rtw_sitesurvey_condition_check(padapter, _TRUE);
3458 
3459     if (ssc_chk == SS_DENY_MP_MODE)
3460         goto bypass_p2p_chk;
3461 #ifdef DBG_LA_MODE
3462     if (ssc_chk == SS_DENY_LA_MODE)
3463         goto bypass_p2p_chk;
3464 #endif
3465 #ifdef CONFIG_P2P
3466     if (pwdinfo->driver_interface == DRIVER_CFG80211) {
3467         if (request->n_ssids && ssids
3468             && _rtw_memcmp(ssids[0].ssid, "DIRECT-", 7)
3469             && rtw_get_p2p_ie((u8 *)request->ie, request->ie_len, NULL, NULL)
3470         ) {
3471             if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3472                 if (!rtw_p2p_enable(padapter, P2P_ROLE_DEVICE)) {
3473                     ret = -EOPNOTSUPP;
3474                     goto exit;
3475                 }
3476             } else {
3477                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3478                 #ifdef CONFIG_DEBUG_CFG80211
3479                 RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
3480                 #endif
3481             }
3482             rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3483 
3484             if (request->n_channels == 3 &&
3485                 request->channels[0]->hw_value == 1 &&
3486                 request->channels[1]->hw_value == 6 &&
3487                 request->channels[2]->hw_value == 11
3488             )
3489                 social_channel = 1;
3490         }
3491     }
3492 #endif /*CONFIG_P2P*/
3493 
3494     if (request->ie && request->ie_len > 0)
3495         rtw_cfg80211_set_probe_req_wpsp2pie(padapter, (u8 *)request->ie, request->ie_len);
3496 
3497 bypass_p2p_chk:
3498 
3499     switch (ssc_chk) {
3500         case SS_ALLOW :
3501             break;
3502 
3503         case SS_DENY_MP_MODE:
3504             ret = -EPERM;
3505             goto exit;
3506         #ifdef DBG_LA_MODE
3507         case SS_DENY_LA_MODE:
3508             ret = -EPERM;
3509             goto exit;
3510         #endif
3511         #ifdef CONFIG_RTW_REPEATER_SON
3512         case SS_DENY_RSON_SCANING :
3513         #endif
3514         case SS_DENY_BLOCK_SCAN :
3515         case SS_DENY_SELF_AP_UNDER_WPS :
3516         case SS_DENY_SELF_AP_UNDER_LINKING :
3517         case SS_DENY_SELF_AP_UNDER_SURVEY :
3518         case SS_DENY_SELF_STA_UNDER_SURVEY :
3519         #ifdef CONFIG_CONCURRENT_MODE
3520         case SS_DENY_BUDDY_UNDER_LINK_WPS :
3521         #endif
3522         case SS_DENY_BUSY_TRAFFIC :
3523         case SS_DENY_ADAPTIVITY:
3524             need_indicate_scan_done = _TRUE;
3525             goto check_need_indicate_scan_done;
3526 
3527         case SS_DENY_BY_DRV :
3528             #ifdef CONFIG_NOTIFY_SCAN_ABORT_WITH_BUSY
3529             ret = -EBUSY;
3530             goto exit;
3531             #else
3532             need_indicate_scan_done = _TRUE;
3533             goto check_need_indicate_scan_done;
3534             #endif
3535             break;
3536 
3537         case SS_DENY_SELF_STA_UNDER_LINKING :
3538             ret = -EBUSY;
3539             goto check_need_indicate_scan_done;
3540 
3541         #ifdef CONFIG_CONCURRENT_MODE
3542         case SS_DENY_BUDDY_UNDER_SURVEY :
3543             {
3544                 bool scan_via_buddy = rtw_cfg80211_scan_via_buddy(padapter, request);
3545 
3546                 if (scan_via_buddy == _FALSE)
3547                     need_indicate_scan_done = _TRUE;
3548 
3549                 goto check_need_indicate_scan_done;
3550             }
3551         #endif
3552 
3553         default :
3554             RTW_ERR("site survey check code (%d) unknown\n", ssc_chk);
3555             need_indicate_scan_done = _TRUE;
3556             goto check_need_indicate_scan_done;
3557     }
3558 
3559     rtw_ps_deny(padapter, PS_DENY_SCAN);
3560     ps_denied = _TRUE;
3561     if (_FAIL == rtw_pwr_wakeup(padapter)) {
3562         need_indicate_scan_done = _TRUE;
3563         goto check_need_indicate_scan_done;
3564     }
3565 
3566 #else
3567 
3568 
3569 #ifdef CONFIG_MP_INCLUDED
3570     if (rtw_mp_mode_check(padapter)) {
3571         RTW_INFO("MP mode block Scan request\n");
3572         ret = -EPERM;
3573         goto exit;
3574     }
3575 #endif
3576 
3577 #ifdef CONFIG_P2P
3578     if (pwdinfo->driver_interface == DRIVER_CFG80211) {
3579         if (request->n_ssids && ssids
3580             && _rtw_memcmp(ssids[0].ssid, "DIRECT-", 7)
3581             && rtw_get_p2p_ie((u8 *)request->ie, request->ie_len, NULL, NULL)
3582         ) {
3583             if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
3584                 rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);
3585             else {
3586                 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3587                 #ifdef CONFIG_DEBUG_CFG80211
3588                 RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
3589                 #endif
3590             }
3591             rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3592 
3593             if (request->n_channels == 3 &&
3594                 request->channels[0]->hw_value == 1 &&
3595                 request->channels[1]->hw_value == 6 &&
3596                 request->channels[2]->hw_value == 11
3597             )
3598                 social_channel = 1;
3599         }
3600     }
3601 #endif /*CONFIG_P2P*/
3602 
3603     if (request->ie && request->ie_len > 0)
3604         rtw_cfg80211_set_probe_req_wpsp2pie(padapter, (u8 *)request->ie, request->ie_len);
3605 
3606 #ifdef CONFIG_RTW_REPEATER_SON
3607     if (padapter->rtw_rson_scanstage == RSON_SCAN_PROCESS) {
3608         RTW_INFO(FUNC_ADPT_FMT" blocking scan for under rson scanning process\n", FUNC_ADPT_ARG(padapter));
3609         need_indicate_scan_done = _TRUE;
3610         goto check_need_indicate_scan_done;
3611     }
3612 #endif
3613 
3614     if (adapter_wdev_data(padapter)->block_scan == _TRUE) {
3615         RTW_INFO(FUNC_ADPT_FMT" wdev_priv.block_scan is set\n", FUNC_ADPT_ARG(padapter));
3616         need_indicate_scan_done = _TRUE;
3617         goto check_need_indicate_scan_done;
3618     }
3619 
3620     rtw_ps_deny(padapter, PS_DENY_SCAN);
3621     ps_denied = _TRUE;
3622     if (_FAIL == rtw_pwr_wakeup(padapter)) {
3623         need_indicate_scan_done = _TRUE;
3624         goto check_need_indicate_scan_done;
3625     }
3626 
3627     if (rtw_is_scan_deny(padapter)) {
3628         RTW_INFO(FUNC_ADPT_FMT    ": scan deny\n", FUNC_ADPT_ARG(padapter));
3629 #ifdef CONFIG_NOTIFY_SCAN_ABORT_WITH_BUSY
3630         ret = -EBUSY;
3631         goto exit;
3632 #else
3633         need_indicate_scan_done = _TRUE;
3634         goto check_need_indicate_scan_done;
3635 #endif
3636     }
3637 
3638     /* check fw state*/
3639     if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) {
3640 
3641 #ifdef CONFIG_DEBUG_CFG80211
3642         RTW_INFO(FUNC_ADPT_FMT" under WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter));
3643 #endif
3644 
3645         if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS | WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING) == _TRUE) {
3646             RTW_INFO("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);
3647 
3648             if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS))
3649                 RTW_INFO("AP mode process WPS\n");
3650 
3651             need_indicate_scan_done = _TRUE;
3652             goto check_need_indicate_scan_done;
3653         }
3654     }
3655 
3656     if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY) == _TRUE) {
3657         RTW_INFO("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);
3658         need_indicate_scan_done = _TRUE;
3659         goto check_need_indicate_scan_done;
3660     } else if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING) == _TRUE) {
3661         RTW_INFO("%s, fwstate=0x%x\n", __func__, pmlmepriv->fw_state);
3662         ret = -EBUSY;
3663         goto check_need_indicate_scan_done;
3664     }
3665 
3666 #ifdef CONFIG_CONCURRENT_MODE
3667     if (rtw_mi_buddy_check_fwstate(padapter, WIFI_UNDER_LINKING | WIFI_UNDER_WPS)) {
3668         RTW_INFO("%s exit due to buddy_intf's mlme state under linking or wps\n", __func__);
3669         need_indicate_scan_done = _TRUE;
3670         goto check_need_indicate_scan_done;
3671 
3672     } else if (rtw_mi_buddy_check_fwstate(padapter, WIFI_UNDER_SURVEY)) {
3673         bool scan_via_buddy = rtw_cfg80211_scan_via_buddy(padapter, request);
3674 
3675         if (scan_via_buddy == _FALSE)
3676             need_indicate_scan_done = _TRUE;
3677 
3678         goto check_need_indicate_scan_done;
3679     }
3680 #endif /* CONFIG_CONCURRENT_MODE */
3681 
3682 #ifdef RTW_BUSY_DENY_SCAN
3683     /*
3684      * busy traffic check
3685      * Rules:
3686      * 1. If (scan interval <= BUSY_TRAFFIC_SCAN_DENY_PERIOD) always allow
3687      *    scan, otherwise goto rule 2.
3688      * 2. Deny scan if any interface is busy, otherwise allow scan.
3689      */
3690     if (pmlmepriv->lastscantime
3691         && (rtw_get_passing_time_ms(pmlmepriv->lastscantime) >
3692         registry_par->scan_interval_thr)
3693         && rtw_mi_busy_traffic_check(padapter)) {
3694         RTW_WARN(FUNC_ADPT_FMT ": scan abort!! BusyTraffic\n",
3695              FUNC_ADPT_ARG(padapter));
3696          need_indicate_scan_done = _TRUE;
3697         goto check_need_indicate_scan_done;
3698     }
3699 #endif /* RTW_BUSY_DENY_SCAN */
3700 #endif
3701 
3702 #ifdef CONFIG_P2P
3703     if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
3704         rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
3705 
3706         if (social_channel == 0)
3707             rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
3708         else
3709             rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_SOCIAL_LAST);
3710     }
3711 #endif /* CONFIG_P2P */
3712 
3713     rtw_init_sitesurvey_parm(padapter, &parm);
3714 
3715     /* parsing request ssids, n_ssids */
3716     for (i = 0; i < request->n_ssids && ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
3717         #ifdef CONFIG_DEBUG_CFG80211
3718         RTW_INFO("ssid=%s, len=%d\n", ssids[i].ssid, ssids[i].ssid_len);
3719         #endif
3720         _rtw_memcpy(&parm.ssid[i].Ssid, ssids[i].ssid, ssids[i].ssid_len);
3721         parm.ssid[i].SsidLength = ssids[i].ssid_len;
3722     }
3723     parm.ssid_num = i;
3724 
3725     /* no ssid entry, set the scan type as passvie */
3726     if (request->n_ssids == 0)
3727         parm.scan_mode = SCAN_PASSIVE;
3728 
3729     /* parsing channels, n_channels */
3730     for (i = 0; i < request->n_channels && i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
3731         #ifdef CONFIG_DEBUG_CFG80211
3732         RTW_INFO(FUNC_ADPT_FMT CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(request->channels[i]));
3733         #endif
3734         parm.ch[i].hw_value = request->channels[i]->hw_value;
3735         parm.ch[i].flags = request->channels[i]->flags;
3736     }
3737     parm.ch_num = i;
3738 
3739     if (request->n_channels == 1) {
3740         for (i = 1; i < survey_times_for_one_ch; i++)
3741             _rtw_memcpy(&parm.ch[i], &parm.ch[0], sizeof(struct rtw_ieee80211_channel));
3742         parm.ch_num = survey_times_for_one_ch;
3743     } else if (request->n_channels <= 4) {
3744         for (j = request->n_channels - 1; j >= 0; j--)
3745             for (i = 0; i < survey_times; i++)
3746                 _rtw_memcpy(&parm.ch[j * survey_times + i], &parm.ch[j], sizeof(struct rtw_ieee80211_channel));
3747         parm.ch_num = survey_times * request->n_channels;
3748     }
3749 
3750     _enter_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
3751     _enter_critical_bh(&pmlmepriv->lock, &irqL);
3752     _status = rtw_sitesurvey_cmd(padapter, &parm);
3753     if (_status == _SUCCESS)
3754         pwdev_priv->scan_request = request;
3755     else
3756         ret = -1;
3757     _exit_critical_bh(&pmlmepriv->lock, &irqL);
3758     _exit_critical_bh(&pwdev_priv->scan_req_lock, &irqL);
3759 
3760 check_need_indicate_scan_done:
3761     if (_TRUE == need_indicate_scan_done) {
3762 #if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE)
3763         struct cfg80211_scan_info info;
3764 
3765         memset(&info, 0, sizeof(info));
3766         info.aborted = 0;
3767 #endif
3768         /* the process time of scan results must be over at least 1ms in the newly Android */
3769         rtw_msleep_os(1);
3770 
3771         _rtw_cfg80211_surveydone_event_callback(padapter, request);
3772 #if (KERNEL_VERSION(4, 8, 0) <= LINUX_VERSION_CODE)
3773 #ifdef CONFIG_RTL8822CS_WIFI_HDF
3774         HdfWifiEventScanDone(get_rtl_netdev(), 0);
3775         WifiScanFree(&request);
3776 #else
3777         cfg80211_scan_done(request, &info);
3778 #endif
3779 #else
3780         cfg80211_scan_done(request, 0);
3781 #endif
3782     }
3783 
3784     if (ps_denied == _TRUE)
3785         rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
3786 
3787 exit:
3788 #ifdef RTW_BUSY_DENY_SCAN
3789     if (pmlmepriv)
3790         pmlmepriv->lastscantime = rtw_get_current_time();
3791 #endif
3792 
3793     return ret;
3794 }
3795 
3796 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
cfg80211_rtw_abort_scan(struct wiphy * wiphy,struct wireless_dev * wdev)3797 static void cfg80211_rtw_abort_scan(struct wiphy *wiphy,
3798                     struct wireless_dev *wdev)
3799 {
3800     _adapter *padapter = wiphy_to_adapter(wiphy);
3801 
3802     RTW_INFO("=>"FUNC_ADPT_FMT" - Abort Scan\n", FUNC_ADPT_ARG(padapter));
3803     if (wdev->iftype != NL80211_IFTYPE_STATION) {
3804         RTW_ERR("abort scan ignored, iftype(%d)\n", wdev->iftype);
3805         return;
3806     }
3807     rtw_scan_abort(padapter);
3808 }
3809 #endif
3810 
cfg80211_rtw_set_wiphy_params(struct wiphy * wiphy,u32 changed)3811 static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
3812 {
3813 #if 0
3814     struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
3815 
3816     if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
3817         (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
3818         int ret;
3819 
3820         iwm->conf.rts_threshold = wiphy->rts_threshold;
3821 
3822         ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
3823                 CFG_RTS_THRESHOLD,
3824                 iwm->conf.rts_threshold);
3825         if (ret < 0)
3826             return ret;
3827     }
3828 
3829     if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
3830         (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
3831         int ret;
3832 
3833         iwm->conf.frag_threshold = wiphy->frag_threshold;
3834 
3835         ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
3836                 CFG_FRAG_THRESHOLD,
3837                 iwm->conf.frag_threshold);
3838         if (ret < 0)
3839             return ret;
3840     }
3841 #endif
3842     RTW_INFO("%s\n", __func__);
3843     return 0;
3844 }
3845 
3846 
3847 
rtw_cfg80211_set_wpa_version(struct security_priv * psecuritypriv,u32 wpa_version)3848 static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv, u32 wpa_version)
3849 {
3850     RTW_INFO("%s, wpa_version=%d\n", __func__, wpa_version);
3851 
3852     if (!wpa_version) {
3853         psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
3854         return 0;
3855     }
3856 
3857 
3858     if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
3859         psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
3860 
3861 #if 0
3862     if (wpa_version & NL80211_WPA_VERSION_2)
3863         psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
3864 #endif
3865 
3866     #ifdef CONFIG_WAPI_SUPPORT
3867     if (wpa_version & NL80211_WAPI_VERSION_1)
3868         psecuritypriv->ndisauthtype = Ndis802_11AuthModeWAPI;
3869     #endif
3870 
3871     return 0;
3872 
3873 }
3874 
rtw_cfg80211_set_auth_type(struct security_priv * psecuritypriv,enum nl80211_auth_type sme_auth_type)3875 static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
3876         enum nl80211_auth_type sme_auth_type)
3877 {
3878     RTW_INFO("%s, nl80211_auth_type=%d\n", __func__, sme_auth_type);
3879 
3880 #ifndef CONFIG_KERNEL_PATCH_EXTERNAL_AUTH
3881     if (NL80211_AUTHTYPE_MAX <= (int)MLME_AUTHTYPE_SAE) {
3882         if (MLME_AUTHTYPE_SAE == psecuritypriv->auth_type) {
3883             /* This case pre handle in
3884              * rtw_check_connect_sae_compat()
3885              */
3886             psecuritypriv->auth_alg = WLAN_AUTH_SAE;
3887             return 0;
3888         }
3889     } else
3890 #endif
3891     if (sme_auth_type == (int)MLME_AUTHTYPE_SAE) {
3892         psecuritypriv->auth_type = MLME_AUTHTYPE_SAE;
3893         psecuritypriv->auth_alg = WLAN_AUTH_SAE;
3894         return 0;
3895     }
3896 
3897     psecuritypriv->auth_type = sme_auth_type;
3898 
3899     switch (sme_auth_type) {
3900     case NL80211_AUTHTYPE_AUTOMATIC:
3901 
3902         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
3903 
3904         break;
3905     case NL80211_AUTHTYPE_OPEN_SYSTEM:
3906 
3907         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
3908 
3909         if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)
3910             psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
3911 
3912 #ifdef CONFIG_WAPI_SUPPORT
3913         if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWAPI)
3914             psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
3915 #endif
3916 
3917         break;
3918     case NL80211_AUTHTYPE_SHARED_KEY:
3919 
3920         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
3921 
3922         psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
3923 
3924 
3925         break;
3926     default:
3927         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
3928         /* return -ENOTSUPP; */
3929     }
3930 
3931     return 0;
3932 
3933 }
3934 
rtw_cfg80211_set_cipher(struct security_priv * psecuritypriv,u32 cipher,bool ucast)3935 static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv, u32 cipher, bool ucast)
3936 {
3937     u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
3938 
3939     u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
3940         &psecuritypriv->dot118021XGrpPrivacy;
3941 
3942     RTW_INFO("%s, ucast=%d, cipher=0x%x\n", __func__, ucast, cipher);
3943 
3944 
3945     if (!cipher) {
3946         *profile_cipher = _NO_PRIVACY_;
3947         psecuritypriv->ndisencryptstatus = ndisencryptstatus;
3948         return 0;
3949     }
3950 
3951     switch (cipher) {
3952     case IW_AUTH_CIPHER_NONE:
3953         *profile_cipher = _NO_PRIVACY_;
3954         ndisencryptstatus = Ndis802_11EncryptionDisabled;
3955 #ifdef CONFIG_WAPI_SUPPORT
3956         if (psecuritypriv->dot11PrivacyAlgrthm == _SMS4_)
3957             *profile_cipher = _SMS4_;
3958 #endif
3959         break;
3960     case WLAN_CIPHER_SUITE_WEP40:
3961         *profile_cipher = _WEP40_;
3962         ndisencryptstatus = Ndis802_11Encryption1Enabled;
3963         break;
3964     case WLAN_CIPHER_SUITE_WEP104:
3965         *profile_cipher = _WEP104_;
3966         ndisencryptstatus = Ndis802_11Encryption1Enabled;
3967         break;
3968     case WLAN_CIPHER_SUITE_TKIP:
3969         *profile_cipher = _TKIP_;
3970         ndisencryptstatus = Ndis802_11Encryption2Enabled;
3971         break;
3972     case WLAN_CIPHER_SUITE_CCMP:
3973         *profile_cipher = _AES_;
3974         ndisencryptstatus = Ndis802_11Encryption3Enabled;
3975         break;
3976     case WIFI_CIPHER_SUITE_GCMP:
3977         *profile_cipher = _GCMP_;
3978         ndisencryptstatus = Ndis802_11Encryption3Enabled;
3979         break;
3980     case WIFI_CIPHER_SUITE_GCMP_256:
3981         *profile_cipher = _GCMP_256_;
3982         ndisencryptstatus = Ndis802_11Encryption3Enabled;
3983         break;
3984     case WIFI_CIPHER_SUITE_CCMP_256:
3985         *profile_cipher = _CCMP_256_;
3986         ndisencryptstatus = Ndis802_11Encryption3Enabled;
3987         break;
3988 #ifdef CONFIG_WAPI_SUPPORT
3989     case WLAN_CIPHER_SUITE_SMS4:
3990         *profile_cipher = _SMS4_;
3991         ndisencryptstatus = Ndis802_11_EncrypteionWAPI;
3992         break;
3993 #endif
3994     default:
3995         RTW_INFO("Unsupported cipher: 0x%x\n", cipher);
3996         return -ENOTSUPP;
3997     }
3998 
3999     if (ucast) {
4000         psecuritypriv->ndisencryptstatus = ndisencryptstatus;
4001 
4002         /* if(psecuritypriv->dot11PrivacyAlgrthm >= _AES_) */
4003         /*    psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK; */
4004     }
4005 
4006     return 0;
4007 }
4008 
rtw_cfg80211_set_key_mgt(struct security_priv * psecuritypriv,u32 key_mgt)4009 static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv, u32 key_mgt)
4010 {
4011     RTW_INFO("%s, key_mgt=0x%x\n", __func__, key_mgt);
4012 
4013     if (key_mgt == WLAN_AKM_SUITE_8021X) {
4014         /* *auth_type = UMAC_AUTH_TYPE_8021X; */
4015         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
4016         psecuritypriv->rsn_akm_suite_type = 1;
4017     } else if (key_mgt == WLAN_AKM_SUITE_PSK) {
4018         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
4019         psecuritypriv->rsn_akm_suite_type = 2;
4020     }
4021 #ifdef CONFIG_WAPI_SUPPORT
4022     else if (key_mgt == WLAN_AKM_SUITE_WAPI_PSK)
4023         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
4024     else if (key_mgt == WLAN_AKM_SUITE_WAPI_CERT)
4025         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_WAPI;
4026 #endif
4027 #ifdef CONFIG_RTW_80211R
4028     else if (key_mgt == WLAN_AKM_SUITE_FT_8021X) {
4029         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
4030         psecuritypriv->rsn_akm_suite_type = 3;
4031     } else if (key_mgt == WLAN_AKM_SUITE_FT_PSK) {
4032         psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
4033         psecuritypriv->rsn_akm_suite_type = 4;
4034     } else if ((key_mgt == WLAN_AKM_SUITE_FT_OVER_SAE)
4035         || (key_mgt == WLAN_AKM_SUITE_FT_FILS_SHA256)
4036         ) {
4037         RTW_INFO("FT-SAE key mgt: 0x%x\n", key_mgt);
4038         if (key_mgt == WLAN_AKM_SUITE_FT_OVER_SAE)
4039             psecuritypriv->rsn_akm_suite_type = 9;
4040     }
4041 #endif
4042     else if (key_mgt == WLAN_AKM_SUITE_SAE) {
4043         psecuritypriv->rsn_akm_suite_type = 8;
4044     } else {
4045         RTW_INFO("Invalid key mgt: 0x%x\n", key_mgt);
4046         /* return -EINVAL; */
4047     }
4048 
4049     return 0;
4050 }
4051 
rtw_cfg80211_set_wpa_ie(_adapter * padapter,u8 * pie,size_t ielen)4052 static int rtw_cfg80211_set_wpa_ie(_adapter *padapter, u8 *pie, size_t ielen)
4053 {
4054     u8 *buf = NULL, *pos = NULL;
4055     int group_cipher = 0, pairwise_cipher = 0;
4056     u8 mfp_opt = MFP_NO;
4057     int ret = 0;
4058     int wpa_ielen = 0;
4059     int wpa2_ielen = 0;
4060     int rsnx_ielen = 0;
4061     u8 *pwpa, *pwpa2, *prsnx;
4062     u8 null_addr[] = {0, 0, 0, 0, 0, 0};
4063 
4064     if (pie == NULL || !ielen) {
4065         /* Treat this as normal case, but need to clear WIFI_UNDER_WPS */
4066         _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
4067         goto exit;
4068     }
4069 
4070     if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {
4071         ret = -EINVAL;
4072         goto exit;
4073     }
4074 
4075     buf = rtw_zmalloc(ielen);
4076     if (buf == NULL) {
4077         ret =  -ENOMEM;
4078         goto exit;
4079     }
4080 
4081     _rtw_memcpy(buf, pie , ielen);
4082 
4083     RTW_INFO("set wpa_ie(length:%zu):\n", ielen);
4084     RTW_INFO_DUMP(NULL, buf, ielen);
4085 
4086     pos = buf;
4087     if (ielen < RSN_HEADER_LEN) {
4088         ret  = -1;
4089         goto exit;
4090     }
4091 
4092     pwpa = rtw_get_wpa_ie(buf, &wpa_ielen, ielen);
4093     if (pwpa && wpa_ielen > 0) {
4094         if (rtw_parse_wpa_ie(pwpa, wpa_ielen + 2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
4095             padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
4096             padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPAPSK;
4097             _rtw_memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0], wpa_ielen + 2);
4098 
4099             RTW_INFO("got wpa_ie, wpa_ielen:%u\n", wpa_ielen);
4100         }
4101     }
4102 
4103     pwpa2 = rtw_get_wpa2_ie(buf, &wpa2_ielen, ielen);
4104     if (pwpa2 && wpa2_ielen > 0) {
4105         if (rtw_parse_wpa2_ie(pwpa2, wpa2_ielen + 2, &group_cipher, &pairwise_cipher, NULL, NULL, &mfp_opt, NULL) == _SUCCESS) {
4106             padapter->securitypriv.dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
4107             padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeWPA2PSK;
4108             _rtw_memcpy(padapter->securitypriv.supplicant_ie, &pwpa2[0], wpa2_ielen + 2);
4109 
4110             RTW_INFO("got wpa2_ie, wpa2_ielen:%u\n", wpa2_ielen);
4111         }
4112 
4113         prsnx = rtw_get_ie(buf, WLAN_EID_RSNX, &rsnx_ielen, ielen);
4114         if (prsnx && (rsnx_ielen > 0)) {
4115             if ((rsnx_ielen + 2) <= MAX_RSNX_IE_LEN) {
4116                 _rtw_memset(padapter->securitypriv.rsnx_ie, 0,
4117                     MAX_RSNX_IE_LEN);
4118                 padapter->securitypriv.rsnx_ie_len = \
4119                     (rsnx_ielen + 2);
4120                 _rtw_memcpy(padapter->securitypriv.rsnx_ie,
4121                     prsnx,
4122                 padapter->securitypriv.rsnx_ie_len);
4123             } else
4124                 RTW_ERR("%s:no more buf to save RSNX Cap!\n",
4125                     __func__);
4126         } else {
4127             _rtw_memset(padapter->securitypriv.rsnx_ie, 0,
4128                     MAX_RSNX_IE_LEN);
4129             padapter->securitypriv.rsnx_ie_len = 0;
4130         }
4131     } /* end of (pwpa2 && wpa2_ielen > 0) */
4132 
4133     if (group_cipher == 0)
4134         group_cipher = WPA_CIPHER_NONE;
4135     if (pairwise_cipher == 0)
4136         pairwise_cipher = WPA_CIPHER_NONE;
4137 
4138     switch (group_cipher) {
4139     case WPA_CIPHER_NONE:
4140         padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
4141         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
4142         break;
4143     case WPA_CIPHER_WEP40:
4144         padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
4145         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
4146         break;
4147     case WPA_CIPHER_TKIP:
4148         padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
4149         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
4150         break;
4151     case WPA_CIPHER_CCMP:
4152         padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
4153         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4154         break;
4155     case WPA_CIPHER_GCMP:
4156         padapter->securitypriv.dot118021XGrpPrivacy = _GCMP_;
4157         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4158         break;
4159     case WPA_CIPHER_GCMP_256:
4160         padapter->securitypriv.dot118021XGrpPrivacy = _GCMP_256_;
4161         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4162         break;
4163     case WPA_CIPHER_CCMP_256:
4164         padapter->securitypriv.dot118021XGrpPrivacy = _CCMP_256_;
4165         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4166         break;
4167     case WPA_CIPHER_WEP104:
4168         padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
4169         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
4170         break;
4171     }
4172 
4173     switch (pairwise_cipher) {
4174     case WPA_CIPHER_NONE:
4175         padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
4176         padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
4177         break;
4178     case WPA_CIPHER_WEP40:
4179         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
4180         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
4181         break;
4182     case WPA_CIPHER_TKIP:
4183         padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
4184         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
4185         break;
4186     case WPA_CIPHER_CCMP:
4187         padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
4188         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4189         break;
4190     case WPA_CIPHER_GCMP:
4191         padapter->securitypriv.dot11PrivacyAlgrthm = _GCMP_;
4192         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4193         break;
4194     case WPA_CIPHER_GCMP_256:
4195         padapter->securitypriv.dot11PrivacyAlgrthm = _GCMP_256_;
4196         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4197         break;
4198     case WPA_CIPHER_CCMP_256:
4199         padapter->securitypriv.dot11PrivacyAlgrthm = _CCMP_256_;
4200         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
4201         break;
4202     case WPA_CIPHER_WEP104:
4203         padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
4204         padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
4205         break;
4206     }
4207 
4208     if (mfp_opt == MFP_INVALID) {
4209         RTW_INFO(FUNC_ADPT_FMT" invalid MFP setting\n", FUNC_ADPT_ARG(padapter));
4210         ret = -EINVAL;
4211         goto exit;
4212     }
4213     padapter->securitypriv.mfp_opt = mfp_opt;
4214 
4215     {/* handle wps_ie */
4216         uint wps_ielen;
4217         u8 *wps_ie;
4218 
4219         wps_ie = rtw_get_wps_ie(buf, ielen, NULL, &wps_ielen);
4220         if (wps_ie && wps_ielen > 0) {
4221             RTW_INFO("got wps_ie, wps_ielen:%u\n", wps_ielen);
4222             padapter->securitypriv.wps_ie_len = wps_ielen < MAX_WPS_IE_LEN ? wps_ielen : MAX_WPS_IE_LEN;
4223             _rtw_memcpy(padapter->securitypriv.wps_ie, wps_ie, padapter->securitypriv.wps_ie_len);
4224             set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
4225         } else
4226             _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
4227     }
4228 
4229     {/* handle owe_ie */
4230         uint owe_ielen;
4231         u8 *owe_ie;
4232 
4233         owe_ie = rtw_get_owe_ie(buf, ielen, NULL, &owe_ielen);
4234         if (owe_ie && owe_ielen > 0) {
4235             RTW_INFO("got owe_ie, owe_ielen:%u\n", owe_ielen);
4236             padapter->securitypriv.owe_ie_len = owe_ielen < MAX_OWE_IE_LEN ? owe_ielen : MAX_OWE_IE_LEN;
4237             _rtw_memcpy(padapter->securitypriv.owe_ie, owe_ie, padapter->securitypriv.owe_ie_len);
4238         }
4239     }
4240 
4241     #ifdef CONFIG_P2P
4242     {/* check p2p_ie for assoc req; */
4243         uint p2p_ielen = 0;
4244         u8 *p2p_ie;
4245         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4246 
4247         p2p_ie = rtw_get_p2p_ie(buf, ielen, NULL, &p2p_ielen);
4248         if (p2p_ie) {
4249             #ifdef CONFIG_DEBUG_CFG80211
4250             RTW_INFO("%s p2p_assoc_req_ielen=%d\n", __FUNCTION__, p2p_ielen);
4251             #endif
4252 
4253             if (pmlmepriv->p2p_assoc_req_ie) {
4254                 u32 free_len = pmlmepriv->p2p_assoc_req_ie_len;
4255                 pmlmepriv->p2p_assoc_req_ie_len = 0;
4256                 rtw_mfree(pmlmepriv->p2p_assoc_req_ie, free_len);
4257                 pmlmepriv->p2p_assoc_req_ie = NULL;
4258             }
4259 
4260             pmlmepriv->p2p_assoc_req_ie = rtw_malloc(p2p_ielen);
4261             if (pmlmepriv->p2p_assoc_req_ie == NULL) {
4262                 RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
4263                 goto exit;
4264             }
4265             _rtw_memcpy(pmlmepriv->p2p_assoc_req_ie, p2p_ie, p2p_ielen);
4266             pmlmepriv->p2p_assoc_req_ie_len = p2p_ielen;
4267         }
4268     }
4269     #endif /* CONFIG_P2P */
4270 
4271     #ifdef CONFIG_WFD
4272     {
4273         uint wfd_ielen = 0;
4274         u8 *wfd_ie;
4275         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4276 
4277         wfd_ie = rtw_get_wfd_ie(buf, ielen, NULL, &wfd_ielen);
4278         if (wfd_ie) {
4279             #ifdef CONFIG_DEBUG_CFG80211
4280             RTW_INFO("%s wfd_assoc_req_ielen=%d\n", __FUNCTION__, wfd_ielen);
4281             #endif
4282 
4283             if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_ASSOC_REQ_IE, wfd_ie, wfd_ielen) != _SUCCESS)
4284                 goto exit;
4285         }
4286     }
4287     #endif /* CONFIG_WFD */
4288 
4289     #ifdef CONFIG_RTW_MULTI_AP
4290     padapter->multi_ap = rtw_get_multi_ap_ie_ext(buf, ielen) & MULTI_AP_BACKHAUL_STA;
4291     if (padapter->multi_ap)
4292         adapter_set_use_wds(padapter, 1);
4293     #endif
4294 
4295     /* TKIP and AES disallow multicast packets until installing group key */
4296     if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_
4297         || padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_
4298         || padapter->securitypriv.dot11PrivacyAlgrthm == _AES_
4299         || padapter->securitypriv.dot11PrivacyAlgrthm == _GCMP_
4300         || padapter->securitypriv.dot11PrivacyAlgrthm == _GCMP_256_
4301         || padapter->securitypriv.dot11PrivacyAlgrthm == _CCMP_256_)
4302         /* WPS open need to enable multicast */
4303         /* || check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == _TRUE) */
4304         rtw_hal_set_hwreg(padapter, HW_VAR_OFF_RCR_AM, null_addr);
4305 
4306 
4307 exit:
4308     if (buf)
4309         rtw_mfree(buf, ielen);
4310     if (ret)
4311         _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
4312 
4313     return ret;
4314 }
4315 
cfg80211_rtw_join_ibss(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_ibss_params * params)4316 static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
4317                   struct cfg80211_ibss_params *params)
4318 {
4319     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
4320     NDIS_802_11_SSID ndis_ssid;
4321     struct security_priv *psecuritypriv = &padapter->securitypriv;
4322     struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4323 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
4324     struct cfg80211_chan_def *pch_def;
4325 #endif
4326     struct ieee80211_channel *pch;
4327     int ret = 0;
4328 
4329 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
4330     pch_def = (struct cfg80211_chan_def *)(&params->chandef);
4331     pch = (struct ieee80211_channel *) pch_def->chan;
4332 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
4333     pch = (struct ieee80211_channel *)(params->channel);
4334 #endif
4335 
4336     if (!params->ssid || !params->ssid_len) {
4337         ret = -EINVAL;
4338         goto exit;
4339     }
4340 
4341     if (params->ssid_len > IW_ESSID_MAX_SIZE) {
4342         ret = -E2BIG;
4343         goto exit;
4344     }
4345 
4346     rtw_ps_deny(padapter, PS_DENY_JOIN);
4347     if (_FAIL == rtw_pwr_wakeup(padapter)) {
4348         ret = -EPERM;
4349         goto cancel_ps_deny;
4350     }
4351 
4352 #ifdef CONFIG_CONCURRENT_MODE
4353     if (rtw_mi_buddy_check_fwstate(padapter, WIFI_UNDER_LINKING)) {
4354         RTW_INFO("%s, but buddy_intf is under linking\n", __FUNCTION__);
4355         ret = -EINVAL;
4356         goto cancel_ps_deny;
4357     }
4358     rtw_mi_buddy_scan_abort(padapter, _TRUE); /* OR rtw_mi_scan_abort(padapter, _TRUE);*/
4359 #endif /*CONFIG_CONCURRENT_MODE*/
4360 
4361 
4362     _rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
4363     ndis_ssid.SsidLength = params->ssid_len;
4364     _rtw_memcpy(ndis_ssid.Ssid, (u8 *)params->ssid, params->ssid_len);
4365 
4366     /* RTW_INFO("ssid=%s, len=%zu\n", ndis_ssid.Ssid, params->ssid_len); */
4367 
4368     psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
4369     psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
4370     psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
4371     psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
4372     psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
4373 
4374     ret = rtw_cfg80211_set_auth_type(psecuritypriv, NL80211_AUTHTYPE_OPEN_SYSTEM);
4375     rtw_set_802_11_authentication_mode(padapter, psecuritypriv->ndisauthtype);
4376 
4377     RTW_INFO("%s: center_freq = %d\n", __func__, pch->center_freq);
4378     pmlmeext->cur_channel = rtw_freq2ch(pch->center_freq);
4379 
4380     if (rtw_set_802_11_ssid(padapter, &ndis_ssid) == _FALSE) {
4381         ret = -1;
4382         goto cancel_ps_deny;
4383     }
4384 
4385 cancel_ps_deny:
4386     rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
4387 exit:
4388     return ret;
4389 }
4390 
cfg80211_rtw_leave_ibss(struct wiphy * wiphy,struct net_device * ndev)4391 static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
4392 {
4393     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
4394     struct wireless_dev *rtw_wdev = padapter->rtw_wdev;
4395     enum nl80211_iftype old_type;
4396     int ret = 0;
4397 
4398     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
4399 
4400 #if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_DISCONNECT)
4401     rtw_wdev_set_not_indic_disco(adapter_wdev_data(padapter), 1);
4402 #endif
4403 
4404     old_type = rtw_wdev->iftype;
4405 
4406     rtw_set_to_roam(padapter, 0);
4407 
4408     if (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) {
4409         rtw_scan_abort(padapter);
4410         LeaveAllPowerSaveMode(padapter);
4411 
4412         rtw_wdev->iftype = NL80211_IFTYPE_STATION;
4413 
4414         if (rtw_set_802_11_infrastructure_mode(padapter, Ndis802_11Infrastructure, 0) == _FALSE) {
4415             rtw_wdev->iftype = old_type;
4416             ret = -EPERM;
4417             goto leave_ibss;
4418         }
4419         rtw_setopmode_cmd(padapter, Ndis802_11Infrastructure, RTW_CMDF_WAIT_ACK);
4420     }
4421 
4422 leave_ibss:
4423 #if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_DISCONNECT)
4424     rtw_wdev_set_not_indic_disco(adapter_wdev_data(padapter), 0);
4425 #endif
4426 
4427     return 0;
4428 }
4429 
rtw_cfg80211_is_connect_requested(_adapter * adapter)4430 bool rtw_cfg80211_is_connect_requested(_adapter *adapter)
4431 {
4432     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
4433     _irqL irqL;
4434     bool requested;
4435 
4436     _enter_critical_bh(&pwdev_priv->connect_req_lock, &irqL);
4437     requested = pwdev_priv->connect_req ? 1 : 0;
4438     _exit_critical_bh(&pwdev_priv->connect_req_lock, &irqL);
4439 
4440     return requested;
4441 }
4442 
_rtw_disconnect(struct wiphy * wiphy,struct net_device * ndev)4443 static int _rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev)
4444 {
4445     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
4446 
4447 
4448     /* if(check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) */
4449     {
4450         rtw_scan_abort(padapter);
4451         rtw_join_abort_timeout(padapter, 300);
4452         LeaveAllPowerSaveMode(padapter);
4453         rtw_disassoc_cmd(padapter, 500, RTW_CMDF_WAIT_ACK);
4454 #ifdef CONFIG_RTW_REPEATER_SON
4455         rtw_rson_do_disconnect(padapter);
4456 #endif
4457         RTW_INFO("%s...call rtw_indicate_disconnect\n", __func__);
4458 
4459         rtw_free_assoc_resources_cmd(padapter, _TRUE, RTW_CMDF_WAIT_ACK);
4460 
4461         /* indicate locally_generated = 0 when suspend */
4462         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
4463         rtw_indicate_disconnect(padapter, 0, wiphy->dev.power.is_prepared ? _FALSE : _TRUE);
4464         #else
4465         /*
4466         * for kernel < 4.2, DISCONNECT event is hardcoded with
4467         * NL80211_ATTR_DISCONNECTED_BY_AP=1 in NL80211 layer
4468         * no need to judge if under suspend
4469         */
4470         rtw_indicate_disconnect(padapter, 0, _TRUE);
4471         #endif
4472 
4473         rtw_pwr_wakeup(padapter);
4474     }
4475     return 0;
4476 }
4477 
4478 #if (KERNEL_VERSION(4, 17, 0) > LINUX_VERSION_CODE) \
4479     && !defined(CONFIG_KERNEL_PATCH_EXTERNAL_AUTH)
rtw_check_connect_sae_compat(struct cfg80211_connect_params * sme)4480 static bool rtw_check_connect_sae_compat(struct cfg80211_connect_params *sme)
4481 {
4482     struct rtw_ieee802_11_elems elems;
4483     struct rsne_info info;
4484     u8 AKM_SUITE_SAE[] = { 0x00, 0x0f, 0xac, 8 };
4485 #ifdef CONFIG_RTW_80211R
4486     u8 AKM_SUITE_FTSAE[] = { 0x00, 0x0f, 0xac, 9 };
4487 #endif
4488     int i;
4489 
4490     if (sme->auth_type != (int)MLME_AUTHTYPE_SHARED_KEY)
4491         return false;
4492 
4493     if (rtw_ieee802_11_parse_elems((u8 *)sme->ie, sme->ie_len, &elems, 0)
4494         == ParseFailed)
4495         return false;
4496 
4497     if (!elems.rsn_ie)
4498         return false;
4499 
4500     if (rtw_rsne_info_parse(elems.rsn_ie - 2, elems.rsn_ie_len + 2, &info) == _FAIL)
4501         return false;
4502 
4503     for (i = 0; i < info.akm_cnt; i++) {
4504         if ((memcmp(info.akm_list + i * RSN_SELECTOR_LEN,
4505                AKM_SUITE_SAE, RSN_SELECTOR_LEN) == 0)
4506     #ifdef CONFIG_RTW_80211R
4507             || (memcmp(info.akm_list + i * RSN_SELECTOR_LEN,
4508                            AKM_SUITE_FTSAE, RSN_SELECTOR_LEN) == 0)
4509     #endif
4510         )
4511             return true;
4512     }
4513     return false;
4514 }
4515 #else
4516 #define rtw_check_connect_sae_compat(sme)    false
4517 #endif
4518 
4519 #ifndef CONFIG_RTL8822CS_WIFI_HDF
4520 static
4521 #endif
cfg80211_rtw_connect(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_connect_params * sme)4522 int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
4523                 struct cfg80211_connect_params *sme)
4524 {
4525     int ret = 0;
4526     NDIS_802_11_AUTHENTICATION_MODE authmode;
4527     NDIS_802_11_SSID ndis_ssid;
4528     /* u8 matched_by_bssid=_FALSE; */
4529     /* u8 matched_by_ssid=_FALSE; */
4530     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
4531     struct security_priv *psecuritypriv = &padapter->securitypriv;
4532     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
4533     struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4534     _irqL irqL;
4535 
4536 #if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_CONNECT)
4537     rtw_wdev_set_not_indic_disco(pwdev_priv, 1);
4538 #endif
4539 
4540     RTW_INFO("=>"FUNC_NDEV_FMT" - Start to Connection\n", FUNC_NDEV_ARG(ndev));
4541     RTW_INFO("privacy=%d, key=%p, key_len=%d, key_idx=%d, auth_type=%d\n",
4542         sme->privacy, sme->key, sme->key_len, sme->key_idx, sme->auth_type);
4543 
4544     if (rtw_check_connect_sae_compat(sme)) {
4545         sme->auth_type = (int)MLME_AUTHTYPE_SAE;
4546         psecuritypriv->auth_type = MLME_AUTHTYPE_SAE;
4547         psecuritypriv->auth_alg = WLAN_AUTH_SAE;
4548         RTW_INFO("%s set sme->auth_type for SAE compat\n", __FUNCTION__);
4549     }
4550 
4551     if (pwdev_priv->block == _TRUE) {
4552         ret = -EBUSY;
4553         RTW_INFO("%s wdev_priv.block is set\n", __FUNCTION__);
4554         goto exit;
4555     }
4556 
4557        if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE | WIFI_UNDER_LINKING) == _TRUE) {
4558 
4559         _rtw_disconnect(wiphy, ndev);
4560         RTW_INFO("%s disconnect before connecting! fw_state=0x%x\n",
4561             __FUNCTION__, pmlmepriv->fw_state);
4562     }
4563 
4564 #ifdef CONFIG_PLATFORM_MSTAR_SCAN_BEFORE_CONNECT
4565     printk("MStar Android!\n");
4566     if (pwdev_priv->bandroid_scan == _FALSE) {
4567 #ifdef CONFIG_P2P
4568         struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
4569         if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
4570 #endif /* CONFIG_P2P */
4571         {
4572             ret = -EBUSY;
4573             printk("Android hasn't attached yet!\n");
4574             goto exit;
4575         }
4576     }
4577 #endif
4578 
4579     if (!sme->ssid || !sme->ssid_len) {
4580         ret = -EINVAL;
4581         goto exit;
4582     }
4583 
4584     if (sme->ssid_len > IW_ESSID_MAX_SIZE) {
4585         ret = -E2BIG;
4586         goto exit;
4587     }
4588 
4589     rtw_ps_deny(padapter, PS_DENY_JOIN);
4590     if (_FAIL == rtw_pwr_wakeup(padapter)) {
4591         ret = -EPERM;
4592         goto cancel_ps_deny;
4593     }
4594 
4595     rtw_mi_scan_abort(padapter, _TRUE);
4596 
4597     rtw_join_abort_timeout(padapter, 300);
4598 #ifdef CONFIG_CONCURRENT_MODE
4599     if (rtw_mi_buddy_check_fwstate(padapter, WIFI_UNDER_LINKING)) {
4600         ret = -EINVAL;
4601         goto cancel_ps_deny;
4602     }
4603 #endif
4604 
4605     _rtw_memset(&ndis_ssid, 0, sizeof(NDIS_802_11_SSID));
4606     ndis_ssid.SsidLength = sme->ssid_len;
4607     _rtw_memcpy(ndis_ssid.Ssid, (u8 *)sme->ssid, sme->ssid_len);
4608 
4609     RTW_INFO("ssid=%s, len=%zu\n", ndis_ssid.Ssid, sme->ssid_len);
4610 
4611 
4612     if (sme->bssid)
4613         RTW_INFO("bssid="MAC_FMT"\n", MAC_ARG(sme->bssid));
4614 
4615 
4616     psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
4617     psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
4618     psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
4619     psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open; /* open system */
4620     psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
4621     psecuritypriv->auth_alg = WLAN_AUTH_OPEN;
4622     psecuritypriv->extauth_status = WLAN_STATUS_UNSPECIFIED_FAILURE;
4623 
4624 #ifdef CONFIG_WAPI_SUPPORT
4625     padapter->wapiInfo.bWapiEnable = false;
4626 #endif
4627 
4628     ret = rtw_cfg80211_set_wpa_version(psecuritypriv, sme->crypto.wpa_versions);
4629     if (ret < 0)
4630         goto cancel_ps_deny;
4631 
4632 #ifdef CONFIG_WAPI_SUPPORT
4633     if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) {
4634         padapter->wapiInfo.bWapiEnable = true;
4635         padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;
4636         padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;
4637     }
4638 #endif
4639 
4640     ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
4641 
4642 #ifdef CONFIG_WAPI_SUPPORT
4643     if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_WAPI)
4644         padapter->mlmeextpriv.mlmext_info.auth_algo = psecuritypriv->dot11AuthAlgrthm;
4645 #endif
4646 
4647 
4648     if (ret < 0)
4649         goto cancel_ps_deny;
4650 
4651     RTW_INFO("%s, ie_len=%zu\n", __func__, sme->ie_len);
4652 
4653     ret = rtw_cfg80211_set_wpa_ie(padapter, (u8 *)sme->ie, sme->ie_len);
4654     if (ret < 0)
4655         goto cancel_ps_deny;
4656 
4657     if (sme->crypto.n_ciphers_pairwise) {
4658         ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.ciphers_pairwise[0], _TRUE);
4659         if (ret < 0)
4660             goto cancel_ps_deny;
4661     }
4662 
4663     /* For WEP Shared auth */
4664     if (sme->key_len > 0 && sme->key) {
4665         u32 wep_key_idx, wep_key_len, wep_total_len;
4666         NDIS_802_11_WEP    *pwep = NULL;
4667         RTW_INFO("%s(): Shared/Auto WEP\n", __FUNCTION__);
4668 
4669         wep_key_idx = sme->key_idx;
4670         wep_key_len = sme->key_len;
4671 
4672         if (sme->key_idx > WEP_KEYS) {
4673             ret = -EINVAL;
4674             goto cancel_ps_deny;
4675         }
4676 
4677         if (wep_key_len > 0) {
4678             wep_key_len = wep_key_len <= 5 ? 5 : 13;
4679             wep_total_len = wep_key_len + FIELD_OFFSET(NDIS_802_11_WEP, KeyMaterial);
4680             pwep = (NDIS_802_11_WEP *) rtw_malloc(wep_total_len);
4681             if (pwep == NULL) {
4682                 RTW_INFO(" wpa_set_encryption: pwep allocate fail !!!\n");
4683                 ret = -ENOMEM;
4684                 goto cancel_ps_deny;
4685             }
4686 
4687             _rtw_memset(pwep, 0, wep_total_len);
4688 
4689             pwep->KeyLength = wep_key_len;
4690             pwep->Length = wep_total_len;
4691 
4692             if (wep_key_len == 13) {
4693                 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
4694                 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
4695             }
4696         } else {
4697             ret = -EINVAL;
4698             goto cancel_ps_deny;
4699         }
4700 
4701         pwep->KeyIndex = wep_key_idx;
4702         pwep->KeyIndex |= 0x80000000;
4703 
4704         _rtw_memcpy(pwep->KeyMaterial, (void *)sme->key, pwep->KeyLength);
4705 
4706         if (rtw_set_802_11_add_wep(padapter, pwep) == (u8)_FAIL)
4707             ret = -EOPNOTSUPP ;
4708 
4709         if (pwep)
4710             rtw_mfree((u8 *)pwep, wep_total_len);
4711 
4712         if (ret < 0)
4713             goto cancel_ps_deny;
4714     }
4715 
4716     ret = rtw_cfg80211_set_cipher(psecuritypriv, sme->crypto.cipher_group, _FALSE);
4717     if (ret < 0)
4718         return ret;
4719 
4720     if (sme->crypto.n_akm_suites) {
4721         ret = rtw_cfg80211_set_key_mgt(psecuritypriv, sme->crypto.akm_suites[0]);
4722         if (ret < 0)
4723             goto cancel_ps_deny;
4724     }
4725 #ifdef CONFIG_8011R
4726     else {
4727         /*It could be a connection without RSN IEs*/
4728         psecuritypriv->rsn_akm_suite_type = 0;
4729     }
4730 #endif
4731 
4732 #ifdef CONFIG_WAPI_SUPPORT
4733     if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_WAPI_PSK)
4734         padapter->wapiInfo.bWapiPSK = true;
4735     else if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_WAPI_CERT)
4736         padapter->wapiInfo.bWapiPSK = false;
4737 #endif
4738 
4739     authmode = psecuritypriv->ndisauthtype;
4740     rtw_set_802_11_authentication_mode(padapter, authmode);
4741 
4742     /* rtw_set_802_11_encryption_mode(padapter, padapter->securitypriv.ndisencryptstatus); */
4743 
4744 #ifdef CONFIG_RTW_MBO
4745     rtw_mbo_update_ie_data(padapter, (u8 *)sme->ie, sme->ie_len);
4746 #endif
4747 
4748     if (rtw_set_802_11_connect(padapter, (u8 *)sme->bssid, &ndis_ssid, \
4749             sme->channel ? sme->channel->hw_value : 0) == _FALSE) {
4750         ret = -1;
4751         goto cancel_ps_deny;
4752     }
4753 
4754 
4755     _enter_critical_bh(&pwdev_priv->connect_req_lock, &irqL);
4756 
4757     if (pwdev_priv->connect_req) {
4758         rtw_wdev_free_connect_req(pwdev_priv);
4759         RTW_INFO(FUNC_NDEV_FMT" free existing connect_req\n", FUNC_NDEV_ARG(ndev));
4760     }
4761 
4762     pwdev_priv->connect_req = (struct cfg80211_connect_params *)rtw_malloc(sizeof(*pwdev_priv->connect_req));
4763     if (pwdev_priv->connect_req)
4764         _rtw_memcpy(pwdev_priv->connect_req, sme, sizeof(*pwdev_priv->connect_req));
4765     else
4766         RTW_WARN(FUNC_NDEV_FMT" alloc connect_req fail\n", FUNC_NDEV_ARG(ndev));
4767 
4768     _exit_critical_bh(&pwdev_priv->connect_req_lock, &irqL);
4769 
4770     RTW_INFO("set ssid:dot11AuthAlgrthm=%d, dot11PrivacyAlgrthm=%d, dot118021XGrpPrivacy=%d\n", psecuritypriv->dot11AuthAlgrthm, psecuritypriv->dot11PrivacyAlgrthm,
4771         psecuritypriv->dot118021XGrpPrivacy);
4772 
4773 cancel_ps_deny:
4774     rtw_ps_deny_cancel(padapter, PS_DENY_JOIN);
4775 
4776 exit:
4777     RTW_INFO("<=%s, ret %d\n", __FUNCTION__, ret);
4778 
4779 #if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_CONNECT)
4780     rtw_wdev_set_not_indic_disco(pwdev_priv, 0);
4781 #endif
4782 
4783     return ret;
4784 }
4785 
4786 #ifndef CONFIG_RTL8822CS_WIFI_HDF
4787 static
4788 #endif
cfg80211_rtw_disconnect(struct wiphy * wiphy,struct net_device * ndev,u16 reason_code)4789 int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
4790                    u16 reason_code)
4791 {
4792     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
4793 
4794     RTW_INFO(FUNC_NDEV_FMT" - Start to Disconnect\n", FUNC_NDEV_ARG(ndev));
4795 
4796 #if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_DISCONNECT)
4797     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
4798     if (!wiphy->dev.power.is_prepared)
4799     #endif
4800         rtw_wdev_set_not_indic_disco(adapter_wdev_data(padapter), 1);
4801 #endif
4802 
4803     rtw_set_to_roam(padapter, 0);
4804 
4805     /* if(check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) */
4806     {
4807         _rtw_disconnect(wiphy, ndev);
4808     }
4809 
4810 #if (RTW_CFG80211_BLOCK_STA_DISCON_EVENT & RTW_CFG80211_BLOCK_DISCON_WHEN_DISCONNECT)
4811     rtw_wdev_set_not_indic_disco(adapter_wdev_data(padapter), 0);
4812 #endif
4813 
4814     RTW_INFO(FUNC_NDEV_FMT" return 0\n", FUNC_NDEV_ARG(ndev));
4815     return 0;
4816 }
4817 
4818 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
4819 #ifdef CONFIG_RTW_DEBUG
nl80211_tx_power_setting_str(int type)4820 static const char *nl80211_tx_power_setting_str(int type)
4821 {
4822     switch (type) {
4823     case NL80211_TX_POWER_AUTOMATIC:
4824         return "AUTO";
4825     case NL80211_TX_POWER_LIMITED:
4826         return "LIMIT";
4827     case NL80211_TX_POWER_FIXED:
4828         return "FIX";
4829     default:
4830         return "UNKNOWN";
4831     };
4832 }
4833 #endif    /*    CONFIG_RTW_DEBUG    */
4834 
4835 #ifndef CONFIG_RTL8822CS_WIFI_HDF
4836 static
4837 #endif
cfg80211_rtw_set_txpower(struct wiphy * wiphy,struct wireless_dev * wdev,enum nl80211_tx_power_setting type,int mbm)4838 int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
4839 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
4840     struct wireless_dev *wdev,
4841 #endif
4842 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) || defined(COMPAT_KERNEL_RELEASE)
4843     enum nl80211_tx_power_setting type, int mbm)
4844 #else
4845     enum tx_power_setting type, int dbm)
4846 #endif
4847 {
4848 #if !((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) || defined(COMPAT_KERNEL_RELEASE))
4849     int mbm = dbm * 100;
4850 #endif
4851     struct rtw_wiphy_data *wiphy_data = rtw_wiphy_priv(wiphy);
4852     _adapter *adapter = wiphy_to_adapter(wiphy);
4853     int ret = -EOPNOTSUPP;
4854 
4855 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
4856     if (wdev) {
4857         RTW_WARN(FUNC_WIPHY_FMT" wdev specific control is not supported\n", FUNC_WIPHY_ARG(wiphy));
4858         goto exit;
4859     }
4860 #endif
4861 
4862     RTW_INFO(FUNC_WIPHY_FMT" type:%s(%u) mbm:%d\n", FUNC_WIPHY_ARG(wiphy)
4863         , nl80211_tx_power_setting_str(type), type, mbm);
4864 
4865     switch (type) {
4866     case NL80211_TX_POWER_AUTOMATIC:
4867         wiphy_data->txpwr_total_lmt_mbm = UNSPECIFIED_MBM;
4868         wiphy_data->txpwr_total_target_mbm = UNSPECIFIED_MBM;
4869         ret = 0;
4870         break;
4871     case NL80211_TX_POWER_LIMITED:
4872         if (!phy_is_txpwr_user_mbm_valid(adapter, mbm)) {
4873             RTW_WARN(FUNC_WIPHY_FMT" mbm:%d not support\n", FUNC_WIPHY_ARG(wiphy), mbm);
4874             goto exit;
4875         }
4876         wiphy_data->txpwr_total_lmt_mbm = mbm;
4877         wiphy_data->txpwr_total_target_mbm = UNSPECIFIED_MBM;
4878         ret = 0;
4879         break;
4880     case NL80211_TX_POWER_FIXED:
4881         if (!phy_is_txpwr_user_mbm_valid(adapter, mbm)) {
4882             RTW_WARN(FUNC_WIPHY_FMT" mbm:%d not support\n", FUNC_WIPHY_ARG(wiphy), mbm);
4883             goto exit;
4884         }
4885         wiphy_data->txpwr_total_lmt_mbm = UNSPECIFIED_MBM;
4886         wiphy_data->txpwr_total_target_mbm = mbm;
4887         ret = 0;
4888         break;
4889     default:
4890         RTW_WARN(FUNC_WIPHY_FMT" unknown type:%d\n", FUNC_WIPHY_ARG(wiphy), type);
4891     }
4892 
4893     if (ret == 0)
4894         rtw_run_in_thread_cmd_wait(adapter, ((void *)(rtw_hal_update_txpwr_level)), adapter, 2000);
4895 
4896 exit:
4897     return ret;
4898 }
4899 
cfg80211_rtw_get_txpower(struct wiphy * wiphy,struct wireless_dev * wdev,int * dbm)4900 static int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
4901 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
4902     struct wireless_dev *wdev,
4903 #endif
4904     int *dbm)
4905 {
4906     struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);
4907     s16 mbm;
4908 
4909 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
4910     if (wdev && wdev_to_ndev(wdev)) {
4911         _adapter *adapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
4912         mbm = rtw_adapter_get_oper_txpwr_max_mbm(adapter, 1);
4913         RTW_INFO(FUNC_ADPT_FMT" total max: %d mbm\n", FUNC_ADPT_ARG(adapter), mbm);
4914     } else
4915 #endif
4916     {
4917         mbm = rtw_get_oper_txpwr_max_mbm(dvobj, 1);
4918         RTW_INFO(FUNC_WIPHY_FMT" total max: %d mbm\n", FUNC_WIPHY_ARG(wiphy), mbm);
4919     }
4920 
4921     *dbm = mbm / MBM_PDBM;
4922 
4923     return 0;
4924 }
4925 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) */
4926 
rtw_cfg80211_pwr_mgmt(_adapter * adapter)4927 inline bool rtw_cfg80211_pwr_mgmt(_adapter *adapter)
4928 {
4929     struct rtw_wdev_priv *rtw_wdev_priv = adapter_wdev_data(adapter);
4930     struct wireless_dev *wdev = rtw_wdev_priv->rtw_wdev;
4931 
4932     return wdev->ps;
4933 }
4934 
cfg80211_rtw_set_power_mgmt(struct wiphy * wiphy,struct net_device * ndev,bool enabled,int timeout)4935 static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
4936                        struct net_device *ndev,
4937                        bool enabled, int timeout)
4938 {
4939     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
4940 
4941     RTW_INFO(FUNC_NDEV_FMT" enabled:%u, timeout:%d\n", FUNC_NDEV_ARG(ndev),
4942         enabled, timeout);
4943 
4944 #ifdef CONFIG_LPS
4945     if (!enabled)
4946         rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE_CFG80211_PWRMGMT, 0);
4947 #endif
4948 
4949     return 0;
4950 }
4951 
_rtw_set_pmksa(struct net_device * ndev,u8 * bssid,u8 * pmkid)4952 static void _rtw_set_pmksa(struct net_device *ndev,
4953     u8 *bssid, u8 *pmkid)
4954 {
4955     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
4956     struct security_priv *psecuritypriv = &padapter->securitypriv;
4957     u8 index, blInserted = _FALSE;
4958 
4959     /* overwrite PMKID */
4960     for (index = 0 ; index < NUM_PMKID_CACHE; index++) {
4961         if (_rtw_memcmp(psecuritypriv->PMKIDList[index].Bssid, bssid, ETH_ALEN) == _TRUE) {
4962             /* BSSID is matched, the same AP => rewrite with new PMKID. */
4963             RTW_INFO("BSSID("MAC_FMT") exists in the PMKList.\n", MAC_ARG(bssid));
4964 
4965             _rtw_memcpy(psecuritypriv->PMKIDList[index].PMKID, pmkid, WLAN_PMKID_LEN);
4966             psecuritypriv->PMKIDList[index].bUsed = _TRUE;
4967             blInserted = _TRUE;
4968             break;
4969         }
4970     }
4971 
4972     if (!blInserted) {
4973         /* Find a new entry */
4974         RTW_INFO("Use the new entry index = %d for this PMKID.\n",
4975             psecuritypriv->PMKIDIndex);
4976 
4977         _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].Bssid, bssid, ETH_ALEN);
4978         _rtw_memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].PMKID, pmkid, WLAN_PMKID_LEN);
4979 
4980         psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed = _TRUE;
4981         psecuritypriv->PMKIDIndex++ ;
4982         if (psecuritypriv->PMKIDIndex == 16)
4983             psecuritypriv->PMKIDIndex = 0;
4984     }
4985 }
4986 
cfg80211_rtw_set_pmksa(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_pmksa * pmksa)4987 static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
4988                   struct net_device *ndev,
4989                   struct cfg80211_pmksa *pmksa)
4990 {
4991     u8    index, blInserted = _FALSE;
4992     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
4993     struct mlme_priv *mlme = &padapter->mlmepriv;
4994     struct security_priv    *psecuritypriv = &padapter->securitypriv;
4995     u8    strZeroMacAddress[ETH_ALEN] = { 0x00 };
4996     bool sae_auth = rtw_sec_chk_auth_type(padapter, MLME_AUTHTYPE_SAE);
4997 
4998     RTW_INFO(FUNC_NDEV_FMT" "MAC_FMT" "KEY_FMT"\n", FUNC_NDEV_ARG(ndev)
4999         , MAC_ARG(pmksa->bssid), KEY_ARG(pmksa->pmkid));
5000 
5001     if (_rtw_memcmp((u8 *)pmksa->bssid, strZeroMacAddress, ETH_ALEN) == _TRUE)
5002         return -EINVAL;
5003 
5004     _rtw_set_pmksa(ndev, (u8 *)pmksa->bssid, (u8 *)pmksa->pmkid);
5005 
5006     if (sae_auth &&
5007         (psecuritypriv->extauth_status == WLAN_STATUS_SUCCESS)) {
5008         RTW_PRINT("SAE: auth success, start assoc\n");
5009         start_clnt_assoc(padapter);
5010     }
5011 
5012     return 0;
5013 }
5014 
cfg80211_rtw_del_pmksa(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_pmksa * pmksa)5015 static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
5016                   struct net_device *ndev,
5017                   struct cfg80211_pmksa *pmksa)
5018 {
5019     u8    index, bMatched = _FALSE;
5020     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
5021     struct security_priv    *psecuritypriv = &padapter->securitypriv;
5022 
5023     RTW_INFO(FUNC_NDEV_FMT" "MAC_FMT" "KEY_FMT"\n", FUNC_NDEV_ARG(ndev)
5024         , MAC_ARG(pmksa->bssid), KEY_ARG(pmksa->pmkid));
5025 
5026     for (index = 0 ; index < NUM_PMKID_CACHE; index++) {
5027         if (_rtw_memcmp(psecuritypriv->PMKIDList[index].Bssid, (u8 *)pmksa->bssid, ETH_ALEN) == _TRUE) {
5028             /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
5029             _rtw_memset(psecuritypriv->PMKIDList[index].Bssid, 0x00, ETH_ALEN);
5030             _rtw_memset(psecuritypriv->PMKIDList[index].PMKID, 0x00, WLAN_PMKID_LEN);
5031             psecuritypriv->PMKIDList[index].bUsed = _FALSE;
5032             bMatched = _TRUE;
5033             RTW_INFO(FUNC_NDEV_FMT" clear id:%hhu\n", FUNC_NDEV_ARG(ndev), index);
5034             break;
5035         }
5036     }
5037 
5038     if (_FALSE == bMatched) {
5039         RTW_INFO(FUNC_NDEV_FMT" do not have matched BSSID\n"
5040             , FUNC_NDEV_ARG(ndev));
5041         return -EINVAL;
5042     }
5043 
5044     return 0;
5045 }
5046 
cfg80211_rtw_flush_pmksa(struct wiphy * wiphy,struct net_device * ndev)5047 static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
5048                     struct net_device *ndev)
5049 {
5050     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
5051     struct security_priv    *psecuritypriv = &padapter->securitypriv;
5052 
5053     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
5054 
5055     _rtw_memset(&psecuritypriv->PMKIDList[0], 0x00, sizeof(RT_PMKID_LIST) * NUM_PMKID_CACHE);
5056     psecuritypriv->PMKIDIndex = 0;
5057 
5058     return 0;
5059 }
5060 
5061 #ifndef CONFIG_RTL8822CS_WIFI_HDF
5062 static
5063 #endif
rtw_cfg80211_monitor_if_open(struct net_device * ndev)5064 int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
5065 {
5066     int ret = 0;
5067 
5068     RTW_INFO("%s\n", __func__);
5069 
5070     return ret;
5071 }
5072 
5073 #ifndef CONFIG_RTL8822CS_WIFI_HDF
5074 static
5075 #endif
rtw_cfg80211_monitor_if_close(struct net_device * ndev)5076 int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
5077 {
5078     int ret = 0;
5079 
5080     RTW_INFO("%s\n", __func__);
5081 
5082     return ret;
5083 }
5084 
5085 #ifndef CONFIG_RTL8822CS_WIFI_HDF
5086 static
5087 #endif
rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff * skb,struct net_device * ndev)5088 int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb, struct net_device *ndev)
5089 {
5090     int ret = 0;
5091     int rtap_len;
5092     int qos_len = 0;
5093     int dot11_hdr_len = 24;
5094     int snap_len = 6;
5095     unsigned char *pdata;
5096     u16 frame_ctl;
5097     unsigned char src_mac_addr[ETH_ALEN];
5098     unsigned char dst_mac_addr[ETH_ALEN];
5099     struct rtw_ieee80211_hdr *dot11_hdr;
5100     struct ieee80211_radiotap_header *rtap_hdr;
5101     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
5102 #ifdef CONFIG_DFS_MASTER
5103     struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
5104 #endif
5105 
5106     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
5107 
5108     rtw_mstat_update(MSTAT_TYPE_SKB, MSTAT_ALLOC_SUCCESS, skb->truesize);
5109 
5110     if (IS_CH_WAITING(rfctl)) {
5111         #ifdef CONFIG_DFS_MASTER
5112         if (rtw_rfctl_overlap_radar_detect_ch(rfctl))
5113             goto fail;
5114         #endif
5115     }
5116 
5117     if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
5118         goto fail;
5119 
5120     rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
5121     if (unlikely(rtap_hdr->it_version))
5122         goto fail;
5123 
5124     rtap_len = ieee80211_get_radiotap_len(skb->data);
5125     if (unlikely(skb->len < rtap_len))
5126         goto fail;
5127 
5128     if (rtap_len != 14) {
5129         RTW_INFO("radiotap len (should be 14): %d\n", rtap_len);
5130         goto fail;
5131     }
5132 
5133     /* Skip the ratio tap header */
5134     skb_pull(skb, rtap_len);
5135 
5136     dot11_hdr = (struct rtw_ieee80211_hdr *)skb->data;
5137     frame_ctl = le16_to_cpu(dot11_hdr->frame_ctl);
5138     /* Check if the QoS bit is set */
5139     if ((frame_ctl & RTW_IEEE80211_FCTL_FTYPE) == RTW_IEEE80211_FTYPE_DATA) {
5140         /* Check if this ia a Wireless Distribution System (WDS) frame
5141          * which has 4 MAC addresses
5142          */
5143         if (dot11_hdr->frame_ctl & 0x0080)
5144             qos_len = 2;
5145         if ((dot11_hdr->frame_ctl & 0x0300) == 0x0300)
5146             dot11_hdr_len += 6;
5147 
5148         memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
5149         memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
5150 
5151         /* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for
5152          * for two MAC addresses
5153          */
5154         skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2);
5155         pdata = (unsigned char *)skb->data;
5156         memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr));
5157         memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr));
5158 
5159         RTW_INFO("should be eapol packet\n");
5160 
5161         /* Use the real net device to transmit the packet */
5162         ret = _rtw_xmit_entry(skb, padapter->pnetdev);
5163 
5164         return ret;
5165 
5166     } else if ((frame_ctl & (RTW_IEEE80211_FCTL_FTYPE | RTW_IEEE80211_FCTL_STYPE))
5167         == (RTW_IEEE80211_FTYPE_MGMT | RTW_IEEE80211_STYPE_ACTION)
5168     ) {
5169         /* only for action frames */
5170         struct xmit_frame        *pmgntframe;
5171         struct pkt_attrib    *pattrib;
5172         unsigned char    *pframe;
5173         /* u8 category, action, OUI_Subtype, dialogToken=0; */
5174         /* unsigned char    *frame_body; */
5175         struct rtw_ieee80211_hdr *pwlanhdr;
5176         struct xmit_priv    *pxmitpriv = &(padapter->xmitpriv);
5177         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5178         u8 *buf = skb->data;
5179         u32 len = skb->len;
5180         u8 category, action;
5181         int type = -1;
5182 
5183         if (rtw_action_frame_parse(buf, len, &category, &action) == _FALSE) {
5184             RTW_INFO(FUNC_NDEV_FMT" frame_control:0x%x\n", FUNC_NDEV_ARG(ndev),
5185                 le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl));
5186             goto fail;
5187         }
5188 
5189         RTW_INFO("RTW_Tx:da="MAC_FMT" via "FUNC_NDEV_FMT"\n",
5190             MAC_ARG(GetAddr1Ptr(buf)), FUNC_NDEV_ARG(ndev));
5191         #ifdef CONFIG_P2P
5192         type = rtw_p2p_check_frames(padapter, buf, len, _TRUE);
5193         if (type >= 0)
5194             goto dump;
5195         #endif
5196         if (category == RTW_WLAN_CATEGORY_PUBLIC)
5197             RTW_INFO("RTW_Tx:%s\n", action_public_str(action));
5198         else
5199             RTW_INFO("RTW_Tx:category(%u), action(%u)\n", category, action);
5200 #ifdef CONFIG_P2P
5201 dump:
5202 #endif
5203         /* starting alloc mgmt frame to dump it */
5204         pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5205         if (pmgntframe == NULL)
5206             goto fail;
5207 
5208         /* update attribute */
5209         pattrib = &pmgntframe->attrib;
5210         update_mgntframe_attrib(padapter, pattrib);
5211         pattrib->retry_ctrl = _FALSE;
5212 
5213         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5214 
5215         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5216 
5217         _rtw_memcpy(pframe, (void *)buf, len);
5218         pattrib->pktlen = len;
5219 
5220 #ifdef CONFIG_P2P
5221         if (type >= 0)
5222             rtw_xframe_chk_wfd_ie(pmgntframe);
5223 #endif /* CONFIG_P2P */
5224 
5225         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5226         /* update seq number */
5227         pmlmeext->mgnt_seq = GetSequence(pwlanhdr);
5228         pattrib->seqnum = pmlmeext->mgnt_seq;
5229         pmlmeext->mgnt_seq++;
5230 
5231         pattrib->last_txcmdsz = pattrib->pktlen;
5232 
5233         dump_mgntframe(padapter, pmgntframe);
5234 
5235     } else
5236         RTW_INFO("frame_ctl=0x%x\n", frame_ctl & (RTW_IEEE80211_FCTL_FTYPE | RTW_IEEE80211_FCTL_STYPE));
5237 
5238 
5239 fail:
5240 
5241     rtw_skb_free(skb);
5242 
5243     return 0;
5244 
5245 }
5246 
5247 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
rtw_cfg80211_monitor_if_set_multicast_list(struct net_device * ndev)5248 static void rtw_cfg80211_monitor_if_set_multicast_list(struct net_device *ndev)
5249 {
5250     RTW_INFO("%s\n", __func__);
5251 }
5252 #endif
5253 #ifndef CONFIG_RTL8822CS_WIFI_HDF
5254 static
5255 #endif
rtw_cfg80211_monitor_if_set_mac_address(struct net_device * ndev,void * addr)5256 int rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
5257 {
5258     int ret = 0;
5259 
5260     RTW_INFO("%s\n", __func__);
5261 
5262     return ret;
5263 }
5264 
5265 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
5266 #ifdef CONFIG_RTL8822CS_WIFI_HDF
5267 static
5268 #endif
5269 const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
5270     .ndo_open = rtw_cfg80211_monitor_if_open,
5271     .ndo_stop = rtw_cfg80211_monitor_if_close,
5272     .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
5273     #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
5274     .ndo_set_multicast_list = rtw_cfg80211_monitor_if_set_multicast_list,
5275     #endif
5276     .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
5277 };
5278 #endif
5279 
rtw_cfg80211_add_monitor_if(_adapter * padapter,char * name,struct net_device ** ndev)5280 static int rtw_cfg80211_add_monitor_if(_adapter *padapter, char *name, struct net_device **ndev)
5281 {
5282     int ret = 0;
5283     struct net_device *mon_ndev = NULL;
5284     struct wireless_dev *mon_wdev = NULL;
5285     struct rtw_netdev_priv_indicator *pnpi;
5286     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
5287 
5288     if (!name) {
5289         RTW_INFO(FUNC_ADPT_FMT" without specific name\n", FUNC_ADPT_ARG(padapter));
5290         ret = -EINVAL;
5291         goto out;
5292     }
5293 
5294     if (pwdev_priv->pmon_ndev) {
5295         RTW_INFO(FUNC_ADPT_FMT" monitor interface exist: "NDEV_FMT"\n",
5296             FUNC_ADPT_ARG(padapter), NDEV_ARG(pwdev_priv->pmon_ndev));
5297         ret = -EBUSY;
5298         goto out;
5299     }
5300 
5301     mon_ndev = alloc_etherdev(sizeof(struct rtw_netdev_priv_indicator));
5302     if (!mon_ndev) {
5303         RTW_INFO(FUNC_ADPT_FMT" allocate ndev fail\n", FUNC_ADPT_ARG(padapter));
5304         ret = -ENOMEM;
5305         goto out;
5306     }
5307 
5308     mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
5309     strncpy(mon_ndev->name, name, IFNAMSIZ);
5310     mon_ndev->name[IFNAMSIZ - 1] = 0;
5311 #if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 11, 8))
5312     mon_ndev->priv_destructor = rtw_ndev_destructor;
5313 #else
5314     mon_ndev->destructor = rtw_ndev_destructor;
5315 #endif
5316 
5317 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
5318     mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
5319 #else
5320     mon_ndev->open = rtw_cfg80211_monitor_if_open;
5321     mon_ndev->stop = rtw_cfg80211_monitor_if_close;
5322     mon_ndev->hard_start_xmit = rtw_cfg80211_monitor_if_xmit_entry;
5323     mon_ndev->set_mac_address = rtw_cfg80211_monitor_if_set_mac_address;
5324 #endif
5325 
5326     pnpi = netdev_priv(mon_ndev);
5327     pnpi->priv = padapter;
5328     pnpi->sizeof_priv = sizeof(_adapter);
5329 
5330     /*  wdev */
5331     mon_wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));
5332     if (!mon_wdev) {
5333         RTW_INFO(FUNC_ADPT_FMT" allocate mon_wdev fail\n", FUNC_ADPT_ARG(padapter));
5334         ret = -ENOMEM;
5335         goto out;
5336     }
5337 
5338     mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
5339     mon_wdev->netdev = mon_ndev;
5340     mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
5341     mon_ndev->ieee80211_ptr = mon_wdev;
5342 
5343     ret = register_netdevice(mon_ndev);
5344     if (ret)
5345         goto out;
5346 
5347     *ndev = pwdev_priv->pmon_ndev = mon_ndev;
5348     _rtw_memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);
5349 
5350 out:
5351     if (ret && mon_wdev) {
5352         rtw_mfree((u8 *)mon_wdev, sizeof(struct wireless_dev));
5353         mon_wdev = NULL;
5354     }
5355 
5356     if (ret && mon_ndev) {
5357         free_netdev(mon_ndev);
5358         *ndev = mon_ndev = NULL;
5359     }
5360 
5361     return ret;
5362 }
5363 
5364 #ifdef CONFIG_AP_MODE
rtw_cfg80211_indicate_sta_assoc(_adapter * padapter,u8 * pmgmt_frame,uint frame_len)5365 void rtw_cfg80211_indicate_sta_assoc(_adapter *padapter, u8 *pmgmt_frame, uint frame_len)
5366 {
5367 #if !defined(RTW_USE_CFG80211_STA_EVENT) && !defined(COMPAT_KERNEL_RELEASE)
5368     s32 freq;
5369     int channel;
5370     struct wireless_dev *pwdev = padapter->rtw_wdev;
5371     struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
5372 #endif
5373     struct net_device *ndev = padapter->pnetdev;
5374 
5375     RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
5376 
5377 #if defined(RTW_USE_CFG80211_STA_EVENT) || defined(COMPAT_KERNEL_RELEASE)
5378     {
5379         struct station_info sinfo;
5380         u8 ie_offset;
5381         if (get_frame_sub_type(pmgmt_frame) == WIFI_ASSOCREQ)
5382             ie_offset = _ASOCREQ_IE_OFFSET_;
5383         else /* WIFI_REASSOCREQ */
5384             ie_offset = _REASOCREQ_IE_OFFSET_;
5385 
5386         memset(&sinfo, 0, sizeof(sinfo));
5387         sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
5388         sinfo.assoc_req_ies = pmgmt_frame + WLAN_HDR_A3_LEN + ie_offset;
5389         sinfo.assoc_req_ies_len = frame_len - WLAN_HDR_A3_LEN - ie_offset;
5390         cfg80211_new_sta(ndev, get_addr2_ptr(pmgmt_frame), &sinfo, GFP_ATOMIC);
5391     }
5392 #else /* defined(RTW_USE_CFG80211_STA_EVENT) */
5393     channel = pmlmeext->cur_channel;
5394     freq = rtw_ch2freq(channel);
5395 
5396     #ifdef COMPAT_KERNEL_RELEASE
5397     rtw_cfg80211_rx_mgmt(pwdev, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);
5398     #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
5399     rtw_cfg80211_rx_mgmt(pwdev, freq, 0, pmgmt_frame, frame_len, GFP_ATOMIC);
5400     #else /* COMPAT_KERNEL_RELEASE */
5401     {
5402         /* to avoid WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)  when calling cfg80211_send_rx_assoc() */
5403         #ifndef CONFIG_PLATFORM_MSTAR
5404         pwdev->iftype = NL80211_IFTYPE_STATION;
5405         #endif /* CONFIG_PLATFORM_MSTAR */
5406         RTW_INFO("iftype=%d before call cfg80211_send_rx_assoc()\n", pwdev->iftype);
5407         rtw_cfg80211_send_rx_assoc(padapter, NULL, pmgmt_frame, frame_len);
5408         RTW_INFO("iftype=%d after call cfg80211_send_rx_assoc()\n", pwdev->iftype);
5409         pwdev->iftype = NL80211_IFTYPE_AP;
5410         /* cfg80211_rx_action(padapter->pnetdev, freq, pmgmt_frame, frame_len, GFP_ATOMIC); */
5411     }
5412     #endif /* COMPAT_KERNEL_RELEASE */
5413 #endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
5414 
5415 }
5416 
rtw_cfg80211_indicate_sta_disassoc(_adapter * padapter,const u8 * da,unsigned short reason)5417 void rtw_cfg80211_indicate_sta_disassoc(_adapter *padapter, const u8 *da, unsigned short reason)
5418 {
5419 #if !defined(RTW_USE_CFG80211_STA_EVENT) && !defined(COMPAT_KERNEL_RELEASE)
5420     s32 freq;
5421     int channel;
5422     u8 *pmgmt_frame;
5423     uint frame_len;
5424     struct rtw_ieee80211_hdr *pwlanhdr;
5425     unsigned short *fctrl;
5426     u8 mgmt_buf[128] = {0};
5427     struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5428     struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5429     struct wireless_dev *wdev = padapter->rtw_wdev;
5430 #endif
5431     struct net_device *ndev = padapter->pnetdev;
5432 
5433     RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
5434 
5435 #if defined(RTW_USE_CFG80211_STA_EVENT) || defined(COMPAT_KERNEL_RELEASE)
5436     cfg80211_del_sta(ndev, da, GFP_ATOMIC);
5437 #else /* defined(RTW_USE_CFG80211_STA_EVENT) */
5438     channel = pmlmeext->cur_channel;
5439     freq = rtw_ch2freq(channel);
5440 
5441     pmgmt_frame = mgmt_buf;
5442     pwlanhdr = (struct rtw_ieee80211_hdr *)pmgmt_frame;
5443 
5444     fctrl = &(pwlanhdr->frame_ctl);
5445     *(fctrl) = 0;
5446 
5447     _rtw_memcpy(pwlanhdr->addr1, adapter_mac_addr(padapter), ETH_ALEN);
5448     _rtw_memcpy(pwlanhdr->addr2, da, ETH_ALEN);
5449     _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5450 
5451     SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5452     pmlmeext->mgnt_seq++;
5453     set_frame_sub_type(pmgmt_frame, WIFI_DEAUTH);
5454 
5455     pmgmt_frame += sizeof(struct rtw_ieee80211_hdr_3addr);
5456     frame_len = sizeof(struct rtw_ieee80211_hdr_3addr);
5457 
5458     reason = cpu_to_le16(reason);
5459     pmgmt_frame = rtw_set_fixed_ie(pmgmt_frame, _RSON_CODE_ , (unsigned char *)&reason, &frame_len);
5460 
5461     #ifdef COMPAT_KERNEL_RELEASE
5462     rtw_cfg80211_rx_mgmt(wdev, freq, 0, mgmt_buf, frame_len, GFP_ATOMIC);
5463     #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
5464     rtw_cfg80211_rx_mgmt(wdev, freq, 0, mgmt_buf, frame_len, GFP_ATOMIC);
5465     #else /* COMPAT_KERNEL_RELEASE */
5466     cfg80211_send_disassoc(padapter->pnetdev, mgmt_buf, frame_len);
5467     /* cfg80211_rx_action(padapter->pnetdev, freq, mgmt_buf, frame_len, GFP_ATOMIC); */
5468     #endif /* COMPAT_KERNEL_RELEASE */
5469 #endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
5470 }
5471 
rtw_add_beacon(_adapter * adapter,const u8 * head,size_t head_len,const u8 * tail,size_t tail_len)5472 static int rtw_add_beacon(_adapter *adapter, const u8 *head, size_t head_len, const u8 *tail, size_t tail_len)
5473 {
5474     int ret = 0;
5475     u8 *pbuf = NULL;
5476     uint len, wps_ielen = 0;
5477     uint p2p_ielen = 0;
5478     u8 got_p2p_ie = _FALSE;
5479     struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
5480     /* struct sta_priv *pstapriv = &padapter->stapriv; */
5481 
5482 
5483     RTW_INFO("%s beacon_head_len=%zu, beacon_tail_len=%zu\n", __FUNCTION__, head_len, tail_len);
5484 
5485 
5486     if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
5487         return -EINVAL;
5488 
5489     if (head_len < 24)
5490         return -EINVAL;
5491 
5492     #ifdef CONFIG_FW_HANDLE_TXBCN
5493     if (!rtw_ap_nums_check(adapter)) {
5494         RTW_ERR(FUNC_ADPT_FMT"failed, con't support over %d BCN\n", FUNC_ADPT_ARG(adapter), CONFIG_LIMITED_AP_NUM);
5495         return -EINVAL;
5496     }
5497     #endif /*CONFIG_FW_HANDLE_TXBCN*/
5498 
5499     pbuf = rtw_zmalloc(head_len + tail_len);
5500     if (!pbuf) {
5501         ret = -ENOMEM;
5502         goto exit;
5503     }
5504 
5505 
5506     /* _rtw_memcpy(&pstapriv->max_num_sta, param->u.bcn_ie.reserved, 2); */
5507 
5508     /* if((pstapriv->max_num_sta>NUM_STA) || (pstapriv->max_num_sta<=0)) */
5509     /*    pstapriv->max_num_sta = NUM_STA; */
5510 
5511 
5512     _rtw_memcpy(pbuf, (void *)head + 24, head_len - 24); /* 24=beacon header len. */
5513     _rtw_memcpy(pbuf + head_len - 24, (void *)tail, tail_len);
5514 
5515     len = head_len + tail_len - 24;
5516 
5517     /* check wps ie if inclued */
5518     if (rtw_get_wps_ie(pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL, &wps_ielen))
5519         RTW_INFO("add bcn, wps_ielen=%d\n", wps_ielen);
5520 
5521 #ifdef CONFIG_P2P
5522     if (adapter->wdinfo.driver_interface == DRIVER_CFG80211) {
5523         /* check p2p if enable */
5524         if (rtw_get_p2p_ie(pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL, &p2p_ielen)) {
5525             struct wifidirect_info *pwdinfo = &(adapter->wdinfo);
5526 
5527             RTW_INFO("got p2p_ie, len=%d\n", p2p_ielen);
5528 
5529             got_p2p_ie = _TRUE;
5530 
5531             if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
5532 
5533                 if (rtw_p2p_enable(adapter, P2P_ROLE_GO)) {
5534                     RTW_INFO("Enable P2P function for the first time\n");
5535                     adapter->stapriv.expire_to = 3; /* 3x2 = 6 sec in p2p mode */
5536                 } else {
5537                     ret = -EOPNOTSUPP;
5538                     goto exit;
5539                 }
5540             } else {
5541                 RTW_INFO("enter GO Mode, p2p_ielen=%d\n", p2p_ielen);
5542 
5543                 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
5544                 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
5545                 pwdinfo->intent = 15;
5546             }
5547         }
5548     }
5549 #endif /* CONFIG_P2P */
5550 
5551     if (adapter_to_dvobj(adapter)->wpas_type == RTW_WPAS_ANDROID) {
5552         /* pbss_network->IEs will not include p2p_ie, wfd ie */
5553         rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, P2P_OUI, 4);
5554         rtw_ies_remove_ie(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, WFD_OUI, 4);
5555     }
5556 
5557     if (rtw_check_beacon_data(adapter, pbuf,  len) == _SUCCESS) {
5558 #ifdef CONFIG_P2P
5559         /* check p2p if enable */
5560         if (got_p2p_ie == _TRUE) {
5561             struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
5562             struct wifidirect_info *pwdinfo = &(adapter->wdinfo);
5563             pwdinfo->operating_channel = pmlmeext->cur_channel;
5564         }
5565 #endif /* CONFIG_P2P */
5566         ret = 0;
5567     } else
5568         ret = -EINVAL;
5569 
5570 exit:
5571     if (pbuf)
5572         rtw_mfree(pbuf, head_len + tail_len);
5573 
5574     return ret;
5575 }
5576 
5577 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(COMPAT_KERNEL_RELEASE)
cfg80211_rtw_add_beacon(struct wiphy * wiphy,struct net_device * ndev,struct beacon_parameters * info)5578 static int cfg80211_rtw_add_beacon(struct wiphy *wiphy, struct net_device *ndev,
5579         struct beacon_parameters *info)
5580 {
5581     int ret = 0;
5582     _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
5583 
5584     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
5585 
5586     if (rtw_cfg80211_sync_iftype(adapter) != _SUCCESS) {
5587         ret = -ENOTSUPP;
5588         goto exit;
5589     }
5590     rtw_mi_scan_abort(adapter, _TRUE);
5591     rtw_mi_buddy_set_scan_deny(adapter, 300);
5592     ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);
5593 
5594 exit:
5595     return ret;
5596 }
5597 
cfg80211_rtw_set_beacon(struct wiphy * wiphy,struct net_device * ndev,struct beacon_parameters * info)5598 static int cfg80211_rtw_set_beacon(struct wiphy *wiphy, struct net_device *ndev,
5599         struct beacon_parameters *info)
5600 {
5601     _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
5602     struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
5603 
5604     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
5605 
5606     pmlmeext->bstart_bss = _TRUE;
5607 
5608     cfg80211_rtw_add_beacon(wiphy, ndev, info);
5609 
5610     return 0;
5611 }
5612 
cfg80211_rtw_del_beacon(struct wiphy * wiphy,struct net_device * ndev)5613 static int    cfg80211_rtw_del_beacon(struct wiphy *wiphy, struct net_device *ndev)
5614 {
5615     _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
5616 
5617     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
5618 
5619     rtw_stop_ap_cmd(adapter, RTW_CMDF_WAIT_ACK);
5620     return 0;
5621 }
5622 #else
cfg80211_rtw_start_ap(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_ap_settings * settings)5623 static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
5624         struct cfg80211_ap_settings *settings)
5625 {
5626     int ret = 0;
5627     _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
5628 
5629     RTW_INFO(FUNC_NDEV_FMT" hidden_ssid:%d, auth_type:%d\n", FUNC_NDEV_ARG(ndev),
5630         settings->hidden_ssid, settings->auth_type);
5631 
5632     if (rtw_cfg80211_sync_iftype(adapter) != _SUCCESS) {
5633         ret = -ENOTSUPP;
5634         goto exit;
5635     }
5636 
5637     if (adapter_to_dvobj(adapter)->wpas_type == RTW_WPAS_W1FI) {
5638         struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
5639 
5640         /* turn on the beacon send */
5641         pmlmeext->bstart_bss = _TRUE;
5642     }
5643 
5644     /* Kernel < v5.x, the auth_type set as NL80211_AUTHTYPE_AUTOMATIC. if
5645      * the AKM SAE in the RSN IE, we have to update the auth_type for SAE in
5646      * rtw_check_beacon_data().
5647      *
5648      * we only update auth_type when rtw_check_beacon_data()
5649      */
5650     /* rtw_cfg80211_set_auth_type(&adapter->securitypriv, settings->auth_type); */
5651 
5652     rtw_mi_scan_abort(adapter, _TRUE);
5653     rtw_mi_buddy_set_scan_deny(adapter, 300);
5654 
5655     adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode = settings->hidden_ssid;
5656     ret = rtw_add_beacon(adapter, settings->beacon.head, settings->beacon.head_len,
5657         settings->beacon.tail, settings->beacon.tail_len);
5658 
5659 #ifdef CONFIG_RTW_80211R_AP
5660     rtw_ft_update_assocresp_ies(ndev, settings);
5661 #endif
5662 
5663     if (settings->beacon.assocresp_ies &&
5664         settings->beacon.assocresp_ies_len > 0) {
5665         rtw_cfg80211_set_assocresp_ies(ndev,
5666             settings->beacon.assocresp_ies,
5667             settings->beacon.assocresp_ies_len);
5668     }
5669 
5670     if (settings->ssid && settings->ssid_len) {
5671         WLAN_BSSID_EX *pbss_network = &adapter->mlmepriv.cur_network.network;
5672         WLAN_BSSID_EX *pbss_network_ext = &adapter->mlmeextpriv.mlmext_info.network;
5673 
5674         if (0)
5675             RTW_INFO(FUNC_ADPT_FMT" ssid:(%s,%zu), from ie:(%s,%d)\n", FUNC_ADPT_ARG(adapter),
5676                 settings->ssid, settings->ssid_len,
5677                 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength);
5678 
5679         _rtw_memcpy(pbss_network->Ssid.Ssid, (void *)settings->ssid, settings->ssid_len);
5680         pbss_network->Ssid.SsidLength = settings->ssid_len;
5681         _rtw_memcpy(pbss_network_ext->Ssid.Ssid, (void *)settings->ssid, settings->ssid_len);
5682         pbss_network_ext->Ssid.SsidLength = settings->ssid_len;
5683 
5684         if (0)
5685             RTW_INFO(FUNC_ADPT_FMT" after ssid:(%s,%d), (%s,%d)\n", FUNC_ADPT_ARG(adapter),
5686                 pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength,
5687                 pbss_network_ext->Ssid.Ssid, pbss_network_ext->Ssid.SsidLength);
5688     }
5689 
5690 exit:
5691     return ret;
5692 }
5693 
rtw_cfg80211_set_assocresp_ies(struct net_device * net,const u8 * buf,int len)5694 static int rtw_cfg80211_set_assocresp_ies(struct net_device *net, const u8 *buf, int len)
5695 {
5696     int ret = 0;
5697     _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
5698     struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5699 
5700     RTW_INFO("%s, ielen=%d\n", __func__, len);
5701 
5702     if (len <= 0)
5703         goto exit;
5704 
5705     if (pmlmepriv->assoc_rsp) {
5706         u32 free_len = pmlmepriv->assoc_rsp_len;
5707 
5708         pmlmepriv->assoc_rsp_len = 0;
5709         rtw_mfree(pmlmepriv->assoc_rsp, free_len);
5710         pmlmepriv->assoc_rsp = NULL;
5711     }
5712 
5713     pmlmepriv->assoc_rsp = rtw_malloc(len);
5714     if (pmlmepriv->assoc_rsp == NULL) {
5715         RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
5716         return -EINVAL;
5717     }
5718     _rtw_memcpy(pmlmepriv->assoc_rsp, buf, len);
5719     pmlmepriv->assoc_rsp_len = len;
5720 
5721 exit:
5722     return ret;
5723 }
5724 
cfg80211_rtw_change_beacon(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_beacon_data * info)5725 static int cfg80211_rtw_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
5726         struct cfg80211_beacon_data *info)
5727 {
5728     int ret = 0;
5729     _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
5730 
5731     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
5732 
5733 #ifdef not_yet
5734     /*
5735      * @proberesp_ies: extra information element(s) to add into Probe Response
5736      *    frames or %NULL
5737      * @proberesp_ies_len: length of proberesp_ies in octets
5738      */
5739     if (info->proberesp_ies_len > 0)
5740         rtw_cfg80211_set_proberesp_ies(ndev, info->proberesp_ies, info->proberesp_ies_len);
5741 #endif /* not_yet */
5742 
5743     if (info->assocresp_ies_len > 0)
5744         rtw_cfg80211_set_assocresp_ies(ndev, info->assocresp_ies, info->assocresp_ies_len);
5745 
5746     ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail, info->tail_len);
5747 
5748     return ret;
5749 }
5750 
cfg80211_rtw_stop_ap(struct wiphy * wiphy,struct net_device * ndev)5751 static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
5752 {
5753     _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
5754 
5755     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
5756 
5757     rtw_stop_ap_cmd(adapter, RTW_CMDF_WAIT_ACK);
5758     return 0;
5759 }
5760 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) */
5761 
5762 #if CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
cfg80211_rtw_set_mac_acl(struct wiphy * wiphy,struct net_device * ndev,const struct cfg80211_acl_data * params)5763 static int cfg80211_rtw_set_mac_acl(struct wiphy *wiphy, struct net_device *ndev,
5764         const struct cfg80211_acl_data *params)
5765 {
5766     _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
5767     u8 acl_mode = RTW_ACL_MODE_DISABLED;
5768     int ret = -1;
5769     int i;
5770 
5771     if (!params) {
5772         RTW_WARN(FUNC_ADPT_FMT" params NULL\n", FUNC_ADPT_ARG(adapter));
5773         rtw_macaddr_acl_clear(adapter, RTW_ACL_PERIOD_BSS);
5774         goto exit;
5775     }
5776 
5777     RTW_INFO(FUNC_ADPT_FMT" acl_policy:%d, entry_num:%d\n"
5778         , FUNC_ADPT_ARG(adapter), params->acl_policy, params->n_acl_entries);
5779 
5780     if (params->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED)
5781         acl_mode = RTW_ACL_MODE_ACCEPT_UNLESS_LISTED;
5782     else if (params->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
5783         acl_mode = RTW_ACL_MODE_DENY_UNLESS_LISTED;
5784 
5785     rtw_macaddr_acl_clear(adapter, RTW_ACL_PERIOD_BSS);
5786 
5787     rtw_set_macaddr_acl(adapter, RTW_ACL_PERIOD_BSS, acl_mode);
5788 
5789     for (i = 0; i < params->n_acl_entries; i++)
5790         rtw_acl_add_sta(adapter, RTW_ACL_PERIOD_BSS, params->mac_addrs[i].addr);
5791 
5792     ret = 0;
5793 
5794 exit:
5795     return ret;
5796 }
5797 #endif /* CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)) */
5798 
5799 const char *_nl80211_sta_flags_str[] = {
5800     "INVALID",
5801     "AUTHORIZED",
5802     "SHORT_PREAMBLE",
5803     "WME",
5804     "MFP",
5805     "AUTHENTICATED",
5806     "TDLS_PEER",
5807     "ASSOCIATED",
5808 };
5809 
5810 #define nl80211_sta_flags_str(_f) ((_f <= NL80211_STA_FLAG_MAX) ? _nl80211_sta_flags_str[_f] : _nl80211_sta_flags_str[0])
5811 
5812 const char *_nl80211_plink_state_str[] = {
5813     "LISTEN",
5814     "OPN_SNT",
5815     "OPN_RCVD",
5816     "CNF_RCVD",
5817     "ESTAB",
5818     "HOLDING",
5819     "BLOCKED",
5820     "UNKNOWN",
5821 };
5822 
5823 #define nl80211_plink_state_str(_s) ((_s < NUM_NL80211_PLINK_STATES) ? _nl80211_plink_state_str[_s] : _nl80211_plink_state_str[NUM_NL80211_PLINK_STATES])
5824 
5825 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0))
5826 #define NL80211_PLINK_ACTION_NO_ACTION PLINK_ACTION_INVALID
5827 #define NL80211_PLINK_ACTION_OPEN PLINK_ACTION_OPEN
5828 #define NL80211_PLINK_ACTION_BLOCK PLINK_ACTION_BLOCK
5829 #define NUM_NL80211_PLINK_ACTIONS 3
5830 #endif
5831 
5832 const char *_nl80211_plink_actions_str[] = {
5833     "NO_ACTION",
5834     "OPEN",
5835     "BLOCK",
5836     "UNKNOWN",
5837 };
5838 
5839 #define nl80211_plink_actions_str(_a) ((_a < NUM_NL80211_PLINK_ACTIONS) ? _nl80211_plink_actions_str[_a] : _nl80211_plink_actions_str[NUM_NL80211_PLINK_ACTIONS])
5840 
5841 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
5842 const char *_nl80211_mesh_power_mode_str[] = {
5843     "UNKNOWN",
5844     "ACTIVE",
5845     "LIGHT_SLEEP",
5846     "DEEP_SLEEP",
5847 };
5848 
5849 #define nl80211_mesh_power_mode_str(_p) ((_p <= NL80211_MESH_POWER_MAX) ? _nl80211_mesh_power_mode_str[_p] : _nl80211_mesh_power_mode_str[0])
5850 #endif
5851 
dump_station_parameters(void * sel,struct wiphy * wiphy,const struct station_parameters * params)5852 void dump_station_parameters(void *sel, struct wiphy *wiphy, const struct station_parameters *params)
5853 {
5854 #if DBG_RTW_CFG80211_STA_PARAM
5855     if (params->supported_rates_len) {
5856         #define SUPP_RATES_BUF_LEN (3 * RTW_G_RATES_NUM + 1)
5857         int i;
5858         char supp_rates_buf[SUPP_RATES_BUF_LEN] = {0};
5859         u8 cnt = 0;
5860 
5861         rtw_warn_on(params->supported_rates_len > RTW_G_RATES_NUM);
5862 
5863         for (i = 0; i < params->supported_rates_len; i++) {
5864             if (i >= RTW_G_RATES_NUM)
5865                 break;
5866             cnt += snprintf(supp_rates_buf + cnt, SUPP_RATES_BUF_LEN - cnt -1
5867                 , "%02X ", params->supported_rates[i]);
5868             if (cnt >= SUPP_RATES_BUF_LEN - 1)
5869                 break;
5870         }
5871 
5872         RTW_PRINT_SEL(sel, "supported_rates:%s\n", supp_rates_buf);
5873     }
5874 
5875     if (params->vlan)
5876         RTW_PRINT_SEL(sel, "vlan:"NDEV_FMT"\n", NDEV_ARG(params->vlan));
5877 
5878 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
5879     if (params->sta_flags_mask) {
5880         #define STA_FLAGS_BUF_LEN 128
5881         int i = 0;
5882         char sta_flags_buf[STA_FLAGS_BUF_LEN] = {0};
5883         u8 cnt = 0;
5884 
5885         for (i = 1; i <= NL80211_STA_FLAG_MAX; i++) {
5886             if (params->sta_flags_mask & BIT(i)) {
5887                 cnt += snprintf(sta_flags_buf + cnt, STA_FLAGS_BUF_LEN - cnt -1, "%s=%u "
5888                     , nl80211_sta_flags_str(i), (params->sta_flags_set & BIT(i)) ? 1 : 0);
5889                 if (cnt >= STA_FLAGS_BUF_LEN - 1)
5890                     break;
5891             }
5892         }
5893 
5894         RTW_PRINT_SEL(sel, "sta_flags:%s\n", sta_flags_buf);
5895     }
5896 #else
5897     u32 station_flags;
5898     #error "TBD\n"
5899 #endif
5900 
5901     if (params->listen_interval != -1)
5902         RTW_PRINT_SEL(sel, "listen_interval:%d\n", params->listen_interval);
5903 
5904     if (params->aid)
5905         RTW_PRINT_SEL(sel, "aid:%u\n", params->aid);
5906 
5907 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
5908     if (params->peer_aid)
5909         RTW_PRINT_SEL(sel, "peer_aid:%u\n", params->peer_aid);
5910 #endif
5911 
5912 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26))
5913     if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
5914         RTW_PRINT_SEL(sel, "plink_action:%s\n", nl80211_plink_actions_str(params->plink_action));
5915 #endif
5916 
5917 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
5918     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
5919     if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
5920     #endif
5921         RTW_PRINT_SEL(sel, "plink_state:%s\n"
5922             , nl80211_plink_state_str(params->plink_state));
5923 #endif
5924 
5925 #if 0 /* TODO */
5926 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
5927     const struct ieee80211_ht_cap *ht_capa;
5928 #endif
5929 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
5930     const struct ieee80211_vht_cap *vht_capa;
5931 #endif
5932 #endif
5933 
5934 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
5935     if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD)
5936         RTW_PRINT_SEL(sel, "uapsd_queues:0x%02x\n", params->uapsd_queues);
5937     if (params->max_sp)
5938         RTW_PRINT_SEL(sel, "max_sp:%u\n", params->max_sp);
5939 #endif
5940 
5941 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
5942     if (params->local_pm != NL80211_MESH_POWER_UNKNOWN) {
5943         RTW_PRINT_SEL(sel, "local_pm:%s\n"
5944             , nl80211_mesh_power_mode_str(params->local_pm));
5945     }
5946 
5947     if (params->sta_modify_mask & STATION_PARAM_APPLY_CAPABILITY)
5948         RTW_PRINT_SEL(sel, "capability:0x%04x\n", params->capability);
5949 
5950 #if 0 /* TODO */
5951     const u8 *ext_capab;
5952     u8 ext_capab_len;
5953 #endif
5954 #endif
5955 
5956 #if 0 /* TODO */
5957 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
5958     const u8 *supported_channels;
5959     u8 supported_channels_len;
5960     const u8 *supported_oper_classes;
5961     u8 supported_oper_classes_len;
5962 #endif
5963 
5964 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
5965     u8 opmode_notif;
5966     bool opmode_notif_used;
5967 #endif
5968 
5969 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
5970     int support_p2p_ps;
5971 #endif
5972 #endif
5973 #endif /* DBG_RTW_CFG80211_STA_PARAM */
5974 }
5975 
cfg80211_rtw_add_station(struct wiphy * wiphy,struct net_device * ndev,u8 * mac,struct station_parameters * params)5976 static int    cfg80211_rtw_add_station(struct wiphy *wiphy, struct net_device *ndev,
5977 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
5978     u8 *mac,
5979 #else
5980     const u8 *mac,
5981 #endif
5982     struct station_parameters *params)
5983 {
5984     int ret = 0;
5985     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
5986 #if defined(CONFIG_TDLS) || defined(CONFIG_RTW_MESH)
5987     struct sta_priv *pstapriv = &padapter->stapriv;
5988 #endif
5989 #ifdef CONFIG_TDLS
5990     struct sta_info *psta;
5991 #endif /* CONFIG_TDLS */
5992 
5993     RTW_INFO(FUNC_NDEV_FMT" mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(mac));
5994 
5995 #if CONFIG_RTW_MACADDR_ACL
5996     if (rtw_access_ctrl(padapter, mac) == _FALSE) {
5997         RTW_INFO(FUNC_NDEV_FMT" deny by macaddr ACL\n", FUNC_NDEV_ARG(ndev));
5998         ret = -EINVAL;
5999         goto exit;
6000     }
6001 #endif
6002 
6003     dump_station_parameters(RTW_DBGDUMP, wiphy, params);
6004 
6005 #ifdef CONFIG_RTW_MESH
6006     if (MLME_IS_MESH(padapter)) {
6007         struct rtw_mesh_cfg *mcfg = &padapter->mesh_cfg;
6008         struct rtw_mesh_info *minfo = &padapter->mesh_info;
6009         struct mesh_plink_pool *plink_ctl = &minfo->plink_ctl;
6010         struct mesh_plink_ent *plink = NULL;
6011         struct wlan_network *scanned = NULL;
6012         bool acnode = 0;
6013         u8 add_new_sta = 0, probe_req = 0;
6014         _irqL irqL;
6015 
6016         if (params->plink_state != NL80211_PLINK_LISTEN) {
6017             RTW_WARN(FUNC_NDEV_FMT" %s\n", FUNC_NDEV_ARG(ndev), nl80211_plink_state_str(params->plink_state));
6018             rtw_warn_on(1);
6019         }
6020         if (!params->aid || params->aid > pstapriv->max_aid) {
6021             RTW_WARN(FUNC_NDEV_FMT" invalid aid:%u\n", FUNC_NDEV_ARG(ndev), params->aid);
6022             rtw_warn_on(1);
6023             ret = -EINVAL;
6024             goto exit;
6025         }
6026 
6027         _enter_critical_bh(&(plink_ctl->lock), &irqL);
6028 
6029         plink = _rtw_mesh_plink_get(padapter, mac);
6030         if (plink)
6031             goto release_plink_ctl;
6032 
6033         #if CONFIG_RTW_MESH_PEER_BLACKLIST
6034         if (rtw_mesh_peer_blacklist_search(padapter, mac)) {
6035             RTW_INFO(FUNC_NDEV_FMT" deny by peer blacklist\n"
6036                 , FUNC_NDEV_ARG(ndev));
6037             ret = -EINVAL;
6038             goto release_plink_ctl;
6039         }
6040         #endif
6041 
6042         scanned = rtw_find_network(&padapter->mlmepriv.scanned_queue, mac);
6043         if (!scanned
6044             || rtw_get_passing_time_ms(scanned->last_scanned) >= mcfg->peer_sel_policy.scanr_exp_ms
6045         ) {
6046             if (!scanned)
6047                 RTW_INFO(FUNC_NDEV_FMT" corresponding network not found\n", FUNC_NDEV_ARG(ndev));
6048             else
6049                 RTW_INFO(FUNC_NDEV_FMT" corresponding network too old\n", FUNC_NDEV_ARG(ndev));
6050 
6051             if (adapter_to_rfctl(padapter)->offch_state == OFFCHS_NONE)
6052                 probe_req = 1;
6053 
6054             ret = -EINVAL;
6055             goto release_plink_ctl;
6056         }
6057 
6058         #if CONFIG_RTW_MESH_ACNODE_PREVENT
6059         if (plink_ctl->acnode_rsvd)
6060             acnode = rtw_mesh_scanned_is_acnode_confirmed(padapter, scanned);
6061         #endif
6062 
6063         /* wpa_supplicant's auto peer will initiate peering when candidate peer is reported without max_peer_links consideration */
6064         if (plink_ctl->num >= mcfg->max_peer_links + acnode ? 1 : 0) {
6065             RTW_INFO(FUNC_NDEV_FMT" exceed max_peer_links:%u%s\n"
6066                 , FUNC_NDEV_ARG(ndev), mcfg->max_peer_links, acnode ? " acn" : "");
6067             ret = -EINVAL;
6068             goto release_plink_ctl;
6069         }
6070 
6071         if (!rtw_bss_is_candidate_mesh_peer(padapter, &scanned->network, 1, 1)) {
6072             RTW_WARN(FUNC_NDEV_FMT" corresponding network is not candidate with same ch\n"
6073                 , FUNC_NDEV_ARG(ndev));
6074             ret = -EINVAL;
6075             goto release_plink_ctl;
6076         }
6077 
6078         #if CONFIG_RTW_MESH_CTO_MGATE_BLACKLIST
6079         if (!rtw_mesh_cto_mgate_network_filter(padapter, scanned)) {
6080             RTW_INFO(FUNC_NDEV_FMT" peer filtered out by cto_mgate check\n"
6081                 , FUNC_NDEV_ARG(ndev));
6082             ret = -EINVAL;
6083             goto release_plink_ctl;
6084         }
6085         #endif
6086 
6087         if (_rtw_mesh_plink_add(padapter, mac) == _SUCCESS) {
6088             /* hook corresponding network in scan queue */
6089             plink = _rtw_mesh_plink_get(padapter, mac);
6090             plink->aid = params->aid;
6091             plink->scanned = scanned;
6092 
6093             #if CONFIG_RTW_MESH_ACNODE_PREVENT
6094             if (acnode) {
6095                 RTW_INFO(FUNC_ADPT_FMT" acnode "MAC_FMT"\n"
6096                 , FUNC_ADPT_ARG(padapter), MAC_ARG(scanned->network.MacAddress));
6097             }
6098             #endif
6099 
6100             add_new_sta = 1;
6101         } else {
6102             RTW_WARN(FUNC_NDEV_FMT" rtw_mesh_plink_add not success\n"
6103                 , FUNC_NDEV_ARG(ndev));
6104             ret = -EINVAL;
6105         }
6106 release_plink_ctl:
6107         _exit_critical_bh(&(plink_ctl->lock), &irqL);
6108 
6109         if (probe_req)
6110             issue_probereq(padapter, &padapter->mlmepriv.cur_network.network.mesh_id, mac);
6111 
6112         if (add_new_sta) {
6113             struct station_info sinfo;
6114 
6115             #ifdef CONFIG_DFS_MASTER
6116             if (IS_UNDER_CAC(adapter_to_rfctl(padapter)))
6117                 rtw_force_stop_cac(adapter_to_rfctl(padapter), 300);
6118             #endif
6119 
6120             /* indicate new sta */
6121             _rtw_memset(&sinfo, 0, sizeof(sinfo));
6122             cfg80211_new_sta(ndev, mac, &sinfo, GFP_ATOMIC);
6123         }
6124         goto exit;
6125     }
6126 #endif /* CONFIG_RTW_MESH */
6127 
6128 #ifdef CONFIG_TDLS
6129     psta = rtw_get_stainfo(pstapriv, (u8 *)mac);
6130     if (psta == NULL) {
6131         psta = rtw_alloc_stainfo(pstapriv, (u8 *)mac);
6132         if (psta == NULL) {
6133             RTW_INFO("[%s] Alloc station for "MAC_FMT" fail\n", __FUNCTION__, MAC_ARG(mac));
6134             ret = -EOPNOTSUPP;
6135             goto exit;
6136         }
6137     }
6138 #endif /* CONFIG_TDLS */
6139 
6140 exit:
6141     return ret;
6142 }
6143 
cfg80211_rtw_del_station(struct wiphy * wiphy,struct net_device * ndev,u8 * mac)6144 static int    cfg80211_rtw_del_station(struct wiphy *wiphy, struct net_device *ndev,
6145 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
6146     u8 *mac
6147 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
6148     const u8 *mac
6149 #else
6150     struct station_del_parameters *params
6151 #endif
6152 )
6153 {
6154     int ret = 0;
6155     _irqL irqL;
6156     _list    *phead, *plist;
6157     u8 updated = _FALSE;
6158     const u8 *target_mac;
6159     struct sta_info *psta = NULL;
6160     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
6161     struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6162     struct sta_priv *pstapriv = &padapter->stapriv;
6163 
6164 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0))
6165     target_mac = mac;
6166 #else
6167     target_mac = params->mac;
6168 #endif
6169 
6170     RTW_INFO("+"FUNC_NDEV_FMT" mac=%pM\n", FUNC_NDEV_ARG(ndev), target_mac);
6171 
6172     if (check_fwstate(pmlmepriv, (WIFI_ASOC_STATE | WIFI_AP_STATE | WIFI_MESH_STATE)) != _TRUE) {
6173         RTW_INFO("%s, fw_state != FW_LINKED|WIFI_AP_STATE|WIFI_MESH_STATE\n", __func__);
6174         return -EINVAL;
6175     }
6176 
6177 
6178     if (!target_mac) {
6179         RTW_INFO("flush all sta, and cam_entry\n");
6180 
6181         flush_all_cam_entry(padapter);    /* clear CAM */
6182 
6183 #ifdef CONFIG_AP_MODE
6184         ret = rtw_sta_flush(padapter, _TRUE);
6185 #endif
6186         return ret;
6187     }
6188 
6189 
6190     RTW_INFO("free sta macaddr =" MAC_FMT "\n", MAC_ARG(target_mac));
6191 
6192     if (target_mac[0] == 0xff && target_mac[1] == 0xff &&
6193         target_mac[2] == 0xff && target_mac[3] == 0xff &&
6194         target_mac[4] == 0xff && target_mac[5] == 0xff)
6195         return -EINVAL;
6196 
6197 
6198     _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
6199 
6200     phead = &pstapriv->asoc_list;
6201     plist = get_next(phead);
6202 
6203     /* check asoc_queue */
6204     while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
6205         psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
6206 
6207         plist = get_next(plist);
6208 
6209         if (_rtw_memcmp((u8 *)target_mac, psta->cmn.mac_addr, ETH_ALEN)) {
6210             if (psta->dot8021xalg == 1 && psta->bpairwise_key_installed == _FALSE) {
6211                 RTW_INFO("%s, sta's dot8021xalg = 1 and key_installed = _FALSE\n", __func__);
6212 
6213                 #ifdef CONFIG_AP_MODE
6214                 if (MLME_IS_AP(padapter)) {
6215                     rtw_list_delete(&psta->asoc_list);
6216                     pstapriv->asoc_list_cnt--;
6217                     #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
6218                     if (psta->tbtx_enable)
6219                         pstapriv->tbtx_asoc_list_cnt--;
6220                     #endif
6221                     STA_SET_MESH_PLINK(psta, NULL);
6222 
6223                     ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_IEEE_802_1X_AUTH_FAILED, _TRUE);
6224                     psta = NULL;
6225                     break;
6226                 }
6227                 #endif
6228             } else {
6229                 RTW_INFO("free psta=%p, aid=%d\n", psta, psta->cmn.aid);
6230 
6231                 rtw_list_delete(&psta->asoc_list);
6232                 pstapriv->asoc_list_cnt--;
6233                 #ifdef CONFIG_RTW_TOKEN_BASED_XMIT
6234                 if (psta->tbtx_enable)
6235                     pstapriv->tbtx_asoc_list_cnt--;
6236                 #endif
6237                 STA_SET_MESH_PLINK(psta, NULL);
6238 
6239                 /* _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL); */
6240                 if (MLME_IS_AP(padapter))
6241                     updated = ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_PREV_AUTH_NOT_VALID, _TRUE);
6242                 else
6243                     updated = ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, _TRUE);
6244                 /* _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL); */
6245 
6246                 psta = NULL;
6247 
6248                 break;
6249             }
6250 
6251         }
6252 
6253     }
6254 
6255     _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
6256 
6257     associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
6258 
6259 #ifdef CONFIG_RTW_MESH
6260     if (MLME_IS_MESH(padapter))
6261         rtw_mesh_plink_del(padapter, target_mac);
6262 #endif
6263 
6264     RTW_INFO("-"FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
6265 
6266     return ret;
6267 
6268 }
6269 
cfg80211_rtw_change_station(struct wiphy * wiphy,struct net_device * ndev,u8 * mac,struct station_parameters * params)6270 static int    cfg80211_rtw_change_station(struct wiphy *wiphy, struct net_device *ndev,
6271 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0))
6272     u8 *mac,
6273 #else
6274     const u8 *mac,
6275 #endif
6276     struct station_parameters *params)
6277 {
6278     _adapter *adapter = (_adapter *)rtw_netdev_priv(ndev);
6279     int ret = 0;
6280 
6281     RTW_INFO(FUNC_ADPT_FMT" mac:"MAC_FMT"\n", FUNC_ADPT_ARG(adapter), MAC_ARG(mac));
6282 
6283     dump_station_parameters(RTW_DBGDUMP, wiphy, params);
6284 
6285 #ifdef CONFIG_RTW_MESH
6286     if (MLME_IS_MESH(adapter)) {
6287         enum cfg80211_station_type sta_type = CFG80211_STA_MESH_PEER_USER;
6288         u8 plink_state = nl80211_plink_state_to_rtw_plink_state(params->plink_state);
6289 
6290         ret = cfg80211_check_station_change(wiphy, params, sta_type);
6291         if (ret) {
6292             RTW_INFO("cfg80211_check_station_change return %d\n", ret);
6293             goto exit;
6294         }
6295 
6296         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
6297         if (!(params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE))
6298             goto exit;
6299         #endif
6300 
6301         if (rtw_mesh_set_plink_state_cmd(adapter, mac, plink_state) != _SUCCESS)
6302             ret = -ENOENT;
6303     }
6304 
6305 exit:
6306 #endif /* CONFIG_RTW_MESH */
6307 
6308     if (ret)
6309         RTW_INFO(FUNC_ADPT_FMT" mac:"MAC_FMT" ret:%d\n", FUNC_ADPT_ARG(adapter), MAC_ARG(mac), ret);
6310     return ret;
6311 }
6312 
rtw_sta_info_get_by_idx(struct sta_priv * pstapriv,const int idx,u8 * asoc_list_num)6313 struct sta_info *rtw_sta_info_get_by_idx(struct sta_priv *pstapriv, const int idx, u8 *asoc_list_num)
6314 {
6315     _list    *phead, *plist;
6316     struct sta_info *psta = NULL;
6317     int i = 0;
6318 
6319     phead = &pstapriv->asoc_list;
6320     plist = get_next(phead);
6321 
6322     /* check asoc_queue */
6323     while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
6324         if (idx == i)
6325             psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
6326         plist = get_next(plist);
6327         i++;
6328     }
6329 
6330     if (asoc_list_num)
6331         *asoc_list_num = i;
6332 
6333     return psta;
6334 }
6335 
cfg80211_rtw_dump_station(struct wiphy * wiphy,struct net_device * ndev,int idx,u8 * mac,struct station_info * sinfo)6336 static int    cfg80211_rtw_dump_station(struct wiphy *wiphy, struct net_device *ndev,
6337         int idx, u8 *mac, struct station_info *sinfo)
6338 {
6339 #define DBG_DUMP_STATION 0
6340 
6341     int ret = 0;
6342     _irqL irqL;
6343     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
6344     struct sta_priv *pstapriv = &padapter->stapriv;
6345     struct sta_info *psta = NULL;
6346 #ifdef CONFIG_RTW_MESH
6347     struct mesh_plink_ent *plink = NULL;
6348 #endif
6349     u8 asoc_list_num;
6350 
6351     if (DBG_DUMP_STATION)
6352         RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
6353 
6354     _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
6355     psta = rtw_sta_info_get_by_idx(pstapriv, idx, &asoc_list_num);
6356     _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
6357 
6358 #ifdef CONFIG_RTW_MESH
6359     if (MLME_IS_MESH(padapter)) {
6360         if (psta)
6361             plink = psta->plink;
6362         if (!plink)
6363             plink = rtw_mesh_plink_get_no_estab_by_idx(padapter, idx - asoc_list_num);
6364     }
6365 #endif /* CONFIG_RTW_MESH */
6366 
6367     if ((!MLME_IS_MESH(padapter) && !psta)
6368         #ifdef CONFIG_RTW_MESH
6369         || (MLME_IS_MESH(padapter) && !plink)
6370         #endif
6371     ) {
6372         if (DBG_DUMP_STATION)
6373             RTW_INFO(FUNC_NDEV_FMT" end with idx:%d\n", FUNC_NDEV_ARG(ndev), idx);
6374         ret = -ENOENT;
6375         goto exit;
6376     }
6377 
6378     if (psta)
6379         _rtw_memcpy(mac, psta->cmn.mac_addr, ETH_ALEN);
6380     #ifdef CONFIG_RTW_MESH
6381     else
6382         _rtw_memcpy(mac, plink->addr, ETH_ALEN);
6383     #endif
6384 
6385     sinfo->filled = 0;
6386 
6387     if (psta) {
6388         sinfo->filled |= STATION_INFO_SIGNAL;
6389         sinfo->signal = translate_percentage_to_dbm(psta->cmn.rssi_stat.rssi);
6390         sinfo->filled |= STATION_INFO_INACTIVE_TIME;
6391         sinfo->inactive_time = rtw_get_passing_time_ms(psta->sta_stats.last_rx_time);
6392     }
6393 
6394 #ifdef CONFIG_RTW_MESH
6395     if (MLME_IS_MESH(padapter))
6396         rtw_cfg80211_fill_mesh_only_sta_info(plink, psta, sinfo);
6397 #endif
6398 
6399 exit:
6400     return ret;
6401 }
6402 
6403 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
cfg80211_rtw_change_bss(struct wiphy * wiphy,struct net_device * ndev,struct bss_parameters * params)6404 static int    cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
6405         struct bss_parameters *params)
6406 {
6407     _adapter *adapter = rtw_netdev_priv(ndev);
6408 
6409     RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
6410 
6411 if (0) {
6412     if (params->use_cts_prot != -1)
6413         RTW_INFO("use_cts_prot=%d\n", params->use_cts_prot);
6414     if (params->use_short_preamble != -1)
6415         RTW_INFO("use_short_preamble=%d\n", params->use_short_preamble);
6416     if (params->use_short_slot_time != -1)
6417         RTW_INFO("use_short_slot_time=%d\n", params->use_short_slot_time);
6418 
6419 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
6420     if (params->basic_rates && params->basic_rates_len) {
6421         RTW_INFO("basic_rates_len=%d\n", params->basic_rates_len);
6422         RTW_INFO_DUMP("basic_rates=", params->basic_rates, params->basic_rates_len);
6423     }
6424 #endif
6425 }
6426 
6427 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
6428     if (params->ap_isolate != -1) {
6429         RTW_INFO("ap_isolate=%d\n", params->ap_isolate);
6430         adapter->mlmepriv.ap_isolate = params->ap_isolate ? 1 : 0;
6431     }
6432 #endif
6433 
6434 if (0) {
6435 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
6436     if (params->ht_opmode != -1)
6437         RTW_INFO("ht_opmode=0x%04x\n", params->ht_opmode);
6438 #endif
6439 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
6440     if (params->p2p_ctwindow != -1)
6441         RTW_INFO("p2p_ctwindow=%d\n", params->p2p_ctwindow);
6442     if (params->p2p_opp_ps != -1)
6443         RTW_INFO("p2p_opp_ps=%d\n", params->p2p_opp_ps);
6444 #endif
6445 }
6446     return 0;
6447 }
6448 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) */
6449 
6450 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
cfg80211_rtw_set_txq_params(struct wiphy * wiphy,struct net_device * ndev,struct ieee80211_txq_params * params)6451 static int    cfg80211_rtw_set_txq_params(struct wiphy *wiphy
6452 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
6453     , struct net_device *ndev
6454 #endif
6455     , struct ieee80211_txq_params *params)
6456 {
6457 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
6458     _adapter *padapter = rtw_netdev_priv(ndev);
6459 #else
6460     _adapter *padapter = wiphy_to_adapter(wiphy);
6461 #endif
6462     struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6463     struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6464     u8    ac, AIFS, ECWMin, ECWMax, aSifsTime;
6465     u16    TXOP;
6466     u8    shift_count = 0;
6467     u32    acParm;
6468 
6469 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
6470     ac = params->ac;
6471 #else
6472     ac = params->queue;
6473 #endif
6474 
6475     switch (ac) {
6476     case NL80211_TXQ_Q_VO:
6477         ac = XMIT_VO_QUEUE;
6478         break;
6479 
6480     case NL80211_TXQ_Q_VI:
6481         ac = XMIT_VI_QUEUE;
6482         break;
6483 
6484     case NL80211_TXQ_Q_BE:
6485         ac = XMIT_BE_QUEUE;
6486         break;
6487 
6488     case NL80211_TXQ_Q_BK:
6489         ac = XMIT_BK_QUEUE;
6490         break;
6491 
6492     default:
6493         break;
6494     }
6495 
6496 #if 0
6497     RTW_INFO("ac=%d\n", ac);
6498     RTW_INFO("txop=%u\n", params->txop);
6499     RTW_INFO("cwmin=%u\n", params->cwmin);
6500     RTW_INFO("cwmax=%u\n", params->cwmax);
6501     RTW_INFO("aifs=%u\n", params->aifs);
6502 #endif
6503 
6504     if (is_supported_5g(pmlmeext->cur_wireless_mode) ||
6505         (pmlmeext->cur_wireless_mode & WIRELESS_11_24N))
6506         aSifsTime = 16;
6507     else
6508         aSifsTime = 10;
6509 
6510     AIFS = params->aifs * pmlmeinfo->slotTime + aSifsTime;
6511 
6512     while ((params->cwmin + 1) >> shift_count != 1) {
6513         shift_count++;
6514         if (shift_count == 15)
6515             break;
6516     }
6517 
6518     ECWMin = shift_count;
6519 
6520     shift_count = 0;
6521     while ((params->cwmax + 1) >> shift_count != 1) {
6522         shift_count++;
6523         if (shift_count == 15)
6524             break;
6525     }
6526 
6527     ECWMax = shift_count;
6528 
6529     TXOP = le16_to_cpu(params->txop);
6530 
6531     acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
6532 
6533     set_txq_params_cmd(padapter, acParm, ac);
6534 
6535     return 0;
6536 }
6537 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) */
6538 
6539 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
cfg80211_rtw_set_channel(struct wiphy * wiphy,struct net_device * ndev,struct ieee80211_channel * chan,enum nl80211_channel_type channel_type)6540 static int    cfg80211_rtw_set_channel(struct wiphy *wiphy
6541     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
6542     , struct net_device *ndev
6543     #endif
6544     , struct ieee80211_channel *chan, enum nl80211_channel_type channel_type)
6545 {
6546 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
6547     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
6548 #else
6549     _adapter *padapter = wiphy_to_adapter(wiphy);
6550 #endif
6551     int chan_target = (u8) ieee80211_frequency_to_channel(chan->center_freq);
6552     int chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6553     int chan_width = CHANNEL_WIDTH_20;
6554 
6555 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35))
6556     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
6557 #endif
6558 
6559     switch (channel_type) {
6560     case NL80211_CHAN_NO_HT:
6561     case NL80211_CHAN_HT20:
6562         chan_width = CHANNEL_WIDTH_20;
6563         chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6564         break;
6565     case NL80211_CHAN_HT40MINUS:
6566         chan_width = CHANNEL_WIDTH_40;
6567         chan_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
6568         break;
6569     case NL80211_CHAN_HT40PLUS:
6570         chan_width = CHANNEL_WIDTH_40;
6571         chan_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
6572         break;
6573     default:
6574         chan_width = CHANNEL_WIDTH_20;
6575         chan_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6576         break;
6577     }
6578 
6579     RTW_INFO(FUNC_ADPT_FMT" ch:%d bw:%d, offset:%d\n"
6580         , FUNC_ADPT_ARG(padapter), chan_target, chan_width, chan_offset);
6581 
6582     rtw_set_chbw_cmd(padapter, chan_target, chan_width, chan_offset, RTW_CMDF_WAIT_ACK);
6583 
6584     return 0;
6585 }
6586 #endif /*#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))*/
6587 
6588 /*
6589 static int    cfg80211_rtw_auth(struct wiphy *wiphy, struct net_device *ndev,
6590         struct cfg80211_auth_request *req)
6591 {
6592     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
6593 
6594     return 0;
6595 }
6596 
6597 static int    cfg80211_rtw_assoc(struct wiphy *wiphy, struct net_device *ndev,
6598         struct cfg80211_assoc_request *req)
6599 {
6600     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
6601 
6602     return 0;
6603 }
6604 */
6605 
rtw_cfg80211_set_beacon_wpsp2pie(struct net_device * ndev,char * buf,int len)6606 static int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf, int len)
6607 {
6608     int ret = 0;
6609     uint wps_ielen = 0;
6610     u8 *wps_ie;
6611     u32    p2p_ielen = 0;
6612     u8 wps_oui[8] = {0x0, 0x50, 0xf2, 0x04};
6613     u8 *p2p_ie;
6614     u32    wfd_ielen = 0;
6615     u8 *wfd_ie;
6616     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
6617     struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6618     struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
6619 
6620     RTW_INFO(FUNC_NDEV_FMT" ielen=%d\n", FUNC_NDEV_ARG(ndev), len);
6621 
6622     if (len > 0) {
6623         wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen);
6624         if (wps_ie) {
6625             #ifdef CONFIG_DEBUG_CFG80211
6626             RTW_INFO("bcn_wps_ielen=%d\n", wps_ielen);
6627             #endif
6628 
6629             if (pmlmepriv->wps_beacon_ie) {
6630                 u32 free_len = pmlmepriv->wps_beacon_ie_len;
6631                 pmlmepriv->wps_beacon_ie_len = 0;
6632                 rtw_mfree(pmlmepriv->wps_beacon_ie, free_len);
6633                 pmlmepriv->wps_beacon_ie = NULL;
6634             }
6635 
6636             pmlmepriv->wps_beacon_ie = rtw_malloc(wps_ielen);
6637             if (pmlmepriv->wps_beacon_ie == NULL) {
6638                 RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
6639                 return -EINVAL;
6640 
6641             }
6642 
6643             _rtw_memcpy(pmlmepriv->wps_beacon_ie, wps_ie, wps_ielen);
6644             pmlmepriv->wps_beacon_ie_len = wps_ielen;
6645 
6646             update_beacon(padapter, _VENDOR_SPECIFIC_IE_, wps_oui, _TRUE, RTW_CMDF_WAIT_ACK);
6647 
6648         }
6649 
6650         /* buf += wps_ielen; */
6651         /* len -= wps_ielen; */
6652 
6653         #ifdef CONFIG_P2P
6654         p2p_ie = rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen);
6655         if (p2p_ie) {
6656             #ifdef CONFIG_DEBUG_CFG80211
6657             RTW_INFO("bcn_p2p_ielen=%d\n", p2p_ielen);
6658             #endif
6659 
6660             if (pmlmepriv->p2p_beacon_ie) {
6661                 u32 free_len = pmlmepriv->p2p_beacon_ie_len;
6662                 pmlmepriv->p2p_beacon_ie_len = 0;
6663                 rtw_mfree(pmlmepriv->p2p_beacon_ie, free_len);
6664                 pmlmepriv->p2p_beacon_ie = NULL;
6665             }
6666 
6667             pmlmepriv->p2p_beacon_ie = rtw_malloc(p2p_ielen);
6668             if (pmlmepriv->p2p_beacon_ie == NULL) {
6669                 RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
6670                 return -EINVAL;
6671 
6672             }
6673 
6674             _rtw_memcpy(pmlmepriv->p2p_beacon_ie, p2p_ie, p2p_ielen);
6675             pmlmepriv->p2p_beacon_ie_len = p2p_ielen;
6676 
6677         }
6678         #endif /* CONFIG_P2P */
6679 
6680 
6681         #ifdef CONFIG_WFD
6682         wfd_ie = rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen);
6683         if (wfd_ie) {
6684             #ifdef CONFIG_DEBUG_CFG80211
6685             RTW_INFO("bcn_wfd_ielen=%d\n", wfd_ielen);
6686             #endif
6687 
6688             if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_BEACON_IE, wfd_ie, wfd_ielen) != _SUCCESS)
6689                 return -EINVAL;
6690         }
6691         #endif /* CONFIG_WFD */
6692 
6693         pmlmeext->bstart_bss = _TRUE;
6694 
6695     }
6696 
6697     return ret;
6698 
6699 }
6700 
rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device * net,char * buf,int len)6701 static int rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device *net, char *buf, int len)
6702 {
6703     int ret = 0;
6704     uint wps_ielen = 0;
6705     u8 *wps_ie;
6706     u32    p2p_ielen = 0;
6707     u8 *p2p_ie;
6708     u32    wfd_ielen = 0;
6709     u8 *wfd_ie;
6710     _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
6711     struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6712 
6713 #ifdef CONFIG_DEBUG_CFG80211
6714     RTW_INFO("%s, ielen=%d\n", __func__, len);
6715 #endif
6716 
6717     if (len > 0) {
6718         wps_ie = rtw_get_wps_ie(buf, len, NULL, &wps_ielen);
6719         if (wps_ie) {
6720             uint    attr_contentlen = 0;
6721             u16    uconfig_method, *puconfig_method = NULL;
6722 
6723             #ifdef CONFIG_DEBUG_CFG80211
6724             RTW_INFO("probe_resp_wps_ielen=%d\n", wps_ielen);
6725             #endif
6726 
6727             if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
6728                 u8 sr = 0;
6729                 rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
6730 
6731                 if (sr != 0)
6732                     RTW_INFO("%s, got sr\n", __func__);
6733                 else {
6734                     RTW_INFO("GO mode process WPS under site-survey,  sr no set\n");
6735                     return ret;
6736                 }
6737             }
6738 
6739             if (pmlmepriv->wps_probe_resp_ie) {
6740                 u32 free_len = pmlmepriv->wps_probe_resp_ie_len;
6741                 pmlmepriv->wps_probe_resp_ie_len = 0;
6742                 rtw_mfree(pmlmepriv->wps_probe_resp_ie, free_len);
6743                 pmlmepriv->wps_probe_resp_ie = NULL;
6744             }
6745 
6746             pmlmepriv->wps_probe_resp_ie = rtw_malloc(wps_ielen);
6747             if (pmlmepriv->wps_probe_resp_ie == NULL) {
6748                 RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
6749                 return -EINVAL;
6750 
6751             }
6752 
6753             /* add PUSH_BUTTON config_method by driver self in wpsie of probe_resp at GO Mode */
6754             puconfig_method = (u16 *)rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_CONF_METHOD , NULL, &attr_contentlen);
6755             if (puconfig_method != NULL) {
6756                 /* struct registry_priv *pregistrypriv = &padapter->registrypriv; */
6757                 struct wireless_dev *wdev = padapter->rtw_wdev;
6758 
6759                 #ifdef CONFIG_DEBUG_CFG80211
6760                 /* printk("config_method in wpsie of probe_resp = 0x%x\n", be16_to_cpu(*puconfig_method)); */
6761                 #endif
6762 
6763                 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
6764                 /* for WIFI-DIRECT LOGO 4.2.2, AUTO GO can't set PUSH_BUTTON flags */
6765                 if (wdev->iftype == NL80211_IFTYPE_P2P_GO) {
6766                     uconfig_method = WPS_CM_PUSH_BUTTON;
6767                     uconfig_method = cpu_to_be16(uconfig_method);
6768 
6769                     *puconfig_method &= ~uconfig_method;
6770                 }
6771                 #endif
6772             }
6773 
6774             _rtw_memcpy(pmlmepriv->wps_probe_resp_ie, wps_ie, wps_ielen);
6775             pmlmepriv->wps_probe_resp_ie_len = wps_ielen;
6776 
6777         }
6778 
6779         /* buf += wps_ielen; */
6780         /* len -= wps_ielen; */
6781 
6782         #ifdef CONFIG_P2P
6783         p2p_ie = rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen);
6784         if (p2p_ie) {
6785             u8 is_GO = _FALSE;
6786             u32 attr_contentlen = 0;
6787             u16 cap_attr = 0;
6788 
6789             #ifdef CONFIG_DEBUG_CFG80211
6790             RTW_INFO("probe_resp_p2p_ielen=%d\n", p2p_ielen);
6791             #endif
6792 
6793             /* Check P2P Capability ATTR */
6794             attr_contentlen = sizeof(cap_attr);
6795             if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&cap_attr, (uint *) &attr_contentlen)) {
6796                 u8 grp_cap = 0;
6797                 /* RTW_INFO( "[%s] Got P2P Capability Attr!!\n", __FUNCTION__ ); */
6798                 cap_attr = le16_to_cpu(cap_attr);
6799                 grp_cap = (u8)((cap_attr >> 8) & 0xff);
6800 
6801                 is_GO = (grp_cap & BIT(0)) ? _TRUE : _FALSE;
6802 
6803                 if (is_GO)
6804                     RTW_INFO("Got P2P Capability Attr, grp_cap=0x%x, is_GO\n", grp_cap);
6805             }
6806 
6807 
6808             if (is_GO == _FALSE) {
6809                 if (pmlmepriv->p2p_probe_resp_ie) {
6810                     u32 free_len = pmlmepriv->p2p_probe_resp_ie_len;
6811                     pmlmepriv->p2p_probe_resp_ie_len = 0;
6812                     rtw_mfree(pmlmepriv->p2p_probe_resp_ie, free_len);
6813                     pmlmepriv->p2p_probe_resp_ie = NULL;
6814                 }
6815 
6816                 pmlmepriv->p2p_probe_resp_ie = rtw_malloc(p2p_ielen);
6817                 if (pmlmepriv->p2p_probe_resp_ie == NULL) {
6818                     RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
6819                     return -EINVAL;
6820 
6821                 }
6822                 _rtw_memcpy(pmlmepriv->p2p_probe_resp_ie, p2p_ie, p2p_ielen);
6823                 pmlmepriv->p2p_probe_resp_ie_len = p2p_ielen;
6824             } else {
6825                 if (pmlmepriv->p2p_go_probe_resp_ie) {
6826                     u32 free_len = pmlmepriv->p2p_go_probe_resp_ie_len;
6827                     pmlmepriv->p2p_go_probe_resp_ie_len = 0;
6828                     rtw_mfree(pmlmepriv->p2p_go_probe_resp_ie, free_len);
6829                     pmlmepriv->p2p_go_probe_resp_ie = NULL;
6830                 }
6831 
6832                 pmlmepriv->p2p_go_probe_resp_ie = rtw_malloc(p2p_ielen);
6833                 if (pmlmepriv->p2p_go_probe_resp_ie == NULL) {
6834                     RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
6835                     return -EINVAL;
6836 
6837                 }
6838                 _rtw_memcpy(pmlmepriv->p2p_go_probe_resp_ie, p2p_ie, p2p_ielen);
6839                 pmlmepriv->p2p_go_probe_resp_ie_len = p2p_ielen;
6840             }
6841 
6842         }
6843         #endif /* CONFIG_P2P */
6844 
6845 
6846         #ifdef CONFIG_WFD
6847         wfd_ie = rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen);
6848         #ifdef CONFIG_DEBUG_CFG80211
6849         RTW_INFO("probe_resp_wfd_ielen=%d\n", wfd_ielen);
6850         #endif
6851 
6852         if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_PROBE_RESP_IE, wfd_ie, wfd_ielen) != _SUCCESS)
6853             return -EINVAL;
6854         #endif /* CONFIG_WFD */
6855 
6856     }
6857 
6858     return ret;
6859 
6860 }
6861 
rtw_cfg80211_set_assoc_resp_wpsp2pie(struct net_device * net,char * buf,int len)6862 static int rtw_cfg80211_set_assoc_resp_wpsp2pie(struct net_device *net, char *buf, int len)
6863 {
6864     int ret = 0;
6865     _adapter *padapter = (_adapter *)rtw_netdev_priv(net);
6866     struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
6867     u8 *ie;
6868     u32 ie_len;
6869 
6870     RTW_INFO("%s, ielen=%d\n", __func__, len);
6871 
6872     if (len <= 0)
6873         goto exit;
6874 
6875     ie = rtw_get_wps_ie(buf, len, NULL, &ie_len);
6876     if (ie && ie_len) {
6877         if (pmlmepriv->wps_assoc_resp_ie) {
6878             u32 free_len = pmlmepriv->wps_assoc_resp_ie_len;
6879 
6880             pmlmepriv->wps_assoc_resp_ie_len = 0;
6881             rtw_mfree(pmlmepriv->wps_assoc_resp_ie, free_len);
6882             pmlmepriv->wps_assoc_resp_ie = NULL;
6883         }
6884 
6885         pmlmepriv->wps_assoc_resp_ie = rtw_malloc(ie_len);
6886         if (pmlmepriv->wps_assoc_resp_ie == NULL) {
6887             RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
6888             return -EINVAL;
6889         }
6890         _rtw_memcpy(pmlmepriv->wps_assoc_resp_ie, ie, ie_len);
6891         pmlmepriv->wps_assoc_resp_ie_len = ie_len;
6892     }
6893 #ifdef CONFIG_P2P
6894     ie = rtw_get_p2p_ie(buf, len, NULL, &ie_len);
6895     if (ie && ie_len) {
6896         if (pmlmepriv->p2p_assoc_resp_ie) {
6897             u32 free_len = pmlmepriv->p2p_assoc_resp_ie_len;
6898 
6899             pmlmepriv->p2p_assoc_resp_ie_len = 0;
6900             rtw_mfree(pmlmepriv->p2p_assoc_resp_ie, free_len);
6901             pmlmepriv->p2p_assoc_resp_ie = NULL;
6902         }
6903 
6904         pmlmepriv->p2p_assoc_resp_ie = rtw_malloc(ie_len);
6905         if (pmlmepriv->p2p_assoc_resp_ie == NULL) {
6906             RTW_INFO("%s()-%d: rtw_malloc() ERROR!\n", __FUNCTION__, __LINE__);
6907             return -EINVAL;
6908         }
6909         _rtw_memcpy(pmlmepriv->p2p_assoc_resp_ie, ie, ie_len);
6910         pmlmepriv->p2p_assoc_resp_ie_len = ie_len;
6911     }
6912 #endif
6913 #ifdef CONFIG_WFD
6914     ie = rtw_get_wfd_ie(buf, len, NULL, &ie_len);
6915     if (rtw_mlme_update_wfd_ie_data(pmlmepriv, MLME_ASSOC_RESP_IE, ie, ie_len) != _SUCCESS)
6916         return -EINVAL;
6917 #endif
6918 
6919 exit:
6920     return ret;
6921 }
6922 
rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device * net,char * buf,int len,int type)6923 int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len,
6924     int type)
6925 {
6926     int ret = 0;
6927     uint wps_ielen = 0;
6928     u32    p2p_ielen = 0;
6929 
6930 #ifdef CONFIG_DEBUG_CFG80211
6931     RTW_INFO("%s, ielen=%d\n", __func__, len);
6932 #endif
6933 
6934     if ((rtw_get_wps_ie(buf, len, NULL, &wps_ielen) && (wps_ielen > 0))
6935         #ifdef CONFIG_P2P
6936         || (rtw_get_p2p_ie(buf, len, NULL, &p2p_ielen) && (p2p_ielen > 0))
6937         #endif
6938     ) {
6939         if (net != NULL) {
6940             switch (type) {
6941             case 0x1: /* BEACON */
6942                 ret = rtw_cfg80211_set_beacon_wpsp2pie(net, buf, len);
6943                 break;
6944             case 0x2: /* PROBE_RESP */
6945                 ret = rtw_cfg80211_set_probe_resp_wpsp2pie(net, buf, len);
6946                 #ifdef CONFIG_P2P
6947                 if (ret == 0)
6948                     adapter_wdev_data((_adapter *)rtw_netdev_priv(net))->probe_resp_ie_update_time = rtw_get_current_time();
6949                 #endif
6950                 break;
6951             case 0x4: /* ASSOC_RESP */
6952                 ret = rtw_cfg80211_set_assoc_resp_wpsp2pie(net, buf, len);
6953                 break;
6954             }
6955         }
6956     }
6957 
6958     return ret;
6959 
6960 }
6961 #endif /* CONFIG_AP_MODE */
6962 
6963 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
6964 static struct wireless_dev *
6965 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
6966 static struct net_device *
6967 #else
6968 static int
6969 #endif
cfg80211_rtw_add_virtual_intf(struct wiphy * wiphy,const char * name,unsigned char name_assign_type,enum nl80211_iftype type,u32 * flags,struct vif_params * params)6970     cfg80211_rtw_add_virtual_intf(
6971         struct wiphy *wiphy,
6972         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
6973         const char *name,
6974         #else
6975         char *name,
6976         #endif
6977         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
6978         unsigned char name_assign_type,
6979         #endif
6980         enum nl80211_iftype type,
6981         #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
6982         u32 *flags,
6983         #endif
6984         struct vif_params *params)
6985 {
6986     int ret = 0;
6987     struct wireless_dev *wdev = NULL;
6988     struct net_device *ndev = NULL;
6989     _adapter *padapter;
6990     struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);
6991 
6992     rtw_set_rtnl_lock_holder(dvobj, current);
6993 
6994     RTW_INFO(FUNC_WIPHY_FMT" name:%s, type:%d\n", FUNC_WIPHY_ARG(wiphy), name, type);
6995 
6996     switch (type) {
6997     case NL80211_IFTYPE_MONITOR:
6998         padapter = wiphy_to_adapter(wiphy); /* TODO: get ap iface ? */
6999         ret = rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);
7000         if (ret == 0)
7001             wdev = ndev->ieee80211_ptr;
7002         break;
7003 
7004 #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
7005     case NL80211_IFTYPE_P2P_CLIENT:
7006     case NL80211_IFTYPE_P2P_GO:
7007 #endif
7008     case NL80211_IFTYPE_STATION:
7009     case NL80211_IFTYPE_AP:
7010 #ifdef CONFIG_RTW_MESH
7011     case NL80211_IFTYPE_MESH_POINT:
7012 #endif
7013         padapter = dvobj_get_unregisterd_adapter(dvobj);
7014         if (!padapter) {
7015             RTW_WARN("adapter pool empty!\n");
7016             ret = -ENODEV;
7017             break;
7018         }
7019 
7020         #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_P2P)
7021         #if defined(CONFIG_P2P) && ((KERNEL_VERSION(2, 6, 37) <= LINUX_VERSION_CODE) || defined(COMPAT_KERNEL_RELEASE))
7022         if ((type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO) && (padapter->iface_id != padapter->registrypriv.sel_p2p_iface)) {
7023             RTW_ERR("%s, iface_id:%d is not P2P interface!\n", __func__, padapter->iface_id);
7024             ret = -EOPNOTSUPP;
7025             break;
7026         }
7027         #endif
7028         #endif
7029 
7030         if (rtw_os_ndev_init(padapter, name) != _SUCCESS) {
7031             RTW_WARN("ndev init fail!\n");
7032             ret = -ENODEV;
7033             break;
7034         }
7035         #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
7036         if (type == NL80211_IFTYPE_P2P_CLIENT || type == NL80211_IFTYPE_P2P_GO)
7037             rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);
7038         #endif
7039         ndev = padapter->pnetdev;
7040         wdev = ndev->ieee80211_ptr;
7041         break;
7042 
7043 #if defined(CONFIG_P2P) && defined(RTW_DEDICATED_P2P_DEVICE)
7044     case NL80211_IFTYPE_P2P_DEVICE:
7045         ret = rtw_pd_iface_alloc(wiphy, name, &wdev);
7046         break;
7047 #endif
7048 
7049     case NL80211_IFTYPE_ADHOC:
7050     case NL80211_IFTYPE_AP_VLAN:
7051     case NL80211_IFTYPE_WDS:
7052     default:
7053         ret = -ENODEV;
7054         RTW_INFO("Unsupported interface type\n");
7055         break;
7056     }
7057 
7058     if (ndev)
7059         RTW_INFO(FUNC_WIPHY_FMT" ndev:%p, ret:%d\n", FUNC_WIPHY_ARG(wiphy), ndev, ret);
7060     else
7061         RTW_INFO(FUNC_WIPHY_FMT" wdev:%p, ret:%d\n", FUNC_WIPHY_ARG(wiphy), wdev, ret);
7062 
7063     rtw_set_rtnl_lock_holder(dvobj, NULL);
7064 
7065 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
7066     return wdev ? wdev : ERR_PTR(ret);
7067 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
7068     return ndev ? ndev : ERR_PTR(ret);
7069 #else
7070     return ret;
7071 #endif
7072 }
7073 
cfg80211_rtw_del_virtual_intf(struct wiphy * wiphy,struct wireless_dev * wdev)7074 static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
7075 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
7076     struct wireless_dev *wdev
7077 #else
7078     struct net_device *ndev
7079 #endif
7080 )
7081 {
7082 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
7083     struct net_device *ndev = wdev_to_ndev(wdev);
7084 #endif
7085     int ret = 0;
7086     struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);
7087     _adapter *adapter;
7088     struct rtw_wdev_priv *pwdev_priv;
7089 
7090     rtw_set_rtnl_lock_holder(dvobj, current);
7091 
7092     if (ndev) {
7093         adapter = (_adapter *)rtw_netdev_priv(ndev);
7094         pwdev_priv = adapter_wdev_data(adapter);
7095 
7096         if (ndev == pwdev_priv->pmon_ndev) {
7097             unregister_netdevice(ndev);
7098             pwdev_priv->pmon_ndev = NULL;
7099             pwdev_priv->ifname_mon[0] = '\0';
7100             RTW_INFO(FUNC_NDEV_FMT" remove monitor ndev\n", FUNC_NDEV_ARG(ndev));
7101         } else {
7102             RTW_INFO(FUNC_NDEV_FMT" unregister ndev\n", FUNC_NDEV_ARG(ndev));
7103             rtw_os_ndev_unregister(adapter);
7104         }
7105     } else
7106 #if defined(CONFIG_P2P) && defined(RTW_DEDICATED_P2P_DEVICE)
7107     if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
7108         if (wdev == wiphy_to_pd_wdev(wiphy))
7109             rtw_pd_iface_free(wiphy);
7110         else {
7111             RTW_ERR(FUNC_WIPHY_FMT" unknown P2P Device wdev:%p\n", FUNC_WIPHY_ARG(wiphy), wdev);
7112             rtw_warn_on(1);
7113         }
7114     } else
7115 #endif
7116     {
7117         ret = -EINVAL;
7118         goto exit;
7119     }
7120 
7121 exit:
7122     rtw_set_rtnl_lock_holder(dvobj, NULL);
7123     return ret;
7124 }
7125 
7126 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
cfg80211_rtw_get_channel(struct wiphy * wiphy,struct wireless_dev * wdev,struct cfg80211_chan_def * chandef)7127 static int cfg80211_rtw_get_channel(struct wiphy *wiphy,
7128     struct wireless_dev *wdev,
7129     struct cfg80211_chan_def *chandef)
7130 {
7131     _adapter *padapter = wiphy_to_adapter(wiphy);
7132     struct mlme_ext_priv *mlmeext = &(padapter->mlmeextpriv);
7133     u8 ht_option = 0;
7134     u8 report = 0;
7135     int retval = 1;
7136 
7137     if (MLME_IS_ASOC(padapter)) {
7138 #ifdef CONFIG_80211N_HT
7139         ht_option = padapter->mlmepriv.htpriv.ht_option;
7140 #endif /* CONFIG_80211N_HT */
7141         report = 1;
7142     } else if (MLME_IS_MONITOR(padapter)) {
7143         /* monitor mode always set to HT
7144            we don't support sniffer No HT */
7145         ht_option = 1;
7146         report = 1;
7147     }
7148 
7149     if (report) {
7150         rtw_chbw_to_cfg80211_chan_def(wiphy, chandef,
7151             mlmeext->cur_channel, mlmeext->cur_bwmode,
7152             mlmeext->cur_ch_offset, ht_option);
7153         retval = 0;
7154     }
7155 
7156     return retval;
7157 }
7158 
rtw_get_chbwoff_from_cfg80211_chan_def(struct cfg80211_chan_def * chandef,u8 * ht,u8 * ch,u8 * bw,u8 * offset)7159 static void rtw_get_chbwoff_from_cfg80211_chan_def(
7160     struct cfg80211_chan_def *chandef,
7161     u8 *ht, u8 *ch, u8 *bw, u8 *offset)
7162 {
7163     struct ieee80211_channel *chan = chandef->chan;
7164 
7165     *ch = chan->hw_value;
7166     *ht = 1;
7167 
7168     switch (chandef->width) {
7169     case NL80211_CHAN_WIDTH_20_NOHT:
7170         *ht = 0;
7171         fallthrough;
7172         /* fall through */
7173     case NL80211_CHAN_WIDTH_20:
7174         *bw = CHANNEL_WIDTH_20;
7175         *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7176         break;
7177     case NL80211_CHAN_WIDTH_40:
7178         *bw = CHANNEL_WIDTH_40;
7179         *offset = (chandef->center_freq1 > chan->center_freq) ?
7180             HAL_PRIME_CHNL_OFFSET_LOWER : HAL_PRIME_CHNL_OFFSET_UPPER;
7181         break;
7182     case NL80211_CHAN_WIDTH_80:
7183         *bw = CHANNEL_WIDTH_80;
7184         *offset = (chandef->center_freq1 > chan->center_freq) ?
7185             HAL_PRIME_CHNL_OFFSET_LOWER : HAL_PRIME_CHNL_OFFSET_UPPER;
7186         break;
7187     case NL80211_CHAN_WIDTH_160:
7188         *bw = CHANNEL_WIDTH_160;
7189         *offset = (chandef->center_freq1 > chan->center_freq) ?
7190             HAL_PRIME_CHNL_OFFSET_LOWER : HAL_PRIME_CHNL_OFFSET_UPPER;
7191         break;
7192     case NL80211_CHAN_WIDTH_80P80:
7193         *bw = CHANNEL_WIDTH_80_80;
7194         *offset = (chandef->center_freq1 > chan->center_freq) ?
7195             HAL_PRIME_CHNL_OFFSET_LOWER : HAL_PRIME_CHNL_OFFSET_UPPER;
7196         break;
7197 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
7198     case NL80211_CHAN_WIDTH_5:
7199         *bw = CHANNEL_WIDTH_5;
7200         *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7201         break;
7202     case NL80211_CHAN_WIDTH_10:
7203         *bw = CHANNEL_WIDTH_10;
7204         *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7205         break;
7206 #endif
7207     default:
7208         *ht = 0;
7209         *bw = CHANNEL_WIDTH_20;
7210         *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7211         RTW_INFO("unsupported cwidth:%u\n", chandef->width);
7212         rtw_warn_on(1);
7213     };
7214 }
7215 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) */
7216 
cfg80211_rtw_set_monitor_channel(struct wiphy * wiphy,struct cfg80211_chan_def * chandef)7217 static int cfg80211_rtw_set_monitor_channel(struct wiphy *wiphy
7218 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
7219     , struct cfg80211_chan_def *chandef
7220 #else
7221     , struct ieee80211_channel *chan
7222     , enum nl80211_channel_type channel_type
7223 #endif
7224     )
7225 {
7226     _adapter *padapter = wiphy_to_adapter(wiphy);
7227     u8 target_channal, target_offset, target_width, ht_option;
7228 
7229 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
7230 #ifdef CONFIG_DEBUG_CFG80211
7231     RTW_INFO("center_freq %u Mhz ch %u width %u freq1 %u freq2 %u\n"
7232         , chandef->chan->center_freq
7233         , chandef->chan->hw_value
7234         , chandef->width
7235         , chandef->center_freq1
7236         , chandef->center_freq2);
7237 #endif /* CONFIG_DEBUG_CFG80211 */
7238 
7239     rtw_get_chbwoff_from_cfg80211_chan_def(chandef,
7240         &ht_option, &target_channal, &target_width, &target_offset);
7241 #else
7242 #ifdef CONFIG_DEBUG_CFG80211
7243     RTW_INFO("center_freq %u Mhz ch %u channel_type %u\n"
7244         , chan->center_freq
7245         , chan->hw_value
7246         , channel_type);
7247 #endif /* CONFIG_DEBUG_CFG80211 */
7248 
7249     rtw_get_chbw_from_nl80211_channel_type(chan, channel_type,
7250         &ht_option, &target_channal, &target_width, &target_offset);
7251 #endif
7252     RTW_INFO(FUNC_ADPT_FMT" ch:%d bw:%d, offset:%d\n",
7253         FUNC_ADPT_ARG(padapter), target_channal,
7254         target_width, target_offset);
7255 
7256     rtw_set_chbw_cmd(padapter, target_channal, target_width,
7257         target_offset, RTW_CMDF_WAIT_ACK);
7258 
7259     return 0;
7260 }
7261 
rtw_cfg80211_external_auth_request(_adapter * padapter,union recv_frame * rframe)7262 void rtw_cfg80211_external_auth_request(_adapter *padapter, union recv_frame *rframe)
7263 {
7264     struct rtw_external_auth_params params;
7265     struct wireless_dev *wdev = padapter->rtw_wdev;
7266     struct net_device *netdev = wdev_to_ndev(wdev);
7267     struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
7268     struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
7269 
7270     u8 frame[256] = { 0 };
7271     uint frame_len = 24;
7272     s32 freq = 0;
7273 
7274     /* rframe, in this case is null point */
7275 
7276     freq = rtw_ch2freq(pmlmeext->cur_channel);
7277 
7278 #if (KERNEL_VERSION(4, 17, 0) <= LINUX_VERSION_CODE) \
7279     || defined(CONFIG_KERNEL_PATCH_EXTERNAL_AUTH)
7280     params.action = EXTERNAL_AUTH_START;
7281     _rtw_memcpy(params.bssid, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
7282     params.ssid.ssid_len = pmlmeinfo->network.Ssid.SsidLength;
7283     _rtw_memcpy(params.ssid.ssid, pmlmeinfo->network.Ssid.Ssid,
7284         pmlmeinfo->network.Ssid.SsidLength);
7285     params.key_mgmt_suite = 0x8ac0f00;
7286 
7287     RTW_INFO("external auth: use kernel API: cfg80211_external_auth_request()\n");
7288     cfg80211_external_auth_request(netdev,
7289         (struct cfg80211_external_auth_params *)&params, GFP_ATOMIC);
7290 #elif (KERNEL_VERSION(2, 6, 37) <= LINUX_VERSION_CODE)
7291     set_frame_sub_type(frame, WIFI_AUTH);
7292 
7293     _rtw_memcpy(frame + 4, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
7294     _rtw_memcpy(frame + 10, adapter_mac_addr(padapter), ETH_ALEN);
7295     _rtw_memcpy(frame + 16, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
7296     RTW_PUT_LE32((frame + 18), 0x8ac0f00);
7297     RTW_PUT_LE32((frame + 24), 0x0003);
7298 
7299     if (pmlmeinfo->network.Ssid.SsidLength) {
7300         *(frame + 26) = pmlmeinfo->network.Ssid.SsidLength;
7301         _rtw_memcpy(frame + 27, pmlmeinfo->network.Ssid.Ssid,
7302             pmlmeinfo->network.Ssid.SsidLength);
7303         frame_len = 27 + pmlmeinfo->network.Ssid.SsidLength;
7304     }
7305 
7306     RTW_INFO("external auth: with wpa_supplicant patch\n");
7307     rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
7308 #endif
7309 }
7310 
rtw_cfg80211_rx_probe_request(_adapter * adapter,union recv_frame * rframe)7311 void rtw_cfg80211_rx_probe_request(_adapter *adapter, union recv_frame *rframe)
7312 {
7313     struct wireless_dev *wdev = adapter->rtw_wdev;
7314     u8 *frame = get_recvframe_data(rframe);
7315     uint frame_len = rframe->u.hdr.len;
7316     s32 freq;
7317     u8 ch, sch = rtw_get_oper_ch(adapter);
7318 
7319     ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;
7320     freq = rtw_ch2freq(ch);
7321 
7322 #ifdef CONFIG_DEBUG_CFG80211
7323     RTW_INFO("RTW_Rx: probe request, ch=%d(%d), ta="MAC_FMT"\n"
7324         , ch, sch, MAC_ARG(get_addr2_ptr(frame)));
7325 #endif
7326 
7327 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) || defined(COMPAT_KERNEL_RELEASE)
7328     rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
7329 #else
7330     cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);
7331 #endif
7332 }
7333 
rtw_cfg80211_rx_action_p2p(_adapter * adapter,union recv_frame * rframe)7334 void rtw_cfg80211_rx_action_p2p(_adapter *adapter, union recv_frame *rframe)
7335 {
7336     struct wireless_dev *wdev = adapter->rtw_wdev;
7337     u8 *frame = get_recvframe_data(rframe);
7338     uint frame_len = rframe->u.hdr.len;
7339     s32 freq;
7340     u8 ch, sch = rtw_get_oper_ch(adapter);
7341     u8 category, action;
7342     int type;
7343 
7344     ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;
7345     freq = rtw_ch2freq(ch);
7346 
7347     RTW_INFO("RTW_Rx:ch=%d(%d), ta="MAC_FMT"\n"
7348         , ch, sch, MAC_ARG(get_addr2_ptr(frame)));
7349 #ifdef CONFIG_P2P
7350     type = rtw_p2p_check_frames(adapter, frame, frame_len, _FALSE);
7351     if (type >= 0)
7352         goto indicate;
7353 #endif
7354     rtw_action_frame_parse(frame, frame_len, &category, &action);
7355     RTW_INFO("RTW_Rx:category(%u), action(%u)\n", category, action);
7356 #ifdef CONFIG_P2P
7357 indicate:
7358 #endif
7359 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
7360     rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
7361 #else
7362     cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);
7363 #endif
7364 }
7365 
rtw_cfg80211_rx_p2p_action_public(_adapter * adapter,union recv_frame * rframe)7366 void rtw_cfg80211_rx_p2p_action_public(_adapter *adapter, union recv_frame *rframe)
7367 {
7368     struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
7369     struct wireless_dev *wdev = adapter->rtw_wdev;
7370     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
7371     u8 *frame = get_recvframe_data(rframe);
7372     uint frame_len = rframe->u.hdr.len;
7373     s32 freq;
7374     u8 ch, sch = rtw_get_oper_ch(adapter);
7375     u8 category, action;
7376     int type;
7377 
7378     ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;
7379     freq = rtw_ch2freq(ch);
7380 
7381     RTW_INFO("RTW_Rx:ch=%d(%d), ta="MAC_FMT"\n"
7382         , ch, sch, MAC_ARG(get_addr2_ptr(frame)));
7383     #ifdef CONFIG_P2P
7384     type = rtw_p2p_check_frames(adapter, frame, frame_len, _FALSE);
7385     if (type >= 0) {
7386         switch (type) {
7387         case P2P_GO_NEGO_CONF:
7388             if (0) {
7389                 RTW_INFO(FUNC_ADPT_FMT" Nego confirm. state=%u, status=%u, iaddr="MAC_FMT"\n"
7390                     , FUNC_ADPT_ARG(adapter), pwdev_priv->nego_info.state, pwdev_priv->nego_info.status
7391                     , MAC_ARG(pwdev_priv->nego_info.iface_addr));
7392             }
7393             if (pwdev_priv->nego_info.state == 2
7394                 && pwdev_priv->nego_info.status == 0
7395                 && rtw_check_invalid_mac_address(pwdev_priv->nego_info.iface_addr, _FALSE) == _FALSE
7396             ) {
7397                 _adapter *intended_iface = dvobj_get_adapter_by_addr(dvobj, pwdev_priv->nego_info.iface_addr);
7398 
7399                 if (intended_iface) {
7400                     RTW_INFO(FUNC_ADPT_FMT" Nego confirm. Allow only "ADPT_FMT" to scan for 2000 ms\n"
7401                         , FUNC_ADPT_ARG(adapter), ADPT_ARG(intended_iface));
7402                     /* allow only intended_iface to do scan for 2000 ms */
7403                     rtw_mi_set_scan_deny(adapter, 2000);
7404                     rtw_clear_scan_deny(intended_iface);
7405                 }
7406             }
7407             break;
7408         case P2P_PROVISION_DISC_RESP:
7409         case P2P_INVIT_RESP:
7410             rtw_clear_scan_deny(adapter);
7411             #if !RTW_P2P_GROUP_INTERFACE
7412             rtw_mi_buddy_set_scan_deny(adapter, 2000);
7413             #endif
7414             break;
7415         }
7416         goto indicate;
7417     }
7418     #endif
7419     rtw_action_frame_parse(frame, frame_len, &category, &action);
7420     RTW_INFO("RTW_Rx:category(%u), action(%u)\n", category, action);
7421 #ifdef CONFIG_P2P
7422 indicate:
7423 #endif
7424     #if defined(RTW_DEDICATED_P2P_DEVICE)
7425     if (rtw_cfg80211_redirect_pd_wdev(dvobj_to_wiphy(dvobj), get_ra(frame), &wdev))
7426         if (0)
7427             RTW_INFO("redirect to pd_wdev:%p\n", wdev);
7428     #endif
7429 
7430 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
7431     rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
7432 #else
7433     cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);
7434 #endif
7435 }
7436 
rtw_cfg80211_rx_action(_adapter * adapter,union recv_frame * rframe,const char * msg)7437 void rtw_cfg80211_rx_action(_adapter *adapter, union recv_frame *rframe, const char *msg)
7438 {
7439     struct wireless_dev *wdev = adapter->rtw_wdev;
7440     u8 *frame = get_recvframe_data(rframe);
7441     uint frame_len = rframe->u.hdr.len;
7442     s32 freq;
7443     u8 ch, sch = rtw_get_oper_ch(adapter);
7444     u8 category, action;
7445     int type = -1;
7446 
7447     ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;
7448     freq = rtw_ch2freq(ch);
7449 
7450     RTW_INFO("RTW_Rx:ch=%d(%d), ta="MAC_FMT"\n"
7451         , ch, sch, MAC_ARG(get_addr2_ptr(frame)));
7452 
7453 #ifdef CONFIG_RTW_MESH
7454     if (MLME_IS_MESH(adapter)) {
7455         type = rtw_mesh_check_frames_rx(adapter, frame, frame_len);
7456         if (type >= 0)
7457             goto indicate;
7458     }
7459 #endif
7460     rtw_action_frame_parse(frame, frame_len, &category, &action);
7461     if (category == RTW_WLAN_CATEGORY_PUBLIC) {
7462         if (action == ACT_PUBLIC_GAS_INITIAL_REQ) {
7463             rtw_mi_set_scan_deny(adapter, 200);
7464             rtw_mi_scan_abort(adapter, _FALSE); /*rtw_scan_abort_no_wait*/
7465         }
7466     }
7467 #ifdef CONFIG_RTW_MESH
7468 indicate:
7469 #endif
7470 
7471 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
7472     rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
7473 #else
7474     cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);
7475 #endif
7476 
7477     if (type == -1) {
7478         if (msg)
7479             RTW_INFO("RTW_Rx:%s\n", msg);
7480         else
7481             RTW_INFO("RTW_Rx:category(%u), action(%u)\n", category, action);
7482     }
7483 }
7484 
7485 #ifdef CONFIG_RTW_80211K
rtw_cfg80211_rx_rrm_action(_adapter * adapter,union recv_frame * rframe)7486 void rtw_cfg80211_rx_rrm_action(_adapter *adapter, union recv_frame *rframe)
7487 {
7488     struct wireless_dev *wdev = adapter->rtw_wdev;
7489     u8 *frame = get_recvframe_data(rframe);
7490     uint frame_len = rframe->u.hdr.len;
7491     s32 freq;
7492     u8 ch, sch = rtw_get_oper_ch(adapter);
7493 
7494     ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;
7495     freq = rtw_ch2freq(ch);
7496 
7497 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
7498     rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
7499 #else
7500     cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);
7501 #endif
7502     RTW_INFO("RTW_Rx:ch=%d(%d), ta="MAC_FMT"\n"
7503         , ch, sch, MAC_ARG(get_addr2_ptr(frame)));
7504 }
7505 #endif /* CONFIG_RTW_80211K */
7506 
rtw_cfg80211_rx_mframe(_adapter * adapter,union recv_frame * rframe,const char * msg)7507 void rtw_cfg80211_rx_mframe(_adapter *adapter, union recv_frame *rframe, const char *msg)
7508 {
7509     struct wireless_dev *wdev = adapter->rtw_wdev;
7510     u8 *frame = get_recvframe_data(rframe);
7511     uint frame_len = rframe->u.hdr.len;
7512     s32 freq;
7513     u8 ch, sch = rtw_get_oper_ch(adapter);
7514 
7515     ch = rframe->u.hdr.attrib.ch ? rframe->u.hdr.attrib.ch : sch;
7516     freq = rtw_ch2freq(ch);
7517 
7518 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
7519     rtw_cfg80211_rx_mgmt(wdev, freq, 0, frame, frame_len, GFP_ATOMIC);
7520 #else
7521     cfg80211_rx_action(adapter->pnetdev, freq, frame, frame_len, GFP_ATOMIC);
7522 #endif
7523 
7524     RTW_INFO("RTW_Rx:ch=%d(%d), ta="MAC_FMT"\n", ch, sch, MAC_ARG(get_addr2_ptr(frame)));
7525     if (!rtw_sae_preprocess(adapter, frame, frame_len, _FALSE)) {
7526         if (msg)
7527             RTW_INFO("RTW_Rx:%s\n", msg);
7528         else
7529             RTW_INFO("RTW_Rx:frame_control:0x%02x\n", le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)rframe)->frame_ctl));
7530     }
7531 }
7532 
7533 #ifdef CONFIG_P2P
rtw_cfg80211_issue_p2p_provision_request(_adapter * padapter,const u8 * buf,size_t len)7534 void rtw_cfg80211_issue_p2p_provision_request(_adapter *padapter, const u8 *buf, size_t len)
7535 {
7536     u16    wps_devicepassword_id = 0x0000;
7537     uint    wps_devicepassword_id_len = 0;
7538     u8            wpsie[255] = { 0x00 }, p2p_ie[255] = { 0x00 };
7539     uint            p2p_ielen = 0;
7540     uint            wpsielen = 0;
7541     u32    devinfo_contentlen = 0;
7542     u8    devinfo_content[64] = { 0x00 };
7543     u16    capability = 0;
7544     uint capability_len = 0;
7545 
7546     unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
7547     u8            action = P2P_PUB_ACTION_ACTION;
7548     u8            dialogToken = 1;
7549     u32            p2poui = cpu_to_be32(P2POUI);
7550     u8            oui_subtype = P2P_PROVISION_DISC_REQ;
7551     u32            p2pielen = 0;
7552 #ifdef CONFIG_WFD
7553     u32                    wfdielen = 0;
7554 #endif
7555 
7556     struct xmit_frame            *pmgntframe;
7557     struct pkt_attrib            *pattrib;
7558     unsigned char                    *pframe;
7559     struct rtw_ieee80211_hdr    *pwlanhdr;
7560     unsigned short                *fctrl;
7561     struct xmit_priv            *pxmitpriv = &(padapter->xmitpriv);
7562     struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7563 
7564     struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
7565     u8 *frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));
7566     size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);
7567 
7568 
7569     RTW_INFO("[%s] In\n", __FUNCTION__);
7570 
7571     /* prepare for building provision_request frame     */
7572     _rtw_memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr1Ptr(buf), ETH_ALEN);
7573     _rtw_memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, GetAddr1Ptr(buf), ETH_ALEN);
7574 
7575     pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
7576 
7577     rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
7578     wps_devicepassword_id_len = sizeof(wps_devicepassword_id);
7579     rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *) &wps_devicepassword_id, &wps_devicepassword_id_len);
7580     wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
7581 
7582     switch (wps_devicepassword_id) {
7583     case WPS_DPID_PIN:
7584         pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_LABEL;
7585         break;
7586     case WPS_DPID_USER_SPEC:
7587         pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_DISPLYA;
7588         break;
7589     case WPS_DPID_MACHINE_SPEC:
7590         break;
7591     case WPS_DPID_REKEY:
7592         break;
7593     case WPS_DPID_PBC:
7594         pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_PUSH_BUTTON;
7595         break;
7596     case WPS_DPID_REGISTRAR_SPEC:
7597         pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_KEYPAD;
7598         break;
7599     default:
7600         break;
7601     }
7602 
7603 
7604     if (rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, p2p_ie, &p2p_ielen)) {
7605 
7606         devinfo_contentlen = sizeof(devinfo_content);
7607         rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, devinfo_content, &devinfo_contentlen);
7608         capability_len = sizeof(capability);
7609         rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8 *)&capability, &capability_len);
7610 
7611     }
7612 
7613 
7614     /* start to build provision_request frame     */
7615     _rtw_memset(wpsie, 0, sizeof(wpsie));
7616     _rtw_memset(p2p_ie, 0, sizeof(p2p_ie));
7617     p2p_ielen = 0;
7618 
7619     pmgntframe = alloc_mgtxmitframe(pxmitpriv);
7620     if (pmgntframe == NULL)
7621         return;
7622 
7623 
7624     /* update attribute */
7625     pattrib = &pmgntframe->attrib;
7626     update_mgntframe_attrib(padapter, pattrib);
7627 
7628     _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
7629 
7630     pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
7631     pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
7632 
7633     fctrl = &(pwlanhdr->frame_ctl);
7634     *(fctrl) = 0;
7635 
7636     _rtw_memcpy(pwlanhdr->addr1, pwdinfo->tx_prov_disc_info.peerDevAddr, ETH_ALEN);
7637     _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
7638     _rtw_memcpy(pwlanhdr->addr3, pwdinfo->tx_prov_disc_info.peerDevAddr, ETH_ALEN);
7639 
7640     SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
7641     pmlmeext->mgnt_seq++;
7642     set_frame_sub_type(pframe, WIFI_ACTION);
7643 
7644     pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
7645     pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
7646 
7647     pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
7648     pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
7649     pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
7650     pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
7651     pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
7652 
7653 
7654     /* build_prov_disc_request_p2p_ie     */
7655     /*    P2P OUI */
7656     p2pielen = 0;
7657     p2p_ie[p2pielen++] = 0x50;
7658     p2p_ie[p2pielen++] = 0x6F;
7659     p2p_ie[p2pielen++] = 0x9A;
7660     p2p_ie[p2pielen++] = 0x09;    /*    WFA P2P v1.0 */
7661 
7662     /*    Commented by Albert 20110301 */
7663     /*    According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
7664     /*    1. P2P Capability */
7665     /*    2. Device Info */
7666     /*    3. Group ID ( When joining an operating P2P Group ) */
7667 
7668     /*    P2P Capability ATTR */
7669     /*    Type:     */
7670     p2p_ie[p2pielen++] = P2P_ATTR_CAPABILITY;
7671 
7672     /*    Length: */
7673     /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 ); */
7674     RTW_PUT_LE16(p2p_ie + p2pielen, 0x0002);
7675     p2pielen += 2;
7676 
7677     /*    Value: */
7678     /*    Device Capability Bitmap, 1 byte */
7679     /*    Group Capability Bitmap, 1 byte */
7680     _rtw_memcpy(p2p_ie + p2pielen, &capability, 2);
7681     p2pielen += 2;
7682 
7683 
7684     /*    Device Info ATTR */
7685     /*    Type: */
7686     p2p_ie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
7687 
7688     /*    Length: */
7689     /*    21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes)  */
7690     /*    + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
7691     /* *(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len ); */
7692     RTW_PUT_LE16(p2p_ie + p2pielen, devinfo_contentlen);
7693     p2pielen += 2;
7694 
7695     /*    Value: */
7696     _rtw_memcpy(p2p_ie + p2pielen, devinfo_content, devinfo_contentlen);
7697     p2pielen += devinfo_contentlen;
7698 
7699 
7700     pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2p_ie, &p2p_ielen);
7701     /* p2pielen = build_prov_disc_request_p2p_ie( pwdinfo, pframe, NULL, 0, pwdinfo->tx_prov_disc_info.peerDevAddr); */
7702     /* pframe += p2pielen; */
7703     pattrib->pktlen += p2p_ielen;
7704 
7705     wpsielen = 0;
7706     /*    WPS OUI */
7707     *(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
7708     wpsielen += 4;
7709 
7710     /*    WPS version */
7711     /*    Type: */
7712     *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
7713     wpsielen += 2;
7714 
7715     /*    Length: */
7716     *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
7717     wpsielen += 2;
7718 
7719     /*    Value: */
7720     wpsie[wpsielen++] = WPS_VERSION_1;    /*    Version 1.0 */
7721 
7722     /*    Config Method */
7723     /*    Type: */
7724     *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
7725     wpsielen += 2;
7726 
7727     /*    Length: */
7728     *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
7729     wpsielen += 2;
7730 
7731     /*    Value: */
7732     *(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
7733     wpsielen += 2;
7734 
7735     pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);
7736 
7737 
7738 #ifdef CONFIG_WFD
7739     wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
7740     pframe += wfdielen;
7741     pattrib->pktlen += wfdielen;
7742 #endif
7743 
7744     pattrib->last_txcmdsz = pattrib->pktlen;
7745 
7746     /* dump_mgntframe(padapter, pmgntframe); */
7747     if (dump_mgntframe_and_wait_ack(padapter, pmgntframe) != _SUCCESS)
7748         RTW_INFO("%s, ack to\n", __func__);
7749 
7750     #if 0
7751     if(wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC) {
7752         RTW_INFO("waiting for p2p peer key-in PIN CODE\n");
7753         rtw_msleep_os(15000); /* 15 sec for key in PIN CODE, workaround for GS2 before issuing Nego Req. */
7754     }
7755     #endif
7756 
7757 }
7758 
7759 #ifdef CONFIG_RTW_80211R
cfg80211_rtw_update_ft_ies(struct wiphy * wiphy,struct net_device * ndev,struct cfg80211_update_ft_ies_params * ftie)7760 static s32 cfg80211_rtw_update_ft_ies(struct wiphy *wiphy,
7761     struct net_device *ndev,
7762     struct cfg80211_update_ft_ies_params *ftie)
7763 {
7764     _adapter *padapter = NULL;
7765     struct mlme_priv *pmlmepriv = NULL;
7766     struct ft_roam_info *pft_roam = NULL;
7767     _irqL irqL;
7768     u8 *p;
7769     u8 *pie = NULL;
7770     u32 ie_len = 0;
7771 
7772     if (ndev == NULL)
7773         return  -EINVAL;
7774 
7775     padapter = (_adapter *)rtw_netdev_priv(ndev);
7776     pmlmepriv = &(padapter->mlmepriv);
7777     pft_roam = &(pmlmepriv->ft_roam);
7778 
7779     p = (u8 *)ftie->ie;
7780     if (ftie->ie_len <= sizeof(pft_roam->updated_ft_ies)) {
7781         _enter_critical_bh(&pmlmepriv->lock, &irqL);
7782         _rtw_memcpy(pft_roam->updated_ft_ies, ftie->ie, ftie->ie_len);
7783         pft_roam->updated_ft_ies_len = ftie->ie_len;
7784         _exit_critical_bh(&pmlmepriv->lock, &irqL);
7785     } else {
7786         RTW_ERR("FTIEs parsing fail!\n");
7787         return -EINVAL;
7788     }
7789 
7790     if (rtw_ft_roam_status(padapter, RTW_FT_AUTHENTICATED_STA)) {
7791         RTW_PRINT("auth success, start reassoc\n");
7792         rtw_ft_lock_set_status(padapter, RTW_FT_ASSOCIATING_STA, &irqL);
7793         start_clnt_assoc(padapter);
7794     }
7795 
7796     return 0;
7797 }
7798 #endif
7799 #endif /* CONFIG_P2P */
7800 
rtw_cfg80211_set_is_roch(_adapter * adapter,bool val)7801 inline void rtw_cfg80211_set_is_roch(_adapter *adapter, bool val)
7802 {
7803     adapter->rochinfo.is_ro_ch = val;
7804     rtw_mi_update_iface_status(&(adapter->mlmepriv), 0);
7805 }
7806 
rtw_cfg80211_get_is_roch(_adapter * adapter)7807 inline bool rtw_cfg80211_get_is_roch(_adapter *adapter)
7808 {
7809     return adapter->rochinfo.is_ro_ch;
7810 }
7811 
rtw_cfg80211_is_ro_ch_once(_adapter * adapter)7812 inline bool rtw_cfg80211_is_ro_ch_once(_adapter *adapter)
7813 {
7814     return adapter->rochinfo.last_ro_ch_time ? 1 : 0;
7815 }
7816 
rtw_cfg80211_set_last_ro_ch_time(_adapter * adapter)7817 inline void rtw_cfg80211_set_last_ro_ch_time(_adapter *adapter)
7818 {
7819     adapter->rochinfo.last_ro_ch_time = rtw_get_current_time();
7820 
7821     if (!adapter->rochinfo.last_ro_ch_time)
7822         adapter->rochinfo.last_ro_ch_time++;
7823 }
7824 
rtw_cfg80211_get_last_ro_ch_passing_ms(_adapter * adapter)7825 inline s32 rtw_cfg80211_get_last_ro_ch_passing_ms(_adapter *adapter)
7826 {
7827     return rtw_get_passing_time_ms(adapter->rochinfo.last_ro_ch_time);
7828 }
7829 
cfg80211_rtw_remain_on_channel(struct wiphy * wiphy,struct wireless_dev * wdev,struct ieee80211_channel * channel,enum nl80211_channel_type channel_type,unsigned int duration,u64 * cookie)7830 static s32 cfg80211_rtw_remain_on_channel(struct wiphy *wiphy,
7831 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
7832     struct wireless_dev *wdev,
7833 #else
7834     struct net_device *ndev,
7835 #endif
7836     struct ieee80211_channel *channel,
7837 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
7838     enum nl80211_channel_type channel_type,
7839 #endif
7840     unsigned int duration, u64 *cookie)
7841 {
7842     s32 err = 0;
7843     u8 remain_ch = (u8) ieee80211_frequency_to_channel(channel->center_freq);
7844     _adapter *padapter = NULL;
7845     struct rtw_wdev_priv *pwdev_priv;
7846     struct roch_info *prochinfo;
7847 #ifdef CONFIG_P2P
7848     struct wifidirect_info *pwdinfo;
7849 #ifdef CONFIG_CONCURRENT_MODE
7850     u8 is_p2p_find = _FALSE;
7851 #endif
7852 #endif
7853 
7854 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
7855     #if defined(RTW_DEDICATED_P2P_DEVICE)
7856     if (wdev == wiphy_to_pd_wdev(wiphy))
7857         padapter = wiphy_to_adapter(wiphy);
7858     else
7859     #endif
7860     if (wdev_to_ndev(wdev))
7861         padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
7862     else {
7863         err = -EINVAL;
7864         goto exit;
7865     }
7866 #else
7867     struct wireless_dev *wdev;
7868 
7869     if (ndev == NULL) {
7870         err = -EINVAL;
7871         goto exit;
7872     }
7873     padapter = (_adapter *)rtw_netdev_priv(ndev);
7874     wdev = ndev_to_wdev(ndev);
7875 #endif
7876 
7877     pwdev_priv = adapter_wdev_data(padapter);
7878     prochinfo = &padapter->rochinfo;
7879 #ifdef CONFIG_P2P
7880     pwdinfo = &padapter->wdinfo;
7881 #ifdef CONFIG_CONCURRENT_MODE
7882     is_p2p_find = (duration < (pwdinfo->ext_listen_interval)) ? _TRUE : _FALSE;
7883 #endif
7884 #endif
7885 
7886     *cookie = ATOMIC_INC_RETURN(&prochinfo->ro_ch_cookie_gen);
7887 
7888     RTW_INFO(FUNC_ADPT_FMT"%s ch:%u duration:%d, cookie:0x%llx\n"
7889         , FUNC_ADPT_ARG(padapter), wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : ""
7890         , remain_ch, duration, *cookie);
7891 
7892     if (rtw_chset_search_ch(adapter_to_chset(padapter), remain_ch) < 0) {
7893         RTW_WARN(FUNC_ADPT_FMT" invalid ch:%u\n", FUNC_ADPT_ARG(padapter), remain_ch);
7894         err = -EFAULT;
7895         goto exit;
7896     }
7897 
7898 #ifdef CONFIG_MP_INCLUDED
7899     if (rtw_mp_mode_check(padapter)) {
7900         RTW_INFO("MP mode block remain_on_channel request\n");
7901         err = -EFAULT;
7902         goto exit;
7903     }
7904 #endif
7905 
7906     if (_FAIL == rtw_pwr_wakeup(padapter)) {
7907         err = -EFAULT;
7908         goto exit;
7909     }
7910 
7911     rtw_scan_abort(padapter);
7912 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_P2P)
7913     /*don't scan_abort during p2p_listen.*/
7914     if (is_p2p_find)
7915         rtw_mi_buddy_scan_abort(padapter, _TRUE);
7916 #endif /* defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_P2P) */
7917 
7918     if (rtw_cfg80211_get_is_roch(padapter) == _TRUE) {
7919         _cancel_timer_ex(&padapter->rochinfo.remain_on_ch_timer);
7920         rtw_cancel_roch_cmd(padapter, 0, NULL, RTW_CMDF_WAIT_ACK);
7921     }
7922 
7923 #ifdef CONFIG_P2P
7924     /* if(!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) && !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) */
7925     if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
7926         #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_P2P)
7927         && ((padapter->iface_id == padapter->registrypriv.sel_p2p_iface))
7928         #endif
7929     ) {
7930         rtw_p2p_enable(padapter, P2P_ROLE_DEVICE);
7931         padapter->wdinfo.listen_channel = remain_ch;
7932         RTW_INFO(FUNC_ADPT_FMT" init listen_channel %u\n"
7933             , FUNC_ADPT_ARG(padapter), padapter->wdinfo.listen_channel);
7934     } else if (rtw_p2p_chk_state(pwdinfo , P2P_STATE_LISTEN)
7935         && (time_after_eq(rtw_get_current_time(), pwdev_priv->probe_resp_ie_update_time)
7936             && rtw_get_passing_time_ms(pwdev_priv->probe_resp_ie_update_time) < 50)
7937     ) {
7938         if (padapter->wdinfo.listen_channel != remain_ch) {
7939             padapter->wdinfo.listen_channel = remain_ch;
7940             RTW_INFO(FUNC_ADPT_FMT" update listen_channel %u\n"
7941                 , FUNC_ADPT_ARG(padapter), padapter->wdinfo.listen_channel);
7942         }
7943     } else {
7944         rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
7945 #ifdef CONFIG_DEBUG_CFG80211
7946         RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
7947 #endif
7948     }
7949 
7950     rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
7951 #endif /* CONFIG_P2P */
7952 
7953     #ifdef RTW_ROCH_DURATION_ENLARGE
7954     if (duration < 400)
7955         duration = duration * 3; /* extend from exper */
7956     #endif
7957 
7958 #if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_P2P)
7959     if (rtw_mi_check_status(padapter, MI_LINKED)) {
7960         if (is_p2p_find) /* p2p_find , duration<1000 */
7961             duration = duration + pwdinfo->ext_listen_interval;
7962     }
7963 #endif /* defined (RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_P2P) */
7964 
7965     rtw_cfg80211_set_is_roch(padapter, _TRUE);
7966     prochinfo->ro_ch_wdev = wdev;
7967     prochinfo->remain_on_ch_cookie = *cookie;
7968     rtw_cfg80211_set_last_ro_ch_time(padapter);
7969     _rtw_memcpy(&prochinfo->remain_on_ch_channel, channel, sizeof(struct ieee80211_channel));
7970     #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
7971     prochinfo->remain_on_ch_type = channel_type;
7972     #endif
7973     prochinfo->restore_channel = rtw_get_oper_ch(padapter);
7974 
7975     rtw_roch_cmd(padapter, *cookie, wdev, channel, prochinfo->remain_on_ch_type,
7976         duration, RTW_CMDF_WAIT_ACK);
7977 
7978     rtw_cfg80211_ready_on_channel(wdev, *cookie, channel, channel_type, duration, GFP_KERNEL);
7979 exit:
7980     return err;
7981 }
7982 
cfg80211_rtw_cancel_remain_on_channel(struct wiphy * wiphy,struct wireless_dev * wdev,u64 cookie)7983 static s32 cfg80211_rtw_cancel_remain_on_channel(struct wiphy *wiphy,
7984 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
7985     struct wireless_dev *wdev,
7986 #else
7987     struct net_device *ndev,
7988 #endif
7989     u64 cookie)
7990 {
7991     s32 err = 0;
7992     _adapter *padapter;
7993     struct rtw_wdev_priv *pwdev_priv;
7994     struct roch_info *prochinfo;
7995 #ifdef CONFIG_P2P
7996     struct wifidirect_info *pwdinfo;
7997 #endif
7998 
7999 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8000     #if defined(RTW_DEDICATED_P2P_DEVICE)
8001     if (wdev == wiphy_to_pd_wdev(wiphy))
8002         padapter = wiphy_to_adapter(wiphy);
8003     else
8004     #endif
8005     if (wdev_to_ndev(wdev))
8006         padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
8007     else {
8008         err = -EINVAL;
8009         goto exit;
8010     }
8011 #else
8012     struct wireless_dev *wdev;
8013 
8014     if (ndev == NULL) {
8015         err = -EINVAL;
8016         goto exit;
8017     }
8018     padapter = (_adapter *)rtw_netdev_priv(ndev);
8019     wdev = ndev_to_wdev(ndev);
8020 #endif
8021 
8022     pwdev_priv = adapter_wdev_data(padapter);
8023     prochinfo = &padapter->rochinfo;
8024 #ifdef CONFIG_P2P
8025     pwdinfo = &padapter->wdinfo;
8026 #endif
8027 
8028     RTW_INFO(FUNC_ADPT_FMT"%s cookie:0x%llx\n"
8029         , FUNC_ADPT_ARG(padapter), wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : ""
8030         , cookie);
8031 
8032     if (rtw_cfg80211_get_is_roch(padapter) == _TRUE) {
8033         _cancel_timer_ex(&padapter->rochinfo.remain_on_ch_timer);
8034         rtw_cancel_roch_cmd(padapter, cookie, wdev, RTW_CMDF_WAIT_ACK);
8035     }
8036 
8037 exit:
8038     return err;
8039 }
8040 
8041 #ifdef CONFIG_P2P
rtw_cfg80211_iface_has_p2p_group_cap(_adapter * adapter)8042 inline int rtw_cfg80211_iface_has_p2p_group_cap(_adapter *adapter)
8043 {
8044 #if RTW_P2P_GROUP_INTERFACE
8045     if (is_primary_adapter(adapter))
8046         return 0;
8047 #endif
8048     return 1;
8049 }
8050 
rtw_cfg80211_is_p2p_scan(_adapter * adapter)8051 inline int rtw_cfg80211_is_p2p_scan(_adapter *adapter)
8052 {
8053 #if RTW_P2P_GROUP_INTERFACE
8054     if (rtw_cfg80211_iface_has_p2p_group_cap(adapter))
8055 #endif
8056     {
8057         struct wifidirect_info *wdinfo = &adapter->wdinfo;
8058 
8059         return rtw_p2p_chk_state(wdinfo, P2P_STATE_SCAN)
8060             || rtw_p2p_chk_state(wdinfo, P2P_STATE_FIND_PHASE_SEARCH);
8061     }
8062 
8063 #if RTW_P2P_GROUP_INTERFACE
8064     #if defined(RTW_DEDICATED_P2P_DEVICE)
8065     if (wiphy_to_pd_wdev(adapter_to_wiphy(adapter))) /* pd_wdev exist */
8066         return rtw_cfg80211_is_scan_by_pd_wdev(adapter);
8067     #endif
8068     {
8069         /*
8070         * For 2 RTW_P2P_GROUP_INTERFACE cases:
8071         * 1. RTW_DEDICATED_P2P_DEVICE defined but upper layer don't use pd_wdev or
8072         * 2. RTW_DEDICATED_P2P_DEVICE not defined
8073         */
8074         struct rtw_wdev_priv *wdev_data = adapter_wdev_data(adapter);
8075         _irqL irqL;
8076         int is_p2p_scan = 0;
8077 
8078         _enter_critical_bh(&wdev_data->scan_req_lock, &irqL);
8079         if (wdev_data->scan_request
8080             && wdev_data->scan_request->n_ssids
8081             && wdev_data->scan_request->ssids
8082             && wdev_data->scan_request->ie
8083         ) {
8084             if (_rtw_memcmp(wdev_data->scan_request->ssids[0].ssid, "DIRECT-", 7)
8085                 && rtw_get_p2p_ie((u8 *)wdev_data->scan_request->ie, wdev_data->scan_request->ie_len, NULL, NULL))
8086                 is_p2p_scan = 1;
8087         }
8088         _exit_critical_bh(&wdev_data->scan_req_lock, &irqL);
8089 
8090         return is_p2p_scan;
8091     }
8092 #endif
8093 }
8094 
8095 #if defined(RTW_DEDICATED_P2P_DEVICE)
rtw_pd_iface_alloc(struct wiphy * wiphy,const char * name,struct wireless_dev ** pd_wdev)8096 int rtw_pd_iface_alloc(struct wiphy *wiphy, const char *name, struct wireless_dev **pd_wdev)
8097 {
8098     struct rtw_wiphy_data *wiphy_data = rtw_wiphy_priv(wiphy);
8099     struct wireless_dev *wdev = NULL;
8100     struct rtw_netdev_priv_indicator *npi;
8101     _adapter *primary_adpt = wiphy_to_adapter(wiphy);
8102     int ret = 0;
8103 
8104     if (wiphy_data->pd_wdev) {
8105         RTW_WARN(FUNC_WIPHY_FMT" pd_wdev already exists\n", FUNC_WIPHY_ARG(wiphy));
8106         ret = -EBUSY;
8107         goto exit;
8108     }
8109 
8110     wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));
8111     if (!wdev) {
8112         RTW_WARN(FUNC_WIPHY_FMT" allocate wdev fail\n", FUNC_WIPHY_ARG(wiphy));
8113         ret = -ENOMEM;
8114         goto exit;
8115     }
8116 
8117     wdev->wiphy = wiphy;
8118     wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
8119     _rtw_memcpy(wdev->address, adapter_mac_addr(primary_adpt), ETH_ALEN);
8120 
8121     wiphy_data->pd_wdev = wdev;
8122     *pd_wdev = wdev;
8123 
8124     RTW_INFO(FUNC_WIPHY_FMT" pd_wdev:%p, addr="MAC_FMT" added\n"
8125         , FUNC_WIPHY_ARG(wiphy), wdev, MAC_ARG(wdev_address(wdev)));
8126 
8127 exit:
8128     if (ret && wdev) {
8129         rtw_mfree((u8 *)wdev, sizeof(struct wireless_dev));
8130         wdev = NULL;
8131     }
8132 
8133     return ret;
8134 }
8135 
rtw_pd_iface_free(struct wiphy * wiphy)8136 void rtw_pd_iface_free(struct wiphy *wiphy)
8137 {
8138     struct dvobj_priv *dvobj = wiphy_to_dvobj(wiphy);
8139     struct rtw_wiphy_data *wiphy_data = rtw_wiphy_priv(wiphy);
8140     u8 rtnl_lock_needed;
8141 
8142     if (!wiphy_data->pd_wdev)
8143         goto exit;
8144 
8145     RTW_INFO(FUNC_WIPHY_FMT" pd_wdev:%p, addr="MAC_FMT"\n"
8146         , FUNC_WIPHY_ARG(wiphy), wiphy_data->pd_wdev
8147         , MAC_ARG(wdev_address(wiphy_data->pd_wdev)));
8148 
8149     rtnl_lock_needed = rtw_rtnl_lock_needed(dvobj);
8150     if (rtnl_lock_needed)
8151         rtnl_lock();
8152     cfg80211_unregister_wdev(wiphy_data->pd_wdev);
8153     if (rtnl_lock_needed)
8154         rtnl_unlock();
8155 
8156     rtw_mfree((u8 *)wiphy_data->pd_wdev, sizeof(struct wireless_dev));
8157     wiphy_data->pd_wdev = NULL;
8158 
8159 exit:
8160     return;
8161 }
8162 
cfg80211_rtw_start_p2p_device(struct wiphy * wiphy,struct wireless_dev * wdev)8163 static int cfg80211_rtw_start_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
8164 {
8165     _adapter *adapter = wiphy_to_adapter(wiphy);
8166 
8167     RTW_INFO(FUNC_WIPHY_FMT" wdev=%p\n", FUNC_WIPHY_ARG(wiphy), wdev);
8168 
8169     rtw_p2p_enable(adapter, P2P_ROLE_DEVICE);
8170     return 0;
8171 }
8172 
cfg80211_rtw_stop_p2p_device(struct wiphy * wiphy,struct wireless_dev * wdev)8173 static void cfg80211_rtw_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
8174 {
8175     _adapter *adapter = wiphy_to_adapter(wiphy);
8176 
8177     RTW_INFO(FUNC_WIPHY_FMT" wdev=%p\n", FUNC_WIPHY_ARG(wiphy), wdev);
8178 
8179     if (rtw_cfg80211_is_p2p_scan(adapter))
8180         rtw_scan_abort(adapter);
8181 
8182     rtw_p2p_enable(adapter, P2P_ROLE_DISABLE);
8183 }
8184 
rtw_cfg80211_redirect_pd_wdev(struct wiphy * wiphy,u8 * ra,struct wireless_dev ** wdev)8185 inline int rtw_cfg80211_redirect_pd_wdev(struct wiphy *wiphy, u8 *ra, struct wireless_dev **wdev)
8186 {
8187     struct wireless_dev *pd_wdev = wiphy_to_pd_wdev(wiphy);
8188 
8189     if (pd_wdev && pd_wdev != *wdev
8190         && _rtw_memcmp(wdev_address(pd_wdev), ra, ETH_ALEN) == _TRUE
8191     ) {
8192         *wdev = pd_wdev;
8193         return 1;
8194     }
8195     return 0;
8196 }
8197 
rtw_cfg80211_is_scan_by_pd_wdev(_adapter * adapter)8198 inline int rtw_cfg80211_is_scan_by_pd_wdev(_adapter *adapter)
8199 {
8200     struct wiphy *wiphy = adapter_to_wiphy(adapter);
8201     struct rtw_wdev_priv *wdev_data = adapter_wdev_data(adapter);
8202     struct wireless_dev *wdev = NULL;
8203     _irqL irqL;
8204 
8205     _enter_critical_bh(&wdev_data->scan_req_lock, &irqL);
8206     if (wdev_data->scan_request)
8207         wdev = wdev_data->scan_request->wdev;
8208     _exit_critical_bh(&wdev_data->scan_req_lock, &irqL);
8209 
8210     if (wdev && wdev == wiphy_to_pd_wdev(wiphy))
8211         return 1;
8212 
8213     return 0;
8214 }
8215 #endif /* RTW_DEDICATED_P2P_DEVICE */
8216 #endif /* CONFIG_P2P */
8217 
rtw_cfg80211_set_is_mgmt_tx(_adapter * adapter,u8 val)8218 inline void rtw_cfg80211_set_is_mgmt_tx(_adapter *adapter, u8 val)
8219 {
8220     struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);
8221 
8222     wdev_priv->is_mgmt_tx = val;
8223     rtw_mi_update_iface_status(&(adapter->mlmepriv), 0);
8224 }
8225 
rtw_cfg80211_get_is_mgmt_tx(_adapter * adapter)8226 inline u8 rtw_cfg80211_get_is_mgmt_tx(_adapter *adapter)
8227 {
8228     struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);
8229 
8230     return wdev_priv->is_mgmt_tx;
8231 }
8232 
_cfg80211_rtw_mgmt_tx(_adapter * padapter,u8 tx_ch,u8 no_cck,const u8 * buf,size_t len,int wait_ack)8233 static int _cfg80211_rtw_mgmt_tx(_adapter *padapter, u8 tx_ch, u8 no_cck, const u8 *buf, size_t len, int wait_ack)
8234 {
8235     struct xmit_frame    *pmgntframe;
8236     struct pkt_attrib    *pattrib;
8237     unsigned char    *pframe;
8238     int ret = _FAIL;
8239     bool ack = _TRUE;
8240     struct rtw_ieee80211_hdr *pwlanhdr;
8241 #if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)
8242     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
8243 #endif
8244     struct xmit_priv    *pxmitpriv = &(padapter->xmitpriv);
8245     struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
8246     u8 u_ch = rtw_mi_get_union_chan(padapter);
8247     u8 leave_op = 0;
8248     struct roch_info *prochinfo = &padapter->rochinfo;
8249 #if defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)
8250     struct wifidirect_info *pwdinfo = &padapter->wdinfo;
8251 #endif
8252 
8253     rtw_cfg80211_set_is_mgmt_tx(padapter, 1);
8254 
8255 #ifdef CONFIG_BT_COEXIST
8256     rtw_btcoex_ScanNotify(padapter, _TRUE);
8257 #endif
8258 
8259 #ifdef CONFIG_P2P
8260     if (rtw_cfg80211_get_is_roch(padapter) == _TRUE) {
8261         #ifdef CONFIG_CONCURRENT_MODE
8262         if (!check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE)) {
8263             RTW_INFO("%s, extend ro ch time\n", __func__);
8264             _set_timer(&padapter->rochinfo.remain_on_ch_timer, pwdinfo->ext_listen_period);
8265         }
8266         #endif /* CONFIG_CONCURRENT_MODE */
8267     }
8268 #endif /* CONFIG_P2P */
8269 
8270 #ifdef CONFIG_MCC_MODE
8271     if (MCC_EN(padapter)) {
8272         if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
8273             /* don't set channel, issue frame directly */
8274             goto issue_mgmt_frame;
8275     }
8276 #endif /* CONFIG_MCC_MODE */
8277 
8278     if (rtw_mi_check_status(padapter, MI_LINKED)
8279         && tx_ch != u_ch
8280     ) {
8281         rtw_leave_opch(padapter);
8282         leave_op = 1;
8283     }
8284 
8285     if (tx_ch != rtw_get_oper_ch(padapter))
8286         set_channel_bwmode(padapter, tx_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
8287 #ifdef CONFIG_MCC_MODE
8288 issue_mgmt_frame:
8289 #endif
8290     /* starting alloc mgmt frame to dump it */
8291     pmgntframe = alloc_mgtxmitframe(pxmitpriv);
8292     if (pmgntframe == NULL) {
8293         /* ret = -ENOMEM; */
8294         ret = _FAIL;
8295         goto exit;
8296     }
8297 
8298     /* update attribute */
8299     pattrib = &pmgntframe->attrib;
8300     update_mgntframe_attrib(padapter, pattrib);
8301 
8302     if (no_cck && IS_CCK_RATE(pattrib->rate)) {
8303         /* force OFDM 6M rate*/
8304         pattrib->rate = MGN_6M;
8305         pattrib->raid = rtw_get_mgntframe_raid(padapter, WIRELESS_11G);
8306     }
8307 
8308     pattrib->retry_ctrl = _FALSE;
8309 
8310     _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
8311 
8312     pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
8313 
8314     _rtw_memcpy(pframe, (void *)buf, len);
8315     pattrib->pktlen = len;
8316 
8317     pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
8318     /* update seq number */
8319     pmlmeext->mgnt_seq = GetSequence(pwlanhdr);
8320     pattrib->seqnum = pmlmeext->mgnt_seq;
8321     pmlmeext->mgnt_seq++;
8322 
8323 #ifdef CONFIG_P2P
8324     rtw_xframe_chk_wfd_ie(pmgntframe);
8325 #endif /* CONFIG_P2P */
8326 
8327     pattrib->last_txcmdsz = pattrib->pktlen;
8328 
8329     if (wait_ack) {
8330         if (dump_mgntframe_and_wait_ack(padapter, pmgntframe) != _SUCCESS) {
8331             ack = _FALSE;
8332             ret = _FAIL;
8333 
8334 #ifdef CONFIG_DEBUG_CFG80211
8335             RTW_INFO("%s, ack == _FAIL\n", __func__);
8336 #endif
8337         } else {
8338 
8339 #ifdef CONFIG_XMIT_ACK
8340             if (!MLME_IS_MESH(padapter)) /* TODO: remove this sleep for all mode */
8341                 rtw_msleep_os(50);
8342 #endif
8343 #ifdef CONFIG_DEBUG_CFG80211
8344             RTW_INFO("%s, ack=%d, ok!\n", __func__, ack);
8345 #endif
8346             ret = _SUCCESS;
8347         }
8348     } else {
8349         dump_mgntframe(padapter, pmgntframe);
8350         ret = _SUCCESS;
8351     }
8352 
8353 exit:
8354     if (rtw_cfg80211_get_is_roch(padapter)
8355         && !rtw_roch_stay_in_cur_chan(padapter)
8356         && prochinfo->remain_on_ch_channel.hw_value != u_ch
8357     ) {
8358         /* roch is ongoing, switch back to rch */
8359         if (prochinfo->remain_on_ch_channel.hw_value != tx_ch)
8360             set_channel_bwmode(padapter, prochinfo->remain_on_ch_channel.hw_value
8361                 , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
8362     } else if (leave_op) {
8363         if (rtw_mi_check_status(padapter, MI_LINKED)) {
8364             u8 u_bw = rtw_mi_get_union_bw(padapter);
8365             u8 u_offset = rtw_mi_get_union_offset(padapter);
8366 
8367             set_channel_bwmode(padapter, u_ch, u_offset, u_bw);
8368         }
8369         rtw_back_opch(padapter);
8370     }
8371 
8372     rtw_cfg80211_set_is_mgmt_tx(padapter, 0);
8373 
8374 #ifdef CONFIG_BT_COEXIST
8375     rtw_btcoex_ScanNotify(padapter, _FALSE);
8376 #endif
8377 
8378 #ifdef CONFIG_DEBUG_CFG80211
8379     RTW_INFO("%s, ret=%d\n", __func__, ret);
8380 #endif
8381 
8382     return ret;
8383 
8384 }
8385 
rtw_mgnt_tx_handler(_adapter * adapter,u8 * buf)8386 u8 rtw_mgnt_tx_handler(_adapter *adapter, u8 *buf)
8387 {
8388     u8 rst = H2C_CMD_FAIL;
8389     struct mgnt_tx_parm *mgnt_parm = (struct mgnt_tx_parm *)buf;
8390 
8391     if (_cfg80211_rtw_mgmt_tx(adapter, mgnt_parm->tx_ch, mgnt_parm->no_cck,
8392         mgnt_parm->buf, mgnt_parm->len, mgnt_parm->wait_ack) == _SUCCESS)
8393         rst = H2C_SUCCESS;
8394 
8395     return rst;
8396 }
8397 
cfg80211_rtw_mgmt_tx(struct wiphy * wiphy,struct wireless_dev * wdev,struct ieee80211_channel * chan,bool offchan,enum nl80211_channel_type channel_type,bool channel_type_valid,unsigned int wait,const u8 * buf,size_t len,bool no_cck,bool dont_wait_for_ack,u64 * cookie)8398 static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy,
8399 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8400     struct wireless_dev *wdev,
8401 #else
8402     struct net_device *ndev,
8403 #endif
8404 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)) || defined(COMPAT_KERNEL_RELEASE)
8405     struct ieee80211_channel *chan,
8406     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
8407     bool offchan,
8408     #endif
8409     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
8410     enum nl80211_channel_type channel_type,
8411     #endif
8412     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
8413     bool channel_type_valid,
8414     #endif
8415     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
8416     unsigned int wait,
8417     #endif
8418     const u8 *buf, size_t len,
8419     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
8420     bool no_cck,
8421     #endif
8422     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
8423     bool dont_wait_for_ack,
8424     #endif
8425 #else
8426     struct cfg80211_mgmt_tx_params *params,
8427 #endif
8428     u64 *cookie)
8429 {
8430 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) || defined(COMPAT_KERNEL_RELEASE)
8431     struct ieee80211_channel *chan = params->chan;
8432     const u8 *buf = params->buf;
8433     size_t len = params->len;
8434     bool no_cck = params->no_cck;
8435 #endif
8436 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
8437     bool no_cck = 0;
8438 #endif
8439     int ret = 0;
8440     u8 tx_ret;
8441     int wait_ack = 1;
8442     const u8 *dump_buf = buf;
8443     size_t dump_len = len;
8444     u32 dump_limit = RTW_MAX_MGMT_TX_CNT;
8445     u32 dump_cnt = 0;
8446     u32 sleep_ms = 0;
8447     u32 retry_guarantee_ms = 0;
8448     bool ack = _TRUE;
8449     u8 tx_ch;
8450     u8 category, action;
8451     u8 frame_styp;
8452 #ifdef CONFIG_P2P
8453     u8 is_p2p = 0;
8454 #endif
8455     int type = (-1);
8456     systime start = rtw_get_current_time();
8457     _adapter *padapter;
8458     struct dvobj_priv *dvobj;
8459     struct rtw_wdev_priv *pwdev_priv;
8460     struct rf_ctl_t *rfctl;
8461 
8462 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8463     #if defined(RTW_DEDICATED_P2P_DEVICE)
8464     if (wdev == wiphy_to_pd_wdev(wiphy))
8465         padapter = wiphy_to_adapter(wiphy);
8466     else
8467     #endif
8468     if (wdev_to_ndev(wdev))
8469         padapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
8470     else {
8471         ret = -EINVAL;
8472         goto exit;
8473     }
8474 #else
8475     struct wireless_dev *wdev;
8476 
8477     if (ndev == NULL) {
8478         ret = -EINVAL;
8479         goto exit;
8480     }
8481     padapter = (_adapter *)rtw_netdev_priv(ndev);
8482     wdev = ndev_to_wdev(ndev);
8483 #endif
8484 
8485     if (chan == NULL) {
8486         ret = -EINVAL;
8487         goto exit;
8488     }
8489 
8490     rfctl = adapter_to_rfctl(padapter);
8491     tx_ch = (u8)ieee80211_frequency_to_channel(chan->center_freq);
8492     if (IS_CH_WAITING(rfctl)) {
8493         #ifdef CONFIG_DFS_MASTER
8494         if (_rtw_rfctl_overlap_radar_detect_ch(rfctl, tx_ch, CHANNEL_WIDTH_20, HAL_PRIME_CHNL_OFFSET_DONT_CARE)) {
8495             ret = -EINVAL;
8496             goto exit;
8497         }
8498         #endif
8499     }
8500 
8501     dvobj = adapter_to_dvobj(padapter);
8502     pwdev_priv = adapter_wdev_data(padapter);
8503 
8504     /* cookie generation */
8505     *cookie = pwdev_priv->mgmt_tx_cookie++;
8506 
8507 #ifdef CONFIG_DEBUG_CFG80211
8508     RTW_INFO(FUNC_ADPT_FMT"%s len=%zu, ch=%d"
8509         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
8510         ", ch_type=%d"
8511         #endif
8512         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
8513         ", channel_type_valid=%d"
8514         #endif
8515         "\n", FUNC_ADPT_ARG(padapter), wdev == wiphy_to_pd_wdev(wiphy) ? " PD" : ""
8516         , len, tx_ch
8517         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
8518         , channel_type
8519         #endif
8520         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0))
8521         , channel_type_valid
8522         #endif
8523     );
8524 #endif /* CONFIG_DEBUG_CFG80211 */
8525 
8526     /* indicate ack before issue frame to avoid racing with rsp frame */
8527 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
8528     rtw_cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, GFP_KERNEL);
8529 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 36))
8530     cfg80211_action_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL);
8531 #endif
8532 
8533     frame_styp = le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl) & IEEE80211_FCTL_STYPE;
8534     if (IEEE80211_STYPE_PROBE_RESP == frame_styp) {
8535 #ifdef CONFIG_DEBUG_CFG80211
8536         RTW_INFO("RTW_Tx: probe_resp tx_ch=%d, no_cck=%u, da="MAC_FMT"\n", tx_ch, no_cck, MAC_ARG(GetAddr1Ptr(buf)));
8537 #endif /* CONFIG_DEBUG_CFG80211 */
8538         wait_ack = 0;
8539         goto dump;
8540     }
8541     else if (frame_styp == RTW_IEEE80211_STYPE_AUTH) {
8542         int retval = 0;
8543 
8544         RTW_INFO("RTW_Tx:tx_ch=%d, no_cck=%u, da="MAC_FMT"\n", tx_ch, no_cck, MAC_ARG(GetAddr1Ptr(buf)));
8545 
8546         retval = rtw_sae_preprocess(padapter, buf, len, _TRUE);
8547         if (retval == 2)
8548             goto exit;
8549         if (retval == 0)
8550             RTW_INFO("RTW_Tx:AUTH\n");
8551         dump_limit = 1;
8552         goto dump;
8553     }
8554 
8555     if (rtw_action_frame_parse(buf, len, &category, &action) == _FALSE) {
8556         RTW_INFO(FUNC_ADPT_FMT" frame_control:0x%02x\n", FUNC_ADPT_ARG(padapter),
8557             le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)buf)->frame_ctl));
8558         goto exit;
8559     }
8560 
8561     RTW_INFO("RTW_Tx:tx_ch=%d, no_cck=%u, da="MAC_FMT"\n", tx_ch, no_cck, MAC_ARG(GetAddr1Ptr(buf)));
8562 #ifdef CONFIG_P2P
8563     type = rtw_p2p_check_frames(padapter, buf, len, _TRUE);
8564     if (type >= 0) {
8565         is_p2p = 1;
8566         no_cck = 1; /* force no CCK for P2P frames */
8567         goto dump;
8568     }
8569 #endif
8570 #ifdef CONFIG_RTW_MESH
8571     if (MLME_IS_MESH(padapter)) {
8572         type = rtw_mesh_check_frames_tx(padapter, &dump_buf, &dump_len);
8573         if (type >= 0) {
8574             dump_limit = 1;
8575             goto dump;
8576         }
8577     }
8578 #endif
8579     if (category == RTW_WLAN_CATEGORY_PUBLIC) {
8580         RTW_INFO("RTW_Tx:%s\n", action_public_str(action));
8581         switch (action) {
8582         case ACT_PUBLIC_GAS_INITIAL_REQ:
8583         case ACT_PUBLIC_GAS_INITIAL_RSP:
8584             sleep_ms = 50;
8585             retry_guarantee_ms = RTW_MAX_MGMT_TX_MS_GAS;
8586             break;
8587         }
8588     }
8589 #ifdef CONFIG_RTW_80211K
8590     else if (category == RTW_WLAN_CATEGORY_RADIO_MEAS)
8591         RTW_INFO("RTW_Tx: RRM Action\n");
8592 #endif
8593     else
8594         RTW_INFO("RTW_Tx:category(%u), action(%u)\n", category, action);
8595 
8596 dump:
8597 
8598     rtw_ps_deny(padapter, PS_DENY_MGNT_TX);
8599     if (_FAIL == rtw_pwr_wakeup(padapter)) {
8600         ret = -EFAULT;
8601         goto cancel_ps_deny;
8602     }
8603 
8604     while (1) {
8605         dump_cnt++;
8606 
8607         rtw_mi_set_scan_deny(padapter, 1000);
8608         rtw_mi_scan_abort(padapter, _TRUE);
8609         tx_ret = rtw_mgnt_tx_cmd(padapter, tx_ch, no_cck, dump_buf, dump_len, wait_ack, RTW_CMDF_WAIT_ACK);
8610         if (tx_ret == _SUCCESS
8611             || (dump_cnt >= dump_limit && rtw_get_passing_time_ms(start) >= retry_guarantee_ms))
8612             break;
8613 
8614         if (sleep_ms > 0)
8615             rtw_msleep_os(sleep_ms);
8616     }
8617 
8618     if (tx_ret != _SUCCESS || dump_cnt > 1) {
8619         RTW_INFO(FUNC_ADPT_FMT" %s (%d/%d) in %d ms\n", FUNC_ADPT_ARG(padapter),
8620             tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt, dump_limit, rtw_get_passing_time_ms(start));
8621     }
8622 
8623 #ifdef CONFIG_P2P
8624     if (is_p2p) {
8625         switch (type) {
8626         case P2P_GO_NEGO_CONF:
8627             if (0) {
8628                 RTW_INFO(FUNC_ADPT_FMT" Nego confirm. state=%u, status=%u, iaddr="MAC_FMT"\n"
8629                     , FUNC_ADPT_ARG(padapter), pwdev_priv->nego_info.state, pwdev_priv->nego_info.status
8630                     , MAC_ARG(pwdev_priv->nego_info.iface_addr));
8631             }
8632             if (pwdev_priv->nego_info.state == 2
8633                 && pwdev_priv->nego_info.status == 0
8634                 && rtw_check_invalid_mac_address(pwdev_priv->nego_info.iface_addr, _FALSE) == _FALSE
8635             ) {
8636                 _adapter *intended_iface = dvobj_get_adapter_by_addr(dvobj, pwdev_priv->nego_info.iface_addr);
8637 
8638                 if (intended_iface) {
8639                     RTW_INFO(FUNC_ADPT_FMT" Nego confirm. Allow only "ADPT_FMT" to scan for 2000 ms\n"
8640                         , FUNC_ADPT_ARG(padapter), ADPT_ARG(intended_iface));
8641                     /* allow only intended_iface to do scan for 2000 ms */
8642                     rtw_mi_set_scan_deny(padapter, 2000);
8643                     rtw_clear_scan_deny(intended_iface);
8644                 }
8645             }
8646             break;
8647         case P2P_INVIT_RESP:
8648             if (pwdev_priv->invit_info.flags & BIT(0)
8649                 && pwdev_priv->invit_info.status == 0
8650             ) {
8651                 rtw_clear_scan_deny(padapter);
8652                 RTW_INFO(FUNC_ADPT_FMT" agree with invitation of persistent group\n",
8653                     FUNC_ADPT_ARG(padapter));
8654                 #if !RTW_P2P_GROUP_INTERFACE
8655                 rtw_mi_buddy_set_scan_deny(padapter, 5000);
8656                 #endif
8657                 rtw_pwr_wakeup_ex(padapter, 5000);
8658             }
8659             break;
8660         }
8661     }
8662 #endif /* CONFIG_P2P */
8663 
8664 cancel_ps_deny:
8665     rtw_ps_deny_cancel(padapter, PS_DENY_MGNT_TX);
8666 
8667     if (dump_buf != buf)
8668         rtw_mfree((u8 *)dump_buf, dump_len);
8669 exit:
8670     return ret;
8671 }
8672 
8673 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0))
cfg80211_rtw_mgmt_frame_register(struct wiphy * wiphy,struct wireless_dev * wdev,u16 frame_type,bool reg)8674 static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
8675 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8676     struct wireless_dev *wdev,
8677 #else
8678     struct net_device *ndev,
8679 #endif
8680     u16 frame_type, bool reg)
8681 {
8682 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8683     struct net_device *ndev = wdev_to_ndev(wdev);
8684 #endif
8685     _adapter *adapter;
8686     struct rtw_wdev_priv *pwdev_priv;
8687 
8688     if (ndev == NULL)
8689         goto exit;
8690 
8691     adapter = (_adapter *)rtw_netdev_priv(ndev);
8692     pwdev_priv = adapter_wdev_data(adapter);
8693 
8694 #ifdef CONFIG_DEBUG_CFG80211
8695     RTW_INFO(FUNC_ADPT_FMT" frame_type:%x, reg:%d\n", FUNC_ADPT_ARG(adapter),
8696         frame_type, reg);
8697 #endif
8698 
8699     switch (frame_type) {
8700     case IEEE80211_STYPE_AUTH: /* 0x00B0 */
8701         if (reg > 0)
8702             SET_CFG80211_REPORT_MGMT(pwdev_priv, IEEE80211_STYPE_AUTH);
8703         else
8704             CLR_CFG80211_REPORT_MGMT(pwdev_priv, IEEE80211_STYPE_AUTH);
8705         break;
8706     case IEEE80211_STYPE_PROBE_REQ: /* 0x0040 */
8707         if (reg > 0)
8708             SET_CFG80211_REPORT_MGMT(pwdev_priv, IEEE80211_STYPE_PROBE_REQ);
8709         else
8710             CLR_CFG80211_REPORT_MGMT(pwdev_priv, IEEE80211_STYPE_PROBE_REQ);
8711         break;
8712 #ifdef not_yet
8713     case IEEE80211_STYPE_ACTION: /* 0x00D0 */
8714         if (reg > 0)
8715             SET_CFG80211_REPORT_MGMT(pwdev_priv, IEEE80211_STYPE_ACTION);
8716         else
8717             CLR_CFG80211_REPORT_MGMT(pwdev_priv, IEEE80211_STYPE_ACTION);
8718         break;
8719 #endif
8720     default:
8721         break;
8722     }
8723 
8724 exit:
8725     return;
8726 }
8727 #else
cfg80211_rtw_update_mgmt_frame_register(struct wiphy * wiphy,struct wireless_dev * wdev,struct mgmt_frame_regs * upd)8728 static void cfg80211_rtw_update_mgmt_frame_register(
8729     struct wiphy *wiphy,
8730     struct wireless_dev *wdev,
8731     struct mgmt_frame_regs *upd)
8732 {
8733     struct net_device *ndev;
8734     _adapter *padapter;
8735     struct rtw_wdev_priv *pwdev_priv;
8736     u32 rtw_stypes_mask = 0;
8737     u32 rtw_mstypes_mask = 0;
8738 
8739     ndev = wdev_to_ndev(wdev);
8740 
8741     if (ndev == NULL)
8742         goto exit;
8743 
8744     padapter = (_adapter *)rtw_netdev_priv(ndev);
8745     pwdev_priv = adapter_wdev_data(padapter);
8746 
8747     /* Driver only supports Auth and Probe request */
8748     rtw_stypes_mask = BIT(IEEE80211_STYPE_AUTH >> 4) |
8749               BIT(IEEE80211_STYPE_PROBE_REQ >> 4);
8750 
8751 #ifdef CONFIG_DEBUG_CFG80211
8752     RTW_INFO(FUNC_ADPT_FMT " global_stypes:0x%08x interface_stypes:0x%08x\n",
8753         FUNC_ADPT_ARG(padapter), upd->global_stypes, upd->interface_stypes);
8754     RTW_INFO(FUNC_ADPT_FMT " global_mcast_stypes:0x%08x interface_mcast_stypes:0x%08x\n",
8755         FUNC_ADPT_ARG(padapter), upd->global_mcast_stypes, upd->interface_mcast_stypes);
8756     RTW_INFO(FUNC_ADPT_FMT " old_regs:0x%08x new_regs:0x%08x\n",
8757         FUNC_ADPT_ARG(padapter), pwdev_priv->mgmt_regs,
8758         (upd->interface_stypes & rtw_stypes_mask));
8759 #endif
8760     if (pwdev_priv->mgmt_regs !=
8761             (upd->interface_stypes & rtw_stypes_mask)) {
8762         pwdev_priv->mgmt_regs = (upd->interface_stypes & rtw_stypes_mask);
8763     }
8764 
8765 exit:
8766     return;
8767 }
8768 #endif
8769 
8770 #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
cfg80211_rtw_tdls_mgmt(struct wiphy * wiphy,struct net_device * ndev,const u8 * peer,u8 action_code,u8 dialog_token,u16 status_code,u32 peer_capability,bool initiator,const u8 * buf,size_t len)8771 static int cfg80211_rtw_tdls_mgmt(struct wiphy *wiphy,
8772     struct net_device *ndev,
8773 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
8774     const u8 *peer,
8775 #else
8776     u8 *peer,
8777 #endif
8778     u8 action_code,
8779     u8 dialog_token,
8780     u16 status_code,
8781 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
8782     u32 peer_capability,
8783 #endif
8784 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
8785     bool initiator,
8786 #endif
8787     const u8 *buf,
8788     size_t len)
8789 {
8790     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
8791     struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8792     struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;
8793     int ret = 0;
8794     struct tdls_txmgmt txmgmt;
8795 
8796     if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _FALSE) {
8797         RTW_INFO("Discard tdls action:%d, since hal doesn't support tdls\n", action_code);
8798         goto discard;
8799     }
8800 
8801     if (rtw_is_tdls_enabled(padapter) == _FALSE) {
8802         RTW_INFO("TDLS is not enabled\n");
8803         goto discard;
8804     }
8805 
8806     if (rtw_tdls_is_driver_setup(padapter)) {
8807         RTW_INFO("Discard tdls action:%d, let driver to set up direct link\n", action_code);
8808         goto discard;
8809     }
8810 
8811     _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
8812     _rtw_memcpy(txmgmt.peer, peer, ETH_ALEN);
8813     txmgmt.action_code = action_code;
8814     txmgmt.dialog_token = dialog_token;
8815     txmgmt.status_code = status_code;
8816     txmgmt.len = len;
8817     txmgmt.buf = (u8 *)rtw_malloc(txmgmt.len);
8818     if (txmgmt.buf == NULL) {
8819         ret = -ENOMEM;
8820         goto bad;
8821     }
8822     _rtw_memcpy(txmgmt.buf, (void *)buf, txmgmt.len);
8823 
8824     /* Debug purpose */
8825 #if 1
8826     RTW_INFO("%s %d\n", __FUNCTION__, __LINE__);
8827     RTW_INFO("peer:"MAC_FMT", action code:%d, dialog:%d, status code:%d\n",
8828         MAC_ARG(txmgmt.peer), txmgmt.action_code,
8829         txmgmt.dialog_token, txmgmt.status_code);
8830     if (txmgmt.len > 0) {
8831         int i = 0;
8832         for (; i < len; i++)
8833             printk("%02x ", *(txmgmt.buf + i));
8834         RTW_INFO("len:%d\n", (u32)txmgmt.len);
8835     }
8836 #endif
8837 
8838     switch (txmgmt.action_code) {
8839     case TDLS_SETUP_REQUEST:
8840         issue_tdls_setup_req(padapter, &txmgmt, _TRUE);
8841         break;
8842     case TDLS_SETUP_RESPONSE:
8843         issue_tdls_setup_rsp(padapter, &txmgmt);
8844         break;
8845     case TDLS_SETUP_CONFIRM:
8846         issue_tdls_setup_cfm(padapter, &txmgmt);
8847         break;
8848     case TDLS_TEARDOWN:
8849         issue_tdls_teardown(padapter, &txmgmt, _TRUE);
8850         break;
8851     case TDLS_DISCOVERY_REQUEST:
8852         issue_tdls_dis_req(padapter, &txmgmt);
8853         break;
8854     case TDLS_DISCOVERY_RESPONSE:
8855         issue_tdls_dis_rsp(padapter, &txmgmt, pmlmeinfo->enc_algo ? _TRUE : _FALSE);
8856         break;
8857     }
8858 
8859 bad:
8860     if (txmgmt.buf)
8861         rtw_mfree(txmgmt.buf, txmgmt.len);
8862 
8863 discard:
8864     return ret;
8865 }
8866 
cfg80211_rtw_tdls_oper(struct wiphy * wiphy,struct net_device * ndev,const u8 * peer,enum nl80211_tdls_operation oper)8867 static int cfg80211_rtw_tdls_oper(struct wiphy *wiphy,
8868     struct net_device *ndev,
8869 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
8870     const u8 *peer,
8871 #else
8872     u8 *peer,
8873 #endif
8874     enum nl80211_tdls_operation oper)
8875 {
8876     _adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
8877     struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
8878     struct tdls_txmgmt    txmgmt;
8879     struct sta_info *ptdls_sta = NULL;
8880 
8881     RTW_INFO(FUNC_NDEV_FMT", nl80211_tdls_operation:%d\n", FUNC_NDEV_ARG(ndev), oper);
8882 
8883     if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _FALSE) {
8884         RTW_INFO("Discard tdls oper:%d, since hal doesn't support tdls\n", oper);
8885         return 0;
8886     }
8887 
8888     if (rtw_is_tdls_enabled(padapter) == _FALSE) {
8889         RTW_INFO("TDLS is not enabled\n");
8890         return 0;
8891     }
8892 
8893 #ifdef CONFIG_LPS
8894     rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 0);
8895 #endif /* CONFIG_LPS */
8896 
8897     _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
8898     if (peer)
8899         _rtw_memcpy(txmgmt.peer, peer, ETH_ALEN);
8900 
8901     if (rtw_tdls_is_driver_setup(padapter)) {
8902         /* these two cases are done by driver itself */
8903         if (oper == NL80211_TDLS_ENABLE_LINK || oper == NL80211_TDLS_DISABLE_LINK)
8904             return 0;
8905     }
8906 
8907     switch (oper) {
8908     case NL80211_TDLS_DISCOVERY_REQ:
8909         issue_tdls_dis_req(padapter, &txmgmt);
8910         break;
8911     case NL80211_TDLS_SETUP:
8912 #ifdef CONFIG_WFD
8913         if (_AES_ != padapter->securitypriv.dot11PrivacyAlgrthm) {
8914             if (padapter->wdinfo.wfd_tdls_weaksec == _TRUE)
8915                 issue_tdls_setup_req(padapter, &txmgmt, _TRUE);
8916             else
8917                 RTW_INFO("[%s] Current link is not AES, SKIP sending the tdls setup request!!\n", __FUNCTION__);
8918         } else
8919 #endif /* CONFIG_WFD */
8920         {
8921             issue_tdls_setup_req(padapter, &txmgmt, _TRUE);
8922         }
8923         break;
8924     case NL80211_TDLS_TEARDOWN:
8925         ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), txmgmt.peer);
8926         if (ptdls_sta != NULL) {
8927             txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
8928             issue_tdls_teardown(padapter, &txmgmt, _TRUE);
8929         } else
8930             RTW_INFO("TDLS peer not found\n");
8931         break;
8932     case NL80211_TDLS_ENABLE_LINK:
8933         RTW_INFO(FUNC_NDEV_FMT", NL80211_TDLS_ENABLE_LINK;mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(peer));
8934         ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), (u8 *)peer);
8935         if (ptdls_sta != NULL) {
8936             rtw_tdls_set_link_established(padapter, _TRUE);
8937             ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;
8938             ptdls_sta->state |= WIFI_ASOC_STATE;
8939             rtw_tdls_cmd(padapter, txmgmt.peer, TDLS_ESTABLISHED);
8940         }
8941         break;
8942     case NL80211_TDLS_DISABLE_LINK:
8943         RTW_INFO(FUNC_NDEV_FMT", NL80211_TDLS_DISABLE_LINK;mac:"MAC_FMT"\n", FUNC_NDEV_ARG(ndev), MAC_ARG(peer));
8944         ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), (u8 *)peer);
8945         if (ptdls_sta != NULL) {
8946             rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);
8947             rtw_tdls_cmd(padapter, (u8 *)peer, TDLS_TEARDOWN_STA_LOCALLY_POST);
8948         }
8949         break;
8950     }
8951     return 0;
8952 }
8953 #endif /* CONFIG_TDLS */
8954 
8955 #if defined(CONFIG_RTW_MESH) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
8956 
8957 #if DBG_RTW_CFG80211_MESH_CONF
8958 #define LEGACY_RATES_STR_LEN (RTW_G_RATES_NUM * 5 + 1)
get_legacy_rates_str(struct wiphy * wiphy,enum nl80211_band band,u32 mask,char * buf)8959 int get_legacy_rates_str(struct wiphy *wiphy, enum nl80211_band band, u32 mask, char *buf)
8960 {
8961     int i;
8962     int cnt = 0;
8963 
8964     for (i = 0; i < wiphy->bands[band]->n_bitrates; i++) {
8965         if (mask & BIT(i)) {
8966             cnt += snprintf(buf + cnt, LEGACY_RATES_STR_LEN - cnt -1, "%d.%d "
8967                 , wiphy->bands[band]->bitrates[i].bitrate / 10
8968                 , wiphy->bands[band]->bitrates[i].bitrate % 10);
8969             if (cnt >= LEGACY_RATES_STR_LEN - 1)
8970                 break;
8971         }
8972     }
8973 
8974     return cnt;
8975 }
8976 
dump_mesh_setup(void * sel,struct wiphy * wiphy,const struct mesh_setup * setup)8977 void dump_mesh_setup(void *sel, struct wiphy *wiphy, const struct mesh_setup *setup)
8978 {
8979 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8980 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
8981     struct cfg80211_chan_def *chdef = (struct cfg80211_chan_def *)(&setup->chandef);
8982 #endif
8983     struct ieee80211_channel *chan;
8984 #endif
8985 
8986 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
8987     chan = (struct ieee80211_channel *)chdef->chan;
8988 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8989     chan = (struct ieee80211_channel *)setup->channel;
8990 #endif
8991 
8992     RTW_PRINT_SEL(sel, "mesh_id:\"%s\", len:%u\n", setup->mesh_id, setup->mesh_id_len);
8993 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
8994     RTW_PRINT_SEL(sel, "sync_method:%u\n", setup->sync_method);
8995 #endif
8996     RTW_PRINT_SEL(sel, "path_sel_proto:%u, path_metric:%u\n", setup->path_sel_proto, setup->path_metric);
8997 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8998     RTW_PRINT_SEL(sel, "auth_id:%u\n", setup->auth_id);
8999 #endif
9000 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
9001     if (setup->ie && setup->ie_len) {
9002         RTW_PRINT_SEL(sel, "ie:%p, len:%u\n", setup->ie, setup->ie_len);
9003         dump_ies(RTW_DBGDUMP, setup->ie, setup->ie_len);
9004     }
9005 #else
9006     if (setup->vendor_ie && setup->vendor_ie_len) {
9007         RTW_PRINT_SEL(sel, "ie:%p, len:%u\n", setup->vendor_ie, setup->vendor_ie_len);
9008         dump_ies(RTW_DBGDUMP, setup->vendor_ie, setup->vendor_ie_len);
9009     }
9010 #endif
9011 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
9012     RTW_PRINT_SEL(sel, "is_authenticated:%d, is_secure:%d\n", setup->is_authenticated, setup->is_secure);
9013 #endif
9014 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
9015     RTW_PRINT_SEL(sel, "user_mpm:%d\n", setup->user_mpm);
9016 #endif
9017 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9018     RTW_PRINT_SEL(sel, "dtim_period:%u, beacon_interval:%u\n", setup->dtim_period, setup->beacon_interval);
9019 #endif
9020 
9021 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9022 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
9023     RTW_PRINT_SEL(sel, "center_freq:%u, ch:%u, width:%s, cfreq1:%u, cfreq2:%u\n"
9024         , chan->center_freq, chan->hw_value, nl80211_chan_width_str(chdef->width), chdef->center_freq1, chdef->center_freq2);
9025 #else
9026     RTW_PRINT_SEL(sel, "center_freq:%u, ch:%u, channel_type:%s\n"
9027         , chan->center_freq, chan->hw_value, nl80211_channel_type_str(setup->channel_type));
9028 #endif
9029 #endif
9030 
9031 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
9032     if (setup->mcast_rate[chan->band]) {
9033         RTW_PRINT_SEL(sel, "mcast_rate:%d.%d\n"
9034             , wiphy->bands[chan->band]->bitrates[setup->mcast_rate[chan->band] - 1].bitrate / 10
9035             , wiphy->bands[chan->band]->bitrates[setup->mcast_rate[chan->band] - 1].bitrate % 10
9036         );
9037     }
9038 #endif
9039 
9040 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9041     if (setup->basic_rates) {
9042         char buf[LEGACY_RATES_STR_LEN] = {0};
9043 
9044         get_legacy_rates_str(wiphy, chan->band, setup->basic_rates, buf);
9045         RTW_PRINT_SEL(sel, "basic_rates:%s\n", buf);
9046     }
9047 #endif
9048 
9049 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
9050     if (setup->beacon_rate.control[chan->band].legacy) {
9051         char buf[LEGACY_RATES_STR_LEN] = {0};
9052 
9053         get_legacy_rates_str(wiphy, chan->band, setup->beacon_rate.control[chan->band].legacy, buf);
9054         RTW_PRINT_SEL(sel, "beacon_rate.legacy:%s\n", buf);
9055     }
9056     if (*((u32 *)&(setup->beacon_rate.control[chan->band].ht_mcs[0]))
9057         || *((u32 *)&(setup->beacon_rate.control[chan->band].ht_mcs[4]))
9058         || *((u16 *)&(setup->beacon_rate.control[chan->band].ht_mcs[8]))
9059     ) {
9060         RTW_PRINT_SEL(sel, "beacon_rate.ht_mcs:"HT_RX_MCS_BMP_FMT"\n"
9061             , HT_RX_MCS_BMP_ARG(setup->beacon_rate.control[chan->band].ht_mcs));
9062     }
9063 
9064     if (setup->beacon_rate.control[chan->band].vht_mcs[0]
9065         || setup->beacon_rate.control[chan->band].vht_mcs[1]
9066         || setup->beacon_rate.control[chan->band].vht_mcs[2]
9067         || setup->beacon_rate.control[chan->band].vht_mcs[3]
9068     ) {
9069         int i;
9070 
9071         for (i = 0; i < 4; i++) {/* parsing up to 4SS */
9072             u16 mcs_mask = setup->beacon_rate.control[chan->band].vht_mcs[i];
9073 
9074             RTW_PRINT_SEL(sel, "beacon_rate.vht_mcs[%d]:%s\n", i
9075                 , mcs_mask == 0x00FF ? "0~7" : mcs_mask == 0x01FF ? "0~8" : mcs_mask == 0x03FF ? "0~9" : "invalid");
9076         }
9077     }
9078 
9079     if (setup->beacon_rate.control[chan->band].gi) {
9080         RTW_PRINT_SEL(sel, "beacon_rate.gi:%s\n"
9081             , setup->beacon_rate.control[chan->band].gi == NL80211_TXRATE_FORCE_SGI ? "SGI" :
9082                 setup->beacon_rate.control[chan->band].gi == NL80211_TXRATE_FORCE_LGI ? "LGI" : "invalid"
9083         );
9084     }
9085 #endif
9086 }
9087 
dump_mesh_config(void * sel,const struct mesh_config * conf)9088 void dump_mesh_config(void *sel, const struct mesh_config *conf)
9089 {
9090     RTW_PRINT_SEL(sel, "dot11MeshRetryTimeout:%u\n", conf->dot11MeshRetryTimeout);
9091     RTW_PRINT_SEL(sel, "dot11MeshConfirmTimeout:%u\n", conf->dot11MeshConfirmTimeout);
9092     RTW_PRINT_SEL(sel, "dot11MeshHoldingTimeout:%u\n", conf->dot11MeshHoldingTimeout);
9093     RTW_PRINT_SEL(sel, "dot11MeshMaxPeerLinks:%u\n", conf->dot11MeshMaxPeerLinks);
9094     RTW_PRINT_SEL(sel, "dot11MeshMaxRetries:%u\n", conf->dot11MeshMaxRetries);
9095     RTW_PRINT_SEL(sel, "dot11MeshTTL:%u\n", conf->dot11MeshTTL);
9096     RTW_PRINT_SEL(sel, "element_ttl:%u\n", conf->element_ttl);
9097     RTW_PRINT_SEL(sel, "auto_open_plinks:%d\n", conf->auto_open_plinks);
9098 
9099 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
9100     RTW_PRINT_SEL(sel, "dot11MeshNbrOffsetMaxNeighbor:%u\n", conf->dot11MeshNbrOffsetMaxNeighbor);
9101 #endif
9102 
9103     RTW_PRINT_SEL(sel, "dot11MeshHWMPmaxPREQretries:%u\n", conf->dot11MeshHWMPmaxPREQretries);
9104     RTW_PRINT_SEL(sel, "path_refresh_time:%u\n", conf->path_refresh_time);
9105     RTW_PRINT_SEL(sel, "min_discovery_timeout:%u\n", conf->min_discovery_timeout);
9106     RTW_PRINT_SEL(sel, "dot11MeshHWMPactivePathTimeout:%u\n", conf->dot11MeshHWMPactivePathTimeout);
9107     RTW_PRINT_SEL(sel, "dot11MeshHWMPpreqMinInterval:%u\n", conf->dot11MeshHWMPpreqMinInterval);
9108 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
9109     RTW_PRINT_SEL(sel, "dot11MeshHWMPperrMinInterval:%u\n", conf->dot11MeshHWMPperrMinInterval);
9110 #endif
9111     RTW_PRINT_SEL(sel, "dot11MeshHWMPnetDiameterTraversalTime:%u\n", conf->dot11MeshHWMPnetDiameterTraversalTime);
9112     RTW_PRINT_SEL(sel, "dot11MeshHWMPRootMode:%u\n", conf->dot11MeshHWMPRootMode);
9113 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
9114     RTW_PRINT_SEL(sel, "dot11MeshHWMPRannInterval:%u\n", conf->dot11MeshHWMPRannInterval);
9115     RTW_PRINT_SEL(sel, "dot11MeshGateAnnouncementProtocol:%d\n", conf->dot11MeshGateAnnouncementProtocol);
9116 #endif
9117 
9118 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9119     RTW_PRINT_SEL(sel, "dot11MeshForwarding:%d\n", conf->dot11MeshForwarding);
9120     RTW_PRINT_SEL(sel, "rssi_threshold:%d\n", conf->rssi_threshold);
9121 #endif
9122 
9123 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
9124     RTW_PRINT_SEL(sel, "ht_opmode:0x%04x\n", conf->ht_opmode);
9125 #endif
9126 
9127 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9128     RTW_PRINT_SEL(sel, "dot11MeshHWMPactivePathToRootTimeout:%u\n", conf->dot11MeshHWMPactivePathToRootTimeout);
9129     RTW_PRINT_SEL(sel, "dot11MeshHWMProotInterval:%u\n", conf->dot11MeshHWMProotInterval);
9130     RTW_PRINT_SEL(sel, "dot11MeshHWMPconfirmationInterval:%u\n", conf->dot11MeshHWMPconfirmationInterval);
9131 #endif
9132 
9133 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9134     RTW_PRINT_SEL(sel, "power_mode:%s\n", nl80211_mesh_power_mode_str(conf->power_mode));
9135     RTW_PRINT_SEL(sel, "dot11MeshAwakeWindowDuration:%u\n", conf->dot11MeshAwakeWindowDuration);
9136 #endif
9137 
9138 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9139     RTW_PRINT_SEL(sel, "plink_timeout:%u\n", conf->plink_timeout);
9140 #endif
9141 }
9142 #endif /* DBG_RTW_CFG80211_MESH_CONF */
9143 
rtw_cfg80211_mesh_info_set_profile(struct rtw_mesh_info * minfo,const struct mesh_setup * setup)9144 static void rtw_cfg80211_mesh_info_set_profile(struct rtw_mesh_info *minfo, const struct mesh_setup *setup)
9145 {
9146     _rtw_memcpy(minfo->mesh_id, setup->mesh_id, setup->mesh_id_len);
9147     minfo->mesh_id_len = setup->mesh_id_len;
9148     minfo->mesh_pp_id = setup->path_sel_proto;
9149     minfo->mesh_pm_id = setup->path_metric;
9150     minfo->mesh_cc_id = 0;
9151 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
9152     minfo->mesh_sp_id = setup->sync_method;
9153 #endif
9154 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9155     minfo->mesh_auth_id = setup->auth_id;
9156 #else
9157     if (setup->is_authenticated) {
9158         u8 *rsn_ie;
9159         sint rsn_ie_len;
9160         struct rsne_info info;
9161         u8 *akm;
9162         u8 AKM_SUITE_SAE[4] = {0x00, 0x0F, 0xAC, 0x08};
9163 
9164         rsn_ie = rtw_get_ie(setup->ie, WLAN_EID_RSN, &rsn_ie_len, setup->ie_len);
9165         if (!rsn_ie || !rsn_ie_len) {
9166             rtw_warn_on(1);
9167             return;
9168         }
9169 
9170         if (rtw_rsne_info_parse(rsn_ie, rsn_ie_len + 2, &info) != _SUCCESS) {
9171             rtw_warn_on(1);
9172             return;
9173         }
9174 
9175         if (!info.akm_list || !info.akm_cnt) {
9176             rtw_warn_on(1);
9177             return;
9178         }
9179 
9180         akm = info.akm_list;
9181         while (akm < info.akm_list + info.akm_cnt * 4) {
9182             if (_rtw_memcmp(akm, AKM_SUITE_SAE, 4) == _TRUE) {
9183                 minfo->mesh_auth_id = 0x01;
9184                 break;
9185             }
9186         }
9187 
9188         if (!minfo->mesh_auth_id) {
9189             rtw_warn_on(1);
9190             return;
9191         }
9192     }
9193 #endif
9194 }
9195 
chk_mesh_attr(enum nl80211_meshconf_params parm,u32 mask)9196 static inline bool chk_mesh_attr(enum nl80211_meshconf_params parm, u32 mask)
9197 {
9198     return (mask >> (parm - 1)) & 0x1;
9199 }
9200 
rtw_cfg80211_mesh_cfg_set(_adapter * adapter,const struct mesh_config * conf,u32 mask)9201 static void rtw_cfg80211_mesh_cfg_set(_adapter *adapter, const struct mesh_config *conf, u32 mask)
9202 {
9203     struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
9204 
9205 #if 0 /* driver MPM */
9206     if (chk_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask));
9207     if (chk_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask));
9208     if (chk_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask));
9209     if (chk_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask));
9210     if (chk_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask));
9211 #endif
9212 
9213     if (chk_mesh_attr(NL80211_MESHCONF_TTL, mask))
9214         mcfg->dot11MeshTTL = conf->dot11MeshTTL;
9215     if (chk_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask))
9216         mcfg->element_ttl = conf->element_ttl;
9217 
9218 #if 0 /* driver MPM */
9219     if (chk_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask));
9220 #endif
9221 
9222 #if 0 /* TBD: synchronization */
9223 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
9224     if (chk_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask));
9225 #endif
9226 #endif
9227 
9228     if (chk_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask))
9229         mcfg->dot11MeshHWMPmaxPREQretries = conf->dot11MeshHWMPmaxPREQretries;
9230     if (chk_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask))
9231         mcfg->path_refresh_time = conf->path_refresh_time;
9232     if (chk_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask))
9233         mcfg->min_discovery_timeout = conf->min_discovery_timeout;
9234     if (chk_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask))
9235         mcfg->dot11MeshHWMPactivePathTimeout = conf->dot11MeshHWMPactivePathTimeout;
9236     if (chk_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask))
9237         mcfg->dot11MeshHWMPpreqMinInterval = conf->dot11MeshHWMPpreqMinInterval;
9238 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
9239     if (chk_mesh_attr(NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, mask))
9240         mcfg->dot11MeshHWMPperrMinInterval = conf->dot11MeshHWMPperrMinInterval;
9241 #endif
9242     if (chk_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, mask))
9243         mcfg->dot11MeshHWMPnetDiameterTraversalTime = conf->dot11MeshHWMPnetDiameterTraversalTime;
9244 
9245     if (chk_mesh_attr(NL80211_MESHCONF_HWMP_ROOTMODE, mask))
9246         mcfg->dot11MeshHWMPRootMode = conf->dot11MeshHWMPRootMode;
9247 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
9248     if (chk_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask))
9249         mcfg->dot11MeshGateAnnouncementProtocol = conf->dot11MeshGateAnnouncementProtocol;
9250     /* our current gate annc implementation rides on root annc with gate annc bit in PREQ flags */
9251     if (mcfg->dot11MeshGateAnnouncementProtocol
9252         && mcfg->dot11MeshHWMPRootMode <= RTW_IEEE80211_ROOTMODE_ROOT
9253     ) {
9254         mcfg->dot11MeshHWMPRootMode = RTW_IEEE80211_PROACTIVE_RANN;
9255         RTW_INFO(ADPT_FMT" enable PROACTIVE_RANN becaue gate annc is needed\n", ADPT_ARG(adapter));
9256     }
9257     if (chk_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask))
9258         mcfg->dot11MeshHWMPRannInterval = conf->dot11MeshHWMPRannInterval;
9259 #endif
9260 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9261     if (chk_mesh_attr(NL80211_MESHCONF_FORWARDING, mask))
9262         mcfg->dot11MeshForwarding = conf->dot11MeshForwarding;
9263 
9264     if (chk_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask))
9265         mcfg->rssi_threshold = conf->rssi_threshold;
9266 #endif
9267 
9268 #if 0 /* controlled by driver */
9269 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
9270     if (chk_mesh_attr(NL80211_MESHCONF_HT_OPMODE, mask));
9271 #endif
9272 #endif
9273 
9274 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9275     if (chk_mesh_attr(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, mask))
9276         mcfg->dot11MeshHWMPactivePathToRootTimeout = conf->dot11MeshHWMPactivePathToRootTimeout;
9277     if (chk_mesh_attr(NL80211_MESHCONF_HWMP_ROOT_INTERVAL, mask))
9278         mcfg->dot11MeshHWMProotInterval = conf->dot11MeshHWMProotInterval;
9279     if (chk_mesh_attr(NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, mask))
9280         mcfg->dot11MeshHWMPconfirmationInterval = conf->dot11MeshHWMPconfirmationInterval;
9281 #endif
9282 
9283 #if 0 /* TBD */
9284 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9285     if (chk_mesh_attr(NL80211_MESHCONF_POWER_MODE, mask));
9286     if (chk_mesh_attr(NL80211_MESHCONF_AWAKE_WINDOW, mask));
9287 #endif
9288 #endif
9289 
9290 #if 0 /* driver MPM */
9291 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9292     if (chk_mesh_attr(NL80211_MESHCONF_PLINK_TIMEOUT, mask));
9293 #endif
9294 #endif
9295 }
9296 
rtw_cfg80211_construct_mesh_beacon_ies(struct wiphy * wiphy,_adapter * adapter,const struct mesh_config * conf,const struct mesh_setup * setup,uint * ies_len)9297 u8 *rtw_cfg80211_construct_mesh_beacon_ies(struct wiphy *wiphy, _adapter *adapter
9298     , const struct mesh_config *conf, const struct mesh_setup *setup
9299     , uint *ies_len)
9300 {
9301     struct rtw_mesh_info *minfo = &adapter->mesh_info;
9302     struct rtw_mesh_cfg *mcfg = &adapter->mesh_cfg;
9303 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9304 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
9305     struct cfg80211_chan_def *chdef = (struct cfg80211_chan_def *)(&setup->chandef);
9306 #endif
9307     struct ieee80211_channel *chan;
9308     u8 ch, bw, offset;
9309 #endif
9310     uint len;
9311     u8 n_bitrates;
9312     u8 ht = 0;
9313     u8 vht = 0;
9314     u8 *rsn_ie = NULL;
9315     sint rsn_ie_len = 0;
9316     u8 *ies = NULL, *c;
9317     u8 supported_rates[RTW_G_RATES_NUM] = {0};
9318     int i;
9319 
9320     *ies_len = 0;
9321 
9322 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
9323     chan = (struct ieee80211_channel *)chdef->chan;
9324 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9325     chan = (struct ieee80211_channel *)setup->channel;
9326 #endif
9327 
9328     n_bitrates = wiphy->bands[chan->band]->n_bitrates;
9329 
9330 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9331 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
9332     rtw_get_chbw_from_cfg80211_chan_def(chdef, &ht, &ch, &bw, &offset);
9333 #else
9334     rtw_get_chbw_from_nl80211_channel_type(chan, setup->channel_type, &ht, &ch, &bw, &offset);
9335 #endif
9336     if (!ch)
9337         goto exit;
9338 
9339 #if defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9340     vht = ht && ch > 14 && bw >= CHANNEL_WIDTH_80; /* VHT40/VHT20? */
9341 #endif
9342 
9343     RTW_INFO(FUNC_ADPT_FMT" => ch:%u,%u,%u, ht:%u, vht:%u\n"
9344         , FUNC_ADPT_ARG(adapter), ch, bw, offset, ht, vht);
9345 #endif
9346 
9347     rsn_ie = rtw_get_ie(setup->ie, WLAN_EID_RSN, &rsn_ie_len, setup->ie_len);
9348     if (rsn_ie && !rsn_ie_len) {
9349         rtw_warn_on(1);
9350         rsn_ie = NULL;
9351     }
9352 
9353     len = _BEACON_IE_OFFSET_
9354         + 2 /* 0-length SSID */
9355         + (n_bitrates >= 8 ? 8 : n_bitrates) + 2 /* Supported Rates */
9356         + 3 /* DS parameter set */
9357         + 6 /* TIM  */
9358         + (n_bitrates > 8 ? n_bitrates - 8 + 2 : 0) /* Extended Supported Rates */
9359         + (rsn_ie ? rsn_ie_len + 2 : 0) /* RSN */
9360         #if defined(CONFIG_80211N_HT)
9361         + (ht ? HT_CAP_IE_LEN + 2 + HT_OP_IE_LEN + 2 : 0) /* HT */
9362         #endif
9363         #if defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9364         + (vht ? VHT_CAP_IE_LEN + 2 + VHT_OP_IE_LEN + 2 : 0) /* VHT */
9365         #endif
9366         + minfo->mesh_id_len + 2 /* Mesh ID */
9367         + 9 /* Mesh configuration */
9368         ;
9369 
9370     ies = rtw_zmalloc(len);
9371     if (!ies)
9372         goto exit;
9373 
9374     /* timestamp */
9375     c = ies + 8;
9376 
9377     /* beacon interval */
9378     RTW_PUT_LE16(c , setup->beacon_interval);
9379     c += 2;
9380 
9381     /* capability */
9382     if (rsn_ie)
9383         *((u16 *)c) |= cpu_to_le16(cap_Privacy);
9384     c += 2;
9385 
9386     /* SSID */
9387     c = rtw_set_ie(c, WLAN_EID_SSID, 0, NULL, NULL);
9388 
9389     /* Supported Rates */
9390     for (i = 0; i < n_bitrates; i++) {
9391         supported_rates[i] = wiphy->bands[chan->band]->bitrates[i].bitrate / 5;
9392         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9393         if (setup->basic_rates & BIT(i))
9394         #else
9395         if (rtw_is_basic_rate_mix(supported_rates[i]))
9396         #endif
9397             supported_rates[i] |= IEEE80211_BASIC_RATE_MASK;
9398     }
9399     c = rtw_set_ie(c, WLAN_EID_SUPP_RATES, (n_bitrates >= 8 ? 8 : n_bitrates), supported_rates, NULL);
9400 
9401     /* DS parameter set */
9402     c = rtw_set_ie(c, WLAN_EID_DS_PARAMS, 1, &ch, NULL);
9403 
9404     /* TIM */
9405     *c = WLAN_EID_TIM;
9406     *(c + 1) = 4;
9407     c += 6;
9408     //c = rtw_set_ie(c, _TIM_IE_, 4, NULL, NULL);
9409 
9410     /* Extended Supported Rates */
9411     if (n_bitrates > 8)
9412         c = rtw_set_ie(c, WLAN_EID_EXT_SUPP_RATES, n_bitrates - 8, supported_rates + 8, NULL);
9413 
9414     /* RSN */
9415     if (rsn_ie)
9416         c = rtw_set_ie(c, WLAN_EID_RSN, rsn_ie_len, rsn_ie + 2, NULL);
9417 
9418 #if defined(CONFIG_80211N_HT)
9419     if (ht) {
9420         struct ieee80211_sta_ht_cap *sta_ht_cap = &wiphy->bands[chan->band]->ht_cap;
9421         u8 ht_cap[HT_CAP_IE_LEN];
9422         u8 ht_op[HT_OP_IE_LEN];
9423 
9424         _rtw_memset(ht_cap, 0, HT_CAP_IE_LEN);
9425         _rtw_memset(ht_op, 0, HT_OP_IE_LEN);
9426 
9427         /* WLAN_EID_HT_CAP */
9428         RTW_PUT_LE16(HT_CAP_ELE_CAP_INFO(ht_cap), sta_ht_cap->cap);
9429         SET_HT_CAP_ELE_MAX_AMPDU_LEN_EXP(ht_cap, sta_ht_cap->ampdu_factor);
9430         SET_HT_CAP_ELE_MIN_MPDU_S_SPACE(ht_cap, sta_ht_cap->ampdu_density);
9431         _rtw_memcpy(HT_CAP_ELE_SUP_MCS_SET(ht_cap), &sta_ht_cap->mcs, 16);
9432         c = rtw_set_ie(c, WLAN_EID_HT_CAP, HT_CAP_IE_LEN, ht_cap, NULL);
9433 
9434         /* WLAN_EID_HT_OPERATION */
9435         SET_HT_OP_ELE_PRI_CHL(ht_op, ch);
9436         switch (offset) {
9437         case HAL_PRIME_CHNL_OFFSET_LOWER:
9438             SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op, SCA);
9439             break;
9440         case HAL_PRIME_CHNL_OFFSET_UPPER:
9441             SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op, SCB);
9442             break;
9443         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
9444         default:
9445             SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op, SCN);
9446             break;
9447         }
9448         if (bw >= CHANNEL_WIDTH_40)
9449             SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op, 1);
9450         else
9451             SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op, 0);
9452         c = rtw_set_ie(c, WLAN_EID_HT_OPERATION, HT_OP_IE_LEN, ht_op, NULL);
9453     }
9454 #endif /* defined(CONFIG_80211N_HT) */
9455 
9456 #if defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9457     if (vht) {
9458         struct ieee80211_sta_vht_cap *sta_vht_cap = &wiphy->bands[chan->band]->vht_cap;
9459         u8 vht_cap[VHT_CAP_IE_LEN];
9460         u8 vht_op[VHT_OP_IE_LEN];
9461         u8 cch = rtw_get_center_ch(ch, bw, offset);
9462 
9463         _rtw_memset(vht_op, 0, VHT_OP_IE_LEN);
9464 
9465         /* WLAN_EID_VHT_CAPABILITY */
9466         _rtw_memcpy(vht_cap, &sta_vht_cap->cap, 4);
9467         _rtw_memcpy(vht_cap + 4, &sta_vht_cap->vht_mcs, 8);
9468         c = rtw_set_ie(c, WLAN_EID_VHT_CAPABILITY, VHT_CAP_IE_LEN, vht_cap, NULL);
9469 
9470         /* WLAN_EID_VHT_OPERATION */
9471         if (bw < CHANNEL_WIDTH_80) {
9472             SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op, 0);
9473             SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op, 0);
9474             SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op, 0);
9475         } else if (bw == CHANNEL_WIDTH_80) {
9476             SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op, 1);
9477             SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op, cch);
9478             SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op, 0);
9479         } else {
9480             RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(adapter), bw);
9481             rtw_warn_on(1);
9482             rtw_mfree(ies, len);
9483             goto exit;
9484         }
9485 
9486         /* Hard code 1 stream, MCS0-7 is a min Basic VHT MCS rates */
9487         vht_op[3] = 0xfc;
9488         vht_op[4] = 0xff;
9489         c = rtw_set_ie(c, WLAN_EID_VHT_OPERATION, VHT_OP_IE_LEN, vht_op, NULL);
9490     }
9491 #endif /* defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) */
9492 
9493     /* Mesh ID */
9494     c = rtw_set_ie_mesh_id(c, NULL, minfo->mesh_id, minfo->mesh_id_len);
9495 
9496     /* Mesh configuration */
9497     c = rtw_set_ie_mesh_config(c, NULL
9498         , minfo->mesh_pp_id
9499         , minfo->mesh_pm_id
9500         , minfo->mesh_cc_id
9501         , minfo->mesh_sp_id
9502         , minfo->mesh_auth_id
9503         , 0, 0, 0
9504         , 1
9505         , 0, 0
9506         , mcfg->dot11MeshForwarding
9507         , 0, 0, 0
9508     );
9509 
9510 #if DBG_RTW_CFG80211_MESH_CONF
9511     RTW_INFO(FUNC_ADPT_FMT" ies_len:%u\n", FUNC_ADPT_ARG(adapter), len);
9512     dump_ies(RTW_DBGDUMP, ies + _BEACON_IE_OFFSET_, len - _BEACON_IE_OFFSET_);
9513 #endif
9514 
9515 exit:
9516     if (ies)
9517         *ies_len = len;
9518     return ies;
9519 }
9520 
cfg80211_rtw_get_mesh_config(struct wiphy * wiphy,struct net_device * dev,struct mesh_config * conf)9521 static int cfg80211_rtw_get_mesh_config(struct wiphy *wiphy, struct net_device *dev
9522     , struct mesh_config *conf)
9523 {
9524     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9525     struct rtw_mesh_cfg *mesh_cfg = &adapter->mesh_cfg;
9526     int ret = 0;
9527 
9528     RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
9529 
9530     /* driver MPM */
9531     conf->dot11MeshRetryTimeout = 0;
9532     conf->dot11MeshConfirmTimeout = 0;
9533     conf->dot11MeshHoldingTimeout = 0;
9534     conf->dot11MeshMaxPeerLinks = mesh_cfg->max_peer_links;
9535     conf->dot11MeshMaxRetries = 0;
9536 
9537     conf->dot11MeshTTL = mesh_cfg->dot11MeshTTL;
9538     conf->element_ttl = mesh_cfg->element_ttl;
9539 
9540     /* driver MPM */
9541     conf->auto_open_plinks = 0;
9542 
9543     /* TBD: synchronization */
9544 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
9545     conf->dot11MeshNbrOffsetMaxNeighbor = 0;
9546 #endif
9547 
9548     conf->dot11MeshHWMPmaxPREQretries = mesh_cfg->dot11MeshHWMPmaxPREQretries;
9549     conf->path_refresh_time = mesh_cfg->path_refresh_time;
9550     conf->min_discovery_timeout = mesh_cfg->min_discovery_timeout;
9551     conf->dot11MeshHWMPactivePathTimeout = mesh_cfg->dot11MeshHWMPactivePathTimeout;
9552     conf->dot11MeshHWMPpreqMinInterval = mesh_cfg->dot11MeshHWMPpreqMinInterval;
9553 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
9554     conf->dot11MeshHWMPperrMinInterval = mesh_cfg->dot11MeshHWMPperrMinInterval;
9555 #endif
9556     conf->dot11MeshHWMPnetDiameterTraversalTime = mesh_cfg->dot11MeshHWMPnetDiameterTraversalTime;
9557     conf->dot11MeshHWMPRootMode = mesh_cfg->dot11MeshHWMPRootMode;
9558 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
9559     conf->dot11MeshHWMPRannInterval = mesh_cfg->dot11MeshHWMPRannInterval;
9560 #endif
9561     conf->dot11MeshGateAnnouncementProtocol = mesh_cfg->dot11MeshGateAnnouncementProtocol;
9562 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9563     conf->dot11MeshForwarding = mesh_cfg->dot11MeshForwarding;
9564     conf->rssi_threshold = mesh_cfg->rssi_threshold;
9565 #endif
9566 
9567     /* TBD */
9568 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
9569     conf->ht_opmode = 0xffff;
9570 #endif
9571 
9572 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9573     conf->dot11MeshHWMPactivePathToRootTimeout = mesh_cfg->dot11MeshHWMPactivePathToRootTimeout;
9574     conf->dot11MeshHWMProotInterval = mesh_cfg->dot11MeshHWMProotInterval;
9575     conf->dot11MeshHWMPconfirmationInterval = mesh_cfg->dot11MeshHWMPconfirmationInterval;
9576 #endif
9577 
9578     /* TBD: power save */
9579 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9580     conf->power_mode = NL80211_MESH_POWER_ACTIVE;
9581     conf->dot11MeshAwakeWindowDuration = 0;
9582 #endif
9583 
9584 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9585     conf->plink_timeout = mesh_cfg->plink_timeout;
9586 #endif
9587 
9588     return ret;
9589 }
9590 
rtw_mbss_info_change_notify(_adapter * adapter,bool minfo_changed,bool need_work)9591 static void rtw_mbss_info_change_notify(_adapter *adapter, bool minfo_changed, bool need_work)
9592 {
9593     if (need_work)
9594         rtw_mesh_work(&adapter->mesh_work);
9595 }
9596 
cfg80211_rtw_update_mesh_config(struct wiphy * wiphy,struct net_device * dev,u32 mask,const struct mesh_config * nconf)9597 static int cfg80211_rtw_update_mesh_config(struct wiphy *wiphy, struct net_device *dev
9598     , u32 mask, const struct mesh_config *nconf)
9599 {
9600     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9601     int ret = 0;
9602     bool minfo_changed = _FALSE, need_work = _FALSE;
9603 
9604     RTW_INFO(FUNC_ADPT_FMT" mask:0x%08x\n", FUNC_ADPT_ARG(adapter), mask);
9605 
9606     rtw_cfg80211_mesh_cfg_set(adapter, nconf, mask);
9607     update_beacon(adapter, WLAN_EID_MESH_CONFIG, NULL, _TRUE, 0);
9608 #if CONFIG_RTW_MESH_CTO_MGATE_CARRIER
9609     if (rtw_mesh_cto_mgate_required(adapter))
9610         rtw_netif_carrier_off(adapter->pnetdev);
9611     else
9612         rtw_netif_carrier_on(adapter->pnetdev);
9613 #endif
9614     need_work = rtw_ieee80211_mesh_root_setup(adapter);
9615 
9616     rtw_mbss_info_change_notify(adapter, minfo_changed, need_work);
9617 
9618     return ret;
9619 }
9620 
cfg80211_rtw_join_mesh(struct wiphy * wiphy,struct net_device * dev,const struct mesh_config * conf,const struct mesh_setup * setup)9621 static int cfg80211_rtw_join_mesh(struct wiphy *wiphy, struct net_device *dev,
9622     const struct mesh_config *conf, const struct mesh_setup *setup)
9623 {
9624     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9625     u8 *ies = NULL;
9626     uint ies_len;
9627     int ret = 0;
9628 
9629     RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
9630 
9631 #if DBG_RTW_CFG80211_MESH_CONF
9632     RTW_INFO(FUNC_ADPT_FMT" mesh_setup:\n", FUNC_ADPT_ARG(adapter));
9633     dump_mesh_setup(RTW_DBGDUMP, wiphy, setup);
9634     RTW_INFO(FUNC_ADPT_FMT" mesh_config:\n", FUNC_ADPT_ARG(adapter));
9635     dump_mesh_config(RTW_DBGDUMP, conf);
9636 #endif
9637 
9638     if (rtw_cfg80211_sync_iftype(adapter) != _SUCCESS) {
9639         ret = -ENOTSUPP;
9640         goto exit;
9641     }
9642 
9643     /* initialization */
9644     rtw_mesh_init_mesh_info(adapter);
9645 
9646     /* apply cfg80211 settings*/
9647     rtw_cfg80211_mesh_info_set_profile(&adapter->mesh_info, setup);
9648     rtw_cfg80211_mesh_cfg_set(adapter, conf, 0xFFFFFFFF);
9649 
9650     /* apply cfg80211 settings (join only) */
9651     rtw_mesh_cfg_init_max_peer_links(adapter, conf->dot11MeshMaxPeerLinks);
9652     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9653     rtw_mesh_cfg_init_plink_timeout(adapter, conf->plink_timeout);
9654     #endif
9655 
9656     rtw_ieee80211_mesh_root_setup(adapter);
9657 
9658     ies = rtw_cfg80211_construct_mesh_beacon_ies(wiphy, adapter, conf, setup, &ies_len);
9659     if (!ies) {
9660         ret = -EINVAL;
9661         goto exit;
9662     }
9663 
9664     /* start mbss */
9665     if (rtw_check_beacon_data(adapter, ies,  ies_len) != _SUCCESS) {
9666         ret = -EINVAL;
9667         goto exit;
9668     }
9669 
9670     rtw_mesh_work(&adapter->mesh_work);
9671 
9672 exit:
9673     if (ies)
9674         rtw_mfree(ies, ies_len);
9675     if (ret)
9676         rtw_mesh_deinit_mesh_info(adapter);
9677 
9678     return ret;
9679 }
9680 
cfg80211_rtw_leave_mesh(struct wiphy * wiphy,struct net_device * dev)9681 static int cfg80211_rtw_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
9682 {
9683     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9684     int ret = 0;
9685 
9686     RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
9687 
9688     rtw_mesh_deinit_mesh_info(adapter);
9689 
9690     rtw_stop_ap_cmd(adapter, RTW_CMDF_WAIT_ACK);
9691 
9692     return ret;
9693 }
9694 
cfg80211_rtw_add_mpath(struct wiphy * wiphy,struct net_device * dev,const u8 * dst,const u8 * next_hop)9695 static int cfg80211_rtw_add_mpath(struct wiphy *wiphy, struct net_device *dev
9696     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9697     , const u8 *dst, const u8 *next_hop
9698     #else
9699     , u8 *dst, u8 *next_hop
9700     #endif
9701 )
9702 {
9703     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9704     struct sta_priv *stapriv = &adapter->stapriv;
9705     struct sta_info *sta;
9706     struct rtw_mesh_path *mpath;
9707     int ret = 0;
9708 
9709     rtw_rcu_read_lock();
9710 
9711     sta = rtw_get_stainfo(stapriv, next_hop);
9712     if (!sta) {
9713         ret = -ENOENT;
9714         goto exit;
9715     }
9716 
9717     mpath = rtw_mesh_path_add(adapter, dst);
9718     if (!mpath) {
9719         ret = -ENOENT;
9720         goto exit;
9721     }
9722 
9723     rtw_mesh_path_fix_nexthop(mpath, sta);
9724 
9725 exit:
9726     rtw_rcu_read_unlock();
9727 
9728     return ret;
9729 }
9730 
cfg80211_rtw_del_mpath(struct wiphy * wiphy,struct net_device * dev,const u8 * dst)9731 static int cfg80211_rtw_del_mpath(struct wiphy *wiphy, struct net_device *dev
9732     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9733     , const u8 *dst
9734     #else
9735     , u8 *dst
9736     #endif
9737 )
9738 {
9739     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9740     int ret = 0;
9741 
9742     if (dst) {
9743         if (rtw_mesh_path_del(adapter, dst)) {
9744             ret = -ENOENT;
9745             goto exit;
9746         }
9747     } else {
9748         rtw_mesh_path_flush_by_iface(adapter);
9749     }
9750 
9751 exit:
9752     return ret;
9753 }
9754 
cfg80211_rtw_change_mpath(struct wiphy * wiphy,struct net_device * dev,const u8 * dst,const u8 * next_hop)9755 static int cfg80211_rtw_change_mpath(struct wiphy *wiphy, struct net_device *dev
9756     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9757     , const u8 *dst, const u8 *next_hop
9758     #else
9759     , u8 *dst, u8 *next_hop
9760     #endif
9761 )
9762 {
9763     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9764     struct sta_priv *stapriv = &adapter->stapriv;
9765     struct sta_info *sta;
9766     struct rtw_mesh_path *mpath;
9767     int ret = 0;
9768 
9769     rtw_rcu_read_lock();
9770 
9771     sta = rtw_get_stainfo(stapriv, next_hop);
9772     if (!sta) {
9773         ret = -ENOENT;
9774         goto exit;
9775     }
9776 
9777     mpath = rtw_mesh_path_lookup(adapter, dst);
9778     if (!mpath) {
9779         ret = -ENOENT;
9780         goto exit;
9781     }
9782 
9783     rtw_mesh_path_fix_nexthop(mpath, sta);
9784 
9785 exit:
9786     rtw_rcu_read_unlock();
9787 
9788     return ret;
9789 }
9790 
rtw_cfg80211_mpath_set_pinfo(struct rtw_mesh_path * mpath,u8 * next_hop,struct mpath_info * pinfo)9791 static void rtw_cfg80211_mpath_set_pinfo(struct rtw_mesh_path *mpath, u8 *next_hop, struct mpath_info *pinfo)
9792 {
9793     struct sta_info *next_hop_sta = rtw_rcu_dereference(mpath->next_hop);
9794 
9795     if (next_hop_sta)
9796         _rtw_memcpy(next_hop, next_hop_sta->cmn.mac_addr, ETH_ALEN);
9797     else
9798         _rtw_memset(next_hop, 0, ETH_ALEN);
9799 
9800     _rtw_memset(pinfo, 0, sizeof(*pinfo));
9801 
9802     pinfo->generation = mpath->adapter->mesh_info.mesh_paths_generation;
9803 
9804     pinfo->filled = 0
9805         | MPATH_INFO_FRAME_QLEN
9806         | MPATH_INFO_SN
9807         | MPATH_INFO_METRIC
9808         | MPATH_INFO_EXPTIME
9809         | MPATH_INFO_DISCOVERY_TIMEOUT
9810         | MPATH_INFO_DISCOVERY_RETRIES
9811         | MPATH_INFO_FLAGS
9812         ;
9813 
9814     pinfo->frame_qlen = mpath->frame_queue_len;
9815     pinfo->sn = mpath->sn;
9816     pinfo->metric = mpath->metric;
9817     if (rtw_time_after(mpath->exp_time, rtw_get_current_time()))
9818         pinfo->exptime = rtw_get_remaining_time_ms(mpath->exp_time);
9819     pinfo->discovery_timeout = rtw_systime_to_ms(mpath->discovery_timeout);
9820     pinfo->discovery_retries = mpath->discovery_retries;
9821     if (mpath->flags & RTW_MESH_PATH_ACTIVE)
9822         pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
9823     if (mpath->flags & RTW_MESH_PATH_RESOLVING)
9824         pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
9825     if (mpath->flags & RTW_MESH_PATH_SN_VALID)
9826         pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID;
9827     if (mpath->flags & RTW_MESH_PATH_FIXED)
9828         pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
9829     if (mpath->flags & RTW_MESH_PATH_RESOLVED)
9830         pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED;
9831 }
9832 
cfg80211_rtw_get_mpath(struct wiphy * wiphy,struct net_device * dev,u8 * dst,u8 * next_hop,struct mpath_info * pinfo)9833 static int cfg80211_rtw_get_mpath(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
9834 {
9835     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9836     struct rtw_mesh_path *mpath;
9837     int ret = 0;
9838 
9839     rtw_rcu_read_lock();
9840 
9841     mpath = rtw_mesh_path_lookup(adapter, dst);
9842     if (!mpath) {
9843         ret = -ENOENT;
9844         goto exit;
9845     }
9846 
9847     rtw_cfg80211_mpath_set_pinfo(mpath, next_hop, pinfo);
9848 
9849 exit:
9850     rtw_rcu_read_unlock();
9851 
9852     return ret;
9853 }
9854 
cfg80211_rtw_dump_mpath(struct wiphy * wiphy,struct net_device * dev,int idx,u8 * dst,u8 * next_hop,struct mpath_info * pinfo)9855 static int cfg80211_rtw_dump_mpath(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
9856 {
9857     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9858     struct rtw_mesh_path *mpath;
9859     int ret = 0;
9860 
9861     rtw_rcu_read_lock();
9862 
9863     mpath = rtw_mesh_path_lookup_by_idx(adapter, idx);
9864     if (!mpath) {
9865         ret = -ENOENT;
9866         goto exit;
9867     }
9868 
9869     _rtw_memcpy(dst, mpath->dst, ETH_ALEN);
9870     rtw_cfg80211_mpath_set_pinfo(mpath, next_hop, pinfo);
9871 
9872 exit:
9873     rtw_rcu_read_unlock();
9874 
9875     return ret;
9876 }
9877 
9878 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
rtw_cfg80211_mpp_set_pinfo(struct rtw_mesh_path * mpath,u8 * mpp,struct mpath_info * pinfo)9879 static void rtw_cfg80211_mpp_set_pinfo(struct rtw_mesh_path *mpath, u8 *mpp, struct mpath_info *pinfo)
9880 {
9881     _rtw_memcpy(mpp, mpath->mpp, ETH_ALEN);
9882 
9883     _rtw_memset(pinfo, 0, sizeof(*pinfo));
9884     pinfo->generation = mpath->adapter->mesh_info.mpp_paths_generation;
9885 }
9886 
cfg80211_rtw_get_mpp(struct wiphy * wiphy,struct net_device * dev,u8 * dst,u8 * mpp,struct mpath_info * pinfo)9887 static int cfg80211_rtw_get_mpp(struct wiphy *wiphy, struct net_device *dev, u8 *dst, u8 *mpp, struct mpath_info *pinfo)
9888 {
9889     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9890     struct rtw_mesh_path *mpath;
9891     int ret = 0;
9892 
9893     rtw_rcu_read_lock();
9894 
9895     mpath = rtw_mpp_path_lookup(adapter, dst);
9896     if (!mpath) {
9897         ret = -ENOENT;
9898         goto exit;
9899     }
9900 
9901     rtw_cfg80211_mpp_set_pinfo(mpath, mpp, pinfo);
9902 
9903 exit:
9904     rtw_rcu_read_unlock();
9905 
9906     return ret;
9907 }
9908 
cfg80211_rtw_dump_mpp(struct wiphy * wiphy,struct net_device * dev,int idx,u8 * dst,u8 * mpp,struct mpath_info * pinfo)9909 static int cfg80211_rtw_dump_mpp(struct wiphy *wiphy, struct net_device *dev, int idx, u8 *dst, u8 *mpp, struct mpath_info *pinfo)
9910 {
9911     _adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
9912     struct rtw_mesh_path *mpath;
9913     int ret = 0;
9914 
9915     rtw_rcu_read_lock();
9916 
9917     mpath = rtw_mpp_path_lookup_by_idx(adapter, idx);
9918     if (!mpath) {
9919         ret = -ENOENT;
9920         goto exit;
9921     }
9922 
9923     _rtw_memcpy(dst, mpath->dst, ETH_ALEN);
9924     rtw_cfg80211_mpp_set_pinfo(mpath, mpp, pinfo);
9925 
9926 exit:
9927     rtw_rcu_read_unlock();
9928 
9929     return ret;
9930 }
9931 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9932 
9933 #endif /* defined(CONFIG_RTW_MESH) */
9934 
9935 #ifdef CONFIG_80211N_HT
rtw_cfg80211_init_ht_capab_ex(_adapter * padapter,struct ieee80211_sta_ht_cap * ht_cap,BAND_TYPE band,u8 rf_type)9936 static void rtw_cfg80211_init_ht_capab_ex(_adapter *padapter
9937     , struct ieee80211_sta_ht_cap *ht_cap, BAND_TYPE band, u8 rf_type)
9938 {
9939     struct registry_priv *pregistrypriv = &padapter->registrypriv;
9940     struct mlme_priv    *pmlmepriv = &padapter->mlmepriv;
9941     struct ht_priv        *phtpriv = &pmlmepriv->htpriv;
9942     u8 stbc_rx_enable = _FALSE;
9943 
9944     rtw_ht_use_default_setting(padapter);
9945 
9946     /* RX LDPC */
9947     if (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_RX))
9948         ht_cap->cap |= IEEE80211_HT_CAP_LDPC_CODING;
9949 
9950     /* TX STBC */
9951     if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX))
9952         ht_cap->cap |= IEEE80211_HT_CAP_TX_STBC;
9953 
9954     /* RX STBC */
9955     if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX)) {
9956         /*rtw_rx_stbc 0: disable, bit(0):enable 2.4g, bit(1):enable 5g*/
9957         if (band == BAND_ON_2_4G)
9958             stbc_rx_enable = (pregistrypriv->rx_stbc & BIT(0)) ? _TRUE : _FALSE;
9959         if (band == BAND_ON_5G)
9960             stbc_rx_enable = (pregistrypriv->rx_stbc & BIT(1)) ? _TRUE : _FALSE;
9961 
9962         if (stbc_rx_enable) {
9963             switch (rf_type) {
9964             case RF_1T1R:
9965                 ht_cap->cap |= IEEE80211_HT_CAP_RX_STBC_1R;/*RX STBC One spatial stream*/
9966                 break;
9967 
9968             case RF_2T2R:
9969             case RF_1T2R:
9970                 ht_cap->cap |= IEEE80211_HT_CAP_RX_STBC_1R;/* Only one spatial-stream STBC RX is supported */
9971                 break;
9972             case RF_3T3R:
9973             case RF_3T4R:
9974             case RF_4T4R:
9975                 ht_cap->cap |= IEEE80211_HT_CAP_RX_STBC_1R;/* Only one spatial-stream STBC RX is supported */
9976                 break;
9977             default:
9978                 RTW_INFO("[warning] rf_type %d is not expected\n", rf_type);
9979                 break;
9980             }
9981         }
9982     }
9983 }
9984 
rtw_cfg80211_init_ht_capab(_adapter * padapter,struct ieee80211_sta_ht_cap * ht_cap,BAND_TYPE band,u8 rf_type)9985 static void rtw_cfg80211_init_ht_capab(_adapter *padapter
9986     , struct ieee80211_sta_ht_cap *ht_cap, BAND_TYPE band, u8 rf_type)
9987 {
9988     struct registry_priv *regsty = &padapter->registrypriv;
9989     u8 rx_nss = 0;
9990 
9991     if (!regsty->ht_enable || !is_supported_ht(regsty->wireless_mode))
9992         return;
9993 
9994     ht_cap->ht_supported = 1;
9995 
9996     ht_cap->cap = IEEE80211_HT_CAP_MAX_AMSDU;
9997 
9998     if (TEST_FLAG(regsty->short_gi, BIT0))
9999         ht_cap->cap |= IEEE80211_HT_CAP_SGI_20;
10000     if (hal_is_bw_support(padapter, CHANNEL_WIDTH_40)
10001         && ((band == BAND_ON_2_4G && REGSTY_IS_BW_2G_SUPPORT(regsty, CHANNEL_WIDTH_40))
10002             || (band == BAND_ON_5G && REGSTY_IS_BW_5G_SUPPORT(regsty, CHANNEL_WIDTH_40)))
10003     ) {
10004         ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
10005         if (band == BAND_ON_2_4G)
10006             ht_cap->cap |= IEEE80211_HT_CAP_DSSSCCK40;
10007         if (TEST_FLAG(regsty->short_gi, BIT1))
10008             ht_cap->cap |= IEEE80211_HT_CAP_SGI_40;
10009     }
10010 
10011     rtw_cfg80211_init_ht_capab_ex(padapter, ht_cap, band, rf_type);
10012 
10013     /*
10014      *Maximum length of AMPDU that the STA can receive.
10015      *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
10016      */
10017     ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
10018 
10019     /*Minimum MPDU start spacing , */
10020     ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
10021 
10022     ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
10023 
10024     rx_nss = GET_HAL_RX_NSS(padapter);
10025     switch (rx_nss) {
10026     case 1:
10027         ht_cap->mcs.rx_mask[0] = 0xFF;
10028         break;
10029     case 2:
10030         ht_cap->mcs.rx_mask[0] = 0xFF;
10031         ht_cap->mcs.rx_mask[1] = 0xFF;
10032         break;
10033     case 3:
10034         ht_cap->mcs.rx_mask[0] = 0xFF;
10035         ht_cap->mcs.rx_mask[1] = 0xFF;
10036         ht_cap->mcs.rx_mask[2] = 0xFF;
10037         break;
10038     case 4:
10039         ht_cap->mcs.rx_mask[0] = 0xFF;
10040         ht_cap->mcs.rx_mask[1] = 0xFF;
10041         ht_cap->mcs.rx_mask[2] = 0xFF;
10042         ht_cap->mcs.rx_mask[3] = 0xFF;
10043         break;
10044     default:
10045         rtw_warn_on(1);
10046         RTW_INFO("%s, error rf_type=%d, rx_nss=%d\n", __func__, rf_type, rx_nss);
10047     };
10048 
10049     ht_cap->mcs.rx_highest = cpu_to_le16(
10050         rtw_ht_mcs_rate(hal_is_bw_support(padapter, CHANNEL_WIDTH_40)
10051             , hal_is_bw_support(padapter, CHANNEL_WIDTH_40) ? ht_cap->cap & IEEE80211_HT_CAP_SGI_40 : ht_cap->cap & IEEE80211_HT_CAP_SGI_20
10052             , ht_cap->mcs.rx_mask) / 10);
10053 }
10054 #endif /* CONFIG_80211N_HT */
10055 
10056 #if defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
rtw_cfg80211_init_vht_capab(_adapter * padapter,struct ieee80211_sta_vht_cap * sta_vht_cap,BAND_TYPE band,u8 rf_type)10057 static void rtw_cfg80211_init_vht_capab(_adapter *padapter
10058     , struct ieee80211_sta_vht_cap *sta_vht_cap, BAND_TYPE band, u8 rf_type)
10059 {
10060     struct registry_priv *regsty = &padapter->registrypriv;
10061     u8 vht_cap_ie[2 + 12] = {0};
10062 
10063     if (!REGSTY_IS_11AC_ENABLE(regsty) || !is_supported_vht(regsty->wireless_mode))
10064         return;
10065 
10066     rtw_vht_use_default_setting(padapter);
10067     rtw_build_vht_cap_ie(padapter, vht_cap_ie);
10068 
10069     sta_vht_cap->vht_supported = 1;
10070 
10071     _rtw_memcpy(&sta_vht_cap->cap, vht_cap_ie + 2, 4);
10072     _rtw_memcpy(&sta_vht_cap->vht_mcs, vht_cap_ie + 2 + 4, 8);
10073 }
10074 #endif /* defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) */
10075 
rtw_cfg80211_init_wdev_data(_adapter * padapter)10076 void rtw_cfg80211_init_wdev_data(_adapter *padapter)
10077 {
10078 #ifdef CONFIG_CONCURRENT_MODE
10079     struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
10080 
10081     ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
10082 #endif
10083 }
10084 
rtw_cfg80211_init_wiphy_band(_adapter * padapter,struct wiphy * wiphy)10085 static int rtw_cfg80211_init_wiphy_band(_adapter *padapter, struct wiphy *wiphy)
10086 {
10087     u8 rf_type;
10088     struct ieee80211_supported_band *band;
10089     int ret = _FAIL;
10090 
10091     rf_type = GET_HAL_RFPATH(padapter);
10092     RTW_INFO("%s:rf_type=%d\n", __func__, rf_type);
10093 
10094     if (IsSupported24G(padapter->registrypriv.wireless_mode)) {
10095         band = wiphy->bands[NL80211_BAND_2GHZ] = rtw_spt_band_alloc(BAND_ON_2_4G);
10096         if (!band)
10097             goto exit;
10098         rtw_2g_channels_init(band->channels);
10099         rtw_2g_rates_init(band->bitrates);
10100         #if defined(CONFIG_80211N_HT)
10101         rtw_cfg80211_init_ht_capab(padapter, &band->ht_cap, BAND_ON_2_4G, rf_type);
10102         #endif
10103     }
10104 #if CONFIG_IEEE80211_BAND_5GHZ
10105     if (is_supported_5g(padapter->registrypriv.wireless_mode)) {
10106         band = wiphy->bands[NL80211_BAND_5GHZ] = rtw_spt_band_alloc(BAND_ON_5G);
10107         if (!band) {
10108             if (wiphy->bands[NL80211_BAND_2GHZ]) {
10109                 rtw_spt_band_free(wiphy->bands[NL80211_BAND_2GHZ]);
10110                 wiphy->bands[NL80211_BAND_2GHZ] = NULL;
10111             }
10112             goto exit;
10113         }
10114         rtw_5g_channels_init(band->channels);
10115         rtw_5g_rates_init(band->bitrates);
10116         #if defined(CONFIG_80211N_HT)
10117         rtw_cfg80211_init_ht_capab(padapter, &band->ht_cap, BAND_ON_5G, rf_type);
10118         #endif
10119         #if defined(CONFIG_80211AC_VHT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
10120         rtw_cfg80211_init_vht_capab(padapter, &band->vht_cap, BAND_ON_5G, rf_type);
10121         #endif
10122     }
10123 #endif
10124 
10125     ret = _SUCCESS;
10126 
10127 exit:
10128     return ret;
10129 }
10130 
10131 #if !defined(CONFIG_REGD_SRC_FROM_OS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
rtw_cfg80211_update_wiphy_max_txpower(_adapter * adapter,struct wiphy * wiphy)10132 void rtw_cfg80211_update_wiphy_max_txpower(_adapter *adapter, struct wiphy *wiphy)
10133 {
10134     struct ieee80211_supported_band *band;
10135     struct ieee80211_channel *channel;
10136     s16 max_txpwr;
10137     int i;
10138 
10139     if (IsSupported24G(adapter->registrypriv.wireless_mode)) {
10140         band = wiphy->bands[NL80211_BAND_2GHZ];
10141         if (band) {
10142             max_txpwr = phy_get_txpwr_by_rate_total_max_mbm(adapter, BAND_ON_2_4G, 1, 1);
10143             if (max_txpwr != UNSPECIFIED_MBM) {
10144                 for (i = 0; i < band->n_channels; i++) {
10145                     channel = &band->channels[i];
10146                     channel->max_power = max_txpwr / MBM_PDBM;
10147                 }
10148             }
10149         }
10150     }
10151 #if CONFIG_IEEE80211_BAND_5GHZ
10152     if (is_supported_5g(adapter->registrypriv.wireless_mode)) {
10153         band = wiphy->bands[NL80211_BAND_5GHZ];
10154         if (band) {
10155             max_txpwr = phy_get_txpwr_by_rate_total_max_mbm(adapter, BAND_ON_5G, 1, 1);
10156             if (max_txpwr != UNSPECIFIED_MBM) {
10157                 for (i = 0; i < band->n_channels; i++) {
10158                     channel = &band->channels[i];
10159                     channel->max_power = max_txpwr / MBM_PDBM;
10160                 }
10161             }
10162         }
10163     }
10164 #endif
10165 }
10166 #endif /* defined(CONFIG_REGD_SRC_FROM_OS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
10167 
10168 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && defined(RTW_SINGLE_WIPHY) && (CONFIG_IFACE_NUMBER >= 2)
10169 struct ieee80211_iface_limit rtw_limits[] = {
10170     {
10171         .max = CONFIG_IFACE_NUMBER,
10172         .types = BIT(NL80211_IFTYPE_STATION)
10173             #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
10174             | BIT(NL80211_IFTYPE_P2P_CLIENT)
10175             #endif
10176     },
10177     #ifdef CONFIG_AP_MODE
10178     {
10179         .max = rtw_min(CONFIG_IFACE_NUMBER, CONFIG_LIMITED_AP_NUM),
10180         .types = BIT(NL80211_IFTYPE_AP)
10181             #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
10182             | BIT(NL80211_IFTYPE_P2P_GO)
10183             #endif
10184     },
10185     #endif
10186     #if defined(RTW_DEDICATED_P2P_DEVICE)
10187     {
10188         .max = 1,
10189         .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
10190     },
10191     #endif
10192     #if defined(CONFIG_RTW_MESH)
10193     {
10194         .max = 1,
10195         .types = BIT(NL80211_IFTYPE_MESH_POINT)
10196     },
10197     #endif
10198 };
10199 
10200 struct ieee80211_iface_combination rtw_combinations[] = {
10201     {
10202         .limits = rtw_limits,
10203         .n_limits = ARRAY_SIZE(rtw_limits),
10204         #if defined(RTW_DEDICATED_P2P_DEVICE)
10205         .max_interfaces = CONFIG_IFACE_NUMBER + 1,
10206         #else
10207         .max_interfaces = CONFIG_IFACE_NUMBER,
10208         #endif
10209         .num_different_channels = 1,
10210     },
10211 };
10212 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) */
10213 
rtw_cfg80211_init_wiphy(_adapter * adapter,struct wiphy * wiphy)10214 static int rtw_cfg80211_init_wiphy(_adapter *adapter, struct wiphy *wiphy)
10215 {
10216     struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
10217     struct registry_priv *regsty = dvobj_to_regsty(dvobj);
10218     int ret = _FAIL;
10219 
10220     /* copy mac_addr to wiphy */
10221     _rtw_memcpy(wiphy->perm_addr, adapter_mac_addr(adapter), ETH_ALEN);
10222 
10223     wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10224 
10225     wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
10226     wiphy->max_scan_ie_len = RTW_SCAN_IE_LEN_MAX;
10227     wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
10228 
10229 #if CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
10230     wiphy->max_acl_mac_addrs = NUM_ACL;
10231 #endif
10232 
10233 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) || defined(COMPAT_KERNEL_RELEASE)
10234     wiphy->max_remain_on_channel_duration = RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
10235 #endif
10236 
10237     wiphy->interface_modes =    BIT(NL80211_IFTYPE_STATION)
10238                                 #ifdef CONFIG_AP_MODE
10239                                 | BIT(NL80211_IFTYPE_ADHOC) /* todo : AD-HOC task group will refine it */
10240                                 | BIT(NL80211_IFTYPE_AP)
10241                                 #endif
10242                                 #ifdef CONFIG_WIFI_MONITOR
10243                                 | BIT(NL80211_IFTYPE_MONITOR)
10244                                 #endif
10245 #if defined(CONFIG_P2P) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE))
10246                                 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10247                                 | BIT(NL80211_IFTYPE_P2P_GO)
10248                                 #if defined(RTW_DEDICATED_P2P_DEVICE)
10249                                 | BIT(NL80211_IFTYPE_P2P_DEVICE)
10250                                 #endif
10251 #endif
10252 #ifdef CONFIG_RTW_MESH
10253                                 | BIT(NL80211_IFTYPE_MESH_POINT) /* 2.6.26 */
10254 #endif
10255                                 ;
10256 
10257 #if !defined(RTW_SINGLE_WIPHY) && defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_P2P)
10258     if (adapter->iface_id != adapter->registrypriv.sel_p2p_iface) {
10259         wiphy->interface_modes &= ~(BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT));
10260         RTW_INFO("%s iface_id:%d- don't set p2p capability\n", __func__, adapter->iface_id);
10261     }
10262 #endif
10263 
10264 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
10265     wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
10266 #endif
10267 
10268 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
10269     #ifdef CONFIG_WIFI_MONITOR
10270     wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
10271     #endif
10272 #endif
10273 
10274 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && defined(RTW_SINGLE_WIPHY) && (CONFIG_IFACE_NUMBER >= 2)
10275     wiphy->iface_combinations = rtw_combinations;
10276     wiphy->n_iface_combinations = ARRAY_SIZE(rtw_combinations);
10277 #endif
10278 
10279     wiphy->cipher_suites = rtw_cipher_suites;
10280 
10281     /* Todo refine */
10282     if (_rtw_camctl_chk_cap(adapter, SEC_CAP_CHK_EXTRA_SEC))
10283         wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
10284     else {
10285 #ifdef CONFIG_IEEE80211W
10286         /* remove hardware not support cipher */
10287         wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites) - 6;
10288 #else
10289         wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
10290 #endif
10291     }
10292 
10293     if (rtw_cfg80211_init_wiphy_band(adapter, wiphy) != _SUCCESS) {
10294         RTW_ERR("rtw_cfg80211_init_wiphy_band fail\n");
10295         goto exit;
10296     }
10297     #if !defined(CONFIG_REGD_SRC_FROM_OS) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
10298     rtw_cfg80211_update_wiphy_max_txpower(adapter, wiphy);
10299     #endif
10300 
10301 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) && LINUX_VERSION_CODE < KERNEL_VERSION(3, 0, 0))
10302     wiphy->flags |= WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS;
10303 #endif
10304 
10305 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
10306     wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
10307     wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
10308     /* remove WIPHY_FLAG_OFFCHAN_TX, because we not support this feature */
10309     /* wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME; */
10310 #endif
10311 
10312 #if (KERNEL_VERSION(3, 2, 0) <= LINUX_VERSION_CODE)
10313     wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
10314 #endif
10315 
10316 #if defined(CONFIG_PM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
10317 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
10318      wiphy->max_sched_scan_reqs = 1;
10319 #else
10320       wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10321 #endif
10322 #ifdef CONFIG_PNO_SUPPORT
10323     wiphy->max_sched_scan_ssids = MAX_PNO_LIST_COUNT;
10324 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
10325     wiphy->max_match_sets = MAX_PNO_LIST_COUNT;
10326 #endif
10327 #endif
10328 #endif
10329 
10330 #if defined(CONFIG_PM) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
10331 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
10332     wiphy->wowlan = wowlan_stub;
10333 #else
10334     wiphy->wowlan = &wowlan_stub;
10335 #endif
10336 #endif
10337 
10338 #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10339     wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
10340 #ifndef CONFIG_TDLS_DRIVER_SETUP
10341     wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;    /* Driver handles key exchange */
10342     wiphy->flags |= NL80211_ATTR_HT_CAPABILITY;
10343 #endif /* CONFIG_TDLS_DRIVER_SETUP */
10344 #endif /* CONFIG_TDLS */
10345 
10346 #ifdef CONFIG_LPS
10347         wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
10348 #else
10349         wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
10350 #endif
10351 
10352 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10353     /* wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */
10354 #endif
10355 
10356 #ifdef CONFIG_RTW_WDS
10357     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
10358     wiphy->flags |= WIPHY_FLAG_4ADDR_AP;
10359     wiphy->flags |= WIPHY_FLAG_4ADDR_STATION;
10360     #endif
10361 #endif
10362 
10363 #ifdef CONFIG_RTW_MESH
10364     wiphy->flags |= 0
10365         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
10366         | WIPHY_FLAG_IBSS_RSN
10367         #endif
10368         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
10369         | WIPHY_FLAG_MESH_AUTH
10370         #endif
10371         ;
10372 
10373 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
10374     wiphy->features |= 0
10375         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
10376         | NL80211_FEATURE_USERSPACE_MPM
10377         #endif
10378         ;
10379 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) */
10380 #endif /* CONFIG_RTW_MESH */
10381 
10382 #if defined(CONFIG_RTW_80211K) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
10383     wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM);
10384 #endif
10385 
10386 #if (KERNEL_VERSION(3, 8, 0) <= LINUX_VERSION_CODE)
10387     wiphy->features |= NL80211_FEATURE_SAE;
10388 #endif
10389 
10390 #ifdef CONFIG_RTW_SCAN_RAND
10391     #if (KERNEL_VERSION(3, 19, 0) <= LINUX_VERSION_CODE)
10392     wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
10393     #endif
10394 #endif
10395 
10396 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10397 #ifdef CONFIG_WIFI_MONITOR
10398     /* Currently only for Monitor debugging */
10399     wiphy->flags |= WIPHY_FLAG_SUPPORTS_5_10_MHZ;
10400 #endif
10401 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) */
10402 
10403 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
10404     wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
10405 #endif
10406 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
10407     wiphy->max_num_csa_counters = MAX_CSA_CNT;
10408 #endif
10409 
10410     ret = _SUCCESS;
10411 
10412 exit:
10413     return ret;
10414 }
10415 
10416 #ifdef CONFIG_RFKILL_POLL
rtw_cfg80211_init_rfkill(struct wiphy * wiphy)10417 void rtw_cfg80211_init_rfkill(struct wiphy *wiphy)
10418 {
10419     wiphy_rfkill_set_hw_state(wiphy, 0);
10420     wiphy_rfkill_start_polling(wiphy);
10421 }
10422 
rtw_cfg80211_deinit_rfkill(struct wiphy * wiphy)10423 void rtw_cfg80211_deinit_rfkill(struct wiphy *wiphy)
10424 {
10425     wiphy_rfkill_stop_polling(wiphy);
10426 }
10427 
cfg80211_rtw_rfkill_poll(struct wiphy * wiphy)10428 static void cfg80211_rtw_rfkill_poll(struct wiphy *wiphy)
10429 {
10430     _adapter *padapter = NULL;
10431     bool blocked = _FALSE;
10432     u8 valid = 0;
10433 
10434     padapter = wiphy_to_adapter(wiphy);
10435 
10436     if (adapter_to_dvobj(padapter)->processing_dev_remove == _TRUE) {
10437         /*RTW_INFO("cfg80211_rtw_rfkill_poll: device is removed!\n");*/
10438         return;
10439     }
10440 
10441     blocked = rtw_hal_rfkill_poll(padapter, &valid);
10442     /*RTW_INFO("cfg80211_rtw_rfkill_poll: valid=%d, blocked=%d\n",
10443             valid, blocked);*/
10444 
10445     if (valid)
10446         wiphy_rfkill_set_hw_state(wiphy, blocked);
10447 }
10448 #endif
10449 
10450 #if defined(CONFIG_RTW_HOSTAPD_ACS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
10451 
10452 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
10453 #define SURVEY_INFO_TIME            SURVEY_INFO_CHANNEL_TIME
10454 #define SURVEY_INFO_TIME_BUSY        SURVEY_INFO_CHANNEL_TIME_BUSY
10455 #define SURVEY_INFO_TIME_EXT_BUSY    SURVEY_INFO_CHANNEL_TIME_EXT_BUSY
10456 #define SURVEY_INFO_TIME_RX            SURVEY_INFO_CHANNEL_TIME_RX
10457 #define SURVEY_INFO_TIME_TX            SURVEY_INFO_CHANNEL_TIME_TX
10458 #endif
10459 
10460 #ifdef CONFIG_RTW_ACS
rtw_cfg80211_set_survey_info_with_clm(PADAPTER padapter,int idx,struct survey_info * pinfo)10461 static void rtw_cfg80211_set_survey_info_with_clm(PADAPTER padapter, int idx, struct survey_info *pinfo)
10462 {
10463     s8 noise = -50;            /*channel noise in dBm. This and all following fields are optional */
10464     u64 time = SURVEY_TO;    /*amount of time in ms the radio was turn on (on the channel)*/
10465     u64 time_busy = 0;        /*amount of time the primary channel was sensed busy*/
10466     u8 chan = (u8)idx;
10467 
10468     if ((idx < 0) || (pinfo == NULL))
10469         return;
10470 
10471     pinfo->filled  = SURVEY_INFO_NOISE_DBM
10472         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
10473         | SURVEY_INFO_TIME | SURVEY_INFO_TIME_BUSY
10474         #endif
10475         ;
10476 
10477     time_busy = rtw_acs_get_clm_ratio_by_ch_idx(padapter, chan);
10478     noise = rtw_acs_get_nhm_noise_pwr_by_ch_idx(padapter, chan);
10479     /* RTW_INFO("%s: ch-idx:%d time=%llu(ms), time_busy=%llu(ms), noise=%d(dbm)\n", __func__, idx, time, time_busy, noise); */
10480 
10481 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37))
10482     #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
10483     pinfo->channel_time = time;
10484     pinfo->channel_time_busy = time_busy;
10485     #else
10486     pinfo->time = time;
10487     pinfo->time_busy = time_busy;
10488     #endif
10489 #endif
10490     pinfo->noise = noise;
10491 }
10492 #endif /* CONFIG_RTW_ACS */
10493 
rtw_hostapd_acs_dump_survey(struct wiphy * wiphy,struct net_device * netdev,int idx,struct survey_info * info)10494 static int rtw_hostapd_acs_dump_survey(struct wiphy *wiphy, struct net_device *netdev, int idx, struct survey_info *info)
10495 {
10496     PADAPTER padapter = (_adapter *)rtw_netdev_priv(netdev);
10497     struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
10498     RT_CHANNEL_INFO *pch_set = rfctl->channel_set;
10499     u8 max_chan_nums = rfctl->max_chan_nums;
10500     u32 freq = 0;
10501     u8 ret = 0;
10502     u16 channel = 0;
10503 
10504     if (!netdev || !info) {
10505         RTW_INFO("%s: invial parameters.\n", __func__);
10506         return -EINVAL;
10507     }
10508 
10509     _rtw_memset(info, 0, sizeof(struct survey_info));
10510     if (padapter->bup == _FALSE) {
10511         RTW_INFO("%s: net device is down.\n", __func__);
10512         return -EIO;
10513     }
10514 
10515     if (idx >= max_chan_nums)
10516         return -ENOENT;
10517 
10518     channel = pch_set[idx].ChannelNum;
10519     freq = rtw_ch2freq(channel);
10520     info->channel = ieee80211_get_channel(wiphy, freq);
10521     /* RTW_INFO("%s: channel %d, freq %d\n", __func__, channel, freq); */
10522 
10523     if (!info->channel)
10524         return -EINVAL;
10525 
10526     if (info->channel->flags == IEEE80211_CHAN_DISABLED)
10527         return ret;
10528 
10529 #ifdef CONFIG_RTW_ACS
10530     rtw_cfg80211_set_survey_info_with_clm(padapter, idx, info);
10531 #else
10532     RTW_ERR("%s: unknown acs operation!\n", __func__);
10533 #endif
10534 
10535     return ret;
10536 }
10537 #endif /* defined(CONFIG_RTW_HOSTAPD_ACS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) */
10538 
10539 #if (KERNEL_VERSION(4, 17, 0) <= LINUX_VERSION_CODE) \
10540     || defined(CONFIG_KERNEL_PATCH_EXTERNAL_AUTH)
cfg80211_rtw_external_auth(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_external_auth_params * params)10541 int cfg80211_rtw_external_auth(struct wiphy *wiphy, struct net_device *dev,
10542     struct cfg80211_external_auth_params *params)
10543 {
10544     PADAPTER padapter = (_adapter *)rtw_netdev_priv(dev);
10545 
10546     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(dev));
10547 
10548     rtw_cfg80211_external_auth_status(wiphy, dev,
10549         (struct rtw_external_auth_params *)params);
10550 
10551     return 0;
10552 }
10553 #endif
10554 
rtw_cfg80211_external_auth_status(struct wiphy * wiphy,struct net_device * dev,struct rtw_external_auth_params * params)10555 void rtw_cfg80211_external_auth_status(struct wiphy *wiphy, struct net_device *dev,
10556     struct rtw_external_auth_params *params)
10557 {
10558     PADAPTER padapter = (_adapter *)rtw_netdev_priv(dev);
10559     struct security_priv *psecuritypriv = &padapter->securitypriv;
10560     struct sta_priv *pstapriv = &padapter->stapriv;
10561     struct sta_info    *psta = NULL;
10562     u8 *buf = NULL;
10563     u32 len = 0;
10564     _irqL irqL;
10565 
10566     RTW_INFO(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(dev));
10567 
10568     RTW_INFO("SAE: action: %u, status: %u\n", params->action, params->status);
10569     if (params->status == WLAN_STATUS_SUCCESS) {
10570         RTW_INFO("bssid: "MAC_FMT"\n", MAC_ARG(params->bssid));
10571         RTW_INFO("SSID: [%s]\n",
10572             ((params->ssid.ssid_len == 0) ? "" : (char *)params->ssid.ssid));
10573         RTW_INFO("suite: 0x%08x\n", params->key_mgmt_suite);
10574     }
10575 
10576     psta = rtw_get_stainfo(pstapriv, params->bssid);
10577     if (psta && (params->status == WLAN_STATUS_SUCCESS)) {
10578 #ifdef CONFIG_AP_MODE
10579         /* AP mode */
10580         RTW_INFO("station match\n");
10581 
10582         psta->state &= ~WIFI_FW_AUTH_NULL;
10583         psta->state |= WIFI_FW_AUTH_SUCCESS;
10584         psta->expire_to = padapter->stapriv.assoc_to;
10585 
10586         /* ToDo: Kernel v5.1 pmkid is pointer */
10587         /* RTW_INFO_DUMP("PMKID:", params->pmkid, PMKID_LEN); */
10588         _rtw_set_pmksa(dev, params->bssid, params->pmkid);
10589 
10590         _enter_critical_bh(&psta->lock, &irqL);
10591         if ((psta->auth_len != 0) && (psta->pauth_frame != NULL)) {
10592             buf =  rtw_zmalloc(psta->auth_len);
10593             if (buf) {
10594                 _rtw_memcpy(buf, psta->pauth_frame, psta->auth_len);
10595                 len = psta->auth_len;
10596             }
10597 
10598             rtw_mfree(psta->pauth_frame, psta->auth_len);
10599             psta->pauth_frame = NULL;
10600             psta->auth_len = 0;
10601         }
10602         _exit_critical_bh(&psta->lock, &irqL);
10603 
10604         if (buf) {
10605             struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
10606             /* send the SAE auth Confirm */
10607 
10608             rtw_ps_deny(padapter, PS_DENY_MGNT_TX);
10609             if (_SUCCESS == rtw_pwr_wakeup(padapter)) {
10610                 rtw_mi_set_scan_deny(padapter, 1000);
10611                 rtw_mi_scan_abort(padapter, _TRUE);
10612 
10613                 RTW_INFO("SAE: Tx auth Confirm\n");
10614                 rtw_mgnt_tx_cmd(padapter, pmlmeext->cur_channel, 1, buf, len, 0, RTW_CMDF_DIRECTLY);
10615 
10616             }
10617             rtw_ps_deny_cancel(padapter, PS_DENY_MGNT_TX);
10618 
10619             rtw_mfree(buf, len);
10620             buf = NULL;
10621             len = 0;
10622         }
10623 #endif
10624     } else if (psta && (params->status == WLAN_STATUS_UNSPECIFIED_FAILURE)) {
10625 #ifdef CONFIG_AP_MODE
10626         rtw_cfg80211_indicate_sta_disassoc(padapter, psta->cmn.mac_addr, WLAN_STATUS_UNSPECIFIED_FAILURE);
10627 #endif
10628     } else {
10629         /* STA mode */
10630         psecuritypriv->extauth_status = params->status;
10631     }
10632 }
10633 
10634 #ifdef CONFIG_AP_MODE
check_channel(_adapter * padapter,u8 ch,u8 bw,u8 offset)10635 static int check_channel(_adapter* padapter,u8 ch, u8 bw, u8 offset) {
10636     int ret = _SUCCESS;
10637     u8 ifbmp_s = rtw_mi_get_ld_sta_ifbmp(padapter);
10638     u8 u_ch, u_bw, u_offset;
10639     struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
10640     struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
10641     struct    mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
10642 
10643     u_ch = rtw_mi_get_union_chan(padapter);
10644     u_bw = rtw_mi_get_union_bw(padapter);
10645     u_offset = rtw_mi_get_union_offset(padapter);
10646 
10647     if (rtw_chset_search_ch(rfctl->channel_set, ch) < 0
10648         || rtw_chset_is_ch_non_ocp(rfctl->channel_set, ch)) {
10649         ret = _FAIL;
10650         RTW_INFO("ch not legal %d,%d,%d\n", ch, bw, offset);
10651     } else if(pmlmeext->cur_channel == ch && pmlmeext->cur_bwmode == bw && pmlmeext->cur_ch_offset == offset) {
10652         /* channel, bandwidth, offset doesn't change */
10653         ret = _FAIL;
10654         RTW_INFO("ch same, skip switching %d,%d,%d ==> %d,%d,%d  (union:%d,%d,%d)\n",
10655          pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset, ch, bw, offset, u_ch, u_bw, u_offset);
10656     } else if((u_ch != ch || (offset != HAL_PRIME_CHNL_OFFSET_DONT_CARE && u_offset != offset)) && ifbmp_s) {
10657         ret = _FAIL;
10658         RTW_INFO("must follow STA's ch, %d,%d,%d ==> %d,%d,%d  (union:%d,%d,%d)\n",
10659          pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset, ch, bw, offset, u_ch, u_bw, u_offset);
10660     } else {
10661         RTW_INFO("channel switch.%d,%d,%d ==> %d,%d,%d  (union:%d,%d,%d)\n",
10662          pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset, ch, bw, offset, u_ch, u_bw, u_offset);
10663     }
10664     return ret;
10665 }
10666 
10667 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
cfg80211_rtw_channel_switch(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_csa_settings * params)10668 static int cfg80211_rtw_channel_switch(struct wiphy *wiphy,
10669                 struct net_device *dev,
10670                 struct cfg80211_csa_settings *params)
10671 {
10672     _adapter *padapter = NULL;
10673     struct dvobj_priv *dvobj = NULL;
10674     PNDIS_802_11_VARIABLE_IEs    pIE;
10675     u8 *ies;
10676     u8 mode = 0, count = 0, bw = CHANNEL_WIDTH_20, ch = 0, offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE, ht = 0, vht = 0, ifbmp = 0, enable = 1;
10677     u32 i, ies_len;
10678     struct rf_ctl_t *rfctl;
10679 
10680     padapter = (_adapter *)rtw_netdev_priv(dev);
10681     dvobj = adapter_to_dvobj(padapter);
10682     rfctl = dvobj_to_rfctl(dvobj);
10683 
10684     ifbmp = rtw_mi_get_ap_mesh_ifbmp(padapter);
10685 
10686     if(params && params->chandef.chan) {
10687 
10688         rtw_get_chbw_from_cfg80211_chan_def(&params->chandef, &ht, &ch, &bw, &offset);
10689 
10690         if (check_channel(padapter, ch, bw, offset) == _FAIL)
10691             return -EINVAL;
10692 
10693         if (!ch) {
10694             RTW_INFO(" => ch:%u invalid\n", ch);
10695             return -EINVAL;
10696         }
10697 
10698         /* return error code when switch process is running */
10699         if(rfctl->ap_csa_en == AP_SWITCH_CH_CSA || rfctl->ap_csa_en == STA_RX_CSA
10700             || rfctl->ap_csa_en == CSA_STA_JOINBSS)
10701             return -EINVAL;
10702 
10703         /* todo, disable vht or something */
10704         vht = ht && ch > 14 && bw >= CHANNEL_WIDTH_80;
10705         RTW_INFO(" => ch:%u,%u,%u, ht:%u, vht:%u\n", ch, bw, offset, ht, vht);
10706 
10707         if(params->beacon_csa.tail) {
10708             /* dump_ies(RTW_DBGDUMP, (char *) params->beacon_csa.tail, params->beacon_csa.tail_len); */
10709             ies = (u8 *)params->beacon_csa.tail;
10710             ies_len = params->beacon_csa.tail_len;
10711             for (i = 0; i + 1 < ies_len;) {
10712                 pIE = (PNDIS_802_11_VARIABLE_IEs)(ies + i);
10713 
10714                 switch (pIE->ElementID) {
10715                 case WLAN_EID_CHANNEL_SWITCH:
10716                     mode = *(pIE->data);
10717                     ch = *(pIE->data + 1);
10718                     count = *(pIE->data + 2);
10719                     RTW_INFO("CSA IE, mode=%d, ch=%d, count=%d\n", mode, ch, count);
10720                     break;
10721                 default:
10722                     break;
10723                 }
10724                 i += (pIE->Length + 2);
10725             }
10726 
10727             if (count == 0) {
10728                 RTW_INFO("CSA count should not be 0\n");
10729                 return -EINVAL;
10730             }
10731 
10732             if (ifbmp && count > 0) {
10733                 rfctl->ap_csa_en = AP_SWITCH_CH_CSA;
10734                 rfctl->ap_csa_ch = ch;
10735                 rfctl->ap_csa_switch_cnt = count;
10736                 rfctl->ap_csa_ch_offset = offset;
10737                 rfctl->ap_csa_ch_width = bw;
10738                 rtw_set_ap_csa_cmd(padapter);
10739             }
10740         }
10741     }
10742 
10743     return 0;
10744 }
10745 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)) */
10746 #endif /* CONFIG_AP_MODE */
10747 
10748 #ifdef CONFIG_RTL8822CS_WIFI_HDF
10749 static
10750 #endif
10751 struct cfg80211_ops rtw_cfg80211_ops = {
10752     .change_virtual_intf = cfg80211_rtw_change_iface,
10753     .add_key = cfg80211_rtw_add_key,
10754     .get_key = cfg80211_rtw_get_key,
10755     .del_key = cfg80211_rtw_del_key,
10756     .set_default_key = cfg80211_rtw_set_default_key,
10757 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30))
10758     .set_default_mgmt_key = cfg80211_rtw_set_default_mgmt_key,
10759 #endif
10760 #if defined(CONFIG_GTK_OL) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
10761     .set_rekey_data = cfg80211_rtw_set_rekey_data,
10762 #endif /*CONFIG_GTK_OL*/
10763     .get_station = cfg80211_rtw_get_station,
10764     .scan = cfg80211_rtw_scan,
10765 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
10766     .abort_scan = cfg80211_rtw_abort_scan,
10767 #endif
10768     .set_wiphy_params = cfg80211_rtw_set_wiphy_params,
10769     .connect = cfg80211_rtw_connect,
10770     .disconnect = cfg80211_rtw_disconnect,
10771     .join_ibss = cfg80211_rtw_join_ibss,
10772     .leave_ibss = cfg80211_rtw_leave_ibss,
10773 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
10774     .set_tx_power = cfg80211_rtw_set_txpower,
10775     .get_tx_power = cfg80211_rtw_get_txpower,
10776 #endif
10777     .set_power_mgmt = cfg80211_rtw_set_power_mgmt,
10778     .set_pmksa = cfg80211_rtw_set_pmksa,
10779     .del_pmksa = cfg80211_rtw_del_pmksa,
10780     .flush_pmksa = cfg80211_rtw_flush_pmksa,
10781 
10782     .add_virtual_intf = cfg80211_rtw_add_virtual_intf,
10783     .del_virtual_intf = cfg80211_rtw_del_virtual_intf,
10784 
10785 #ifdef CONFIG_AP_MODE
10786 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(COMPAT_KERNEL_RELEASE)
10787     .add_beacon = cfg80211_rtw_add_beacon,
10788     .set_beacon = cfg80211_rtw_set_beacon,
10789     .del_beacon = cfg80211_rtw_del_beacon,
10790 #else
10791     .start_ap = cfg80211_rtw_start_ap,
10792     .change_beacon = cfg80211_rtw_change_beacon,
10793     .stop_ap = cfg80211_rtw_stop_ap,
10794 #endif
10795 
10796 #if CONFIG_RTW_MACADDR_ACL && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
10797     .set_mac_acl = cfg80211_rtw_set_mac_acl,
10798 #endif
10799 
10800     .add_station = cfg80211_rtw_add_station,
10801     .del_station = cfg80211_rtw_del_station,
10802     .change_station = cfg80211_rtw_change_station,
10803     .dump_station = cfg80211_rtw_dump_station,
10804 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28))
10805     .change_bss = cfg80211_rtw_change_bss,
10806 #endif
10807 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29))
10808     .set_txq_params = cfg80211_rtw_set_txq_params,
10809 #endif
10810 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
10811     .set_channel = cfg80211_rtw_set_channel,
10812 #endif
10813     /* .auth = cfg80211_rtw_auth, */
10814     /* .assoc = cfg80211_rtw_assoc,     */
10815 #endif /* CONFIG_AP_MODE */
10816 
10817 #if defined(CONFIG_RTW_MESH) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
10818     .get_mesh_config = cfg80211_rtw_get_mesh_config,
10819     .update_mesh_config = cfg80211_rtw_update_mesh_config,
10820     .join_mesh = cfg80211_rtw_join_mesh,
10821     .leave_mesh = cfg80211_rtw_leave_mesh,
10822     .add_mpath = cfg80211_rtw_add_mpath,
10823     .del_mpath = cfg80211_rtw_del_mpath,
10824     .change_mpath = cfg80211_rtw_change_mpath,
10825     .get_mpath = cfg80211_rtw_get_mpath,
10826     .dump_mpath = cfg80211_rtw_dump_mpath,
10827     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
10828     .get_mpp = cfg80211_rtw_get_mpp,
10829     .dump_mpp = cfg80211_rtw_dump_mpp,
10830     #endif
10831 #endif
10832 
10833 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
10834     .set_monitor_channel = cfg80211_rtw_set_monitor_channel,
10835 #endif
10836 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
10837     .get_channel = cfg80211_rtw_get_channel,
10838 #endif
10839 
10840     .remain_on_channel = cfg80211_rtw_remain_on_channel,
10841     .cancel_remain_on_channel = cfg80211_rtw_cancel_remain_on_channel,
10842 
10843 #if defined(CONFIG_P2P) && defined(RTW_DEDICATED_P2P_DEVICE)
10844     .start_p2p_device = cfg80211_rtw_start_p2p_device,
10845     .stop_p2p_device = cfg80211_rtw_stop_p2p_device,
10846 #endif
10847 
10848 #ifdef CONFIG_RTW_80211R
10849     .update_ft_ies = cfg80211_rtw_update_ft_ies,
10850 #endif
10851 
10852 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) || defined(COMPAT_KERNEL_RELEASE)
10853     .mgmt_tx = cfg80211_rtw_mgmt_tx,
10854 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 8, 0))
10855     .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
10856 #else
10857     .update_mgmt_frame_registrations = cfg80211_rtw_update_mgmt_frame_register,
10858 #endif
10859 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34) && LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
10860     .action = cfg80211_rtw_mgmt_tx,
10861 #endif
10862 
10863 #if defined(CONFIG_TDLS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10864     .tdls_mgmt = cfg80211_rtw_tdls_mgmt,
10865     .tdls_oper = cfg80211_rtw_tdls_oper,
10866 #endif /* CONFIG_TDLS */
10867 
10868 #if defined(CONFIG_PNO_SUPPORT) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
10869     .sched_scan_start = cfg80211_rtw_sched_scan_start,
10870     .sched_scan_stop = cfg80211_rtw_sched_scan_stop,
10871     .suspend = cfg80211_rtw_suspend,
10872     .resume = cfg80211_rtw_resume,
10873 #endif /* CONFIG_PNO_SUPPORT */
10874 #ifdef CONFIG_RFKILL_POLL
10875     .rfkill_poll = cfg80211_rtw_rfkill_poll,
10876 #endif
10877 #if defined(CONFIG_RTW_HOSTAPD_ACS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33))
10878     .dump_survey = rtw_hostapd_acs_dump_survey,
10879 #endif
10880 #if (KERNEL_VERSION(4, 17, 0) <= LINUX_VERSION_CODE) \
10881     || defined(CONFIG_KERNEL_PATCH_EXTERNAL_AUTH)
10882     .external_auth = cfg80211_rtw_external_auth,
10883 #endif
10884 #ifdef CONFIG_AP_MODE
10885 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
10886     .channel_switch = cfg80211_rtw_channel_switch,
10887 #endif
10888 #endif /* #ifdef CONFIG_AP_MODE */
10889 };
10890 
rtw_wiphy_alloc(_adapter * padapter,struct device * dev)10891 struct wiphy *rtw_wiphy_alloc(_adapter *padapter, struct device *dev)
10892 {
10893     struct wiphy *wiphy;
10894     struct rtw_wiphy_data *wiphy_data;
10895 
10896     /* wiphy */
10897     wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wiphy_data));
10898     if (!wiphy) {
10899         RTW_ERR("Couldn't allocate wiphy device\n");
10900         goto exit;
10901     }
10902     set_wiphy_dev(wiphy, dev);
10903 
10904     /* wiphy_data */
10905     wiphy_data = rtw_wiphy_priv(wiphy);
10906     wiphy_data->dvobj = adapter_to_dvobj(padapter);
10907 #ifndef RTW_SINGLE_WIPHY
10908     wiphy_data->adapter = padapter;
10909 #endif
10910     wiphy_data->txpwr_total_lmt_mbm = UNSPECIFIED_MBM;
10911     wiphy_data->txpwr_total_target_mbm = UNSPECIFIED_MBM;
10912 
10913     rtw_regd_init(wiphy);
10914 
10915     if (rtw_cfg80211_init_wiphy(padapter, wiphy) != _SUCCESS) {
10916         rtw_wiphy_free(wiphy);
10917         wiphy = NULL;
10918         goto exit;
10919     }
10920 
10921     RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));
10922 
10923 exit:
10924     return wiphy;
10925 }
10926 
rtw_wiphy_free(struct wiphy * wiphy)10927 void rtw_wiphy_free(struct wiphy *wiphy)
10928 {
10929     if (!wiphy)
10930         return;
10931 
10932     RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));
10933 
10934     rtw_regd_deinit(wiphy);
10935 
10936     if (wiphy->bands[NL80211_BAND_2GHZ]) {
10937         rtw_spt_band_free(wiphy->bands[NL80211_BAND_2GHZ]);
10938         wiphy->bands[NL80211_BAND_2GHZ] = NULL;
10939     }
10940     if (wiphy->bands[NL80211_BAND_5GHZ]) {
10941         rtw_spt_band_free(wiphy->bands[NL80211_BAND_5GHZ]);
10942         wiphy->bands[NL80211_BAND_5GHZ] = NULL;
10943     }
10944 
10945     wiphy_free(wiphy);
10946 }
10947 
10948 #ifdef CONFIG_RTL8822CS_WIFI_HDF
10949 struct wiphy *g_wiphy = NULL;
10950 
oal_wiphy_register(struct wiphy * wiphy)10951 int oal_wiphy_register(struct wiphy *wiphy)
10952 {
10953     g_wiphy = wiphy;
10954     return 0;
10955 }
10956 
oal_wiphy_get(void)10957 struct wiphy *oal_wiphy_get(void)
10958 {
10959     return g_wiphy;
10960 }
10961 #endif
10962 
rtw_wiphy_register(struct wiphy * wiphy)10963 int rtw_wiphy_register(struct wiphy *wiphy)
10964 {
10965     struct get_chplan_resp *chplan;
10966     int ret;
10967 
10968     RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));
10969 
10970 #if ( (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) \
10971      || defined(RTW_VENDOR_EXT_SUPPORT) )
10972     rtw_cfgvendor_attach(wiphy);
10973 #endif
10974 
10975     ret = wiphy_register(wiphy);
10976     if (ret != 0) {
10977         RTW_INFO(FUNC_WIPHY_FMT" wiphy_register() return %d\n", FUNC_WIPHY_ARG(wiphy), ret);
10978         goto exit;
10979     }
10980 
10981     rtw_chset_hook_os_channels(dvobj_to_rfctl(wiphy_to_dvobj(wiphy)));
10982 
10983     if (rtw_get_chplan_cmd(wiphy_to_adapter(wiphy), RTW_CMDF_DIRECTLY, &chplan) == _SUCCESS)
10984         rtw_regd_change_complete_sync(wiphy, chplan, 1);
10985     else
10986         rtw_warn_on(1);
10987 
10988 exit:
10989     return ret;
10990 }
10991 
rtw_wiphy_unregister(struct wiphy * wiphy)10992 void rtw_wiphy_unregister(struct wiphy *wiphy)
10993 {
10994     RTW_INFO(FUNC_WIPHY_FMT"\n", FUNC_WIPHY_ARG(wiphy));
10995 
10996 #if ( (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) \
10997      || defined(RTW_VENDOR_EXT_SUPPORT) )
10998     rtw_cfgvendor_detach(wiphy);
10999 #endif
11000 
11001     #if defined(RTW_DEDICATED_P2P_DEVICE)
11002     rtw_pd_iface_free(wiphy);
11003     #endif
11004 
11005     return wiphy_unregister(wiphy);
11006 }
11007 
rtw_wdev_alloc(_adapter * padapter,struct wiphy * wiphy)11008 int rtw_wdev_alloc(_adapter *padapter, struct wiphy *wiphy)
11009 {
11010     int ret = 0;
11011     struct net_device *pnetdev = padapter->pnetdev;
11012     struct wireless_dev *wdev;
11013     struct rtw_wdev_priv *pwdev_priv;
11014 
11015     RTW_INFO("%s(padapter=%p)\n", __func__, padapter);
11016 
11017     /*  wdev */
11018     wdev = (struct wireless_dev *)rtw_zmalloc(sizeof(struct wireless_dev));
11019     if (!wdev) {
11020         RTW_INFO("Couldn't allocate wireless device\n");
11021         ret = -ENOMEM;
11022         goto exit;
11023     }
11024     wdev->wiphy = wiphy;
11025     wdev->netdev = pnetdev;
11026     wdev->iftype = NL80211_IFTYPE_STATION;
11027     padapter->rtw_wdev = wdev;
11028     pnetdev->ieee80211_ptr = wdev;
11029 
11030 #ifdef CONFIG_RTL8822CS_WIFI_HDF
11031     oal_wiphy_register(wiphy);
11032 
11033     /* Need Init? */
11034     INIT_LIST_HEAD(&wdev->event_list);
11035     INIT_LIST_HEAD(&wdev->list);
11036     INIT_LIST_HEAD(&wdev->pmsr_list);
11037     INIT_LIST_HEAD(&wdev->mgmt_registrations);
11038 #endif
11039 
11040     /* init pwdev_priv */
11041     pwdev_priv = adapter_wdev_data(padapter);
11042     pwdev_priv->rtw_wdev = wdev;
11043     pwdev_priv->pmon_ndev = NULL;
11044     pwdev_priv->ifname_mon[0] = '\0';
11045     pwdev_priv->padapter = padapter;
11046     pwdev_priv->scan_request = NULL;
11047     _rtw_spinlock_init(&pwdev_priv->scan_req_lock);
11048     pwdev_priv->connect_req = NULL;
11049     _rtw_spinlock_init(&pwdev_priv->connect_req_lock);
11050 
11051     pwdev_priv->p2p_enabled = _FALSE;
11052     pwdev_priv->probe_resp_ie_update_time = rtw_get_current_time();
11053     pwdev_priv->provdisc_req_issued = _FALSE;
11054     rtw_wdev_invit_info_init(&pwdev_priv->invit_info);
11055     rtw_wdev_nego_info_init(&pwdev_priv->nego_info);
11056 
11057     pwdev_priv->bandroid_scan = _FALSE;
11058 
11059     _rtw_mutex_init(&pwdev_priv->roch_mutex);
11060 
11061 #ifdef CONFIG_CONCURRENT_MODE
11062     ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
11063 #endif
11064 
11065 #ifdef CONFIG_RTW_CFGVENDOR_RSSIMONITOR
11066         pwdev_priv->rssi_monitor_enable = 0;
11067         pwdev_priv->rssi_monitor_max = 0;
11068         pwdev_priv->rssi_monitor_min = 0;
11069 #endif
11070 
11071 
11072 exit:
11073     return ret;
11074 }
11075 
rtw_wdev_free(struct wireless_dev * wdev)11076 void rtw_wdev_free(struct wireless_dev *wdev)
11077 {
11078     if (!wdev)
11079         return;
11080 
11081     RTW_INFO("%s(wdev=%p)\n", __func__, wdev);
11082 
11083     if (wdev_to_ndev(wdev)) {
11084         _adapter *adapter = (_adapter *)rtw_netdev_priv(wdev_to_ndev(wdev));
11085         struct rtw_wdev_priv *wdev_priv = adapter_wdev_data(adapter);
11086         _irqL irqL;
11087 
11088         _rtw_spinlock_free(&wdev_priv->scan_req_lock);
11089 
11090         _enter_critical_bh(&wdev_priv->connect_req_lock, &irqL);
11091         rtw_wdev_free_connect_req(wdev_priv);
11092         _exit_critical_bh(&wdev_priv->connect_req_lock, &irqL);
11093         _rtw_spinlock_free(&wdev_priv->connect_req_lock);
11094 
11095         _rtw_mutex_free(&wdev_priv->roch_mutex);
11096     }
11097 
11098     rtw_mfree((u8 *)wdev, sizeof(struct wireless_dev));
11099 }
11100 
rtw_wdev_unregister(struct wireless_dev * wdev)11101 void rtw_wdev_unregister(struct wireless_dev *wdev)
11102 {
11103     struct net_device *ndev;
11104     _adapter *adapter;
11105     struct rtw_wdev_priv *pwdev_priv;
11106 
11107     if (!wdev)
11108         return;
11109 
11110     RTW_INFO("%s(wdev=%p)\n", __func__, wdev);
11111 
11112     ndev = wdev_to_ndev(wdev);
11113     if (!ndev)
11114         return;
11115 
11116     adapter = (_adapter *)rtw_netdev_priv(ndev);
11117     pwdev_priv = adapter_wdev_data(adapter);
11118 
11119     rtw_cfg80211_indicate_scan_done(adapter, _TRUE);
11120 
11121     #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)) || defined(COMPAT_KERNEL_RELEASE)
11122     if (wdev->current_bss) {
11123         RTW_INFO(FUNC_ADPT_FMT" clear current_bss by cfg80211_disconnected\n", FUNC_ADPT_ARG(adapter));
11124         rtw_cfg80211_indicate_disconnect(adapter, 0, 1);
11125     }
11126     #endif
11127 
11128     if (pwdev_priv->pmon_ndev) {
11129         RTW_INFO("%s, unregister monitor interface\n", __func__);
11130         unregister_netdev(pwdev_priv->pmon_ndev);
11131     }
11132 }
11133 
rtw_cfg80211_ndev_res_alloc(_adapter * adapter)11134 int rtw_cfg80211_ndev_res_alloc(_adapter *adapter)
11135 {
11136     int ret = _FAIL;
11137 
11138 #if !defined(RTW_SINGLE_WIPHY)
11139     struct wiphy *wiphy;
11140     struct device *dev = dvobj_to_dev(adapter_to_dvobj(adapter));
11141 
11142     wiphy = rtw_wiphy_alloc(adapter, dev);
11143     if (wiphy == NULL)
11144         goto exit;
11145 
11146     adapter->wiphy = wiphy;
11147 #endif
11148 
11149     if (rtw_wdev_alloc(adapter, adapter_to_wiphy(adapter)) == 0)
11150         ret = _SUCCESS;
11151 
11152 #if !defined(RTW_SINGLE_WIPHY)
11153     if (ret != _SUCCESS) {
11154         rtw_wiphy_free(wiphy);
11155         adapter->wiphy = NULL;
11156     }
11157 
11158 exit:
11159 #endif
11160 
11161     return ret;
11162 }
11163 
rtw_cfg80211_ndev_res_free(_adapter * adapter)11164 void rtw_cfg80211_ndev_res_free(_adapter *adapter)
11165 {
11166     rtw_wdev_free(adapter->rtw_wdev);
11167     adapter->rtw_wdev = NULL;
11168 #if !defined(RTW_SINGLE_WIPHY)
11169     rtw_wiphy_free(adapter_to_wiphy(adapter));
11170     adapter->wiphy = NULL;
11171 #endif
11172 }
11173 
11174 
rtw_cfg80211_ndev_res_register(_adapter * adapter)11175 int rtw_cfg80211_ndev_res_register(_adapter *adapter)
11176 {
11177 #if !defined(RTW_SINGLE_WIPHY)
11178     int ret = _FAIL;
11179 
11180     if (rtw_wiphy_register(adapter_to_wiphy(adapter)) < 0) {
11181         RTW_INFO("%s rtw_wiphy_register fail for if%d\n", __func__, (adapter->iface_id + 1));
11182         goto exit;
11183     }
11184 
11185     #ifdef CONFIG_RFKILL_POLL
11186     rtw_cfg80211_init_rfkill(adapter_to_wiphy(adapter));
11187     #endif
11188 
11189     ret = _SUCCESS;
11190 
11191 exit:
11192     return ret;
11193 #else
11194     return _SUCCESS;
11195 #endif
11196 }
11197 
rtw_cfg80211_ndev_res_unregister(_adapter * adapter)11198 void rtw_cfg80211_ndev_res_unregister(_adapter *adapter)
11199 {
11200     rtw_wdev_unregister(adapter->rtw_wdev);
11201 }
11202 
rtw_cfg80211_dev_res_alloc(struct dvobj_priv * dvobj)11203 int rtw_cfg80211_dev_res_alloc(struct dvobj_priv *dvobj)
11204 {
11205     int ret = _FAIL;
11206 
11207 #if defined(RTW_SINGLE_WIPHY)
11208     struct wiphy *wiphy;
11209     struct device *dev = dvobj_to_dev(dvobj);
11210 
11211     wiphy = rtw_wiphy_alloc(dvobj_get_primary_adapter(dvobj), dev);
11212     if (wiphy == NULL)
11213         return ret;
11214 
11215     dvobj->wiphy = wiphy;
11216 #endif
11217 
11218     ret = _SUCCESS;
11219     return ret;
11220 }
11221 
rtw_cfg80211_dev_res_free(struct dvobj_priv * dvobj)11222 void rtw_cfg80211_dev_res_free(struct dvobj_priv *dvobj)
11223 {
11224 #if defined(RTW_SINGLE_WIPHY)
11225     rtw_wiphy_free(dvobj_to_wiphy(dvobj));
11226     dvobj->wiphy = NULL;
11227 #endif
11228 }
11229 
rtw_cfg80211_dev_res_register(struct dvobj_priv * dvobj)11230 int rtw_cfg80211_dev_res_register(struct dvobj_priv *dvobj)
11231 {
11232     int ret = _FAIL;
11233 
11234 #if defined(RTW_SINGLE_WIPHY)
11235     if (rtw_wiphy_register(dvobj_to_wiphy(dvobj)) != 0)
11236         return ret;
11237 
11238 #ifdef CONFIG_RFKILL_POLL
11239     rtw_cfg80211_init_rfkill(dvobj_to_wiphy(dvobj));
11240 #endif
11241 #endif
11242 
11243     ret = _SUCCESS;
11244 
11245     return ret;
11246 }
11247 
rtw_cfg80211_dev_res_unregister(struct dvobj_priv * dvobj)11248 void rtw_cfg80211_dev_res_unregister(struct dvobj_priv *dvobj)
11249 {
11250 #ifndef CONFIG_RTL8822CS_WIFI_HDF
11251 #if defined(RTW_SINGLE_WIPHY)
11252 #ifdef CONFIG_RFKILL_POLL
11253     rtw_cfg80211_deinit_rfkill(dvobj_to_wiphy(dvobj));
11254 #endif
11255     rtw_wiphy_unregister(dvobj_to_wiphy(dvobj));
11256 #endif
11257 #endif
11258 }
11259 
rtw_cfg80211_dev_get_total_txpwr_lmt_mbm(struct dvobj_priv * dvobj)11260 s16 rtw_cfg80211_dev_get_total_txpwr_lmt_mbm(struct dvobj_priv *dvobj)
11261 {
11262     struct rtw_wiphy_data *wiphy_data;
11263     s16 mbm = UNSPECIFIED_MBM;
11264 
11265     /* TODO: input radio index to choose corresponding wiphy(s) */
11266 
11267 #if defined(RTW_SINGLE_WIPHY)
11268     wiphy_data = rtw_wiphy_priv(dvobj_to_wiphy(dvobj));
11269     mbm = wiphy_data->txpwr_total_lmt_mbm;
11270 #else
11271     struct wiphy *wiphy;
11272     int i;
11273 
11274     for (i = 0; i < dvobj->iface_nums; i++) {
11275         if (!dvobj->padapters[i])
11276             continue;
11277         wiphy = dvobj->padapters[i]->wiphy;
11278         if (!wiphy)
11279             continue;
11280         wiphy_data = rtw_wiphy_priv(wiphy);
11281         if (wiphy_data->txpwr_total_lmt_mbm == UNSPECIFIED_MBM)
11282             continue;
11283         if (mbm > wiphy_data->txpwr_total_lmt_mbm)
11284             mbm = wiphy_data->txpwr_total_lmt_mbm;
11285     }
11286 #endif
11287 
11288     return mbm;
11289 }
11290 
rtw_cfg80211_dev_get_total_txpwr_target_mbm(struct dvobj_priv * dvobj)11291 s16 rtw_cfg80211_dev_get_total_txpwr_target_mbm(struct dvobj_priv *dvobj)
11292 {
11293     struct rtw_wiphy_data *wiphy_data;
11294     s16 mbm = UNSPECIFIED_MBM;
11295 
11296     /* TODO: input radio index to choose corresponding wiphy(s) */
11297 
11298 #if defined(RTW_SINGLE_WIPHY)
11299     wiphy_data = rtw_wiphy_priv(dvobj_to_wiphy(dvobj));
11300     mbm = wiphy_data->txpwr_total_target_mbm;
11301 #else
11302     struct wiphy *wiphy;
11303     int i;
11304 
11305     for (i = 0; i < dvobj->iface_nums; i++) {
11306         if (!dvobj->padapters[i])
11307             continue;
11308         wiphy = dvobj->padapters[i]->wiphy;
11309         if (!wiphy)
11310             continue;
11311         wiphy_data = rtw_wiphy_priv(wiphy);
11312         if (wiphy_data->txpwr_total_target_mbm == UNSPECIFIED_MBM)
11313             continue;
11314         if (mbm > wiphy_data->txpwr_total_target_mbm)
11315             mbm = wiphy_data->txpwr_total_target_mbm;
11316     }
11317 #endif
11318 
11319     return mbm;
11320 }
11321 #endif /* CONFIG_IOCTL_CFG80211 */
11322