aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2014-03-28 22:37:40 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-04-05 17:51:23 -0400
commitb1925ad84625302fac456d8671b2acafcabf57f5 (patch)
treedc29690f13d2220eeb2262874b43e8a039a58168
parentf7c92d2cc2beb3367f244480300eaecdd9502932 (diff)
staging: r8723au: Add source files for new driver - part 3
The Realtek USB device RTL8723AU is found in Lenovo Yoga 13 tablets. A driver for it has been available in a GitHub repo for several months. This commit contains the third part of source files. The source is arbitrarily split to avoid E-mail files that are too large. Jes Sorensen at RedHat has made many improvements to the vendor code, and he has been doing the testing. I do not have access to this device. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Cc: Jes Sorensen <Jes.Sorensen@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c4501
-rw-r--r--drivers/staging/rtl8723au/os_dep/mlme_linux.c187
-rw-r--r--drivers/staging/rtl8723au/os_dep/os_intfs.c970
-rw-r--r--drivers/staging/rtl8723au/os_dep/osdep_service.c429
-rw-r--r--drivers/staging/rtl8723au/os_dep/recv_linux.c225
-rw-r--r--drivers/staging/rtl8723au/os_dep/usb_intf.c836
-rw-r--r--drivers/staging/rtl8723au/os_dep/usb_ops_linux.c283
-rw-r--r--drivers/staging/rtl8723au/os_dep/xmit_linux.c195
8 files changed, 7626 insertions, 0 deletions
diff --git a/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
new file mode 100644
index 000000000000..1c99616f51ac
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
@@ -0,0 +1,4501 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _IOCTL_CFG80211_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <rtw_ioctl_set.h>
20#include <xmit_osdep.h>
21
22#include "ioctl_cfg80211.h"
23#include <linux/version.h>
24
25#define RTW_MAX_MGMT_TX_CNT 8
26
27#define RTW_MAX_REMAIN_ON_CHANNEL_DURATION 65535 /* ms */
28#define RTW_MAX_NUM_PMKIDS 4
29
30#define RTW_CH_MAX_2G_CHANNEL 14 /* Max channel in 2G band */
31
32static const u32 rtw_cipher_suites[] = {
33 WLAN_CIPHER_SUITE_WEP40,
34 WLAN_CIPHER_SUITE_WEP104,
35 WLAN_CIPHER_SUITE_TKIP,
36 WLAN_CIPHER_SUITE_CCMP,
37};
38
39#define RATETAB_ENT(_rate, _rateid, _flags) { \
40 .bitrate = (_rate), \
41 .hw_value = (_rateid), \
42 .flags = (_flags), \
43}
44
45#define CHAN2G(_channel, _freq, _flags) { \
46 .band = IEEE80211_BAND_2GHZ, \
47 .center_freq = (_freq), \
48 .hw_value = (_channel), \
49 .flags = (_flags), \
50 .max_antenna_gain = 0, \
51 .max_power = 30, \
52}
53
54#define CHAN5G(_channel, _flags) { \
55 .band = IEEE80211_BAND_5GHZ, \
56 .center_freq = 5000 + (5 * (_channel)), \
57 .hw_value = (_channel), \
58 .flags = (_flags), \
59 .max_antenna_gain = 0, \
60 .max_power = 30, \
61}
62
63static struct ieee80211_rate rtw_rates[] = {
64 RATETAB_ENT(10, 0x1, 0),
65 RATETAB_ENT(20, 0x2, 0),
66 RATETAB_ENT(55, 0x4, 0),
67 RATETAB_ENT(110, 0x8, 0),
68 RATETAB_ENT(60, 0x10, 0),
69 RATETAB_ENT(90, 0x20, 0),
70 RATETAB_ENT(120, 0x40, 0),
71 RATETAB_ENT(180, 0x80, 0),
72 RATETAB_ENT(240, 0x100, 0),
73 RATETAB_ENT(360, 0x200, 0),
74 RATETAB_ENT(480, 0x400, 0),
75 RATETAB_ENT(540, 0x800, 0),
76};
77
78#define rtw_a_rates (rtw_rates + 4)
79#define RTW_A_RATES_NUM 8
80#define rtw_g_rates (rtw_rates + 0)
81#define RTW_G_RATES_NUM 12
82
83#define RTW_2G_CHANNELS_NUM 14
84#define RTW_5G_CHANNELS_NUM 37
85
86static struct ieee80211_channel rtw_2ghz_channels[] = {
87 CHAN2G(1, 2412, 0),
88 CHAN2G(2, 2417, 0),
89 CHAN2G(3, 2422, 0),
90 CHAN2G(4, 2427, 0),
91 CHAN2G(5, 2432, 0),
92 CHAN2G(6, 2437, 0),
93 CHAN2G(7, 2442, 0),
94 CHAN2G(8, 2447, 0),
95 CHAN2G(9, 2452, 0),
96 CHAN2G(10, 2457, 0),
97 CHAN2G(11, 2462, 0),
98 CHAN2G(12, 2467, 0),
99 CHAN2G(13, 2472, 0),
100 CHAN2G(14, 2484, 0),
101};
102
103static struct ieee80211_channel rtw_5ghz_a_channels[] = {
104 CHAN5G(34, 0), CHAN5G(36, 0),
105 CHAN5G(38, 0), CHAN5G(40, 0),
106 CHAN5G(42, 0), CHAN5G(44, 0),
107 CHAN5G(46, 0), CHAN5G(48, 0),
108 CHAN5G(52, 0), CHAN5G(56, 0),
109 CHAN5G(60, 0), CHAN5G(64, 0),
110 CHAN5G(100, 0), CHAN5G(104, 0),
111 CHAN5G(108, 0), CHAN5G(112, 0),
112 CHAN5G(116, 0), CHAN5G(120, 0),
113 CHAN5G(124, 0), CHAN5G(128, 0),
114 CHAN5G(132, 0), CHAN5G(136, 0),
115 CHAN5G(140, 0), CHAN5G(149, 0),
116 CHAN5G(153, 0), CHAN5G(157, 0),
117 CHAN5G(161, 0), CHAN5G(165, 0),
118 CHAN5G(184, 0), CHAN5G(188, 0),
119 CHAN5G(192, 0), CHAN5G(196, 0),
120 CHAN5G(200, 0), CHAN5G(204, 0),
121 CHAN5G(208, 0), CHAN5G(212, 0),
122 CHAN5G(216, 0),
123};
124
125static void rtw_2g_channels_init(struct ieee80211_channel *channels)
126{
127 memcpy((void *)channels, (void *)rtw_2ghz_channels,
128 sizeof(struct ieee80211_channel) * RTW_2G_CHANNELS_NUM);
129}
130
131static void rtw_5g_channels_init(struct ieee80211_channel *channels)
132{
133 memcpy((void *)channels, (void *)rtw_5ghz_a_channels,
134 sizeof(struct ieee80211_channel) * RTW_5G_CHANNELS_NUM);
135}
136
137static void rtw_2g_rates_init(struct ieee80211_rate *rates)
138{
139 memcpy(rates, rtw_g_rates,
140 sizeof(struct ieee80211_rate) * RTW_G_RATES_NUM);
141}
142
143static void rtw_5g_rates_init(struct ieee80211_rate *rates)
144{
145 memcpy(rates, rtw_a_rates,
146 sizeof(struct ieee80211_rate) * RTW_A_RATES_NUM);
147}
148
149static struct ieee80211_supported_band *
150rtw_spt_band_alloc(enum ieee80211_band band)
151{
152 struct ieee80211_supported_band *spt_band = NULL;
153 int n_channels, n_bitrates;
154
155 if (band == IEEE80211_BAND_2GHZ) {
156 n_channels = RTW_2G_CHANNELS_NUM;
157 n_bitrates = RTW_G_RATES_NUM;
158 } else if (band == IEEE80211_BAND_5GHZ) {
159 n_channels = RTW_5G_CHANNELS_NUM;
160 n_bitrates = RTW_A_RATES_NUM;
161 } else {
162 goto exit;
163 }
164 spt_band = kzalloc(sizeof(struct ieee80211_supported_band) +
165 sizeof(struct ieee80211_channel) * n_channels +
166 sizeof(struct ieee80211_rate) * n_bitrates,
167 GFP_KERNEL);
168 if (!spt_band)
169 goto exit;
170
171 spt_band->channels =
172 (struct ieee80211_channel *)(((u8 *) spt_band) +
173 sizeof(struct
174 ieee80211_supported_band));
175 spt_band->bitrates =
176 (struct ieee80211_rate *)(((u8 *) spt_band->channels) +
177 sizeof(struct ieee80211_channel) *
178 n_channels);
179 spt_band->band = band;
180 spt_band->n_channels = n_channels;
181 spt_band->n_bitrates = n_bitrates;
182
183 if (band == IEEE80211_BAND_2GHZ) {
184 rtw_2g_channels_init(spt_band->channels);
185 rtw_2g_rates_init(spt_band->bitrates);
186 } else if (band == IEEE80211_BAND_5GHZ) {
187 rtw_5g_channels_init(spt_band->channels);
188 rtw_5g_rates_init(spt_band->bitrates);
189 }
190
191 /* spt_band.ht_cap */
192
193exit:
194 return spt_band;
195}
196
197static const struct ieee80211_txrx_stypes
198rtw_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
199 [NL80211_IFTYPE_ADHOC] = {
200 .tx = 0xffff,
201 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
202 },
203 [NL80211_IFTYPE_STATION] = {
204 .tx = 0xffff,
205 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
206 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
207 },
208 [NL80211_IFTYPE_AP] = {
209 .tx = 0xffff,
210 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
211 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
212 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
213 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
214 BIT(IEEE80211_STYPE_AUTH >> 4) |
215 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
216 BIT(IEEE80211_STYPE_ACTION >> 4)
217 },
218 [NL80211_IFTYPE_AP_VLAN] = {
219 /* copy AP */
220 .tx = 0xffff,
221 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
222 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
223 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
224 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
225 BIT(IEEE80211_STYPE_AUTH >> 4) |
226 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
227 BIT(IEEE80211_STYPE_ACTION >> 4)
228 },
229 [NL80211_IFTYPE_P2P_CLIENT] = {
230 .tx = 0xffff,
231 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
232 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
233 },
234 [NL80211_IFTYPE_P2P_GO] = {
235 .tx = 0xffff,
236 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
237 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
238 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
239 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
240 BIT(IEEE80211_STYPE_AUTH >> 4) |
241 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
242 BIT(IEEE80211_STYPE_ACTION >> 4)
243 },
244};
245
246#define MAX_BSSINFO_LEN 1000
247static int rtw_cfg80211_inform_bss(struct rtw_adapter *padapter,
248 struct wlan_network *pnetwork)
249{
250 int ret = 0;
251 struct ieee80211_channel *notify_channel;
252 struct cfg80211_bss *bss;
253 /* struct ieee80211_supported_band *band; */
254 u16 channel;
255 u32 freq;
256 u64 notify_timestamp;
257 u16 notify_capability;
258 u16 notify_interval;
259 u8 *notify_ie;
260 size_t notify_ielen;
261 s32 notify_signal;
262 u8 buf[MAX_BSSINFO_LEN], *pbuf;
263 size_t len, bssinf_len = 0;
264 struct ieee80211_hdr *pwlanhdr;
265 unsigned short *fctrl;
266 u8 bc_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
267
268 struct wireless_dev *wdev = padapter->rtw_wdev;
269 struct wiphy *wiphy = wdev->wiphy;
270 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
271
272 /* DBG_8723A("%s\n", __func__); */
273
274 bssinf_len =
275 pnetwork->network.IELength + sizeof(struct ieee80211_hdr_3addr);
276 if (bssinf_len > MAX_BSSINFO_LEN) {
277 DBG_8723A("%s IE Length too long > %d byte\n", __func__,
278 MAX_BSSINFO_LEN);
279 goto exit;
280 }
281
282 channel = pnetwork->network.Configuration.DSConfig;
283 if (channel <= RTW_CH_MAX_2G_CHANNEL)
284 freq = ieee80211_channel_to_frequency(channel,
285 IEEE80211_BAND_2GHZ);
286 else
287 freq = ieee80211_channel_to_frequency(channel,
288 IEEE80211_BAND_5GHZ);
289
290 notify_channel = ieee80211_get_channel(wiphy, freq);
291
292 /* rtw_get_timestampe_from_ie23a() */
293 notify_timestamp = jiffies_to_msecs(jiffies) * 1000; /* uSec */
294
295 notify_interval =
296 le16_to_cpu(*(u16 *)
297 rtw_get_beacon_interval23a_from_ie(pnetwork->network.IEs));
298 notify_capability =
299 le16_to_cpu(*(u16 *)
300 rtw_get_capability23a_from_ie(pnetwork->network.IEs));
301
302 notify_ie = pnetwork->network.IEs + _FIXED_IE_LENGTH_;
303 notify_ielen = pnetwork->network.IELength - _FIXED_IE_LENGTH_;
304
305 /* We've set wiphy's signal_type as CFG80211_SIGNAL_TYPE_MBM:
306 * signal strength in mBm (100*dBm)
307 */
308 if (check_fwstate(pmlmepriv, _FW_LINKED) &&
309 is_same_network23a(&pmlmepriv->cur_network.network,
310 &pnetwork->network)) {
311 notify_signal = 100 * translate_percentage_to_dbm(padapter->recvpriv.signal_strength); /* dbm */
312 } else {
313 notify_signal = 100 * translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength); /* dbm */
314 }
315 pbuf = buf;
316
317 pwlanhdr = (struct ieee80211_hdr *)pbuf;
318 fctrl = &pwlanhdr->frame_control;
319 *(fctrl) = 0;
320
321 SetSeqNum(pwlanhdr, 0);
322
323 if (pnetwork->network.reserved == 1) { /* WIFI_BEACON */
324 memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
325 SetFrameSubType(pbuf, WIFI_BEACON);
326 } else {
327 memcpy(pwlanhdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN);
328 SetFrameSubType(pbuf, WIFI_PROBERSP);
329 }
330
331 memcpy(pwlanhdr->addr2, pnetwork->network.MacAddress, ETH_ALEN);
332 memcpy(pwlanhdr->addr3, pnetwork->network.MacAddress, ETH_ALEN);
333
334 pbuf += sizeof(struct ieee80211_hdr_3addr);
335 len = sizeof(struct ieee80211_hdr_3addr);
336
337 memcpy(pbuf, pnetwork->network.IEs, pnetwork->network.IELength);
338 len += pnetwork->network.IELength;
339
340 bss = cfg80211_inform_bss_frame(wiphy, notify_channel,
341 (struct ieee80211_mgmt *)buf, len,
342 notify_signal, GFP_ATOMIC);
343
344 if (unlikely(!bss)) {
345 DBG_8723A("rtw_cfg80211_inform_bss error\n");
346 return -EINVAL;
347 }
348
349 cfg80211_put_bss(wiphy, bss);
350
351exit:
352 return ret;
353}
354
355void rtw_cfg80211_indicate_connect(struct rtw_adapter *padapter)
356{
357 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
358 struct wlan_network *cur_network = &pmlmepriv->cur_network;
359 struct wireless_dev *pwdev = padapter->rtw_wdev;
360#ifdef CONFIG_8723AU_P2P
361 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
362#endif
363
364 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
365
366 if (pwdev->iftype != NL80211_IFTYPE_STATION &&
367 pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
368 return;
369
370 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
371 return;
372
373#ifdef CONFIG_8723AU_P2P
374 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
375 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
376 rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
377 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
378 DBG_8723A("%s, role =%d, p2p_state =%d, pre_p2p_state =%d\n",
379 __func__, rtw_p2p_role(pwdinfo),
380 rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
381 }
382#endif /* CONFIG_8723AU_P2P */
383
384 if (rtw_to_roaming(padapter) > 0) {
385 struct wiphy *wiphy = pwdev->wiphy;
386 struct ieee80211_channel *notify_channel;
387 u32 freq;
388 u16 channel = cur_network->network.Configuration.DSConfig;
389
390 if (channel <= RTW_CH_MAX_2G_CHANNEL)
391 freq =
392 ieee80211_channel_to_frequency(channel,
393 IEEE80211_BAND_2GHZ);
394 else
395 freq =
396 ieee80211_channel_to_frequency(channel,
397 IEEE80211_BAND_5GHZ);
398
399 notify_channel = ieee80211_get_channel(wiphy, freq);
400
401 DBG_8723A("%s call cfg80211_roamed\n", __func__);
402 cfg80211_roamed(padapter->pnetdev, notify_channel,
403 cur_network->network.MacAddress,
404 pmlmepriv->assoc_req +
405 sizeof(struct ieee80211_hdr_3addr) + 2,
406 pmlmepriv->assoc_req_len -
407 sizeof(struct ieee80211_hdr_3addr) - 2,
408 pmlmepriv->assoc_rsp +
409 sizeof(struct ieee80211_hdr_3addr) + 6,
410 pmlmepriv->assoc_rsp_len -
411 sizeof(struct ieee80211_hdr_3addr) - 6,
412 GFP_ATOMIC);
413 } else {
414 cfg80211_connect_result(padapter->pnetdev,
415 cur_network->network.MacAddress,
416 pmlmepriv->assoc_req +
417 sizeof(struct ieee80211_hdr_3addr) + 2,
418 pmlmepriv->assoc_req_len -
419 sizeof(struct ieee80211_hdr_3addr) - 2,
420 pmlmepriv->assoc_rsp +
421 sizeof(struct ieee80211_hdr_3addr) + 6,
422 pmlmepriv->assoc_rsp_len -
423 sizeof(struct ieee80211_hdr_3addr) - 6,
424 WLAN_STATUS_SUCCESS, GFP_ATOMIC);
425 }
426}
427
428void rtw_cfg80211_indicate_disconnect(struct rtw_adapter *padapter)
429{
430 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
431 struct wireless_dev *pwdev = padapter->rtw_wdev;
432#ifdef CONFIG_8723AU_P2P
433 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
434#endif
435
436 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
437
438 if (pwdev->iftype != NL80211_IFTYPE_STATION &&
439 pwdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
440 return;
441
442 if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
443 return;
444
445#ifdef CONFIG_8723AU_P2P
446 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
447 del_timer_sync(&pwdinfo->find_phase_timer);
448 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
449 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
450
451 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
452 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
453
454 DBG_8723A("%s, role =%d, p2p_state =%d, pre_p2p_state =%d\n",
455 __func__, rtw_p2p_role(pwdinfo),
456 rtw_p2p_state(pwdinfo), rtw_p2p_pre_state(pwdinfo));
457 }
458#endif /* CONFIG_8723AU_P2P */
459
460 if (!padapter->mlmepriv.not_indic_disco) {
461 if (check_fwstate(&padapter->mlmepriv, WIFI_UNDER_LINKING)) {
462 cfg80211_connect_result(padapter->pnetdev, NULL, NULL,
463 0, NULL, 0,
464 WLAN_STATUS_UNSPECIFIED_FAILURE,
465 GFP_ATOMIC);
466 } else {
467 cfg80211_disconnected(padapter->pnetdev, 0, NULL,
468 0, GFP_ATOMIC);
469 }
470 }
471}
472
473#ifdef CONFIG_8723AU_AP_MODE
474static u8 set_pairwise_key(struct rtw_adapter *padapter, struct sta_info *psta)
475{
476 struct cmd_obj *ph2c;
477 struct set_stakey_parm *psetstakey_para;
478 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
479 u8 res = _SUCCESS;
480
481 ph2c = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
482 if (ph2c == NULL) {
483 res = _FAIL;
484 goto exit;
485 }
486
487 psetstakey_para = kzalloc(sizeof(struct set_stakey_parm), GFP_KERNEL);
488 if (psetstakey_para == NULL) {
489 kfree(ph2c);
490 res = _FAIL;
491 goto exit;
492 }
493
494 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
495
496 psetstakey_para->algorithm = (u8) psta->dot118021XPrivacy;
497
498 memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
499
500 memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
501
502 res = rtw_enqueue_cmd23a(pcmdpriv, ph2c);
503
504exit:
505 return res;
506}
507
508static int set_group_key(struct rtw_adapter *padapter, u8 *key, u8 alg,
509 int keyid)
510{
511 u8 keylen;
512 struct cmd_obj *pcmd;
513 struct setkey_parm *psetkeyparm;
514 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
515 int res = _SUCCESS;
516
517 DBG_8723A("%s\n", __func__);
518
519 pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
520 if (!pcmd) {
521 res = _FAIL;
522 goto exit;
523 }
524 psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
525 if (!psetkeyparm) {
526 kfree(pcmd);
527 res = _FAIL;
528 goto exit;
529 }
530
531 psetkeyparm->keyid = (u8) keyid;
532 if (is_wep_enc(alg))
533 padapter->mlmepriv.key_mask |= CHKBIT(psetkeyparm->keyid);
534
535 psetkeyparm->algorithm = alg;
536
537 psetkeyparm->set_tx = 1;
538
539 switch (alg) {
540 case _WEP40_:
541 keylen = 5;
542 break;
543 case _WEP104_:
544 keylen = 13;
545 break;
546 case _TKIP_:
547 case _TKIP_WTMIC_:
548 case _AES_:
549 default:
550 keylen = 16;
551 }
552
553 memcpy(&psetkeyparm->key[0], key, keylen);
554
555 pcmd->cmdcode = _SetKey_CMD_;
556 pcmd->parmbuf = (u8 *) psetkeyparm;
557 pcmd->cmdsz = (sizeof(struct setkey_parm));
558 pcmd->rsp = NULL;
559 pcmd->rspsz = 0;
560
561 INIT_LIST_HEAD(&pcmd->list);
562
563 res = rtw_enqueue_cmd23a(pcmdpriv, pcmd);
564
565exit:
566 return res;
567}
568
569static int set_wep_key(struct rtw_adapter *padapter, u8 *key, u8 keylen,
570 int keyid)
571{
572 u8 alg;
573
574 switch (keylen) {
575 case 5:
576 alg = _WEP40_;
577 break;
578 case 13:
579 alg = _WEP104_;
580 break;
581 default:
582 alg = _NO_PRIVACY_;
583 }
584
585 return set_group_key(padapter, key, alg, keyid);
586}
587
588static int rtw_cfg80211_ap_set_encryption(struct net_device *dev,
589 struct ieee_param *param,
590 u32 param_len)
591{
592 int ret = 0;
593 u32 wep_key_idx, wep_key_len;
594 struct sta_info *psta = NULL, *pbcmc_sta = NULL;
595 struct rtw_adapter *padapter = netdev_priv(dev);
596 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
597 struct security_priv *psecuritypriv = &padapter->securitypriv;
598 struct sta_priv *pstapriv = &padapter->stapriv;
599
600 DBG_8723A("%s\n", __func__);
601
602 param->u.crypt.err = 0;
603 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
604
605 /* sizeof(struct ieee_param) = 64 bytes; */
606 /* if (param_len != (u32) ((u8 *) param->u.crypt.key -
607 (u8 *) param) + param->u.crypt.key_len) */
608 if (param_len != sizeof(struct ieee_param) + param->u.crypt.key_len) {
609 ret = -EINVAL;
610 goto exit;
611 }
612
613 if (is_broadcast_ether_addr(param->sta_addr)) {
614 if (param->u.crypt.idx >= WEP_KEYS) {
615 ret = -EINVAL;
616 goto exit;
617 }
618 } else {
619 psta = rtw_get_stainfo23a(pstapriv, param->sta_addr);
620 if (!psta) {
621 /* ret = -EINVAL; */
622 DBG_8723A("rtw_set_encryption(), sta has already "
623 "been removed or never been added\n");
624 goto exit;
625 }
626 }
627
628 if (strcmp(param->u.crypt.alg, "none") == 0 && (psta == NULL)) {
629 /* todo:clear default encryption keys */
630
631 DBG_8723A("clear default encryption keys, keyid =%d\n",
632 param->u.crypt.idx);
633
634 goto exit;
635 }
636
637 if (strcmp(param->u.crypt.alg, "WEP") == 0 && (psta == NULL)) {
638 DBG_8723A("r871x_set_encryption, crypt.alg = WEP\n");
639
640 wep_key_idx = param->u.crypt.idx;
641 wep_key_len = param->u.crypt.key_len;
642
643 DBG_8723A("r871x_set_encryption, wep_key_idx =%d, len =%d\n",
644 wep_key_idx, wep_key_len);
645
646 if ((wep_key_idx >= WEP_KEYS) || (wep_key_len <= 0)) {
647 ret = -EINVAL;
648 goto exit;
649 }
650
651 if (wep_key_len > 0) {
652 wep_key_len = wep_key_len <= 5 ? 5 : 13;
653 }
654
655 if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
656 /* wep default key has not been set, so use
657 this key index as default key. */
658
659 psecuritypriv->ndisencryptstatus =
660 Ndis802_11Encryption1Enabled;
661 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
662 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
663
664 if (wep_key_len == 13) {
665 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
666 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
667 }
668
669 psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
670 }
671
672 memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0],
673 param->u.crypt.key, wep_key_len);
674
675 psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
676
677 set_wep_key(padapter, param->u.crypt.key, wep_key_len,
678 wep_key_idx);
679
680 goto exit;
681
682 }
683
684 if (!psta && check_fwstate(pmlmepriv, WIFI_AP_STATE)) { /* group key */
685 if (param->u.crypt.set_tx == 0) { /* group key */
686 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
687 DBG_8723A("%s, set group_key, WEP\n",
688 __func__);
689
690 memcpy(psecuritypriv->
691 dot118021XGrpKey[param->u.crypt.idx].
692 skey, param->u.crypt.key,
693 (param->u.crypt.key_len >
694 16 ? 16 : param->u.crypt.key_len));
695
696 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
697 if (param->u.crypt.key_len == 13) {
698 psecuritypriv->dot118021XGrpPrivacy =
699 _WEP104_;
700 }
701
702 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
703 DBG_8723A("%s, set group_key, TKIP\n",
704 __func__);
705
706 psecuritypriv->dot118021XGrpPrivacy = _TKIP_;
707
708 memcpy(psecuritypriv->
709 dot118021XGrpKey[param->u.crypt.idx].
710 skey, param->u.crypt.key,
711 (param->u.crypt.key_len >
712 16 ? 16 : param->u.crypt.key_len));
713
714 /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
715 /* set mic key */
716 memcpy(psecuritypriv->
717 dot118021XGrptxmickey[param->u.crypt.
718 idx].skey,
719 &param->u.crypt.key[16], 8);
720 memcpy(psecuritypriv->
721 dot118021XGrprxmickey[param->u.crypt.
722 idx].skey,
723 &param->u.crypt.key[24], 8);
724
725 psecuritypriv->busetkipkey = true;
726
727 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
728 DBG_8723A("%s, set group_key, CCMP\n",
729 __func__);
730
731 psecuritypriv->dot118021XGrpPrivacy = _AES_;
732
733 memcpy(psecuritypriv->
734 dot118021XGrpKey[param->u.crypt.idx].
735 skey, param->u.crypt.key,
736 (param->u.crypt.key_len >
737 16 ? 16 : param->u.crypt.key_len));
738 } else {
739 DBG_8723A("%s, set group_key, none\n",
740 __func__);
741
742 psecuritypriv->dot118021XGrpPrivacy =
743 _NO_PRIVACY_;
744 }
745
746 psecuritypriv->dot118021XGrpKeyid = param->u.crypt.idx;
747
748 psecuritypriv->binstallGrpkey = true;
749
750 psecuritypriv->dot11PrivacyAlgrthm =
751 psecuritypriv->dot118021XGrpPrivacy;
752
753 set_group_key(padapter, param->u.crypt.key,
754 psecuritypriv->dot118021XGrpPrivacy,
755 param->u.crypt.idx);
756
757 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
758 if (pbcmc_sta) {
759 pbcmc_sta->ieee8021x_blocked = false;
760 /* rx will use bmc_sta's dot118021XPrivacy */
761 pbcmc_sta->dot118021XPrivacy =
762 psecuritypriv->dot118021XGrpPrivacy;
763
764 }
765
766 }
767
768 goto exit;
769 }
770
771 if (psecuritypriv->dot11AuthAlgrthm ==
772 dot11AuthAlgrthm_8021X && psta) { /* psk/802_1x */
773 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
774 if (param->u.crypt.set_tx == 1) {
775 /* pairwise key */
776 memcpy(psta->dot118021x_UncstKey.skey,
777 param->u.crypt.key,
778 (param->u.crypt.key_len >
779 16 ? 16 : param->u.crypt.key_len));
780
781 if (!strcmp(param->u.crypt.alg, "WEP")) {
782 DBG_8723A("%s, set pairwise key, WEP\n",
783 __func__);
784
785 psta->dot118021XPrivacy = _WEP40_;
786 if (param->u.crypt.key_len == 13) {
787 psta->dot118021XPrivacy =
788 _WEP104_;
789 }
790 } else if (!strcmp(param->u.crypt.alg, "TKIP")) {
791 DBG_8723A("%s, set pairwise key, "
792 "TKIP\n", __func__);
793
794 psta->dot118021XPrivacy = _TKIP_;
795
796 /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
797 /* set mic key */
798 memcpy(psta->dot11tkiptxmickey.skey,
799 &param->u.crypt.key[16], 8);
800 memcpy(psta->dot11tkiprxmickey.skey,
801 &param->u.crypt.key[24], 8);
802
803 psecuritypriv->busetkipkey = true;
804
805 } else if (!strcmp(param->u.crypt.alg, "CCMP")) {
806
807 DBG_8723A("%s, set pairwise key, "
808 "CCMP\n", __func__);
809
810 psta->dot118021XPrivacy = _AES_;
811 } else {
812 DBG_8723A("%s, set pairwise key, "
813 "none\n", __func__);
814
815 psta->dot118021XPrivacy = _NO_PRIVACY_;
816 }
817
818 set_pairwise_key(padapter, psta);
819
820 psta->ieee8021x_blocked = false;
821
822 psta->bpairwise_key_installed = true;
823 } else { /* group key??? */
824 if (!strcmp(param->u.crypt.alg, "WEP")) {
825 memcpy(psecuritypriv->
826 dot118021XGrpKey[param->u.crypt.
827 idx].skey,
828 param->u.crypt.key,
829 (param->u.crypt.key_len >
830 16 ? 16 : param->u.crypt.
831 key_len));
832
833 psecuritypriv->dot118021XGrpPrivacy =
834 _WEP40_;
835 if (param->u.crypt.key_len == 13) {
836 psecuritypriv->
837 dot118021XGrpPrivacy =
838 _WEP104_;
839 }
840 } else if (!strcmp(param->u.crypt.alg, "TKIP")) {
841 psecuritypriv->dot118021XGrpPrivacy =
842 _TKIP_;
843
844 memcpy(psecuritypriv->
845 dot118021XGrpKey[param->u.crypt.
846 idx].skey,
847 param->u.crypt.key,
848 (param->u.crypt.key_len >
849 16 ? 16 : param->u.crypt.
850 key_len));
851
852 /* DEBUG_ERR("set key length :param->u"
853 ".crypt.key_len =%d\n",
854 param->u.crypt.key_len); */
855 /* set mic key */
856 memcpy(psecuritypriv->
857 dot118021XGrptxmickey[param->u.
858 crypt.idx].
859 skey, &param->u.crypt.key[16],
860 8);
861 memcpy(psecuritypriv->
862 dot118021XGrprxmickey[param->u.
863 crypt.idx].
864 skey, &param->u.crypt.key[24],
865 8);
866
867 psecuritypriv->busetkipkey = true;
868
869 } else if (!strcmp(param->u.crypt.alg, "CCMP")) {
870 psecuritypriv->dot118021XGrpPrivacy =
871 _AES_;
872
873 memcpy(psecuritypriv->
874 dot118021XGrpKey[param->u.crypt.
875 idx].skey,
876 param->u.crypt.key,
877 (param->u.crypt.key_len >
878 16 ? 16 : param->u.crypt.
879 key_len));
880 } else {
881 psecuritypriv->dot118021XGrpPrivacy =
882 _NO_PRIVACY_;
883 }
884
885 psecuritypriv->dot118021XGrpKeyid =
886 param->u.crypt.idx;
887
888 psecuritypriv->binstallGrpkey = true;
889
890 psecuritypriv->dot11PrivacyAlgrthm =
891 psecuritypriv->dot118021XGrpPrivacy;
892
893 set_group_key(padapter, param->u.crypt.key,
894 psecuritypriv->
895 dot118021XGrpPrivacy,
896 param->u.crypt.idx);
897
898 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
899 if (pbcmc_sta) {
900 /* rx will use bmc_sta's
901 dot118021XPrivacy */
902 pbcmc_sta->ieee8021x_blocked = false;
903 pbcmc_sta->dot118021XPrivacy = psecuritypriv->dot118021XGrpPrivacy;
904 }
905 }
906 }
907 }
908
909exit:
910
911 return ret;
912
913}
914#endif
915
916static int rtw_cfg80211_set_encryption(struct net_device *dev,
917 struct ieee_param *param, u32 param_len)
918{
919 int ret = 0;
920 u32 wep_key_idx, wep_key_len;
921 struct rtw_adapter *padapter = netdev_priv(dev);
922 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
923 struct security_priv *psecuritypriv = &padapter->securitypriv;
924#ifdef CONFIG_8723AU_P2P
925 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
926#endif /* CONFIG_8723AU_P2P */
927
928
929
930 DBG_8723A("%s\n", __func__);
931
932 param->u.crypt.err = 0;
933 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
934
935 if (param_len <
936 (u32) ((u8 *) param->u.crypt.key - (u8 *) param) +
937 param->u.crypt.key_len) {
938 ret = -EINVAL;
939 goto exit;
940 }
941
942 if (is_broadcast_ether_addr(param->sta_addr)) {
943 if (param->u.crypt.idx >= WEP_KEYS) {
944 ret = -EINVAL;
945 goto exit;
946 }
947 } else {
948 ret = -EINVAL;
949 goto exit;
950 }
951
952 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
953 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
954 ("wpa_set_encryption, crypt.alg = WEP\n"));
955 DBG_8723A("wpa_set_encryption, crypt.alg = WEP\n");
956
957 wep_key_idx = param->u.crypt.idx;
958 wep_key_len = param->u.crypt.key_len;
959
960 if ((wep_key_idx > WEP_KEYS) || (wep_key_len <= 0)) {
961 ret = -EINVAL;
962 goto exit;
963 }
964
965 if (psecuritypriv->bWepDefaultKeyIdxSet == 0) {
966 /* wep default key has not been set, so use this
967 key index as default key. */
968
969 wep_key_len = wep_key_len <= 5 ? 5 : 13;
970
971 psecuritypriv->ndisencryptstatus =
972 Ndis802_11Encryption1Enabled;
973 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
974 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
975
976 if (wep_key_len == 13) {
977 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
978 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
979 }
980
981 psecuritypriv->dot11PrivacyKeyIndex = wep_key_idx;
982 }
983
984 memcpy(&psecuritypriv->dot11DefKey[wep_key_idx].skey[0],
985 param->u.crypt.key, wep_key_len);
986
987 psecuritypriv->dot11DefKeylen[wep_key_idx] = wep_key_len;
988
989 rtw_set_key23a(padapter, psecuritypriv, wep_key_idx, 0);
990
991 goto exit;
992 }
993
994 if (padapter->securitypriv.dot11AuthAlgrthm ==
995 dot11AuthAlgrthm_8021X) { /* 802_1x */
996 struct sta_info *psta, *pbcmc_sta;
997 struct sta_priv *pstapriv = &padapter->stapriv;
998
999 if (check_fwstate(pmlmepriv,
1000 WIFI_STATION_STATE | WIFI_MP_STATE)) {
1001 /* sta mode */
1002 psta = rtw_get_stainfo23a(pstapriv, get_bssid(pmlmepriv));
1003 if (psta == NULL) {
1004 DBG_8723A("%s, : Obtain Sta_info fail\n",
1005 __func__);
1006 } else {
1007 /* Jeff: don't disable ieee8021x_blocked
1008 while clearing key */
1009 if (strcmp(param->u.crypt.alg, "none") != 0)
1010 psta->ieee8021x_blocked = false;
1011
1012 if ((padapter->securitypriv.ndisencryptstatus ==
1013 Ndis802_11Encryption2Enabled) ||
1014 (padapter->securitypriv.ndisencryptstatus ==
1015 Ndis802_11Encryption3Enabled)) {
1016 psta->dot118021XPrivacy =
1017 padapter->securitypriv.
1018 dot11PrivacyAlgrthm;
1019 }
1020
1021 if (param->u.crypt.set_tx == 1) {
1022 /* pairwise key */
1023 DBG_8723A("%s, : param->u.crypt.set_tx"
1024 " == 1\n", __func__);
1025
1026 memcpy(psta->dot118021x_UncstKey.skey,
1027 param->u.crypt.key,
1028 (param->u.crypt.key_len >
1029 16 ? 16 : param->u.crypt.
1030 key_len));
1031
1032 if (strcmp(param->u.crypt.alg,
1033 "TKIP") == 0) {
1034 memcpy(psta->dot11tkiptxmickey.
1035 skey,
1036 &param->u.crypt.key[16],
1037 8);
1038 memcpy(psta->dot11tkiprxmickey.
1039 skey,
1040 &param->u.crypt.key[24],
1041 8);
1042
1043 padapter->securitypriv.
1044 busetkipkey = false;
1045 }
1046 DBG_8723A(" ~~~~set sta key:unicastkey\n");
1047
1048 rtw_setstakey_cmd23a(padapter,
1049 (unsigned char *)psta,
1050 true);
1051 } else { /* group key */
1052 memcpy(padapter->securitypriv.
1053 dot118021XGrpKey[param->u.crypt.
1054 idx].skey,
1055 param->u.crypt.key,
1056 (param->u.crypt.key_len >
1057 16 ? 16 : param->u.crypt.
1058 key_len));
1059 memcpy(padapter->securitypriv.
1060 dot118021XGrptxmickey[param->u.
1061 crypt.idx].
1062 skey, &param->u.crypt.key[16],
1063 8);
1064 memcpy(padapter->securitypriv.
1065 dot118021XGrprxmickey[param->u.
1066 crypt.idx].
1067 skey, &param->u.crypt.key[24],
1068 8);
1069 padapter->securitypriv.binstallGrpkey =
1070 true;
1071 /* DEBUG_ERR((" param->u.crypt.key_len"
1072 "=%d\n", param->u.crypt.key_len)); */
1073 DBG_8723A
1074 (" ~~~~set sta key:groupkey\n");
1075
1076 padapter->securitypriv.
1077 dot118021XGrpKeyid =
1078 param->u.crypt.idx;
1079
1080 rtw_set_key23a(padapter,
1081 &padapter->securitypriv,
1082 param->u.crypt.idx, 1);
1083#ifdef CONFIG_8723AU_P2P
1084 if (rtw_p2p_chk_state
1085 (pwdinfo,
1086 P2P_STATE_PROVISIONING_ING)) {
1087 rtw_p2p_set_state(pwdinfo,
1088 P2P_STATE_PROVISIONING_DONE);
1089 }
1090#endif /* CONFIG_8723AU_P2P */
1091
1092 }
1093 }
1094
1095 pbcmc_sta = rtw_get_bcmc_stainfo23a(padapter);
1096 if (pbcmc_sta) {
1097 /* Jeff: don't disable ieee8021x_blocked
1098 while clearing key */
1099 if (strcmp(param->u.crypt.alg, "none") != 0)
1100 pbcmc_sta->ieee8021x_blocked = false;
1101
1102 if ((padapter->securitypriv.ndisencryptstatus ==
1103 Ndis802_11Encryption2Enabled) ||
1104 (padapter->securitypriv.ndisencryptstatus ==
1105 Ndis802_11Encryption3Enabled)) {
1106 pbcmc_sta->dot118021XPrivacy =
1107 padapter->securitypriv.
1108 dot11PrivacyAlgrthm;
1109 }
1110 }
1111 } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) { /* adhoc mode */
1112 }
1113 }
1114
1115exit:
1116
1117 DBG_8723A("%s, ret =%d\n", __func__, ret);
1118
1119
1120
1121 return ret;
1122}
1123
1124static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
1125 u8 key_index, bool pairwise,
1126 const u8 *mac_addr, struct key_params *params)
1127{
1128 char *alg_name;
1129 u32 param_len;
1130 struct ieee_param *param = NULL;
1131 int ret = 0;
1132 struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
1133 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1134 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1135
1136 DBG_8723A(FUNC_NDEV_FMT " adding key for %pM\n", FUNC_NDEV_ARG(ndev),
1137 mac_addr);
1138 DBG_8723A("cipher = 0x%x\n", params->cipher);
1139 DBG_8723A("key_len = 0x%x\n", params->key_len);
1140 DBG_8723A("seq_len = 0x%x\n", params->seq_len);
1141 DBG_8723A("key_index =%d\n", key_index);
1142 DBG_8723A("pairwise =%d\n", pairwise);
1143
1144 param_len = sizeof(struct ieee_param) + params->key_len;
1145 param = kzalloc(param_len, GFP_KERNEL);
1146 if (param == NULL)
1147 return -1;
1148
1149 param->cmd = IEEE_CMD_SET_ENCRYPTION;
1150 memset(param->sta_addr, 0xff, ETH_ALEN);
1151
1152 switch (params->cipher) {
1153 case IW_AUTH_CIPHER_NONE:
1154 /* todo: remove key */
1155 /* remove = 1; */
1156 alg_name = "none";
1157 break;
1158 case WLAN_CIPHER_SUITE_WEP40:
1159 case WLAN_CIPHER_SUITE_WEP104:
1160 alg_name = "WEP";
1161 break;
1162 case WLAN_CIPHER_SUITE_TKIP:
1163 alg_name = "TKIP";
1164 break;
1165 case WLAN_CIPHER_SUITE_CCMP:
1166 alg_name = "CCMP";
1167 break;
1168
1169 default:
1170 ret = -ENOTSUPP;
1171 goto addkey_end;
1172 }
1173
1174 strncpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
1175
1176 if (!mac_addr || is_broadcast_ether_addr(mac_addr)) {
1177 param->u.crypt.set_tx = 0; /* for wpa/wpa2 group key */
1178 } else {
1179 param->u.crypt.set_tx = 1; /* for wpa/wpa2 pairwise key */
1180 }
1181
1182 /* param->u.crypt.idx = key_index - 1; */
1183 param->u.crypt.idx = key_index;
1184
1185 if (params->seq_len && params->seq) {
1186 memcpy(param->u.crypt.seq, params->seq, params->seq_len);
1187 }
1188
1189 if (params->key_len && params->key) {
1190 param->u.crypt.key_len = params->key_len;
1191 memcpy(param->u.crypt.key, params->key, params->key_len);
1192 }
1193
1194 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1195 ret = rtw_cfg80211_set_encryption(ndev, param, param_len);
1196 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1197#ifdef CONFIG_8723AU_AP_MODE
1198 if (mac_addr)
1199 memcpy(param->sta_addr, (void *)mac_addr, ETH_ALEN);
1200
1201 ret = rtw_cfg80211_ap_set_encryption(ndev, param, param_len);
1202#endif
1203 } else {
1204 DBG_8723A("error! fw_state = 0x%x, iftype =%d\n",
1205 pmlmepriv->fw_state, rtw_wdev->iftype);
1206
1207 }
1208
1209addkey_end:
1210 kfree(param);
1211
1212 return ret;
1213}
1214
1215static int
1216cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
1217 u8 key_index, bool pairwise, const u8 *mac_addr,
1218 void *cookie,
1219 void (*callback) (void *cookie, struct key_params *))
1220{
1221 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
1222 return 0;
1223}
1224
1225static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
1226 u8 key_index, bool pairwise,
1227 const u8 *mac_addr)
1228{
1229 struct rtw_adapter *padapter = netdev_priv(ndev);
1230 struct security_priv *psecuritypriv = &padapter->securitypriv;
1231
1232 DBG_8723A(FUNC_NDEV_FMT " key_index =%d\n", FUNC_NDEV_ARG(ndev),
1233 key_index);
1234
1235 if (key_index == psecuritypriv->dot11PrivacyKeyIndex) {
1236 /* clear the flag of wep default key set. */
1237 psecuritypriv->bWepDefaultKeyIdxSet = 0;
1238 }
1239
1240 return 0;
1241}
1242
1243static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
1244 struct net_device *ndev, u8 key_index,
1245 bool unicast, bool multicast)
1246{
1247 struct rtw_adapter *padapter = netdev_priv(ndev);
1248 struct security_priv *psecuritypriv = &padapter->securitypriv;
1249
1250 DBG_8723A(FUNC_NDEV_FMT " key_index =%d"
1251 ", unicast =%d, multicast =%d.\n", FUNC_NDEV_ARG(ndev),
1252 key_index, unicast, multicast);
1253
1254 if ((key_index < WEP_KEYS) &&
1255 ((psecuritypriv->dot11PrivacyAlgrthm == _WEP40_) ||
1256 (psecuritypriv->dot11PrivacyAlgrthm == _WEP104_))) {
1257 /* set wep default key */
1258 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1259
1260 psecuritypriv->dot11PrivacyKeyIndex = key_index;
1261
1262 psecuritypriv->dot11PrivacyAlgrthm = _WEP40_;
1263 psecuritypriv->dot118021XGrpPrivacy = _WEP40_;
1264 if (psecuritypriv->dot11DefKeylen[key_index] == 13) {
1265 psecuritypriv->dot11PrivacyAlgrthm = _WEP104_;
1266 psecuritypriv->dot118021XGrpPrivacy = _WEP104_;
1267 }
1268
1269 /* set the flag to represent that wep default key
1270 has been set */
1271 psecuritypriv->bWepDefaultKeyIdxSet = 1;
1272 }
1273
1274 return 0;
1275}
1276
1277static int cfg80211_rtw_get_station(struct wiphy *wiphy,
1278 struct net_device *ndev,
1279 u8 *mac, struct station_info *sinfo)
1280{
1281 int ret = 0;
1282 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1283 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1284 struct sta_info *psta = NULL;
1285 struct sta_priv *pstapriv = &padapter->stapriv;
1286
1287 sinfo->filled = 0;
1288
1289 if (!mac) {
1290 DBG_8723A(FUNC_NDEV_FMT " mac ==%p\n", FUNC_NDEV_ARG(ndev), mac);
1291 ret = -ENOENT;
1292 goto exit;
1293 }
1294
1295 psta = rtw_get_stainfo23a(pstapriv, mac);
1296 if (psta == NULL) {
1297 DBG_8723A("%s, sta_info is null\n", __func__);
1298 ret = -ENOENT;
1299 goto exit;
1300 }
1301#ifdef CONFIG_DEBUG_CFG80211
1302 DBG_8723A(FUNC_NDEV_FMT " mac =" MAC_FMT "\n", FUNC_NDEV_ARG(ndev),
1303 MAC_ARG(mac));
1304#endif
1305
1306 /* for infra./P2PClient mode */
1307 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
1308 check_fwstate(pmlmepriv, _FW_LINKED)) {
1309 struct wlan_network *cur_network = &pmlmepriv->cur_network;
1310
1311 if (memcmp(mac, cur_network->network.MacAddress, ETH_ALEN)) {
1312 DBG_8723A("%s, mismatch bssid =" MAC_FMT "\n", __func__,
1313 MAC_ARG(cur_network->network.MacAddress));
1314 ret = -ENOENT;
1315 goto exit;
1316 }
1317
1318 sinfo->filled |= STATION_INFO_SIGNAL;
1319 sinfo->signal = translate_percentage_to_dbm(padapter->recvpriv.
1320 signal_strength);
1321
1322 sinfo->filled |= STATION_INFO_TX_BITRATE;
1323 sinfo->txrate.legacy = rtw_get_cur_max_rate23a(padapter);
1324
1325 sinfo->filled |= STATION_INFO_RX_PACKETS;
1326 sinfo->rx_packets = sta_rx_data_pkts(psta);
1327
1328 sinfo->filled |= STATION_INFO_TX_PACKETS;
1329 sinfo->tx_packets = psta->sta_stats.tx_pkts;
1330 }
1331
1332 /* for Ad-Hoc/AP mode */
1333 if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
1334 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1335 check_fwstate(pmlmepriv, WIFI_AP_STATE)) &&
1336 check_fwstate(pmlmepriv, _FW_LINKED)
1337 ) {
1338 /* TODO: should acquire station info... */
1339 }
1340
1341exit:
1342 return ret;
1343}
1344
1345static int cfg80211_rtw_change_iface(struct wiphy *wiphy,
1346 struct net_device *ndev,
1347 enum nl80211_iftype type, u32 *flags,
1348 struct vif_params *params)
1349{
1350 enum nl80211_iftype old_type;
1351 enum ndis_802_11_net_infra networkType;
1352 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1353 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1354 struct wireless_dev *rtw_wdev = wiphy_to_wdev(wiphy);
1355#ifdef CONFIG_8723AU_P2P
1356 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1357#endif
1358 int ret = 0;
1359 u8 change = false;
1360
1361 DBG_8723A(FUNC_NDEV_FMT " call netdev_open23a\n", FUNC_NDEV_ARG(ndev));
1362 if (netdev_open23a(ndev) != 0) {
1363 ret = -EPERM;
1364 goto exit;
1365 }
1366
1367 if (_FAIL == rtw_pwr_wakeup(padapter)) {
1368 ret = -EPERM;
1369 goto exit;
1370 }
1371
1372 old_type = rtw_wdev->iftype;
1373 DBG_8723A(FUNC_NDEV_FMT " old_iftype =%d, new_iftype =%d\n",
1374 FUNC_NDEV_ARG(ndev), old_type, type);
1375
1376 if (old_type != type) {
1377 change = true;
1378 pmlmeext->action_public_rxseq = 0xffff;
1379 pmlmeext->action_public_dialog_token = 0xff;
1380 }
1381
1382 switch (type) {
1383 case NL80211_IFTYPE_ADHOC:
1384 networkType = Ndis802_11IBSS;
1385 break;
1386 case NL80211_IFTYPE_P2P_CLIENT:
1387 case NL80211_IFTYPE_STATION:
1388 networkType = Ndis802_11Infrastructure;
1389#ifdef CONFIG_8723AU_P2P
1390 if (change && rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1391 del_timer_sync(&pwdinfo->find_phase_timer);
1392 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
1393 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
1394
1395 /* it means remove GO and change mode from AP(GO)
1396 to station(P2P DEVICE) */
1397 rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
1398 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
1399
1400 DBG_8723A("%s, role =%d, p2p_state =%d, pre_p2p_state ="
1401 "%d\n", __func__, rtw_p2p_role(pwdinfo),
1402 rtw_p2p_state(pwdinfo),
1403 rtw_p2p_pre_state(pwdinfo));
1404 }
1405#endif /* CONFIG_8723AU_P2P */
1406 break;
1407 case NL80211_IFTYPE_P2P_GO:
1408 case NL80211_IFTYPE_AP:
1409 networkType = Ndis802_11APMode;
1410#ifdef CONFIG_8723AU_P2P
1411 if (change && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
1412 /* it means P2P Group created, we will be GO
1413 and change mode from P2P DEVICE to AP(GO) */
1414 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
1415 }
1416#endif /* CONFIG_8723AU_P2P */
1417 break;
1418 default:
1419 return -EOPNOTSUPP;
1420 }
1421
1422 rtw_wdev->iftype = type;
1423
1424 if (rtw_set_802_11_infrastructure_mode23a(padapter, networkType) == false) {
1425 rtw_wdev->iftype = old_type;
1426 ret = -EPERM;
1427 goto exit;
1428 }
1429
1430 rtw_setopmode_cmd23a(padapter, networkType);
1431
1432exit:
1433 return ret;
1434}
1435
1436void rtw_cfg80211_indicate_scan_done(struct rtw_wdev_priv *pwdev_priv,
1437 bool aborted)
1438{
1439 spin_lock_bh(&pwdev_priv->scan_req_lock);
1440 if (pwdev_priv->scan_request != NULL) {
1441#ifdef CONFIG_DEBUG_CFG80211
1442 DBG_8723A("%s with scan req\n", __func__);
1443#endif
1444 if (pwdev_priv->scan_request->wiphy !=
1445 pwdev_priv->rtw_wdev->wiphy)
1446 DBG_8723A("error wiphy compare\n");
1447 else
1448 cfg80211_scan_done(pwdev_priv->scan_request, aborted);
1449
1450 pwdev_priv->scan_request = NULL;
1451 } else {
1452#ifdef CONFIG_DEBUG_CFG80211
1453 DBG_8723A("%s without scan req\n", __func__);
1454#endif
1455 }
1456 spin_unlock_bh(&pwdev_priv->scan_req_lock);
1457}
1458
1459void rtw_cfg80211_surveydone_event_callback(struct rtw_adapter *padapter)
1460{
1461 struct list_head *plist, *phead, *ptmp;
1462 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1463 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
1464 struct wlan_network *pnetwork;
1465
1466#ifdef CONFIG_DEBUG_CFG80211
1467 DBG_8723A("%s\n", __func__);
1468#endif
1469
1470 spin_lock_bh(&pmlmepriv->scanned_queue.lock);
1471
1472 phead = get_list_head(queue);
1473
1474 list_for_each_safe(plist, ptmp, phead) {
1475 pnetwork = container_of(plist, struct wlan_network, list);
1476
1477 /* report network only if the current channel set
1478 contains the channel to which this network belongs */
1479 if (rtw_ch_set_search_ch23a
1480 (padapter->mlmeextpriv.channel_set,
1481 pnetwork->network.Configuration.DSConfig) >= 0)
1482 rtw_cfg80211_inform_bss(padapter, pnetwork);
1483 }
1484
1485 spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1486
1487 /* call this after other things have been done */
1488 rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
1489 false);
1490}
1491
1492static int rtw_cfg80211_set_probe_req_wpsp2pie(struct rtw_adapter *padapter,
1493 char *buf, int len)
1494{
1495 int ret = 0;
1496 uint wps_ielen = 0;
1497 u8 *wps_ie;
1498 u32 p2p_ielen = 0;
1499 u8 *p2p_ie;
1500 u32 wfd_ielen = 0;
1501 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1502
1503#ifdef CONFIG_DEBUG_CFG80211
1504 DBG_8723A("%s, ielen =%d\n", __func__, len);
1505#endif
1506
1507 if (len > 0) {
1508 wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
1509 if (wps_ie) {
1510#ifdef CONFIG_DEBUG_CFG80211
1511 DBG_8723A("probe_req_wps_ielen =%d\n", wps_ielen);
1512#endif
1513 if (pmlmepriv->wps_probe_req_ie) {
1514 pmlmepriv->wps_probe_req_ie_len = 0;
1515 kfree(pmlmepriv->wps_probe_req_ie);
1516 pmlmepriv->wps_probe_req_ie = NULL;
1517 }
1518
1519 pmlmepriv->wps_probe_req_ie =
1520 kmalloc(wps_ielen, GFP_KERNEL);
1521 if (pmlmepriv->wps_probe_req_ie == NULL) {
1522 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1523 __func__, __LINE__);
1524 return -EINVAL;
1525 }
1526 memcpy(pmlmepriv->wps_probe_req_ie, wps_ie, wps_ielen);
1527 pmlmepriv->wps_probe_req_ie_len = wps_ielen;
1528 }
1529#ifdef CONFIG_8723AU_P2P
1530 p2p_ie = rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen);
1531 if (p2p_ie) {
1532#ifdef CONFIG_DEBUG_CFG80211
1533 DBG_8723A("probe_req_p2p_ielen =%d\n", p2p_ielen);
1534#endif
1535
1536 if (pmlmepriv->p2p_probe_req_ie) {
1537 pmlmepriv->p2p_probe_req_ie_len = 0;
1538 kfree(pmlmepriv->p2p_probe_req_ie);
1539 pmlmepriv->p2p_probe_req_ie = NULL;
1540 }
1541
1542 pmlmepriv->p2p_probe_req_ie =
1543 kmalloc(p2p_ielen, GFP_KERNEL);
1544 if (pmlmepriv->p2p_probe_req_ie == NULL) {
1545 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1546 __func__, __LINE__);
1547 return -EINVAL;
1548
1549 }
1550 memcpy(pmlmepriv->p2p_probe_req_ie, p2p_ie, p2p_ielen);
1551 pmlmepriv->p2p_probe_req_ie_len = p2p_ielen;
1552 }
1553#endif /* CONFIG_8723AU_P2P */
1554
1555 /* buf += p2p_ielen; */
1556 /* len -= p2p_ielen; */
1557
1558#ifdef CONFIG_8723AU_P2P
1559 if (rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) {
1560#ifdef CONFIG_DEBUG_CFG80211
1561 DBG_8723A("probe_req_wfd_ielen =%d\n", wfd_ielen);
1562#endif
1563
1564 if (pmlmepriv->wfd_probe_req_ie) {
1565 pmlmepriv->wfd_probe_req_ie_len = 0;
1566 kfree(pmlmepriv->wfd_probe_req_ie);
1567 pmlmepriv->wfd_probe_req_ie = NULL;
1568 }
1569
1570 pmlmepriv->wfd_probe_req_ie =
1571 kmalloc(wfd_ielen, GFP_KERNEL);
1572 if (pmlmepriv->wfd_probe_req_ie == NULL) {
1573 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
1574 __func__, __LINE__);
1575 return -EINVAL;
1576
1577 }
1578 rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_probe_req_ie,
1579 &pmlmepriv->wfd_probe_req_ie_len);
1580 }
1581#endif /* CONFIG_8723AU_P2P */
1582
1583 }
1584
1585 return ret;
1586}
1587
1588static int cfg80211_rtw_scan(struct wiphy *wiphy,
1589 struct cfg80211_scan_request *request)
1590{
1591 int i;
1592 u8 _status = false;
1593 int ret = 0;
1594 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
1595 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1596 struct cfg80211_ssid ssid[RTW_SSID_SCAN_AMOUNT];
1597 struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
1598#ifdef CONFIG_8723AU_P2P
1599 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1600#endif /* CONFIG_8723AU_P2P */
1601 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
1602 struct cfg80211_ssid *ssids = request->ssids;
1603 int social_channel = 0;
1604 bool need_indicate_scan_done = false;
1605
1606#ifdef CONFIG_DEBUG_CFG80211
1607 DBG_8723A(FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter));
1608#endif
1609
1610 spin_lock_bh(&pwdev_priv->scan_req_lock);
1611 pwdev_priv->scan_request = request;
1612 spin_unlock_bh(&pwdev_priv->scan_req_lock);
1613
1614 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1615
1616#ifdef CONFIG_DEBUG_CFG80211
1617 DBG_8723A("%s under WIFI_AP_STATE\n", __func__);
1618#endif
1619 /* need_indicate_scan_done = true; */
1620 /* goto check_need_indicate_scan_done; */
1621 }
1622
1623 if (rtw_pwr_wakeup(padapter) == _FAIL) {
1624 need_indicate_scan_done = true;
1625 goto check_need_indicate_scan_done;
1626 }
1627#ifdef CONFIG_8723AU_P2P
1628 if (ssids->ssid != NULL &&
1629 !memcmp(ssids->ssid, "DIRECT-", 7) &&
1630 rtw_get_p2p_ie23a((u8 *) request->ie, request->ie_len, NULL, NULL)) {
1631 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
1632 rtw_p2p_enable23a(padapter, P2P_ROLE_DEVICE);
1633 wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = true;
1634 } else {
1635 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
1636#ifdef CONFIG_DEBUG_CFG80211
1637 DBG_8723A("%s, role =%d, p2p_state =%d\n", __func__,
1638 rtw_p2p_role(pwdinfo),
1639 rtw_p2p_state(pwdinfo));
1640#endif
1641 }
1642 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
1643
1644 if (request->n_channels == 3 &&
1645 request->channels[0]->hw_value == 1 &&
1646 request->channels[1]->hw_value == 6 &&
1647 request->channels[2]->hw_value == 11)
1648 social_channel = 1;
1649 }
1650#endif /* CONFIG_8723AU_P2P */
1651
1652 if (request->ie && request->ie_len > 0) {
1653 rtw_cfg80211_set_probe_req_wpsp2pie(padapter,
1654 (u8 *) request->ie,
1655 request->ie_len);
1656 }
1657
1658 if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
1659 DBG_8723A("%s, bBusyTraffic == true\n", __func__);
1660 need_indicate_scan_done = true;
1661 goto check_need_indicate_scan_done;
1662 }
1663 if (rtw_is_scan_deny(padapter)) {
1664 DBG_8723A(FUNC_ADPT_FMT ": scan deny\n",
1665 FUNC_ADPT_ARG(padapter));
1666 need_indicate_scan_done = true;
1667 goto check_need_indicate_scan_done;
1668 }
1669
1670 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ==
1671 true) {
1672 DBG_8723A("%s, fwstate = 0x%x\n", __func__, pmlmepriv->fw_state);
1673 need_indicate_scan_done = true;
1674 goto check_need_indicate_scan_done;
1675 }
1676#ifdef CONFIG_8723AU_P2P
1677 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
1678 !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
1679 rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
1680 rtw_free_network_queue23a(padapter, true);
1681
1682 if (social_channel == 0)
1683 rtw_p2p_findphase_ex_set(pwdinfo,
1684 P2P_FINDPHASE_EX_NONE);
1685 else
1686 rtw_p2p_findphase_ex_set(pwdinfo,
1687 P2P_FINDPHASE_EX_SOCIAL_LAST);
1688 }
1689#endif /* CONFIG_8723AU_P2P */
1690
1691 memset(ssid, 0, sizeof(struct cfg80211_ssid) * RTW_SSID_SCAN_AMOUNT);
1692 /* parsing request ssids, n_ssids */
1693 for (i = 0; i < request->n_ssids && i < RTW_SSID_SCAN_AMOUNT; i++) {
1694#ifdef CONFIG_DEBUG_CFG80211
1695 DBG_8723A("ssid =%s, len =%d\n", ssids[i].ssid,
1696 ssids[i].ssid_len);
1697#endif
1698 memcpy(ssid[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
1699 ssid[i].ssid_len = ssids[i].ssid_len;
1700 }
1701
1702 /* parsing channels, n_channels */
1703 memset(ch, 0,
1704 sizeof(struct rtw_ieee80211_channel) * RTW_CHANNEL_SCAN_AMOUNT);
1705
1706 if (request->n_channels == 1) {
1707 for (i = 0; i < request->n_channels &&
1708 i < RTW_CHANNEL_SCAN_AMOUNT; i++) {
1709#ifdef CONFIG_DEBUG_CFG80211
1710 DBG_8723A(FUNC_ADPT_FMT CHAN_FMT "\n",
1711 FUNC_ADPT_ARG(padapter),
1712 CHAN_ARG(request->channels[i]));
1713#endif
1714 ch[i].hw_value = request->channels[i]->hw_value;
1715 ch[i].flags = request->channels[i]->flags;
1716 }
1717 }
1718
1719 spin_lock_bh(&pmlmepriv->lock);
1720 if (request->n_channels == 1) {
1721 memcpy(&ch[1], &ch[0], sizeof(struct rtw_ieee80211_channel));
1722 memcpy(&ch[2], &ch[0], sizeof(struct rtw_ieee80211_channel));
1723 _status = rtw_sitesurvey_cmd23a(padapter, ssid,
1724 RTW_SSID_SCAN_AMOUNT, ch, 3);
1725 } else {
1726 _status = rtw_sitesurvey_cmd23a(padapter, ssid,
1727 RTW_SSID_SCAN_AMOUNT, NULL, 0);
1728 }
1729 spin_unlock_bh(&pmlmepriv->lock);
1730
1731 if (_status == false)
1732 ret = -1;
1733
1734check_need_indicate_scan_done:
1735 if (need_indicate_scan_done)
1736 rtw_cfg80211_surveydone_event_callback(padapter);
1737 return ret;
1738}
1739
1740static int cfg80211_rtw_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1741{
1742 DBG_8723A("%s\n", __func__);
1743 return 0;
1744}
1745
1746static int cfg80211_rtw_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
1747 struct cfg80211_ibss_params *params)
1748{
1749 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
1750 return 0;
1751}
1752
1753static int cfg80211_rtw_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1754{
1755 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
1756 return 0;
1757}
1758
1759static int rtw_cfg80211_set_wpa_version(struct security_priv *psecuritypriv,
1760 u32 wpa_version)
1761{
1762 DBG_8723A("%s, wpa_version =%d\n", __func__, wpa_version);
1763
1764 if (!wpa_version) {
1765 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
1766 return 0;
1767 }
1768
1769 if (wpa_version & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) {
1770 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPAPSK;
1771 }
1772
1773/*
1774 if (wpa_version & NL80211_WPA_VERSION_2)
1775 {
1776 psecuritypriv->ndisauthtype = Ndis802_11AuthModeWPA2PSK;
1777 }
1778*/
1779
1780 return 0;
1781}
1782
1783static int rtw_cfg80211_set_auth_type(struct security_priv *psecuritypriv,
1784 enum nl80211_auth_type sme_auth_type)
1785{
1786 DBG_8723A("%s, nl80211_auth_type =%d\n", __func__, sme_auth_type);
1787
1788 switch (sme_auth_type) {
1789 case NL80211_AUTHTYPE_AUTOMATIC:
1790 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Auto;
1791
1792 break;
1793 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1794 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1795
1796 if (psecuritypriv->ndisauthtype > Ndis802_11AuthModeWPA)
1797 psecuritypriv->dot11AuthAlgrthm =
1798 dot11AuthAlgrthm_8021X;
1799 break;
1800 case NL80211_AUTHTYPE_SHARED_KEY:
1801 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Shared;
1802
1803 psecuritypriv->ndisencryptstatus = Ndis802_11Encryption1Enabled;
1804 break;
1805 default:
1806 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
1807 /* return -ENOTSUPP; */
1808 }
1809
1810 return 0;
1811}
1812
1813static int rtw_cfg80211_set_cipher(struct security_priv *psecuritypriv,
1814 u32 cipher, bool ucast)
1815{
1816 u32 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1817
1818 u32 *profile_cipher = ucast ? &psecuritypriv->dot11PrivacyAlgrthm :
1819 &psecuritypriv->dot118021XGrpPrivacy;
1820
1821 DBG_8723A("%s, ucast =%d, cipher = 0x%x\n", __func__, ucast, cipher);
1822
1823 if (!cipher) {
1824 *profile_cipher = _NO_PRIVACY_;
1825 psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1826 return 0;
1827 }
1828
1829 switch (cipher) {
1830 case IW_AUTH_CIPHER_NONE:
1831 *profile_cipher = _NO_PRIVACY_;
1832 ndisencryptstatus = Ndis802_11EncryptionDisabled;
1833 break;
1834 case WLAN_CIPHER_SUITE_WEP40:
1835 *profile_cipher = _WEP40_;
1836 ndisencryptstatus = Ndis802_11Encryption1Enabled;
1837 break;
1838 case WLAN_CIPHER_SUITE_WEP104:
1839 *profile_cipher = _WEP104_;
1840 ndisencryptstatus = Ndis802_11Encryption1Enabled;
1841 break;
1842 case WLAN_CIPHER_SUITE_TKIP:
1843 *profile_cipher = _TKIP_;
1844 ndisencryptstatus = Ndis802_11Encryption2Enabled;
1845 break;
1846 case WLAN_CIPHER_SUITE_CCMP:
1847 *profile_cipher = _AES_;
1848 ndisencryptstatus = Ndis802_11Encryption3Enabled;
1849 break;
1850 default:
1851 DBG_8723A("Unsupported cipher: 0x%x\n", cipher);
1852 return -ENOTSUPP;
1853 }
1854
1855 if (ucast)
1856 psecuritypriv->ndisencryptstatus = ndisencryptstatus;
1857
1858 return 0;
1859}
1860
1861static int rtw_cfg80211_set_key_mgt(struct security_priv *psecuritypriv,
1862 u32 key_mgt)
1863{
1864 DBG_8723A("%s, key_mgt = 0x%x\n", __func__, key_mgt);
1865
1866 if (key_mgt == WLAN_AKM_SUITE_8021X)
1867 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1868 else if (key_mgt == WLAN_AKM_SUITE_PSK)
1869 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X;
1870 else
1871 DBG_8723A("Invalid key mgt: 0x%x\n", key_mgt);
1872
1873 return 0;
1874}
1875
1876static int rtw_cfg80211_set_wpa_ie(struct rtw_adapter *padapter, const u8 *pie,
1877 size_t ielen)
1878{
1879 u8 *buf = NULL, *pos = NULL;
1880 int group_cipher = 0, pairwise_cipher = 0;
1881 int ret = 0;
1882 int wpa_ielen = 0;
1883 int wpa2_ielen = 0;
1884 u8 *pwpa, *pwpa2;
1885 u8 null_addr[] = { 0, 0, 0, 0, 0, 0 };
1886 int i;
1887
1888 if (!pie || !ielen) {
1889 /* Treat this as normal case, but need to clear
1890 WIFI_UNDER_WPS */
1891 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
1892 goto exit;
1893 }
1894 if (ielen > MAX_WPA_IE_LEN + MAX_WPS_IE_LEN + MAX_P2P_IE_LEN) {
1895 ret = -EINVAL;
1896 goto exit;
1897 }
1898 buf = kzalloc(ielen, GFP_KERNEL);
1899 if (buf == NULL) {
1900 ret = -ENOMEM;
1901 goto exit;
1902 }
1903 memcpy(buf, pie, ielen);
1904
1905 /* dump */
1906 DBG_8723A("set wpa_ie(length:%zu):\n", ielen);
1907 for (i = 0; i < ielen; i = i + 8)
1908 DBG_8723A("0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n",
1909 buf[i], buf[i + 1],
1910 buf[i + 2], buf[i + 3], buf[i + 4],
1911 buf[i + 5], buf[i + 6], buf[i + 7]);
1912 pos = buf;
1913 if (ielen < RSN_HEADER_LEN) {
1914 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_err_,
1915 ("Ie len too short %d\n", (int)ielen));
1916 ret = -1;
1917 goto exit;
1918 }
1919
1920 pwpa = rtw_get_wpa_ie23a(buf, &wpa_ielen, ielen);
1921 if (pwpa && wpa_ielen > 0) {
1922 if (rtw_parse_wpa_ie23a(pwpa, wpa_ielen + 2, &group_cipher,
1923 &pairwise_cipher, NULL) == _SUCCESS) {
1924 padapter->securitypriv.dot11AuthAlgrthm =
1925 dot11AuthAlgrthm_8021X;
1926 padapter->securitypriv.ndisauthtype =
1927 Ndis802_11AuthModeWPAPSK;
1928 memcpy(padapter->securitypriv.supplicant_ie, &pwpa[0],
1929 wpa_ielen + 2);
1930
1931 DBG_8723A("got wpa_ie, wpa_ielen:%u\n", wpa_ielen);
1932 }
1933 }
1934
1935 pwpa2 = rtw_get_wpa2_ie23a(buf, &wpa2_ielen, ielen);
1936 if (pwpa2 && wpa2_ielen > 0) {
1937 if (rtw_parse_wpa2_ie23a (pwpa2, wpa2_ielen + 2, &group_cipher,
1938 &pairwise_cipher, NULL) == _SUCCESS) {
1939 padapter->securitypriv.dot11AuthAlgrthm =
1940 dot11AuthAlgrthm_8021X;
1941 padapter->securitypriv.ndisauthtype =
1942 Ndis802_11AuthModeWPA2PSK;
1943 memcpy(padapter->securitypriv.supplicant_ie, &pwpa2[0],
1944 wpa2_ielen + 2);
1945
1946 DBG_8723A("got wpa2_ie, wpa2_ielen:%u\n", wpa2_ielen);
1947 }
1948 }
1949
1950 if (group_cipher == 0) {
1951 group_cipher = WPA_CIPHER_NONE;
1952 }
1953 if (pairwise_cipher == 0) {
1954 pairwise_cipher = WPA_CIPHER_NONE;
1955 }
1956
1957 switch (group_cipher) {
1958 case WPA_CIPHER_NONE:
1959 padapter->securitypriv.dot118021XGrpPrivacy = _NO_PRIVACY_;
1960 padapter->securitypriv.ndisencryptstatus =
1961 Ndis802_11EncryptionDisabled;
1962 break;
1963 case WPA_CIPHER_WEP40:
1964 padapter->securitypriv.dot118021XGrpPrivacy = _WEP40_;
1965 padapter->securitypriv.ndisencryptstatus =
1966 Ndis802_11Encryption1Enabled;
1967 break;
1968 case WPA_CIPHER_TKIP:
1969 padapter->securitypriv.dot118021XGrpPrivacy = _TKIP_;
1970 padapter->securitypriv.ndisencryptstatus =
1971 Ndis802_11Encryption2Enabled;
1972 break;
1973 case WPA_CIPHER_CCMP:
1974 padapter->securitypriv.dot118021XGrpPrivacy = _AES_;
1975 padapter->securitypriv.ndisencryptstatus =
1976 Ndis802_11Encryption3Enabled;
1977 break;
1978 case WPA_CIPHER_WEP104:
1979 padapter->securitypriv.dot118021XGrpPrivacy = _WEP104_;
1980 padapter->securitypriv.ndisencryptstatus =
1981 Ndis802_11Encryption1Enabled;
1982 break;
1983 }
1984
1985 switch (pairwise_cipher) {
1986 case WPA_CIPHER_NONE:
1987 padapter->securitypriv.dot11PrivacyAlgrthm = _NO_PRIVACY_;
1988 padapter->securitypriv.ndisencryptstatus =
1989 Ndis802_11EncryptionDisabled;
1990 break;
1991 case WPA_CIPHER_WEP40:
1992 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP40_;
1993 padapter->securitypriv.ndisencryptstatus =
1994 Ndis802_11Encryption1Enabled;
1995 break;
1996 case WPA_CIPHER_TKIP:
1997 padapter->securitypriv.dot11PrivacyAlgrthm = _TKIP_;
1998 padapter->securitypriv.ndisencryptstatus =
1999 Ndis802_11Encryption2Enabled;
2000 break;
2001 case WPA_CIPHER_CCMP:
2002 padapter->securitypriv.dot11PrivacyAlgrthm = _AES_;
2003 padapter->securitypriv.ndisencryptstatus =
2004 Ndis802_11Encryption3Enabled;
2005 break;
2006 case WPA_CIPHER_WEP104:
2007 padapter->securitypriv.dot11PrivacyAlgrthm = _WEP104_;
2008 padapter->securitypriv.ndisencryptstatus =
2009 Ndis802_11Encryption1Enabled;
2010 break;
2011 }
2012
2013 { /* handle wps_ie */
2014 uint wps_ielen;
2015 u8 *wps_ie;
2016
2017 wps_ie = rtw_get_wps_ie23a(buf, ielen, NULL, &wps_ielen);
2018 if (wps_ie && wps_ielen > 0) {
2019 DBG_8723A("got wps_ie, wps_ielen:%u\n", wps_ielen);
2020 padapter->securitypriv.wps_ie_len =
2021 wps_ielen <
2022 MAX_WPS_IE_LEN ? wps_ielen : MAX_WPS_IE_LEN;
2023 memcpy(padapter->securitypriv.wps_ie, wps_ie,
2024 padapter->securitypriv.wps_ie_len);
2025 set_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS);
2026 } else {
2027 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
2028 }
2029 }
2030
2031#ifdef CONFIG_8723AU_P2P
2032 { /* check p2p_ie for assoc req; */
2033 uint p2p_ielen = 0;
2034 u8 *p2p_ie;
2035 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2036
2037 p2p_ie = rtw_get_p2p_ie23a(buf, ielen, NULL, &p2p_ielen);
2038 if (p2p_ie) {
2039#ifdef CONFIG_DEBUG_CFG80211
2040 DBG_8723A("%s p2p_assoc_req_ielen =%d\n", __func__,
2041 p2p_ielen);
2042#endif
2043
2044 if (pmlmepriv->p2p_assoc_req_ie) {
2045 pmlmepriv->p2p_assoc_req_ie_len = 0;
2046 kfree(pmlmepriv->p2p_assoc_req_ie);
2047 pmlmepriv->p2p_assoc_req_ie = NULL;
2048 }
2049
2050 pmlmepriv->p2p_assoc_req_ie =
2051 kmalloc(p2p_ielen, GFP_KERNEL);
2052 if (pmlmepriv->p2p_assoc_req_ie == NULL) {
2053 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
2054 __func__, __LINE__);
2055 goto exit;
2056 }
2057 memcpy(pmlmepriv->p2p_assoc_req_ie, p2p_ie, p2p_ielen);
2058 pmlmepriv->p2p_assoc_req_ie_len = p2p_ielen;
2059 }
2060 }
2061#endif /* CONFIG_8723AU_P2P */
2062
2063#ifdef CONFIG_8723AU_P2P
2064 { /* check wfd_ie for assoc req; */
2065 uint wfd_ielen = 0;
2066 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2067
2068 if (rtw_get_wfd_ie(buf, ielen, NULL, &wfd_ielen)) {
2069#ifdef CONFIG_DEBUG_CFG80211
2070 DBG_8723A("%s wfd_assoc_req_ielen =%d\n", __func__,
2071 wfd_ielen);
2072#endif
2073
2074 if (pmlmepriv->wfd_assoc_req_ie) {
2075 pmlmepriv->wfd_assoc_req_ie_len = 0;
2076 kfree(pmlmepriv->wfd_assoc_req_ie);
2077 pmlmepriv->wfd_assoc_req_ie = NULL;
2078 }
2079
2080 pmlmepriv->wfd_assoc_req_ie =
2081 kmalloc(wfd_ielen, GFP_KERNEL);
2082 if (pmlmepriv->wfd_assoc_req_ie == NULL) {
2083 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
2084 __func__, __LINE__);
2085 goto exit;
2086 }
2087 rtw_get_wfd_ie(buf, ielen, pmlmepriv->wfd_assoc_req_ie,
2088 &pmlmepriv->wfd_assoc_req_ie_len);
2089 }
2090 }
2091#endif /* CONFIG_8723AU_P2P */
2092
2093 /* TKIP and AES disallow multicast packets until installing group key */
2094 if (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_ ||
2095 padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_WTMIC_ ||
2096 padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
2097 /* WPS open need to enable multicast */
2098 /* check_fwstate(&padapter->mlmepriv, WIFI_UNDER_WPS) == true)*/
2099 rtw_hal_set_hwreg23a(padapter, HW_VAR_OFF_RCR_AM, null_addr);
2100
2101 RT_TRACE(_module_rtl871x_ioctl_os_c, _drv_info_,
2102 ("rtw_set_wpa_ie: pairwise_cipher = 0x%08x padapter->"
2103 "securitypriv.ndisencryptstatus =%d padapter->"
2104 "securitypriv.ndisauthtype =%d\n", pairwise_cipher,
2105 padapter->securitypriv.ndisencryptstatus,
2106 padapter->securitypriv.ndisauthtype));
2107
2108exit:
2109 kfree(buf);
2110 if (ret)
2111 _clr_fwstate_(&padapter->mlmepriv, WIFI_UNDER_WPS);
2112 return ret;
2113}
2114
2115static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev,
2116 struct cfg80211_connect_params *sme)
2117{
2118 int ret = 0;
2119 struct list_head *phead, *plist, *ptmp;
2120 struct wlan_network *pnetwork = NULL;
2121 enum ndis_802_11_auth_mode authmode;
2122 struct cfg80211_ssid ndis_ssid;
2123 u8 *dst_ssid;
2124 u8 *src_ssid;
2125 u8 *dst_bssid;
2126 const u8 *src_bssid;
2127 /* u8 matched_by_bssid = false; */
2128 /* u8 matched_by_ssid = false; */
2129 u8 matched = false;
2130 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2131 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2132 struct security_priv *psecuritypriv = &padapter->securitypriv;
2133 struct rtw_queue *queue = &pmlmepriv->scanned_queue;
2134
2135 DBG_8723A("=>" FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
2136 DBG_8723A("privacy =%d, key =%p, key_len =%d, key_idx =%d\n",
2137 sme->privacy, sme->key, sme->key_len, sme->key_idx);
2138
2139 if (wdev_to_priv(padapter->rtw_wdev)->block) {
2140 ret = -EBUSY;
2141 DBG_8723A("%s wdev_priv.block is set\n", __func__);
2142 goto exit;
2143 }
2144
2145 if (_FAIL == rtw_pwr_wakeup(padapter)) {
2146 ret = -EPERM;
2147 goto exit;
2148 }
2149
2150 if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
2151 ret = -EPERM;
2152 goto exit;
2153 }
2154
2155 if (!sme->ssid || !sme->ssid_len) {
2156 ret = -EINVAL;
2157 goto exit;
2158 }
2159
2160 if (sme->ssid_len > IW_ESSID_MAX_SIZE) {
2161 ret = -E2BIG;
2162 goto exit;
2163 }
2164
2165 memset(&ndis_ssid, 0, sizeof(struct cfg80211_ssid));
2166 ndis_ssid.ssid_len = sme->ssid_len;
2167 memcpy(ndis_ssid.ssid, sme->ssid, sme->ssid_len);
2168
2169 DBG_8723A("ssid =%s, len =%zu\n", ndis_ssid.ssid, sme->ssid_len);
2170
2171 if (sme->bssid)
2172 DBG_8723A("bssid =" MAC_FMT "\n", MAC_ARG(sme->bssid));
2173
2174 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
2175 ret = -EBUSY;
2176 DBG_8723A("%s, fw_state = 0x%x, goto exit\n", __func__,
2177 pmlmepriv->fw_state);
2178 goto exit;
2179 }
2180 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
2181 rtw_scan_abort23a(padapter);
2182 }
2183
2184 spin_lock_bh(&queue->lock);
2185
2186 phead = get_list_head(queue);
2187
2188 list_for_each_safe(plist, ptmp, phead) {
2189 pnetwork = container_of(plist, struct wlan_network, list);
2190
2191 dst_ssid = pnetwork->network.Ssid.ssid;
2192 dst_bssid = pnetwork->network.MacAddress;
2193
2194 if (sme->bssid) {
2195 if (memcmp(pnetwork->network.MacAddress,
2196 sme->bssid, ETH_ALEN))
2197 continue;
2198 }
2199
2200 if (sme->ssid && sme->ssid_len) {
2201 if (pnetwork->network.Ssid.ssid_len != sme->ssid_len ||
2202 memcmp(pnetwork->network.Ssid.ssid, sme->ssid,
2203 sme->ssid_len))
2204 continue;
2205 }
2206
2207 if (sme->bssid) {
2208 src_bssid = sme->bssid;
2209
2210 if ((!memcmp(dst_bssid, src_bssid, ETH_ALEN))) {
2211 DBG_8723A("matched by bssid\n");
2212
2213 ndis_ssid.ssid_len =
2214 pnetwork->network.Ssid.ssid_len;
2215 memcpy(ndis_ssid.ssid,
2216 pnetwork->network.Ssid.ssid,
2217 pnetwork->network.Ssid.ssid_len);
2218
2219 matched = true;
2220 break;
2221 }
2222
2223 } else if (sme->ssid && sme->ssid_len) {
2224 src_ssid = ndis_ssid.ssid;
2225
2226 if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.ssid_len)) &&
2227 (pnetwork->network.Ssid.ssid_len ==
2228 ndis_ssid.ssid_len)) {
2229 DBG_8723A("matched by ssid\n");
2230 matched = true;
2231 break;
2232 }
2233 }
2234 }
2235
2236 spin_unlock_bh(&queue->lock);
2237
2238 if (!matched || (pnetwork == NULL)) {
2239 ret = -ENOENT;
2240 DBG_8723A("connect, matched == false, goto exit\n");
2241 goto exit;
2242 }
2243
2244 if (rtw_set_802_11_infrastructure_mode23a
2245 (padapter, pnetwork->network.InfrastructureMode) == false) {
2246 ret = -EPERM;
2247 goto exit;
2248 }
2249
2250 psecuritypriv->ndisencryptstatus = Ndis802_11EncryptionDisabled;
2251 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
2252 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
2253 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
2254 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
2255
2256 ret =
2257 rtw_cfg80211_set_wpa_version(psecuritypriv,
2258 sme->crypto.wpa_versions);
2259 if (ret < 0)
2260 goto exit;
2261
2262 ret = rtw_cfg80211_set_auth_type(psecuritypriv, sme->auth_type);
2263
2264 if (ret < 0)
2265 goto exit;
2266
2267 DBG_8723A("%s, ie_len =%zu\n", __func__, sme->ie_len);
2268
2269 ret = rtw_cfg80211_set_wpa_ie(padapter, sme->ie, sme->ie_len);
2270 if (ret < 0)
2271 goto exit;
2272
2273 if (sme->crypto.n_ciphers_pairwise) {
2274 ret = rtw_cfg80211_set_cipher(psecuritypriv,
2275 sme->crypto.ciphers_pairwise[0],
2276 true);
2277 if (ret < 0)
2278 goto exit;
2279 }
2280
2281 /* For WEP Shared auth */
2282 if ((psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Shared ||
2283 psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_Auto) &&
2284 sme->key) {
2285 u32 wep_key_idx, wep_key_len, wep_total_len;
2286 struct ndis_802_11_wep *pwep = NULL;
2287 DBG_8723A("%s(): Shared/Auto WEP\n", __func__);
2288
2289 wep_key_idx = sme->key_idx;
2290 wep_key_len = sme->key_len;
2291
2292 if (sme->key_idx > WEP_KEYS) {
2293 ret = -EINVAL;
2294 goto exit;
2295 }
2296
2297 if (wep_key_len > 0) {
2298 wep_key_len = wep_key_len <= 5 ? 5 : 13;
2299 wep_total_len =
2300 wep_key_len +
2301 offsetof(struct ndis_802_11_wep, KeyMaterial);
2302 pwep = (struct ndis_802_11_wep *)kmalloc(wep_total_len,
2303 GFP_KERNEL);
2304 if (pwep == NULL) {
2305 DBG_8723A(" wpa_set_encryption: pwep "
2306 "allocate fail !!!\n");
2307 ret = -ENOMEM;
2308 goto exit;
2309 }
2310
2311 memset(pwep, 0, wep_total_len);
2312
2313 pwep->KeyLength = wep_key_len;
2314 pwep->Length = wep_total_len;
2315
2316 if (wep_key_len == 13) {
2317 padapter->securitypriv.dot11PrivacyAlgrthm =
2318 _WEP104_;
2319 padapter->securitypriv.dot118021XGrpPrivacy =
2320 _WEP104_;
2321 }
2322 } else {
2323 ret = -EINVAL;
2324 goto exit;
2325 }
2326
2327 pwep->KeyIndex = wep_key_idx;
2328 pwep->KeyIndex |= 0x80000000;
2329
2330 memcpy(pwep->KeyMaterial, (void *)sme->key, pwep->KeyLength);
2331
2332 if (rtw_set_802_11_add_wep23a(padapter, pwep) == (u8) _FAIL) {
2333 ret = -EOPNOTSUPP;
2334 }
2335
2336 kfree(pwep);
2337
2338 if (ret < 0)
2339 goto exit;
2340 }
2341
2342 ret = rtw_cfg80211_set_cipher(psecuritypriv,
2343 sme->crypto.cipher_group, false);
2344 if (ret < 0)
2345 return ret;
2346
2347 if (sme->crypto.n_akm_suites) {
2348 ret = rtw_cfg80211_set_key_mgt(psecuritypriv,
2349 sme->crypto.akm_suites[0]);
2350 if (ret < 0)
2351 goto exit;
2352 }
2353
2354 authmode = psecuritypriv->ndisauthtype;
2355 rtw_set_802_11_authentication_mode23a(padapter, authmode);
2356
2357 /* rtw_set_802_11_encryption_mode(padapter,
2358 padapter->securitypriv.ndisencryptstatus); */
2359
2360 if (rtw_set_802_11_ssid23a(padapter, &ndis_ssid) == false) {
2361 ret = -1;
2362 goto exit;
2363 }
2364
2365 DBG_8723A("set ssid:dot11AuthAlgrthm =%d, dot11PrivacyAlgrthm =%d, "
2366 "dot118021XGrpPrivacy =%d\n", psecuritypriv->dot11AuthAlgrthm,
2367 psecuritypriv->dot11PrivacyAlgrthm,
2368 psecuritypriv->dot118021XGrpPrivacy);
2369
2370exit:
2371
2372 DBG_8723A("<=%s, ret %d\n", __func__, ret);
2373
2374 return ret;
2375}
2376
2377static int cfg80211_rtw_disconnect(struct wiphy *wiphy, struct net_device *ndev,
2378 u16 reason_code)
2379{
2380 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2381
2382 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
2383
2384 rtw_set_roaming(padapter, 0);
2385
2386 if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
2387 rtw_scan_abort23a(padapter);
2388 LeaveAllPowerSaveMode23a(padapter);
2389 rtw_disassoc_cmd23a(padapter, 500, false);
2390
2391 DBG_8723A("%s...call rtw_indicate_disconnect23a\n", __func__);
2392
2393 padapter->mlmepriv.not_indic_disco = true;
2394 rtw_indicate_disconnect23a(padapter);
2395 padapter->mlmepriv.not_indic_disco = false;
2396
2397 rtw_free_assoc_resources23a(padapter, 1);
2398 }
2399
2400 return 0;
2401}
2402
2403static int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
2404 struct wireless_dev *wdev,
2405 enum nl80211_tx_power_setting type, int mbm)
2406{
2407 DBG_8723A("%s\n", __func__);
2408 return 0;
2409}
2410
2411static int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
2412 struct wireless_dev *wdev, int *dbm)
2413{
2414 DBG_8723A("%s\n", __func__);
2415 *dbm = (12);
2416 return 0;
2417}
2418
2419inline bool rtw_cfg80211_pwr_mgmt(struct rtw_adapter *adapter)
2420{
2421 struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(adapter->rtw_wdev);
2422 return rtw_wdev_priv->power_mgmt;
2423}
2424
2425static int cfg80211_rtw_set_power_mgmt(struct wiphy *wiphy,
2426 struct net_device *ndev,
2427 bool enabled, int timeout)
2428{
2429 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2430 struct rtw_wdev_priv *rtw_wdev_priv = wdev_to_priv(padapter->rtw_wdev);
2431
2432 DBG_8723A(FUNC_NDEV_FMT " enabled:%u, timeout:%d\n",
2433 FUNC_NDEV_ARG(ndev), enabled, timeout);
2434
2435 rtw_wdev_priv->power_mgmt = enabled;
2436
2437 if (!enabled)
2438 LPS_Leave23a(padapter);
2439
2440 return 0;
2441}
2442
2443static int cfg80211_rtw_set_pmksa(struct wiphy *wiphy,
2444 struct net_device *netdev,
2445 struct cfg80211_pmksa *pmksa)
2446{
2447 u8 index, blInserted = false;
2448 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2449 struct security_priv *psecuritypriv = &padapter->securitypriv;
2450 u8 strZeroMacAddress[ETH_ALEN] = { 0x00 };
2451
2452 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(netdev));
2453
2454 if (!memcmp(pmksa->bssid, strZeroMacAddress, ETH_ALEN)) {
2455 return -EINVAL;
2456 }
2457
2458 blInserted = false;
2459
2460 /* overwrite PMKID */
2461 for (index = 0; index < NUM_PMKID_CACHE; index++) {
2462 if (!memcmp(psecuritypriv->PMKIDList[index].Bssid,
2463 pmksa->bssid, ETH_ALEN)) {
2464 /* BSSID is matched, the same AP => rewrite with
2465 new PMKID. */
2466 DBG_8723A(FUNC_NDEV_FMT
2467 " BSSID exists in the PMKList.\n",
2468 FUNC_NDEV_ARG(netdev));
2469
2470 memcpy(psecuritypriv->PMKIDList[index].PMKID,
2471 pmksa->pmkid, WLAN_PMKID_LEN);
2472 psecuritypriv->PMKIDList[index].bUsed = true;
2473 psecuritypriv->PMKIDIndex = index + 1;
2474 blInserted = true;
2475 break;
2476 }
2477 }
2478
2479 if (!blInserted) {
2480 /* Find a new entry */
2481 DBG_8723A(FUNC_NDEV_FMT
2482 " Use the new entry index = %d for this PMKID.\n",
2483 FUNC_NDEV_ARG(netdev), psecuritypriv->PMKIDIndex);
2484
2485 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2486 Bssid, pmksa->bssid, ETH_ALEN);
2487 memcpy(psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].
2488 PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2489
2490 psecuritypriv->PMKIDList[psecuritypriv->PMKIDIndex].bUsed =
2491 true;
2492 psecuritypriv->PMKIDIndex++;
2493 if (psecuritypriv->PMKIDIndex == 16) {
2494 psecuritypriv->PMKIDIndex = 0;
2495 }
2496 }
2497
2498 return 0;
2499}
2500
2501static int cfg80211_rtw_del_pmksa(struct wiphy *wiphy,
2502 struct net_device *netdev,
2503 struct cfg80211_pmksa *pmksa)
2504{
2505 u8 index, bMatched = false;
2506 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2507 struct security_priv *psecuritypriv = &padapter->securitypriv;
2508
2509 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(netdev));
2510
2511 for (index = 0; index < NUM_PMKID_CACHE; index++) {
2512 if (!memcmp(psecuritypriv->PMKIDList[index].Bssid,
2513 pmksa->bssid, ETH_ALEN)) {
2514 /* BSSID is matched, the same AP => Remove this PMKID information and reset it. */
2515 memset(psecuritypriv->PMKIDList[index].Bssid, 0x00,
2516 ETH_ALEN);
2517 memset(psecuritypriv->PMKIDList[index].PMKID, 0x00,
2518 WLAN_PMKID_LEN);
2519 psecuritypriv->PMKIDList[index].bUsed = false;
2520 bMatched = true;
2521 break;
2522 }
2523 }
2524
2525 if (false == bMatched) {
2526 DBG_8723A(FUNC_NDEV_FMT " do not have matched BSSID\n",
2527 FUNC_NDEV_ARG(netdev));
2528 return -EINVAL;
2529 }
2530
2531 return 0;
2532}
2533
2534static int cfg80211_rtw_flush_pmksa(struct wiphy *wiphy,
2535 struct net_device *netdev)
2536{
2537 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2538 struct security_priv *psecuritypriv = &padapter->securitypriv;
2539
2540 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(netdev));
2541
2542 memset(&psecuritypriv->PMKIDList[0], 0x00,
2543 sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
2544 psecuritypriv->PMKIDIndex = 0;
2545
2546 return 0;
2547}
2548
2549#ifdef CONFIG_8723AU_AP_MODE
2550void rtw_cfg80211_indicate_sta_assoc(struct rtw_adapter *padapter,
2551 u8 *pmgmt_frame, uint frame_len)
2552{
2553 s32 freq;
2554 int channel;
2555 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2556 struct net_device *ndev = padapter->pnetdev;
2557
2558 DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2559
2560#if defined(RTW_USE_CFG80211_STA_EVENT)
2561 {
2562 struct station_info sinfo;
2563 u8 ie_offset;
2564 if (ieee80211_is_assoc_req(hdr->frame_control))
2565 ie_offset = _ASOCREQ_IE_OFFSET_;
2566 else /* WIFI_REASSOCREQ */
2567 ie_offset = _REASOCREQ_IE_OFFSET_;
2568
2569 sinfo.filled = 0;
2570 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
2571 sinfo.assoc_req_ies = pmgmt_frame + WLAN_HDR_A3_LEN + ie_offset;
2572 sinfo.assoc_req_ies_len =
2573 frame_len - WLAN_HDR_A3_LEN - ie_offset;
2574 cfg80211_new_sta(ndev, hdr->addr2, &sinfo, GFP_ATOMIC);
2575 }
2576#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2577 channel = pmlmeext->cur_channel;
2578 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2579 freq = ieee80211_channel_to_frequency(channel,
2580 IEEE80211_BAND_2GHZ);
2581 else
2582 freq = ieee80211_channel_to_frequency(channel,
2583 IEEE80211_BAND_5GHZ);
2584
2585 rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len,
2586 GFP_ATOMIC);
2587#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2588}
2589
2590void rtw_cfg80211_indicate_sta_disassoc(struct rtw_adapter *padapter,
2591 unsigned char *da,
2592 unsigned short reason)
2593{
2594 s32 freq;
2595 int channel;
2596 u8 *pmgmt_frame;
2597 uint frame_len;
2598 struct ieee80211_hdr *pwlanhdr;
2599 unsigned short *fctrl;
2600 u8 mgmt_buf[128] = { 0 };
2601 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2602 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2603 struct net_device *ndev = padapter->pnetdev;
2604
2605 DBG_8723A("%s(padapter =%p,%s)\n", __func__, padapter, ndev->name);
2606
2607#if defined(RTW_USE_CFG80211_STA_EVENT)
2608 cfg80211_del_sta(ndev, da, GFP_ATOMIC);
2609#else /* defined(RTW_USE_CFG80211_STA_EVENT) */
2610 channel = pmlmeext->cur_channel;
2611 if (channel <= RTW_CH_MAX_2G_CHANNEL)
2612 freq = ieee80211_channel_to_frequency(channel,
2613 IEEE80211_BAND_2GHZ);
2614 else
2615 freq = ieee80211_channel_to_frequency(channel,
2616 IEEE80211_BAND_5GHZ);
2617
2618 pmgmt_frame = mgmt_buf;
2619 pwlanhdr = (struct ieee80211_hdr *)pmgmt_frame;
2620
2621 fctrl = &pwlanhdr->frame_control;
2622 *(fctrl) = 0;
2623
2624 memcpy(pwlanhdr->addr1, myid(&padapter->eeprompriv), ETH_ALEN);
2625 memcpy(pwlanhdr->addr2, da, ETH_ALEN);
2626 memcpy(pwlanhdr->addr3, get_my_bssid23a(&pmlmeinfo->network), ETH_ALEN);
2627
2628 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2629 pmlmeext->mgnt_seq++;
2630 SetFrameSubType(pmgmt_frame, WIFI_DEAUTH);
2631
2632 pmgmt_frame += sizeof(struct ieee80211_hdr_3addr);
2633 frame_len = sizeof(struct ieee80211_hdr_3addr);
2634
2635 reason = cpu_to_le16(reason);
2636 pmgmt_frame = rtw_set_fixed_ie23a(pmgmt_frame,
2637 WLAN_REASON_PREV_AUTH_NOT_VALID,
2638 (unsigned char *)&reason, &frame_len);
2639
2640 rtw_cfg80211_rx_mgmt(padapter, freq, 0, mgmt_buf, frame_len,
2641 GFP_ATOMIC);
2642#endif /* defined(RTW_USE_CFG80211_STA_EVENT) */
2643}
2644
2645static int rtw_cfg80211_monitor_if_open(struct net_device *ndev)
2646{
2647 int ret = 0;
2648
2649 DBG_8723A("%s\n", __func__);
2650
2651 return ret;
2652}
2653
2654static int rtw_cfg80211_monitor_if_close(struct net_device *ndev)
2655{
2656 int ret = 0;
2657
2658 DBG_8723A("%s\n", __func__);
2659
2660 return ret;
2661}
2662
2663static int rtw_cfg80211_monitor_if_xmit_entry(struct sk_buff *skb,
2664 struct net_device *ndev)
2665{
2666 int ret = 0;
2667 int rtap_len;
2668 int qos_len = 0;
2669 int dot11_hdr_len = 24;
2670 int snap_len = 6;
2671 unsigned char *pdata;
2672 unsigned char src_mac_addr[6];
2673 unsigned char dst_mac_addr[6];
2674 struct ieee80211_hdr *dot11_hdr;
2675 struct ieee80211_radiotap_header *rtap_hdr;
2676 struct rtw_adapter *padapter = netdev_priv(ndev);
2677
2678 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
2679
2680 if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
2681 goto fail;
2682
2683 rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
2684 if (unlikely(rtap_hdr->it_version))
2685 goto fail;
2686
2687 rtap_len = ieee80211_get_radiotap_len(skb->data);
2688 if (unlikely(skb->len < rtap_len))
2689 goto fail;
2690
2691 if (rtap_len != 14) {
2692 DBG_8723A("radiotap len (should be 14): %d\n", rtap_len);
2693 goto fail;
2694 }
2695
2696 /* Skip the ratio tap header */
2697 skb_pull(skb, rtap_len);
2698
2699 dot11_hdr = (struct ieee80211_hdr *)skb->data;
2700 /* Check if the QoS bit is set */
2701 if (ieee80211_is_data(dot11_hdr->frame_control)) {
2702 /* Check if this ia a Wireless Distribution System (WDS) frame
2703 * which has 4 MAC addresses
2704 */
2705 if (ieee80211_is_data_qos(dot11_hdr->frame_control))
2706 qos_len = IEEE80211_QOS_CTL_LEN;
2707 if (ieee80211_has_a4(dot11_hdr->frame_control))
2708 dot11_hdr_len += 6;
2709
2710 memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
2711 memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
2712
2713 /*
2714 * Skip the 802.11 header, QoS (if any) and SNAP,
2715 * but leave spaces for two MAC addresses
2716 */
2717 skb_pull(skb, dot11_hdr_len + qos_len + snap_len -
2718 ETH_ALEN * 2);
2719 pdata = (unsigned char *)skb->data;
2720 memcpy(pdata, dst_mac_addr, ETH_ALEN);
2721 memcpy(pdata + ETH_ALEN, src_mac_addr, ETH_ALEN);
2722
2723 DBG_8723A("should be eapol packet\n");
2724
2725 /* Use the real net device to transmit the packet */
2726 ret = rtw_xmit23a_entry23a(skb, padapter->pnetdev);
2727
2728 return ret;
2729
2730 } else if (ieee80211_is_action(dot11_hdr->frame_control)) {
2731 /* only for action frames */
2732 struct xmit_frame *pmgntframe;
2733 struct pkt_attrib *pattrib;
2734 unsigned char *pframe;
2735 /* u8 category, action, OUI_Subtype, dialogToken = 0; */
2736 /* unsigned char *frame_body; */
2737 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2738 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2739 u32 len = skb->len;
2740 u8 category, action;
2741 int type = -1;
2742
2743 if (rtw_action_frame_parse23a(skb->data, len, &category,
2744 &action) == false) {
2745 DBG_8723A(FUNC_NDEV_FMT " frame_control:0x%x\n",
2746 FUNC_NDEV_ARG(ndev),
2747 le16_to_cpu(dot11_hdr->frame_control));
2748 goto fail;
2749 }
2750
2751 DBG_8723A("RTW_Tx:da =" MAC_FMT " via " FUNC_NDEV_FMT "\n",
2752 MAC_ARG(dot11_hdr->addr1), FUNC_NDEV_ARG(ndev));
2753#ifdef CONFIG_8723AU_P2P
2754 type = rtw_p2p_check_frames(padapter, skb->data, len, true);
2755 if (type >= 0)
2756 goto dump;
2757#endif
2758 if (category == WLAN_CATEGORY_PUBLIC)
2759 DBG_8723A("RTW_Tx:%s\n", action_public_str23a(action));
2760 else
2761 DBG_8723A("RTW_Tx:category(%u), action(%u)\n", category,
2762 action);
2763dump:
2764 /* starting alloc mgmt frame to dump it */
2765 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
2766 if (pmgntframe == NULL)
2767 goto fail;
2768
2769 /* update attribute */
2770 pattrib = &pmgntframe->attrib;
2771 update_mgntframe_attrib23a(padapter, pattrib);
2772 pattrib->retry_ctrl = false;
2773
2774 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2775
2776 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2777
2778 memcpy(pframe, skb->data, len);
2779#ifdef CONFIG_8723AU_P2P
2780 if (type >= 0) {
2781 struct wifi_display_info *pwfd_info;
2782
2783 pwfd_info = padapter->wdinfo.wfd_info;
2784
2785 if (pwfd_info->wfd_enable)
2786 rtw_append_wfd_ie(padapter, pframe, &len);
2787 }
2788#endif /* CONFIG_8723AU_P2P */
2789 pattrib->pktlen = len;
2790
2791 /* update seq number */
2792 pmlmeext->mgnt_seq = le16_to_cpu(dot11_hdr->seq_ctrl) >> 4;
2793 pattrib->seqnum = pmlmeext->mgnt_seq;
2794 pmlmeext->mgnt_seq++;
2795
2796 pattrib->last_txcmdsz = pattrib->pktlen;
2797
2798 dump_mgntframe23a(padapter, pmgntframe);
2799 }
2800
2801fail:
2802
2803 dev_kfree_skb(skb);
2804
2805 return 0;
2806}
2807
2808static int
2809rtw_cfg80211_monitor_if_set_mac_address(struct net_device *ndev, void *addr)
2810{
2811 int ret = 0;
2812
2813 DBG_8723A("%s\n", __func__);
2814
2815 return ret;
2816}
2817
2818static const struct net_device_ops rtw_cfg80211_monitor_if_ops = {
2819 .ndo_open = rtw_cfg80211_monitor_if_open,
2820 .ndo_stop = rtw_cfg80211_monitor_if_close,
2821 .ndo_start_xmit = rtw_cfg80211_monitor_if_xmit_entry,
2822 .ndo_set_mac_address = rtw_cfg80211_monitor_if_set_mac_address,
2823};
2824
2825static int rtw_cfg80211_add_monitor_if(struct rtw_adapter *padapter, char *name,
2826 struct net_device **ndev)
2827{
2828 int ret = 0;
2829 struct net_device *mon_ndev = NULL;
2830 struct wireless_dev *mon_wdev = NULL;
2831 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
2832
2833 if (!name) {
2834 DBG_8723A(FUNC_ADPT_FMT " without specific name\n",
2835 FUNC_ADPT_ARG(padapter));
2836 ret = -EINVAL;
2837 goto out;
2838 }
2839
2840 if (pwdev_priv->pmon_ndev) {
2841 DBG_8723A(FUNC_ADPT_FMT " monitor interface exist: " NDEV_FMT
2842 "\n", FUNC_ADPT_ARG(padapter),
2843 NDEV_ARG(pwdev_priv->pmon_ndev));
2844 ret = -EBUSY;
2845 goto out;
2846 }
2847
2848 mon_ndev = alloc_etherdev(sizeof(struct rtw_adapter));
2849 if (!mon_ndev) {
2850 DBG_8723A(FUNC_ADPT_FMT " allocate ndev fail\n",
2851 FUNC_ADPT_ARG(padapter));
2852 ret = -ENOMEM;
2853 goto out;
2854 }
2855
2856 mon_ndev->type = ARPHRD_IEEE80211_RADIOTAP;
2857 strncpy(mon_ndev->name, name, IFNAMSIZ);
2858 mon_ndev->name[IFNAMSIZ - 1] = 0;
2859 mon_ndev->destructor = rtw_ndev_destructor;
2860
2861 mon_ndev->netdev_ops = &rtw_cfg80211_monitor_if_ops;
2862
2863 /* wdev */
2864 mon_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
2865 if (!mon_wdev) {
2866 DBG_8723A(FUNC_ADPT_FMT " allocate mon_wdev fail\n",
2867 FUNC_ADPT_ARG(padapter));
2868 ret = -ENOMEM;
2869 goto out;
2870 }
2871
2872 mon_wdev->wiphy = padapter->rtw_wdev->wiphy;
2873 mon_wdev->netdev = mon_ndev;
2874 mon_wdev->iftype = NL80211_IFTYPE_MONITOR;
2875 mon_ndev->ieee80211_ptr = mon_wdev;
2876
2877 ret = register_netdevice(mon_ndev);
2878 if (ret) {
2879 goto out;
2880 }
2881
2882 *ndev = pwdev_priv->pmon_ndev = mon_ndev;
2883 memcpy(pwdev_priv->ifname_mon, name, IFNAMSIZ + 1);
2884
2885out:
2886 if (ret) {
2887 kfree(mon_wdev);
2888 mon_wdev = NULL;
2889 }
2890
2891 if (ret && mon_ndev) {
2892 free_netdev(mon_ndev);
2893 *ndev = mon_ndev = NULL;
2894 }
2895
2896 return ret;
2897}
2898
2899static struct wireless_dev *
2900cfg80211_rtw_add_virtual_intf(struct wiphy *wiphy, const char *name,
2901 enum nl80211_iftype type, u32 *flags,
2902 struct vif_params *params)
2903{
2904 int ret = 0;
2905 struct net_device *ndev = NULL;
2906 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
2907
2908 DBG_8723A(FUNC_ADPT_FMT " wiphy:%s, name:%s, type:%d\n",
2909 FUNC_ADPT_ARG(padapter), wiphy_name(wiphy), name, type);
2910
2911 switch (type) {
2912 case NL80211_IFTYPE_ADHOC:
2913 case NL80211_IFTYPE_AP_VLAN:
2914 case NL80211_IFTYPE_WDS:
2915 case NL80211_IFTYPE_MESH_POINT:
2916 ret = -ENODEV;
2917 break;
2918 case NL80211_IFTYPE_MONITOR:
2919 ret =
2920 rtw_cfg80211_add_monitor_if(padapter, (char *)name, &ndev);
2921 break;
2922
2923 case NL80211_IFTYPE_P2P_CLIENT:
2924 case NL80211_IFTYPE_STATION:
2925 ret = -ENODEV;
2926 break;
2927
2928 case NL80211_IFTYPE_P2P_GO:
2929 case NL80211_IFTYPE_AP:
2930 ret = -ENODEV;
2931 break;
2932 default:
2933 ret = -ENODEV;
2934 DBG_8723A("Unsupported interface type\n");
2935 break;
2936 }
2937
2938 DBG_8723A(FUNC_ADPT_FMT " ndev:%p, ret:%d\n", FUNC_ADPT_ARG(padapter),
2939 ndev, ret);
2940
2941 return ndev ? ndev->ieee80211_ptr : ERR_PTR(ret);
2942}
2943
2944static int cfg80211_rtw_del_virtual_intf(struct wiphy *wiphy,
2945 struct wireless_dev *wdev)
2946{
2947 struct rtw_wdev_priv *pwdev_priv =
2948 (struct rtw_wdev_priv *)wiphy_priv(wiphy);
2949 struct net_device *ndev;
2950 ndev = wdev ? wdev->netdev : NULL;
2951
2952 if (!ndev)
2953 goto exit;
2954
2955 unregister_netdevice(ndev);
2956
2957 if (ndev == pwdev_priv->pmon_ndev) {
2958 pwdev_priv->pmon_ndev = NULL;
2959 pwdev_priv->ifname_mon[0] = '\0';
2960 DBG_8723A(FUNC_NDEV_FMT " remove monitor interface\n",
2961 FUNC_NDEV_ARG(ndev));
2962 }
2963
2964exit:
2965 return 0;
2966}
2967
2968static int rtw_add_beacon(struct rtw_adapter *adapter, const u8 *head,
2969 size_t head_len, const u8 *tail, size_t tail_len)
2970{
2971 int ret = 0;
2972 u8 *pbuf = NULL;
2973 uint len, wps_ielen = 0;
2974 uint p2p_ielen = 0;
2975 u8 got_p2p_ie = false;
2976 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2977 /* struct sta_priv *pstapriv = &padapter->stapriv; */
2978
2979 DBG_8723A("%s beacon_head_len =%zu, beacon_tail_len =%zu\n",
2980 __func__, head_len, tail_len);
2981
2982 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
2983 return -EINVAL;
2984
2985 if (head_len < 24)
2986 return -EINVAL;
2987
2988 pbuf = kzalloc(head_len + tail_len, GFP_KERNEL);
2989 if (!pbuf)
2990 return -ENOMEM;
2991 /* 24 = beacon header len. */
2992 memcpy(pbuf, (void *)head + 24, head_len - 24);
2993 memcpy(pbuf + head_len - 24, (void *)tail, tail_len);
2994
2995 len = head_len + tail_len - 24;
2996
2997 /* check wps ie if inclued */
2998 if (rtw_get_wps_ie23a
2999 (pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL,
3000 &wps_ielen))
3001 DBG_8723A("add bcn, wps_ielen =%d\n", wps_ielen);
3002
3003#ifdef CONFIG_8723AU_P2P
3004 /* check p2p ie if inclued */
3005 if (rtw_get_p2p_ie23a
3006 (pbuf + _FIXED_IE_LENGTH_, len - _FIXED_IE_LENGTH_, NULL,
3007 &p2p_ielen)) {
3008 DBG_8723A("got p2p_ie, len =%d\n", p2p_ielen);
3009 got_p2p_ie = true;
3010 }
3011#endif
3012
3013 /* pbss_network->IEs will not include p2p_ie, wfd ie */
3014 rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_,
3015 P2P_OUI23A, 4);
3016 rtw_ies_remove_ie23a(pbuf, &len, _BEACON_IE_OFFSET_, _VENDOR_SPECIFIC_IE_,
3017 WFD_OUI23A, 4);
3018
3019 if (rtw_check_beacon_data23a(adapter, pbuf, len) == _SUCCESS) {
3020#ifdef CONFIG_8723AU_P2P
3021 /* check p2p if enable */
3022 if (got_p2p_ie == true) {
3023 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
3024 struct wifidirect_info *pwdinfo = &adapter->wdinfo;
3025
3026 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3027 DBG_8723A("Enable P2P function for the first "
3028 "time\n");
3029 rtw_p2p_enable23a(adapter, P2P_ROLE_GO);
3030 wdev_to_priv(adapter->rtw_wdev)->p2p_enabled =
3031 true;
3032 } else {
3033 del_timer_sync(&pwdinfo->find_phase_timer);
3034 del_timer_sync(&pwdinfo->
3035 restore_p2p_state_timer);
3036 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
3037
3038 DBG_8723A("enter GO Mode, p2p_ielen =%d\n",
3039 p2p_ielen);
3040
3041 rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
3042 rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
3043 pwdinfo->intent = 15;
3044 }
3045
3046 pwdinfo->operating_channel = pmlmeext->cur_channel;
3047 }
3048#endif /* CONFIG_8723AU_P2P */
3049
3050 ret = 0;
3051
3052 } else {
3053 ret = -EINVAL;
3054 }
3055
3056 kfree(pbuf);
3057
3058 return ret;
3059}
3060
3061static int cfg80211_rtw_start_ap(struct wiphy *wiphy, struct net_device *ndev,
3062 struct cfg80211_ap_settings *settings)
3063{
3064 int ret = 0;
3065 struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
3066
3067 DBG_8723A(FUNC_NDEV_FMT " hidden_ssid:%d, auth_type:%d\n",
3068 FUNC_NDEV_ARG(ndev), settings->hidden_ssid,
3069 settings->auth_type);
3070
3071 ret = rtw_add_beacon(adapter, settings->beacon.head,
3072 settings->beacon.head_len, settings->beacon.tail,
3073 settings->beacon.tail_len);
3074
3075 adapter->mlmeextpriv.mlmext_info.hidden_ssid_mode =
3076 settings->hidden_ssid;
3077
3078 if (settings->ssid && settings->ssid_len) {
3079 struct wlan_bssid_ex *pbss_network =
3080 &adapter->mlmepriv.cur_network.network;
3081 struct wlan_bssid_ex *pbss_network_ext =
3082 &adapter->mlmeextpriv.mlmext_info.network;
3083
3084 if (0)
3085 DBG_8723A(FUNC_ADPT_FMT
3086 " ssid:(%s,%d), from ie:(%s,%d)\n",
3087 FUNC_ADPT_ARG(adapter), settings->ssid,
3088 (int)settings->ssid_len,
3089 pbss_network->Ssid.ssid,
3090 pbss_network->Ssid.ssid_len);
3091
3092 memcpy(pbss_network->Ssid.ssid, (void *)settings->ssid,
3093 settings->ssid_len);
3094 pbss_network->Ssid.ssid_len = settings->ssid_len;
3095 memcpy(pbss_network_ext->Ssid.ssid, (void *)settings->ssid,
3096 settings->ssid_len);
3097 pbss_network_ext->Ssid.ssid_len = settings->ssid_len;
3098
3099 if (0)
3100 DBG_8723A(FUNC_ADPT_FMT
3101 " after ssid:(%s,%d), (%s,%d)\n",
3102 FUNC_ADPT_ARG(adapter),
3103 pbss_network->Ssid.ssid,
3104 pbss_network->Ssid.ssid_len,
3105 pbss_network_ext->Ssid.ssid,
3106 pbss_network_ext->Ssid.ssid_len);
3107 }
3108
3109 return ret;
3110}
3111
3112static int cfg80211_rtw_change_beacon(struct wiphy *wiphy,
3113 struct net_device *ndev,
3114 struct cfg80211_beacon_data *info)
3115{
3116 int ret = 0;
3117 struct rtw_adapter *adapter = wiphy_to_adapter(wiphy);
3118
3119 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3120
3121 ret = rtw_add_beacon(adapter, info->head, info->head_len, info->tail,
3122 info->tail_len);
3123
3124 return ret;
3125}
3126
3127static int cfg80211_rtw_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
3128{
3129 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3130 return 0;
3131}
3132
3133static int cfg80211_rtw_add_station(struct wiphy *wiphy,
3134 struct net_device *ndev, u8 *mac,
3135 struct station_parameters *params)
3136{
3137 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3138
3139 return 0;
3140}
3141
3142static int cfg80211_rtw_del_station(struct wiphy *wiphy,
3143 struct net_device *ndev, u8 *mac)
3144{
3145 int ret = 0;
3146 struct list_head *phead, *plist, *ptmp;
3147 u8 updated = 0;
3148 struct sta_info *psta;
3149 struct rtw_adapter *padapter = netdev_priv(ndev);
3150 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3151 struct sta_priv *pstapriv = &padapter->stapriv;
3152
3153 DBG_8723A("+" FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3154
3155 if (check_fwstate(pmlmepriv, (_FW_LINKED | WIFI_AP_STATE)) != true) {
3156 DBG_8723A("%s, fw_state != FW_LINKED|WIFI_AP_STATE\n",
3157 __func__);
3158 return -EINVAL;
3159 }
3160
3161 if (!mac) {
3162 DBG_8723A("flush all sta, and cam_entry\n");
3163
3164 flush_all_cam_entry23a(padapter); /* clear CAM */
3165
3166 ret = rtw_sta_flush23a(padapter);
3167
3168 return ret;
3169 }
3170
3171 DBG_8723A("free sta macaddr =" MAC_FMT "\n", MAC_ARG(mac));
3172
3173 if (is_broadcast_ether_addr(mac))
3174 return -EINVAL;
3175
3176 spin_lock_bh(&pstapriv->asoc_list_lock);
3177
3178 phead = &pstapriv->asoc_list;
3179
3180 /* check asoc_queue */
3181 list_for_each_safe(plist, ptmp, phead) {
3182 psta = container_of(plist, struct sta_info, asoc_list);
3183
3184 if (!memcmp(mac, psta->hwaddr, ETH_ALEN)) {
3185 if (psta->dot8021xalg == 1 &&
3186 psta->bpairwise_key_installed == false) {
3187 DBG_8723A("%s, sta's dot8021xalg = 1 and "
3188 "key_installed = false\n", __func__);
3189 } else {
3190 DBG_8723A("free psta =%p, aid =%d\n", psta,
3191 psta->aid);
3192
3193 list_del_init(&psta->asoc_list);
3194 pstapriv->asoc_list_cnt--;
3195
3196 /* spin_unlock_bh(&pstapriv->asoc_list_lock); */
3197 updated =
3198 ap_free_sta23a(padapter, psta, true,
3199 WLAN_REASON_DEAUTH_LEAVING);
3200 /* spin_lock_bh(&pstapriv->asoc_list_lock); */
3201
3202 psta = NULL;
3203
3204 break;
3205 }
3206 }
3207 }
3208
3209 spin_unlock_bh(&pstapriv->asoc_list_lock);
3210
3211 associated_clients_update23a(padapter, updated);
3212
3213 DBG_8723A("-" FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3214
3215 return ret;
3216}
3217
3218static int cfg80211_rtw_change_station(struct wiphy *wiphy,
3219 struct net_device *ndev, u8 *mac,
3220 struct station_parameters *params)
3221{
3222 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3223 return 0;
3224}
3225
3226static int cfg80211_rtw_dump_station(struct wiphy *wiphy,
3227 struct net_device *ndev, int idx, u8 *mac,
3228 struct station_info *sinfo)
3229{
3230 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3231
3232 /* TODO: dump scanned queue */
3233
3234 return -ENOENT;
3235}
3236
3237static int cfg80211_rtw_change_bss(struct wiphy *wiphy, struct net_device *ndev,
3238 struct bss_parameters *params)
3239{
3240 DBG_8723A(FUNC_NDEV_FMT "\n", FUNC_NDEV_ARG(ndev));
3241 return 0;
3242}
3243#endif /* CONFIG_8723AU_AP_MODE */
3244
3245void rtw_cfg80211_rx_action_p2p(struct rtw_adapter *padapter, u8 *pmgmt_frame,
3246 uint frame_len)
3247{
3248 int type;
3249 s32 freq;
3250 int channel;
3251 u8 category, action;
3252
3253 channel = rtw_get_oper_ch23a(padapter);
3254
3255 DBG_8723A("RTW_Rx:cur_ch =%d\n", channel);
3256#ifdef CONFIG_8723AU_P2P
3257 type = rtw_p2p_check_frames(padapter, pmgmt_frame, frame_len, false);
3258 if (type >= 0)
3259 goto indicate;
3260#endif
3261 rtw_action_frame_parse23a(pmgmt_frame, frame_len, &category, &action);
3262 DBG_8723A("RTW_Rx:category(%u), action(%u)\n", category, action);
3263
3264indicate:
3265 if (channel <= RTW_CH_MAX_2G_CHANNEL)
3266 freq = ieee80211_channel_to_frequency(channel,
3267 IEEE80211_BAND_2GHZ);
3268 else
3269 freq = ieee80211_channel_to_frequency(channel,
3270 IEEE80211_BAND_5GHZ);
3271
3272 rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len,
3273 GFP_ATOMIC);
3274}
3275
3276void rtw_cfg80211_rx_p2p_action_public(struct rtw_adapter *padapter,
3277 u8 *pmgmt_frame, uint frame_len)
3278{
3279 int type;
3280 s32 freq;
3281 int channel;
3282 u8 category, action;
3283
3284 channel = rtw_get_oper_ch23a(padapter);
3285
3286 DBG_8723A("RTW_Rx:cur_ch =%d\n", channel);
3287#ifdef CONFIG_8723AU_P2P
3288 type = rtw_p2p_check_frames(padapter, pmgmt_frame, frame_len, false);
3289 if (type >= 0) {
3290 switch (type) {
3291 case P2P_GO_NEGO_CONF:
3292 case P2P_PROVISION_DISC_RESP:
3293 rtw_clear_scan_deny(padapter);
3294 }
3295 goto indicate;
3296 }
3297#endif
3298 rtw_action_frame_parse23a(pmgmt_frame, frame_len, &category, &action);
3299 DBG_8723A("RTW_Rx:category(%u), action(%u)\n", category, action);
3300
3301indicate:
3302 if (channel <= RTW_CH_MAX_2G_CHANNEL)
3303 freq = ieee80211_channel_to_frequency(channel,
3304 IEEE80211_BAND_2GHZ);
3305 else
3306 freq = ieee80211_channel_to_frequency(channel,
3307 IEEE80211_BAND_5GHZ);
3308
3309 rtw_cfg80211_rx_mgmt(padapter, freq, 0, pmgmt_frame, frame_len,
3310 GFP_ATOMIC);
3311}
3312
3313void rtw_cfg80211_rx_action(struct rtw_adapter *adapter, u8 *frame,
3314 uint frame_len, const char *msg)
3315{
3316 s32 freq;
3317 int channel;
3318 u8 category, action;
3319
3320 channel = rtw_get_oper_ch23a(adapter);
3321
3322 rtw_action_frame_parse23a(frame, frame_len, &category, &action);
3323
3324 DBG_8723A("RTW_Rx:cur_ch =%d\n", channel);
3325 if (msg)
3326 DBG_8723A("RTW_Rx:%s\n", msg);
3327 else
3328 DBG_8723A("RTW_Rx:category(%u), action(%u)\n", category,
3329 action);
3330
3331 if (channel <= RTW_CH_MAX_2G_CHANNEL)
3332 freq = ieee80211_channel_to_frequency(channel,
3333 IEEE80211_BAND_2GHZ);
3334 else
3335 freq = ieee80211_channel_to_frequency(channel,
3336 IEEE80211_BAND_5GHZ);
3337
3338 rtw_cfg80211_rx_mgmt(adapter, freq, 0, frame, frame_len, GFP_ATOMIC);
3339}
3340
3341#ifdef CONFIG_8723AU_P2P
3342void rtw_cfg80211_issue_p2p_provision_request23a(struct rtw_adapter *padapter,
3343 const u8 *buf, size_t len)
3344{
3345 u16 wps_devicepassword_id = 0x0000;
3346 uint wps_devicepassword_id_len = 0;
3347 u8 wpsie[255] = { 0x00 }, p2p_ie[255] = { 0x00 };
3348 uint p2p_ielen = 0;
3349 uint wpsielen = 0;
3350 u32 devinfo_contentlen = 0;
3351 u8 devinfo_content[64] = { 0x00 };
3352 u16 capability = 0;
3353 uint capability_len = 0;
3354
3355 unsigned char category = WLAN_CATEGORY_PUBLIC;
3356 u8 action = P2P_PUB_ACTION_ACTION;
3357 u8 dialogToken = 1;
3358 u32 p2poui = cpu_to_be32(P2POUI);
3359 u8 oui_subtype = P2P_PROVISION_DISC_REQ;
3360 u32 p2pielen = 0;
3361#ifdef CONFIG_8723AU_P2P
3362 u32 wfdielen = 0;
3363#endif /* CONFIG_8723AU_P2P */
3364
3365 struct xmit_frame *pmgntframe;
3366 struct pkt_attrib *pattrib;
3367 unsigned char *pframe;
3368 struct ieee80211_hdr *pwlanhdr, *hdr;
3369 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3370 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3371
3372 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3373 u8 *frame_body =
3374 (unsigned char *)(buf + sizeof(struct ieee80211_hdr_3addr));
3375 size_t frame_body_len = len - sizeof(struct ieee80211_hdr_3addr);
3376
3377 DBG_8723A("[%s] In\n", __func__);
3378
3379 hdr = (struct ieee80211_hdr *)buf;
3380 /* prepare for building provision_request frame */
3381 memcpy(pwdinfo->tx_prov_disc_info.peerIFAddr, hdr->addr1, ETH_ALEN);
3382 memcpy(pwdinfo->tx_prov_disc_info.peerDevAddr, hdr->addr1, ETH_ALEN);
3383
3384 pwdinfo->tx_prov_disc_info.wps_config_method_request =
3385 WPS_CM_PUSH_BUTTON;
3386
3387 rtw_get_wps_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
3388 frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, wpsie,
3389 &wpsielen);
3390 rtw_get_wps_attr_content23a(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID,
3391 (u8 *)&wps_devicepassword_id,
3392 &wps_devicepassword_id_len);
3393 wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);
3394
3395 switch (wps_devicepassword_id) {
3396 case WPS_DPID_PIN:
3397 pwdinfo->tx_prov_disc_info.wps_config_method_request =
3398 WPS_CM_LABEL;
3399 break;
3400 case WPS_DPID_USER_SPEC:
3401 pwdinfo->tx_prov_disc_info.wps_config_method_request =
3402 WPS_CM_DISPLYA;
3403 break;
3404 case WPS_DPID_MACHINE_SPEC:
3405 break;
3406 case WPS_DPID_REKEY:
3407 break;
3408 case WPS_DPID_PBC:
3409 pwdinfo->tx_prov_disc_info.wps_config_method_request =
3410 WPS_CM_PUSH_BUTTON;
3411 break;
3412 case WPS_DPID_REGISTRAR_SPEC:
3413 pwdinfo->tx_prov_disc_info.wps_config_method_request =
3414 WPS_CM_KEYPAD;
3415 break;
3416 default:
3417 break;
3418 }
3419
3420 if (rtw_get_p2p_ie23a(frame_body + _PUBLIC_ACTION_IE_OFFSET_,
3421 frame_body_len - _PUBLIC_ACTION_IE_OFFSET_,
3422 p2p_ie, &p2p_ielen)) {
3423 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
3424 P2P_ATTR_DEVICE_INFO, devinfo_content,
3425 &devinfo_contentlen);
3426 rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY,
3427 (u8 *)&capability, &capability_len);
3428 }
3429
3430 /* start to build provision_request frame */
3431 memset(wpsie, 0, sizeof(wpsie));
3432 memset(p2p_ie, 0, sizeof(p2p_ie));
3433 p2p_ielen = 0;
3434
3435 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3436 if (pmgntframe == NULL)
3437 return;
3438 /* update attribute */
3439 pattrib = &pmgntframe->attrib;
3440 update_mgntframe_attrib23a(padapter, pattrib);
3441
3442 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3443
3444 pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
3445 pwlanhdr = (struct ieee80211_hdr *)pframe;
3446
3447 pwlanhdr->frame_control = 0;
3448
3449 memcpy(pwlanhdr->addr1, pwdinfo->tx_prov_disc_info.peerDevAddr,
3450 ETH_ALEN);
3451 memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
3452 memcpy(pwlanhdr->addr3, pwdinfo->tx_prov_disc_info.peerDevAddr,
3453 ETH_ALEN);
3454
3455 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3456 pmlmeext->mgnt_seq++;
3457 SetFrameSubType(pframe, WIFI_ACTION);
3458
3459 pframe += sizeof(struct ieee80211_hdr_3addr);
3460 pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3461
3462 pframe = rtw_set_fixed_ie23a(pframe, 1, &category, &pattrib->pktlen);
3463 pframe = rtw_set_fixed_ie23a(pframe, 1, &action, &pattrib->pktlen);
3464 pframe = rtw_set_fixed_ie23a(pframe, 4, (unsigned char *)&p2poui,
3465 &pattrib->pktlen);
3466 pframe = rtw_set_fixed_ie23a(pframe, 1, &oui_subtype, &pattrib->pktlen);
3467 pframe = rtw_set_fixed_ie23a(pframe, 1, &dialogToken, &pattrib->pktlen);
3468
3469 /* build_prov_disc_request_p2p_ie23a */
3470 /* P2P OUI */
3471 p2pielen = 0;
3472 p2p_ie[p2pielen++] = 0x50;
3473 p2p_ie[p2pielen++] = 0x6F;
3474 p2p_ie[p2pielen++] = 0x9A;
3475 p2p_ie[p2pielen++] = 0x09; /* WFA P2P v1.0 */
3476
3477 /* Commented by Albert 20110301 */
3478 /* According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes */
3479 /* 1. P2P Capability */
3480 /* 2. Device Info */
3481 /* 3. Group ID ( When joining an operating P2P Group ) */
3482
3483 /* P2P Capability ATTR */
3484 /* Type: */
3485 p2p_ie[p2pielen++] = P2P_ATTR_CAPABILITY;
3486
3487 /* Length: */
3488 RTW_PUT_LE16(p2p_ie + p2pielen, 0x0002);
3489 p2pielen += 2;
3490
3491 /* Value: */
3492 /* Device Capability Bitmap, 1 byte */
3493 /* Group Capability Bitmap, 1 byte */
3494 memcpy(p2p_ie + p2pielen, &capability, 2);
3495 p2pielen += 2;
3496
3497 /* Device Info ATTR */
3498 /* Type: */
3499 p2p_ie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
3500
3501 /* Length: */
3502 RTW_PUT_LE16(p2p_ie + p2pielen, devinfo_contentlen);
3503 p2pielen += 2;
3504
3505 /* Value: */
3506 memcpy(p2p_ie + p2pielen, devinfo_content, devinfo_contentlen);
3507 p2pielen += devinfo_contentlen;
3508
3509 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, p2pielen,
3510 (unsigned char *)p2p_ie, &p2p_ielen);
3511 pattrib->pktlen += p2p_ielen;
3512
3513 wpsielen = 0;
3514 /* WPS OUI */
3515 *(u32 *)(wpsie) = cpu_to_be32(WPSOUI);
3516 wpsielen += 4;
3517
3518 /* WPS version */
3519 /* Type: */
3520 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3521 wpsielen += 2;
3522
3523 /* Length: */
3524 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3525 wpsielen += 2;
3526
3527 /* Value: */
3528 wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */
3529
3530 /* Config Method */
3531 /* Type: */
3532 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3533 wpsielen += 2;
3534
3535 /* Length: */
3536 *(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3537 wpsielen += 2;
3538
3539 /* Value: */
3540 *(u16 *)(wpsie + wpsielen) =
3541 cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
3542 wpsielen += 2;
3543
3544 pframe = rtw_set_ie23a(pframe, _VENDOR_SPECIFIC_IE_, wpsielen,
3545 (unsigned char *)wpsie, &pattrib->pktlen);
3546
3547#ifdef CONFIG_8723AU_P2P
3548 wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
3549 pframe += wfdielen;
3550 pattrib->pktlen += wfdielen;
3551#endif /* CONFIG_8723AU_P2P */
3552
3553 pattrib->last_txcmdsz = pattrib->pktlen;
3554
3555 /* dump_mgntframe23a(padapter, pmgntframe); */
3556 if (dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe) != _SUCCESS)
3557 DBG_8723A("%s, ack to\n", __func__);
3558}
3559
3560static s32 cfg80211_rtw_remain_on_channel(struct wiphy *wiphy,
3561 struct wireless_dev *wdev,
3562 struct ieee80211_channel *channel,
3563 unsigned int duration, u64 *cookie)
3564{
3565 s32 err = 0;
3566 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
3567 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3568 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3569 struct cfg80211_wifidirect_info *pcfg80211_wdinfo =
3570 &padapter->cfg80211_wdinfo;
3571 u8 remain_ch =
3572 (u8) ieee80211_frequency_to_channel(channel->center_freq);
3573 u8 ready_on_channel = false;
3574
3575 DBG_8723A(FUNC_ADPT_FMT " ch:%u duration:%d\n", FUNC_ADPT_ARG(padapter),
3576 remain_ch, duration);
3577
3578 if (pcfg80211_wdinfo->is_ro_ch == true) {
3579 DBG_8723A("%s, cancel ro ch timer\n", __func__);
3580
3581 del_timer_sync(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
3582
3583 p2p_protocol_wk_hdl23a(padapter, P2P_RO_CH_WK);
3584 }
3585
3586 pcfg80211_wdinfo->is_ro_ch = true;
3587
3588 if (_FAIL == rtw_pwr_wakeup(padapter)) {
3589 err = -EFAULT;
3590 goto exit;
3591 }
3592
3593 memcpy(&pcfg80211_wdinfo->remain_on_ch_channel, channel,
3594 sizeof(struct ieee80211_channel));
3595 pcfg80211_wdinfo->remain_on_ch_cookie = *cookie;
3596
3597 rtw_scan_abort23a(padapter);
3598 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
3599 rtw_p2p_enable23a(padapter, P2P_ROLE_DEVICE);
3600 wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = true;
3601 } else {
3602 rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3603#ifdef CONFIG_DEBUG_CFG80211
3604 DBG_8723A("%s, role =%d, p2p_state =%d\n", __func__,
3605 rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
3606#endif
3607 }
3608
3609 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
3610
3611 if (duration < 400)
3612 duration = duration * 3; /* extend from exper. */
3613
3614 pcfg80211_wdinfo->restore_channel = pmlmeext->cur_channel;
3615
3616 if (rtw_ch_set_search_ch23a(pmlmeext->channel_set, remain_ch) >= 0) {
3617 if (remain_ch != pmlmeext->cur_channel) {
3618 ready_on_channel = true;
3619 }
3620 } else {
3621 DBG_8723A("%s remain_ch:%u not in channel plan!!!!\n",
3622 __func__, remain_ch);
3623 }
3624
3625 /* call this after other things have been done */
3626 if (ready_on_channel == true) {
3627 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
3628 pmlmeext->cur_channel = remain_ch;
3629
3630 set_channel_bwmode23a(padapter, remain_ch,
3631 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3632 HT_CHANNEL_WIDTH_20);
3633 }
3634 }
3635 DBG_8723A("%s, set ro ch timer, duration =%d\n", __func__, duration);
3636 mod_timer(&pcfg80211_wdinfo->remain_on_ch_timer,
3637 jiffies + msecs_to_jiffies(duration));
3638
3639 rtw_cfg80211_ready_on_channel(padapter, *cookie, channel, channel_type,
3640 duration, GFP_KERNEL);
3641
3642 pwdinfo->listen_channel = pmlmeext->cur_channel;
3643
3644exit:
3645 if (err)
3646 pcfg80211_wdinfo->is_ro_ch = false;
3647
3648 return err;
3649}
3650
3651static s32 cfg80211_rtw_cancel_remain_on_channel(struct wiphy *wiphy,
3652 struct wireless_dev *wdev,
3653 u64 cookie)
3654{
3655 s32 err = 0;
3656 struct rtw_adapter *padapter = wiphy_to_adapter(wiphy);
3657 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3658 struct cfg80211_wifidirect_info *pcfg80211_wdinfo =
3659 &padapter->cfg80211_wdinfo;
3660
3661 DBG_8723A(FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter));
3662
3663 if (pcfg80211_wdinfo->is_ro_ch == true) {
3664 DBG_8723A("%s, cancel ro ch timer\n", __func__);
3665 del_timer_sync(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
3666 p2p_protocol_wk_hdl23a(padapter, P2P_RO_CH_WK);
3667 }
3668
3669 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3670#ifdef CONFIG_DEBUG_CFG80211
3671 DBG_8723A("%s, role =%d, p2p_state =%d\n", __func__,
3672 rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
3673#endif
3674 pcfg80211_wdinfo->is_ro_ch = false;
3675
3676 return err;
3677}
3678
3679#endif /* CONFIG_8723AU_P2P */
3680
3681static int _cfg80211_rtw_mgmt_tx(struct rtw_adapter *padapter, u8 tx_ch,
3682 const u8 *buf, size_t len)
3683{
3684 struct xmit_frame *pmgntframe;
3685 struct pkt_attrib *pattrib;
3686 unsigned char *pframe;
3687 int ret = _FAIL;
3688 bool ack = true;
3689 struct ieee80211_hdr *pwlanhdr;
3690 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
3691 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3692 /* struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo; */
3693
3694 if (_FAIL == rtw_pwr_wakeup(padapter)) {
3695 ret = -EFAULT;
3696 goto exit;
3697 }
3698
3699 rtw_set_scan_deny(padapter, 1000);
3700
3701 rtw_scan_abort23a(padapter);
3702
3703 if (tx_ch != rtw_get_oper_ch23a(padapter)) {
3704 if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED))
3705 pmlmeext->cur_channel = tx_ch;
3706 set_channel_bwmode23a(padapter, tx_ch,
3707 HAL_PRIME_CHNL_OFFSET_DONT_CARE,
3708 HT_CHANNEL_WIDTH_20);
3709 }
3710
3711 /* starting alloc mgmt frame to dump it */
3712 pmgntframe = alloc_mgtxmitframe23a(pxmitpriv);
3713 if (pmgntframe == NULL) {
3714 /* ret = -ENOMEM; */
3715 ret = _FAIL;
3716 goto exit;
3717 }
3718
3719 /* update attribute */
3720 pattrib = &pmgntframe->attrib;
3721 update_mgntframe_attrib23a(padapter, pattrib);
3722 pattrib->retry_ctrl = false;
3723
3724 memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3725
3726 pframe = (u8 *) (pmgntframe->buf_addr) + TXDESC_OFFSET;
3727
3728 memcpy(pframe, (void *)buf, len);
3729 pattrib->pktlen = len;
3730
3731 pwlanhdr = (struct ieee80211_hdr *)pframe;
3732 /* update seq number */
3733 pmlmeext->mgnt_seq = le16_to_cpu(pwlanhdr->seq_ctrl) >> 4;
3734 pattrib->seqnum = pmlmeext->mgnt_seq;
3735 pmlmeext->mgnt_seq++;
3736
3737#ifdef CONFIG_8723AU_P2P
3738 {
3739 struct wifi_display_info *pwfd_info;
3740
3741 pwfd_info = padapter->wdinfo.wfd_info;
3742
3743 if (true == pwfd_info->wfd_enable) {
3744 rtw_append_wfd_ie(padapter, pframe, &pattrib->pktlen);
3745 }
3746 }
3747#endif /* CONFIG_8723AU_P2P */
3748
3749 pattrib->last_txcmdsz = pattrib->pktlen;
3750
3751 if (dump_mgntframe23a_and_wait_ack23a(padapter, pmgntframe) != _SUCCESS) {
3752 ack = false;
3753 ret = _FAIL;
3754
3755#ifdef CONFIG_DEBUG_CFG80211
3756 DBG_8723A("%s, ack == _FAIL\n", __func__);
3757#endif
3758 } else {
3759#ifdef CONFIG_DEBUG_CFG80211
3760 DBG_8723A("%s, ack =%d, ok!\n", __func__, ack);
3761#endif
3762 ret = _SUCCESS;
3763 }
3764
3765exit:
3766
3767#ifdef CONFIG_DEBUG_CFG80211
3768 DBG_8723A("%s, ret =%d\n", __func__, ret);
3769#endif
3770
3771 return ret;
3772}
3773
3774static int cfg80211_rtw_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
3775#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
3776 struct ieee80211_channel *chan,
3777 bool offchan,
3778 unsigned int wait,
3779 const u8 *buf, size_t len,
3780 bool no_cck, bool dont_wait_for_ack,
3781#else
3782 struct cfg80211_mgmt_tx_params *params,
3783#endif
3784 u64 *cookie)
3785{
3786 struct rtw_adapter *padapter =
3787 (struct rtw_adapter *)wiphy_to_adapter(wiphy);
3788 struct rtw_wdev_priv *pwdev_priv = wdev_to_priv(padapter->rtw_wdev);
3789 int ret = 0;
3790 int tx_ret;
3791 u32 dump_limit = RTW_MAX_MGMT_TX_CNT;
3792 u32 dump_cnt = 0;
3793 bool ack = true;
3794 u8 category, action;
3795 int type = (-1);
3796 unsigned long start = jiffies;
3797#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
3798 size_t len = params->len;
3799 struct ieee80211_channel *chan = params->chan;
3800 const u8 *buf = params->buf;
3801#endif
3802 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)buf;
3803 u8 tx_ch = (u8) ieee80211_frequency_to_channel(chan->center_freq);
3804
3805 /* cookie generation */
3806 *cookie = (unsigned long)buf;
3807
3808#ifdef CONFIG_DEBUG_CFG80211
3809 DBG_8723A(FUNC_ADPT_FMT " len =%zu, ch =%d"
3810 "\n", FUNC_ADPT_ARG(padapter), len, tx_ch);
3811#endif /* CONFIG_DEBUG_CFG80211 */
3812
3813 /* indicate ack before issue frame to avoid racing with rsp frame */
3814 rtw_cfg80211_mgmt_tx_status(padapter, *cookie, buf, len, ack,
3815 GFP_KERNEL);
3816
3817 if (rtw_action_frame_parse23a(buf, len, &category, &action) == false) {
3818 DBG_8723A(FUNC_ADPT_FMT " frame_control:0x%x\n",
3819 FUNC_ADPT_ARG(padapter),
3820 le16_to_cpu(hdr->frame_control));
3821 goto exit;
3822 }
3823
3824 DBG_8723A("RTW_Tx:tx_ch =%d, da =" MAC_FMT "\n", tx_ch,
3825 MAC_ARG(hdr->addr1));
3826#ifdef CONFIG_8723AU_P2P
3827 type = rtw_p2p_check_frames(padapter, buf, len, true);
3828 if (type >= 0)
3829 goto dump;
3830#endif
3831 if (category == WLAN_CATEGORY_PUBLIC)
3832 DBG_8723A("RTW_Tx:%s\n", action_public_str23a(action));
3833 else
3834 DBG_8723A("RTW_Tx:category(%u), action(%u)\n",
3835 category, action);
3836
3837dump:
3838 do {
3839 dump_cnt++;
3840 tx_ret = _cfg80211_rtw_mgmt_tx(padapter, tx_ch, buf, len);
3841 } while (dump_cnt < dump_limit && tx_ret != _SUCCESS);
3842
3843 if (tx_ret != _SUCCESS || dump_cnt > 1) {
3844 DBG_8723A(FUNC_ADPT_FMT " %s (%d/%d) in %d ms\n",
3845 FUNC_ADPT_ARG(padapter),
3846 tx_ret == _SUCCESS ? "OK" : "FAIL", dump_cnt,
3847 dump_limit, jiffies_to_msecs(jiffies - start));
3848 }
3849
3850 switch (type) {
3851 case P2P_GO_NEGO_CONF:
3852 rtw_clear_scan_deny(padapter);
3853 break;
3854 case P2P_INVIT_RESP:
3855 if (pwdev_priv->invit_info.flags & BIT(0)
3856 && pwdev_priv->invit_info.status == 0) {
3857 DBG_8723A(FUNC_ADPT_FMT " agree with invitation of "
3858 "persistent group\n",
3859 FUNC_ADPT_ARG(padapter));
3860 rtw_set_scan_deny(padapter, 5000);
3861 rtw_pwr_wakeup_ex(padapter, 5000);
3862 rtw_clear_scan_deny(padapter);
3863 }
3864 break;
3865 }
3866
3867exit:
3868 return ret;
3869}
3870
3871static void cfg80211_rtw_mgmt_frame_register(struct wiphy *wiphy,
3872 struct wireless_dev *wdev,
3873 u16 frame_type, bool reg)
3874{
3875
3876#ifdef CONFIG_DEBUG_CFG80211
3877 DBG_8723A(FUNC_ADPT_FMT " frame_type:%x, reg:%d\n",
3878 FUNC_ADPT_ARG(adapter), frame_type, reg);
3879#endif
3880
3881 if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
3882 return;
3883
3884 return;
3885}
3886
3887static int rtw_cfg80211_set_beacon_wpsp2pie(struct net_device *ndev, char *buf,
3888 int len)
3889{
3890 int ret = 0;
3891 uint wps_ielen = 0;
3892 u8 *wps_ie;
3893 u32 p2p_ielen = 0;
3894 u8 wps_oui[8] = { 0x0, 0x50, 0xf2, 0x04 };
3895 u8 *p2p_ie;
3896 u32 wfd_ielen = 0;
3897 struct rtw_adapter *padapter = netdev_priv(ndev);
3898 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3899 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3900
3901 DBG_8723A(FUNC_NDEV_FMT " ielen =%d\n", FUNC_NDEV_ARG(ndev), len);
3902
3903 if (len > 0) {
3904 wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
3905 if (wps_ie) {
3906#ifdef CONFIG_DEBUG_CFG80211
3907 DBG_8723A("bcn_wps_ielen =%d\n", wps_ielen);
3908#endif
3909
3910 if (pmlmepriv->wps_beacon_ie) {
3911 pmlmepriv->wps_beacon_ie_len = 0;
3912 kfree(pmlmepriv->wps_beacon_ie);
3913 pmlmepriv->wps_beacon_ie = NULL;
3914 }
3915
3916 pmlmepriv->wps_beacon_ie =
3917 kmalloc(wps_ielen, GFP_KERNEL);
3918 if (pmlmepriv->wps_beacon_ie == NULL) {
3919 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
3920 __func__, __LINE__);
3921 return -EINVAL;
3922 }
3923 memcpy(pmlmepriv->wps_beacon_ie, wps_ie, wps_ielen);
3924 pmlmepriv->wps_beacon_ie_len = wps_ielen;
3925
3926 update_beacon23a(padapter, _VENDOR_SPECIFIC_IE_, wps_oui,
3927 true);
3928 }
3929#ifdef CONFIG_8723AU_P2P
3930 p2p_ie = rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen);
3931 if (p2p_ie) {
3932#ifdef CONFIG_DEBUG_CFG80211
3933 DBG_8723A("bcn_p2p_ielen =%d\n", p2p_ielen);
3934#endif
3935
3936 if (pmlmepriv->p2p_beacon_ie) {
3937 pmlmepriv->p2p_beacon_ie_len = 0;
3938 kfree(pmlmepriv->p2p_beacon_ie);
3939 pmlmepriv->p2p_beacon_ie = NULL;
3940 }
3941
3942 pmlmepriv->p2p_beacon_ie =
3943 kmalloc(p2p_ielen, GFP_KERNEL);
3944 if (pmlmepriv->p2p_beacon_ie == NULL) {
3945 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
3946 __func__, __LINE__);
3947 return -EINVAL;
3948 }
3949
3950 memcpy(pmlmepriv->p2p_beacon_ie, p2p_ie, p2p_ielen);
3951 pmlmepriv->p2p_beacon_ie_len = p2p_ielen;
3952 }
3953#endif /* CONFIG_8723AU_P2P */
3954
3955 /* buf += p2p_ielen; */
3956 /* len -= p2p_ielen; */
3957
3958#ifdef CONFIG_8723AU_P2P
3959 if (rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) {
3960#ifdef CONFIG_DEBUG_CFG80211
3961 DBG_8723A("bcn_wfd_ielen =%d\n", wfd_ielen);
3962#endif
3963
3964 if (pmlmepriv->wfd_beacon_ie) {
3965 pmlmepriv->wfd_beacon_ie_len = 0;
3966 kfree(pmlmepriv->wfd_beacon_ie);
3967 pmlmepriv->wfd_beacon_ie = NULL;
3968 }
3969
3970 pmlmepriv->wfd_beacon_ie =
3971 kmalloc(wfd_ielen, GFP_KERNEL);
3972 if (pmlmepriv->wfd_beacon_ie == NULL) {
3973 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
3974 __func__, __LINE__);
3975 return -EINVAL;
3976
3977 }
3978 rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_beacon_ie,
3979 &pmlmepriv->wfd_beacon_ie_len);
3980 }
3981#endif /* CONFIG_8723AU_P2P */
3982
3983 pmlmeext->bstart_bss = true;
3984
3985 }
3986
3987 return ret;
3988}
3989
3990static int rtw_cfg80211_set_probe_resp_wpsp2pie(struct net_device *net,
3991 char *buf, int len)
3992{
3993 struct rtw_adapter *padapter = netdev_priv(net);
3994 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3995 int ret = 0;
3996 uint wps_ielen = 0;
3997 u8 *wps_ie;
3998 u32 p2p_ielen = 0;
3999 u8 *p2p_ie;
4000 u32 wfd_ielen = 0;
4001
4002 if (len > 0) {
4003 wps_ie = rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen);
4004 if (wps_ie) {
4005 uint attr_contentlen = 0;
4006 u16 uconfig_method, *puconfig_method = NULL;
4007
4008 if (pmlmepriv->wps_probe_resp_ie) {
4009 pmlmepriv->wps_probe_resp_ie_len = 0;
4010 kfree(pmlmepriv->wps_probe_resp_ie);
4011 pmlmepriv->wps_probe_resp_ie = NULL;
4012 }
4013
4014 pmlmepriv->wps_probe_resp_ie =
4015 kmalloc(wps_ielen, GFP_KERNEL);
4016 if (pmlmepriv->wps_probe_resp_ie == NULL) {
4017 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4018 __func__, __LINE__);
4019 return -EINVAL;
4020
4021 }
4022
4023 /* add PUSH_BUTTON config_method by driver self in
4024 wpsie of probe_resp at GO Mode */
4025 puconfig_method = (u16 *)rtw_get_wps_attr_content23a(wps_ie, wps_ielen,
4026 WPS_ATTR_CONF_METHOD,
4027 NULL,
4028 &attr_contentlen);
4029 if (puconfig_method) {
4030 uconfig_method = WPS_CM_PUSH_BUTTON;
4031 uconfig_method = cpu_to_be16(uconfig_method);
4032
4033 *puconfig_method |= uconfig_method;
4034 }
4035
4036 memcpy(pmlmepriv->wps_probe_resp_ie, wps_ie, wps_ielen);
4037 pmlmepriv->wps_probe_resp_ie_len = wps_ielen;
4038
4039 }
4040
4041 /* buf += wps_ielen; */
4042 /* len -= wps_ielen; */
4043
4044#ifdef CONFIG_8723AU_P2P
4045 p2p_ie = rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen);
4046 if (p2p_ie) {
4047 u8 is_GO = false;
4048 u32 attr_contentlen = 0;
4049 u16 cap_attr = 0;
4050
4051#ifdef CONFIG_DEBUG_CFG80211
4052 DBG_8723A("probe_resp_p2p_ielen =%d\n", p2p_ielen);
4053#endif
4054
4055 /* Check P2P Capability ATTR */
4056 if (rtw_get_p2p_attr23a_content(p2p_ie, p2p_ielen,
4057 P2P_ATTR_CAPABILITY,
4058 (u8 *) &cap_attr,
4059 (uint *) &attr_contentlen)) {
4060 u8 grp_cap = 0;
4061 /* DBG_8723A( "[%s] Got P2P Capability Attr!!\n", __func__ ); */
4062 cap_attr = le16_to_cpu(cap_attr);
4063 grp_cap = (u8) ((cap_attr >> 8) & 0xff);
4064
4065 is_GO = (grp_cap & BIT(0)) ? true : false;
4066
4067 if (is_GO)
4068 DBG_8723A
4069 ("Got P2P Capability Attr, grp_cap"
4070 "= 0x%x, is_GO\n", grp_cap);
4071 }
4072
4073 if (is_GO == false) {
4074 if (pmlmepriv->p2p_probe_resp_ie) {
4075 pmlmepriv->p2p_probe_resp_ie_len = 0;
4076 kfree(pmlmepriv->p2p_probe_resp_ie);
4077 pmlmepriv->p2p_probe_resp_ie = NULL;
4078 }
4079
4080 pmlmepriv->p2p_probe_resp_ie =
4081 kmalloc(p2p_ielen, GFP_KERNEL);
4082 if (pmlmepriv->p2p_probe_resp_ie == NULL) {
4083 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4084 __func__, __LINE__);
4085 return -EINVAL;
4086 }
4087 memcpy(pmlmepriv->p2p_probe_resp_ie, p2p_ie,
4088 p2p_ielen);
4089 pmlmepriv->p2p_probe_resp_ie_len = p2p_ielen;
4090 } else {
4091 if (pmlmepriv->p2p_go_probe_resp_ie) {
4092 pmlmepriv->p2p_go_probe_resp_ie_len = 0;
4093 kfree(pmlmepriv->p2p_go_probe_resp_ie);
4094 pmlmepriv->p2p_go_probe_resp_ie = NULL;
4095 }
4096
4097 pmlmepriv->p2p_go_probe_resp_ie =
4098 kmalloc(p2p_ielen, GFP_KERNEL);
4099 if (pmlmepriv->p2p_go_probe_resp_ie == NULL) {
4100 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4101 __func__, __LINE__);
4102 return -EINVAL;
4103
4104 }
4105 memcpy(pmlmepriv->p2p_go_probe_resp_ie,
4106 p2p_ie, p2p_ielen);
4107 pmlmepriv->p2p_go_probe_resp_ie_len = p2p_ielen;
4108 }
4109 }
4110#endif /* CONFIG_8723AU_P2P */
4111
4112 /* buf += p2p_ielen; */
4113 /* len -= p2p_ielen; */
4114
4115#ifdef CONFIG_8723AU_P2P
4116 if (rtw_get_wfd_ie(buf, len, NULL, &wfd_ielen)) {
4117#ifdef CONFIG_DEBUG_CFG80211
4118 DBG_8723A("probe_resp_wfd_ielen =%d\n", wfd_ielen);
4119#endif
4120
4121 if (pmlmepriv->wfd_probe_resp_ie) {
4122 pmlmepriv->wfd_probe_resp_ie_len = 0;
4123 kfree(pmlmepriv->wfd_probe_resp_ie);
4124 pmlmepriv->wfd_probe_resp_ie = NULL;
4125 }
4126
4127 pmlmepriv->wfd_probe_resp_ie =
4128 kmalloc(wfd_ielen, GFP_KERNEL);
4129 if (pmlmepriv->wfd_probe_resp_ie == NULL) {
4130 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4131 __func__, __LINE__);
4132 return -EINVAL;
4133
4134 }
4135 rtw_get_wfd_ie(buf, len, pmlmepriv->wfd_probe_resp_ie,
4136 &pmlmepriv->wfd_probe_resp_ie_len);
4137 }
4138#endif /* CONFIG_8723AU_P2P */
4139 }
4140
4141 return ret;
4142}
4143
4144static int rtw_cfg80211_set_assoc_resp_wpsp2pie(struct net_device *net,
4145 char *buf, int len)
4146{
4147 int ret = 0;
4148 struct rtw_adapter *padapter = netdev_priv(net);
4149 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4150
4151 DBG_8723A("%s, ielen =%d\n", __func__, len);
4152
4153 if (len > 0) {
4154 if (pmlmepriv->wps_assoc_resp_ie) {
4155 pmlmepriv->wps_assoc_resp_ie_len = 0;
4156 kfree(pmlmepriv->wps_assoc_resp_ie);
4157 pmlmepriv->wps_assoc_resp_ie = NULL;
4158 }
4159
4160 pmlmepriv->wps_assoc_resp_ie = kmalloc(len, GFP_KERNEL);
4161 if (pmlmepriv->wps_assoc_resp_ie == NULL) {
4162 DBG_8723A("%s()-%d: kmalloc() ERROR!\n",
4163 __func__, __LINE__);
4164 return -EINVAL;
4165
4166 }
4167 memcpy(pmlmepriv->wps_assoc_resp_ie, buf, len);
4168 pmlmepriv->wps_assoc_resp_ie_len = len;
4169 }
4170
4171 return ret;
4172}
4173
4174int rtw_cfg80211_set_mgnt_wpsp2pie(struct net_device *net, char *buf, int len,
4175 int type)
4176{
4177 int ret = 0;
4178 uint wps_ielen = 0;
4179 u32 p2p_ielen = 0;
4180
4181#ifdef CONFIG_DEBUG_CFG80211
4182 DBG_8723A("%s, ielen =%d\n", __func__, len);
4183#endif
4184
4185 if ((rtw_get_wps_ie23a(buf, len, NULL, &wps_ielen) && (wps_ielen > 0))
4186#ifdef CONFIG_8723AU_P2P
4187 || (rtw_get_p2p_ie23a(buf, len, NULL, &p2p_ielen) && (p2p_ielen > 0))
4188#endif
4189 ) {
4190 if (net) {
4191 switch (type) {
4192 case 0x1: /* BEACON */
4193 ret =
4194 rtw_cfg80211_set_beacon_wpsp2pie(net, buf,
4195 len);
4196 break;
4197 case 0x2: /* PROBE_RESP */
4198 ret =
4199 rtw_cfg80211_set_probe_resp_wpsp2pie(net,
4200 buf,
4201 len);
4202 break;
4203 case 0x4: /* ASSOC_RESP */
4204 ret =
4205 rtw_cfg80211_set_assoc_resp_wpsp2pie(net,
4206 buf,
4207 len);
4208 break;
4209 }
4210 }
4211 }
4212
4213 return ret;
4214
4215}
4216
4217static struct cfg80211_ops rtw_cfg80211_ops = {
4218 .change_virtual_intf = cfg80211_rtw_change_iface,
4219 .add_key = cfg80211_rtw_add_key,
4220 .get_key = cfg80211_rtw_get_key,
4221 .del_key = cfg80211_rtw_del_key,
4222 .set_default_key = cfg80211_rtw_set_default_key,
4223 .get_station = cfg80211_rtw_get_station,
4224 .scan = cfg80211_rtw_scan,
4225 .set_wiphy_params = cfg80211_rtw_set_wiphy_params,
4226 .connect = cfg80211_rtw_connect,
4227 .disconnect = cfg80211_rtw_disconnect,
4228 .join_ibss = cfg80211_rtw_join_ibss,
4229 .leave_ibss = cfg80211_rtw_leave_ibss,
4230 .set_tx_power = cfg80211_rtw_set_txpower,
4231 .get_tx_power = cfg80211_rtw_get_txpower,
4232 .set_power_mgmt = cfg80211_rtw_set_power_mgmt,
4233 .set_pmksa = cfg80211_rtw_set_pmksa,
4234 .del_pmksa = cfg80211_rtw_del_pmksa,
4235 .flush_pmksa = cfg80211_rtw_flush_pmksa,
4236
4237#ifdef CONFIG_8723AU_AP_MODE
4238 .add_virtual_intf = cfg80211_rtw_add_virtual_intf,
4239 .del_virtual_intf = cfg80211_rtw_del_virtual_intf,
4240
4241 .start_ap = cfg80211_rtw_start_ap,
4242 .change_beacon = cfg80211_rtw_change_beacon,
4243 .stop_ap = cfg80211_rtw_stop_ap,
4244
4245 .add_station = cfg80211_rtw_add_station,
4246 .del_station = cfg80211_rtw_del_station,
4247 .change_station = cfg80211_rtw_change_station,
4248 .dump_station = cfg80211_rtw_dump_station,
4249 .change_bss = cfg80211_rtw_change_bss,
4250#endif /* CONFIG_8723AU_AP_MODE */
4251
4252#ifdef CONFIG_8723AU_P2P
4253 .remain_on_channel = cfg80211_rtw_remain_on_channel,
4254 .cancel_remain_on_channel = cfg80211_rtw_cancel_remain_on_channel,
4255#endif
4256
4257 .mgmt_tx = cfg80211_rtw_mgmt_tx,
4258 .mgmt_frame_register = cfg80211_rtw_mgmt_frame_register,
4259};
4260
4261static void rtw_cfg80211_init_ht_capab(struct ieee80211_sta_ht_cap *ht_cap,
4262 enum ieee80211_band band, u8 rf_type)
4263{
4264
4265#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */
4266#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */
4267
4268 ht_cap->ht_supported = true;
4269
4270 ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
4271 IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
4272 IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
4273
4274 /*
4275 *Maximum length of AMPDU that the STA can receive.
4276 *Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
4277 */
4278 ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
4279
4280 /*Minimum MPDU start spacing , */
4281 ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
4282
4283 ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
4284
4285 /*
4286 *hw->wiphy->bands[IEEE80211_BAND_2GHZ]
4287 *base on ant_num
4288 *rx_mask: RX mask
4289 *if rx_ant = 1 rx_mask[0]= 0xff;==>MCS0-MCS7
4290 *if rx_ant = 2 rx_mask[1]= 0xff;==>MCS8-MCS15
4291 *if rx_ant >= 3 rx_mask[2]= 0xff;
4292 *if BW_40 rx_mask[4]= 0x01;
4293 *highest supported RX rate
4294 */
4295 if (rf_type == RF_1T1R) {
4296 ht_cap->mcs.rx_mask[0] = 0xFF;
4297 ht_cap->mcs.rx_mask[1] = 0x00;
4298 ht_cap->mcs.rx_mask[4] = 0x01;
4299
4300 ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;
4301 } else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R)) {
4302 ht_cap->mcs.rx_mask[0] = 0xFF;
4303 ht_cap->mcs.rx_mask[1] = 0xFF;
4304 ht_cap->mcs.rx_mask[4] = 0x01;
4305
4306 ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;
4307 } else {
4308 DBG_8723A("%s, error rf_type =%d\n", __func__, rf_type);
4309 }
4310
4311}
4312
4313void rtw_cfg80211_init_wiphy(struct rtw_adapter *padapter)
4314{
4315 u8 rf_type;
4316 struct ieee80211_supported_band *bands;
4317 struct wireless_dev *pwdev = padapter->rtw_wdev;
4318 struct wiphy *wiphy = pwdev->wiphy;
4319
4320 rtw23a_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
4321
4322 DBG_8723A("%s:rf_type =%d\n", __func__, rf_type);
4323
4324 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
4325 {
4326 bands = wiphy->bands[IEEE80211_BAND_2GHZ];
4327 if (bands)
4328 rtw_cfg80211_init_ht_capab(&bands->ht_cap,
4329 IEEE80211_BAND_2GHZ,
4330 rf_type);
4331 }
4332
4333 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
4334 {
4335 bands = wiphy->bands[IEEE80211_BAND_5GHZ];
4336 if (bands)
4337 rtw_cfg80211_init_ht_capab(&bands->ht_cap,
4338 IEEE80211_BAND_5GHZ,
4339 rf_type);
4340 }
4341}
4342
4343static void rtw_cfg80211_preinit_wiphy(struct rtw_adapter *padapter,
4344 struct wiphy *wiphy)
4345{
4346 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
4347
4348 wiphy->max_scan_ssids = RTW_SSID_SCAN_AMOUNT;
4349 wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
4350 wiphy->max_num_pmkids = RTW_MAX_NUM_PMKIDS;
4351
4352 wiphy->max_remain_on_channel_duration =
4353 RTW_MAX_REMAIN_ON_CHANNEL_DURATION;
4354
4355 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
4356 BIT(NL80211_IFTYPE_ADHOC) |
4357#ifdef CONFIG_8723AU_AP_MODE
4358 BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR) |
4359#endif
4360#if defined(CONFIG_8723AU_P2P)
4361 BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) |
4362#endif
4363 0;
4364
4365#ifdef CONFIG_8723AU_AP_MODE
4366 wiphy->mgmt_stypes = rtw_cfg80211_default_mgmt_stypes;
4367#endif /* CONFIG_8723AU_AP_MODE */
4368
4369 wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
4370
4371 /*
4372 wiphy->iface_combinations = &rtw_combinations;
4373 wiphy->n_iface_combinations = 1;
4374 */
4375
4376 wiphy->cipher_suites = rtw_cipher_suites;
4377 wiphy->n_cipher_suites = ARRAY_SIZE(rtw_cipher_suites);
4378
4379 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11G) */
4380 wiphy->bands[IEEE80211_BAND_2GHZ] =
4381 rtw_spt_band_alloc(IEEE80211_BAND_2GHZ);
4382 /* if (padapter->registrypriv.wireless_mode & WIRELESS_11A) */
4383 wiphy->bands[IEEE80211_BAND_5GHZ] =
4384 rtw_spt_band_alloc(IEEE80211_BAND_5GHZ);
4385
4386 wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
4387 wiphy->flags |= WIPHY_FLAG_OFFCHAN_TX | WIPHY_FLAG_HAVE_AP_SME;
4388
4389 if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
4390 wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
4391 else
4392 wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
4393}
4394
4395int rtw_wdev_alloc(struct rtw_adapter *padapter, struct device *dev)
4396{
4397 int ret = 0;
4398 struct wiphy *wiphy;
4399 struct wireless_dev *wdev;
4400 struct rtw_wdev_priv *pwdev_priv;
4401 struct net_device *pnetdev = padapter->pnetdev;
4402
4403 DBG_8723A("%s(padapter =%p)\n", __func__, padapter);
4404
4405 /* wiphy */
4406 wiphy = wiphy_new(&rtw_cfg80211_ops, sizeof(struct rtw_wdev_priv));
4407 if (!wiphy) {
4408 DBG_8723A("Couldn't allocate wiphy device\n");
4409 ret = -ENOMEM;
4410 goto exit;
4411 }
4412 set_wiphy_dev(wiphy, dev);
4413 rtw_cfg80211_preinit_wiphy(padapter, wiphy);
4414
4415 ret = wiphy_register(wiphy);
4416 if (ret < 0) {
4417 DBG_8723A("Couldn't register wiphy device\n");
4418 goto free_wiphy;
4419 }
4420
4421 /* wdev */
4422 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
4423 if (!wdev) {
4424 DBG_8723A("Couldn't allocate wireless device\n");
4425 ret = -ENOMEM;
4426 goto unregister_wiphy;
4427 }
4428 wdev->wiphy = wiphy;
4429 wdev->netdev = pnetdev;
4430 /* wdev->iftype = NL80211_IFTYPE_STATION; */
4431 /* for rtw_setopmode_cmd23a() in cfg80211_rtw_change_iface() */
4432 wdev->iftype = NL80211_IFTYPE_MONITOR;
4433 padapter->rtw_wdev = wdev;
4434 pnetdev->ieee80211_ptr = wdev;
4435
4436 /* init pwdev_priv */
4437 pwdev_priv = wdev_to_priv(wdev);
4438 pwdev_priv->rtw_wdev = wdev;
4439 pwdev_priv->pmon_ndev = NULL;
4440 pwdev_priv->ifname_mon[0] = '\0';
4441 pwdev_priv->padapter = padapter;
4442 pwdev_priv->scan_request = NULL;
4443 spin_lock_init(&pwdev_priv->scan_req_lock);
4444
4445 pwdev_priv->p2p_enabled = false;
4446 pwdev_priv->provdisc_req_issued = false;
4447 rtw_wdev_invit_info_init(&pwdev_priv->invit_info);
4448
4449 if (padapter->registrypriv.power_mgnt != PS_MODE_ACTIVE)
4450 pwdev_priv->power_mgmt = true;
4451 else
4452 pwdev_priv->power_mgmt = false;
4453
4454 return ret;
4455unregister_wiphy:
4456 wiphy_unregister(wiphy);
4457free_wiphy:
4458 wiphy_free(wiphy);
4459exit:
4460 return ret;
4461}
4462
4463void rtw_wdev_free(struct wireless_dev *wdev)
4464{
4465 struct rtw_wdev_priv *pwdev_priv;
4466
4467 DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
4468
4469 if (!wdev)
4470 return;
4471
4472 pwdev_priv = wdev_to_priv(wdev);
4473
4474 kfree(wdev->wiphy->bands[IEEE80211_BAND_2GHZ]);
4475 kfree(wdev->wiphy->bands[IEEE80211_BAND_5GHZ]);
4476
4477 wiphy_free(wdev->wiphy);
4478
4479 kfree(wdev);
4480}
4481
4482void rtw_wdev_unregister(struct wireless_dev *wdev)
4483{
4484 struct rtw_wdev_priv *pwdev_priv;
4485
4486 DBG_8723A("%s(wdev =%p)\n", __func__, wdev);
4487
4488 if (!wdev)
4489 return;
4490
4491 pwdev_priv = wdev_to_priv(wdev);
4492
4493 rtw_cfg80211_indicate_scan_done(pwdev_priv, true);
4494
4495 if (pwdev_priv->pmon_ndev) {
4496 DBG_8723A("%s, unregister monitor interface\n", __func__);
4497 unregister_netdev(pwdev_priv->pmon_ndev);
4498 }
4499
4500 wiphy_unregister(wdev->wiphy);
4501}
diff --git a/drivers/staging/rtl8723au/os_dep/mlme_linux.c b/drivers/staging/rtl8723au/os_dep/mlme_linux.c
new file mode 100644
index 000000000000..b30d4d37556a
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/mlme_linux.c
@@ -0,0 +1,187 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15
16#define _MLME_OSDEP_C_
17
18#include <osdep_service.h>
19#include <drv_types.h>
20#include <mlme_osdep.h>
21#include <rtw_ioctl_set.h>
22
23void rtw_os_indicate_connect23a(struct rtw_adapter *adapter)
24{
25 rtw_cfg80211_indicate_connect(adapter);
26
27 netif_carrier_on(adapter->pnetdev);
28
29 if (adapter->pid[2] != 0)
30 rtw_signal_process(adapter->pid[2], SIGALRM);
31}
32
33void rtw_os_indicate_scan_done23a(struct rtw_adapter *padapter, bool aborted)
34{
35 rtw_cfg80211_indicate_scan_done(wdev_to_priv(padapter->rtw_wdev),
36 aborted);
37}
38
39static struct rt_pmkid_list backupPMKIDList[NUM_PMKID_CACHE];
40
41void rtw_reset_securitypriv23a(struct rtw_adapter *adapter)
42{
43 u8 backupPMKIDIndex = 0;
44 u8 backupTKIPCountermeasure = 0x00;
45 unsigned long backupTKIPcountermeasure_time = 0;
46
47 if (adapter->securitypriv.dot11AuthAlgrthm ==
48 dot11AuthAlgrthm_8021X) { /* 802.1x */
49 /* We have to backup the PMK information for WiFi PMK
50 * Caching test item.
51 * Backup the btkip_countermeasure information.
52 * When the countermeasure is trigger, the driver have to
53 * disconnect with AP for 60 seconds.
54 */
55 memset(&backupPMKIDList[0], 0x00, sizeof(struct rt_pmkid_list) *
56 NUM_PMKID_CACHE);
57
58 memcpy(&backupPMKIDList[0], &adapter->securitypriv.PMKIDList[0],
59 sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
60 backupPMKIDIndex = adapter->securitypriv.PMKIDIndex;
61 backupTKIPCountermeasure = adapter->securitypriv.btkip_countermeasure;
62 backupTKIPcountermeasure_time = adapter->securitypriv.btkip_countermeasure_time;
63
64 memset((unsigned char *)&adapter->securitypriv, 0,
65 sizeof (struct security_priv));
66 /* Restore the PMK information to securitypriv structure
67 * for the following connection.
68 */
69 memcpy(&adapter->securitypriv.PMKIDList[0], &backupPMKIDList[0],
70 sizeof(struct rt_pmkid_list) * NUM_PMKID_CACHE);
71 adapter->securitypriv.PMKIDIndex = backupPMKIDIndex;
72 adapter->securitypriv.btkip_countermeasure = backupTKIPCountermeasure;
73 adapter->securitypriv.btkip_countermeasure_time = backupTKIPcountermeasure_time;
74
75 adapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
76 adapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
77 } else { /* reset values in securitypriv */
78 struct security_priv *psec_priv = &adapter->securitypriv;
79
80 /* open system */
81 psec_priv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
82 psec_priv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
83 psec_priv->dot11PrivacyKeyIndex = 0;
84
85 psec_priv->dot118021XGrpPrivacy = _NO_PRIVACY_;
86 psec_priv->dot118021XGrpKeyid = 1;
87
88 psec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
89 psec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
90 }
91}
92
93void rtw_os_indicate_disconnect23a(struct rtw_adapter *adapter)
94{
95 /* Do it first for tx broadcast pkt after disconnection issue! */
96 netif_carrier_off(adapter->pnetdev);
97
98 rtw_cfg80211_indicate_disconnect(adapter);
99
100 rtw_reset_securitypriv23a(adapter);
101}
102
103void rtw_report_sec_ie23a(struct rtw_adapter *adapter, u8 authmode, u8 *sec_ie)
104{
105 uint len;
106 u8 *buff, *p, i;
107 union iwreq_data wrqu;
108
109 RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
110 ("+rtw_report_sec_ie23a, authmode =%d\n", authmode));
111
112 buff = NULL;
113 if (authmode == _WPA_IE_ID_) {
114 RT_TRACE(_module_mlme_osdep_c_, _drv_info_,
115 ("rtw_report_sec_ie23a, authmode =%d\n", authmode));
116
117 buff = kzalloc(IW_CUSTOM_MAX, GFP_KERNEL);
118 if (!buff)
119 return;
120 p = buff;
121
122 p += sprintf(p, "ASSOCINFO(ReqIEs =");
123
124 len = sec_ie[1]+2;
125 len = (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
126
127 for (i = 0; i < len; i++)
128 p += sprintf(p, "%02x", sec_ie[i]);
129
130 p += sprintf(p, ")");
131
132 memset(&wrqu, 0, sizeof(wrqu));
133
134 wrqu.data.length = p-buff;
135
136 wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ?
137 wrqu.data.length : IW_CUSTOM_MAX;
138
139 kfree(buff);
140 }
141}
142
143#ifdef CONFIG_8723AU_AP_MODE
144void rtw_indicate_sta_assoc_event23a(struct rtw_adapter *padapter,
145 struct sta_info *psta)
146{
147 struct sta_priv *pstapriv = &padapter->stapriv;
148 union iwreq_data wrqu;
149
150 if (psta == NULL)
151 return;
152
153 if (psta->aid > NUM_STA)
154 return;
155
156 if (pstapriv->sta_aid[psta->aid - 1] != psta)
157 return;
158
159 wrqu.addr.sa_family = ARPHRD_ETHER;
160
161 memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
162
163 DBG_8723A("+rtw_indicate_sta_assoc_event23a\n");
164}
165
166void rtw_indicate_sta_disassoc_event23a(struct rtw_adapter *padapter,
167 struct sta_info *psta)
168{
169 struct sta_priv *pstapriv = &padapter->stapriv;
170 union iwreq_data wrqu;
171
172 if (psta == NULL)
173 return;
174
175 if (psta->aid > NUM_STA)
176 return;
177
178 if (pstapriv->sta_aid[psta->aid - 1] != psta)
179 return;
180
181 wrqu.addr.sa_family = ARPHRD_ETHER;
182
183 memcpy(wrqu.addr.sa_data, psta->hwaddr, ETH_ALEN);
184
185 DBG_8723A("+rtw_indicate_sta_disassoc_event23a\n");
186}
187#endif
diff --git a/drivers/staging/rtl8723au/os_dep/os_intfs.c b/drivers/staging/rtl8723au/os_dep/os_intfs.c
new file mode 100644
index 000000000000..57eca7a45672
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/os_intfs.c
@@ -0,0 +1,970 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _OS_INTFS_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <xmit_osdep.h>
20#include <recv_osdep.h>
21#include <hal_intf.h>
22#include <rtw_version.h>
23#include <ethernet.h>
24
25#include <usb_osintf.h>
26#include <linux/version.h>
27
28MODULE_LICENSE("GPL");
29MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
30MODULE_AUTHOR("Realtek Semiconductor Corp.");
31MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
32MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@redhat.com>");
33MODULE_VERSION(DRIVERVERSION);
34MODULE_FIRMWARE("rtlwifi/rtl8821aefw.bin");
35
36/* module param defaults */
37static int rtw_chip_version = 0x00;
38static int rtw_rfintfs = HWPI;
39static int rtw_debug = 1;
40
41static int rtw_channel = 1;/* ad-hoc support requirement */
42static int rtw_wireless_mode = WIRELESS_11BG_24N;
43static int rtw_vrtl_carrier_sense = AUTO_VCS;
44static int rtw_vcs_type = RTS_CTS;/* */
45static int rtw_rts_thresh = 2347;/* */
46static int rtw_frag_thresh = 2346;/* */
47static int rtw_preamble = PREAMBLE_LONG;/* long, short, auto */
48static int rtw_scan_mode = 1;/* active, passive */
49static int rtw_adhoc_tx_pwr = 1;
50static int rtw_soft_ap;
51static int rtw_power_mgnt = 1;
52static int rtw_ips_mode = IPS_NORMAL;
53
54static int rtw_smart_ps = 2;
55
56module_param(rtw_ips_mode, int, 0644);
57MODULE_PARM_DESC(rtw_ips_mode, "The default IPS mode");
58
59static int rtw_long_retry_lmt = 7;
60static int rtw_short_retry_lmt = 7;
61static int rtw_busy_thresh = 40;
62static int rtw_ack_policy = NORMAL_ACK;
63
64static int rtw_acm_method;/* 0:By SW 1:By HW. */
65
66static int rtw_wmm_enable = 1;/* default is set to enable the wmm. */
67static int rtw_uapsd_enable;
68
69int rtw_ht_enable23A = 1;
70/* 0 :diable, bit(0): enable 2.4g, bit(1): enable 5g */
71int rtw_cbw40_enable23A = 3;
72int rtw_ampdu_enable23A = 1;/* for enable tx_ampdu */
73/* 0: disable, bit(0):enable 2.4g, bit(1):enable 5g, default is set to enable
74 * 2.4GHZ for IOT issue with bufflao's AP at 5GHZ
75 */
76static int rtw_rx_stbc = 1;
77static int rtw_ampdu_amsdu;/* 0: disabled, 1:enabled, 2:auto */
78
79/* Use 2 path Tx to transmit MCS0~7 and legacy mode */
80static int rtw_lowrate_two_xmit = 1;
81
82/* int rf_config = RF_1T2R; 1T2R */
83static int rtw_rf_config = RF_819X_MAX_TYPE; /* auto */
84static int rtw_low_power;
85static int rtw_wifi_spec;
86static int rtw_channel_plan = RT_CHANNEL_DOMAIN_MAX;
87
88#ifdef CONFIG_8723AU_BT_COEXIST
89static int rtw_btcoex_enable = 1;
90static int rtw_bt_iso = 2;/* 0:Low, 1:High, 2:From Efuse */
91/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy, 5.OtherBusy */
92static int rtw_bt_sco = 3;
93/* 0:Disable BT control A-MPDU, 1:Enable BT control A-MPDU. */
94static int rtw_bt_ampdu = 1 ;
95#endif
96
97/* 0:Reject AP's Add BA req, 1:Accept AP's Add BA req. */
98static int rtw_AcceptAddbaReq = true;
99
100static int rtw_antdiv_cfg = 2; /* 0:OFF , 1:ON, 2:decide by Efuse config */
101static int rtw_antdiv_type; /* 0:decide by efuse */
102
103static int rtw_enusbss;/* 0:disable, 1:enable */
104
105static int rtw_hwpdn_mode = 2;/* 0:disable, 1:enable, 2: by EFUSE config */
106
107static int rtw_hwpwrp_detect; /* HW power ping detect 0:disable , 1:enable */
108
109static int rtw_hw_wps_pbc = 1;
110
111static int rtw_80211d;
112
113static int rtw_regulatory_id = 0xff;/* Regulatory tab id, 0xff = follow efuse's setting */
114
115module_param(rtw_regulatory_id, int, 0644);
116
117static char *ifname = "wlan%d";
118module_param(ifname, charp, 0644);
119MODULE_PARM_DESC(ifname, "The default name to allocate for first interface");
120
121static char *if2name = "wlan%d";
122module_param(if2name, charp, 0644);
123MODULE_PARM_DESC(if2name, "The default name to allocate for second interface");
124
125module_param(rtw_channel_plan, int, 0644);
126module_param(rtw_chip_version, int, 0644);
127module_param(rtw_rfintfs, int, 0644);
128module_param(rtw_channel, int, 0644);
129module_param(rtw_wmm_enable, int, 0644);
130module_param(rtw_vrtl_carrier_sense, int, 0644);
131module_param(rtw_vcs_type, int, 0644);
132module_param(rtw_busy_thresh, int, 0644);
133module_param(rtw_ht_enable23A, int, 0644);
134module_param(rtw_cbw40_enable23A, int, 0644);
135module_param(rtw_ampdu_enable23A, int, 0644);
136module_param(rtw_rx_stbc, int, 0644);
137module_param(rtw_ampdu_amsdu, int, 0644);
138
139module_param(rtw_lowrate_two_xmit, int, 0644);
140
141module_param(rtw_rf_config, int, 0644);
142module_param(rtw_power_mgnt, int, 0644);
143module_param(rtw_smart_ps, int, 0644);
144module_param(rtw_low_power, int, 0644);
145module_param(rtw_wifi_spec, int, 0644);
146
147module_param(rtw_antdiv_cfg, int, 0644);
148
149module_param(rtw_enusbss, int, 0644);
150module_param(rtw_hwpdn_mode, int, 0644);
151module_param(rtw_hwpwrp_detect, int, 0644);
152
153module_param(rtw_hw_wps_pbc, int, 0644);
154
155static uint rtw_max_roaming_times = 2;
156module_param(rtw_max_roaming_times, uint, 0644);
157MODULE_PARM_DESC(rtw_max_roaming_times, "The max roaming times to try");
158
159module_param(rtw_80211d, int, 0644);
160MODULE_PARM_DESC(rtw_80211d, "Enable 802.11d mechanism");
161
162#ifdef CONFIG_8723AU_BT_COEXIST
163module_param(rtw_btcoex_enable, int, 0644);
164MODULE_PARM_DESC(rtw_btcoex_enable, "Enable BT co-existence mechanism");
165#endif
166
167static uint rtw_notch_filter;
168module_param(rtw_notch_filter, uint, 0644);
169MODULE_PARM_DESC(rtw_notch_filter, "0:Disable, 1:Enable, 2:Enable only for P2P");
170module_param_named(debug, rtw_debug, int, 0444);
171MODULE_PARM_DESC(debug, "Set debug level (1-9) (default 1)");
172
173static int netdev_close(struct net_device *pnetdev);
174
175static uint loadparam(struct rtw_adapter *padapter, struct net_device *pnetdev)
176{
177 struct registry_priv *registry_par = &padapter->registrypriv;
178 uint status = _SUCCESS;
179
180 GlobalDebugLevel23A = rtw_debug;
181 registry_par->chip_version = (u8)rtw_chip_version;
182 registry_par->rfintfs = (u8)rtw_rfintfs;
183 memcpy(registry_par->ssid.ssid, "ANY", 3);
184 registry_par->ssid.ssid_len = 3;
185 registry_par->channel = (u8)rtw_channel;
186 registry_par->wireless_mode = (u8)rtw_wireless_mode;
187 registry_par->vrtl_carrier_sense = (u8)rtw_vrtl_carrier_sense;
188 registry_par->vcs_type = (u8)rtw_vcs_type;
189 registry_par->rts_thresh = (u16)rtw_rts_thresh;
190 registry_par->frag_thresh = (u16)rtw_frag_thresh;
191 registry_par->preamble = (u8)rtw_preamble;
192 registry_par->scan_mode = (u8)rtw_scan_mode;
193 registry_par->adhoc_tx_pwr = (u8)rtw_adhoc_tx_pwr;
194 registry_par->soft_ap = (u8)rtw_soft_ap;
195 registry_par->smart_ps = (u8)rtw_smart_ps;
196 registry_par->power_mgnt = (u8)rtw_power_mgnt;
197 registry_par->ips_mode = (u8)rtw_ips_mode;
198 registry_par->long_retry_lmt = (u8)rtw_long_retry_lmt;
199 registry_par->short_retry_lmt = (u8)rtw_short_retry_lmt;
200 registry_par->busy_thresh = (u16)rtw_busy_thresh;
201 registry_par->ack_policy = (u8)rtw_ack_policy;
202 registry_par->acm_method = (u8)rtw_acm_method;
203 /* UAPSD */
204 registry_par->wmm_enable = (u8)rtw_wmm_enable;
205 registry_par->uapsd_enable = (u8)rtw_uapsd_enable;
206 registry_par->ht_enable = (u8)rtw_ht_enable23A;
207 registry_par->cbw40_enable = (u8)rtw_cbw40_enable23A;
208 registry_par->ampdu_enable = (u8)rtw_ampdu_enable23A;
209 registry_par->rx_stbc = (u8)rtw_rx_stbc;
210 registry_par->ampdu_amsdu = (u8)rtw_ampdu_amsdu;
211 registry_par->lowrate_two_xmit = (u8)rtw_lowrate_two_xmit;
212 registry_par->rf_config = (u8)rtw_rf_config;
213 registry_par->low_power = (u8)rtw_low_power;
214 registry_par->wifi_spec = (u8)rtw_wifi_spec;
215 registry_par->channel_plan = (u8)rtw_channel_plan;
216#ifdef CONFIG_8723AU_BT_COEXIST
217 registry_par->btcoex = (u8)rtw_btcoex_enable;
218 registry_par->bt_iso = (u8)rtw_bt_iso;
219 registry_par->bt_sco = (u8)rtw_bt_sco;
220 registry_par->bt_ampdu = (u8)rtw_bt_ampdu;
221#endif
222 registry_par->bAcceptAddbaReq = (u8)rtw_AcceptAddbaReq;
223 registry_par->antdiv_cfg = (u8)rtw_antdiv_cfg;
224 registry_par->antdiv_type = (u8)rtw_antdiv_type;
225
226 /* 0:disable, 1:enable, 2:by EFUSE config */
227 registry_par->hwpdn_mode = (u8)rtw_hwpdn_mode;
228 /* 0:disable, 1:enable */
229 registry_par->hwpwrp_detect = (u8)rtw_hwpwrp_detect;
230 registry_par->hw_wps_pbc = (u8)rtw_hw_wps_pbc;
231 registry_par->max_roaming_times = (u8)rtw_max_roaming_times;
232 registry_par->enable80211d = (u8)rtw_80211d;
233 snprintf(registry_par->ifname, 16, "%s", ifname);
234 snprintf(registry_par->if2name, 16, "%s", if2name);
235 registry_par->notch_filter = (u8)rtw_notch_filter;
236 registry_par->regulatory_tid = (u8)rtw_regulatory_id;
237 return status;
238}
239
240static int rtw_net_set_mac_address(struct net_device *pnetdev, void *p)
241{
242 struct rtw_adapter *padapter = netdev_priv(pnetdev);
243 struct sockaddr *addr = p;
244
245 if (!padapter->bup)
246 ether_addr_copy(padapter->eeprompriv.mac_addr, addr->sa_data);
247 return 0;
248}
249
250static struct net_device_stats *rtw_net_get_stats(struct net_device *pnetdev)
251{
252 struct rtw_adapter *padapter = netdev_priv(pnetdev);
253 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
254 struct recv_priv *precvpriv = &padapter->recvpriv;
255
256 padapter->stats.tx_packets = pxmitpriv->tx_pkts;
257 padapter->stats.rx_packets = precvpriv->rx_pkts;
258 padapter->stats.tx_dropped = pxmitpriv->tx_drop;
259 padapter->stats.rx_dropped = precvpriv->rx_drop;
260 padapter->stats.tx_bytes = pxmitpriv->tx_bytes;
261 padapter->stats.rx_bytes = precvpriv->rx_bytes;
262
263 return &padapter->stats;
264}
265
266/*
267 * AC to queue mapping
268 *
269 * AC_VO -> queue 0
270 * AC_VI -> queue 1
271 * AC_BE -> queue 2
272 * AC_BK -> queue 3
273 */
274static const u16 rtw_1d_to_queue[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
275
276/* Given a data frame determine the 802.1p/1d tag to use. */
277static unsigned int rtw_classify8021d(struct sk_buff *skb)
278{
279 unsigned int dscp;
280
281 /* skb->priority values from 256->263 are magic values to
282 * directly indicate a specific 802.1d priority. This is used
283 * to allow 802.1d priority to be passed directly in from VLAN
284 * tags, etc.
285 */
286 if (skb->priority >= 256 && skb->priority <= 263)
287 return skb->priority - 256;
288 switch (skb->protocol) {
289 case htons(ETH_P_IP):
290 dscp = ip_hdr(skb)->tos & 0xfc;
291 break;
292 default:
293 return 0;
294 }
295 return dscp >> 5;
296}
297
298static u16 rtw_select_queue(struct net_device *dev, struct sk_buff *skb,
299 void *accel_priv,
300 select_queue_fallback_t fallback)
301{
302 struct rtw_adapter *padapter = netdev_priv(dev);
303 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
304
305 skb->priority = rtw_classify8021d(skb);
306
307 if (pmlmepriv->acm_mask != 0)
308 skb->priority = qos_acm23a(pmlmepriv->acm_mask, skb->priority);
309 return rtw_1d_to_queue[skb->priority];
310}
311
312u16 rtw_recv_select_queue23a(struct sk_buff *skb)
313{
314 struct iphdr *piphdr;
315 unsigned int dscp;
316 u16 eth_type;
317 u32 priority;
318 u8 *pdata = skb->data;
319
320 memcpy(&eth_type, pdata + (ETH_ALEN << 1), 2);
321 switch (eth_type) {
322 case htons(ETH_P_IP):
323 piphdr = (struct iphdr *)(pdata + ETH_HLEN);
324 dscp = piphdr->tos & 0xfc;
325 priority = dscp >> 5;
326 break;
327 default:
328 priority = 0;
329 }
330 return rtw_1d_to_queue[priority];
331}
332
333static const struct net_device_ops rtw_netdev_ops = {
334 .ndo_open = netdev_open23a,
335 .ndo_stop = netdev_close,
336 .ndo_start_xmit = rtw_xmit23a_entry23a,
337 .ndo_select_queue = rtw_select_queue,
338 .ndo_set_mac_address = rtw_net_set_mac_address,
339 .ndo_get_stats = rtw_net_get_stats,
340};
341
342int rtw_init_netdev23a_name23a(struct net_device *pnetdev, const char *ifname)
343{
344 if (dev_alloc_name(pnetdev, ifname) < 0) {
345 RT_TRACE(_module_os_intfs_c_, _drv_err_,
346 ("dev_alloc_name, fail!\n"));
347 }
348 netif_carrier_off(pnetdev);
349 return 0;
350}
351
352static const struct device_type wlan_type = {
353 .name = "wlan",
354};
355
356struct net_device *rtw_init_netdev23a(struct rtw_adapter *old_padapter)
357{
358 struct rtw_adapter *padapter;
359 struct net_device *pnetdev;
360
361 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+init_net_dev\n"));
362
363 pnetdev = alloc_etherdev_mq(sizeof(struct rtw_adapter), 4);
364 if (!pnetdev)
365 return NULL;
366
367 pnetdev->dev.type = &wlan_type;
368 padapter = netdev_priv(pnetdev);
369 padapter->pnetdev = pnetdev;
370
371 DBG_8723A("register rtw_netdev_ops to netdev_ops\n");
372 pnetdev->netdev_ops = &rtw_netdev_ops;
373
374 pnetdev->watchdog_timeo = HZ*3; /* 3 second timeout */
375
376 /* step 2. */
377 loadparam(padapter, pnetdev);
378 return pnetdev;
379}
380
381u32 rtw_start_drv_threads23a(struct rtw_adapter *padapter)
382{
383 u32 _status = _SUCCESS;
384
385 RT_TRACE(_module_os_intfs_c_, _drv_info_,
386 ("+rtw_start_drv_threads23a\n"));
387 padapter->cmdThread = kthread_run(rtw_cmd_thread23a, padapter,
388 "RTW_CMD_THREAD");
389 if (IS_ERR(padapter->cmdThread)) {
390 _status = _FAIL;
391 } else {
392 /* wait for cmd_thread to run */
393 down(&padapter->cmdpriv.terminate_cmdthread_sema);
394 }
395 rtw_hal_start_thread23a(padapter);
396 return _status;
397}
398
399void rtw_stop_drv_threads23a(struct rtw_adapter *padapter)
400{
401 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_stop_drv_threads23a\n"));
402
403 /* Below is to termindate rtw_cmd_thread23a & event_thread... */
404 up(&padapter->cmdpriv.cmd_queue_sema);
405 if (padapter->cmdThread)
406 down(&padapter->cmdpriv.terminate_cmdthread_sema);
407 rtw_hal_stop_thread23a(padapter);
408}
409
410static u8 rtw_init_default_value(struct rtw_adapter *padapter)
411{
412 struct registry_priv *pregistrypriv = &padapter->registrypriv;
413 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
414 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
415 struct security_priv *psecuritypriv = &padapter->securitypriv;
416 u8 ret = _SUCCESS;
417
418 /* xmit_priv */
419 pxmitpriv->vcs_setting = pregistrypriv->vrtl_carrier_sense;
420 pxmitpriv->vcs = pregistrypriv->vcs_type;
421 pxmitpriv->vcs_type = pregistrypriv->vcs_type;
422 /* pxmitpriv->rts_thresh = pregistrypriv->rts_thresh; */
423 pxmitpriv->frag_len = pregistrypriv->frag_thresh;
424
425 /* mlme_priv */
426 pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
427 pmlmepriv->scan_mode = SCAN_ACTIVE;
428
429 /* ht_priv */
430 pmlmepriv->htpriv.ampdu_enable = false;/* set to disabled */
431
432 /* security_priv */
433 psecuritypriv->binstallGrpkey = _FAIL;
434
435 /* open system */
436 psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_Open;
437 psecuritypriv->dot11PrivacyAlgrthm = _NO_PRIVACY_;
438
439 psecuritypriv->dot11PrivacyKeyIndex = 0;
440
441 psecuritypriv->dot118021XGrpPrivacy = _NO_PRIVACY_;
442 psecuritypriv->dot118021XGrpKeyid = 1;
443
444 psecuritypriv->ndisauthtype = Ndis802_11AuthModeOpen;
445 psecuritypriv->ndisencryptstatus = Ndis802_11WEPDisabled;
446
447 /* registry_priv */
448 rtw_init_registrypriv_dev_network23a(padapter);
449 rtw_update_registrypriv_dev_network23a(padapter);
450
451 /* hal_priv */
452 rtw_hal_def_value_init23a(padapter);
453
454 /* misc. */
455 padapter->bReadPortCancel = false;
456 padapter->bWritePortCancel = false;
457 padapter->bRxRSSIDisplay = 0;
458 padapter->bNotifyChannelChange = 0;
459#ifdef CONFIG_8723AU_P2P
460 padapter->bShowGetP2PState = 1;
461#endif
462 return ret;
463}
464
465u8 rtw_reset_drv_sw23a(struct rtw_adapter *padapter)
466{
467 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
468 struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
469 u8 ret8 = _SUCCESS;
470
471 /* hal_priv */
472 rtw_hal_def_value_init23a(padapter);
473 padapter->bReadPortCancel = false;
474 padapter->bWritePortCancel = false;
475 padapter->bRxRSSIDisplay = 0;
476 pmlmepriv->scan_interval = SCAN_INTERVAL;/* 30*2 sec = 60sec */
477
478 padapter->xmitpriv.tx_pkts = 0;
479 padapter->recvpriv.rx_pkts = 0;
480
481 pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
482
483 _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING);
484
485 rtw_hal_sreset_reset23a_value23a(padapter);
486 pwrctrlpriv->pwr_state_check_cnts = 0;
487
488 /* mlmeextpriv */
489 padapter->mlmeextpriv.sitesurvey_res.state = SCAN_DISABLE;
490
491 rtw_set_signal_stat_timer(&padapter->recvpriv);
492 return ret8;
493}
494
495u8 rtw_init_drv_sw23a(struct rtw_adapter *padapter)
496{
497 u8 ret8 = _SUCCESS;
498
499 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_init_drv_sw23a\n"));
500
501 if ((rtw_init_cmd_priv23a(&padapter->cmdpriv)) == _FAIL) {
502 RT_TRACE(_module_os_intfs_c_, _drv_err_,
503 ("\n Can't init cmd_priv\n"));
504 ret8 = _FAIL;
505 goto exit;
506 }
507
508 padapter->cmdpriv.padapter = padapter;
509
510 if (rtw_init_evt_priv23a(&padapter->evtpriv) == _FAIL) {
511 RT_TRACE(_module_os_intfs_c_, _drv_err_,
512 ("\n Can't init evt_priv\n"));
513 ret8 = _FAIL;
514 goto exit;
515 }
516
517 if (rtw_init_mlme_priv23a(padapter) == _FAIL) {
518 RT_TRACE(_module_os_intfs_c_, _drv_err_,
519 ("\n Can't init mlme_priv\n"));
520 ret8 = _FAIL;
521 goto exit;
522 }
523
524#ifdef CONFIG_8723AU_P2P
525 rtw_init_wifidirect_timers23a(padapter);
526 init_wifidirect_info23a(padapter, P2P_ROLE_DISABLE);
527 reset_global_wifidirect_info23a(padapter);
528 rtw_init_cfg80211_wifidirect_info(padapter);
529#ifdef CONFIG_8723AU_P2P
530 if (rtw_init_wifi_display_info(padapter) == _FAIL)
531 RT_TRACE(_module_os_intfs_c_, _drv_err_,
532 ("\n Can't init init_wifi_display_info\n"));
533#endif
534#endif /* CONFIG_8723AU_P2P */
535
536 if (init_mlme_ext_priv23a(padapter) == _FAIL) {
537 RT_TRACE(_module_os_intfs_c_, _drv_err_,
538 ("\n Can't init mlme_ext_priv\n"));
539 ret8 = _FAIL;
540 goto exit;
541 }
542
543 if (_rtw_init_xmit_priv23a(&padapter->xmitpriv, padapter) == _FAIL) {
544 DBG_8723A("Can't _rtw_init_xmit_priv23a\n");
545 ret8 = _FAIL;
546 goto exit;
547 }
548
549 if (_rtw_init_recv_priv23a(&padapter->recvpriv, padapter) == _FAIL) {
550 DBG_8723A("Can't _rtw_init_recv_priv23a\n");
551 ret8 = _FAIL;
552 goto exit;
553 }
554
555 if (_rtw_init_sta_priv23a(&padapter->stapriv) == _FAIL) {
556 DBG_8723A("Can't _rtw_init_sta_priv23a\n");
557 ret8 = _FAIL;
558 goto exit;
559 }
560
561 padapter->stapriv.padapter = padapter;
562 padapter->setband = GHZ24_50;
563 rtw_init_bcmc_stainfo23a(padapter);
564
565 rtw_init_pwrctrl_priv23a(padapter);
566
567 ret8 = rtw_init_default_value(padapter);
568
569 rtw_hal_dm_init23a(padapter);
570 rtw_hal_sw_led_init23a(padapter);
571
572 rtw_hal_sreset_init23a(padapter);
573
574exit:
575
576 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_init_drv_sw23a\n"));
577 return ret8;
578}
579
580void rtw_cancel_all_timer23a(struct rtw_adapter *padapter)
581{
582 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+rtw_cancel_all_timer23a\n"));
583
584 del_timer_sync(&padapter->mlmepriv.assoc_timer);
585 RT_TRACE(_module_os_intfs_c_, _drv_info_,
586 ("rtw_cancel_all_timer23a:cancel association timer complete!\n"));
587
588 del_timer_sync(&padapter->mlmepriv.scan_to_timer);
589 RT_TRACE(_module_os_intfs_c_, _drv_info_,
590 ("rtw_cancel_all_timer23a:cancel scan_to_timer!\n"));
591
592 del_timer_sync(&padapter->mlmepriv.dynamic_chk_timer);
593 RT_TRACE(_module_os_intfs_c_, _drv_info_,
594 ("rtw_cancel_all_timer23a:cancel dynamic_chk_timer!\n"));
595
596 /* cancel sw led timer */
597 rtw_hal_sw_led_deinit23a(padapter);
598 RT_TRACE(_module_os_intfs_c_, _drv_info_,
599 ("rtw_cancel_all_timer23a:cancel DeInitSwLeds!\n"));
600
601 del_timer_sync(&padapter->pwrctrlpriv.pwr_state_check_timer);
602
603#ifdef CONFIG_8723AU_P2P
604 del_timer_sync(&padapter->cfg80211_wdinfo.remain_on_ch_timer);
605#endif /* CONFIG_8723AU_P2P */
606
607 del_timer_sync(&padapter->mlmepriv.set_scan_deny_timer);
608 rtw_clear_scan_deny(padapter);
609 RT_TRACE(_module_os_intfs_c_, _drv_info_,
610 ("rtw_cancel_all_timer23a:cancel set_scan_deny_timer!\n"));
611
612 del_timer_sync(&padapter->recvpriv.signal_stat_timer);
613 /* cancel dm timer */
614 rtw_hal_dm_deinit23a(padapter);
615}
616
617u8 rtw_free_drv_sw23a(struct rtw_adapter *padapter)
618{
619#ifdef CONFIG_8723AU_P2P
620 struct wifidirect_info *pwdinfo;
621#endif
622
623 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("==>rtw_free_drv_sw23a"));
624
625 /* we can call rtw_p2p_enable23a here, but:
626 * 1. rtw_p2p_enable23a may have IO operation
627 * 2. rtw_p2p_enable23a is bundled with wext interface
628 */
629#ifdef CONFIG_8723AU_P2P
630 pwdinfo = &padapter->wdinfo;
631 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
632 del_timer_sync(&pwdinfo->find_phase_timer);
633 del_timer_sync(&pwdinfo->restore_p2p_state_timer);
634 del_timer_sync(&pwdinfo->pre_tx_scan_timer);
635 rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
636 }
637#endif
638
639 free_mlme_ext_priv23a(&padapter->mlmeextpriv);
640
641 rtw_free_cmd_priv23a(&padapter->cmdpriv);
642
643 rtw_free_evt_priv23a(&padapter->evtpriv);
644
645 rtw_free_mlme_priv23a(&padapter->mlmepriv);
646
647 _rtw_free_xmit_priv23a(&padapter->xmitpriv);
648
649 _rtw_free_sta_priv23a(&padapter->stapriv);/* will free bcmc_stainfo here */
650
651 _rtw_free_recv_priv23a(&padapter->recvpriv);
652
653 rtw_free_pwrctrl_priv(padapter);
654
655 rtw_hal_free_data23a(padapter);
656
657 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("<== rtw_free_drv_sw23a\n"));
658
659 /* free the old_pnetdev */
660 if (padapter->rereg_nd_name_priv.old_pnetdev) {
661 free_netdev(padapter->rereg_nd_name_priv.old_pnetdev);
662 padapter->rereg_nd_name_priv.old_pnetdev = NULL;
663 }
664
665 /* clear pbuddy_adapter to avoid access wrong pointer. */
666 if (padapter->pbuddy_adapter != NULL)
667 padapter->pbuddy_adapter->pbuddy_adapter = NULL;
668 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-rtw_free_drv_sw23a\n"));
669 return _SUCCESS;
670}
671
672static int _rtw_drv_register_netdev(struct rtw_adapter *padapter, char *name)
673{
674 struct net_device *pnetdev = padapter->pnetdev;
675 int ret = _SUCCESS;
676
677 /* alloc netdev name */
678 rtw_init_netdev23a_name23a(pnetdev, name);
679
680 ether_addr_copy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr);
681
682 /* Tell the network stack we exist */
683 if (register_netdev(pnetdev)) {
684 DBG_8723A(FUNC_NDEV_FMT "Failed!\n", FUNC_NDEV_ARG(pnetdev));
685 ret = _FAIL;
686 goto error_register_netdev;
687 }
688 DBG_8723A("%s, MAC Address (if%d) = " MAC_FMT "\n", __func__,
689 (padapter->iface_id + 1), MAC_ARG(pnetdev->dev_addr));
690 return ret;
691
692error_register_netdev:
693
694 if (padapter->iface_id > IFACE_ID0) {
695 rtw_free_drv_sw23a(padapter);
696
697 free_netdev(pnetdev);
698 }
699 return ret;
700}
701
702int rtw_drv_register_netdev(struct rtw_adapter *if1)
703{
704 struct dvobj_priv *dvobj = if1->dvobj;
705 int i, status = _SUCCESS;
706
707 if (dvobj->iface_nums < IFACE_ID_MAX) {
708 for (i = 0; i < dvobj->iface_nums; i++) {
709 struct rtw_adapter *padapter = dvobj->padapters[i];
710
711 if (padapter) {
712 char *name;
713
714 if (padapter->iface_id == IFACE_ID0)
715 name = if1->registrypriv.ifname;
716 else if (padapter->iface_id == IFACE_ID1)
717 name = if1->registrypriv.if2name;
718 else
719 name = "wlan%d";
720 status = _rtw_drv_register_netdev(padapter,
721 name);
722 if (status != _SUCCESS)
723 break;
724 }
725 }
726 }
727 return status;
728}
729
730int netdev_open23a(struct net_device *pnetdev)
731{
732 struct rtw_adapter *padapter = netdev_priv(pnetdev);
733 struct pwrctrl_priv *pwrctrlpriv;
734 int ret = 0;
735 uint status;
736
737 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+871x_drv - dev_open\n"));
738 DBG_8723A("+871x_drv - drv_open, bup =%d\n", padapter->bup);
739
740 mutex_lock(&adapter_to_dvobj(padapter)->hw_init_mutex);
741
742 pwrctrlpriv = &padapter->pwrctrlpriv;
743 if (pwrctrlpriv->ps_flag) {
744 padapter->net_closed = false;
745 goto netdev_open23a_normal_process;
746 }
747
748 if (!padapter->bup) {
749 padapter->bDriverStopped = false;
750 padapter->bSurpriseRemoved = false;
751 padapter->bCardDisableWOHSM = false;
752
753 status = rtw_hal_init23a(padapter);
754 if (status == _FAIL) {
755 RT_TRACE(_module_os_intfs_c_, _drv_err_,
756 ("rtl871x_hal_init(): Can't init h/w!\n"));
757 goto netdev_open23a_error;
758 }
759
760 DBG_8723A("MAC Address = "MAC_FMT"\n",
761 MAC_ARG(pnetdev->dev_addr));
762
763 status = rtw_start_drv_threads23a(padapter);
764 if (status == _FAIL) {
765 DBG_8723A("Initialize driver software resource Failed!\n");
766 goto netdev_open23a_error;
767 }
768
769 if (init_hw_mlme_ext23a(padapter) == _FAIL) {
770 DBG_8723A("can't init mlme_ext_priv\n");
771 goto netdev_open23a_error;
772 }
773
774 if (padapter->intf_start)
775 padapter->intf_start(padapter);
776
777 rtw_cfg80211_init_wiphy(padapter);
778
779 rtw_led_control(padapter, LED_CTL_NO_LINK);
780
781 padapter->bup = true;
782 }
783 padapter->net_closed = false;
784
785 mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
786 jiffies + msecs_to_jiffies(2000));
787
788 padapter->pwrctrlpriv.bips_processing = false;
789 rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
790
791 /* netif_carrier_on(pnetdev);call this func when
792 rtw23a_joinbss_event_cb return success */
793 if (!rtw_netif_queue_stopped(pnetdev))
794 netif_tx_start_all_queues(pnetdev);
795 else
796 netif_tx_wake_all_queues(pnetdev);
797
798netdev_open23a_normal_process:
799 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-871x_drv - dev_open\n"));
800 DBG_8723A("-871x_drv - drv_open, bup =%d\n", padapter->bup);
801exit:
802 mutex_unlock(&adapter_to_dvobj(padapter)->hw_init_mutex);
803 return ret;
804
805netdev_open23a_error:
806 padapter->bup = false;
807
808 netif_carrier_off(pnetdev);
809 netif_tx_stop_all_queues(pnetdev);
810
811 RT_TRACE(_module_os_intfs_c_, _drv_err_,
812 ("-871x_drv - dev_open, fail!\n"));
813 DBG_8723A("-871x_drv - drv_open fail, bup =%d\n", padapter->bup);
814
815 ret = -1;
816 goto exit;
817}
818
819static int ips_netdrv_open(struct rtw_adapter *padapter)
820{
821 int status = _SUCCESS;
822
823 padapter->net_closed = false;
824 DBG_8723A("===> %s.........\n", __func__);
825
826 padapter->bDriverStopped = false;
827 padapter->bSurpriseRemoved = false;
828 padapter->bCardDisableWOHSM = false;
829
830 status = rtw_hal_init23a(padapter);
831 if (status == _FAIL) {
832 RT_TRACE(_module_os_intfs_c_, _drv_err_,
833 ("ips_netdrv_open(): Can't init h/w!\n"));
834 goto netdev_open23a_error;
835 }
836
837 if (padapter->intf_start)
838 padapter->intf_start(padapter);
839
840 rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
841 mod_timer(&padapter->mlmepriv.dynamic_chk_timer,
842 jiffies + msecs_to_jiffies(5000));
843
844 return _SUCCESS;
845
846netdev_open23a_error:
847 /* padapter->bup = false; */
848 DBG_8723A("-ips_netdrv_open - drv_open failure, bup =%d\n",
849 padapter->bup);
850
851 return _FAIL;
852}
853
854int rtw_ips_pwr_up23a(struct rtw_adapter *padapter)
855{
856 int result;
857 unsigned long start_time = jiffies;
858
859 DBG_8723A("===> rtw_ips_pwr_up23a..............\n");
860 rtw_reset_drv_sw23a(padapter);
861
862 result = ips_netdrv_open(padapter);
863
864 rtw_led_control(padapter, LED_CTL_NO_LINK);
865
866 DBG_8723A("<=== rtw_ips_pwr_up23a.............. in %dms\n",
867 jiffies_to_msecs(jiffies - start_time));
868 return result;
869}
870
871void rtw_ips_pwr_down23a(struct rtw_adapter *padapter)
872{
873 unsigned long start_time = jiffies;
874
875 DBG_8723A("===> rtw_ips_pwr_down23a...................\n");
876
877 padapter->bCardDisableWOHSM = true;
878 padapter->net_closed = true;
879
880 rtw_led_control(padapter, LED_CTL_POWER_OFF);
881
882 rtw_ips_dev_unload23a(padapter);
883 padapter->bCardDisableWOHSM = false;
884 DBG_8723A("<=== rtw_ips_pwr_down23a..................... in %dms\n",
885 jiffies_to_msecs(jiffies - start_time));
886}
887
888void rtw_ips_dev_unload23a(struct rtw_adapter *padapter)
889{
890 rtw_hal_set_hwreg23a(padapter, HW_VAR_FIFO_CLEARN_UP, NULL);
891
892 if (padapter->intf_stop)
893 padapter->intf_stop(padapter);
894
895 /* s5. */
896 if (!padapter->bSurpriseRemoved)
897 rtw_hal_deinit23a(padapter);
898}
899
900int pm_netdev_open23a(struct net_device *pnetdev, u8 bnormal)
901{
902 int status;
903
904 if (bnormal)
905 status = netdev_open23a(pnetdev);
906 else
907 status = (_SUCCESS == ips_netdrv_open(netdev_priv(pnetdev))) ?
908 (0) : (-1);
909
910 return status;
911}
912
913static int netdev_close(struct net_device *pnetdev)
914{
915 struct rtw_adapter *padapter = netdev_priv(pnetdev);
916
917 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("+871x_drv - drv_close\n"));
918
919 if (padapter->pwrctrlpriv.bInternalAutoSuspend) {
920 if (padapter->pwrctrlpriv.rf_pwrstate == rf_off)
921 padapter->pwrctrlpriv.ps_flag = true;
922 }
923 padapter->net_closed = true;
924
925 if (padapter->pwrctrlpriv.rf_pwrstate == rf_on) {
926 DBG_8723A("(2)871x_drv - drv_close, bup =%d, hw_init_completed =%d\n",
927 padapter->bup,
928 padapter->hw_init_completed);
929
930 /* s1. */
931 if (pnetdev) {
932 if (!rtw_netif_queue_stopped(pnetdev))
933 netif_tx_stop_all_queues(pnetdev);
934 }
935
936 /* s2. */
937 LeaveAllPowerSaveMode23a(padapter);
938 rtw_disassoc_cmd23a(padapter, 500, false);
939 /* s2-2. indicate disconnect to os */
940 rtw_indicate_disconnect23a(padapter);
941 /* s2-3. */
942 rtw_free_assoc_resources23a(padapter, 1);
943 /* s2-4. */
944 rtw_free_network_queue23a(padapter, true);
945 /* Close LED */
946 rtw_led_control(padapter, LED_CTL_POWER_OFF);
947 }
948
949#ifdef CONFIG_8723AU_P2P
950 if (wdev_to_priv(padapter->rtw_wdev)->p2p_enabled)
951 wdev_to_priv(padapter->rtw_wdev)->p2p_enabled = false;
952 rtw_p2p_enable23a(padapter, P2P_ROLE_DISABLE);
953#endif /* CONFIG_8723AU_P2P */
954
955 rtw_scan_abort23a(padapter);
956 /* set this at the end */
957 padapter->rtw_wdev->iftype = NL80211_IFTYPE_MONITOR;
958
959 RT_TRACE(_module_os_intfs_c_, _drv_info_, ("-871x_drv - drv_close\n"));
960 DBG_8723A("-871x_drv - drv_close, bup =%d\n", padapter->bup);
961
962 return 0;
963}
964
965void rtw_ndev_destructor(struct net_device *ndev)
966{
967 DBG_8723A(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(ndev));
968 kfree(ndev->ieee80211_ptr);
969 free_netdev(ndev);
970}
diff --git a/drivers/staging/rtl8723au/os_dep/osdep_service.c b/drivers/staging/rtl8723au/os_dep/osdep_service.c
new file mode 100644
index 000000000000..aeb48db0ee8c
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/osdep_service.c
@@ -0,0 +1,429 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15
16
17#define _OSDEP_SERVICE_C_
18
19#include <osdep_service.h>
20#include <drv_types.h>
21#include <recv_osdep.h>
22#include <linux/vmalloc.h>
23
24#define RT_TAG ('1178')
25
26/*
27* Translate the OS dependent @param error_code to OS independent RTW_STATUS_CODE23a
28* @return: one of RTW_STATUS_CODE23a
29*/
30inline int RTW_STATUS_CODE23a(int error_code)
31{
32 if (error_code >= 0)
33 return _SUCCESS;
34 return _FAIL;
35}
36
37inline u8 *_rtw_vmalloc(u32 sz)
38{
39 u8 *pbuf;
40 pbuf = vmalloc(sz);
41
42 return pbuf;
43}
44
45inline u8 *_rtw_zvmalloc(u32 sz)
46{
47 u8 *pbuf;
48 pbuf = _rtw_vmalloc(sz);
49 if (pbuf != NULL)
50 memset(pbuf, 0, sz);
51
52 return pbuf;
53}
54
55inline void _rtw_vmfree(u8 *pbuf, u32 sz)
56{
57 vfree(pbuf);
58}
59
60void _rtw_init_queue23a(struct rtw_queue *pqueue)
61{
62 INIT_LIST_HEAD(&pqueue->queue);
63 spin_lock_init(&pqueue->lock);
64}
65
66u32 _rtw_queue_empty23a(struct rtw_queue *pqueue)
67{
68 if (list_empty(&pqueue->queue))
69 return true;
70 else
71 return false;
72}
73
74u32 rtw_get_current_time(void)
75{
76 return jiffies;
77}
78
79inline u32 rtw_systime_to_ms23a(u32 systime)
80{
81 return systime * 1000 / HZ;
82}
83
84inline u32 rtw_ms_to_systime23a(u32 ms)
85{
86 return ms * HZ / 1000;
87}
88
89/* the input parameter start use the same unit as returned
90 * by rtw_get_current_time
91 */
92inline s32 rtw_get_passing_time_ms23a(u32 start)
93{
94 return rtw_systime_to_ms23a(jiffies-start);
95}
96
97inline s32 rtw_get_time_interval_ms23a(u32 start, u32 end)
98{
99 return rtw_systime_to_ms23a(end-start);
100}
101
102#define RTW_SUSPEND_LOCK_NAME "rtw_wifi"
103
104inline void rtw_suspend_lock_init(void)
105{
106}
107
108inline void rtw_suspend_lock_uninit(void)
109{
110}
111
112inline void rtw_lock_suspend(void)
113{
114}
115
116inline void rtw_unlock_suspend(void)
117{
118}
119
120/* Open a file with the specific @param path, @param flag, @param mode
121 * @param fpp the pointer of struct file pointer to get struct
122 * file pointer while file opening is success
123 * @param path the path of the file to open
124 * @param flag file operation flags, please refer to linux document
125 * @param mode please refer to linux document
126 * @return Linux specific error code
127 */
128static int openFile(struct file **fpp, char *path, int flag, int mode)
129{
130 struct file *fp;
131
132 fp = filp_open(path, flag, mode);
133 if (IS_ERR(fp)) {
134 *fpp = NULL;
135 return PTR_ERR(fp);
136 } else {
137 *fpp = fp;
138 return 0;
139 }
140}
141
142/* Close the file with the specific @param fp
143 * @param fp the pointer of struct file to close
144 * @return always 0
145 */
146static int closeFile(struct file *fp)
147{
148 filp_close(fp, NULL);
149 return 0;
150}
151
152static int readFile(struct file *fp, char *buf, int len)
153{
154 int rlen = 0, sum = 0;
155
156 if (!fp->f_op || !fp->f_op->read)
157 return -EPERM;
158
159 while (sum < len) {
160 rlen = fp->f_op->read(fp, buf+sum, len-sum, &fp->f_pos);
161 if (rlen > 0)
162 sum += rlen;
163 else if (0 != rlen)
164 return rlen;
165 else
166 break;
167 }
168 return sum;
169}
170
171static int writeFile(struct file *fp, char *buf, int len)
172{
173 int wlen = 0, sum = 0;
174
175 if (!fp->f_op || !fp->f_op->write)
176 return -EPERM;
177
178 while (sum < len) {
179 wlen = fp->f_op->write(fp, buf+sum, len-sum, &fp->f_pos);
180 if (wlen > 0)
181 sum += wlen;
182 else if (0 != wlen)
183 return wlen;
184 else
185 break;
186 }
187 return sum;
188}
189
190/* Test if the specifi @param path is a file and readable
191 * @param path the path of the file to test
192 * @return Linux specific error code
193 */
194static int isFileReadable(char *path)
195{
196 struct file *fp;
197 int ret = 0;
198 mm_segment_t oldfs;
199 char buf;
200
201 fp = filp_open(path, O_RDONLY, 0);
202 if (IS_ERR(fp)) {
203 ret = PTR_ERR(fp);
204 } else {
205 oldfs = get_fs();
206 set_fs(get_ds());
207
208 if (1 != readFile(fp, &buf, 1))
209 ret = PTR_ERR(fp);
210
211 set_fs(oldfs);
212 filp_close(fp, NULL);
213 }
214 return ret;
215}
216
217/* Open the file with @param path and retrive the file content into
218 * memory starting from @param buf for @param sz at most
219 * @param path the path of the file to open and read
220 * @param buf the starting address of the buffer to store file content
221 * @param sz how many bytes to read at most
222 * @return the byte we've read, or Linux specific error code
223 */
224static int retriveFromFile(char *path, u8 *buf, u32 sz)
225{
226 int ret = -1;
227 mm_segment_t oldfs;
228 struct file *fp;
229
230 if (path && buf) {
231 ret = openFile(&fp, path, O_RDONLY, 0);
232 if (!ret) {
233 DBG_8723A("%s openFile path:%s fp =%p\n",
234 __func__, path, fp);
235
236 oldfs = get_fs(); set_fs(get_ds());
237 ret = readFile(fp, buf, sz);
238 set_fs(oldfs);
239 closeFile(fp);
240
241 DBG_8723A("%s readFile, ret:%d\n", __func__, ret);
242 } else {
243 DBG_8723A("%s openFile path:%s Fail, ret:%d\n",
244 __func__, path, ret);
245 }
246 } else {
247 DBG_8723A("%s NULL pointer\n", __func__);
248 ret = -EINVAL;
249 }
250 return ret;
251}
252
253/* Open the file with @param path and wirte @param sz byte of data starting
254 * from @param buf into the file
255 * @param path the path of the file to open and write
256 * @param buf the starting address of the data to write into file
257 * @param sz how many bytes to write at most
258 * @return the byte we've written, or Linux specific error code
259 */
260static int storeToFile(char *path, u8 *buf, u32 sz)
261{
262 struct file *fp;
263 int ret = 0;
264 mm_segment_t oldfs;
265
266 if (path && buf) {
267 ret = openFile(&fp, path, O_CREAT|O_WRONLY, 0666);
268 if (!ret) {
269 DBG_8723A("%s openFile path:%s fp =%p\n", __func__,
270 path, fp);
271
272 oldfs = get_fs(); set_fs(get_ds());
273 ret = writeFile(fp, buf, sz);
274 set_fs(oldfs);
275 closeFile(fp);
276
277 DBG_8723A("%s writeFile, ret:%d\n", __func__, ret);
278 } else {
279 DBG_8723A("%s openFile path:%s Fail, ret:%d\n",
280 __func__, path, ret);
281 }
282 } else {
283 DBG_8723A("%s NULL pointer\n", __func__);
284 ret = -EINVAL;
285 }
286 return ret;
287}
288
289/*
290* Test if the specifi @param path is a file and readable
291* @param path the path of the file to test
292* @return true or false
293*/
294int rtw_is_file_readable(char *path)
295{
296 if (isFileReadable(path) == 0)
297 return true;
298 else
299 return false;
300}
301
302/* Open the file with @param path and retrive the file content into memoryi
303 * starting from @param buf for @param sz at most
304 * @param path the path of the file to open and read
305 * @param buf the starting address of the buffer to store file content
306 * @param sz how many bytes to read at most
307 * @return the byte we've read
308 */
309int rtw_retrive_from_file(char *path, u8 *buf, u32 sz)
310{
311 int ret = retriveFromFile(path, buf, sz);
312 return ret >= 0 ? ret : 0;
313}
314
315/* Open the file with @param path and wirte @param sz byte of
316 * data starting from @param buf into the file
317 * @param path the path of the file to open and write
318 * @param buf the starting address of the data to write into file
319 * @param sz how many bytes to write at most
320 * @return the byte we've written
321 */
322int rtw_store_to_file(char *path, u8 *buf, u32 sz)
323{
324 int ret = storeToFile(path, buf, sz);
325 return ret >= 0 ? ret : 0;
326}
327
328u64 rtw_modular6423a(u64 x, u64 y)
329{
330 return do_div(x, y);
331}
332
333u64 rtw_division6423a(u64 x, u64 y)
334{
335 do_div(x, y);
336 return x;
337}
338
339/* rtw_cbuf_full23a - test if cbuf is full
340 * @cbuf: pointer of struct rtw_cbuf
341 *
342 * Returns: true if cbuf is full
343 */
344inline bool rtw_cbuf_full23a(struct rtw_cbuf *cbuf)
345{
346 return (cbuf->write == cbuf->read-1) ? true : false;
347}
348
349/* rtw_cbuf_empty23a - test if cbuf is empty
350 * @cbuf: pointer of struct rtw_cbuf
351 *
352 * Returns: true if cbuf is empty
353 */
354inline bool rtw_cbuf_empty23a(struct rtw_cbuf *cbuf)
355{
356 return (cbuf->write == cbuf->read) ? true : false;
357}
358
359/**
360 * rtw_cbuf_push23a - push a pointer into cbuf
361 * @cbuf: pointer of struct rtw_cbuf
362 * @buf: pointer to push in
363 *
364 * Lock free operation, be careful of the use scheme
365 * Returns: true push success
366 */
367bool rtw_cbuf_push23a(struct rtw_cbuf *cbuf, void *buf)
368{
369 if (rtw_cbuf_full23a(cbuf))
370 return _FAIL;
371
372 if (0)
373 DBG_8723A("%s on %u\n", __func__, cbuf->write);
374 cbuf->bufs[cbuf->write] = buf;
375 cbuf->write = (cbuf->write+1)%cbuf->size;
376
377 return _SUCCESS;
378}
379
380/**
381 * rtw_cbuf_pop23a - pop a pointer from cbuf
382 * @cbuf: pointer of struct rtw_cbuf
383 *
384 * Lock free operation, be careful of the use scheme
385 * Returns: pointer popped out
386 */
387void *rtw_cbuf_pop23a(struct rtw_cbuf *cbuf)
388{
389 void *buf;
390 if (rtw_cbuf_empty23a(cbuf))
391 return NULL;
392
393 if (0)
394 DBG_8723A("%s on %u\n", __func__, cbuf->read);
395 buf = cbuf->bufs[cbuf->read];
396 cbuf->read = (cbuf->read+1)%cbuf->size;
397
398 return buf;
399}
400
401/**
402 * rtw_cbuf_alloc23a - allocte a rtw_cbuf with given size and do initialization
403 * @size: size of pointer
404 *
405 * Returns: pointer of srtuct rtw_cbuf, NULL for allocation failure
406 */
407struct rtw_cbuf *rtw_cbuf_alloc23a(u32 size)
408{
409 struct rtw_cbuf *cbuf;
410
411 cbuf = kmalloc(sizeof(*cbuf) + sizeof(void *)*size, GFP_KERNEL);
412
413 if (cbuf) {
414 cbuf->write = 0;
415 cbuf->read = 0;
416 cbuf->size = size;
417 }
418
419 return cbuf;
420}
421
422/**
423 * rtw_cbuf_free - free the given rtw_cbuf
424 * @cbuf: pointer of struct rtw_cbuf to free
425 */
426void rtw_cbuf_free(struct rtw_cbuf *cbuf)
427{
428 kfree(cbuf);
429}
diff --git a/drivers/staging/rtl8723au/os_dep/recv_linux.c b/drivers/staging/rtl8723au/os_dep/recv_linux.c
new file mode 100644
index 000000000000..84402a589f25
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/recv_linux.c
@@ -0,0 +1,225 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RECV_OSDEP_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19
20#include <wifi.h>
21#include <recv_osdep.h>
22
23#include <osdep_intf.h>
24#include <ethernet.h>
25
26#include <usb_ops.h>
27
28/* alloc os related resource in struct recv_frame */
29int rtw_os_recv_resource_alloc23a(struct rtw_adapter *padapter,
30 struct recv_frame *precvframe)
31{
32 int res = _SUCCESS;
33
34 precvframe->pkt = NULL;
35
36 return res;
37}
38
39/* alloc os related resource in struct recv_buf */
40int rtw_os_recvbuf_resource_alloc23a(struct rtw_adapter *padapter,
41 struct recv_buf *precvbuf)
42{
43 int res = _SUCCESS;
44
45 precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
46 if (precvbuf->purb == NULL)
47 res = _FAIL;
48
49 precvbuf->pskb = NULL;
50
51 return res;
52}
53
54/* free os related resource in struct recv_buf */
55int rtw_os_recvbuf_resource_free23a(struct rtw_adapter *padapter,
56 struct recv_buf *precvbuf)
57{
58 int ret = _SUCCESS;
59
60 usb_free_urb(precvbuf->purb);
61
62 if (precvbuf->pskb)
63 dev_kfree_skb_any(precvbuf->pskb);
64
65 return ret;
66}
67
68void rtw_handle_tkip_mic_err23a(struct rtw_adapter *padapter, u8 bgroup)
69{
70 enum nl80211_key_type key_type = 0;
71 union iwreq_data wrqu;
72 struct iw_michaelmicfailure ev;
73 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
74 struct security_priv *psecuritypriv = &padapter->securitypriv;
75 unsigned long cur_time;
76
77 if (psecuritypriv->last_mic_err_time == 0) {
78 psecuritypriv->last_mic_err_time = jiffies;
79 } else {
80 cur_time = jiffies;
81
82 if (cur_time - psecuritypriv->last_mic_err_time < 60*HZ) {
83 psecuritypriv->btkip_countermeasure = true;
84 psecuritypriv->last_mic_err_time = 0;
85 psecuritypriv->btkip_countermeasure_time = cur_time;
86 } else {
87 psecuritypriv->last_mic_err_time = jiffies;
88 }
89 }
90
91 if (bgroup)
92 key_type |= NL80211_KEYTYPE_GROUP;
93 else
94 key_type |= NL80211_KEYTYPE_PAIRWISE;
95
96 cfg80211_michael_mic_failure(padapter->pnetdev,
97 (u8 *)&pmlmepriv->assoc_bssid[0],
98 key_type, -1, NULL, GFP_ATOMIC);
99
100 memset(&ev, 0x00, sizeof(ev));
101 if (bgroup)
102 ev.flags |= IW_MICFAILURE_GROUP;
103 else
104 ev.flags |= IW_MICFAILURE_PAIRWISE;
105
106 ev.src_addr.sa_family = ARPHRD_ETHER;
107 ether_addr_copy(ev.src_addr.sa_data, &pmlmepriv->assoc_bssid[0]);
108
109 memset(&wrqu, 0x00, sizeof(wrqu));
110 wrqu.data.length = sizeof(ev);
111}
112
113void rtw_hostapd_mlme_rx23a(struct rtw_adapter *padapter,
114 struct recv_frame *precv_frame)
115{
116}
117
118int rtw_recv_indicatepkt23a(struct rtw_adapter *padapter,
119 struct recv_frame *precv_frame)
120{
121 struct recv_priv *precvpriv;
122 struct rtw_queue *pfree_recv_queue;
123 struct sk_buff *skb;
124 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
125
126 precvpriv = &(padapter->recvpriv);
127 pfree_recv_queue = &(precvpriv->free_recv_queue);
128
129 skb = precv_frame->pkt;
130 if (!skb) {
131 RT_TRACE(_module_recv_osdep_c_, _drv_err_,
132 ("rtw_recv_indicatepkt23a():skb == NULL!!!!\n"));
133 goto _recv_indicatepkt_drop;
134 }
135
136 RT_TRACE(_module_recv_osdep_c_, _drv_info_,
137 ("rtw_recv_indicatepkt23a():skb != NULL !!!\n"));
138 RT_TRACE(_module_recv_osdep_c_, _drv_info_,
139 ("rtw_recv_indicatepkt23a():precv_frame->hdr.rx_data =%p\n",
140 precv_frame->pkt->data));
141 RT_TRACE(_module_recv_osdep_c_, _drv_info_,
142 ("\n skb->head =%p skb->data =%p skb->tail =%p skb->end =%p skb->len =%d\n",
143 skb->head, skb->data,
144 skb_tail_pointer(skb), skb_end_pointer(skb), skb->len));
145
146 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
147 struct sk_buff *pskb2 = NULL;
148 struct sta_info *psta = NULL;
149 struct sta_priv *pstapriv = &padapter->stapriv;
150 struct rx_pkt_attrib *pattrib = &precv_frame->attrib;
151 int bmcast = is_multicast_ether_addr(pattrib->dst);
152
153 /* DBG_8723A("bmcast =%d\n", bmcast); */
154
155 if (!ether_addr_equal(pattrib->dst,
156 myid(&padapter->eeprompriv))) {
157 /* DBG_8723A("not ap psta =%p, addr =%pM\n", psta, pattrib->dst); */
158 if (bmcast) {
159 psta = rtw_get_bcmc_stainfo23a(padapter);
160 pskb2 = skb_clone(skb, GFP_ATOMIC);
161 } else {
162 psta = rtw_get_stainfo23a(pstapriv, pattrib->dst);
163 }
164
165 if (psta) {
166 struct net_device *pnetdev = padapter->pnetdev;
167
168 /* DBG_8723A("directly forwarding to the rtw_xmit23a_entry23a\n"); */
169
170 /* skb->ip_summed = CHECKSUM_NONE; */
171 skb->dev = pnetdev;
172 skb_set_queue_mapping(skb, rtw_recv_select_queue23a(skb));
173
174 rtw_xmit23a_entry23a(skb, pnetdev);
175
176 if (bmcast)
177 skb = pskb2;
178 else
179 goto _recv_indicatepkt_end;
180 }
181 } else { /* to APself */
182 /* DBG_8723A("to APSelf\n"); */
183 }
184 }
185
186 skb->ip_summed = CHECKSUM_NONE;
187 skb->dev = padapter->pnetdev;
188 skb->protocol = eth_type_trans(skb, padapter->pnetdev);
189
190 netif_rx(skb);
191
192_recv_indicatepkt_end:
193
194 precv_frame->pkt = NULL; /* pointers to NULL before rtw_free_recvframe23a() */
195
196 rtw_free_recvframe23a(precv_frame, pfree_recv_queue);
197
198 RT_TRACE(_module_recv_osdep_c_, _drv_info_,
199 ("\n rtw_recv_indicatepkt23a :after netif_rx!!!!\n"));
200 return _SUCCESS;
201
202_recv_indicatepkt_drop:
203
204 rtw_free_recvframe23a(precv_frame, pfree_recv_queue);
205 return _FAIL;
206}
207
208void rtw_os_read_port23a(struct rtw_adapter *padapter, struct recv_buf *precvbuf)
209{
210 struct recv_priv *precvpriv = &padapter->recvpriv;
211
212 /* free skb in recv_buf */
213 dev_kfree_skb_any(precvbuf->pskb);
214
215 precvbuf->pskb = NULL;
216
217 rtw_read_port(padapter, precvpriv->ff_hwaddr, 0, precvbuf);
218}
219
220void rtw_init_recv_timer23a(struct recv_reorder_ctrl *preorder_ctrl)
221{
222 setup_timer(&preorder_ctrl->reordering_ctrl_timer,
223 rtw_reordering_ctrl_timeout_handler23a,
224 (unsigned long)preorder_ctrl);
225}
diff --git a/drivers/staging/rtl8723au/os_dep/usb_intf.c b/drivers/staging/rtl8723au/os_dep/usb_intf.c
new file mode 100644
index 000000000000..040bf29b9d06
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/usb_intf.c
@@ -0,0 +1,836 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _HCI_INTF_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <recv_osdep.h>
20#include <xmit_osdep.h>
21#include <hal_intf.h>
22#include <rtw_version.h>
23#include <osdep_intf.h>
24#include <usb_vendor_req.h>
25#include <usb_ops.h>
26#include <usb_osintf.h>
27#include <usb_hal.h>
28
29static int rtw_suspend(struct usb_interface *intf, pm_message_t message);
30static int rtw_resume(struct usb_interface *intf);
31static int rtw_drv_init(struct usb_interface *pusb_intf,
32 const struct usb_device_id *pdid);
33static void rtw_disconnect(struct usb_interface *pusb_intf);
34
35#define USB_VENDER_ID_REALTEK 0x0BDA
36
37#define RTL8723A_USB_IDS \
38 {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x8724, \
39 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ \
40 {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x1724, \
41 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */ \
42 {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDER_ID_REALTEK, 0x0724, \
43 0xff, 0xff, 0xff)}, /* 8723AU 1*1 */
44
45static struct usb_device_id rtl8723a_usb_id_tbl[] = {
46 RTL8723A_USB_IDS
47 {} /* Terminating entry */
48};
49
50MODULE_DEVICE_TABLE(usb, rtl8723a_usb_id_tbl);
51
52static struct usb_driver rtl8723a_usb_drv = {
53 .name = (char *)"rtl8723au",
54 .probe = rtw_drv_init,
55 .disconnect = rtw_disconnect,
56 .id_table = rtl8723a_usb_id_tbl,
57 .suspend = rtw_suspend,
58 .resume = rtw_resume,
59 .reset_resume = rtw_resume,
60};
61
62static struct usb_driver *usb_drv = &rtl8723a_usb_drv;
63
64static inline int RT_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
65{
66 return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN;
67}
68
69static inline int RT_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
70{
71 return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
72}
73
74static inline int RT_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
75{
76 return (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT;
77}
78
79static inline int RT_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
80{
81 return (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK;
82}
83
84static inline int RT_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
85{
86 return RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_in(epd);
87}
88
89static inline int RT_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
90{
91 return RT_usb_endpoint_xfer_bulk(epd) && RT_usb_endpoint_dir_out(epd);
92}
93
94static inline int RT_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
95{
96 return RT_usb_endpoint_xfer_int(epd) && RT_usb_endpoint_dir_in(epd);
97}
98
99static inline int RT_usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
100{
101 return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
102}
103
104static u8 rtw_init_intf_priv(struct dvobj_priv *dvobj)
105{
106 u8 rst = _SUCCESS;
107
108 mutex_init(&dvobj->usb_vendor_req_mutex);
109 dvobj->usb_alloc_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE,
110 GFP_KERNEL);
111 if (dvobj->usb_alloc_vendor_req_buf == NULL) {
112 DBG_8723A("alloc usb_vendor_req_buf failed... /n");
113 rst = _FAIL;
114 goto exit;
115 }
116 dvobj->usb_vendor_req_buf =
117 PTR_ALIGN(dvobj->usb_alloc_vendor_req_buf, ALIGNMENT_UNIT);
118exit:
119 return rst;
120}
121
122static u8 rtw_deinit_intf_priv(struct dvobj_priv *dvobj)
123{
124 u8 rst = _SUCCESS;
125
126 kfree(dvobj->usb_alloc_vendor_req_buf);
127
128 mutex_destroy(&dvobj->usb_vendor_req_mutex);
129
130 return rst;
131}
132
133static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
134{
135 struct dvobj_priv *pdvobjpriv;
136 struct usb_device_descriptor *pdev_desc;
137 struct usb_host_config *phost_conf;
138 struct usb_config_descriptor *pconf_desc;
139 struct usb_host_interface *phost_iface;
140 struct usb_interface_descriptor *piface_desc;
141 struct usb_host_endpoint *phost_endp;
142 struct usb_endpoint_descriptor *pendp_desc;
143 struct usb_device *pusbd;
144 int i;
145 int status = _FAIL;
146
147 pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
148 if (!pdvobjpriv)
149 goto exit;
150
151 mutex_init(&pdvobjpriv->hw_init_mutex);
152 mutex_init(&pdvobjpriv->h2c_fwcmd_mutex);
153 mutex_init(&pdvobjpriv->setch_mutex);
154 mutex_init(&pdvobjpriv->setbw_mutex);
155
156 pdvobjpriv->pusbintf = usb_intf;
157 pusbd = interface_to_usbdev(usb_intf);
158 pdvobjpriv->pusbdev = pusbd;
159 usb_set_intfdata(usb_intf, pdvobjpriv);
160
161 pdvobjpriv->RtNumInPipes = 0;
162 pdvobjpriv->RtNumOutPipes = 0;
163
164 pdev_desc = &pusbd->descriptor;
165
166 phost_conf = pusbd->actconfig;
167 pconf_desc = &phost_conf->desc;
168
169 phost_iface = &usb_intf->altsetting[0];
170 piface_desc = &phost_iface->desc;
171
172 pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
173 pdvobjpriv->InterfaceNumber = piface_desc->bInterfaceNumber;
174 pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
175
176 for (i = 0; i < pdvobjpriv->nr_endpoint; i++) {
177 phost_endp = phost_iface->endpoint + i;
178 if (phost_endp) {
179 pendp_desc = &phost_endp->desc;
180
181 DBG_8723A("\nusb_endpoint_descriptor(%d):\n", i);
182 DBG_8723A("bLength =%x\n", pendp_desc->bLength);
183 DBG_8723A("bDescriptorType =%x\n",
184 pendp_desc->bDescriptorType);
185 DBG_8723A("bEndpointAddress =%x\n",
186 pendp_desc->bEndpointAddress);
187 DBG_8723A("wMaxPacketSize =%d\n",
188 le16_to_cpu(pendp_desc->wMaxPacketSize));
189 DBG_8723A("bInterval =%x\n", pendp_desc->bInterval);
190
191 if (RT_usb_endpoint_is_bulk_in(pendp_desc)) {
192 DBG_8723A("RT_usb_endpoint_is_bulk_in = %x\n",
193 RT_usb_endpoint_num(pendp_desc));
194 pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] =
195 RT_usb_endpoint_num(pendp_desc);
196 pdvobjpriv->RtNumInPipes++;
197 } else if (RT_usb_endpoint_is_int_in(pendp_desc)) {
198 DBG_8723A("RT_usb_endpoint_is_int_in = %x, Interval = %x\n",
199 RT_usb_endpoint_num(pendp_desc),
200 pendp_desc->bInterval);
201 pdvobjpriv->RtInPipe[pdvobjpriv->RtNumInPipes] =
202 RT_usb_endpoint_num(pendp_desc);
203 pdvobjpriv->RtNumInPipes++;
204 } else if (RT_usb_endpoint_is_bulk_out(pendp_desc)) {
205 DBG_8723A("RT_usb_endpoint_is_bulk_out = %x\n",
206 RT_usb_endpoint_num(pendp_desc));
207 pdvobjpriv->RtOutPipe[pdvobjpriv->RtNumOutPipes] =
208 RT_usb_endpoint_num(pendp_desc);
209 pdvobjpriv->RtNumOutPipes++;
210 }
211 pdvobjpriv->ep_num[i] = RT_usb_endpoint_num(pendp_desc);
212 }
213 }
214 DBG_8723A("nr_endpoint =%d, in_num =%d, out_num =%d\n\n",
215 pdvobjpriv->nr_endpoint, pdvobjpriv->RtNumInPipes,
216 pdvobjpriv->RtNumOutPipes);
217
218 if (pusbd->speed == USB_SPEED_HIGH) {
219 pdvobjpriv->ishighspeed = true;
220 DBG_8723A("USB_SPEED_HIGH\n");
221 } else {
222 pdvobjpriv->ishighspeed = false;
223 DBG_8723A("NON USB_SPEED_HIGH\n");
224 }
225
226 if (rtw_init_intf_priv(pdvobjpriv) == _FAIL) {
227 RT_TRACE(_module_os_intfs_c_, _drv_err_,
228 ("\n Can't INIT rtw_init_intf_priv\n"));
229 goto free_dvobj;
230 }
231 /* 3 misc */
232 sema_init(&(pdvobjpriv->usb_suspend_sema), 0);
233 rtw_reset_continual_urb_error(pdvobjpriv);
234 usb_get_dev(pusbd);
235 status = _SUCCESS;
236free_dvobj:
237 if (status != _SUCCESS && pdvobjpriv) {
238 usb_set_intfdata(usb_intf, NULL);
239 mutex_destroy(&pdvobjpriv->hw_init_mutex);
240 mutex_destroy(&pdvobjpriv->h2c_fwcmd_mutex);
241 mutex_destroy(&pdvobjpriv->setch_mutex);
242 mutex_destroy(&pdvobjpriv->setbw_mutex);
243 kfree(pdvobjpriv);
244 pdvobjpriv = NULL;
245 }
246exit:
247 return pdvobjpriv;
248}
249
250static void usb_dvobj_deinit(struct usb_interface *usb_intf)
251{
252 struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
253
254 usb_set_intfdata(usb_intf, NULL);
255 if (dvobj) {
256 /* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
257 if ((dvobj->NumInterfaces != 2 && dvobj->NumInterfaces != 3) ||
258 (dvobj->InterfaceNumber == 1)) {
259 if (interface_to_usbdev(usb_intf)->state !=
260 USB_STATE_NOTATTACHED) {
261 /* If we didn't unplug usb dongle and
262 * remove/insert module, driver fails on
263 * sitesurvey for the first time when
264 * device is up .
265 * Reset usb port for sitesurvey fail issue.
266 */
267 DBG_8723A("usb attached..., try to reset usb device\n");
268 usb_reset_device(interface_to_usbdev(usb_intf));
269 }
270 }
271 rtw_deinit_intf_priv(dvobj);
272 mutex_destroy(&dvobj->hw_init_mutex);
273 mutex_destroy(&dvobj->h2c_fwcmd_mutex);
274 mutex_destroy(&dvobj->setch_mutex);
275 mutex_destroy(&dvobj->setbw_mutex);
276 kfree(dvobj);
277 }
278 usb_put_dev(interface_to_usbdev(usb_intf));
279}
280
281static void decide_chip_type_by_usb_device_id(struct rtw_adapter *padapter,
282 const struct usb_device_id *pdid)
283{
284 padapter->chip_type = NULL_CHIP_TYPE;
285 hal_set_hw_type(padapter);
286}
287
288static void usb_intf_start(struct rtw_adapter *padapter)
289{
290 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_start\n"));
291 rtw_hal_inirp_init23a(padapter);
292 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_start\n"));
293}
294
295static void usb_intf_stop(struct rtw_adapter *padapter)
296{
297 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+usb_intf_stop\n"));
298
299 /* disable_hw_interrupt */
300 if (!padapter->bSurpriseRemoved) {
301 /* device still exists, so driver can do i/o operation
302 * TODO:
303 */
304 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
305 ("SurpriseRemoved == false\n"));
306 }
307
308 /* cancel in irp */
309 rtw_hal_inirp_deinit23a(padapter);
310
311 /* cancel out irp */
312 rtw_write_port_cancel(padapter);
313
314 /* todo:cancel other irps */
315 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-usb_intf_stop\n"));
316}
317
318static void rtw_dev_unload(struct rtw_adapter *padapter)
319{
320 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n"));
321
322 if (padapter->bup) {
323 DBG_8723A("===> rtw_dev_unload\n");
324
325 padapter->bDriverStopped = true;
326 if (padapter->xmitpriv.ack_tx)
327 rtw_ack_tx_done23a(&padapter->xmitpriv,
328 RTW_SCTX_DONE_DRV_STOP);
329
330 /* s3. */
331 if (padapter->intf_stop)
332 padapter->intf_stop(padapter);
333
334 /* s4. */
335 if (!padapter->pwrctrlpriv.bInternalAutoSuspend)
336 rtw_stop_drv_threads23a(padapter);
337
338 /* s5. */
339 if (!padapter->bSurpriseRemoved) {
340 rtw_hal_deinit23a(padapter);
341 padapter->bSurpriseRemoved = true;
342 }
343 padapter->bup = false;
344 } else {
345 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
346 ("r871x_dev_unload():padapter->bup == false\n"));
347 }
348 DBG_8723A("<=== rtw_dev_unload\n");
349 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
350}
351
352int rtw_hw_suspend23a(struct rtw_adapter *padapter)
353{
354 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
355 struct net_device *pnetdev = padapter->pnetdev;
356
357 if ((!padapter->bup) || (padapter->bDriverStopped) ||
358 (padapter->bSurpriseRemoved)) {
359 DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n",
360 padapter->bup, padapter->bDriverStopped,
361 padapter->bSurpriseRemoved);
362 goto error_exit;
363 }
364
365 if (padapter) { /* system suspend */
366 LeaveAllPowerSaveMode23a(padapter);
367
368 DBG_8723A("==> rtw_hw_suspend23a\n");
369 down(&pwrpriv->lock);
370 pwrpriv->bips_processing = true;
371 /* padapter->net_closed = true; */
372 /* s1. */
373 if (pnetdev) {
374 netif_carrier_off(pnetdev);
375 netif_tx_stop_all_queues(pnetdev);
376 }
377
378 /* s2. */
379 rtw_disassoc_cmd23a(padapter, 500, false);
380
381 /* s2-2. indicate disconnect to os */
382 /* rtw_indicate_disconnect23a(padapter); */
383 {
384 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
385
386 if (check_fwstate(pmlmepriv, _FW_LINKED)) {
387 _clr_fwstate_(pmlmepriv, _FW_LINKED);
388
389 rtw_led_control(padapter, LED_CTL_NO_LINK);
390
391 rtw_os_indicate_disconnect23a(padapter);
392
393 /* donnot enqueue cmd */
394 rtw_lps_ctrl_wk_cmd23a(padapter,
395 LPS_CTRL_DISCONNECT, 0);
396 }
397 }
398 /* s2-3. */
399 rtw_free_assoc_resources23a(padapter, 1);
400
401 /* s2-4. */
402 rtw_free_network_queue23a(padapter, true);
403 rtw_ips_dev_unload23a(padapter);
404 pwrpriv->rf_pwrstate = rf_off;
405 pwrpriv->bips_processing = false;
406 up(&pwrpriv->lock);
407 } else {
408 goto error_exit;
409 }
410 return 0;
411error_exit:
412 DBG_8723A("%s, failed\n", __func__);
413 return -1;
414}
415
416int rtw_hw_resume23a(struct rtw_adapter *padapter)
417{
418 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
419 struct net_device *pnetdev = padapter->pnetdev;
420
421 if (padapter) { /* system resume */
422 DBG_8723A("==> rtw_hw_resume23a\n");
423 down(&pwrpriv->lock);
424 pwrpriv->bips_processing = true;
425 rtw_reset_drv_sw23a(padapter);
426
427 if (pm_netdev_open23a(pnetdev, false)) {
428 up(&pwrpriv->lock);
429 goto error_exit;
430 }
431
432 netif_device_attach(pnetdev);
433 netif_carrier_on(pnetdev);
434
435 if (!rtw_netif_queue_stopped(pnetdev))
436 netif_tx_start_all_queues(pnetdev);
437 else
438 netif_tx_wake_all_queues(pnetdev);
439
440 pwrpriv->bkeepfwalive = false;
441 pwrpriv->brfoffbyhw = false;
442
443 pwrpriv->rf_pwrstate = rf_on;
444 pwrpriv->bips_processing = false;
445
446 up(&pwrpriv->lock);
447 } else {
448 goto error_exit;
449 }
450 return 0;
451error_exit:
452 DBG_8723A("%s, Open net dev failed\n", __func__);
453 return -1;
454}
455
456static int rtw_suspend(struct usb_interface *pusb_intf, pm_message_t message)
457{
458 struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
459 struct rtw_adapter *padapter = dvobj->if1;
460 struct net_device *pnetdev = padapter->pnetdev;
461 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
462 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
463 int ret = 0;
464 unsigned long start_time = jiffies;
465
466 DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
467
468 if ((!padapter->bup) || (padapter->bDriverStopped) ||
469 (padapter->bSurpriseRemoved)) {
470 DBG_8723A("padapter->bup =%d bDriverStopped =%d bSurpriseRemoved = %d\n",
471 padapter->bup, padapter->bDriverStopped,
472 padapter->bSurpriseRemoved);
473 goto exit;
474 }
475 pwrpriv->bInSuspend = true;
476 rtw_cancel_all_timer23a(padapter);
477 LeaveAllPowerSaveMode23a(padapter);
478
479 down(&pwrpriv->lock);
480 /* padapter->net_closed = true; */
481 /* s1. */
482 if (pnetdev) {
483 netif_carrier_off(pnetdev);
484 netif_tx_stop_all_queues(pnetdev);
485 }
486
487 /* s2. */
488 rtw_disassoc_cmd23a(padapter, 0, false);
489
490 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
491 check_fwstate(pmlmepriv, _FW_LINKED)) {
492 DBG_8723A("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
493 __func__, __LINE__,
494 pmlmepriv->cur_network.network.Ssid.ssid,
495 pmlmepriv->cur_network.network.MacAddress,
496 pmlmepriv->cur_network.network.Ssid.ssid_len,
497 pmlmepriv->assoc_ssid.ssid_len);
498
499 rtw_set_roaming(padapter, 1);
500 }
501 /* s2-2. indicate disconnect to os */
502 rtw_indicate_disconnect23a(padapter);
503 /* s2-3. */
504 rtw_free_assoc_resources23a(padapter, 1);
505 /* s2-4. */
506 rtw_free_network_queue23a(padapter, true);
507
508 rtw_dev_unload(padapter);
509 up(&pwrpriv->lock);
510
511 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
512 rtw_indicate_scan_done23a(padapter, 1);
513
514 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
515 rtw_indicate_disconnect23a(padapter);
516
517exit:
518 DBG_8723A("<=== %s return %d.............. in %dms\n", __func__,
519 ret, jiffies_to_msecs(jiffies - start_time));
520
521 return ret;
522}
523
524static int rtw_resume(struct usb_interface *pusb_intf)
525{
526 struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
527 struct rtw_adapter *padapter = dvobj->if1;
528 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
529 int ret = 0;
530
531 if (pwrpriv->bInternalAutoSuspend)
532 ret = rtw_resume_process23a(padapter);
533 else
534 ret = rtw_resume_process23a(padapter);
535
536 return ret;
537}
538
539int rtw_resume_process23a(struct rtw_adapter *padapter)
540{
541 struct net_device *pnetdev;
542 struct pwrctrl_priv *pwrpriv = NULL;
543 int ret = -1;
544 unsigned long start_time = jiffies;
545
546 DBG_8723A("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
547
548 if (!padapter)
549 goto exit;
550 pnetdev = padapter->pnetdev;
551 pwrpriv = &padapter->pwrctrlpriv;
552
553 down(&pwrpriv->lock);
554 rtw_reset_drv_sw23a(padapter);
555 pwrpriv->bkeepfwalive = false;
556
557 DBG_8723A("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
558 if (pm_netdev_open23a(pnetdev, true) != 0)
559 goto exit;
560
561 netif_device_attach(pnetdev);
562 netif_carrier_on(pnetdev);
563
564 up(&pwrpriv->lock);
565
566 if (padapter->pid[1] != 0) {
567 DBG_8723A("pid[1]:%d\n", padapter->pid[1]);
568 rtw_signal_process(padapter->pid[1], SIGUSR2);
569 }
570
571 rtw23a_roaming(padapter, NULL);
572
573 ret = 0;
574exit:
575 if (pwrpriv)
576 pwrpriv->bInSuspend = false;
577 DBG_8723A("<=== %s return %d.............. in %dms\n", __func__,
578 ret, jiffies_to_msecs(jiffies - start_time));
579
580 return ret;
581}
582
583/*
584 * drv_init() - a device potentially for us
585 *
586 * notes: drv_init() is called when the bus driver has located a card
587 * for us to support.
588 * We accept the new device by returning 0.
589 */
590static struct rtw_adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
591 struct usb_interface *pusb_intf,
592 const struct usb_device_id *pdid)
593{
594 struct rtw_adapter *padapter = NULL;
595 struct net_device *pnetdev = NULL;
596 int status = _FAIL;
597
598 pnetdev = rtw_init_netdev23a(padapter);
599 if (!pnetdev)
600 goto handle_dualmac;
601 padapter = netdev_priv(pnetdev);
602
603 padapter->dvobj = dvobj;
604 padapter->bDriverStopped = true;
605 dvobj->if1 = padapter;
606 dvobj->padapters[dvobj->iface_nums++] = padapter;
607 padapter->iface_id = IFACE_ID0;
608
609 /* step 1-1., decide the chip_type via vid/pid */
610 decide_chip_type_by_usb_device_id(padapter, pdid);
611
612 if (rtw_handle_dualmac23a(padapter, 1) != _SUCCESS)
613 goto free_adapter;
614
615 SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
616
617 if (rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj)))
618 goto handle_dualmac;
619
620 /* step 2. hook HalFunc, allocate HalData */
621 if (rtl8723au_set_hal_ops(padapter))
622 return NULL;
623
624 padapter->intf_start = &usb_intf_start;
625 padapter->intf_stop = &usb_intf_stop;
626
627 /* step init_io_priv */
628 rtw_init_io_priv23a(padapter, usb_set_intf_ops);
629
630 /* step read_chip_version */
631 rtw_hal_read_chip_version23a(padapter);
632
633 /* step usb endpoint mapping */
634 rtw_hal_chip_configure23a(padapter);
635
636 /* step read efuse/eeprom data and get mac_addr */
637 rtw_hal_read_chip_info23a(padapter);
638
639 /* step 5. */
640 if (rtw_init_drv_sw23a(padapter) == _FAIL) {
641 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
642 ("Initialize driver software resource Failed!\n"));
643 goto free_hal_data;
644 }
645
646#ifdef CONFIG_PM
647 if (padapter->pwrctrlpriv.bSupportRemoteWakeup) {
648 dvobj->pusbdev->do_remote_wakeup = 1;
649 pusb_intf->needs_remote_wakeup = 1;
650 device_init_wakeup(&pusb_intf->dev, 1);
651 DBG_8723A("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
652 DBG_8723A("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
653 device_may_wakeup(&pusb_intf->dev));
654 }
655#endif
656 /* 2012-07-11 Move here to prevent the 8723AS-VAU BT
657 * auto suspend influence
658 */
659 if (usb_autopm_get_interface(pusb_intf) < 0)
660 DBG_8723A("can't get autopm:\n");
661#ifdef CONFIG_8723AU_BT_COEXIST
662 padapter->pwrctrlpriv.autopm_cnt = 1;
663#endif
664
665 /* set mac addr */
666 rtw_macaddr_cfg23a(padapter->eeprompriv.mac_addr);
667 rtw_init_wifidirect_addrs23a(padapter, padapter->eeprompriv.mac_addr,
668 padapter->eeprompriv.mac_addr);
669
670 DBG_8723A("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n",
671 padapter->bDriverStopped, padapter->bSurpriseRemoved,
672 padapter->bup, padapter->hw_init_completed
673 );
674 status = _SUCCESS;
675
676free_hal_data:
677 if (status != _SUCCESS)
678 kfree(padapter->HalData);
679 if (status != _SUCCESS) {
680 rtw_wdev_unregister(padapter->rtw_wdev);
681 rtw_wdev_free(padapter->rtw_wdev);
682 }
683handle_dualmac:
684 if (status != _SUCCESS)
685 rtw_handle_dualmac23a(padapter, 0);
686free_adapter:
687 if (status != _SUCCESS) {
688 if (pnetdev)
689 free_netdev(pnetdev);
690 padapter = NULL;
691 }
692 return padapter;
693}
694
695static void rtw_usb_if1_deinit(struct rtw_adapter *if1)
696{
697 struct net_device *pnetdev = if1->pnetdev;
698 struct mlme_priv *pmlmepriv = &if1->mlmepriv;
699
700 if (check_fwstate(pmlmepriv, _FW_LINKED))
701 rtw_disassoc_cmd23a(if1, 0, false);
702
703#ifdef CONFIG_8723AU_AP_MODE
704 free_mlme_ap_info23a(if1);
705#endif
706
707 if (pnetdev)
708 unregister_netdev(pnetdev); /* will call netdev_close() */
709
710 rtw_cancel_all_timer23a(if1);
711
712 rtw_dev_unload(if1);
713
714 DBG_8723A("+r871xu_dev_remove, hw_init_completed =%d\n",
715 if1->hw_init_completed);
716
717 rtw_handle_dualmac23a(if1, 0);
718
719 if (if1->rtw_wdev) {
720 rtw_wdev_unregister(if1->rtw_wdev);
721 rtw_wdev_free(if1->rtw_wdev);
722 }
723
724#ifdef CONFIG_8723AU_BT_COEXIST
725 if (1 == if1->pwrctrlpriv.autopm_cnt) {
726 usb_autopm_put_interface(adapter_to_dvobj(if1)->pusbintf);
727 if1->pwrctrlpriv.autopm_cnt--;
728 }
729#endif
730
731 rtw_free_drv_sw23a(if1);
732
733 if (pnetdev)
734 free_netdev(pnetdev);
735}
736
737static int rtw_drv_init(struct usb_interface *pusb_intf,
738 const struct usb_device_id *pdid)
739{
740 struct rtw_adapter *if1 = NULL;
741 struct dvobj_priv *dvobj;
742 int status = _FAIL;
743
744 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
745
746 /* Initialize dvobj_priv */
747 dvobj = usb_dvobj_init(pusb_intf);
748 if (!dvobj) {
749 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
750 ("initialize device object priv Failed!\n"));
751 goto exit;
752 }
753
754 if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid);
755 if (!if1) {
756 DBG_8723A("rtw_init_primary_adapter Failed!\n");
757 goto free_dvobj;
758 }
759
760 /* dev_alloc_name && register_netdev */
761 status = rtw_drv_register_netdev(if1);
762 if (status != _SUCCESS)
763 goto free_if1;
764 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
765 ("-871x_drv - drv_init, success!\n"));
766
767 status = _SUCCESS;
768
769free_if1:
770 if (status != _SUCCESS && if1)
771 rtw_usb_if1_deinit(if1);
772free_dvobj:
773 if (status != _SUCCESS)
774 usb_dvobj_deinit(pusb_intf);
775exit:
776 return status == _SUCCESS ? 0 : -ENODEV;
777}
778
779/* dev_remove() - our device is being removed */
780static void rtw_disconnect(struct usb_interface *pusb_intf)
781{
782 struct dvobj_priv *dvobj;
783 struct rtw_adapter *padapter;
784 struct net_device *pnetdev;
785 struct mlme_priv *pmlmepriv;
786
787 dvobj = usb_get_intfdata(pusb_intf);
788 if (!dvobj)
789 return;
790
791 padapter = dvobj->if1;
792 pnetdev = padapter->pnetdev;
793 pmlmepriv = &padapter->mlmepriv;
794
795 usb_set_intfdata(pusb_intf, NULL);
796
797 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
798
799 rtw_pm_set_ips23a(padapter, IPS_NONE);
800 rtw_pm_set_lps23a(padapter, PS_MODE_ACTIVE);
801
802 LeaveAllPowerSaveMode23a(padapter);
803
804 rtw_usb_if1_deinit(padapter);
805
806 usb_dvobj_deinit(pusb_intf);
807
808 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n"));
809 DBG_8723A("-r871xu_dev_remove, done\n");
810
811 return;
812}
813
814extern int console_suspend_enabled;
815
816static int __init rtw_drv_entry(void)
817{
818 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_entry\n"));
819 rtw_suspend_lock_init();
820 return usb_register(usb_drv);
821}
822
823static void __exit rtw_drv_halt(void)
824{
825 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_halt\n"));
826 DBG_8723A("+rtw_drv_halt\n");
827
828 rtw_suspend_lock_uninit();
829
830 usb_deregister(usb_drv);
831
832 DBG_8723A("-rtw_drv_halt\n");
833}
834
835module_init(rtw_drv_entry);
836module_exit(rtw_drv_halt);
diff --git a/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c b/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c
new file mode 100644
index 000000000000..c49160e477d8
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/usb_ops_linux.c
@@ -0,0 +1,283 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _USB_OPS_LINUX_C_
16
17#include <drv_types.h>
18#include <usb_ops_linux.h>
19#include <rtw_sreset.h>
20
21unsigned int ffaddr2pipehdl23a(struct dvobj_priv *pdvobj, u32 addr)
22{
23 struct usb_device *pusbd = pdvobj->pusbdev;
24 unsigned int pipe = 0, ep_num = 0;
25
26 if (addr == RECV_BULK_IN_ADDR) {
27 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[0]);
28 } else if (addr == RECV_INT_IN_ADDR) {
29 pipe = usb_rcvbulkpipe(pusbd, pdvobj->RtInPipe[1]);
30 } else if (addr < HW_QUEUE_ENTRY) {
31 ep_num = pdvobj->Queue2Pipe[addr];
32 pipe = usb_sndbulkpipe(pusbd, ep_num);
33 }
34 return pipe;
35}
36
37struct zero_bulkout_context {
38 void *pbuf;
39 void *purb;
40 void *pirp;
41 void *padapter;
42};
43
44void usb_read_mem23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
45{
46}
47
48void usb_write_mem23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
49{
50}
51
52void usb_read_port_cancel23a(struct intf_hdl *pintfhdl)
53{
54 struct recv_buf *precvbuf;
55 struct rtw_adapter *padapter = pintfhdl->padapter;
56 int i;
57
58 precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
59
60 DBG_8723A("%s\n", __func__);
61
62 padapter->bReadPortCancel = true;
63
64 for (i = 0; i < NR_RECVBUFF ; i++) {
65 if (precvbuf->purb)
66 usb_kill_urb(precvbuf->purb);
67 precvbuf++;
68 }
69 usb_kill_urb(padapter->recvpriv.int_in_urb);
70}
71
72static void usb_write_port23a_complete(struct urb *purb, struct pt_regs *regs)
73{
74 struct xmit_buf *pxmitbuf = (struct xmit_buf *)purb->context;
75 struct rtw_adapter *padapter = pxmitbuf->padapter;
76 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
77 struct hal_data_8723a *phaldata;
78 unsigned long irqL;
79
80 switch (pxmitbuf->flags) {
81 case VO_QUEUE_INX:
82 pxmitpriv->voq_cnt--;
83 break;
84 case VI_QUEUE_INX:
85 pxmitpriv->viq_cnt--;
86 break;
87 case BE_QUEUE_INX:
88 pxmitpriv->beq_cnt--;
89 break;
90 case BK_QUEUE_INX:
91 pxmitpriv->bkq_cnt--;
92 break;
93 case HIGH_QUEUE_INX:
94#ifdef CONFIG_8723AU_AP_MODE
95 rtw_chk_hi_queue_cmd23a(padapter);
96#endif
97 break;
98 default:
99 break;
100 }
101
102 if (padapter->bSurpriseRemoved || padapter->bDriverStopped ||
103 padapter->bWritePortCancel) {
104 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
105 ("usb_write_port23a_complete:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
106 padapter->bDriverStopped, padapter->bSurpriseRemoved));
107 DBG_8723A("%s(): TX Warning! bDriverStopped(%d) OR bSurpriseRemoved(%d) bWritePortCancel(%d) pxmitbuf->ext_tag(%x)\n",
108 __func__, padapter->bDriverStopped,
109 padapter->bSurpriseRemoved, padapter->bReadPortCancel,
110 pxmitbuf->ext_tag);
111
112 goto check_completion;
113 }
114
115 if (purb->status) {
116 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
117 ("usb_write_port23a_complete : purb->status(%d) != 0\n",
118 purb->status));
119 DBG_8723A("###=> urb_write_port_complete status(%d)\n",
120 purb->status);
121 if ((purb->status == -EPIPE) || (purb->status == -EPROTO)) {
122 sreset_set_wifi_error_status23a(padapter,
123 USB_WRITE_PORT_FAIL);
124 } else if (purb->status == -EINPROGRESS) {
125 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
126 ("usb_write_port23a_complete: EINPROGESS\n"));
127 goto check_completion;
128 } else if (purb->status == -ENOENT) {
129 DBG_8723A("%s: -ENOENT\n", __func__);
130 goto check_completion;
131 } else if (purb->status == -ECONNRESET) {
132 DBG_8723A("%s: -ECONNRESET\n", __func__);
133 goto check_completion;
134 } else if (purb->status == -ESHUTDOWN) {
135 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
136 ("usb_write_port23a_complete: ESHUTDOWN\n"));
137 padapter->bDriverStopped = true;
138 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
139 ("usb_write_port23a_complete:bDriverStopped = true\n"));
140 goto check_completion;
141 } else {
142 padapter->bSurpriseRemoved = true;
143 DBG_8723A("bSurpriseRemoved = true\n");
144 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
145 ("usb_write_port23a_complete:bSurpriseRemoved = true\n"));
146 goto check_completion;
147 }
148 }
149 phaldata = GET_HAL_DATA(padapter);
150 phaldata->srestpriv.last_tx_complete_time = jiffies;
151
152check_completion:
153 spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
154 rtw23a_sctx_done_err(&pxmitbuf->sctx,
155 purb->status ? RTW_SCTX_DONE_WRITE_PORT_ERR :
156 RTW_SCTX_DONE_SUCCESS);
157 spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
158
159 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
160
161 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
162}
163
164u32 usb_write_port23a(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
165 struct xmit_buf *pxmitbuf)
166{
167 struct urb *purb = NULL;
168 struct rtw_adapter *padapter = (struct rtw_adapter *)pintfhdl->padapter;
169 struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
170 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
171 struct xmit_frame *pxmitframe = (struct xmit_frame *)pxmitbuf->priv_data;
172 struct usb_device *pusbd = pdvobj->pusbdev;
173 unsigned long irqL;
174 unsigned int pipe;
175 int status;
176 u32 ret = _FAIL;
177
178 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("+usb_write_port23a\n"));
179
180 if ((padapter->bDriverStopped) || (padapter->bSurpriseRemoved) ||
181 (padapter->pwrctrlpriv.pnp_bstop_trx)) {
182 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
183 ("usb_write_port23a:( padapter->bDriverStopped ||padapter->bSurpriseRemoved ||adapter->pwrctrlpriv.pnp_bstop_trx)!!!\n"));
184 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_TX_DENY);
185 goto exit;
186 }
187
188 spin_lock_irqsave(&pxmitpriv->lock, irqL);
189
190 switch (addr) {
191 case VO_QUEUE_INX:
192 pxmitpriv->voq_cnt++;
193 pxmitbuf->flags = VO_QUEUE_INX;
194 break;
195 case VI_QUEUE_INX:
196 pxmitpriv->viq_cnt++;
197 pxmitbuf->flags = VI_QUEUE_INX;
198 break;
199 case BE_QUEUE_INX:
200 pxmitpriv->beq_cnt++;
201 pxmitbuf->flags = BE_QUEUE_INX;
202 break;
203 case BK_QUEUE_INX:
204 pxmitpriv->bkq_cnt++;
205 pxmitbuf->flags = BK_QUEUE_INX;
206 break;
207 case HIGH_QUEUE_INX:
208 pxmitbuf->flags = HIGH_QUEUE_INX;
209 break;
210 default:
211 pxmitbuf->flags = MGT_QUEUE_INX;
212 break;
213 }
214
215 spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
216
217 purb = pxmitbuf->pxmit_urb[0];
218
219 /* translate DMA FIFO addr to pipehandle */
220 pipe = ffaddr2pipehdl23a(pdvobj, addr);
221
222 usb_fill_bulk_urb(purb, pusbd, pipe,
223 pxmitframe->buf_addr, /* pxmitbuf->pbuf */
224 cnt, usb_write_port23a_complete,
225 pxmitbuf);/* context is pxmitbuf */
226
227 status = usb_submit_urb(purb, GFP_ATOMIC);
228 if (!status) {
229 struct hal_data_8723a *phaldata = GET_HAL_DATA(padapter);
230 phaldata->srestpriv.last_tx_time = jiffies;
231 } else {
232 rtw23a_sctx_done_err(&pxmitbuf->sctx,
233 RTW_SCTX_DONE_WRITE_PORT_ERR);
234 DBG_8723A("usb_write_port23a, status =%d\n", status);
235 RT_TRACE(_module_hci_ops_os_c_, _drv_err_,
236 ("usb_write_port23a(): usb_submit_urb, status =%x\n",
237 status));
238
239 switch (status) {
240 case -ENODEV:
241 padapter->bDriverStopped = true;
242 break;
243 default:
244 break;
245 }
246 goto exit;
247 }
248 ret = _SUCCESS;
249 RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("-usb_write_port23a\n"));
250
251exit:
252 if (ret != _SUCCESS)
253 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
254
255 return ret;
256}
257
258void usb_write_port23a_cancel(struct intf_hdl *pintfhdl)
259{
260 struct rtw_adapter *padapter = pintfhdl->padapter;
261 struct xmit_buf *pxmitbuf;
262 struct list_head *plist;
263 int j;
264
265 DBG_8723A("%s\n", __func__);
266
267 padapter->bWritePortCancel = true;
268
269 list_for_each(plist, &padapter->xmitpriv.xmitbuf_list) {
270 pxmitbuf = container_of(plist, struct xmit_buf, list2);
271 for (j = 0; j < 8; j++) {
272 if (pxmitbuf->pxmit_urb[j])
273 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
274 }
275 }
276 list_for_each(plist, &padapter->xmitpriv.xmitextbuf_list) {
277 pxmitbuf = container_of(plist, struct xmit_buf, list2);
278 for (j = 0; j < 8; j++) {
279 if (pxmitbuf->pxmit_urb[j])
280 usb_kill_urb(pxmitbuf->pxmit_urb[j]);
281 }
282 }
283}
diff --git a/drivers/staging/rtl8723au/os_dep/xmit_linux.c b/drivers/staging/rtl8723au/os_dep/xmit_linux.c
new file mode 100644
index 000000000000..e1c6fc746233
--- /dev/null
+++ b/drivers/staging/rtl8723au/os_dep/xmit_linux.c
@@ -0,0 +1,195 @@
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _XMIT_OSDEP_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19
20#include <linux/if_ether.h>
21#include <linux/ip.h>
22#include <wifi.h>
23#include <mlme_osdep.h>
24#include <xmit_osdep.h>
25#include <osdep_intf.h>
26
27uint rtw_remainder_len23a(struct pkt_file *pfile)
28{
29 return pfile->buf_len - ((unsigned long)(pfile->cur_addr) -
30 (unsigned long)(pfile->buf_start));
31}
32
33void _rtw_open_pktfile23a(struct sk_buff *pktptr, struct pkt_file *pfile)
34{
35 pfile->pkt = pktptr;
36 pfile->buf_start = pktptr->data;
37 pfile->cur_addr = pktptr->data;
38 pfile->buf_len = pktptr->len;
39 pfile->pkt_len = pktptr->len;
40
41 pfile->cur_buffer = pfile->buf_start;
42}
43
44uint _rtw_pktfile_read23a(struct pkt_file *pfile, u8 *rmem, uint rlen)
45{
46 uint len = 0;
47
48 len = rtw_remainder_len23a(pfile);
49 len = (rlen > len) ? len : rlen;
50
51 if (rmem)
52 skb_copy_bits(pfile->pkt, pfile->buf_len-pfile->pkt_len,
53 rmem, len);
54
55 pfile->cur_addr += len;
56 pfile->pkt_len -= len;
57
58 return len;
59}
60
61int rtw_endofpktfile23a(struct pkt_file *pfile)
62{
63 if (pfile->pkt_len == 0)
64 return true;
65 return false;
66}
67
68int rtw_os_xmit_resource_alloc23a(struct rtw_adapter *padapter,
69 struct xmit_buf *pxmitbuf, u32 alloc_sz)
70{
71 int i;
72
73 pxmitbuf->pallocated_buf = kzalloc(alloc_sz, GFP_KERNEL);
74 if (pxmitbuf->pallocated_buf == NULL)
75 return _FAIL;
76
77 pxmitbuf->pbuf = PTR_ALIGN(pxmitbuf->pallocated_buf, XMITBUF_ALIGN_SZ);
78
79 for (i = 0; i < 8; i++) {
80 pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
81 if (pxmitbuf->pxmit_urb[i] == NULL) {
82 DBG_8723A("pxmitbuf->pxmit_urb[i]==NULL");
83 return _FAIL;
84 }
85 }
86 return _SUCCESS;
87}
88
89void rtw_os_xmit_resource_free23a(struct rtw_adapter *padapter,
90 struct xmit_buf *pxmitbuf)
91{
92 int i;
93
94 for (i = 0; i < 8; i++)
95 usb_free_urb(pxmitbuf->pxmit_urb[i]);
96 kfree(pxmitbuf->pallocated_buf);
97}
98
99#define WMM_XMIT_THRESHOLD (NR_XMITFRAME*2/5)
100
101void rtw_os_pkt_complete23a(struct rtw_adapter *padapter, struct sk_buff *pkt)
102{
103 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
104 u16 queue;
105
106 queue = skb_get_queue_mapping(pkt);
107 if (padapter->registrypriv.wifi_spec) {
108 if (__netif_subqueue_stopped(padapter->pnetdev, queue) &&
109 (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD))
110 netif_wake_subqueue(padapter->pnetdev, queue);
111 } else {
112 if (__netif_subqueue_stopped(padapter->pnetdev, queue))
113 netif_wake_subqueue(padapter->pnetdev, queue);
114 }
115 dev_kfree_skb_any(pkt);
116}
117
118void rtw_os_xmit_complete23a(struct rtw_adapter *padapter,
119 struct xmit_frame *pxframe)
120{
121 if (pxframe->pkt)
122 rtw_os_pkt_complete23a(padapter, pxframe->pkt);
123
124 pxframe->pkt = NULL;
125}
126
127void rtw_os_xmit_schedule23a(struct rtw_adapter *padapter)
128{
129 struct xmit_priv *pxmitpriv;
130
131 if (!padapter)
132 return;
133 pxmitpriv = &padapter->xmitpriv;
134
135 spin_lock_bh(&pxmitpriv->lock);
136
137 if (rtw_txframes_pending23a(padapter))
138 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
139 spin_unlock_bh(&pxmitpriv->lock);
140}
141
142static void rtw_check_xmit_resource(struct rtw_adapter *padapter,
143 struct sk_buff *pkt)
144{
145 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
146 u16 queue;
147
148 queue = skb_get_queue_mapping(pkt);
149 if (padapter->registrypriv.wifi_spec) {
150 /* No free space for Tx, tx_worker is too slow */
151 if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD)
152 netif_stop_subqueue(padapter->pnetdev, queue);
153 } else {
154 if (pxmitpriv->free_xmitframe_cnt <= 4) {
155 if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue)))
156 netif_stop_subqueue(padapter->pnetdev, queue);
157 }
158 }
159}
160
161int rtw_xmit23a_entry23a(struct sk_buff *skb, struct net_device *pnetdev)
162{
163 struct rtw_adapter *padapter = netdev_priv(pnetdev);
164 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
165 int res = 0;
166
167 RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("+xmit_enry\n"));
168
169 if (!rtw_if_up23a(padapter)) {
170 RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
171 ("rtw_xmit23a_entry23a: rtw_if_up23a fail\n"));
172 goto drop_packet;
173 }
174
175 rtw_check_xmit_resource(padapter, skb);
176
177 res = rtw_xmit23a(padapter, skb);
178 if (res < 0)
179 goto drop_packet;
180
181 pxmitpriv->tx_pkts++;
182 RT_TRACE(_module_xmit_osdep_c_, _drv_info_,
183 ("rtw_xmit23a_entry23a: tx_pkts=%d\n",
184 (u32)pxmitpriv->tx_pkts));
185 goto exit;
186
187drop_packet:
188 pxmitpriv->tx_drop++;
189 dev_kfree_skb_any(skb);
190 RT_TRACE(_module_xmit_osdep_c_, _drv_notice_,
191 ("rtw_xmit23a_entry23a: drop, tx_drop=%d\n",
192 (u32)pxmitpriv->tx_drop));
193exit:
194 return 0;
195}