mwifiex: advertise multichannel support to cfg80211
[deliverable/linux.git] / drivers / net / wireless / mwifiex / cfg80211.c
CommitLineData
5e6e3a92
BZ
1/*
2 * Marvell Wireless LAN device driver: CFG80211
3 *
65da33f5 4 * Copyright (C) 2011-2014, Marvell International Ltd.
5e6e3a92
BZ
5 *
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
18 */
19
20#include "cfg80211.h"
21#include "main.h"
b0497597 22#include "11n.h"
5e6e3a92 23
3c68ef5b
AP
24static char *reg_alpha2;
25module_param(reg_alpha2, charp, 0);
26
cd8440da
AP
27static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
28 {
a4df8f56
AP
29 .max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
30 BIT(NL80211_IFTYPE_P2P_GO) |
31 BIT(NL80211_IFTYPE_P2P_CLIENT),
cd8440da
AP
32 },
33 {
34 .max = 1, .types = BIT(NL80211_IFTYPE_AP),
35 },
36};
37
38static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = {
39 .limits = mwifiex_ap_sta_limits,
40 .num_different_channels = 1,
41 .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
42 .max_interfaces = MWIFIEX_MAX_BSS_NUM,
43 .beacon_int_infra_match = true,
44};
45
de9e9932
AP
46static const struct
47ieee80211_iface_combination mwifiex_drcs_iface_comb_ap_sta = {
48 .limits = mwifiex_ap_sta_limits,
49 .num_different_channels = 2,
50 .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
51 .max_interfaces = MWIFIEX_MAX_BSS_NUM,
52 .beacon_int_infra_match = true,
53};
54
5e6e3a92
BZ
55/*
56 * This function maps the nl802.11 channel type into driver channel type.
57 *
58 * The mapping is as follows -
21c3ba34
AK
59 * NL80211_CHAN_NO_HT -> IEEE80211_HT_PARAM_CHA_SEC_NONE
60 * NL80211_CHAN_HT20 -> IEEE80211_HT_PARAM_CHA_SEC_NONE
61 * NL80211_CHAN_HT40PLUS -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE
62 * NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW
63 * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE
5e6e3a92 64 */
7feb4c48 65u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
5e6e3a92 66{
05910f4a 67 switch (chan_type) {
5e6e3a92
BZ
68 case NL80211_CHAN_NO_HT:
69 case NL80211_CHAN_HT20:
21c3ba34 70 return IEEE80211_HT_PARAM_CHA_SEC_NONE;
5e6e3a92 71 case NL80211_CHAN_HT40PLUS:
21c3ba34 72 return IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
5e6e3a92 73 case NL80211_CHAN_HT40MINUS:
21c3ba34 74 return IEEE80211_HT_PARAM_CHA_SEC_BELOW;
5e6e3a92 75 default:
21c3ba34 76 return IEEE80211_HT_PARAM_CHA_SEC_NONE;
5e6e3a92 77 }
5e6e3a92
BZ
78}
79
7ee38bf4
XH
80/* This function maps IEEE HT secondary channel type to NL80211 channel type
81 */
82u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset)
83{
84 switch (second_chan_offset) {
85 case IEEE80211_HT_PARAM_CHA_SEC_NONE:
86 return NL80211_CHAN_HT20;
87 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
88 return NL80211_CHAN_HT40PLUS;
89 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
90 return NL80211_CHAN_HT40MINUS;
91 default:
92 return NL80211_CHAN_HT20;
93 }
94}
95
5e6e3a92
BZ
96/*
97 * This function checks whether WEP is set.
98 */
99static int
100mwifiex_is_alg_wep(u32 cipher)
101{
5e6e3a92 102 switch (cipher) {
2be50b8d
YAP
103 case WLAN_CIPHER_SUITE_WEP40:
104 case WLAN_CIPHER_SUITE_WEP104:
270e58e8 105 return 1;
5e6e3a92 106 default:
5e6e3a92
BZ
107 break;
108 }
270e58e8
YAP
109
110 return 0;
5e6e3a92
BZ
111}
112
5e6e3a92
BZ
113/*
114 * This function retrieves the private structure from kernel wiphy structure.
115 */
67fdf39e 116static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy)
5e6e3a92
BZ
117{
118 return (void *) (*(unsigned long *) wiphy_priv(wiphy));
119}
120
121/*
122 * CFG802.11 operation handler to delete a network key.
123 */
124static int
125mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
126 u8 key_index, bool pairwise, const u8 *mac_addr)
127{
f540f9f3 128 struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
75edd2c6
AP
129 const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
130 const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
5e6e3a92 131
53b11231 132 if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {
acebe8c1 133 mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n");
5e6e3a92
BZ
134 return -EFAULT;
135 }
136
acebe8c1 137 mwifiex_dbg(priv->adapter, INFO, "info: crypto keys deleted\n");
5e6e3a92
BZ
138 return 0;
139}
140
e39faa73
SP
141/*
142 * This function forms an skb for management frame.
143 */
144static int
145mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len)
146{
147 u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
148 u16 pkt_len;
149 u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;
e39faa73
SP
150
151 pkt_len = len + ETH_ALEN;
152
153 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +
154 MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
155 memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));
156
157 memcpy(skb_push(skb, sizeof(tx_control)),
158 &tx_control, sizeof(tx_control));
159
160 memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));
161
162 /* Add packet data and address4 */
163 memcpy(skb_put(skb, sizeof(struct ieee80211_hdr_3addr)), buf,
164 sizeof(struct ieee80211_hdr_3addr));
165 memcpy(skb_put(skb, ETH_ALEN), addr, ETH_ALEN);
166 memcpy(skb_put(skb, len - sizeof(struct ieee80211_hdr_3addr)),
167 buf + sizeof(struct ieee80211_hdr_3addr),
168 len - sizeof(struct ieee80211_hdr_3addr));
169
170 skb->priority = LOW_PRIO_TID;
c64800e7 171 __net_timestamp(skb);
e39faa73
SP
172
173 return 0;
174}
175
176/*
177 * CFG802.11 operation handler to transmit a management frame.
178 */
179static int
180mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
b176e629 181 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
e39faa73 182{
b176e629
AO
183 const u8 *buf = params->buf;
184 size_t len = params->len;
e39faa73
SP
185 struct sk_buff *skb;
186 u16 pkt_len;
187 const struct ieee80211_mgmt *mgmt;
231d83e2 188 struct mwifiex_txinfo *tx_info;
e39faa73
SP
189 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
190
191 if (!buf || !len) {
acebe8c1 192 mwifiex_dbg(priv->adapter, ERROR, "invalid buffer and length\n");
e39faa73
SP
193 return -EFAULT;
194 }
195
196 mgmt = (const struct ieee80211_mgmt *)buf;
197 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA &&
198 ieee80211_is_probe_resp(mgmt->frame_control)) {
199 /* Since we support offload probe resp, we need to skip probe
200 * resp in AP or GO mode */
acebe8c1
ZL
201 mwifiex_dbg(priv->adapter, INFO,
202 "info: skip to send probe resp in AP or GO mode\n");
e39faa73
SP
203 return 0;
204 }
205
206 pkt_len = len + ETH_ALEN;
207 skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +
208 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
209 pkt_len + sizeof(pkt_len));
210
211 if (!skb) {
acebe8c1
ZL
212 mwifiex_dbg(priv->adapter, ERROR,
213 "allocate skb failed for management frame\n");
e39faa73
SP
214 return -ENOMEM;
215 }
216
231d83e2 217 tx_info = MWIFIEX_SKB_TXCB(skb);
701a9e61 218 memset(tx_info, 0, sizeof(*tx_info));
231d83e2
HY
219 tx_info->bss_num = priv->bss_num;
220 tx_info->bss_type = priv->bss_type;
a1ed4849 221 tx_info->pkt_len = pkt_len;
231d83e2 222
e39faa73 223 mwifiex_form_mgmt_frame(skb, buf, len);
e00adf39 224 *cookie = prandom_u32() | 1;
18ca4382
AK
225
226 if (ieee80211_is_action(mgmt->frame_control))
227 skb = mwifiex_clone_skb_for_tx_status(priv,
228 skb,
229 MWIFIEX_BUF_FLAG_ACTION_TX_STATUS, cookie);
230 else
231 cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
232 GFP_ATOMIC);
233
234 mwifiex_queue_tx_pkt(priv, skb);
e39faa73 235
acebe8c1 236 mwifiex_dbg(priv->adapter, INFO, "info: management frame transmitted\n");
e39faa73
SP
237 return 0;
238}
239
3cec6870
SP
240/*
241 * CFG802.11 operation handler to register a mgmt frame.
242 */
243static void
244mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
245 struct wireless_dev *wdev,
246 u16 frame_type, bool reg)
247{
248 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
4481b2db 249 u32 mask;
3cec6870
SP
250
251 if (reg)
4481b2db 252 mask = priv->mgmt_frame_mask | BIT(frame_type >> 4);
3cec6870 253 else
4481b2db
SP
254 mask = priv->mgmt_frame_mask & ~BIT(frame_type >> 4);
255
256 if (mask != priv->mgmt_frame_mask) {
257 priv->mgmt_frame_mask = mask;
fa0ecbb9
BZ
258 mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
259 HostCmd_ACT_GEN_SET, 0,
260 &priv->mgmt_frame_mask, false);
acebe8c1 261 mwifiex_dbg(priv->adapter, INFO, "info: mgmt frame registered\n");
4481b2db 262 }
3cec6870
SP
263}
264
7feb4c48
SP
265/*
266 * CFG802.11 operation handler to remain on channel.
267 */
268static int
269mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy,
270 struct wireless_dev *wdev,
271 struct ieee80211_channel *chan,
7feb4c48
SP
272 unsigned int duration, u64 *cookie)
273{
274 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
275 int ret;
276
277 if (!chan || !cookie) {
acebe8c1 278 mwifiex_dbg(priv->adapter, ERROR, "Invalid parameter for ROC\n");
7feb4c48
SP
279 return -EINVAL;
280 }
281
282 if (priv->roc_cfg.cookie) {
acebe8c1
ZL
283 mwifiex_dbg(priv->adapter, INFO,
284 "info: ongoing ROC, cookie = 0x%llx\n",
285 priv->roc_cfg.cookie);
7feb4c48
SP
286 return -EBUSY;
287 }
288
289 ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan,
42d97a59 290 duration);
7feb4c48
SP
291
292 if (!ret) {
e00adf39 293 *cookie = prandom_u32() | 1;
7feb4c48
SP
294 priv->roc_cfg.cookie = *cookie;
295 priv->roc_cfg.chan = *chan;
7feb4c48 296
42d97a59 297 cfg80211_ready_on_channel(wdev, *cookie, chan,
7feb4c48
SP
298 duration, GFP_ATOMIC);
299
acebe8c1
ZL
300 mwifiex_dbg(priv->adapter, INFO,
301 "info: ROC, cookie = 0x%llx\n", *cookie);
7feb4c48
SP
302 }
303
304 return ret;
305}
306
307/*
308 * CFG802.11 operation handler to cancel remain on channel.
309 */
310static int
311mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
312 struct wireless_dev *wdev, u64 cookie)
313{
314 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
315 int ret;
316
317 if (cookie != priv->roc_cfg.cookie)
318 return -ENOENT;
319
320 ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE,
42d97a59 321 &priv->roc_cfg.chan, 0);
7feb4c48
SP
322
323 if (!ret) {
324 cfg80211_remain_on_channel_expired(wdev, cookie,
325 &priv->roc_cfg.chan,
7feb4c48
SP
326 GFP_ATOMIC);
327
328 memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg));
329
acebe8c1
ZL
330 mwifiex_dbg(priv->adapter, INFO,
331 "info: cancel ROC, cookie = 0x%llx\n", cookie);
7feb4c48
SP
332 }
333
334 return ret;
335}
336
5e6e3a92
BZ
337/*
338 * CFG802.11 operation handler to set Tx power.
339 */
340static int
341mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
c8442118 342 struct wireless_dev *wdev,
5e6e3a92 343 enum nl80211_tx_power_setting type,
742c29fd 344 int mbm)
5e6e3a92 345{
67fdf39e
AP
346 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
347 struct mwifiex_private *priv;
600f5d90 348 struct mwifiex_power_cfg power_cfg;
742c29fd 349 int dbm = MBM_TO_DBM(mbm);
5e6e3a92 350
600f5d90
AK
351 if (type == NL80211_TX_POWER_FIXED) {
352 power_cfg.is_power_auto = 0;
353 power_cfg.power_level = dbm;
354 } else {
355 power_cfg.is_power_auto = 1;
356 }
357
67fdf39e
AP
358 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
359
636c4598 360 return mwifiex_set_tx_power(priv, &power_cfg);
5e6e3a92
BZ
361}
362
363/*
364 * CFG802.11 operation handler to set Power Save option.
365 *
366 * The timeout value, if provided, is currently ignored.
367 */
368static int
369mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
370 struct net_device *dev,
371 bool enabled, int timeout)
372{
f540f9f3 373 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
600f5d90 374 u32 ps_mode;
5e6e3a92
BZ
375
376 if (timeout)
acebe8c1
ZL
377 mwifiex_dbg(priv->adapter, INFO,
378 "info: ignore timeout value for IEEE Power Save\n");
5e6e3a92 379
600f5d90 380 ps_mode = enabled;
5e6e3a92 381
636c4598 382 return mwifiex_drv_set_power(priv, &ps_mode);
5e6e3a92
BZ
383}
384
385/*
386 * CFG802.11 operation handler to set the default network key.
387 */
388static int
389mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
390 u8 key_index, bool unicast,
391 bool multicast)
392{
f540f9f3 393 struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
5e6e3a92 394
2d3d0a88 395 /* Return if WEP key not configured */
5eb02e44 396 if (!priv->sec_info.wep_enabled)
2d3d0a88
AK
397 return 0;
398
96893538
AP
399 if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
400 priv->wep_key_curr_index = key_index;
53b11231
YL
401 } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,
402 NULL, 0)) {
acebe8c1 403 mwifiex_dbg(priv->adapter, ERROR, "set default Tx key index\n");
5e6e3a92 404 return -EFAULT;
636c4598 405 }
5e6e3a92
BZ
406
407 return 0;
408}
409
410/*
411 * CFG802.11 operation handler to add a network key.
412 */
413static int
414mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
415 u8 key_index, bool pairwise, const u8 *mac_addr,
416 struct key_params *params)
417{
f540f9f3 418 struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
96893538 419 struct mwifiex_wep_key *wep_key;
75edd2c6
AP
420 const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
421 const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
5e6e3a92 422
96893538
AP
423 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
424 (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
425 params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
426 if (params->key && params->key_len) {
427 wep_key = &priv->wep_key[key_index];
428 memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
429 memcpy(wep_key->key_material, params->key,
430 params->key_len);
431 wep_key->key_index = key_index;
432 wep_key->key_length = params->key_len;
433 priv->sec_info.wep_enabled = 1;
434 }
435 return 0;
436 }
437
53b11231 438 if (mwifiex_set_encode(priv, params, params->key, params->key_len,
75edd2c6 439 key_index, peer_mac, 0)) {
acebe8c1 440 mwifiex_dbg(priv->adapter, ERROR, "crypto keys added\n");
5e6e3a92 441 return -EFAULT;
636c4598 442 }
5e6e3a92
BZ
443
444 return 0;
445}
446
447/*
448 * This function sends domain information to the firmware.
449 *
450 * The following information are passed to the firmware -
451 * - Country codes
452 * - Sub bands (first channel, number of channels, maximum Tx power)
453 */
65d48e59 454int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
5e6e3a92
BZ
455{
456 u8 no_of_triplet = 0;
457 struct ieee80211_country_ie_triplet *t;
458 u8 no_of_parsed_chan = 0;
459 u8 first_chan = 0, next_chan = 0, max_pwr = 0;
460 u8 i, flag = 0;
461 enum ieee80211_band band;
462 struct ieee80211_supported_band *sband;
463 struct ieee80211_channel *ch;
67fdf39e
AP
464 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
465 struct mwifiex_private *priv;
5e6e3a92 466 struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg;
5e6e3a92
BZ
467
468 /* Set country code */
67fdf39e
AP
469 domain_info->country_code[0] = adapter->country_code[0];
470 domain_info->country_code[1] = adapter->country_code[1];
5e6e3a92
BZ
471 domain_info->country_code[2] = ' ';
472
473 band = mwifiex_band_to_radio_type(adapter->config_bands);
474 if (!wiphy->bands[band]) {
acebe8c1
ZL
475 mwifiex_dbg(adapter, ERROR,
476 "11D: setting domain info in FW\n");
5e6e3a92
BZ
477 return -1;
478 }
479
480 sband = wiphy->bands[band];
481
482 for (i = 0; i < sband->n_channels ; i++) {
483 ch = &sband->channels[i];
484 if (ch->flags & IEEE80211_CHAN_DISABLED)
485 continue;
486
487 if (!flag) {
488 flag = 1;
489 first_chan = (u32) ch->hw_value;
490 next_chan = first_chan;
22db2497 491 max_pwr = ch->max_power;
5e6e3a92
BZ
492 no_of_parsed_chan = 1;
493 continue;
494 }
495
496 if (ch->hw_value == next_chan + 1 &&
22db2497 497 ch->max_power == max_pwr) {
5e6e3a92
BZ
498 next_chan++;
499 no_of_parsed_chan++;
500 } else {
501 t = &domain_info->triplet[no_of_triplet];
502 t->chans.first_channel = first_chan;
503 t->chans.num_channels = no_of_parsed_chan;
504 t->chans.max_power = max_pwr;
505 no_of_triplet++;
506 first_chan = (u32) ch->hw_value;
507 next_chan = first_chan;
22db2497 508 max_pwr = ch->max_power;
5e6e3a92
BZ
509 no_of_parsed_chan = 1;
510 }
511 }
512
513 if (flag) {
514 t = &domain_info->triplet[no_of_triplet];
515 t->chans.first_channel = first_chan;
516 t->chans.num_channels = no_of_parsed_chan;
517 t->chans.max_power = max_pwr;
518 no_of_triplet++;
519 }
520
521 domain_info->no_of_triplet = no_of_triplet;
636c4598 522
67fdf39e
AP
523 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
524
fa0ecbb9
BZ
525 if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
526 HostCmd_ACT_GEN_SET, 0, NULL, false)) {
acebe8c1
ZL
527 mwifiex_dbg(adapter, INFO,
528 "11D: setting domain info in FW\n");
636c4598
YAP
529 return -1;
530 }
5e6e3a92 531
636c4598 532 return 0;
5e6e3a92
BZ
533}
534
535/*
536 * CFG802.11 regulatory domain callback function.
537 *
538 * This function is called when the regulatory domain is changed due to the
539 * following reasons -
540 * - Set by driver
541 * - Set by system core
542 * - Set by user
543 * - Set bt Country IE
544 */
0c0280bd
LR
545static void mwifiex_reg_notifier(struct wiphy *wiphy,
546 struct regulatory_request *request)
5e6e3a92 547{
67fdf39e 548 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
82efa16a
BZ
549 struct mwifiex_private *priv = mwifiex_get_priv(adapter,
550 MWIFIEX_BSS_ROLE_ANY);
acebe8c1
ZL
551 mwifiex_dbg(adapter, INFO,
552 "info: cfg80211 regulatory domain callback for %c%c\n",
553 request->alpha2[0], request->alpha2[1]);
5e6e3a92 554
5e6e3a92
BZ
555 switch (request->initiator) {
556 case NL80211_REGDOM_SET_BY_DRIVER:
557 case NL80211_REGDOM_SET_BY_CORE:
558 case NL80211_REGDOM_SET_BY_USER:
5e6e3a92
BZ
559 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
560 break;
dd4a9ac0 561 default:
acebe8c1
ZL
562 mwifiex_dbg(adapter, ERROR,
563 "unknown regdom initiator: %d\n",
564 request->initiator);
dd4a9ac0
BZ
565 return;
566 }
567
568 /* Don't send world or same regdom info to firmware */
569 if (strncmp(request->alpha2, "00", 2) &&
570 strncmp(request->alpha2, adapter->country_code,
571 sizeof(request->alpha2))) {
572 memcpy(adapter->country_code, request->alpha2,
573 sizeof(request->alpha2));
574 mwifiex_send_domain_info_cmd_fw(wiphy);
b58df446 575 mwifiex_dnld_txpwr_table(priv);
5e6e3a92 576 }
5e6e3a92
BZ
577}
578
5e6e3a92
BZ
579/*
580 * This function sets the fragmentation threshold.
581 *
600f5d90 582 * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE
5e6e3a92
BZ
583 * and MWIFIEX_FRAG_MAX_VALUE.
584 */
585static int
586mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)
587{
aea0701e
YAP
588 if (frag_thr < MWIFIEX_FRAG_MIN_VALUE ||
589 frag_thr > MWIFIEX_FRAG_MAX_VALUE)
9b930eae 590 frag_thr = MWIFIEX_FRAG_MAX_VALUE;
5e6e3a92 591
fa0ecbb9
BZ
592 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
593 HostCmd_ACT_GEN_SET, FRAG_THRESH_I,
594 &frag_thr, true);
5e6e3a92
BZ
595}
596
597/*
598 * This function sets the RTS threshold.
600f5d90
AK
599
600 * The rts value must lie between MWIFIEX_RTS_MIN_VALUE
601 * and MWIFIEX_RTS_MAX_VALUE.
5e6e3a92
BZ
602 */
603static int
604mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)
605{
5e6e3a92
BZ
606 if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE)
607 rts_thr = MWIFIEX_RTS_MAX_VALUE;
608
fa0ecbb9
BZ
609 return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
610 HostCmd_ACT_GEN_SET, RTS_THRESH_I,
611 &rts_thr, true);
5e6e3a92
BZ
612}
613
614/*
615 * CFG802.11 operation handler to set wiphy parameters.
616 *
617 * This function can be used to set the RTS threshold and the
618 * Fragmentation threshold of the driver.
619 */
620static int
621mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
622{
67fdf39e 623 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
9b930eae
AP
624 struct mwifiex_private *priv;
625 struct mwifiex_uap_bss_param *bss_cfg;
09f63ae6
AP
626 int ret;
627
628 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
9b930eae 629
09f63ae6
AP
630 switch (priv->bss_role) {
631 case MWIFIEX_BSS_ROLE_UAP:
632 if (priv->bss_started) {
acebe8c1
ZL
633 mwifiex_dbg(adapter, ERROR,
634 "cannot change wiphy params when bss started");
09f63ae6
AP
635 return -EINVAL;
636 }
5e6e3a92 637
09f63ae6
AP
638 bss_cfg = kzalloc(sizeof(*bss_cfg), GFP_KERNEL);
639 if (!bss_cfg)
640 return -ENOMEM;
9b930eae 641
09f63ae6 642 mwifiex_set_sys_config_invalid_data(bss_cfg);
5e6e3a92 643
09f63ae6
AP
644 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
645 bss_cfg->rts_threshold = wiphy->rts_threshold;
646 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
647 bss_cfg->frag_threshold = wiphy->frag_threshold;
648 if (changed & WIPHY_PARAM_RETRY_LONG)
649 bss_cfg->retry_limit = wiphy->retry_long;
9b930eae 650
09f63ae6
AP
651 ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
652 HostCmd_ACT_GEN_SET,
653 UAP_BSS_PARAMS_I, bss_cfg,
654 false);
655
656 kfree(bss_cfg);
657 if (ret) {
acebe8c1
ZL
658 mwifiex_dbg(adapter, ERROR,
659 "Failed to set wiphy phy params\n");
09f63ae6
AP
660 return ret;
661 }
662 break;
9b930eae 663
9b930eae 664 case MWIFIEX_BSS_ROLE_STA:
09f63ae6 665 if (priv->media_connected) {
acebe8c1
ZL
666 mwifiex_dbg(adapter, ERROR,
667 "cannot change wiphy params when connected");
09f63ae6
AP
668 return -EINVAL;
669 }
670 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
671 ret = mwifiex_set_rts(priv,
672 wiphy->rts_threshold);
673 if (ret)
674 return ret;
9b930eae 675 }
09f63ae6
AP
676 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
677 ret = mwifiex_set_frag(priv,
678 wiphy->frag_threshold);
679 if (ret)
680 return ret;
681 }
682 break;
9b930eae
AP
683 }
684
685 return 0;
5e6e3a92
BZ
686}
687
e1a2b7a3
SP
688static int
689mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv)
690{
691 u16 mode = P2P_MODE_DISABLE;
692
fa0ecbb9
BZ
693 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
694 HostCmd_ACT_GEN_SET, 0, &mode, true))
e1a2b7a3
SP
695 return -1;
696
697 return 0;
698}
699
700/*
701 * This function initializes the functionalities for P2P client.
702 * The P2P client initialization sequence is:
703 * disable -> device -> client
704 */
705static int
706mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv)
707{
708 u16 mode;
709
710 if (mwifiex_cfg80211_deinit_p2p(priv))
711 return -1;
712
713 mode = P2P_MODE_DEVICE;
fa0ecbb9
BZ
714 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
715 HostCmd_ACT_GEN_SET, 0, &mode, true))
e1a2b7a3
SP
716 return -1;
717
718 mode = P2P_MODE_CLIENT;
fa0ecbb9
BZ
719 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
720 HostCmd_ACT_GEN_SET, 0, &mode, true))
e1a2b7a3
SP
721 return -1;
722
723 return 0;
724}
725
9197ab9e
SP
726/*
727 * This function initializes the functionalities for P2P GO.
728 * The P2P GO initialization sequence is:
729 * disable -> device -> GO
730 */
731static int
732mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv)
733{
734 u16 mode;
735
736 if (mwifiex_cfg80211_deinit_p2p(priv))
737 return -1;
738
739 mode = P2P_MODE_DEVICE;
fa0ecbb9
BZ
740 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
741 HostCmd_ACT_GEN_SET, 0, &mode, true))
9197ab9e
SP
742 return -1;
743
744 mode = P2P_MODE_GO;
fa0ecbb9
BZ
745 if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG,
746 HostCmd_ACT_GEN_SET, 0, &mode, true))
9197ab9e
SP
747 return -1;
748
047eaaf6
AP
749 return 0;
750}
751
752static int mwifiex_deinit_priv_params(struct mwifiex_private *priv)
753{
a9adbcb3
AP
754 struct mwifiex_adapter *adapter = priv->adapter;
755 unsigned long flags;
756
047eaaf6
AP
757 priv->mgmt_frame_mask = 0;
758 if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG,
759 HostCmd_ACT_GEN_SET, 0,
760 &priv->mgmt_frame_mask, false)) {
acebe8c1
ZL
761 mwifiex_dbg(adapter, ERROR,
762 "could not unregister mgmt frame rx\n");
047eaaf6
AP
763 return -1;
764 }
765
766 mwifiex_deauthenticate(priv, NULL);
a9adbcb3
AP
767
768 spin_lock_irqsave(&adapter->main_proc_lock, flags);
769 adapter->main_locked = true;
770 if (adapter->mwifiex_processing) {
771 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
772 flush_workqueue(adapter->workqueue);
773 } else {
774 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
775 }
776
777 spin_lock_irqsave(&adapter->rx_proc_lock, flags);
778 adapter->rx_locked = true;
779 if (adapter->rx_processing) {
780 spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
781 flush_workqueue(adapter->rx_workqueue);
782 } else {
783 spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
784 }
785
047eaaf6
AP
786 mwifiex_free_priv(priv);
787 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
788 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
789 priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
790
791 return 0;
792}
793
794static int
795mwifiex_init_new_priv_params(struct mwifiex_private *priv,
796 struct net_device *dev,
797 enum nl80211_iftype type)
798{
a9adbcb3
AP
799 struct mwifiex_adapter *adapter = priv->adapter;
800 unsigned long flags;
801
047eaaf6
AP
802 mwifiex_init_priv(priv);
803
804 priv->bss_mode = type;
805 priv->wdev.iftype = type;
806
807 mwifiex_init_priv_params(priv, priv->netdev);
808 priv->bss_started = 0;
809
810 switch (type) {
811 case NL80211_IFTYPE_STATION:
812 case NL80211_IFTYPE_ADHOC:
813 priv->bss_role = MWIFIEX_BSS_ROLE_STA;
814 priv->bss_type = MWIFIEX_BSS_TYPE_STA;
815 break;
816 case NL80211_IFTYPE_P2P_CLIENT:
817 case NL80211_IFTYPE_P2P_GO:
818 priv->bss_role = MWIFIEX_BSS_ROLE_STA;
819 priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
820 break;
821 case NL80211_IFTYPE_AP:
822 priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
823 priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
824 break;
825 default:
acebe8c1
ZL
826 mwifiex_dbg(adapter, ERROR,
827 "%s: changing to %d not supported\n",
828 dev->name, type);
047eaaf6
AP
829 return -EOPNOTSUPP;
830 }
9197ab9e 831
a9adbcb3
AP
832 spin_lock_irqsave(&adapter->main_proc_lock, flags);
833 adapter->main_locked = false;
834 spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
835
836 spin_lock_irqsave(&adapter->rx_proc_lock, flags);
837 adapter->rx_locked = false;
838 spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
839
9197ab9e
SP
840 return 0;
841}
842
047eaaf6
AP
843static int
844mwifiex_change_vif_to_p2p(struct net_device *dev,
845 enum nl80211_iftype curr_iftype,
846 enum nl80211_iftype type, u32 *flags,
847 struct vif_params *params)
848{
849 struct mwifiex_private *priv;
850 struct mwifiex_adapter *adapter;
851
852 priv = mwifiex_netdev_get_priv(dev);
853
854 if (!priv)
855 return -1;
856
857 adapter = priv->adapter;
858
859 if (adapter->curr_iface_comb.p2p_intf ==
860 adapter->iface_limit.p2p_intf) {
acebe8c1
ZL
861 mwifiex_dbg(adapter, ERROR,
862 "cannot create multiple P2P ifaces\n");
047eaaf6
AP
863 return -1;
864 }
865
acebe8c1
ZL
866 mwifiex_dbg(adapter, INFO,
867 "%s: changing role to p2p\n", dev->name);
047eaaf6
AP
868
869 if (mwifiex_deinit_priv_params(priv))
870 return -1;
871 if (mwifiex_init_new_priv_params(priv, dev, type))
872 return -1;
873
874 switch (type) {
875 case NL80211_IFTYPE_P2P_CLIENT:
876 if (mwifiex_cfg80211_init_p2p_client(priv))
877 return -EFAULT;
878 break;
879 case NL80211_IFTYPE_P2P_GO:
880 if (mwifiex_cfg80211_init_p2p_go(priv))
881 return -EFAULT;
882 break;
883 default:
acebe8c1
ZL
884 mwifiex_dbg(adapter, ERROR,
885 "%s: changing to %d not supported\n",
886 dev->name, type);
047eaaf6
AP
887 return -EOPNOTSUPP;
888 }
889
890 if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
891 HostCmd_ACT_GEN_SET, 0, NULL, true))
892 return -1;
893
894 if (mwifiex_sta_init_cmd(priv, false, false))
895 return -1;
896
897 switch (curr_iftype) {
898 case NL80211_IFTYPE_STATION:
899 case NL80211_IFTYPE_ADHOC:
900 adapter->curr_iface_comb.sta_intf--;
901 break;
902 case NL80211_IFTYPE_AP:
903 adapter->curr_iface_comb.uap_intf--;
904 break;
905 default:
906 break;
907 }
908
909 adapter->curr_iface_comb.p2p_intf++;
910 dev->ieee80211_ptr->iftype = type;
911
912 return 0;
913}
914
915static int
916mwifiex_change_vif_to_sta_adhoc(struct net_device *dev,
917 enum nl80211_iftype curr_iftype,
918 enum nl80211_iftype type, u32 *flags,
919 struct vif_params *params)
920{
921 struct mwifiex_private *priv;
922 struct mwifiex_adapter *adapter;
923
924 priv = mwifiex_netdev_get_priv(dev);
925
926 if (!priv)
927 return -1;
928
929 adapter = priv->adapter;
930
931 if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT &&
932 curr_iftype != NL80211_IFTYPE_P2P_GO) &&
933 (adapter->curr_iface_comb.sta_intf ==
934 adapter->iface_limit.sta_intf)) {
acebe8c1
ZL
935 mwifiex_dbg(adapter, ERROR,
936 "cannot create multiple station/adhoc ifaces\n");
047eaaf6
AP
937 return -1;
938 }
939
940 if (type == NL80211_IFTYPE_STATION)
acebe8c1
ZL
941 mwifiex_dbg(adapter, INFO,
942 "%s: changing role to station\n", dev->name);
047eaaf6 943 else
acebe8c1
ZL
944 mwifiex_dbg(adapter, INFO,
945 "%s: changing role to adhoc\n", dev->name);
047eaaf6
AP
946
947 if (mwifiex_deinit_priv_params(priv))
948 return -1;
949 if (mwifiex_init_new_priv_params(priv, dev, type))
950 return -1;
951 if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
952 HostCmd_ACT_GEN_SET, 0, NULL, true))
953 return -1;
954 if (mwifiex_sta_init_cmd(priv, false, false))
955 return -1;
956
957 switch (curr_iftype) {
958 case NL80211_IFTYPE_P2P_CLIENT:
959 case NL80211_IFTYPE_P2P_GO:
960 adapter->curr_iface_comb.p2p_intf--;
961 break;
962 case NL80211_IFTYPE_AP:
963 adapter->curr_iface_comb.uap_intf--;
964 break;
965 default:
966 break;
967 }
968
969 adapter->curr_iface_comb.sta_intf++;
970 dev->ieee80211_ptr->iftype = type;
971 return 0;
972}
973
974static int
975mwifiex_change_vif_to_ap(struct net_device *dev,
976 enum nl80211_iftype curr_iftype,
977 enum nl80211_iftype type, u32 *flags,
978 struct vif_params *params)
979{
980 struct mwifiex_private *priv;
981 struct mwifiex_adapter *adapter;
982
983 priv = mwifiex_netdev_get_priv(dev);
984
985 if (!priv)
986 return -1;
987
988 adapter = priv->adapter;
989
990 if (adapter->curr_iface_comb.uap_intf ==
991 adapter->iface_limit.uap_intf) {
acebe8c1
ZL
992 mwifiex_dbg(adapter, ERROR,
993 "cannot create multiple AP ifaces\n");
047eaaf6
AP
994 return -1;
995 }
996
acebe8c1
ZL
997 mwifiex_dbg(adapter, INFO,
998 "%s: changing role to AP\n", dev->name);
047eaaf6
AP
999
1000 if (mwifiex_deinit_priv_params(priv))
1001 return -1;
1002 if (mwifiex_init_new_priv_params(priv, dev, type))
1003 return -1;
1004 if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
1005 HostCmd_ACT_GEN_SET, 0, NULL, true))
1006 return -1;
1007 if (mwifiex_sta_init_cmd(priv, false, false))
1008 return -1;
1009
1010 switch (curr_iftype) {
1011 case NL80211_IFTYPE_P2P_CLIENT:
1012 case NL80211_IFTYPE_P2P_GO:
1013 adapter->curr_iface_comb.p2p_intf--;
1014 break;
1015 case NL80211_IFTYPE_STATION:
1016 case NL80211_IFTYPE_ADHOC:
1017 adapter->curr_iface_comb.sta_intf--;
1018 break;
1019 default:
1020 break;
1021 }
1022
1023 adapter->curr_iface_comb.uap_intf++;
1024 dev->ieee80211_ptr->iftype = type;
1025 return 0;
1026}
5e6e3a92
BZ
1027/*
1028 * CFG802.11 operation handler to change interface type.
5e6e3a92
BZ
1029 */
1030static int
1031mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
1032 struct net_device *dev,
1033 enum nl80211_iftype type, u32 *flags,
1034 struct vif_params *params)
1035{
5e6e3a92 1036 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
047eaaf6 1037 enum nl80211_iftype curr_iftype = dev->ieee80211_ptr->iftype;
5e6e3a92 1038
047eaaf6 1039 switch (curr_iftype) {
5e6e3a92 1040 case NL80211_IFTYPE_ADHOC:
4f02341a
AP
1041 switch (type) {
1042 case NL80211_IFTYPE_STATION:
047eaaf6
AP
1043 priv->bss_mode = type;
1044 priv->sec_info.authentication_mode =
1045 NL80211_AUTHTYPE_OPEN_SYSTEM;
1046 dev->ieee80211_ptr->iftype = type;
1047 mwifiex_deauthenticate(priv, NULL);
1048 return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
1049 HostCmd_ACT_GEN_SET, 0, NULL,
1050 true);
1051 case NL80211_IFTYPE_P2P_CLIENT:
1052 case NL80211_IFTYPE_P2P_GO:
1053 return mwifiex_change_vif_to_p2p(dev, curr_iftype,
1054 type, flags, params);
1055 case NL80211_IFTYPE_AP:
1056 return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
1057 flags, params);
4f02341a 1058 case NL80211_IFTYPE_UNSPECIFIED:
acebe8c1
ZL
1059 mwifiex_dbg(priv->adapter, INFO,
1060 "%s: kept type as IBSS\n", dev->name);
4f02341a
AP
1061 case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */
1062 return 0;
4f02341a 1063 default:
acebe8c1
ZL
1064 mwifiex_dbg(priv->adapter, ERROR,
1065 "%s: changing to %d not supported\n",
1066 dev->name, type);
4f02341a
AP
1067 return -EOPNOTSUPP;
1068 }
5e6e3a92
BZ
1069 break;
1070 case NL80211_IFTYPE_STATION:
4f02341a
AP
1071 switch (type) {
1072 case NL80211_IFTYPE_ADHOC:
047eaaf6
AP
1073 priv->bss_mode = type;
1074 priv->sec_info.authentication_mode =
1075 NL80211_AUTHTYPE_OPEN_SYSTEM;
e1a2b7a3 1076 dev->ieee80211_ptr->iftype = type;
047eaaf6
AP
1077 mwifiex_deauthenticate(priv, NULL);
1078 return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE,
1079 HostCmd_ACT_GEN_SET, 0, NULL,
1080 true);
1081 case NL80211_IFTYPE_P2P_CLIENT:
9197ab9e 1082 case NL80211_IFTYPE_P2P_GO:
047eaaf6
AP
1083 return mwifiex_change_vif_to_p2p(dev, curr_iftype,
1084 type, flags, params);
1085 case NL80211_IFTYPE_AP:
1086 return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
1087 flags, params);
4f02341a 1088 case NL80211_IFTYPE_UNSPECIFIED:
acebe8c1
ZL
1089 mwifiex_dbg(priv->adapter, INFO,
1090 "%s: kept type as STA\n", dev->name);
4f02341a
AP
1091 case NL80211_IFTYPE_STATION: /* This shouldn't happen */
1092 return 0;
4f02341a 1093 default:
acebe8c1
ZL
1094 mwifiex_dbg(priv->adapter, ERROR,
1095 "%s: changing to %d not supported\n",
1096 dev->name, type);
4f02341a
AP
1097 return -EOPNOTSUPP;
1098 }
1099 break;
1100 case NL80211_IFTYPE_AP:
1101 switch (type) {
047eaaf6
AP
1102 case NL80211_IFTYPE_ADHOC:
1103 case NL80211_IFTYPE_STATION:
1104 return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
1105 type, flags,
1106 params);
1107 break;
1108 case NL80211_IFTYPE_P2P_CLIENT:
1109 case NL80211_IFTYPE_P2P_GO:
1110 return mwifiex_change_vif_to_p2p(dev, curr_iftype,
1111 type, flags, params);
4f02341a 1112 case NL80211_IFTYPE_UNSPECIFIED:
acebe8c1
ZL
1113 mwifiex_dbg(priv->adapter, INFO,
1114 "%s: kept type as AP\n", dev->name);
4f02341a
AP
1115 case NL80211_IFTYPE_AP: /* This shouldn't happen */
1116 return 0;
4f02341a 1117 default:
acebe8c1
ZL
1118 mwifiex_dbg(priv->adapter, ERROR,
1119 "%s: changing to %d not supported\n",
1120 dev->name, type);
4f02341a
AP
1121 return -EOPNOTSUPP;
1122 }
5e6e3a92 1123 break;
e1a2b7a3 1124 case NL80211_IFTYPE_P2P_CLIENT:
9197ab9e 1125 case NL80211_IFTYPE_P2P_GO:
e1a2b7a3
SP
1126 switch (type) {
1127 case NL80211_IFTYPE_STATION:
047eaaf6 1128 if (mwifiex_cfg80211_init_p2p_client(priv))
e1a2b7a3
SP
1129 return -EFAULT;
1130 dev->ieee80211_ptr->iftype = type;
047eaaf6
AP
1131 break;
1132 case NL80211_IFTYPE_ADHOC:
1133 if (mwifiex_cfg80211_deinit_p2p(priv))
1134 return -EFAULT;
1135 return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
1136 type, flags,
1137 params);
1138 break;
1139 case NL80211_IFTYPE_AP:
1140 if (mwifiex_cfg80211_deinit_p2p(priv))
1141 return -EFAULT;
1142 return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
1143 flags, params);
1144 case NL80211_IFTYPE_UNSPECIFIED:
acebe8c1
ZL
1145 mwifiex_dbg(priv->adapter, INFO,
1146 "%s: kept type as P2P\n", dev->name);
047eaaf6
AP
1147 case NL80211_IFTYPE_P2P_CLIENT:
1148 case NL80211_IFTYPE_P2P_GO:
e1a2b7a3
SP
1149 return 0;
1150 default:
acebe8c1
ZL
1151 mwifiex_dbg(priv->adapter, ERROR,
1152 "%s: changing to %d not supported\n",
1153 dev->name, type);
e1a2b7a3
SP
1154 return -EOPNOTSUPP;
1155 }
1156 break;
5e6e3a92 1157 default:
acebe8c1
ZL
1158 mwifiex_dbg(priv->adapter, ERROR,
1159 "%s: unknown iftype: %d\n",
1160 dev->name, dev->ieee80211_ptr->iftype);
4f02341a 1161 return -EOPNOTSUPP;
5e6e3a92 1162 }
5e6e3a92 1163
eecd8250 1164
047eaaf6 1165 return 0;
5e6e3a92
BZ
1166}
1167
a5f39056
YAP
1168static void
1169mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo,
1170 struct rate_info *rate)
1171{
1172 struct mwifiex_adapter *adapter = priv->adapter;
1173
1174 if (adapter->is_hw_11ac_capable) {
1175 /* bit[1-0]: 00=LG 01=HT 10=VHT */
1176 if (tx_htinfo & BIT(0)) {
1177 /* HT */
1178 rate->mcs = priv->tx_rate;
1179 rate->flags |= RATE_INFO_FLAGS_MCS;
1180 }
1181 if (tx_htinfo & BIT(1)) {
1182 /* VHT */
1183 rate->mcs = priv->tx_rate & 0x0F;
1184 rate->flags |= RATE_INFO_FLAGS_VHT_MCS;
1185 }
1186
1187 if (tx_htinfo & (BIT(1) | BIT(0))) {
1188 /* HT or VHT */
1189 switch (tx_htinfo & (BIT(3) | BIT(2))) {
1190 case 0:
b51f3bee 1191 rate->bw = RATE_INFO_BW_20;
a5f39056
YAP
1192 break;
1193 case (BIT(2)):
b51f3bee 1194 rate->bw = RATE_INFO_BW_40;
a5f39056
YAP
1195 break;
1196 case (BIT(3)):
b51f3bee 1197 rate->bw = RATE_INFO_BW_80;
a5f39056
YAP
1198 break;
1199 case (BIT(3) | BIT(2)):
b51f3bee 1200 rate->bw = RATE_INFO_BW_160;
a5f39056
YAP
1201 break;
1202 }
1203
1204 if (tx_htinfo & BIT(4))
1205 rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
1206
1207 if ((priv->tx_rate >> 4) == 1)
1208 rate->nss = 2;
1209 else
1210 rate->nss = 1;
1211 }
1212 } else {
1213 /*
1214 * Bit 0 in tx_htinfo indicates that current Tx rate
1215 * is 11n rate. Valid MCS index values for us are 0 to 15.
1216 */
1217 if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {
1218 rate->mcs = priv->tx_rate;
1219 rate->flags |= RATE_INFO_FLAGS_MCS;
b51f3bee 1220 rate->bw = RATE_INFO_BW_20;
a5f39056 1221 if (tx_htinfo & BIT(1))
b51f3bee 1222 rate->bw = RATE_INFO_BW_40;
a5f39056
YAP
1223 if (tx_htinfo & BIT(2))
1224 rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
1225 }
1226 }
1227}
1228
5e6e3a92
BZ
1229/*
1230 * This function dumps the station information on a buffer.
1231 *
1232 * The following information are shown -
1233 * - Total bytes transmitted
1234 * - Total bytes received
1235 * - Total packets transmitted
1236 * - Total packets received
1237 * - Signal quality level
1238 * - Transmission rate
1239 */
1240static int
1241mwifiex_dump_station_info(struct mwifiex_private *priv,
8baca1a3 1242 struct mwifiex_sta_node *node,
5e6e3a92
BZ
1243 struct station_info *sinfo)
1244{
006606c0 1245 u32 rate;
5e6e3a92 1246
319090bf
JB
1247 sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) | BIT(NL80211_STA_INFO_TX_BYTES) |
1248 BIT(NL80211_STA_INFO_RX_PACKETS) | BIT(NL80211_STA_INFO_TX_PACKETS) |
1249 BIT(NL80211_STA_INFO_TX_BITRATE) |
1250 BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG);
5e6e3a92 1251
8baca1a3
XH
1252 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
1253 if (!node)
1254 return -ENOENT;
1255
1256 sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) |
1257 BIT(NL80211_STA_INFO_TX_FAILED);
1258 sinfo->inactive_time =
1259 jiffies_to_msecs(jiffies - node->stats.last_rx);
1260
1261 sinfo->signal = node->stats.rssi;
1262 sinfo->signal_avg = node->stats.rssi;
1263 sinfo->rx_bytes = node->stats.rx_bytes;
1264 sinfo->tx_bytes = node->stats.tx_bytes;
1265 sinfo->rx_packets = node->stats.rx_packets;
1266 sinfo->tx_packets = node->stats.tx_packets;
1267 sinfo->tx_failed = node->stats.tx_failed;
1268
1269 mwifiex_parse_htinfo(priv, node->stats.last_tx_htinfo,
1270 &sinfo->txrate);
1271 sinfo->txrate.legacy = node->stats.last_tx_rate * 5;
1272
1273 return 0;
1274 }
1275
5e6e3a92 1276 /* Get signal information from the firmware */
fa0ecbb9
BZ
1277 if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
1278 HostCmd_ACT_GEN_GET, 0, NULL, true)) {
acebe8c1
ZL
1279 mwifiex_dbg(priv->adapter, ERROR,
1280 "failed to get signal information\n");
958a4a86 1281 return -EFAULT;
5e6e3a92
BZ
1282 }
1283
1284 if (mwifiex_drv_get_data_rate(priv, &rate)) {
acebe8c1
ZL
1285 mwifiex_dbg(priv->adapter, ERROR,
1286 "getting data rate error\n");
958a4a86 1287 return -EFAULT;
5e6e3a92
BZ
1288 }
1289
caf60a6c 1290 /* Get DTIM period information from firmware */
fa0ecbb9
BZ
1291 mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
1292 HostCmd_ACT_GEN_GET, DTIM_PERIOD_I,
1293 &priv->dtim_period, true);
caf60a6c 1294
a5f39056 1295 mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate);
4ec6f9c0 1296
7013d3e2 1297 sinfo->signal_avg = priv->bcn_rssi_avg;
5e6e3a92
BZ
1298 sinfo->rx_bytes = priv->stats.rx_bytes;
1299 sinfo->tx_bytes = priv->stats.tx_bytes;
1300 sinfo->rx_packets = priv->stats.rx_packets;
1301 sinfo->tx_packets = priv->stats.tx_packets;
958a4a86 1302 sinfo->signal = priv->bcn_rssi_avg;
4ec6f9c0 1303 /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */
006606c0 1304 sinfo->txrate.legacy = rate * 5;
5e6e3a92 1305
c4f3b972 1306 if (priv->bss_mode == NL80211_IFTYPE_STATION) {
319090bf 1307 sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
c4f3b972
AK
1308 sinfo->bss_param.flags = 0;
1309 if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
1310 WLAN_CAPABILITY_SHORT_PREAMBLE)
1311 sinfo->bss_param.flags |=
1312 BSS_PARAM_FLAGS_SHORT_PREAMBLE;
1313 if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
1314 WLAN_CAPABILITY_SHORT_SLOT_TIME)
1315 sinfo->bss_param.flags |=
1316 BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
caf60a6c 1317 sinfo->bss_param.dtim_period = priv->dtim_period;
c4f3b972
AK
1318 sinfo->bss_param.beacon_interval =
1319 priv->curr_bss_params.bss_descriptor.beacon_period;
1320 }
1321
958a4a86 1322 return 0;
5e6e3a92
BZ
1323}
1324
1325/*
1326 * CFG802.11 operation handler to get station information.
1327 *
1328 * This function only works in connected mode, and dumps the
1329 * requested station information, if available.
1330 */
1331static int
1332mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
3b3a0162 1333 const u8 *mac, struct station_info *sinfo)
5e6e3a92
BZ
1334{
1335 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
5e6e3a92 1336
5e6e3a92
BZ
1337 if (!priv->media_connected)
1338 return -ENOENT;
1339 if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
1340 return -ENOENT;
1341
8baca1a3 1342 return mwifiex_dump_station_info(priv, NULL, sinfo);
5e6e3a92
BZ
1343}
1344
f85aae6b
AK
1345/*
1346 * CFG802.11 operation handler to dump station information.
1347 */
1348static int
1349mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
1350 int idx, u8 *mac, struct station_info *sinfo)
1351{
1352 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
8baca1a3
XH
1353 static struct mwifiex_sta_node *node;
1354
1355 if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
1356 priv->media_connected && idx == 0) {
1357 ether_addr_copy(mac, priv->cfg_bssid);
1358 return mwifiex_dump_station_info(priv, NULL, sinfo);
1359 } else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
1360 mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST,
1361 HostCmd_ACT_GEN_GET, 0, NULL, true);
1362
1363 if (node && (&node->list == &priv->sta_list)) {
1364 node = NULL;
1365 return -ENOENT;
1366 }
f85aae6b 1367
8baca1a3
XH
1368 node = list_prepare_entry(node, &priv->sta_list, list);
1369 list_for_each_entry_continue(node, &priv->sta_list, list) {
1370 ether_addr_copy(mac, node->mac_addr);
1371 return mwifiex_dump_station_info(priv, node, sinfo);
1372 }
1373 }
f85aae6b 1374
8baca1a3 1375 return -ENOENT;
f85aae6b
AK
1376}
1377
6bc6c49f
XH
1378static int
1379mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
1380 int idx, struct survey_info *survey)
1381{
1382 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1383 struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats;
1384 enum ieee80211_band band;
1385
acebe8c1 1386 mwifiex_dbg(priv->adapter, DUMP, "dump_survey idx=%d\n", idx);
6bc6c49f
XH
1387
1388 memset(survey, 0, sizeof(struct survey_info));
1389
1390 if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
1391 priv->media_connected && idx == 0) {
1392 u8 curr_bss_band = priv->curr_bss_params.band;
1393 u32 chan = priv->curr_bss_params.bss_descriptor.channel;
1394
1395 band = mwifiex_band_to_radio_type(curr_bss_band);
1396 survey->channel = ieee80211_get_channel(wiphy,
1397 ieee80211_channel_to_frequency(chan, band));
1398
1399 if (priv->bcn_nf_last) {
1400 survey->filled = SURVEY_INFO_NOISE_DBM;
1401 survey->noise = priv->bcn_nf_last;
1402 }
1403 return 0;
1404 }
1405
1406 if (idx >= priv->adapter->num_in_chan_stats)
1407 return -ENOENT;
1408
1409 if (!pchan_stats[idx].cca_scan_dur)
1410 return 0;
1411
1412 band = pchan_stats[idx].bandcfg;
1413 survey->channel = ieee80211_get_channel(wiphy,
1414 ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band));
1415 survey->filled = SURVEY_INFO_NOISE_DBM |
4ed20beb
JB
1416 SURVEY_INFO_TIME |
1417 SURVEY_INFO_TIME_BUSY;
6bc6c49f 1418 survey->noise = pchan_stats[idx].noise;
4ed20beb
JB
1419 survey->time = pchan_stats[idx].cca_scan_dur;
1420 survey->time_busy = pchan_stats[idx].cca_busy_dur;
6bc6c49f
XH
1421
1422 return 0;
1423}
1424
5e6e3a92 1425/* Supported rates to be advertised to the cfg80211 */
5e6e3a92
BZ
1426static struct ieee80211_rate mwifiex_rates[] = {
1427 {.bitrate = 10, .hw_value = 2, },
1428 {.bitrate = 20, .hw_value = 4, },
1429 {.bitrate = 55, .hw_value = 11, },
1430 {.bitrate = 110, .hw_value = 22, },
5e6e3a92
BZ
1431 {.bitrate = 60, .hw_value = 12, },
1432 {.bitrate = 90, .hw_value = 18, },
1433 {.bitrate = 120, .hw_value = 24, },
1434 {.bitrate = 180, .hw_value = 36, },
1435 {.bitrate = 240, .hw_value = 48, },
1436 {.bitrate = 360, .hw_value = 72, },
1437 {.bitrate = 480, .hw_value = 96, },
1438 {.bitrate = 540, .hw_value = 108, },
5e6e3a92
BZ
1439};
1440
1441/* Channel definitions to be advertised to cfg80211 */
5e6e3a92
BZ
1442static struct ieee80211_channel mwifiex_channels_2ghz[] = {
1443 {.center_freq = 2412, .hw_value = 1, },
1444 {.center_freq = 2417, .hw_value = 2, },
1445 {.center_freq = 2422, .hw_value = 3, },
1446 {.center_freq = 2427, .hw_value = 4, },
1447 {.center_freq = 2432, .hw_value = 5, },
1448 {.center_freq = 2437, .hw_value = 6, },
1449 {.center_freq = 2442, .hw_value = 7, },
1450 {.center_freq = 2447, .hw_value = 8, },
1451 {.center_freq = 2452, .hw_value = 9, },
1452 {.center_freq = 2457, .hw_value = 10, },
1453 {.center_freq = 2462, .hw_value = 11, },
1454 {.center_freq = 2467, .hw_value = 12, },
1455 {.center_freq = 2472, .hw_value = 13, },
1456 {.center_freq = 2484, .hw_value = 14, },
1457};
1458
1459static struct ieee80211_supported_band mwifiex_band_2ghz = {
1460 .channels = mwifiex_channels_2ghz,
1461 .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),
1462 .bitrates = mwifiex_rates,
8763848e 1463 .n_bitrates = ARRAY_SIZE(mwifiex_rates),
5e6e3a92
BZ
1464};
1465
1466static struct ieee80211_channel mwifiex_channels_5ghz[] = {
1467 {.center_freq = 5040, .hw_value = 8, },
1468 {.center_freq = 5060, .hw_value = 12, },
1469 {.center_freq = 5080, .hw_value = 16, },
1470 {.center_freq = 5170, .hw_value = 34, },
1471 {.center_freq = 5190, .hw_value = 38, },
1472 {.center_freq = 5210, .hw_value = 42, },
1473 {.center_freq = 5230, .hw_value = 46, },
1474 {.center_freq = 5180, .hw_value = 36, },
1475 {.center_freq = 5200, .hw_value = 40, },
1476 {.center_freq = 5220, .hw_value = 44, },
1477 {.center_freq = 5240, .hw_value = 48, },
1478 {.center_freq = 5260, .hw_value = 52, },
1479 {.center_freq = 5280, .hw_value = 56, },
1480 {.center_freq = 5300, .hw_value = 60, },
1481 {.center_freq = 5320, .hw_value = 64, },
1482 {.center_freq = 5500, .hw_value = 100, },
1483 {.center_freq = 5520, .hw_value = 104, },
1484 {.center_freq = 5540, .hw_value = 108, },
1485 {.center_freq = 5560, .hw_value = 112, },
1486 {.center_freq = 5580, .hw_value = 116, },
1487 {.center_freq = 5600, .hw_value = 120, },
1488 {.center_freq = 5620, .hw_value = 124, },
1489 {.center_freq = 5640, .hw_value = 128, },
1490 {.center_freq = 5660, .hw_value = 132, },
1491 {.center_freq = 5680, .hw_value = 136, },
1492 {.center_freq = 5700, .hw_value = 140, },
1493 {.center_freq = 5745, .hw_value = 149, },
1494 {.center_freq = 5765, .hw_value = 153, },
1495 {.center_freq = 5785, .hw_value = 157, },
1496 {.center_freq = 5805, .hw_value = 161, },
1497 {.center_freq = 5825, .hw_value = 165, },
1498};
1499
1500static struct ieee80211_supported_band mwifiex_band_5ghz = {
1501 .channels = mwifiex_channels_5ghz,
1502 .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),
eb416ad3
AP
1503 .bitrates = mwifiex_rates + 4,
1504 .n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,
5e6e3a92
BZ
1505};
1506
1507
1508/* Supported crypto cipher suits to be advertised to cfg80211 */
5e6e3a92
BZ
1509static const u32 mwifiex_cipher_suites[] = {
1510 WLAN_CIPHER_SUITE_WEP40,
1511 WLAN_CIPHER_SUITE_WEP104,
1512 WLAN_CIPHER_SUITE_TKIP,
1513 WLAN_CIPHER_SUITE_CCMP,
53b11231 1514 WLAN_CIPHER_SUITE_AES_CMAC,
5e6e3a92
BZ
1515};
1516
83719be8
SP
1517/* Supported mgmt frame types to be advertised to cfg80211 */
1518static const struct ieee80211_txrx_stypes
1519mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = {
1520 [NL80211_IFTYPE_STATION] = {
1521 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1522 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1523 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1524 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1525 },
1526 [NL80211_IFTYPE_AP] = {
1527 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1528 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1529 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1530 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1531 },
1532 [NL80211_IFTYPE_P2P_CLIENT] = {
1533 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1534 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1535 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1536 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1537 },
1538 [NL80211_IFTYPE_P2P_GO] = {
1539 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1540 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
1541 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1542 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
1543 },
1544};
1545
5d82c53a
YAP
1546/*
1547 * CFG802.11 operation handler for setting bit rates.
1548 *
433c3990
AK
1549 * Function configures data rates to firmware using bitrate mask
1550 * provided by cfg80211.
5d82c53a
YAP
1551 */
1552static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
1553 struct net_device *dev,
1554 const u8 *peer,
1555 const struct cfg80211_bitrate_mask *mask)
1556{
5d82c53a 1557 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
433c3990
AK
1558 u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
1559 enum ieee80211_band band;
c44379e2 1560 struct mwifiex_adapter *adapter = priv->adapter;
5d82c53a 1561
433c3990 1562 if (!priv->media_connected) {
acebe8c1
ZL
1563 mwifiex_dbg(adapter, ERROR,
1564 "Can not set Tx data rate in disconnected state\n");
433c3990 1565 return -EINVAL;
5d82c53a
YAP
1566 }
1567
433c3990 1568 band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
5d82c53a 1569
433c3990 1570 memset(bitmap_rates, 0, sizeof(bitmap_rates));
5d82c53a 1571
433c3990
AK
1572 /* Fill HR/DSSS rates. */
1573 if (band == IEEE80211_BAND_2GHZ)
1574 bitmap_rates[0] = mask->control[band].legacy & 0x000f;
5d82c53a 1575
433c3990
AK
1576 /* Fill OFDM rates */
1577 if (band == IEEE80211_BAND_2GHZ)
1578 bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4;
1579 else
1580 bitmap_rates[1] = mask->control[band].legacy;
1581
d1e33e65
JD
1582 /* Fill HT MCS rates */
1583 bitmap_rates[2] = mask->control[band].ht_mcs[0];
c44379e2 1584 if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
d1e33e65 1585 bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8;
433c3990 1586
c44379e2
AK
1587 /* Fill VHT MCS rates */
1588 if (adapter->fw_api_ver == MWIFIEX_FW_V15) {
1589 bitmap_rates[10] = mask->control[band].vht_mcs[0];
1590 if (adapter->hw_dev_mcs_support == HT_STREAM_2X2)
1591 bitmap_rates[11] = mask->control[band].vht_mcs[1];
1592 }
1593
fa0ecbb9
BZ
1594 return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG,
1595 HostCmd_ACT_GEN_SET, 0, bitmap_rates, true);
5d82c53a
YAP
1596}
1597
fa444bf8
AK
1598/*
1599 * CFG802.11 operation handler for connection quality monitoring.
1600 *
1601 * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI
1602 * events to FW.
1603 */
1604static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
1605 struct net_device *dev,
1606 s32 rssi_thold, u32 rssi_hyst)
1607{
1608 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1609 struct mwifiex_ds_misc_subsc_evt subsc_evt;
1610
1611 priv->cqm_rssi_thold = rssi_thold;
1612 priv->cqm_rssi_hyst = rssi_hyst;
1613
1614 memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
1615 subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
1616
1617 /* Subscribe/unsubscribe low and high rssi events */
1618 if (rssi_thold && rssi_hyst) {
1619 subsc_evt.action = HostCmd_ACT_BITWISE_SET;
1620 subsc_evt.bcn_l_rssi_cfg.abs_value = abs(rssi_thold);
1621 subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold);
1622 subsc_evt.bcn_l_rssi_cfg.evt_freq = 1;
1623 subsc_evt.bcn_h_rssi_cfg.evt_freq = 1;
fa0ecbb9
BZ
1624 return mwifiex_send_cmd(priv,
1625 HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
1626 0, 0, &subsc_evt, true);
fa444bf8
AK
1627 } else {
1628 subsc_evt.action = HostCmd_ACT_BITWISE_CLR;
fa0ecbb9
BZ
1629 return mwifiex_send_cmd(priv,
1630 HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
1631 0, 0, &subsc_evt, true);
fa444bf8
AK
1632 }
1633
1634 return 0;
1635}
1636
5370c836
AP
1637/* cfg80211 operation handler for change_beacon.
1638 * Function retrieves and sets modified management IEs to FW.
1639 */
1640static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
1641 struct net_device *dev,
1642 struct cfg80211_beacon_data *data)
1643{
1644 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1645
9197ab9e 1646 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) {
acebe8c1
ZL
1647 mwifiex_dbg(priv->adapter, ERROR,
1648 "%s: bss_type mismatched\n", __func__);
5370c836
AP
1649 return -EINVAL;
1650 }
1651
1652 if (!priv->bss_started) {
acebe8c1
ZL
1653 mwifiex_dbg(priv->adapter, ERROR,
1654 "%s: bss not started\n", __func__);
5370c836
AP
1655 return -EINVAL;
1656 }
1657
1658 if (mwifiex_set_mgmt_ies(priv, data)) {
acebe8c1
ZL
1659 mwifiex_dbg(priv->adapter, ERROR,
1660 "%s: setting mgmt ies failed\n", __func__);
5370c836
AP
1661 return -EFAULT;
1662 }
1663
1664 return 0;
1665}
1666
0f9e9b8b
AP
1667/* cfg80211 operation handler for del_station.
1668 * Function deauthenticates station which value is provided in mac parameter.
1669 * If mac is NULL/broadcast, all stations in associated station list are
1670 * deauthenticated. If bss is not started or there are no stations in
1671 * associated stations list, no action is taken.
1672 */
1673static int
1674mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
89c771e5 1675 struct station_del_parameters *params)
0f9e9b8b
AP
1676{
1677 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1678 struct mwifiex_sta_node *sta_node;
fc99dd08 1679 u8 deauth_mac[ETH_ALEN];
0f9e9b8b
AP
1680 unsigned long flags;
1681
1682 if (list_empty(&priv->sta_list) || !priv->bss_started)
1683 return 0;
1684
fc99dd08
AP
1685 if (!params->mac || is_broadcast_ether_addr(params->mac))
1686 return 0;
1687
acebe8c1
ZL
1688 mwifiex_dbg(priv->adapter, INFO, "%s: mac address %pM\n",
1689 __func__, params->mac);
fc99dd08 1690
93803b33 1691 eth_zero_addr(deauth_mac);
fc99dd08
AP
1692
1693 spin_lock_irqsave(&priv->sta_list_spinlock, flags);
1694 sta_node = mwifiex_get_sta_entry(priv, params->mac);
1695 if (sta_node)
1696 ether_addr_copy(deauth_mac, params->mac);
1697 spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
1698
1699 if (is_valid_ether_addr(deauth_mac)) {
1700 if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
1701 HostCmd_ACT_GEN_SET, 0,
1702 deauth_mac, true))
1703 return -1;
0f9e9b8b
AP
1704 }
1705
1706 return 0;
1707}
1708
8a279d5b
AK
1709static int
1710mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
1711{
1712 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
1713 struct mwifiex_private *priv = mwifiex_get_priv(adapter,
1714 MWIFIEX_BSS_ROLE_ANY);
1715 struct mwifiex_ds_ant_cfg ant_cfg;
1716
1717 if (!tx_ant || !rx_ant)
1718 return -EOPNOTSUPP;
1719
1720 if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {
1721 /* Not a MIMO chip. User should provide specific antenna number
1722 * for Tx/Rx path or enable all antennas for diversity
1723 */
1724 if (tx_ant != rx_ant)
1725 return -EOPNOTSUPP;
1726
1727 if ((tx_ant & (tx_ant - 1)) &&
1728 (tx_ant != BIT(adapter->number_of_antenna) - 1))
1729 return -EOPNOTSUPP;
1730
1731 if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&
1732 (priv->adapter->number_of_antenna > 1)) {
1733 tx_ant = RF_ANTENNA_AUTO;
1734 rx_ant = RF_ANTENNA_AUTO;
1735 }
a5333914
AK
1736 } else {
1737 struct ieee80211_sta_ht_cap *ht_info;
1738 int rx_mcs_supp;
1739 enum ieee80211_band band;
1740
1741 if ((tx_ant == 0x1 && rx_ant == 0x1)) {
1742 adapter->user_dev_mcs_support = HT_STREAM_1X1;
1743 if (adapter->is_hw_11ac_capable)
1744 adapter->usr_dot_11ac_mcs_support =
1745 MWIFIEX_11AC_MCS_MAP_1X1;
1746 } else {
1747 adapter->user_dev_mcs_support = HT_STREAM_2X2;
1748 if (adapter->is_hw_11ac_capable)
1749 adapter->usr_dot_11ac_mcs_support =
1750 MWIFIEX_11AC_MCS_MAP_2X2;
1751 }
1752
1753 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1754 if (!adapter->wiphy->bands[band])
1755 continue;
1756
1757 ht_info = &adapter->wiphy->bands[band]->ht_cap;
1758 rx_mcs_supp =
1759 GET_RXMCSSUPP(adapter->user_dev_mcs_support);
1760 memset(&ht_info->mcs, 0, adapter->number_of_antenna);
1761 memset(&ht_info->mcs, 0xff, rx_mcs_supp);
1762 }
8a279d5b
AK
1763 }
1764
1765 ant_cfg.tx_ant = tx_ant;
1766 ant_cfg.rx_ant = rx_ant;
1767
fa0ecbb9
BZ
1768 return mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA,
1769 HostCmd_ACT_GEN_SET, 0, &ant_cfg, true);
8a279d5b
AK
1770}
1771
12190c5d
AP
1772/* cfg80211 operation handler for stop ap.
1773 * Function stops BSS running at uAP interface.
1774 */
1775static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1776{
1777 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1778
85afb186
AP
1779 mwifiex_abort_cac(priv);
1780
40bbc21a 1781 if (mwifiex_del_mgmt_ies(priv))
acebe8c1
ZL
1782 mwifiex_dbg(priv->adapter, ERROR,
1783 "Failed to delete mgmt IEs!\n");
40bbc21a 1784
c8258913 1785 priv->ap_11n_enabled = 0;
35c739b5 1786 memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg));
c8258913 1787
fa0ecbb9
BZ
1788 if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
1789 HostCmd_ACT_GEN_SET, 0, NULL, true)) {
acebe8c1
ZL
1790 mwifiex_dbg(priv->adapter, ERROR,
1791 "Failed to stop the BSS\n");
12190c5d
AP
1792 return -1;
1793 }
1794
ed5cfbe6
AP
1795 if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,
1796 HostCmd_ACT_GEN_SET, 0, NULL, true)) {
1797 mwifiex_dbg(priv->adapter, ERROR,
1798 "Failed to reset BSS\n");
1799 return -1;
1800 }
1801
12190c5d
AP
1802 return 0;
1803}
1804
1805/* cfg80211 operation handler for start_ap.
1806 * Function sets beacon period, DTIM period, SSID and security into
1807 * AP config structure.
1808 * AP is configured with these settings and BSS is started.
1809 */
1810static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
1811 struct net_device *dev,
1812 struct cfg80211_ap_settings *params)
1813{
1814 struct mwifiex_uap_bss_param *bss_cfg;
1815 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1816
9197ab9e 1817 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP)
f752dcd5
AP
1818 return -1;
1819
12190c5d
AP
1820 bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
1821 if (!bss_cfg)
1822 return -ENOMEM;
1823
1824 mwifiex_set_sys_config_invalid_data(bss_cfg);
1825
1826 if (params->beacon_interval)
1827 bss_cfg->beacon_period = params->beacon_interval;
1828 if (params->dtim_period)
1829 bss_cfg->dtim_period = params->dtim_period;
1830
1831 if (params->ssid && params->ssid_len) {
1832 memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len);
1833 bss_cfg->ssid.ssid_len = params->ssid_len;
1834 }
b654ca18
AP
1835 if (params->inactivity_timeout > 0) {
1836 /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */
1837 bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout;
1838 bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout;
1839 }
12190c5d 1840
7a1c9934
AP
1841 switch (params->hidden_ssid) {
1842 case NL80211_HIDDEN_SSID_NOT_IN_USE:
1843 bss_cfg->bcast_ssid_ctl = 1;
1844 break;
1845 case NL80211_HIDDEN_SSID_ZERO_LEN:
1846 bss_cfg->bcast_ssid_ctl = 0;
1847 break;
1848 case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
1849 /* firmware doesn't support this type of hidden SSID */
1850 default:
b3190466 1851 kfree(bss_cfg);
7a1c9934
AP
1852 return -EINVAL;
1853 }
1854
7ee38bf4 1855 mwifiex_uap_set_channel(priv, bss_cfg, params->chandef);
a3c2c4f6 1856 mwifiex_set_uap_rates(bss_cfg, params);
05910f4a 1857
f752dcd5
AP
1858 if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
1859 kfree(bss_cfg);
acebe8c1
ZL
1860 mwifiex_dbg(priv->adapter, ERROR,
1861 "Failed to parse secuirty parameters!\n");
f752dcd5
AP
1862 return -1;
1863 }
1864
22281256 1865 mwifiex_set_ht_params(priv, bss_cfg, params);
83c78da9
YAP
1866
1867 if (priv->adapter->is_hw_11ac_capable) {
1868 mwifiex_set_vht_params(priv, bss_cfg, params);
1869 mwifiex_set_vht_width(priv, params->chandef.width,
1870 priv->ap_11ac_enabled);
1871 }
1872
2b6254da
AP
1873 if (priv->ap_11ac_enabled)
1874 mwifiex_set_11ac_ba_params(priv);
1875 else
1876 mwifiex_set_ba_params(priv);
1877
54428c57 1878 mwifiex_set_wmm_params(priv, bss_cfg, params);
22281256 1879
8a73dd63
AP
1880 if (mwifiex_is_11h_active(priv))
1881 mwifiex_set_tpc_params(priv, bss_cfg, params);
1882
cf075eac
AP
1883 if (mwifiex_is_11h_active(priv) &&
1884 !cfg80211_chandef_dfs_required(wiphy, &params->chandef,
1885 priv->bss_mode)) {
acebe8c1
ZL
1886 mwifiex_dbg(priv->adapter, INFO,
1887 "Disable 11h extensions in FW\n");
cf075eac 1888 if (mwifiex_11h_activate(priv, false)) {
acebe8c1
ZL
1889 mwifiex_dbg(priv->adapter, ERROR,
1890 "Failed to disable 11h extensions!!");
cf075eac
AP
1891 return -1;
1892 }
7b716625 1893 priv->state_11h.is_11h_active = false;
cf075eac
AP
1894 }
1895
b654ca18 1896 if (mwifiex_config_start_uap(priv, bss_cfg)) {
acebe8c1
ZL
1897 mwifiex_dbg(priv->adapter, ERROR,
1898 "Failed to start AP\n");
12190c5d
AP
1899 kfree(bss_cfg);
1900 return -1;
1901 }
1902
b0d4c5ec
AP
1903 if (mwifiex_set_mgmt_ies(priv, &params->beacon))
1904 return -1;
1905
35c739b5 1906 memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg));
12190c5d 1907 kfree(bss_cfg);
12190c5d
AP
1908 return 0;
1909}
1910
5e6e3a92
BZ
1911/*
1912 * CFG802.11 operation handler for disconnection request.
1913 *
1914 * This function does not work when there is already a disconnection
1915 * procedure going on.
1916 */
1917static int
1918mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
1919 u16 reason_code)
1920{
1921 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1922
600f5d90 1923 if (mwifiex_deauthenticate(priv, NULL))
5e6e3a92
BZ
1924 return -EFAULT;
1925
acebe8c1
ZL
1926 mwifiex_dbg(priv->adapter, MSG,
1927 "info: successfully disconnected from %pM:\t"
1928 "reason code %d\n", priv->cfg_bssid, reason_code);
5e6e3a92 1929
93803b33 1930 eth_zero_addr(priv->cfg_bssid);
587b36d3 1931 priv->hs2_enabled = false;
5e6e3a92
BZ
1932
1933 return 0;
1934}
1935
1936/*
1937 * This function informs the CFG802.11 subsystem of a new IBSS.
1938 *
1939 * The following information are sent to the CFG802.11 subsystem
1940 * to register the new IBSS. If we do not register the new IBSS,
1941 * a kernel panic will result.
1942 * - SSID
1943 * - SSID length
1944 * - BSSID
1945 * - Channel
1946 */
1947static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
1948{
5e6e3a92
BZ
1949 struct ieee80211_channel *chan;
1950 struct mwifiex_bss_info bss_info;
aa95a48d 1951 struct cfg80211_bss *bss;
270e58e8 1952 int ie_len;
5e6e3a92 1953 u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];
4ed5d521 1954 enum ieee80211_band band;
5e6e3a92 1955
636c4598
YAP
1956 if (mwifiex_get_bss_info(priv, &bss_info))
1957 return -1;
5e6e3a92
BZ
1958
1959 ie_buf[0] = WLAN_EID_SSID;
1960 ie_buf[1] = bss_info.ssid.ssid_len;
1961
1962 memcpy(&ie_buf[sizeof(struct ieee_types_header)],
aea0701e 1963 &bss_info.ssid.ssid, bss_info.ssid.ssid_len);
5e6e3a92
BZ
1964 ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
1965
4ed5d521 1966 band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
4facc34a 1967 chan = __ieee80211_get_channel(priv->wdev.wiphy,
5e6e3a92 1968 ieee80211_channel_to_frequency(bss_info.bss_chan,
4ed5d521 1969 band));
5e6e3a92 1970
4facc34a 1971 bss = cfg80211_inform_bss(priv->wdev.wiphy, chan,
5bc8c1f2 1972 CFG80211_BSS_FTYPE_UNKNOWN,
aea0701e
YAP
1973 bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
1974 0, ie_buf, ie_len, 0, GFP_KERNEL);
4facc34a 1975 cfg80211_put_bss(priv->wdev.wiphy, bss);
5e6e3a92
BZ
1976 memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN);
1977
636c4598 1978 return 0;
5e6e3a92
BZ
1979}
1980
5e6e3a92
BZ
1981/*
1982 * This function connects with a BSS.
1983 *
1984 * This function handles both Infra and Ad-Hoc modes. It also performs
1985 * validity checking on the provided parameters, disconnects from the
1986 * current BSS (if any), sets up the association/scan parameters,
1987 * including security settings, and performs specific SSID scan before
1988 * trying to connect.
1989 *
1990 * For Infra mode, the function returns failure if the specified SSID
1991 * is not found in scan table. However, for Ad-Hoc mode, it can create
1992 * the IBSS if it does not exist. On successful completion in either case,
7c6fa2a8 1993 * the function notifies the CFG802.11 subsystem of the new BSS connection.
5e6e3a92
BZ
1994 */
1995static int
664834de
JM
1996mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
1997 const u8 *ssid, const u8 *bssid, int mode,
1998 struct ieee80211_channel *channel,
5e6e3a92
BZ
1999 struct cfg80211_connect_params *sme, bool privacy)
2000{
b9be5f39 2001 struct cfg80211_ssid req_ssid;
270e58e8 2002 int ret, auth_type = 0;
7c6fa2a8 2003 struct cfg80211_bss *bss = NULL;
d7b9c520 2004 u8 is_scanning_required = 0;
5e6e3a92 2005
b9be5f39 2006 memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
5e6e3a92
BZ
2007
2008 req_ssid.ssid_len = ssid_len;
2009 if (ssid_len > IEEE80211_MAX_SSID_LEN) {
acebe8c1 2010 mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
5e6e3a92
BZ
2011 return -EINVAL;
2012 }
2013
2014 memcpy(req_ssid.ssid, ssid, ssid_len);
2015 if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
acebe8c1 2016 mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n");
5e6e3a92
BZ
2017 return -EINVAL;
2018 }
2019
6670f15b
AK
2020 /* As this is new association, clear locally stored
2021 * keys and security related flags */
2022 priv->sec_info.wpa_enabled = false;
2023 priv->sec_info.wpa2_enabled = false;
2024 priv->wep_key_curr_index = 0;
00f157b4 2025 priv->sec_info.encryption_mode = 0;
a0f6d6ca 2026 priv->sec_info.is_authtype_auto = 0;
53b11231 2027 ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
5e6e3a92 2028
eecd8250 2029 if (mode == NL80211_IFTYPE_ADHOC) {
5e6e3a92
BZ
2030 /* "privacy" is set only for ad-hoc mode */
2031 if (privacy) {
2032 /*
2be50b8d 2033 * Keep WLAN_CIPHER_SUITE_WEP104 for now so that
5e6e3a92
BZ
2034 * the firmware can find a matching network from the
2035 * scan. The cfg80211 does not give us the encryption
2036 * mode at this stage so just setting it to WEP here.
2037 */
203afeca 2038 priv->sec_info.encryption_mode =
2be50b8d 2039 WLAN_CIPHER_SUITE_WEP104;
203afeca 2040 priv->sec_info.authentication_mode =
f986b6d5 2041 NL80211_AUTHTYPE_OPEN_SYSTEM;
5e6e3a92
BZ
2042 }
2043
2044 goto done;
2045 }
2046
2047 /* Now handle infra mode. "sme" is valid for infra mode only */
a0f6d6ca 2048 if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
f986b6d5 2049 auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
a0f6d6ca
AK
2050 priv->sec_info.is_authtype_auto = 1;
2051 } else {
2052 auth_type = sme->auth_type;
2053 }
5e6e3a92
BZ
2054
2055 if (sme->crypto.n_ciphers_pairwise) {
2be50b8d
YAP
2056 priv->sec_info.encryption_mode =
2057 sme->crypto.ciphers_pairwise[0];
203afeca 2058 priv->sec_info.authentication_mode = auth_type;
5e6e3a92
BZ
2059 }
2060
2061 if (sme->crypto.cipher_group) {
2be50b8d 2062 priv->sec_info.encryption_mode = sme->crypto.cipher_group;
203afeca 2063 priv->sec_info.authentication_mode = auth_type;
5e6e3a92
BZ
2064 }
2065 if (sme->ie)
2066 ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);
2067
2068 if (sme->key) {
e6faada5 2069 if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {
acebe8c1
ZL
2070 mwifiex_dbg(priv->adapter, INFO,
2071 "info: setting wep encryption\t"
2072 "with key len %d\n", sme->key_len);
6670f15b 2073 priv->wep_key_curr_index = sme->key_idx;
53b11231
YL
2074 ret = mwifiex_set_encode(priv, NULL, sme->key,
2075 sme->key_len, sme->key_idx,
2076 NULL, 0);
5e6e3a92
BZ
2077 }
2078 }
2079done:
7c6fa2a8
AK
2080 /*
2081 * Scan entries are valid for some time (15 sec). So we can save one
2082 * active scan time if we just try cfg80211_get_bss first. If it fails
2083 * then request scan and cfg80211_get_bss() again for final output.
2084 */
2085 while (1) {
2086 if (is_scanning_required) {
2087 /* Do specific SSID scanning */
2088 if (mwifiex_request_scan(priv, &req_ssid)) {
acebe8c1 2089 mwifiex_dbg(priv->adapter, ERROR, "scan error\n");
7c6fa2a8
AK
2090 return -EFAULT;
2091 }
2092 }
5e6e3a92 2093
7c6fa2a8
AK
2094 /* Find the BSS we want using available scan results */
2095 if (mode == NL80211_IFTYPE_ADHOC)
4facc34a 2096 bss = cfg80211_get_bss(priv->wdev.wiphy, channel,
7c6fa2a8 2097 bssid, ssid, ssid_len,
6eb18137
DL
2098 IEEE80211_BSS_TYPE_IBSS,
2099 IEEE80211_PRIVACY_ANY);
7c6fa2a8 2100 else
4facc34a 2101 bss = cfg80211_get_bss(priv->wdev.wiphy, channel,
7c6fa2a8 2102 bssid, ssid, ssid_len,
6eb18137
DL
2103 IEEE80211_BSS_TYPE_ESS,
2104 IEEE80211_PRIVACY_ANY);
7c6fa2a8
AK
2105
2106 if (!bss) {
2107 if (is_scanning_required) {
acebe8c1
ZL
2108 mwifiex_dbg(priv->adapter, WARN,
2109 "assoc: requested bss not found in scan results\n");
7c6fa2a8
AK
2110 break;
2111 }
2112 is_scanning_required = 1;
2113 } else {
acebe8c1
ZL
2114 mwifiex_dbg(priv->adapter, MSG,
2115 "info: trying to associate to '%s' bssid %pM\n",
2116 (char *)req_ssid.ssid, bss->bssid);
7c6fa2a8
AK
2117 memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
2118 break;
2119 }
5e6e3a92
BZ
2120 }
2121
06975884
AK
2122 ret = mwifiex_bss_start(priv, bss, &req_ssid);
2123 if (ret)
2124 return ret;
5e6e3a92 2125
eecd8250 2126 if (mode == NL80211_IFTYPE_ADHOC) {
5e6e3a92
BZ
2127 /* Inform the BSS information to kernel, otherwise
2128 * kernel will give a panic after successful assoc */
2129 if (mwifiex_cfg80211_inform_ibss_bss(priv))
2130 return -EFAULT;
2131 }
2132
2133 return ret;
2134}
2135
2136/*
2137 * CFG802.11 operation handler for association request.
2138 *
2139 * This function does not work when the current mode is set to Ad-Hoc, or
2140 * when there is already an association procedure going on. The given BSS
2141 * information is used to associate.
2142 */
2143static int
2144mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
2145 struct cfg80211_connect_params *sme)
2146{
2147 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
e00483f7 2148 struct mwifiex_adapter *adapter = priv->adapter;
8bc77a4d 2149 int ret;
5e6e3a92 2150
953b3539 2151 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) {
acebe8c1
ZL
2152 mwifiex_dbg(adapter, ERROR,
2153 "%s: reject infra assoc request in non-STA role\n",
2154 dev->name);
8bc77a4d 2155 return -EINVAL;
e568634a
AP
2156 }
2157
4facc34a 2158 if (priv->wdev.current_bss) {
acebe8c1
ZL
2159 mwifiex_dbg(adapter, ERROR,
2160 "%s: already connected\n", dev->name);
71954f24
UR
2161 return -EALREADY;
2162 }
2163
e00483f7 2164 if (adapter->surprise_removed || adapter->is_cmd_timedout) {
acebe8c1
ZL
2165 mwifiex_dbg(adapter, ERROR,
2166 "%s: Ignore connection.\t"
2167 "Card removed or FW in bad state\n",
2168 dev->name);
e00483f7
AK
2169 return -EFAULT;
2170 }
2171
acebe8c1
ZL
2172 mwifiex_dbg(adapter, INFO,
2173 "info: Trying to associate to %s and bssid %pM\n",
2174 (char *)sme->ssid, sme->bssid);
5e6e3a92
BZ
2175
2176 ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
eecd8250 2177 priv->bss_mode, sme->channel, sme, 0);
38c9d664
AK
2178 if (!ret) {
2179 cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
2180 NULL, 0, WLAN_STATUS_SUCCESS,
2181 GFP_KERNEL);
acebe8c1
ZL
2182 mwifiex_dbg(priv->adapter, MSG,
2183 "info: associated to bssid %pM successfully\n",
2184 priv->cfg_bssid);
9927baa3
AP
2185 if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
2186 priv->adapter->auto_tdls &&
2187 priv->bss_type == MWIFIEX_BSS_TYPE_STA)
2188 mwifiex_setup_auto_tdls_timer(priv);
38c9d664 2189 } else {
acebe8c1
ZL
2190 mwifiex_dbg(priv->adapter, ERROR,
2191 "info: association to bssid %pM failed\n",
2192 priv->cfg_bssid);
93803b33 2193 eth_zero_addr(priv->cfg_bssid);
06975884
AK
2194
2195 if (ret > 0)
2196 cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
2197 NULL, 0, NULL, 0, ret,
2198 GFP_KERNEL);
2199 else
2200 cfg80211_connect_result(priv->netdev, priv->cfg_bssid,
2201 NULL, 0, NULL, 0,
2202 WLAN_STATUS_UNSPECIFIED_FAILURE,
2203 GFP_KERNEL);
38c9d664
AK
2204 }
2205
06975884 2206 return 0;
5e6e3a92
BZ
2207}
2208
05910f4a
AK
2209/*
2210 * This function sets following parameters for ibss network.
2211 * - channel
2212 * - start band
2213 * - 11n flag
2214 * - secondary channel offset
2215 */
2216static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
2217 struct cfg80211_ibss_params *params)
2218{
05910f4a
AK
2219 struct mwifiex_adapter *adapter = priv->adapter;
2220 int index = 0, i;
2221 u8 config_bands = 0;
2222
683b6d3b 2223 if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) {
05910f4a
AK
2224 if (!params->basic_rates) {
2225 config_bands = BAND_B | BAND_G;
2226 } else {
2227 for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
2228 /*
2229 * Rates below 6 Mbps in the table are CCK
2230 * rates; 802.11b and from 6 they are OFDM;
2231 * 802.11G
2232 */
2233 if (mwifiex_rates[i].bitrate == 60) {
2234 index = 1 << i;
2235 break;
2236 }
2237 }
2238
2239 if (params->basic_rates < index) {
2240 config_bands = BAND_B;
2241 } else {
2242 config_bands = BAND_G;
2243 if (params->basic_rates % index)
2244 config_bands |= BAND_B;
2245 }
2246 }
2247
683b6d3b
JB
2248 if (cfg80211_get_chandef_type(&params->chandef) !=
2249 NL80211_CHAN_NO_HT)
3b86acb8 2250 config_bands |= BAND_G | BAND_GN;
05910f4a 2251 } else {
c3ff0b2d 2252 if (cfg80211_get_chandef_type(&params->chandef) ==
683b6d3b 2253 NL80211_CHAN_NO_HT)
05910f4a
AK
2254 config_bands = BAND_A;
2255 else
2256 config_bands = BAND_AN | BAND_A;
2257 }
2258
2259 if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) {
2260 adapter->config_bands = config_bands;
2261 adapter->adhoc_start_band = config_bands;
2262
2263 if ((config_bands & BAND_GN) || (config_bands & BAND_AN))
2264 adapter->adhoc_11n_enabled = true;
2265 else
2266 adapter->adhoc_11n_enabled = false;
2267 }
2268
2269 adapter->sec_chan_offset =
683b6d3b
JB
2270 mwifiex_chan_type_to_sec_chan_offset(
2271 cfg80211_get_chandef_type(&params->chandef));
2272 priv->adhoc_channel = ieee80211_frequency_to_channel(
2273 params->chandef.chan->center_freq);
05910f4a 2274
acebe8c1
ZL
2275 mwifiex_dbg(adapter, INFO,
2276 "info: set ibss band %d, chan %d, chan offset %d\n",
2277 config_bands, priv->adhoc_channel,
2278 adapter->sec_chan_offset);
05910f4a
AK
2279
2280 return 0;
2281}
2282
5e6e3a92
BZ
2283/*
2284 * CFG802.11 operation handler to join an IBSS.
2285 *
2286 * This function does not work in any mode other than Ad-Hoc, or if
2287 * a join operation is already in progress.
2288 */
2289static int
2290mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
2291 struct cfg80211_ibss_params *params)
2292{
f540f9f3 2293 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
5e6e3a92 2294 int ret = 0;
5e6e3a92 2295
eecd8250 2296 if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {
acebe8c1
ZL
2297 mwifiex_dbg(priv->adapter, ERROR,
2298 "request to join ibss received\t"
2299 "when station is not in ibss mode\n");
5e6e3a92
BZ
2300 goto done;
2301 }
2302
acebe8c1
ZL
2303 mwifiex_dbg(priv->adapter, MSG,
2304 "info: trying to join to %s and bssid %pM\n",
2305 (char *)params->ssid, params->bssid);
5e6e3a92 2306
05910f4a
AK
2307 mwifiex_set_ibss_params(priv, params);
2308
5e6e3a92 2309 ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
aea0701e 2310 params->bssid, priv->bss_mode,
683b6d3b
JB
2311 params->chandef.chan, NULL,
2312 params->privacy);
5e6e3a92 2313done:
38c9d664 2314 if (!ret) {
fe94f3a4
AQ
2315 cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
2316 params->chandef.chan, GFP_KERNEL);
acebe8c1
ZL
2317 mwifiex_dbg(priv->adapter, MSG,
2318 "info: joined/created adhoc network with bssid\t"
2319 "%pM successfully\n", priv->cfg_bssid);
38c9d664 2320 } else {
acebe8c1
ZL
2321 mwifiex_dbg(priv->adapter, ERROR,
2322 "info: failed creating/joining adhoc network\n");
38c9d664
AK
2323 }
2324
5e6e3a92
BZ
2325 return ret;
2326}
2327
2328/*
2329 * CFG802.11 operation handler to leave an IBSS.
2330 *
2331 * This function does not work if a leave operation is
2332 * already in progress.
2333 */
2334static int
2335mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
2336{
f540f9f3 2337 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
5e6e3a92 2338
acebe8c1
ZL
2339 mwifiex_dbg(priv->adapter, MSG, "info: disconnecting from essid %pM\n",
2340 priv->cfg_bssid);
600f5d90 2341 if (mwifiex_deauthenticate(priv, NULL))
5e6e3a92
BZ
2342 return -EFAULT;
2343
93803b33 2344 eth_zero_addr(priv->cfg_bssid);
5e6e3a92
BZ
2345
2346 return 0;
2347}
2348
2349/*
2350 * CFG802.11 operation handler for scan request.
2351 *
2352 * This function issues a scan request to the firmware based upon
2353 * the user specified scan configuration. On successfull completion,
2354 * it also informs the results.
2355 */
2356static int
fd014284 2357mwifiex_cfg80211_scan(struct wiphy *wiphy,
5e6e3a92
BZ
2358 struct cfg80211_scan_request *request)
2359{
fd014284 2360 struct net_device *dev = request->wdev->netdev;
5e6e3a92 2361 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
c2476335 2362 int i, offset, ret;
38c9d664 2363 struct ieee80211_channel *chan;
ea021f56 2364 struct ieee_types_header *ie;
75ab753d 2365 struct mwifiex_user_scan_cfg *user_scan_cfg;
5e6e3a92 2366
acebe8c1
ZL
2367 mwifiex_dbg(priv->adapter, CMD,
2368 "info: received scan request on %s\n", dev->name);
5e6e3a92 2369
75ab753d
AK
2370 /* Block scan request if scan operation or scan cleanup when interface
2371 * is disabled is in process
2372 */
2373 if (priv->scan_request || priv->scan_aborting) {
acebe8c1
ZL
2374 mwifiex_dbg(priv->adapter, WARN,
2375 "cmd: Scan already in process..\n");
f162cac8
AK
2376 return -EBUSY;
2377 }
2378
75ab753d
AK
2379 user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
2380 if (!user_scan_cfg)
38c9d664 2381 return -ENOMEM;
be0b281e 2382
6fcf2b10
BZ
2383 priv->scan_request = request;
2384
75ab753d
AK
2385 user_scan_cfg->num_ssids = request->n_ssids;
2386 user_scan_cfg->ssid_list = request->ssids;
be0b281e 2387
13d7ba78 2388 if (request->ie && request->ie_len) {
ea021f56 2389 offset = 0;
13d7ba78
AP
2390 for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
2391 if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)
2392 continue;
2393 priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN;
ea021f56
SP
2394 ie = (struct ieee_types_header *)(request->ie + offset);
2395 memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len);
2396 offset += sizeof(*ie) + ie->len;
2397
2398 if (offset >= request->ie_len)
2399 break;
13d7ba78
AP
2400 }
2401 }
2402
901ceba4
SP
2403 for (i = 0; i < min_t(u32, request->n_channels,
2404 MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
38c9d664 2405 chan = request->channels[i];
75ab753d
AK
2406 user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
2407 user_scan_cfg->chan_list[i].radio_type = chan->band;
38c9d664 2408
a9c1c89e 2409 if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids)
75ab753d 2410 user_scan_cfg->chan_list[i].scan_type =
aea0701e 2411 MWIFIEX_SCAN_TYPE_PASSIVE;
38c9d664 2412 else
75ab753d 2413 user_scan_cfg->chan_list[i].scan_type =
aea0701e 2414 MWIFIEX_SCAN_TYPE_ACTIVE;
38c9d664 2415
75ab753d 2416 user_scan_cfg->chan_list[i].scan_time = 0;
38c9d664 2417 }
c2476335 2418
cb91be87
AP
2419 if (priv->adapter->scan_chan_gap_enabled &&
2420 mwifiex_is_any_intf_active(priv))
2421 user_scan_cfg->scan_chan_gap =
2422 priv->adapter->scan_chan_gap_time;
2423
75ab753d
AK
2424 ret = mwifiex_scan_networks(priv, user_scan_cfg);
2425 kfree(user_scan_cfg);
c2476335 2426 if (ret) {
acebe8c1
ZL
2427 mwifiex_dbg(priv->adapter, ERROR,
2428 "scan failed: %d\n", ret);
75ab753d 2429 priv->scan_aborting = false;
6fcf2b10 2430 priv->scan_request = NULL;
c2476335
BZ
2431 return ret;
2432 }
38c9d664 2433
13d7ba78
AP
2434 if (request->ie && request->ie_len) {
2435 for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
2436 if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) {
2437 priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR;
2438 memset(&priv->vs_ie[i].ie, 0,
2439 MWIFIEX_MAX_VSIE_LEN);
2440 }
2441 }
2442 }
5e6e3a92
BZ
2443 return 0;
2444}
2445
a5f39056
YAP
2446static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info,
2447 struct mwifiex_private *priv)
2448{
2449 struct mwifiex_adapter *adapter = priv->adapter;
a5f39056
YAP
2450
2451 vht_info->vht_supported = true;
2452
43283feb 2453 vht_info->cap = adapter->hw_dot_11ac_dev_cap;
a5f39056
YAP
2454 /* Update MCS support for VHT */
2455 vht_info->vht_mcs.rx_mcs_map = cpu_to_le16(
2456 adapter->hw_dot_11ac_mcs_support & 0xFFFF);
2457 vht_info->vht_mcs.rx_highest = 0;
2458 vht_info->vht_mcs.tx_mcs_map = cpu_to_le16(
2459 adapter->hw_dot_11ac_mcs_support >> 16);
2460 vht_info->vht_mcs.tx_highest = 0;
2461}
2462
5e6e3a92
BZ
2463/*
2464 * This function sets up the CFG802.11 specific HT capability fields
2465 * with default values.
2466 *
2467 * The following default values are set -
2468 * - HT Supported = True
a46b7b5c
AK
2469 * - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K
2470 * - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE
2471 * - HT Capabilities supported by firmware
5e6e3a92
BZ
2472 * - MCS information, Rx mask = 0xff
2473 * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01)
2474 */
2475static void
2476mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
2477 struct mwifiex_private *priv)
2478{
2479 int rx_mcs_supp;
2480 struct ieee80211_mcs_info mcs_set;
2481 u8 *mcs = (u8 *)&mcs_set;
2482 struct mwifiex_adapter *adapter = priv->adapter;
2483
2484 ht_info->ht_supported = true;
a46b7b5c
AK
2485 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
2486 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
5e6e3a92
BZ
2487
2488 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
5e6e3a92 2489
a46b7b5c
AK
2490 /* Fill HT capability information */
2491 if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
2492 ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
2493 else
2494 ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
2495
2496 if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap))
2497 ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
2498 else
2499 ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20;
2500
2501 if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap))
2502 ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
2503 else
2504 ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40;
2505
474a41e9
MH
2506 if (adapter->user_dev_mcs_support == HT_STREAM_2X2)
2507 ht_info->cap |= 3 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
a46b7b5c 2508 else
474a41e9 2509 ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
a46b7b5c
AK
2510
2511 if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap))
2512 ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
2513 else
2514 ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC;
2515
dd0d83c2
AP
2516 if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap))
2517 ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
2518 else
2519 ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD;
2520
2521 if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap))
2522 ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT;
2523 else
2524 ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT;
2525
2526 if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap))
2527 ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
2528 else
2529 ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING;
2530
a46b7b5c
AK
2531 ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;
2532 ht_info->cap |= IEEE80211_HT_CAP_SM_PS;
2533
a5333914
AK
2534 rx_mcs_supp = GET_RXMCSSUPP(adapter->user_dev_mcs_support);
2535 /* Set MCS for 1x1/2x2 */
5e6e3a92
BZ
2536 memset(mcs, 0xff, rx_mcs_supp);
2537 /* Clear all the other values */
2538 memset(&mcs[rx_mcs_supp], 0,
aea0701e 2539 sizeof(struct ieee80211_mcs_info) - rx_mcs_supp);
eecd8250 2540 if (priv->bss_mode == NL80211_IFTYPE_STATION ||
aea0701e 2541 ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
5e6e3a92
BZ
2542 /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
2543 SETHT_MCS32(mcs_set.rx_mask);
2544
2545 memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info));
2546
2547 ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
2548}
2549
93a1df48 2550/*
6bab2e19 2551 * create a new virtual interface with the given name and name assign type
93a1df48 2552 */
84efbb84 2553struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
552bff0c 2554 const char *name,
6bab2e19 2555 unsigned char name_assign_type,
84efbb84
JB
2556 enum nl80211_iftype type,
2557 u32 *flags,
2558 struct vif_params *params)
93a1df48 2559{
67fdf39e
AP
2560 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
2561 struct mwifiex_private *priv;
93a1df48
YAP
2562 struct net_device *dev;
2563 void *mdev_priv;
2564
93a1df48 2565 if (!adapter)
858faa57 2566 return ERR_PTR(-EFAULT);
93a1df48
YAP
2567
2568 switch (type) {
2569 case NL80211_IFTYPE_UNSPECIFIED:
2570 case NL80211_IFTYPE_STATION:
2571 case NL80211_IFTYPE_ADHOC:
cf052335
AP
2572 if (adapter->curr_iface_comb.sta_intf ==
2573 adapter->iface_limit.sta_intf) {
acebe8c1
ZL
2574 mwifiex_dbg(adapter, ERROR,
2575 "cannot create multiple sta/adhoc ifaces\n");
858faa57 2576 return ERR_PTR(-EINVAL);
93a1df48
YAP
2577 }
2578
cf052335
AP
2579 priv = mwifiex_get_unused_priv(adapter);
2580 if (!priv) {
acebe8c1
ZL
2581 mwifiex_dbg(adapter, ERROR,
2582 "could not get free private struct\n");
cf052335
AP
2583 return ERR_PTR(-EFAULT);
2584 }
2585
4facc34a
AP
2586 priv->wdev.wiphy = wiphy;
2587 priv->wdev.iftype = NL80211_IFTYPE_STATION;
d6bffe8b 2588
93a1df48
YAP
2589 if (type == NL80211_IFTYPE_UNSPECIFIED)
2590 priv->bss_mode = NL80211_IFTYPE_STATION;
2591 else
2592 priv->bss_mode = type;
2593
2594 priv->bss_type = MWIFIEX_BSS_TYPE_STA;
2595 priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
a458c0ae 2596 priv->bss_priority = 0;
93a1df48 2597 priv->bss_role = MWIFIEX_BSS_ROLE_STA;
c951a667 2598 priv->bss_num = adapter->curr_iface_comb.sta_intf;
93a1df48 2599
d6bffe8b
AP
2600 break;
2601 case NL80211_IFTYPE_AP:
cf052335
AP
2602 if (adapter->curr_iface_comb.uap_intf ==
2603 adapter->iface_limit.uap_intf) {
acebe8c1
ZL
2604 mwifiex_dbg(adapter, ERROR,
2605 "cannot create multiple AP ifaces\n");
858faa57 2606 return ERR_PTR(-EINVAL);
d6bffe8b
AP
2607 }
2608
cf052335
AP
2609 priv = mwifiex_get_unused_priv(adapter);
2610 if (!priv) {
acebe8c1
ZL
2611 mwifiex_dbg(adapter, ERROR,
2612 "could not get free private struct\n");
cf052335
AP
2613 return ERR_PTR(-EFAULT);
2614 }
2615
4facc34a
AP
2616 priv->wdev.wiphy = wiphy;
2617 priv->wdev.iftype = NL80211_IFTYPE_AP;
d6bffe8b
AP
2618
2619 priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
2620 priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
a458c0ae 2621 priv->bss_priority = 0;
d6bffe8b
AP
2622 priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
2623 priv->bss_started = 0;
c951a667 2624 priv->bss_num = adapter->curr_iface_comb.uap_intf;
d6bffe8b
AP
2625 priv->bss_mode = type;
2626
197f4a2e
SP
2627 break;
2628 case NL80211_IFTYPE_P2P_CLIENT:
cf052335
AP
2629 if (adapter->curr_iface_comb.p2p_intf ==
2630 adapter->iface_limit.p2p_intf) {
acebe8c1
ZL
2631 mwifiex_dbg(adapter, ERROR,
2632 "cannot create multiple P2P ifaces\n");
197f4a2e
SP
2633 return ERR_PTR(-EINVAL);
2634 }
2635
cf052335
AP
2636 priv = mwifiex_get_unused_priv(adapter);
2637 if (!priv) {
acebe8c1
ZL
2638 mwifiex_dbg(adapter, ERROR,
2639 "could not get free private struct\n");
cf052335
AP
2640 return ERR_PTR(-EFAULT);
2641 }
197f4a2e 2642
cf052335 2643 priv->wdev.wiphy = wiphy;
197f4a2e
SP
2644 /* At start-up, wpa_supplicant tries to change the interface
2645 * to NL80211_IFTYPE_STATION if it is not managed mode.
197f4a2e 2646 */
4facc34a 2647 priv->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT;
5586d3e2 2648 priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT;
197f4a2e
SP
2649
2650 /* Setting bss_type to P2P tells firmware that this interface
2651 * is receiving P2P peers found during find phase and doing
2652 * action frame handshake.
2653 */
2654 priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
2655
2656 priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
2657 priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
2658 priv->bss_role = MWIFIEX_BSS_ROLE_STA;
2659 priv->bss_started = 0;
c951a667 2660 priv->bss_num = adapter->curr_iface_comb.p2p_intf;
197f4a2e 2661
bec568ff 2662 if (mwifiex_cfg80211_init_p2p_client(priv)) {
4facc34a
AP
2663 memset(&priv->wdev, 0, sizeof(priv->wdev));
2664 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2665 return ERR_PTR(-EFAULT);
bec568ff 2666 }
66aa1ae2 2667
93a1df48
YAP
2668 break;
2669 default:
acebe8c1 2670 mwifiex_dbg(adapter, ERROR, "type not supported\n");
858faa57 2671 return ERR_PTR(-EINVAL);
93a1df48
YAP
2672 }
2673
47411a06 2674 dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name,
6bab2e19 2675 name_assign_type, ether_setup,
c835a677 2676 IEEE80211_NUM_ACS, 1);
93a1df48 2677 if (!dev) {
acebe8c1
ZL
2678 mwifiex_dbg(adapter, ERROR,
2679 "no memory available for netdevice\n");
4facc34a
AP
2680 memset(&priv->wdev, 0, sizeof(priv->wdev));
2681 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
858faa57 2682 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
4facc34a 2683 return ERR_PTR(-ENOMEM);
93a1df48
YAP
2684 }
2685
d6bffe8b
AP
2686 mwifiex_init_priv_params(priv, dev);
2687 priv->netdev = dev;
2688
2689 mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);
a5f39056
YAP
2690 if (adapter->is_hw_11ac_capable)
2691 mwifiex_setup_vht_caps(
2692 &wiphy->bands[IEEE80211_BAND_2GHZ]->vht_cap, priv);
d6bffe8b
AP
2693
2694 if (adapter->config_bands & BAND_A)
2695 mwifiex_setup_ht_caps(
2696 &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
2697
a5f39056
YAP
2698 if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable)
2699 mwifiex_setup_vht_caps(
2700 &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv);
2701
93a1df48 2702 dev_net_set(dev, wiphy_net(wiphy));
4facc34a 2703 dev->ieee80211_ptr = &priv->wdev;
93a1df48
YAP
2704 dev->ieee80211_ptr->iftype = priv->bss_mode;
2705 memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
93a1df48
YAP
2706 SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
2707
2708 dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
2709 dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
2710 dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
0d7f53e3 2711 dev->ethtool_ops = &mwifiex_ethtool_ops;
93a1df48
YAP
2712
2713 mdev_priv = netdev_priv(dev);
2714 *((unsigned long *) mdev_priv) = (unsigned long) priv;
2715
93a1df48
YAP
2716 SET_NETDEV_DEV(dev, adapter->dev);
2717
2718 /* Register network device */
2719 if (register_netdevice(dev)) {
acebe8c1
ZL
2720 mwifiex_dbg(adapter, ERROR,
2721 "cannot register virtual network device\n");
858faa57
BZ
2722 free_netdev(dev);
2723 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
bec568ff 2724 priv->netdev = NULL;
4facc34a
AP
2725 memset(&priv->wdev, 0, sizeof(priv->wdev));
2726 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2727 return ERR_PTR(-EFAULT);
93a1df48
YAP
2728 }
2729
ffdcad05 2730 priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s",
85afb186
AP
2731 WQ_HIGHPRI |
2732 WQ_MEM_RECLAIM |
ffdcad05 2733 WQ_UNBOUND, 1, name);
85afb186 2734 if (!priv->dfs_cac_workqueue) {
acebe8c1
ZL
2735 mwifiex_dbg(adapter, ERROR,
2736 "cannot register virtual network device\n");
85afb186
AP
2737 free_netdev(dev);
2738 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2739 priv->netdev = NULL;
2740 memset(&priv->wdev, 0, sizeof(priv->wdev));
2741 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2742 return ERR_PTR(-ENOMEM);
2743 }
2744
2745 INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue);
2746
ffdcad05 2747 priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s",
7d652034 2748 WQ_HIGHPRI | WQ_UNBOUND |
ffdcad05 2749 WQ_MEM_RECLAIM, 1, name);
7d652034 2750 if (!priv->dfs_chan_sw_workqueue) {
acebe8c1
ZL
2751 mwifiex_dbg(adapter, ERROR,
2752 "cannot register virtual network device\n");
7d652034
AP
2753 free_netdev(dev);
2754 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2755 priv->netdev = NULL;
2756 memset(&priv->wdev, 0, sizeof(priv->wdev));
2757 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
2758 return ERR_PTR(-ENOMEM);
2759 }
2760
2761 INIT_DELAYED_WORK(&priv->dfs_chan_sw_work,
2762 mwifiex_dfs_chan_sw_work_queue);
2763
93a1df48 2764 sema_init(&priv->async_sem, 1);
93a1df48 2765
acebe8c1
ZL
2766 mwifiex_dbg(adapter, INFO,
2767 "info: %s: Marvell 802.11 Adapter\n", dev->name);
93a1df48
YAP
2768
2769#ifdef CONFIG_DEBUG_FS
2770 mwifiex_dev_debugfs_init(priv);
2771#endif
bec568ff 2772
cf052335
AP
2773 switch (type) {
2774 case NL80211_IFTYPE_UNSPECIFIED:
2775 case NL80211_IFTYPE_STATION:
2776 case NL80211_IFTYPE_ADHOC:
2777 adapter->curr_iface_comb.sta_intf++;
2778 break;
2779 case NL80211_IFTYPE_AP:
2780 adapter->curr_iface_comb.uap_intf++;
2781 break;
2782 case NL80211_IFTYPE_P2P_CLIENT:
2783 adapter->curr_iface_comb.p2p_intf++;
2784 break;
2785 default:
acebe8c1 2786 mwifiex_dbg(adapter, ERROR, "type not supported\n");
cf052335
AP
2787 return ERR_PTR(-EINVAL);
2788 }
2789
4facc34a 2790 return &priv->wdev;
93a1df48
YAP
2791}
2792EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
2793
2794/*
2795 * del_virtual_intf: remove the virtual interface determined by dev
2796 */
84efbb84 2797int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
93a1df48 2798{
84efbb84 2799 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
cf052335 2800 struct mwifiex_adapter *adapter = priv->adapter;
a1777327 2801 struct sk_buff *skb, *tmp;
93a1df48
YAP
2802
2803#ifdef CONFIG_DEBUG_FS
2804 mwifiex_dev_debugfs_remove(priv);
2805#endif
2806
cf052335 2807 mwifiex_stop_net_dev_queue(priv->netdev, adapter);
93a1df48 2808
a1777327
AP
2809 skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
2810 mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
2811
93a1df48
YAP
2812 if (netif_carrier_ok(priv->netdev))
2813 netif_carrier_off(priv->netdev);
2814
84efbb84
JB
2815 if (wdev->netdev->reg_state == NETREG_REGISTERED)
2816 unregister_netdevice(wdev->netdev);
93a1df48 2817
85afb186
AP
2818 if (priv->dfs_cac_workqueue) {
2819 flush_workqueue(priv->dfs_cac_workqueue);
2820 destroy_workqueue(priv->dfs_cac_workqueue);
2821 priv->dfs_cac_workqueue = NULL;
2822 }
2823
7d652034
AP
2824 if (priv->dfs_chan_sw_workqueue) {
2825 flush_workqueue(priv->dfs_chan_sw_workqueue);
2826 destroy_workqueue(priv->dfs_chan_sw_workqueue);
2827 priv->dfs_chan_sw_workqueue = NULL;
2828 }
93a1df48 2829 /* Clear the priv in adapter */
98a4635b 2830 priv->netdev->ieee80211_ptr = NULL;
93a1df48 2831 priv->netdev = NULL;
4facc34a 2832 priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED;
93a1df48
YAP
2833
2834 priv->media_connected = false;
2835
cf052335
AP
2836 switch (priv->bss_mode) {
2837 case NL80211_IFTYPE_UNSPECIFIED:
2838 case NL80211_IFTYPE_STATION:
2839 case NL80211_IFTYPE_ADHOC:
2840 adapter->curr_iface_comb.sta_intf++;
2841 break;
2842 case NL80211_IFTYPE_AP:
2843 adapter->curr_iface_comb.uap_intf++;
2844 break;
2845 case NL80211_IFTYPE_P2P_CLIENT:
2846 case NL80211_IFTYPE_P2P_GO:
2847 adapter->curr_iface_comb.p2p_intf++;
2848 break;
2849 default:
acebe8c1
ZL
2850 mwifiex_dbg(adapter, ERROR,
2851 "del_virtual_intf: type not supported\n");
cf052335
AP
2852 break;
2853 }
2854
93a1df48
YAP
2855 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
2856
cbf6e055
XH
2857 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA ||
2858 GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
2859 kfree(priv->hist_data);
2860
93a1df48
YAP
2861 return 0;
2862}
2863EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
2864
7da060c1 2865static bool
0434c464
AK
2866mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq,
2867 u8 max_byte_seq)
7da060c1
AK
2868{
2869 int j, k, valid_byte_cnt = 0;
2870 bool dont_care_byte = false;
2871
2872 for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) {
2873 for (k = 0; k < 8; k++) {
2874 if (pat->mask[j] & 1 << k) {
2875 memcpy(byte_seq + valid_byte_cnt,
2876 &pat->pattern[j * 8 + k], 1);
2877 valid_byte_cnt++;
2878 if (dont_care_byte)
2879 return false;
2880 } else {
2881 if (valid_byte_cnt)
2882 dont_care_byte = true;
2883 }
2884
0434c464 2885 if (valid_byte_cnt > max_byte_seq)
7da060c1
AK
2886 return false;
2887 }
2888 }
2889
0434c464 2890 byte_seq[max_byte_seq] = valid_byte_cnt;
7da060c1
AK
2891
2892 return true;
2893}
2894
d1e2586f 2895#ifdef CONFIG_PM
b533be18
MH
2896static void mwifiex_set_auto_arp_mef_entry(struct mwifiex_private *priv,
2897 struct mwifiex_mef_entry *mef_entry)
2898{
2899 int i, filt_num = 0, num_ipv4 = 0;
2900 struct in_device *in_dev;
2901 struct in_ifaddr *ifa;
2902 __be32 ips[MWIFIEX_MAX_SUPPORTED_IPADDR];
2903 struct mwifiex_adapter *adapter = priv->adapter;
2904
2905 mef_entry->mode = MEF_MODE_HOST_SLEEP;
2906 mef_entry->action = MEF_ACTION_AUTO_ARP;
2907
2908 /* Enable ARP offload feature */
2909 memset(ips, 0, sizeof(ips));
2910 for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) {
2911 if (adapter->priv[i]->netdev) {
2912 in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev);
2913 if (!in_dev)
2914 continue;
2915 ifa = in_dev->ifa_list;
2916 if (!ifa || !ifa->ifa_local)
2917 continue;
2918 ips[i] = ifa->ifa_local;
2919 num_ipv4++;
2920 }
2921 }
2922
2923 for (i = 0; i < num_ipv4; i++) {
2924 if (!ips[i])
2925 continue;
2926 mef_entry->filter[filt_num].repeat = 1;
2927 memcpy(mef_entry->filter[filt_num].byte_seq,
2928 (u8 *)&ips[i], sizeof(ips[i]));
2929 mef_entry->filter[filt_num].
2930 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
2931 sizeof(ips[i]);
2932 mef_entry->filter[filt_num].offset = 46;
2933 mef_entry->filter[filt_num].filt_type = TYPE_EQ;
2934 if (filt_num) {
2935 mef_entry->filter[filt_num].filt_action =
2936 TYPE_OR;
2937 }
2938 filt_num++;
2939 }
2940
2941 mef_entry->filter[filt_num].repeat = 1;
2942 mef_entry->filter[filt_num].byte_seq[0] = 0x08;
2943 mef_entry->filter[filt_num].byte_seq[1] = 0x06;
2944 mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = 2;
2945 mef_entry->filter[filt_num].offset = 20;
2946 mef_entry->filter[filt_num].filt_type = TYPE_EQ;
2947 mef_entry->filter[filt_num].filt_action = TYPE_AND;
2948}
2949
2950static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv,
2951 struct mwifiex_ds_mef_cfg *mef_cfg,
2952 struct mwifiex_mef_entry *mef_entry,
2953 struct cfg80211_wowlan *wowlan)
7da060c1 2954{
468133c5 2955 int i, filt_num = 0, ret = 0;
7da060c1 2956 bool first_pat = true;
3f4e854a 2957 u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1];
7da060c1
AK
2958 const u8 ipv4_mc_mac[] = {0x33, 0x33};
2959 const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
7da060c1 2960
7da060c1
AK
2961 mef_entry->mode = MEF_MODE_HOST_SLEEP;
2962 mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST;
2963
2964 for (i = 0; i < wowlan->n_patterns; i++) {
2965 memset(byte_seq, 0, sizeof(byte_seq));
2966 if (!mwifiex_is_pattern_supported(&wowlan->patterns[i],
468133c5
MH
2967 byte_seq,
2968 MWIFIEX_MEF_MAX_BYTESEQ)) {
acebe8c1
ZL
2969 mwifiex_dbg(priv->adapter, ERROR,
2970 "Pattern not supported\n");
7da060c1
AK
2971 kfree(mef_entry);
2972 return -EOPNOTSUPP;
2973 }
2974
2975 if (!wowlan->patterns[i].pkt_offset) {
2976 if (!(byte_seq[0] & 0x01) &&
3f4e854a 2977 (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) {
b533be18 2978 mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;
7da060c1
AK
2979 continue;
2980 } else if (is_broadcast_ether_addr(byte_seq)) {
b533be18 2981 mef_cfg->criteria |= MWIFIEX_CRITERIA_BROADCAST;
7da060c1
AK
2982 continue;
2983 } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
3f4e854a 2984 (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) ||
7da060c1 2985 (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
3f4e854a 2986 (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) {
b533be18 2987 mef_cfg->criteria |= MWIFIEX_CRITERIA_MULTICAST;
7da060c1
AK
2988 continue;
2989 }
2990 }
7da060c1
AK
2991 mef_entry->filter[filt_num].repeat = 1;
2992 mef_entry->filter[filt_num].offset =
468133c5 2993 wowlan->patterns[i].pkt_offset;
7da060c1 2994 memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq,
468133c5 2995 sizeof(byte_seq));
7da060c1
AK
2996 mef_entry->filter[filt_num].filt_type = TYPE_EQ;
2997
2998 if (first_pat)
2999 first_pat = false;
3000 else
3001 mef_entry->filter[filt_num].filt_action = TYPE_AND;
3002
3003 filt_num++;
3004 }
3005
3006 if (wowlan->magic_pkt) {
b533be18 3007 mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST;
7da060c1
AK
3008 mef_entry->filter[filt_num].repeat = 16;
3009 memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
468133c5 3010 ETH_ALEN);
3f4e854a 3011 mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
468133c5 3012 ETH_ALEN;
09e65f5b 3013 mef_entry->filter[filt_num].offset = 28;
7da060c1
AK
3014 mef_entry->filter[filt_num].filt_type = TYPE_EQ;
3015 if (filt_num)
3016 mef_entry->filter[filt_num].filt_action = TYPE_OR;
4dbc13fa
ZY
3017
3018 filt_num++;
3019 mef_entry->filter[filt_num].repeat = 16;
3020 memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
468133c5 3021 ETH_ALEN);
4dbc13fa 3022 mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
468133c5 3023 ETH_ALEN;
4dbc13fa
ZY
3024 mef_entry->filter[filt_num].offset = 56;
3025 mef_entry->filter[filt_num].filt_type = TYPE_EQ;
3026 mef_entry->filter[filt_num].filt_action = TYPE_OR;
7da060c1 3027 }
b533be18
MH
3028 return ret;
3029}
3030
3031static int mwifiex_set_mef_filter(struct mwifiex_private *priv,
3032 struct cfg80211_wowlan *wowlan)
3033{
3034 int ret = 0, num_entries = 1;
3035 struct mwifiex_ds_mef_cfg mef_cfg;
3036 struct mwifiex_mef_entry *mef_entry;
3037
3038 if (wowlan->n_patterns || wowlan->magic_pkt)
3039 num_entries++;
3040
3041 mef_entry = kcalloc(num_entries, sizeof(*mef_entry), GFP_KERNEL);
3042 if (!mef_entry)
3043 return -ENOMEM;
3044
3045 memset(&mef_cfg, 0, sizeof(mef_cfg));
3046 mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST |
3047 MWIFIEX_CRITERIA_UNICAST;
3048 mef_cfg.num_entries = num_entries;
3049 mef_cfg.mef_entry = mef_entry;
3050
3051 mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]);
3052
3053 if (wowlan->n_patterns || wowlan->magic_pkt)
3054 ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg,
3055 &mef_entry[1], wowlan);
7da060c1
AK
3056
3057 if (!mef_cfg.criteria)
3058 mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST |
468133c5
MH
3059 MWIFIEX_CRITERIA_UNICAST |
3060 MWIFIEX_CRITERIA_MULTICAST;
7da060c1 3061
fa0ecbb9 3062 ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG,
b533be18
MH
3063 HostCmd_ACT_GEN_SET, 0,
3064 &mef_cfg, true);
7da060c1
AK
3065 kfree(mef_entry);
3066 return ret;
3067}
3068
468133c5
MH
3069static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
3070 struct cfg80211_wowlan *wowlan)
3071{
3072 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
8a40084e 3073 struct mwifiex_ds_hs_cfg hs_cfg;
5ff46f79
AP
3074 int i, ret = 0;
3075 struct mwifiex_private *priv;
3076
3077 for (i = 0; i < adapter->priv_num; i++) {
3078 priv = adapter->priv[i];
3079 mwifiex_abort_cac(priv);
3080 }
3081
3082 mwifiex_cancel_all_pending_cmd(adapter);
468133c5
MH
3083
3084 if (!wowlan) {
acebe8c1
ZL
3085 mwifiex_dbg(adapter, ERROR,
3086 "None of the WOWLAN triggers enabled\n");
468133c5
MH
3087 return 0;
3088 }
3089
5ff46f79
AP
3090 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
3091
468133c5 3092 if (!priv->media_connected) {
acebe8c1
ZL
3093 mwifiex_dbg(adapter, ERROR,
3094 "Can not configure WOWLAN in disconnected state\n");
468133c5
MH
3095 return 0;
3096 }
3097
b533be18
MH
3098 ret = mwifiex_set_mef_filter(priv, wowlan);
3099 if (ret) {
acebe8c1 3100 mwifiex_dbg(adapter, ERROR, "Failed to set MEF filter\n");
b533be18 3101 return ret;
468133c5
MH
3102 }
3103
8a40084e
MH
3104 if (wowlan->disconnect) {
3105 memset(&hs_cfg, 0, sizeof(hs_cfg));
3106 hs_cfg.is_invoke_hostcmd = false;
3107 hs_cfg.conditions = HS_CFG_COND_MAC_EVENT;
3108 hs_cfg.gpio = HS_CFG_GPIO_DEF;
3109 hs_cfg.gap = HS_CFG_GAP_DEF;
3110 ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
3111 MWIFIEX_SYNC_CMD, &hs_cfg);
3112 if (ret) {
acebe8c1
ZL
3113 mwifiex_dbg(adapter, ERROR,
3114 "Failed to set HS params\n");
8a40084e
MH
3115 return ret;
3116 }
3117 }
3118
468133c5
MH
3119 return ret;
3120}
3121
7da060c1
AK
3122static int mwifiex_cfg80211_resume(struct wiphy *wiphy)
3123{
3124 return 0;
3125}
3126
3127static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy,
3128 bool enabled)
3129{
3130 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
3131
3132 device_set_wakeup_enable(adapter->dev, enabled);
3133}
3134#endif
3135
562fc5b3
AK
3136static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq)
3137{
3138 const u8 ipv4_mc_mac[] = {0x33, 0x33};
3139 const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e};
3140 const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff};
3141
3142 if ((byte_seq[0] & 0x01) &&
3143 (byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 1))
3144 return PACKET_TYPE_UNICAST;
3145 else if (!memcmp(byte_seq, bc_mac, 4))
3146 return PACKET_TYPE_BROADCAST;
3147 else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) &&
3148 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 2) ||
3149 (!memcmp(byte_seq, ipv6_mc_mac, 3) &&
3150 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 3))
3151 return PACKET_TYPE_MULTICAST;
3152
3153 return 0;
3154}
3155
3156static int
3157mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv,
3158 struct cfg80211_coalesce_rules *crule,
3159 struct mwifiex_coalesce_rule *mrule)
3160{
3161 u8 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ + 1];
3162 struct filt_field_param *param;
3163 int i;
3164
3165 mrule->max_coalescing_delay = crule->delay;
3166
3167 param = mrule->params;
3168
3169 for (i = 0; i < crule->n_patterns; i++) {
3170 memset(byte_seq, 0, sizeof(byte_seq));
3171 if (!mwifiex_is_pattern_supported(&crule->patterns[i],
3172 byte_seq,
3173 MWIFIEX_COALESCE_MAX_BYTESEQ)) {
acebe8c1
ZL
3174 mwifiex_dbg(priv->adapter, ERROR,
3175 "Pattern not supported\n");
562fc5b3
AK
3176 return -EOPNOTSUPP;
3177 }
3178
3179 if (!crule->patterns[i].pkt_offset) {
3180 u8 pkt_type;
3181
3182 pkt_type = mwifiex_get_coalesce_pkt_type(byte_seq);
3183 if (pkt_type && mrule->pkt_type) {
acebe8c1
ZL
3184 mwifiex_dbg(priv->adapter, ERROR,
3185 "Multiple packet types not allowed\n");
562fc5b3
AK
3186 return -EOPNOTSUPP;
3187 } else if (pkt_type) {
3188 mrule->pkt_type = pkt_type;
3189 continue;
3190 }
3191 }
3192
3193 if (crule->condition == NL80211_COALESCE_CONDITION_MATCH)
3194 param->operation = RECV_FILTER_MATCH_TYPE_EQ;
3195 else
3196 param->operation = RECV_FILTER_MATCH_TYPE_NE;
3197
3198 param->operand_len = byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ];
3199 memcpy(param->operand_byte_stream, byte_seq,
3200 param->operand_len);
3201 param->offset = crule->patterns[i].pkt_offset;
3202 param++;
3203
3204 mrule->num_of_fields++;
3205 }
3206
3207 if (!mrule->pkt_type) {
acebe8c1
ZL
3208 mwifiex_dbg(priv->adapter, ERROR,
3209 "Packet type can not be determined\n");
562fc5b3
AK
3210 return -EOPNOTSUPP;
3211 }
3212
3213 return 0;
3214}
3215
3216static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
3217 struct cfg80211_coalesce *coalesce)
3218{
3219 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
3220 int i, ret;
3221 struct mwifiex_ds_coalesce_cfg coalesce_cfg;
3222 struct mwifiex_private *priv =
3223 mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
3224
3225 memset(&coalesce_cfg, 0, sizeof(coalesce_cfg));
3226 if (!coalesce) {
acebe8c1
ZL
3227 mwifiex_dbg(adapter, WARN,
3228 "Disable coalesce and reset all previous rules\n");
fa0ecbb9
BZ
3229 return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
3230 HostCmd_ACT_GEN_SET, 0,
3231 &coalesce_cfg, true);
562fc5b3
AK
3232 }
3233
3234 coalesce_cfg.num_of_rules = coalesce->n_rules;
3235 for (i = 0; i < coalesce->n_rules; i++) {
3236 ret = mwifiex_fill_coalesce_rule_info(priv, &coalesce->rules[i],
3237 &coalesce_cfg.rule[i]);
3238 if (ret) {
acebe8c1
ZL
3239 mwifiex_dbg(adapter, ERROR,
3240 "Recheck the patterns provided for rule %d\n",
562fc5b3
AK
3241 i + 1);
3242 return ret;
3243 }
3244 }
3245
fa0ecbb9
BZ
3246 return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG,
3247 HostCmd_ACT_GEN_SET, 0, &coalesce_cfg, true);
562fc5b3
AK
3248}
3249
b23bce29
AP
3250/* cfg80211 ops handler for tdls_mgmt.
3251 * Function prepares TDLS action frame packets and forwards them to FW
3252 */
3253static int
3254mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
3b3a0162 3255 const u8 *peer, u8 action_code, u8 dialog_token,
df942e7b 3256 u16 status_code, u32 peer_capability,
31fa97c5
AN
3257 bool initiator, const u8 *extra_ies,
3258 size_t extra_ies_len)
b23bce29
AP
3259{
3260 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3261 int ret;
3262
3263 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
3264 return -ENOTSUPP;
3265
3266 /* make sure we are in station mode and connected */
3267 if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
3268 return -ENOTSUPP;
3269
3270 switch (action_code) {
3271 case WLAN_TDLS_SETUP_REQUEST:
acebe8c1
ZL
3272 mwifiex_dbg(priv->adapter, MSG,
3273 "Send TDLS Setup Request to %pM status_code=%d\n",
3274 peer, status_code);
9927baa3 3275 mwifiex_add_auto_tdls_peer(priv, peer);
b23bce29
AP
3276 ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
3277 dialog_token, status_code,
3278 extra_ies, extra_ies_len);
3279 break;
3280 case WLAN_TDLS_SETUP_RESPONSE:
9927baa3 3281 mwifiex_add_auto_tdls_peer(priv, peer);
acebe8c1
ZL
3282 mwifiex_dbg(priv->adapter, MSG,
3283 "Send TDLS Setup Response to %pM status_code=%d\n",
3284 peer, status_code);
b23bce29
AP
3285 ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
3286 dialog_token, status_code,
3287 extra_ies, extra_ies_len);
3288 break;
3289 case WLAN_TDLS_SETUP_CONFIRM:
acebe8c1
ZL
3290 mwifiex_dbg(priv->adapter, MSG,
3291 "Send TDLS Confirm to %pM status_code=%d\n", peer,
3292 status_code);
b23bce29
AP
3293 ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
3294 dialog_token, status_code,
3295 extra_ies, extra_ies_len);
3296 break;
3297 case WLAN_TDLS_TEARDOWN:
acebe8c1
ZL
3298 mwifiex_dbg(priv->adapter, MSG,
3299 "Send TDLS Tear down to %pM\n", peer);
b23bce29
AP
3300 ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
3301 dialog_token, status_code,
3302 extra_ies, extra_ies_len);
3303 break;
3304 case WLAN_TDLS_DISCOVERY_REQUEST:
acebe8c1
ZL
3305 mwifiex_dbg(priv->adapter, MSG,
3306 "Send TDLS Discovery Request to %pM\n", peer);
b23bce29
AP
3307 ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
3308 dialog_token, status_code,
3309 extra_ies, extra_ies_len);
3310 break;
3311 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
acebe8c1
ZL
3312 mwifiex_dbg(priv->adapter, MSG,
3313 "Send TDLS Discovery Response to %pM\n", peer);
b23bce29
AP
3314 ret = mwifiex_send_tdls_action_frame(priv, peer, action_code,
3315 dialog_token, status_code,
3316 extra_ies, extra_ies_len);
3317 break;
3318 default:
acebe8c1
ZL
3319 mwifiex_dbg(priv->adapter, ERROR,
3320 "Unknown TDLS mgmt/action frame %pM\n", peer);
b23bce29
AP
3321 ret = -EINVAL;
3322 break;
3323 }
3324
3325 return ret;
3326}
3327
429d90d2
AP
3328static int
3329mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
3b3a0162 3330 const u8 *peer, enum nl80211_tdls_operation action)
429d90d2
AP
3331{
3332 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3333
3334 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) ||
3335 !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP))
3336 return -ENOTSUPP;
3337
3338 /* make sure we are in station mode and connected */
3339 if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected))
3340 return -ENOTSUPP;
3341
acebe8c1
ZL
3342 mwifiex_dbg(priv->adapter, MSG,
3343 "TDLS peer=%pM, oper=%d\n", peer, action);
429d90d2
AP
3344
3345 switch (action) {
3346 case NL80211_TDLS_ENABLE_LINK:
3347 action = MWIFIEX_TDLS_ENABLE_LINK;
3348 break;
3349 case NL80211_TDLS_DISABLE_LINK:
3350 action = MWIFIEX_TDLS_DISABLE_LINK;
3351 break;
3352 case NL80211_TDLS_TEARDOWN:
3353 /* shouldn't happen!*/
acebe8c1
ZL
3354 mwifiex_dbg(priv->adapter, ERROR,
3355 "tdls_oper: teardown from driver not supported\n");
429d90d2
AP
3356 return -EINVAL;
3357 case NL80211_TDLS_SETUP:
3358 /* shouldn't happen!*/
acebe8c1
ZL
3359 mwifiex_dbg(priv->adapter, ERROR,
3360 "tdls_oper: setup from driver not supported\n");
429d90d2
AP
3361 return -EINVAL;
3362 case NL80211_TDLS_DISCOVERY_REQ:
3363 /* shouldn't happen!*/
acebe8c1
ZL
3364 mwifiex_dbg(priv->adapter, ERROR,
3365 "tdls_oper: discovery from driver not supported\n");
429d90d2
AP
3366 return -EINVAL;
3367 default:
acebe8c1
ZL
3368 mwifiex_dbg(priv->adapter, ERROR,
3369 "tdls_oper: operation not supported\n");
429d90d2
AP
3370 return -ENOTSUPP;
3371 }
3372
3373 return mwifiex_tdls_oper(priv, peer, action);
3374}
3375
b0497597
XH
3376static int
3377mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,
3378 const u8 *addr, u8 oper_class,
3379 struct cfg80211_chan_def *chandef)
3380{
3381 struct mwifiex_sta_node *sta_ptr;
3382 unsigned long flags;
3383 u16 chan;
3384 u8 second_chan_offset, band;
3385 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3386
3387 spin_lock_irqsave(&priv->sta_list_spinlock, flags);
3388 sta_ptr = mwifiex_get_sta_entry(priv, addr);
3389 spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
3390
3391 if (!sta_ptr) {
3392 wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
3393 __func__, addr);
3394 return -ENOENT;
3395 }
3396
3397 if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] &
3398 WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) {
3399 wiphy_err(wiphy, "%pM do not support tdls cs\n", addr);
3400 return -ENOENT;
3401 }
3402
3403 if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
3404 sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) {
3405 wiphy_err(wiphy, "channel switch is running, abort request\n");
3406 return -EALREADY;
3407 }
3408
3409 chan = chandef->chan->hw_value;
3410 second_chan_offset = mwifiex_get_sec_chan_offset(chan);
3411 band = chandef->chan->band;
3412 mwifiex_start_tdls_cs(priv, addr, chan, second_chan_offset, band);
3413
3414 return 0;
3415}
3416
3417static void
3418mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy,
3419 struct net_device *dev,
3420 const u8 *addr)
3421{
3422 struct mwifiex_sta_node *sta_ptr;
3423 unsigned long flags;
3424 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3425
3426 spin_lock_irqsave(&priv->sta_list_spinlock, flags);
3427 sta_ptr = mwifiex_get_sta_entry(priv, addr);
3428 spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
3429
3430 if (!sta_ptr) {
3431 wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
3432 __func__, addr);
3433 } else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
3434 sta_ptr->tdls_status == TDLS_IN_BASE_CHAN ||
3435 sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) {
3436 wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n",
3437 addr);
3438 } else
3439 mwifiex_stop_tdls_cs(priv, addr);
3440}
3441
e48e0de0 3442static int
3b3a0162
JB
3443mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
3444 const u8 *mac, struct station_parameters *params)
e48e0de0
AP
3445{
3446 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3447
3448 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
3449 return -ENOTSUPP;
3450
3451 /* make sure we are in station mode and connected */
3452 if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
3453 return -ENOTSUPP;
3454
3455 return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK);
3456}
3457
7d652034
AP
3458static int
3459mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3460 struct cfg80211_csa_settings *params)
3461{
3462 struct ieee_types_header *chsw_ie;
3463 struct ieee80211_channel_sw_ie *channel_sw;
3464 int chsw_msec;
3465 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3466
3467 if (priv->adapter->scan_processing) {
acebe8c1
ZL
3468 mwifiex_dbg(priv->adapter, ERROR,
3469 "radar detection: scan in process...\n");
7d652034
AP
3470 return -EBUSY;
3471 }
3472
3473 if (priv->wdev.cac_started)
3474 return -EBUSY;
3475
3476 if (cfg80211_chandef_identical(&params->chandef,
3477 &priv->dfs_chandef))
3478 return -EINVAL;
3479
3480 chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,
3481 params->beacon_csa.tail,
3482 params->beacon_csa.tail_len);
3483 if (!chsw_ie) {
acebe8c1
ZL
3484 mwifiex_dbg(priv->adapter, ERROR,
3485 "Could not parse channel switch announcement IE\n");
7d652034
AP
3486 return -EINVAL;
3487 }
3488
3489 channel_sw = (void *)(chsw_ie + 1);
3490 if (channel_sw->mode) {
3491 if (netif_carrier_ok(priv->netdev))
3492 netif_carrier_off(priv->netdev);
3493 mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
3494 }
3495
3496 if (mwifiex_del_mgmt_ies(priv))
acebe8c1
ZL
3497 mwifiex_dbg(priv->adapter, ERROR,
3498 "Failed to delete mgmt IEs!\n");
7d652034
AP
3499
3500 if (mwifiex_set_mgmt_ies(priv, &params->beacon_csa)) {
acebe8c1
ZL
3501 mwifiex_dbg(priv->adapter, ERROR,
3502 "%s: setting mgmt ies failed\n", __func__);
7d652034
AP
3503 return -EFAULT;
3504 }
3505
3506 memcpy(&priv->dfs_chandef, &params->chandef, sizeof(priv->dfs_chandef));
3507 memcpy(&priv->beacon_after, &params->beacon_after,
3508 sizeof(priv->beacon_after));
3509
3510 chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100);
3511 queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work,
3512 msecs_to_jiffies(chsw_msec));
3513 return 0;
3514}
3515
7ee38bf4
XH
3516static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
3517 struct wireless_dev *wdev,
3518 struct cfg80211_chan_def *chandef)
3519{
3520 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
3521 struct mwifiex_bssdescriptor *curr_bss;
3522 struct ieee80211_channel *chan;
3523 u8 second_chan_offset;
3524 enum nl80211_channel_type chan_type;
3525 enum ieee80211_band band;
3526 int freq;
3527 int ret = -ENODATA;
3528
3529 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
3530 cfg80211_chandef_valid(&priv->bss_chandef)) {
3531 *chandef = priv->bss_chandef;
3532 ret = 0;
3533 } else if (priv->media_connected) {
3534 curr_bss = &priv->curr_bss_params.bss_descriptor;
3535 band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
3536 freq = ieee80211_channel_to_frequency(curr_bss->channel, band);
3537 chan = ieee80211_get_channel(wiphy, freq);
3538
3539 if (curr_bss->bcn_ht_oper) {
3540 second_chan_offset = curr_bss->bcn_ht_oper->ht_param &
3541 IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
3542 chan_type = mwifiex_sec_chan_offset_to_chan_type
3543 (second_chan_offset);
3544 cfg80211_chandef_create(chandef, chan, chan_type);
3545 } else {
3546 cfg80211_chandef_create(chandef, chan,
3547 NL80211_CHAN_NO_HT);
3548 }
3549 ret = 0;
3550 }
3551
3552 return ret;
3553}
3554
85afb186
AP
3555static int
3556mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
3557 struct net_device *dev,
3558 struct cfg80211_chan_def *chandef,
3559 u32 cac_time_ms)
3560{
3561 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3562 struct mwifiex_radar_params radar_params;
3563
3564 if (priv->adapter->scan_processing) {
acebe8c1
ZL
3565 mwifiex_dbg(priv->adapter, ERROR,
3566 "radar detection: scan already in process...\n");
85afb186
AP
3567 return -EBUSY;
3568 }
3569
cf075eac 3570 if (!mwifiex_is_11h_active(priv)) {
acebe8c1
ZL
3571 mwifiex_dbg(priv->adapter, INFO,
3572 "Enable 11h extensions in FW\n");
cf075eac 3573 if (mwifiex_11h_activate(priv, true)) {
acebe8c1
ZL
3574 mwifiex_dbg(priv->adapter, ERROR,
3575 "Failed to activate 11h extensions!!");
cf075eac
AP
3576 return -1;
3577 }
3578 priv->state_11h.is_11h_active = true;
3579 }
3580
85afb186
AP
3581 memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
3582 radar_params.chandef = chandef;
3583 radar_params.cac_time_ms = cac_time_ms;
3584
3585 memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef));
3586
3587 if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
3588 HostCmd_ACT_GEN_SET, 0, &radar_params, true))
3589 return -1;
3590
3591 queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work,
3592 msecs_to_jiffies(cac_time_ms));
3593 return 0;
3594}
3595
1f4dfd8a 3596static int
3b3a0162
JB
3597mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev,
3598 const u8 *mac,
3599 struct station_parameters *params)
1f4dfd8a
AP
3600{
3601 int ret;
3602 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
3603
3604 /* we support change_station handler only for TDLS peers*/
3605 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
3606 return -ENOTSUPP;
3607
3608 /* make sure we are in station mode and connected */
3609 if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected)
3610 return -ENOTSUPP;
3611
3612 priv->sta_params = params;
3613
3614 ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK);
3615 priv->sta_params = NULL;
3616
3617 return ret;
3618}
3619
5e6e3a92
BZ
3620/* station cfg80211 operations */
3621static struct cfg80211_ops mwifiex_cfg80211_ops = {
93a1df48
YAP
3622 .add_virtual_intf = mwifiex_add_virtual_intf,
3623 .del_virtual_intf = mwifiex_del_virtual_intf,
5e6e3a92
BZ
3624 .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf,
3625 .scan = mwifiex_cfg80211_scan,
3626 .connect = mwifiex_cfg80211_connect,
3627 .disconnect = mwifiex_cfg80211_disconnect,
3628 .get_station = mwifiex_cfg80211_get_station,
f85aae6b 3629 .dump_station = mwifiex_cfg80211_dump_station,
6bc6c49f 3630 .dump_survey = mwifiex_cfg80211_dump_survey,
5e6e3a92 3631 .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,
5e6e3a92
BZ
3632 .join_ibss = mwifiex_cfg80211_join_ibss,
3633 .leave_ibss = mwifiex_cfg80211_leave_ibss,
3634 .add_key = mwifiex_cfg80211_add_key,
3635 .del_key = mwifiex_cfg80211_del_key,
e39faa73 3636 .mgmt_tx = mwifiex_cfg80211_mgmt_tx,
3cec6870 3637 .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register,
7feb4c48
SP
3638 .remain_on_channel = mwifiex_cfg80211_remain_on_channel,
3639 .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel,
5e6e3a92
BZ
3640 .set_default_key = mwifiex_cfg80211_set_default_key,
3641 .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
3642 .set_tx_power = mwifiex_cfg80211_set_tx_power,
5d82c53a 3643 .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
12190c5d
AP
3644 .start_ap = mwifiex_cfg80211_start_ap,
3645 .stop_ap = mwifiex_cfg80211_stop_ap,
5370c836 3646 .change_beacon = mwifiex_cfg80211_change_beacon,
fa444bf8 3647 .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
8a279d5b 3648 .set_antenna = mwifiex_cfg80211_set_antenna,
0f9e9b8b 3649 .del_station = mwifiex_cfg80211_del_station,
7da060c1
AK
3650#ifdef CONFIG_PM
3651 .suspend = mwifiex_cfg80211_suspend,
3652 .resume = mwifiex_cfg80211_resume,
3653 .set_wakeup = mwifiex_cfg80211_set_wakeup,
3654#endif
d1e2586f 3655 .set_coalesce = mwifiex_cfg80211_set_coalesce,
b23bce29 3656 .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,
429d90d2 3657 .tdls_oper = mwifiex_cfg80211_tdls_oper,
b0497597
XH
3658 .tdls_channel_switch = mwifiex_cfg80211_tdls_chan_switch,
3659 .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch,
e48e0de0 3660 .add_station = mwifiex_cfg80211_add_station,
1f4dfd8a 3661 .change_station = mwifiex_cfg80211_change_station,
7ee38bf4 3662 .get_channel = mwifiex_cfg80211_get_channel,
85afb186 3663 .start_radar_detection = mwifiex_cfg80211_start_radar_detection,
7d652034 3664 .channel_switch = mwifiex_cfg80211_channel_switch,
5e6e3a92
BZ
3665};
3666
964dc9e2
JB
3667#ifdef CONFIG_PM
3668static const struct wiphy_wowlan_support mwifiex_wowlan_support = {
8a40084e 3669 .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
3f4e854a 3670 .n_patterns = MWIFIEX_MEF_MAX_FILTERS,
964dc9e2
JB
3671 .pattern_min_len = 1,
3672 .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,
3673 .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
3674};
3675#endif
3676
3c68ef5b
AP
3677static bool mwifiex_is_valid_alpha2(const char *alpha2)
3678{
3679 if (!alpha2 || strlen(alpha2) != 2)
3680 return false;
3681
3682 if (isalpha(alpha2[0]) && isalpha(alpha2[1]))
3683 return true;
3684
3685 return false;
3686}
3687
562fc5b3
AK
3688static const struct wiphy_coalesce_support mwifiex_coalesce_support = {
3689 .n_rules = MWIFIEX_COALESCE_MAX_RULES,
3690 .max_delay = MWIFIEX_MAX_COALESCING_DELAY,
3691 .n_patterns = MWIFIEX_COALESCE_MAX_FILTERS,
3692 .pattern_min_len = 1,
3693 .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN,
3694 .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
3695};
3696
bf354433
AP
3697int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
3698{
3699 u32 n_channels_bg, n_channels_a = 0;
3700
3701 n_channels_bg = mwifiex_band_2ghz.n_channels;
3702
3703 if (adapter->config_bands & BAND_A)
3704 n_channels_a = mwifiex_band_5ghz.n_channels;
3705
3706 adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a);
3707 adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) *
3708 adapter->num_in_chan_stats);
3709
3710 if (!adapter->chan_stats)
3711 return -ENOMEM;
3712
3713 return 0;
3714}
3715
5e6e3a92
BZ
3716/*
3717 * This function registers the device with CFG802.11 subsystem.
3718 *
3719 * The function creates the wireless device/wiphy, populates it with
3720 * default parameters and handler function pointers, and finally
3721 * registers the device.
3722 */
d6bffe8b
AP
3723
3724int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
5e6e3a92 3725{
270e58e8
YAP
3726 int ret;
3727 void *wdev_priv;
d6bffe8b
AP
3728 struct wiphy *wiphy;
3729 struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
9e04a7c6 3730 u8 *country_code;
f862bfd1 3731 u32 thr, retry;
5e6e3a92 3732
d6bffe8b
AP
3733 /* create a new wiphy for use with cfg80211 */
3734 wiphy = wiphy_new(&mwifiex_cfg80211_ops,
3735 sizeof(struct mwifiex_adapter *));
3736 if (!wiphy) {
acebe8c1
ZL
3737 mwifiex_dbg(adapter, ERROR,
3738 "%s: creating new wiphy\n", __func__);
5e6e3a92
BZ
3739 return -ENOMEM;
3740 }
d6bffe8b
AP
3741 wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
3742 wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
83719be8 3743 wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
7feb4c48 3744 wiphy->max_remain_on_channel_duration = 5000;
d6bffe8b
AP
3745 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
3746 BIT(NL80211_IFTYPE_ADHOC) |
197f4a2e
SP
3747 BIT(NL80211_IFTYPE_P2P_CLIENT) |
3748 BIT(NL80211_IFTYPE_P2P_GO) |
d6bffe8b
AP
3749 BIT(NL80211_IFTYPE_AP);
3750
3751 wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
3752 if (adapter->config_bands & BAND_A)
3753 wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
3754 else
3755 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
5e6e3a92 3756
de9e9932
AP
3757 if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
3758 wiphy->iface_combinations = &mwifiex_drcs_iface_comb_ap_sta;
3759 else
3760 wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;
cd8440da
AP
3761 wiphy->n_iface_combinations = 1;
3762
5e6e3a92 3763 /* Initialize cipher suits */
d6bffe8b
AP
3764 wiphy->cipher_suites = mwifiex_cipher_suites;
3765 wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
5e6e3a92 3766
8d05eb22 3767 ether_addr_copy(wiphy->perm_addr, adapter->perm_addr);
d6bffe8b 3768 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2dd2bd6b 3769 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
cc0ba0d5 3770 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
54428c57 3771 WIPHY_FLAG_AP_UAPSD |
7d652034 3772 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
c2b6680f
AP
3773 WIPHY_FLAG_HAS_CHANNEL_SWITCH |
3774 WIPHY_FLAG_PS_ON_BY_DEFAULT;
b23bce29
AP
3775
3776 if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
3777 wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
3778 WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
3779
7da060c1 3780#ifdef CONFIG_PM
964dc9e2 3781 wiphy->wowlan = &mwifiex_wowlan_support;
7da060c1
AK
3782#endif
3783
562fc5b3
AK
3784 wiphy->coalesce = &mwifiex_coalesce_support;
3785
2dd2bd6b 3786 wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
e39faa73
SP
3787 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
3788 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
5e6e3a92 3789
8a279d5b
AK
3790 wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
3791 wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
5e6e3a92 3792
b292219f 3793 wiphy->features |= NL80211_FEATURE_HT_IBSS |
e45a8419 3794 NL80211_FEATURE_INACTIVITY_TIMER |
e3c91683 3795 NL80211_FEATURE_NEED_OBSS_SCAN;
05910f4a 3796
b0497597
XH
3797 if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
3798 wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
3799
808bbebc
AK
3800 if (adapter->fw_api_ver == MWIFIEX_FW_V15)
3801 wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
3802
b5abcf02 3803 /* Reserve space for mwifiex specific private data for BSS */
d6bffe8b 3804 wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
5116f3ce 3805
d6bffe8b 3806 wiphy->reg_notifier = mwifiex_reg_notifier;
5e6e3a92 3807
67fdf39e 3808 /* Set struct mwifiex_adapter pointer in wiphy_priv */
d6bffe8b 3809 wdev_priv = wiphy_priv(wiphy);
67fdf39e 3810 *(unsigned long *)wdev_priv = (unsigned long)adapter;
5e6e3a92 3811
2c208890 3812 set_wiphy_dev(wiphy, priv->adapter->dev);
a7b21165 3813
d6bffe8b 3814 ret = wiphy_register(wiphy);
5e6e3a92 3815 if (ret < 0) {
acebe8c1
ZL
3816 mwifiex_dbg(adapter, ERROR,
3817 "%s: wiphy_register failed: %d\n", __func__, ret);
d6bffe8b 3818 wiphy_free(wiphy);
5e6e3a92 3819 return ret;
5e6e3a92 3820 }
3c68ef5b
AP
3821
3822 if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) {
acebe8c1
ZL
3823 mwifiex_dbg(adapter, INFO,
3824 "driver hint alpha2: %2.2s\n", reg_alpha2);
3c68ef5b
AP
3825 regulatory_hint(wiphy, reg_alpha2);
3826 } else {
3827 country_code = mwifiex_11d_code_2_region(adapter->region_code);
3828 if (country_code)
acebe8c1
ZL
3829 mwifiex_dbg(adapter, WARN,
3830 "ignoring F/W country code %2.2s\n",
3831 country_code);
3c68ef5b 3832 }
5e6e3a92 3833
fa0ecbb9
BZ
3834 mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
3835 HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr, true);
f862bfd1 3836 wiphy->frag_threshold = thr;
fa0ecbb9
BZ
3837 mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
3838 HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr, true);
f862bfd1 3839 wiphy->rts_threshold = thr;
fa0ecbb9
BZ
3840 mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
3841 HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true);
f862bfd1 3842 wiphy->retry_short = (u8) retry;
fa0ecbb9
BZ
3843 mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
3844 HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true);
f862bfd1
UR
3845 wiphy->retry_long = (u8) retry;
3846
d6bffe8b 3847 adapter->wiphy = wiphy;
5e6e3a92
BZ
3848 return ret;
3849}
This page took 0.631698 seconds and 5 git commands to generate.