mwifiex: advertise mgmt_stype to cfg80211
[deliverable/linux.git] / drivers / net / wireless / mwifiex / cfg80211.c
CommitLineData
5e6e3a92
BZ
1/*
2 * Marvell Wireless LAN device driver: CFG80211
3 *
4 * Copyright (C) 2011, Marvell International Ltd.
5 *
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available by writing to the Free Software Foundation, Inc.,
11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 *
14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
16 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
17 * this warranty disclaimer.
18 */
19
20#include "cfg80211.h"
21#include "main.h"
22
cd8440da
AP
23static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
24 {
25 .max = 1, .types = BIT(NL80211_IFTYPE_STATION),
26 },
27 {
28 .max = 1, .types = BIT(NL80211_IFTYPE_AP),
29 },
30};
31
32static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = {
33 .limits = mwifiex_ap_sta_limits,
34 .num_different_channels = 1,
35 .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
36 .max_interfaces = MWIFIEX_MAX_BSS_NUM,
37 .beacon_int_infra_match = true,
38};
39
cc0ba0d5
AK
40static const struct ieee80211_regdomain mwifiex_world_regdom_custom = {
41 .n_reg_rules = 7,
42 .alpha2 = "99",
43 .reg_rules = {
44 /* Channel 1 - 11 */
45 REG_RULE(2412-10, 2462+10, 40, 3, 20, 0),
46 /* Channel 12 - 13 */
47 REG_RULE(2467-10, 2472+10, 20, 3, 20,
48 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
49 /* Channel 14 */
50 REG_RULE(2484-10, 2484+10, 20, 3, 20,
51 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
52 NL80211_RRF_NO_OFDM),
53 /* Channel 36 - 48 */
54 REG_RULE(5180-10, 5240+10, 40, 3, 20,
55 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
56 /* Channel 149 - 165 */
57 REG_RULE(5745-10, 5825+10, 40, 3, 20,
58 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
59 /* Channel 52 - 64 */
60 REG_RULE(5260-10, 5320+10, 40, 3, 30,
61 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
62 NL80211_RRF_DFS),
63 /* Channel 100 - 140 */
64 REG_RULE(5500-10, 5700+10, 40, 3, 30,
65 NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
66 NL80211_RRF_DFS),
67 }
68};
69
5e6e3a92
BZ
70/*
71 * This function maps the nl802.11 channel type into driver channel type.
72 *
73 * The mapping is as follows -
21c3ba34
AK
74 * NL80211_CHAN_NO_HT -> IEEE80211_HT_PARAM_CHA_SEC_NONE
75 * NL80211_CHAN_HT20 -> IEEE80211_HT_PARAM_CHA_SEC_NONE
76 * NL80211_CHAN_HT40PLUS -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE
77 * NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW
78 * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE
5e6e3a92 79 */
21c3ba34 80static u8
05910f4a 81mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
5e6e3a92 82{
05910f4a 83 switch (chan_type) {
5e6e3a92
BZ
84 case NL80211_CHAN_NO_HT:
85 case NL80211_CHAN_HT20:
21c3ba34 86 return IEEE80211_HT_PARAM_CHA_SEC_NONE;
5e6e3a92 87 case NL80211_CHAN_HT40PLUS:
21c3ba34 88 return IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
5e6e3a92 89 case NL80211_CHAN_HT40MINUS:
21c3ba34 90 return IEEE80211_HT_PARAM_CHA_SEC_BELOW;
5e6e3a92 91 default:
21c3ba34 92 return IEEE80211_HT_PARAM_CHA_SEC_NONE;
5e6e3a92 93 }
5e6e3a92
BZ
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)) {
5e6e3a92
BZ
133 wiphy_err(wiphy, "deleting the crypto keys\n");
134 return -EFAULT;
135 }
136
137 wiphy_dbg(wiphy, "info: crypto keys deleted\n");
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;
150 struct timeval tv;
151
152 pkt_len = len + ETH_ALEN;
153
154 skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN +
155 MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len));
156 memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len));
157
158 memcpy(skb_push(skb, sizeof(tx_control)),
159 &tx_control, sizeof(tx_control));
160
161 memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type));
162
163 /* Add packet data and address4 */
164 memcpy(skb_put(skb, sizeof(struct ieee80211_hdr_3addr)), buf,
165 sizeof(struct ieee80211_hdr_3addr));
166 memcpy(skb_put(skb, ETH_ALEN), addr, ETH_ALEN);
167 memcpy(skb_put(skb, len - sizeof(struct ieee80211_hdr_3addr)),
168 buf + sizeof(struct ieee80211_hdr_3addr),
169 len - sizeof(struct ieee80211_hdr_3addr));
170
171 skb->priority = LOW_PRIO_TID;
172 do_gettimeofday(&tv);
173 skb->tstamp = timeval_to_ktime(tv);
174
175 return 0;
176}
177
178/*
179 * CFG802.11 operation handler to transmit a management frame.
180 */
181static int
182mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
183 struct ieee80211_channel *chan, bool offchan,
184 enum nl80211_channel_type channel_type,
185 bool channel_type_valid, unsigned int wait,
186 const u8 *buf, size_t len, bool no_cck,
187 bool dont_wait_for_ack, u64 *cookie)
188{
189 struct sk_buff *skb;
190 u16 pkt_len;
191 const struct ieee80211_mgmt *mgmt;
192 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
193
194 if (!buf || !len) {
195 wiphy_err(wiphy, "invalid buffer and length\n");
196 return -EFAULT;
197 }
198
199 mgmt = (const struct ieee80211_mgmt *)buf;
200 if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA &&
201 ieee80211_is_probe_resp(mgmt->frame_control)) {
202 /* Since we support offload probe resp, we need to skip probe
203 * resp in AP or GO mode */
204 wiphy_dbg(wiphy,
205 "info: skip to send probe resp in AP or GO mode\n");
206 return 0;
207 }
208
209 pkt_len = len + ETH_ALEN;
210 skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN +
211 MWIFIEX_MGMT_FRAME_HEADER_SIZE +
212 pkt_len + sizeof(pkt_len));
213
214 if (!skb) {
215 wiphy_err(wiphy, "allocate skb failed for management frame\n");
216 return -ENOMEM;
217 }
218
219 mwifiex_form_mgmt_frame(skb, buf, len);
220 mwifiex_queue_tx_pkt(priv, skb);
221
222 *cookie = random32() | 1;
223 cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_ATOMIC);
224
225 wiphy_dbg(wiphy, "info: management frame transmitted\n");
226 return 0;
227}
228
5e6e3a92
BZ
229/*
230 * CFG802.11 operation handler to set Tx power.
231 */
232static int
233mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
234 enum nl80211_tx_power_setting type,
742c29fd 235 int mbm)
5e6e3a92 236{
67fdf39e
AP
237 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
238 struct mwifiex_private *priv;
600f5d90 239 struct mwifiex_power_cfg power_cfg;
742c29fd 240 int dbm = MBM_TO_DBM(mbm);
5e6e3a92 241
600f5d90
AK
242 if (type == NL80211_TX_POWER_FIXED) {
243 power_cfg.is_power_auto = 0;
244 power_cfg.power_level = dbm;
245 } else {
246 power_cfg.is_power_auto = 1;
247 }
248
67fdf39e
AP
249 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
250
636c4598 251 return mwifiex_set_tx_power(priv, &power_cfg);
5e6e3a92
BZ
252}
253
254/*
255 * CFG802.11 operation handler to set Power Save option.
256 *
257 * The timeout value, if provided, is currently ignored.
258 */
259static int
260mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
261 struct net_device *dev,
262 bool enabled, int timeout)
263{
f540f9f3 264 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
600f5d90 265 u32 ps_mode;
5e6e3a92
BZ
266
267 if (timeout)
268 wiphy_dbg(wiphy,
aea0701e 269 "info: ignore timeout value for IEEE Power Save\n");
5e6e3a92 270
600f5d90 271 ps_mode = enabled;
5e6e3a92 272
636c4598 273 return mwifiex_drv_set_power(priv, &ps_mode);
5e6e3a92
BZ
274}
275
276/*
277 * CFG802.11 operation handler to set the default network key.
278 */
279static int
280mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
281 u8 key_index, bool unicast,
282 bool multicast)
283{
f540f9f3 284 struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
5e6e3a92 285
2d3d0a88 286 /* Return if WEP key not configured */
5eb02e44 287 if (!priv->sec_info.wep_enabled)
2d3d0a88
AK
288 return 0;
289
96893538
AP
290 if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
291 priv->wep_key_curr_index = key_index;
53b11231
YL
292 } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,
293 NULL, 0)) {
636c4598 294 wiphy_err(wiphy, "set default Tx key index\n");
5e6e3a92 295 return -EFAULT;
636c4598 296 }
5e6e3a92
BZ
297
298 return 0;
299}
300
301/*
302 * CFG802.11 operation handler to add a network key.
303 */
304static int
305mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
306 u8 key_index, bool pairwise, const u8 *mac_addr,
307 struct key_params *params)
308{
f540f9f3 309 struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
96893538 310 struct mwifiex_wep_key *wep_key;
75edd2c6
AP
311 const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
312 const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
5e6e3a92 313
96893538
AP
314 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
315 (params->cipher == WLAN_CIPHER_SUITE_WEP40 ||
316 params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
317 if (params->key && params->key_len) {
318 wep_key = &priv->wep_key[key_index];
319 memset(wep_key, 0, sizeof(struct mwifiex_wep_key));
320 memcpy(wep_key->key_material, params->key,
321 params->key_len);
322 wep_key->key_index = key_index;
323 wep_key->key_length = params->key_len;
324 priv->sec_info.wep_enabled = 1;
325 }
326 return 0;
327 }
328
53b11231 329 if (mwifiex_set_encode(priv, params, params->key, params->key_len,
75edd2c6 330 key_index, peer_mac, 0)) {
636c4598 331 wiphy_err(wiphy, "crypto keys added\n");
5e6e3a92 332 return -EFAULT;
636c4598 333 }
5e6e3a92
BZ
334
335 return 0;
336}
337
338/*
339 * This function sends domain information to the firmware.
340 *
341 * The following information are passed to the firmware -
342 * - Country codes
343 * - Sub bands (first channel, number of channels, maximum Tx power)
344 */
345static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
346{
347 u8 no_of_triplet = 0;
348 struct ieee80211_country_ie_triplet *t;
349 u8 no_of_parsed_chan = 0;
350 u8 first_chan = 0, next_chan = 0, max_pwr = 0;
351 u8 i, flag = 0;
352 enum ieee80211_band band;
353 struct ieee80211_supported_band *sband;
354 struct ieee80211_channel *ch;
67fdf39e
AP
355 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
356 struct mwifiex_private *priv;
5e6e3a92 357 struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg;
5e6e3a92
BZ
358
359 /* Set country code */
67fdf39e
AP
360 domain_info->country_code[0] = adapter->country_code[0];
361 domain_info->country_code[1] = adapter->country_code[1];
5e6e3a92
BZ
362 domain_info->country_code[2] = ' ';
363
364 band = mwifiex_band_to_radio_type(adapter->config_bands);
365 if (!wiphy->bands[band]) {
366 wiphy_err(wiphy, "11D: setting domain info in FW\n");
367 return -1;
368 }
369
370 sband = wiphy->bands[band];
371
372 for (i = 0; i < sband->n_channels ; i++) {
373 ch = &sband->channels[i];
374 if (ch->flags & IEEE80211_CHAN_DISABLED)
375 continue;
376
377 if (!flag) {
378 flag = 1;
379 first_chan = (u32) ch->hw_value;
380 next_chan = first_chan;
34202e28 381 max_pwr = ch->max_reg_power;
5e6e3a92
BZ
382 no_of_parsed_chan = 1;
383 continue;
384 }
385
386 if (ch->hw_value == next_chan + 1 &&
34202e28 387 ch->max_reg_power == max_pwr) {
5e6e3a92
BZ
388 next_chan++;
389 no_of_parsed_chan++;
390 } else {
391 t = &domain_info->triplet[no_of_triplet];
392 t->chans.first_channel = first_chan;
393 t->chans.num_channels = no_of_parsed_chan;
394 t->chans.max_power = max_pwr;
395 no_of_triplet++;
396 first_chan = (u32) ch->hw_value;
397 next_chan = first_chan;
34202e28 398 max_pwr = ch->max_reg_power;
5e6e3a92
BZ
399 no_of_parsed_chan = 1;
400 }
401 }
402
403 if (flag) {
404 t = &domain_info->triplet[no_of_triplet];
405 t->chans.first_channel = first_chan;
406 t->chans.num_channels = no_of_parsed_chan;
407 t->chans.max_power = max_pwr;
408 no_of_triplet++;
409 }
410
411 domain_info->no_of_triplet = no_of_triplet;
636c4598 412
67fdf39e
AP
413 priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
414
636c4598 415 if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
aea0701e 416 HostCmd_ACT_GEN_SET, 0, NULL)) {
5e6e3a92 417 wiphy_err(wiphy, "11D: setting domain info in FW\n");
636c4598
YAP
418 return -1;
419 }
5e6e3a92 420
636c4598 421 return 0;
5e6e3a92
BZ
422}
423
424/*
425 * CFG802.11 regulatory domain callback function.
426 *
427 * This function is called when the regulatory domain is changed due to the
428 * following reasons -
429 * - Set by driver
430 * - Set by system core
431 * - Set by user
432 * - Set bt Country IE
433 */
434static int mwifiex_reg_notifier(struct wiphy *wiphy,
aea0701e 435 struct regulatory_request *request)
5e6e3a92 436{
67fdf39e 437 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
5e6e3a92 438
67fdf39e
AP
439 wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n",
440 request->alpha2[0], request->alpha2[1]);
5e6e3a92 441
67fdf39e 442 memcpy(adapter->country_code, request->alpha2, sizeof(request->alpha2));
5e6e3a92
BZ
443
444 switch (request->initiator) {
445 case NL80211_REGDOM_SET_BY_DRIVER:
446 case NL80211_REGDOM_SET_BY_CORE:
447 case NL80211_REGDOM_SET_BY_USER:
448 break;
449 /* Todo: apply driver specific changes in channel flags based
450 on the request initiator if necessary. */
451 case NL80211_REGDOM_SET_BY_COUNTRY_IE:
452 break;
453 }
454 mwifiex_send_domain_info_cmd_fw(wiphy);
455
456 return 0;
457}
458
5e6e3a92
BZ
459/*
460 * This function sets the fragmentation threshold.
461 *
600f5d90 462 * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE
5e6e3a92
BZ
463 * and MWIFIEX_FRAG_MAX_VALUE.
464 */
465static int
466mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr)
467{
aea0701e
YAP
468 if (frag_thr < MWIFIEX_FRAG_MIN_VALUE ||
469 frag_thr > MWIFIEX_FRAG_MAX_VALUE)
9b930eae 470 frag_thr = MWIFIEX_FRAG_MAX_VALUE;
5e6e3a92 471
9b930eae
AP
472 return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB,
473 HostCmd_ACT_GEN_SET, FRAG_THRESH_I,
474 &frag_thr);
5e6e3a92
BZ
475}
476
477/*
478 * This function sets the RTS threshold.
600f5d90
AK
479
480 * The rts value must lie between MWIFIEX_RTS_MIN_VALUE
481 * and MWIFIEX_RTS_MAX_VALUE.
5e6e3a92
BZ
482 */
483static int
484mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr)
485{
5e6e3a92
BZ
486 if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE)
487 rts_thr = MWIFIEX_RTS_MAX_VALUE;
488
636c4598 489 return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB,
600f5d90
AK
490 HostCmd_ACT_GEN_SET, RTS_THRESH_I,
491 &rts_thr);
5e6e3a92
BZ
492}
493
494/*
495 * CFG802.11 operation handler to set wiphy parameters.
496 *
497 * This function can be used to set the RTS threshold and the
498 * Fragmentation threshold of the driver.
499 */
500static int
501mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
502{
67fdf39e 503 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
9b930eae
AP
504 struct mwifiex_private *priv;
505 struct mwifiex_uap_bss_param *bss_cfg;
506 int ret, bss_started, i;
507
508 for (i = 0; i < adapter->priv_num; i++) {
509 priv = adapter->priv[i];
510
511 switch (priv->bss_role) {
512 case MWIFIEX_BSS_ROLE_UAP:
513 bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param),
514 GFP_KERNEL);
515 if (!bss_cfg)
516 return -ENOMEM;
517
518 mwifiex_set_sys_config_invalid_data(bss_cfg);
519
520 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
521 bss_cfg->rts_threshold = wiphy->rts_threshold;
522 if (changed & WIPHY_PARAM_FRAG_THRESHOLD)
523 bss_cfg->frag_threshold = wiphy->frag_threshold;
524 if (changed & WIPHY_PARAM_RETRY_LONG)
525 bss_cfg->retry_limit = wiphy->retry_long;
526
527 bss_started = priv->bss_started;
528
529 ret = mwifiex_send_cmd_sync(priv,
530 HostCmd_CMD_UAP_BSS_STOP,
531 HostCmd_ACT_GEN_SET, 0,
532 NULL);
533 if (ret) {
534 wiphy_err(wiphy, "Failed to stop the BSS\n");
535 kfree(bss_cfg);
536 return ret;
537 }
538
539 ret = mwifiex_send_cmd_async(priv,
540 HostCmd_CMD_UAP_SYS_CONFIG,
541 HostCmd_ACT_GEN_SET,
e76268da 542 UAP_BSS_PARAMS_I, bss_cfg);
5e6e3a92 543
9b930eae
AP
544 kfree(bss_cfg);
545
546 if (ret) {
547 wiphy_err(wiphy, "Failed to set bss config\n");
548 return ret;
549 }
5e6e3a92 550
9b930eae
AP
551 if (!bss_started)
552 break;
553
554 ret = mwifiex_send_cmd_async(priv,
555 HostCmd_CMD_UAP_BSS_START,
556 HostCmd_ACT_GEN_SET, 0,
557 NULL);
558 if (ret) {
559 wiphy_err(wiphy, "Failed to start BSS\n");
560 return ret;
561 }
562
563 break;
564 case MWIFIEX_BSS_ROLE_STA:
565 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
566 ret = mwifiex_set_rts(priv,
567 wiphy->rts_threshold);
568 if (ret)
569 return ret;
570 }
571 if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
572 ret = mwifiex_set_frag(priv,
573 wiphy->frag_threshold);
574 if (ret)
575 return ret;
576 }
577 break;
578 }
579 }
580
581 return 0;
5e6e3a92
BZ
582}
583
584/*
585 * CFG802.11 operation handler to change interface type.
5e6e3a92
BZ
586 */
587static int
588mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
589 struct net_device *dev,
590 enum nl80211_iftype type, u32 *flags,
591 struct vif_params *params)
592{
270e58e8 593 int ret;
5e6e3a92 594 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
5e6e3a92 595
4f02341a 596 switch (dev->ieee80211_ptr->iftype) {
5e6e3a92 597 case NL80211_IFTYPE_ADHOC:
4f02341a
AP
598 switch (type) {
599 case NL80211_IFTYPE_STATION:
600 break;
601 case NL80211_IFTYPE_UNSPECIFIED:
602 wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name);
603 case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */
604 return 0;
605 case NL80211_IFTYPE_AP:
606 default:
607 wiphy_err(wiphy, "%s: changing to %d not supported\n",
608 dev->name, type);
609 return -EOPNOTSUPP;
610 }
5e6e3a92
BZ
611 break;
612 case NL80211_IFTYPE_STATION:
4f02341a
AP
613 switch (type) {
614 case NL80211_IFTYPE_ADHOC:
615 break;
616 case NL80211_IFTYPE_UNSPECIFIED:
617 wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name);
618 case NL80211_IFTYPE_STATION: /* This shouldn't happen */
619 return 0;
620 case NL80211_IFTYPE_AP:
621 default:
622 wiphy_err(wiphy, "%s: changing to %d not supported\n",
623 dev->name, type);
624 return -EOPNOTSUPP;
625 }
626 break;
627 case NL80211_IFTYPE_AP:
628 switch (type) {
629 case NL80211_IFTYPE_UNSPECIFIED:
630 wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name);
631 case NL80211_IFTYPE_AP: /* This shouldn't happen */
632 return 0;
633 case NL80211_IFTYPE_ADHOC:
634 case NL80211_IFTYPE_STATION:
635 default:
636 wiphy_err(wiphy, "%s: changing to %d not supported\n",
637 dev->name, type);
638 return -EOPNOTSUPP;
639 }
5e6e3a92 640 break;
5e6e3a92 641 default:
4f02341a
AP
642 wiphy_err(wiphy, "%s: unknown iftype: %d\n",
643 dev->name, dev->ieee80211_ptr->iftype);
644 return -EOPNOTSUPP;
5e6e3a92 645 }
5e6e3a92 646
4f02341a
AP
647 dev->ieee80211_ptr->iftype = type;
648 priv->bss_mode = type;
600f5d90 649 mwifiex_deauthenticate(priv, NULL);
eecd8250 650
f986b6d5 651 priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM;
eecd8250 652
600f5d90
AK
653 ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE,
654 HostCmd_ACT_GEN_SET, 0, NULL);
eecd8250 655
5e6e3a92
BZ
656 return ret;
657}
658
659/*
660 * This function dumps the station information on a buffer.
661 *
662 * The following information are shown -
663 * - Total bytes transmitted
664 * - Total bytes received
665 * - Total packets transmitted
666 * - Total packets received
667 * - Signal quality level
668 * - Transmission rate
669 */
670static int
671mwifiex_dump_station_info(struct mwifiex_private *priv,
672 struct station_info *sinfo)
673{
006606c0 674 u32 rate;
5e6e3a92
BZ
675
676 sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES |
7013d3e2
AK
677 STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS |
678 STATION_INFO_TX_BITRATE |
679 STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG;
5e6e3a92
BZ
680
681 /* Get signal information from the firmware */
958a4a86
AK
682 if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_RSSI_INFO,
683 HostCmd_ACT_GEN_GET, 0, NULL)) {
684 dev_err(priv->adapter->dev, "failed to get signal information\n");
685 return -EFAULT;
5e6e3a92
BZ
686 }
687
688 if (mwifiex_drv_get_data_rate(priv, &rate)) {
689 dev_err(priv->adapter->dev, "getting data rate\n");
958a4a86 690 return -EFAULT;
5e6e3a92
BZ
691 }
692
caf60a6c
AK
693 /* Get DTIM period information from firmware */
694 mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB,
695 HostCmd_ACT_GEN_GET, DTIM_PERIOD_I,
696 &priv->dtim_period);
697
4ec6f9c0
AK
698 /*
699 * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid
fe020120 700 * MCS index values for us are 0 to 15.
4ec6f9c0 701 */
fe020120 702 if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {
4ec6f9c0
AK
703 sinfo->txrate.mcs = priv->tx_rate;
704 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
705 /* 40MHz rate */
706 if (priv->tx_htinfo & BIT(1))
707 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
708 /* SGI enabled */
709 if (priv->tx_htinfo & BIT(2))
710 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
711 }
712
7013d3e2 713 sinfo->signal_avg = priv->bcn_rssi_avg;
5e6e3a92
BZ
714 sinfo->rx_bytes = priv->stats.rx_bytes;
715 sinfo->tx_bytes = priv->stats.tx_bytes;
716 sinfo->rx_packets = priv->stats.rx_packets;
717 sinfo->tx_packets = priv->stats.tx_packets;
958a4a86 718 sinfo->signal = priv->bcn_rssi_avg;
4ec6f9c0 719 /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */
006606c0 720 sinfo->txrate.legacy = rate * 5;
5e6e3a92 721
c4f3b972
AK
722 if (priv->bss_mode == NL80211_IFTYPE_STATION) {
723 sinfo->filled |= STATION_INFO_BSS_PARAM;
724 sinfo->bss_param.flags = 0;
725 if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
726 WLAN_CAPABILITY_SHORT_PREAMBLE)
727 sinfo->bss_param.flags |=
728 BSS_PARAM_FLAGS_SHORT_PREAMBLE;
729 if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap &
730 WLAN_CAPABILITY_SHORT_SLOT_TIME)
731 sinfo->bss_param.flags |=
732 BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
caf60a6c 733 sinfo->bss_param.dtim_period = priv->dtim_period;
c4f3b972
AK
734 sinfo->bss_param.beacon_interval =
735 priv->curr_bss_params.bss_descriptor.beacon_period;
736 }
737
958a4a86 738 return 0;
5e6e3a92
BZ
739}
740
741/*
742 * CFG802.11 operation handler to get station information.
743 *
744 * This function only works in connected mode, and dumps the
745 * requested station information, if available.
746 */
747static int
748mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
749 u8 *mac, struct station_info *sinfo)
750{
751 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
5e6e3a92 752
5e6e3a92
BZ
753 if (!priv->media_connected)
754 return -ENOENT;
755 if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
756 return -ENOENT;
757
636c4598 758 return mwifiex_dump_station_info(priv, sinfo);
5e6e3a92
BZ
759}
760
f85aae6b
AK
761/*
762 * CFG802.11 operation handler to dump station information.
763 */
764static int
765mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
766 int idx, u8 *mac, struct station_info *sinfo)
767{
768 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
769
770 if (!priv->media_connected || idx)
771 return -ENOENT;
772
773 memcpy(mac, priv->cfg_bssid, ETH_ALEN);
774
775 return mwifiex_dump_station_info(priv, sinfo);
776}
777
5e6e3a92 778/* Supported rates to be advertised to the cfg80211 */
5e6e3a92
BZ
779static struct ieee80211_rate mwifiex_rates[] = {
780 {.bitrate = 10, .hw_value = 2, },
781 {.bitrate = 20, .hw_value = 4, },
782 {.bitrate = 55, .hw_value = 11, },
783 {.bitrate = 110, .hw_value = 22, },
5e6e3a92
BZ
784 {.bitrate = 60, .hw_value = 12, },
785 {.bitrate = 90, .hw_value = 18, },
786 {.bitrate = 120, .hw_value = 24, },
787 {.bitrate = 180, .hw_value = 36, },
788 {.bitrate = 240, .hw_value = 48, },
789 {.bitrate = 360, .hw_value = 72, },
790 {.bitrate = 480, .hw_value = 96, },
791 {.bitrate = 540, .hw_value = 108, },
5e6e3a92
BZ
792};
793
794/* Channel definitions to be advertised to cfg80211 */
5e6e3a92
BZ
795static struct ieee80211_channel mwifiex_channels_2ghz[] = {
796 {.center_freq = 2412, .hw_value = 1, },
797 {.center_freq = 2417, .hw_value = 2, },
798 {.center_freq = 2422, .hw_value = 3, },
799 {.center_freq = 2427, .hw_value = 4, },
800 {.center_freq = 2432, .hw_value = 5, },
801 {.center_freq = 2437, .hw_value = 6, },
802 {.center_freq = 2442, .hw_value = 7, },
803 {.center_freq = 2447, .hw_value = 8, },
804 {.center_freq = 2452, .hw_value = 9, },
805 {.center_freq = 2457, .hw_value = 10, },
806 {.center_freq = 2462, .hw_value = 11, },
807 {.center_freq = 2467, .hw_value = 12, },
808 {.center_freq = 2472, .hw_value = 13, },
809 {.center_freq = 2484, .hw_value = 14, },
810};
811
812static struct ieee80211_supported_band mwifiex_band_2ghz = {
813 .channels = mwifiex_channels_2ghz,
814 .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),
815 .bitrates = mwifiex_rates,
8763848e 816 .n_bitrates = ARRAY_SIZE(mwifiex_rates),
5e6e3a92
BZ
817};
818
819static struct ieee80211_channel mwifiex_channels_5ghz[] = {
820 {.center_freq = 5040, .hw_value = 8, },
821 {.center_freq = 5060, .hw_value = 12, },
822 {.center_freq = 5080, .hw_value = 16, },
823 {.center_freq = 5170, .hw_value = 34, },
824 {.center_freq = 5190, .hw_value = 38, },
825 {.center_freq = 5210, .hw_value = 42, },
826 {.center_freq = 5230, .hw_value = 46, },
827 {.center_freq = 5180, .hw_value = 36, },
828 {.center_freq = 5200, .hw_value = 40, },
829 {.center_freq = 5220, .hw_value = 44, },
830 {.center_freq = 5240, .hw_value = 48, },
831 {.center_freq = 5260, .hw_value = 52, },
832 {.center_freq = 5280, .hw_value = 56, },
833 {.center_freq = 5300, .hw_value = 60, },
834 {.center_freq = 5320, .hw_value = 64, },
835 {.center_freq = 5500, .hw_value = 100, },
836 {.center_freq = 5520, .hw_value = 104, },
837 {.center_freq = 5540, .hw_value = 108, },
838 {.center_freq = 5560, .hw_value = 112, },
839 {.center_freq = 5580, .hw_value = 116, },
840 {.center_freq = 5600, .hw_value = 120, },
841 {.center_freq = 5620, .hw_value = 124, },
842 {.center_freq = 5640, .hw_value = 128, },
843 {.center_freq = 5660, .hw_value = 132, },
844 {.center_freq = 5680, .hw_value = 136, },
845 {.center_freq = 5700, .hw_value = 140, },
846 {.center_freq = 5745, .hw_value = 149, },
847 {.center_freq = 5765, .hw_value = 153, },
848 {.center_freq = 5785, .hw_value = 157, },
849 {.center_freq = 5805, .hw_value = 161, },
850 {.center_freq = 5825, .hw_value = 165, },
851};
852
853static struct ieee80211_supported_band mwifiex_band_5ghz = {
854 .channels = mwifiex_channels_5ghz,
855 .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),
eb416ad3
AP
856 .bitrates = mwifiex_rates + 4,
857 .n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,
5e6e3a92
BZ
858};
859
860
861/* Supported crypto cipher suits to be advertised to cfg80211 */
5e6e3a92
BZ
862static const u32 mwifiex_cipher_suites[] = {
863 WLAN_CIPHER_SUITE_WEP40,
864 WLAN_CIPHER_SUITE_WEP104,
865 WLAN_CIPHER_SUITE_TKIP,
866 WLAN_CIPHER_SUITE_CCMP,
53b11231 867 WLAN_CIPHER_SUITE_AES_CMAC,
5e6e3a92
BZ
868};
869
83719be8
SP
870/* Supported mgmt frame types to be advertised to cfg80211 */
871static const struct ieee80211_txrx_stypes
872mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = {
873 [NL80211_IFTYPE_STATION] = {
874 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
875 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
876 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
877 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
878 },
879 [NL80211_IFTYPE_AP] = {
880 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
881 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
882 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
883 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
884 },
885 [NL80211_IFTYPE_P2P_CLIENT] = {
886 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
887 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
888 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
889 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
890 },
891 [NL80211_IFTYPE_P2P_GO] = {
892 .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
893 BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
894 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
895 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
896 },
897};
898
5d82c53a
YAP
899/*
900 * CFG802.11 operation handler for setting bit rates.
901 *
433c3990
AK
902 * Function configures data rates to firmware using bitrate mask
903 * provided by cfg80211.
5d82c53a
YAP
904 */
905static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
906 struct net_device *dev,
907 const u8 *peer,
908 const struct cfg80211_bitrate_mask *mask)
909{
5d82c53a 910 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
433c3990
AK
911 u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
912 enum ieee80211_band band;
5d82c53a 913
433c3990
AK
914 if (!priv->media_connected) {
915 dev_err(priv->adapter->dev,
916 "Can not set Tx data rate in disconnected state\n");
917 return -EINVAL;
5d82c53a
YAP
918 }
919
433c3990 920 band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
5d82c53a 921
433c3990 922 memset(bitmap_rates, 0, sizeof(bitmap_rates));
5d82c53a 923
433c3990
AK
924 /* Fill HR/DSSS rates. */
925 if (band == IEEE80211_BAND_2GHZ)
926 bitmap_rates[0] = mask->control[band].legacy & 0x000f;
5d82c53a 927
433c3990
AK
928 /* Fill OFDM rates */
929 if (band == IEEE80211_BAND_2GHZ)
930 bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4;
931 else
932 bitmap_rates[1] = mask->control[band].legacy;
933
934 /* Fill MCS rates */
935 bitmap_rates[2] = mask->control[band].mcs[0];
936 if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2)
937 bitmap_rates[2] |= mask->control[band].mcs[1] << 8;
938
939 return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG,
940 HostCmd_ACT_GEN_SET, 0, bitmap_rates);
5d82c53a
YAP
941}
942
fa444bf8
AK
943/*
944 * CFG802.11 operation handler for connection quality monitoring.
945 *
946 * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI
947 * events to FW.
948 */
949static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy,
950 struct net_device *dev,
951 s32 rssi_thold, u32 rssi_hyst)
952{
953 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
954 struct mwifiex_ds_misc_subsc_evt subsc_evt;
955
956 priv->cqm_rssi_thold = rssi_thold;
957 priv->cqm_rssi_hyst = rssi_hyst;
958
959 memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt));
960 subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH;
961
962 /* Subscribe/unsubscribe low and high rssi events */
963 if (rssi_thold && rssi_hyst) {
964 subsc_evt.action = HostCmd_ACT_BITWISE_SET;
965 subsc_evt.bcn_l_rssi_cfg.abs_value = abs(rssi_thold);
966 subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold);
967 subsc_evt.bcn_l_rssi_cfg.evt_freq = 1;
968 subsc_evt.bcn_h_rssi_cfg.evt_freq = 1;
969 return mwifiex_send_cmd_sync(priv,
970 HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
971 0, 0, &subsc_evt);
972 } else {
973 subsc_evt.action = HostCmd_ACT_BITWISE_CLR;
974 return mwifiex_send_cmd_sync(priv,
975 HostCmd_CMD_802_11_SUBSCRIBE_EVENT,
976 0, 0, &subsc_evt);
977 }
978
979 return 0;
980}
981
5370c836
AP
982/* cfg80211 operation handler for change_beacon.
983 * Function retrieves and sets modified management IEs to FW.
984 */
985static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
986 struct net_device *dev,
987 struct cfg80211_beacon_data *data)
988{
989 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
990
991 if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
992 wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__);
993 return -EINVAL;
994 }
995
996 if (!priv->bss_started) {
997 wiphy_err(wiphy, "%s: bss not started\n", __func__);
998 return -EINVAL;
999 }
1000
1001 if (mwifiex_set_mgmt_ies(priv, data)) {
1002 wiphy_err(wiphy, "%s: setting mgmt ies failed\n", __func__);
1003 return -EFAULT;
1004 }
1005
1006 return 0;
1007}
1008
8a279d5b
AK
1009static int
1010mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
1011{
1012 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
1013 struct mwifiex_private *priv = mwifiex_get_priv(adapter,
1014 MWIFIEX_BSS_ROLE_ANY);
1015 struct mwifiex_ds_ant_cfg ant_cfg;
1016
1017 if (!tx_ant || !rx_ant)
1018 return -EOPNOTSUPP;
1019
1020 if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) {
1021 /* Not a MIMO chip. User should provide specific antenna number
1022 * for Tx/Rx path or enable all antennas for diversity
1023 */
1024 if (tx_ant != rx_ant)
1025 return -EOPNOTSUPP;
1026
1027 if ((tx_ant & (tx_ant - 1)) &&
1028 (tx_ant != BIT(adapter->number_of_antenna) - 1))
1029 return -EOPNOTSUPP;
1030
1031 if ((tx_ant == BIT(adapter->number_of_antenna) - 1) &&
1032 (priv->adapter->number_of_antenna > 1)) {
1033 tx_ant = RF_ANTENNA_AUTO;
1034 rx_ant = RF_ANTENNA_AUTO;
1035 }
1036 }
1037
1038 ant_cfg.tx_ant = tx_ant;
1039 ant_cfg.rx_ant = rx_ant;
1040
1041 return mwifiex_send_cmd_sync(priv, HostCmd_CMD_RF_ANTENNA,
1042 HostCmd_ACT_GEN_SET, 0, &ant_cfg);
1043}
1044
12190c5d
AP
1045/* cfg80211 operation handler for stop ap.
1046 * Function stops BSS running at uAP interface.
1047 */
1048static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1049{
1050 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1051
40bbc21a
AP
1052 if (mwifiex_del_mgmt_ies(priv))
1053 wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
1054
c8258913
AP
1055 priv->ap_11n_enabled = 0;
1056
12190c5d
AP
1057 if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP,
1058 HostCmd_ACT_GEN_SET, 0, NULL)) {
1059 wiphy_err(wiphy, "Failed to stop the BSS\n");
1060 return -1;
1061 }
1062
1063 return 0;
1064}
1065
1066/* cfg80211 operation handler for start_ap.
1067 * Function sets beacon period, DTIM period, SSID and security into
1068 * AP config structure.
1069 * AP is configured with these settings and BSS is started.
1070 */
1071static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
1072 struct net_device *dev,
1073 struct cfg80211_ap_settings *params)
1074{
1075 struct mwifiex_uap_bss_param *bss_cfg;
1076 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
05910f4a 1077 u8 config_bands = 0;
12190c5d 1078
f752dcd5
AP
1079 if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP)
1080 return -1;
adb6ed0c 1081 if (mwifiex_set_mgmt_ies(priv, &params->beacon))
f31acabe 1082 return -1;
f752dcd5 1083
12190c5d
AP
1084 bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
1085 if (!bss_cfg)
1086 return -ENOMEM;
1087
1088 mwifiex_set_sys_config_invalid_data(bss_cfg);
1089
1090 if (params->beacon_interval)
1091 bss_cfg->beacon_period = params->beacon_interval;
1092 if (params->dtim_period)
1093 bss_cfg->dtim_period = params->dtim_period;
1094
1095 if (params->ssid && params->ssid_len) {
1096 memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len);
1097 bss_cfg->ssid.ssid_len = params->ssid_len;
1098 }
1099
7a1c9934
AP
1100 switch (params->hidden_ssid) {
1101 case NL80211_HIDDEN_SSID_NOT_IN_USE:
1102 bss_cfg->bcast_ssid_ctl = 1;
1103 break;
1104 case NL80211_HIDDEN_SSID_ZERO_LEN:
1105 bss_cfg->bcast_ssid_ctl = 0;
1106 break;
1107 case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
1108 /* firmware doesn't support this type of hidden SSID */
1109 default:
b3190466 1110 kfree(bss_cfg);
7a1c9934
AP
1111 return -EINVAL;
1112 }
1113
0abd79e5
AP
1114 bss_cfg->channel =
1115 (u8)ieee80211_frequency_to_channel(params->channel->center_freq);
0abd79e5 1116
05910f4a
AK
1117 /* Set appropriate bands */
1118 if (params->channel->band == IEEE80211_BAND_2GHZ) {
a3c2c4f6
AP
1119 bss_cfg->band_cfg = BAND_CONFIG_BG;
1120
05910f4a
AK
1121 if (params->channel_type == NL80211_CHAN_NO_HT)
1122 config_bands = BAND_B | BAND_G;
1123 else
1124 config_bands = BAND_B | BAND_G | BAND_GN;
1125 } else {
a3c2c4f6
AP
1126 bss_cfg->band_cfg = BAND_CONFIG_A;
1127
05910f4a
AK
1128 if (params->channel_type == NL80211_CHAN_NO_HT)
1129 config_bands = BAND_A;
1130 else
1131 config_bands = BAND_AN | BAND_A;
0abd79e5
AP
1132 }
1133
05910f4a
AK
1134 if (!((config_bands | priv->adapter->fw_bands) &
1135 ~priv->adapter->fw_bands))
1136 priv->adapter->config_bands = config_bands;
1137
a3c2c4f6 1138 mwifiex_set_uap_rates(bss_cfg, params);
05910f4a
AK
1139 mwifiex_send_domain_info_cmd_fw(wiphy);
1140
f752dcd5
AP
1141 if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
1142 kfree(bss_cfg);
1143 wiphy_err(wiphy, "Failed to parse secuirty parameters!\n");
1144 return -1;
1145 }
1146
22281256
AP
1147 mwifiex_set_ht_params(priv, bss_cfg, params);
1148
12190c5d
AP
1149 if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP,
1150 HostCmd_ACT_GEN_SET, 0, NULL)) {
1151 wiphy_err(wiphy, "Failed to stop the BSS\n");
1152 kfree(bss_cfg);
1153 return -1;
1154 }
1155
1156 if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG,
e76268da
AP
1157 HostCmd_ACT_GEN_SET,
1158 UAP_BSS_PARAMS_I, bss_cfg)) {
12190c5d
AP
1159 wiphy_err(wiphy, "Failed to set the SSID\n");
1160 kfree(bss_cfg);
1161 return -1;
1162 }
1163
1164 kfree(bss_cfg);
1165
1166 if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_BSS_START,
1167 HostCmd_ACT_GEN_SET, 0, NULL)) {
1168 wiphy_err(wiphy, "Failed to start the BSS\n");
1169 return -1;
1170 }
1171
96893538
AP
1172 if (priv->sec_info.wep_enabled)
1173 priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE;
1174 else
1175 priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
1176
1177 if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL,
1178 HostCmd_ACT_GEN_SET, 0,
1179 &priv->curr_pkt_filter))
1180 return -1;
1181
12190c5d
AP
1182 return 0;
1183}
1184
5e6e3a92
BZ
1185/*
1186 * CFG802.11 operation handler for disconnection request.
1187 *
1188 * This function does not work when there is already a disconnection
1189 * procedure going on.
1190 */
1191static int
1192mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
1193 u16 reason_code)
1194{
1195 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1196
600f5d90 1197 if (mwifiex_deauthenticate(priv, NULL))
5e6e3a92
BZ
1198 return -EFAULT;
1199
1200 wiphy_dbg(wiphy, "info: successfully disconnected from %pM:"
1201 " reason code %d\n", priv->cfg_bssid, reason_code);
1202
38c9d664 1203 memset(priv->cfg_bssid, 0, ETH_ALEN);
5e6e3a92
BZ
1204
1205 return 0;
1206}
1207
1208/*
1209 * This function informs the CFG802.11 subsystem of a new IBSS.
1210 *
1211 * The following information are sent to the CFG802.11 subsystem
1212 * to register the new IBSS. If we do not register the new IBSS,
1213 * a kernel panic will result.
1214 * - SSID
1215 * - SSID length
1216 * - BSSID
1217 * - Channel
1218 */
1219static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
1220{
5e6e3a92
BZ
1221 struct ieee80211_channel *chan;
1222 struct mwifiex_bss_info bss_info;
aa95a48d 1223 struct cfg80211_bss *bss;
270e58e8 1224 int ie_len;
5e6e3a92 1225 u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];
4ed5d521 1226 enum ieee80211_band band;
5e6e3a92 1227
636c4598
YAP
1228 if (mwifiex_get_bss_info(priv, &bss_info))
1229 return -1;
5e6e3a92
BZ
1230
1231 ie_buf[0] = WLAN_EID_SSID;
1232 ie_buf[1] = bss_info.ssid.ssid_len;
1233
1234 memcpy(&ie_buf[sizeof(struct ieee_types_header)],
aea0701e 1235 &bss_info.ssid.ssid, bss_info.ssid.ssid_len);
5e6e3a92
BZ
1236 ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
1237
4ed5d521 1238 band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
5e6e3a92
BZ
1239 chan = __ieee80211_get_channel(priv->wdev->wiphy,
1240 ieee80211_channel_to_frequency(bss_info.bss_chan,
4ed5d521 1241 band));
5e6e3a92 1242
aa95a48d 1243 bss = cfg80211_inform_bss(priv->wdev->wiphy, chan,
aea0701e
YAP
1244 bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
1245 0, ie_buf, ie_len, 0, GFP_KERNEL);
aa95a48d 1246 cfg80211_put_bss(bss);
5e6e3a92
BZ
1247 memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN);
1248
636c4598 1249 return 0;
5e6e3a92
BZ
1250}
1251
5e6e3a92
BZ
1252/*
1253 * This function connects with a BSS.
1254 *
1255 * This function handles both Infra and Ad-Hoc modes. It also performs
1256 * validity checking on the provided parameters, disconnects from the
1257 * current BSS (if any), sets up the association/scan parameters,
1258 * including security settings, and performs specific SSID scan before
1259 * trying to connect.
1260 *
1261 * For Infra mode, the function returns failure if the specified SSID
1262 * is not found in scan table. However, for Ad-Hoc mode, it can create
1263 * the IBSS if it does not exist. On successful completion in either case,
7c6fa2a8 1264 * the function notifies the CFG802.11 subsystem of the new BSS connection.
5e6e3a92
BZ
1265 */
1266static int
1267mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
1268 u8 *bssid, int mode, struct ieee80211_channel *channel,
1269 struct cfg80211_connect_params *sme, bool privacy)
1270{
b9be5f39 1271 struct cfg80211_ssid req_ssid;
270e58e8 1272 int ret, auth_type = 0;
7c6fa2a8 1273 struct cfg80211_bss *bss = NULL;
05910f4a 1274 u8 is_scanning_required = 0, config_bands = 0;
5e6e3a92 1275
b9be5f39 1276 memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
5e6e3a92
BZ
1277
1278 req_ssid.ssid_len = ssid_len;
1279 if (ssid_len > IEEE80211_MAX_SSID_LEN) {
1280 dev_err(priv->adapter->dev, "invalid SSID - aborting\n");
1281 return -EINVAL;
1282 }
1283
1284 memcpy(req_ssid.ssid, ssid, ssid_len);
1285 if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) {
1286 dev_err(priv->adapter->dev, "invalid SSID - aborting\n");
1287 return -EINVAL;
1288 }
1289
1290 /* disconnect before try to associate */
600f5d90 1291 mwifiex_deauthenticate(priv, NULL);
5e6e3a92 1292
05910f4a
AK
1293 if (channel) {
1294 if (mode == NL80211_IFTYPE_STATION) {
1295 if (channel->band == IEEE80211_BAND_2GHZ)
1296 config_bands = BAND_B | BAND_G | BAND_GN;
1297 else
1298 config_bands = BAND_A | BAND_AN;
1299
1300 if (!((config_bands | priv->adapter->fw_bands) &
1301 ~priv->adapter->fw_bands))
1302 priv->adapter->config_bands = config_bands;
1303 }
05910f4a 1304 }
5e6e3a92 1305
6670f15b
AK
1306 /* As this is new association, clear locally stored
1307 * keys and security related flags */
1308 priv->sec_info.wpa_enabled = false;
1309 priv->sec_info.wpa2_enabled = false;
1310 priv->wep_key_curr_index = 0;
00f157b4 1311 priv->sec_info.encryption_mode = 0;
a0f6d6ca 1312 priv->sec_info.is_authtype_auto = 0;
53b11231 1313 ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
5e6e3a92 1314
eecd8250 1315 if (mode == NL80211_IFTYPE_ADHOC) {
5e6e3a92
BZ
1316 /* "privacy" is set only for ad-hoc mode */
1317 if (privacy) {
1318 /*
2be50b8d 1319 * Keep WLAN_CIPHER_SUITE_WEP104 for now so that
5e6e3a92
BZ
1320 * the firmware can find a matching network from the
1321 * scan. The cfg80211 does not give us the encryption
1322 * mode at this stage so just setting it to WEP here.
1323 */
203afeca 1324 priv->sec_info.encryption_mode =
2be50b8d 1325 WLAN_CIPHER_SUITE_WEP104;
203afeca 1326 priv->sec_info.authentication_mode =
f986b6d5 1327 NL80211_AUTHTYPE_OPEN_SYSTEM;
5e6e3a92
BZ
1328 }
1329
1330 goto done;
1331 }
1332
1333 /* Now handle infra mode. "sme" is valid for infra mode only */
a0f6d6ca 1334 if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
f986b6d5 1335 auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
a0f6d6ca
AK
1336 priv->sec_info.is_authtype_auto = 1;
1337 } else {
1338 auth_type = sme->auth_type;
1339 }
5e6e3a92
BZ
1340
1341 if (sme->crypto.n_ciphers_pairwise) {
2be50b8d
YAP
1342 priv->sec_info.encryption_mode =
1343 sme->crypto.ciphers_pairwise[0];
203afeca 1344 priv->sec_info.authentication_mode = auth_type;
5e6e3a92
BZ
1345 }
1346
1347 if (sme->crypto.cipher_group) {
2be50b8d 1348 priv->sec_info.encryption_mode = sme->crypto.cipher_group;
203afeca 1349 priv->sec_info.authentication_mode = auth_type;
5e6e3a92
BZ
1350 }
1351 if (sme->ie)
1352 ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len);
1353
1354 if (sme->key) {
e6faada5 1355 if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) {
5e6e3a92
BZ
1356 dev_dbg(priv->adapter->dev,
1357 "info: setting wep encryption"
1358 " with key len %d\n", sme->key_len);
6670f15b 1359 priv->wep_key_curr_index = sme->key_idx;
53b11231
YL
1360 ret = mwifiex_set_encode(priv, NULL, sme->key,
1361 sme->key_len, sme->key_idx,
1362 NULL, 0);
5e6e3a92
BZ
1363 }
1364 }
1365done:
7c6fa2a8
AK
1366 /*
1367 * Scan entries are valid for some time (15 sec). So we can save one
1368 * active scan time if we just try cfg80211_get_bss first. If it fails
1369 * then request scan and cfg80211_get_bss() again for final output.
1370 */
1371 while (1) {
1372 if (is_scanning_required) {
1373 /* Do specific SSID scanning */
1374 if (mwifiex_request_scan(priv, &req_ssid)) {
1375 dev_err(priv->adapter->dev, "scan error\n");
1376 return -EFAULT;
1377 }
1378 }
5e6e3a92 1379
7c6fa2a8
AK
1380 /* Find the BSS we want using available scan results */
1381 if (mode == NL80211_IFTYPE_ADHOC)
1382 bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
1383 bssid, ssid, ssid_len,
1384 WLAN_CAPABILITY_IBSS,
1385 WLAN_CAPABILITY_IBSS);
1386 else
1387 bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
1388 bssid, ssid, ssid_len,
1389 WLAN_CAPABILITY_ESS,
1390 WLAN_CAPABILITY_ESS);
1391
1392 if (!bss) {
1393 if (is_scanning_required) {
aea0701e
YAP
1394 dev_warn(priv->adapter->dev,
1395 "assoc: requested bss not found in scan results\n");
7c6fa2a8
AK
1396 break;
1397 }
1398 is_scanning_required = 1;
1399 } else {
aea0701e
YAP
1400 dev_dbg(priv->adapter->dev,
1401 "info: trying to associate to '%s' bssid %pM\n",
1402 (char *) req_ssid.ssid, bss->bssid);
7c6fa2a8
AK
1403 memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
1404 break;
1405 }
5e6e3a92
BZ
1406 }
1407
7c6fa2a8 1408 if (mwifiex_bss_start(priv, bss, &req_ssid))
5e6e3a92
BZ
1409 return -EFAULT;
1410
eecd8250 1411 if (mode == NL80211_IFTYPE_ADHOC) {
5e6e3a92
BZ
1412 /* Inform the BSS information to kernel, otherwise
1413 * kernel will give a panic after successful assoc */
1414 if (mwifiex_cfg80211_inform_ibss_bss(priv))
1415 return -EFAULT;
1416 }
1417
1418 return ret;
1419}
1420
1421/*
1422 * CFG802.11 operation handler for association request.
1423 *
1424 * This function does not work when the current mode is set to Ad-Hoc, or
1425 * when there is already an association procedure going on. The given BSS
1426 * information is used to associate.
1427 */
1428static int
1429mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
1430 struct cfg80211_connect_params *sme)
1431{
1432 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
1433 int ret = 0;
5e6e3a92 1434
eecd8250 1435 if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
5e6e3a92
BZ
1436 wiphy_err(wiphy, "received infra assoc request "
1437 "when station is in ibss mode\n");
1438 goto done;
1439 }
1440
e568634a
AP
1441 if (priv->bss_mode == NL80211_IFTYPE_AP) {
1442 wiphy_err(wiphy, "skip association request for AP interface\n");
1443 goto done;
1444 }
1445
5e6e3a92 1446 wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
aea0701e 1447 (char *) sme->ssid, sme->bssid);
5e6e3a92
BZ
1448
1449 ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid,
eecd8250 1450 priv->bss_mode, sme->channel, sme, 0);
5e6e3a92 1451done:
38c9d664
AK
1452 if (!ret) {
1453 cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0,
1454 NULL, 0, WLAN_STATUS_SUCCESS,
1455 GFP_KERNEL);
1456 dev_dbg(priv->adapter->dev,
1457 "info: associated to bssid %pM successfully\n",
1458 priv->cfg_bssid);
1459 } else {
1460 dev_dbg(priv->adapter->dev,
1461 "info: association to bssid %pM failed\n",
1462 priv->cfg_bssid);
1463 memset(priv->cfg_bssid, 0, ETH_ALEN);
1464 }
1465
5e6e3a92
BZ
1466 return ret;
1467}
1468
05910f4a
AK
1469/*
1470 * This function sets following parameters for ibss network.
1471 * - channel
1472 * - start band
1473 * - 11n flag
1474 * - secondary channel offset
1475 */
1476static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
1477 struct cfg80211_ibss_params *params)
1478{
1479 struct wiphy *wiphy = priv->wdev->wiphy;
1480 struct mwifiex_adapter *adapter = priv->adapter;
1481 int index = 0, i;
1482 u8 config_bands = 0;
1483
1484 if (params->channel->band == IEEE80211_BAND_2GHZ) {
1485 if (!params->basic_rates) {
1486 config_bands = BAND_B | BAND_G;
1487 } else {
1488 for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
1489 /*
1490 * Rates below 6 Mbps in the table are CCK
1491 * rates; 802.11b and from 6 they are OFDM;
1492 * 802.11G
1493 */
1494 if (mwifiex_rates[i].bitrate == 60) {
1495 index = 1 << i;
1496 break;
1497 }
1498 }
1499
1500 if (params->basic_rates < index) {
1501 config_bands = BAND_B;
1502 } else {
1503 config_bands = BAND_G;
1504 if (params->basic_rates % index)
1505 config_bands |= BAND_B;
1506 }
1507 }
1508
1509 if (params->channel_type != NL80211_CHAN_NO_HT)
1510 config_bands |= BAND_GN;
1511 } else {
1512 if (params->channel_type == NL80211_CHAN_NO_HT)
1513 config_bands = BAND_A;
1514 else
1515 config_bands = BAND_AN | BAND_A;
1516 }
1517
1518 if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) {
1519 adapter->config_bands = config_bands;
1520 adapter->adhoc_start_band = config_bands;
1521
1522 if ((config_bands & BAND_GN) || (config_bands & BAND_AN))
1523 adapter->adhoc_11n_enabled = true;
1524 else
1525 adapter->adhoc_11n_enabled = false;
1526 }
1527
1528 adapter->sec_chan_offset =
1529 mwifiex_chan_type_to_sec_chan_offset(params->channel_type);
1530 priv->adhoc_channel =
1531 ieee80211_frequency_to_channel(params->channel->center_freq);
1532
1533 wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n",
1534 config_bands, priv->adhoc_channel, adapter->sec_chan_offset);
1535
1536 return 0;
1537}
1538
5e6e3a92
BZ
1539/*
1540 * CFG802.11 operation handler to join an IBSS.
1541 *
1542 * This function does not work in any mode other than Ad-Hoc, or if
1543 * a join operation is already in progress.
1544 */
1545static int
1546mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
1547 struct cfg80211_ibss_params *params)
1548{
f540f9f3 1549 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
5e6e3a92 1550 int ret = 0;
5e6e3a92 1551
eecd8250 1552 if (priv->bss_mode != NL80211_IFTYPE_ADHOC) {
5e6e3a92
BZ
1553 wiphy_err(wiphy, "request to join ibss received "
1554 "when station is not in ibss mode\n");
1555 goto done;
1556 }
1557
5e6e3a92 1558 wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n",
aea0701e 1559 (char *) params->ssid, params->bssid);
5e6e3a92 1560
05910f4a
AK
1561 mwifiex_set_ibss_params(priv, params);
1562
5e6e3a92 1563 ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
aea0701e
YAP
1564 params->bssid, priv->bss_mode,
1565 params->channel, NULL, params->privacy);
5e6e3a92 1566done:
38c9d664
AK
1567 if (!ret) {
1568 cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
1569 dev_dbg(priv->adapter->dev,
1570 "info: joined/created adhoc network with bssid"
1571 " %pM successfully\n", priv->cfg_bssid);
1572 } else {
1573 dev_dbg(priv->adapter->dev,
1574 "info: failed creating/joining adhoc network\n");
1575 }
1576
5e6e3a92
BZ
1577 return ret;
1578}
1579
1580/*
1581 * CFG802.11 operation handler to leave an IBSS.
1582 *
1583 * This function does not work if a leave operation is
1584 * already in progress.
1585 */
1586static int
1587mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1588{
f540f9f3 1589 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
5e6e3a92 1590
5e6e3a92 1591 wiphy_dbg(wiphy, "info: disconnecting from essid %pM\n",
aea0701e 1592 priv->cfg_bssid);
600f5d90 1593 if (mwifiex_deauthenticate(priv, NULL))
5e6e3a92
BZ
1594 return -EFAULT;
1595
38c9d664 1596 memset(priv->cfg_bssid, 0, ETH_ALEN);
5e6e3a92
BZ
1597
1598 return 0;
1599}
1600
1601/*
1602 * CFG802.11 operation handler for scan request.
1603 *
1604 * This function issues a scan request to the firmware based upon
1605 * the user specified scan configuration. On successfull completion,
1606 * it also informs the results.
1607 */
1608static int
fd014284 1609mwifiex_cfg80211_scan(struct wiphy *wiphy,
5e6e3a92
BZ
1610 struct cfg80211_scan_request *request)
1611{
fd014284 1612 struct net_device *dev = request->wdev->netdev;
5e6e3a92 1613 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
38c9d664
AK
1614 int i;
1615 struct ieee80211_channel *chan;
5e6e3a92
BZ
1616
1617 wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
1618
de09364e
AK
1619 if (atomic_read(&priv->wmm.tx_pkts_queued) >=
1620 MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) {
1621 dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n");
1622 return -EBUSY;
1623 }
1624
5e6e3a92
BZ
1625 priv->scan_request = request;
1626
38c9d664 1627 priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
aea0701e 1628 GFP_KERNEL);
38c9d664
AK
1629 if (!priv->user_scan_cfg) {
1630 dev_err(priv->adapter->dev, "failed to alloc scan_req\n");
1631 return -ENOMEM;
1632 }
be0b281e
AK
1633
1634 priv->user_scan_cfg->num_ssids = request->n_ssids;
1635 priv->user_scan_cfg->ssid_list = request->ssids;
1636
13d7ba78
AP
1637 if (request->ie && request->ie_len) {
1638 for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
1639 if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR)
1640 continue;
1641 priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN;
1642 memcpy(&priv->vs_ie[i].ie, request->ie,
1643 request->ie_len);
1644 break;
1645 }
1646 }
1647
38c9d664
AK
1648 for (i = 0; i < request->n_channels; i++) {
1649 chan = request->channels[i];
1650 priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
1651 priv->user_scan_cfg->chan_list[i].radio_type = chan->band;
1652
1653 if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
1654 priv->user_scan_cfg->chan_list[i].scan_type =
aea0701e 1655 MWIFIEX_SCAN_TYPE_PASSIVE;
38c9d664
AK
1656 else
1657 priv->user_scan_cfg->chan_list[i].scan_type =
aea0701e 1658 MWIFIEX_SCAN_TYPE_ACTIVE;
38c9d664
AK
1659
1660 priv->user_scan_cfg->chan_list[i].scan_time = 0;
1661 }
1a1fb970 1662 if (mwifiex_scan_networks(priv, priv->user_scan_cfg))
38c9d664
AK
1663 return -EFAULT;
1664
13d7ba78
AP
1665 if (request->ie && request->ie_len) {
1666 for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) {
1667 if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) {
1668 priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR;
1669 memset(&priv->vs_ie[i].ie, 0,
1670 MWIFIEX_MAX_VSIE_LEN);
1671 }
1672 }
1673 }
5e6e3a92
BZ
1674 return 0;
1675}
1676
1677/*
1678 * This function sets up the CFG802.11 specific HT capability fields
1679 * with default values.
1680 *
1681 * The following default values are set -
1682 * - HT Supported = True
a46b7b5c
AK
1683 * - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K
1684 * - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE
1685 * - HT Capabilities supported by firmware
5e6e3a92
BZ
1686 * - MCS information, Rx mask = 0xff
1687 * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01)
1688 */
1689static void
1690mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
1691 struct mwifiex_private *priv)
1692{
1693 int rx_mcs_supp;
1694 struct ieee80211_mcs_info mcs_set;
1695 u8 *mcs = (u8 *)&mcs_set;
1696 struct mwifiex_adapter *adapter = priv->adapter;
1697
1698 ht_info->ht_supported = true;
a46b7b5c
AK
1699 ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
1700 ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
5e6e3a92
BZ
1701
1702 memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
5e6e3a92 1703
a46b7b5c
AK
1704 /* Fill HT capability information */
1705 if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
1706 ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
1707 else
1708 ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
1709
1710 if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap))
1711 ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
1712 else
1713 ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20;
1714
1715 if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap))
1716 ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
1717 else
1718 ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40;
1719
1720 if (ISSUPP_RXSTBC(adapter->hw_dot_11n_dev_cap))
1721 ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT;
1722 else
1723 ht_info->cap &= ~(3 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
1724
1725 if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap))
1726 ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
1727 else
1728 ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC;
1729
1730 ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU;
1731 ht_info->cap |= IEEE80211_HT_CAP_SM_PS;
1732
1733 rx_mcs_supp = GET_RXMCSSUPP(adapter->hw_dev_mcs_support);
5e6e3a92
BZ
1734 /* Set MCS for 1x1 */
1735 memset(mcs, 0xff, rx_mcs_supp);
1736 /* Clear all the other values */
1737 memset(&mcs[rx_mcs_supp], 0,
aea0701e 1738 sizeof(struct ieee80211_mcs_info) - rx_mcs_supp);
eecd8250 1739 if (priv->bss_mode == NL80211_IFTYPE_STATION ||
aea0701e 1740 ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap))
5e6e3a92
BZ
1741 /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */
1742 SETHT_MCS32(mcs_set.rx_mask);
1743
1744 memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info));
1745
1746 ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
1747}
1748
93a1df48
YAP
1749/*
1750 * create a new virtual interface with the given name
1751 */
84efbb84 1752struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
552bff0c 1753 const char *name,
84efbb84
JB
1754 enum nl80211_iftype type,
1755 u32 *flags,
1756 struct vif_params *params)
93a1df48 1757{
67fdf39e
AP
1758 struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
1759 struct mwifiex_private *priv;
93a1df48
YAP
1760 struct net_device *dev;
1761 void *mdev_priv;
d6bffe8b 1762 struct wireless_dev *wdev;
93a1df48 1763
93a1df48 1764 if (!adapter)
858faa57 1765 return ERR_PTR(-EFAULT);
93a1df48
YAP
1766
1767 switch (type) {
1768 case NL80211_IFTYPE_UNSPECIFIED:
1769 case NL80211_IFTYPE_STATION:
1770 case NL80211_IFTYPE_ADHOC:
d6bffe8b 1771 priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
93a1df48 1772 if (priv->bss_mode) {
d6bffe8b
AP
1773 wiphy_err(wiphy,
1774 "cannot create multiple sta/adhoc ifaces\n");
858faa57 1775 return ERR_PTR(-EINVAL);
93a1df48
YAP
1776 }
1777
d6bffe8b
AP
1778 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
1779 if (!wdev)
858faa57 1780 return ERR_PTR(-ENOMEM);
d6bffe8b
AP
1781
1782 wdev->wiphy = wiphy;
1783 priv->wdev = wdev;
1784 wdev->iftype = NL80211_IFTYPE_STATION;
1785
93a1df48
YAP
1786 if (type == NL80211_IFTYPE_UNSPECIFIED)
1787 priv->bss_mode = NL80211_IFTYPE_STATION;
1788 else
1789 priv->bss_mode = type;
1790
1791 priv->bss_type = MWIFIEX_BSS_TYPE_STA;
1792 priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
a458c0ae 1793 priv->bss_priority = 0;
93a1df48 1794 priv->bss_role = MWIFIEX_BSS_ROLE_STA;
93a1df48
YAP
1795 priv->bss_num = 0;
1796
d6bffe8b
AP
1797 break;
1798 case NL80211_IFTYPE_AP:
1799 priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP];
1800
1801 if (priv->bss_mode) {
1802 wiphy_err(wiphy, "Can't create multiple AP interfaces");
858faa57 1803 return ERR_PTR(-EINVAL);
d6bffe8b
AP
1804 }
1805
1806 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
1807 if (!wdev)
858faa57 1808 return ERR_PTR(-ENOMEM);
d6bffe8b
AP
1809
1810 priv->wdev = wdev;
1811 wdev->wiphy = wiphy;
1812 wdev->iftype = NL80211_IFTYPE_AP;
1813
1814 priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
1815 priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
a458c0ae 1816 priv->bss_priority = 0;
d6bffe8b
AP
1817 priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
1818 priv->bss_started = 0;
1819 priv->bss_num = 0;
1820 priv->bss_mode = type;
1821
93a1df48
YAP
1822 break;
1823 default:
1824 wiphy_err(wiphy, "type not supported\n");
858faa57 1825 return ERR_PTR(-EINVAL);
93a1df48
YAP
1826 }
1827
1828 dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name,
1829 ether_setup, 1);
1830 if (!dev) {
1831 wiphy_err(wiphy, "no memory available for netdevice\n");
858faa57
BZ
1832 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
1833 return ERR_PTR(-ENOMEM);
93a1df48
YAP
1834 }
1835
d6bffe8b
AP
1836 mwifiex_init_priv_params(priv, dev);
1837 priv->netdev = dev;
1838
1839 mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv);
1840
1841 if (adapter->config_bands & BAND_A)
1842 mwifiex_setup_ht_caps(
1843 &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv);
1844
93a1df48
YAP
1845 dev_net_set(dev, wiphy_net(wiphy));
1846 dev->ieee80211_ptr = priv->wdev;
1847 dev->ieee80211_ptr->iftype = priv->bss_mode;
1848 memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN);
1849 memcpy(dev->perm_addr, wiphy->perm_addr, ETH_ALEN);
1850 SET_NETDEV_DEV(dev, wiphy_dev(wiphy));
1851
1852 dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
1853 dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT;
1854 dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN;
1855
1856 mdev_priv = netdev_priv(dev);
1857 *((unsigned long *) mdev_priv) = (unsigned long) priv;
1858
93a1df48
YAP
1859 SET_NETDEV_DEV(dev, adapter->dev);
1860
1861 /* Register network device */
1862 if (register_netdevice(dev)) {
1863 wiphy_err(wiphy, "cannot register virtual network device\n");
858faa57
BZ
1864 free_netdev(dev);
1865 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
1866 return ERR_PTR(-EFAULT);
93a1df48
YAP
1867 }
1868
1869 sema_init(&priv->async_sem, 1);
1870 priv->scan_pending_on_block = false;
1871
1872 dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
1873
1874#ifdef CONFIG_DEBUG_FS
1875 mwifiex_dev_debugfs_init(priv);
1876#endif
84efbb84 1877 return wdev;
93a1df48
YAP
1878}
1879EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
1880
1881/*
1882 * del_virtual_intf: remove the virtual interface determined by dev
1883 */
84efbb84 1884int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
93a1df48 1885{
84efbb84 1886 struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
93a1df48
YAP
1887
1888#ifdef CONFIG_DEBUG_FS
1889 mwifiex_dev_debugfs_remove(priv);
1890#endif
1891
1892 if (!netif_queue_stopped(priv->netdev))
1893 netif_stop_queue(priv->netdev);
1894
1895 if (netif_carrier_ok(priv->netdev))
1896 netif_carrier_off(priv->netdev);
1897
84efbb84
JB
1898 if (wdev->netdev->reg_state == NETREG_REGISTERED)
1899 unregister_netdevice(wdev->netdev);
93a1df48 1900
84efbb84
JB
1901 if (wdev->netdev->reg_state == NETREG_UNREGISTERED)
1902 free_netdev(wdev->netdev);
93a1df48
YAP
1903
1904 /* Clear the priv in adapter */
1905 priv->netdev = NULL;
1906
1907 priv->media_connected = false;
1908
93a1df48
YAP
1909 priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
1910
1911 return 0;
1912}
1913EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf);
1914
5e6e3a92
BZ
1915/* station cfg80211 operations */
1916static struct cfg80211_ops mwifiex_cfg80211_ops = {
93a1df48
YAP
1917 .add_virtual_intf = mwifiex_add_virtual_intf,
1918 .del_virtual_intf = mwifiex_del_virtual_intf,
5e6e3a92
BZ
1919 .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf,
1920 .scan = mwifiex_cfg80211_scan,
1921 .connect = mwifiex_cfg80211_connect,
1922 .disconnect = mwifiex_cfg80211_disconnect,
1923 .get_station = mwifiex_cfg80211_get_station,
f85aae6b 1924 .dump_station = mwifiex_cfg80211_dump_station,
5e6e3a92 1925 .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,
5e6e3a92
BZ
1926 .join_ibss = mwifiex_cfg80211_join_ibss,
1927 .leave_ibss = mwifiex_cfg80211_leave_ibss,
1928 .add_key = mwifiex_cfg80211_add_key,
1929 .del_key = mwifiex_cfg80211_del_key,
e39faa73 1930 .mgmt_tx = mwifiex_cfg80211_mgmt_tx,
5e6e3a92
BZ
1931 .set_default_key = mwifiex_cfg80211_set_default_key,
1932 .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt,
1933 .set_tx_power = mwifiex_cfg80211_set_tx_power,
5d82c53a 1934 .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask,
12190c5d
AP
1935 .start_ap = mwifiex_cfg80211_start_ap,
1936 .stop_ap = mwifiex_cfg80211_stop_ap,
5370c836 1937 .change_beacon = mwifiex_cfg80211_change_beacon,
fa444bf8 1938 .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config,
8a279d5b 1939 .set_antenna = mwifiex_cfg80211_set_antenna,
5e6e3a92
BZ
1940};
1941
1942/*
1943 * This function registers the device with CFG802.11 subsystem.
1944 *
1945 * The function creates the wireless device/wiphy, populates it with
1946 * default parameters and handler function pointers, and finally
1947 * registers the device.
1948 */
d6bffe8b
AP
1949
1950int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
5e6e3a92 1951{
270e58e8
YAP
1952 int ret;
1953 void *wdev_priv;
d6bffe8b
AP
1954 struct wiphy *wiphy;
1955 struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA];
9e04a7c6 1956 u8 *country_code;
5e6e3a92 1957
d6bffe8b
AP
1958 /* create a new wiphy for use with cfg80211 */
1959 wiphy = wiphy_new(&mwifiex_cfg80211_ops,
1960 sizeof(struct mwifiex_adapter *));
1961 if (!wiphy) {
1962 dev_err(adapter->dev, "%s: creating new wiphy\n", __func__);
5e6e3a92
BZ
1963 return -ENOMEM;
1964 }
d6bffe8b
AP
1965 wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH;
1966 wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN;
83719be8 1967 wiphy->mgmt_stypes = mwifiex_mgmt_stypes;
d6bffe8b
AP
1968 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1969 BIT(NL80211_IFTYPE_ADHOC) |
1970 BIT(NL80211_IFTYPE_AP);
1971
1972 wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz;
1973 if (adapter->config_bands & BAND_A)
1974 wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz;
1975 else
1976 wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
5e6e3a92 1977
cd8440da
AP
1978 wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;
1979 wiphy->n_iface_combinations = 1;
1980
5e6e3a92 1981 /* Initialize cipher suits */
d6bffe8b
AP
1982 wiphy->cipher_suites = mwifiex_cipher_suites;
1983 wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
5e6e3a92 1984
d6bffe8b
AP
1985 memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN);
1986 wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2dd2bd6b 1987 wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
cc0ba0d5
AK
1988 WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
1989 WIPHY_FLAG_CUSTOM_REGULATORY;
1990
1991 wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
2dd2bd6b
AP
1992
1993 wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
e39faa73
SP
1994 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
1995 NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
5e6e3a92 1996
8a279d5b
AK
1997 wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
1998 wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
5e6e3a92 1999
05910f4a
AK
2000 wiphy->features = NL80211_FEATURE_HT_IBSS;
2001
b5abcf02 2002 /* Reserve space for mwifiex specific private data for BSS */
d6bffe8b 2003 wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
5116f3ce 2004
d6bffe8b 2005 wiphy->reg_notifier = mwifiex_reg_notifier;
5e6e3a92 2006
67fdf39e 2007 /* Set struct mwifiex_adapter pointer in wiphy_priv */
d6bffe8b 2008 wdev_priv = wiphy_priv(wiphy);
67fdf39e 2009 *(unsigned long *)wdev_priv = (unsigned long)adapter;
5e6e3a92 2010
2c208890 2011 set_wiphy_dev(wiphy, priv->adapter->dev);
a7b21165 2012
d6bffe8b 2013 ret = wiphy_register(wiphy);
5e6e3a92 2014 if (ret < 0) {
d6bffe8b
AP
2015 dev_err(adapter->dev,
2016 "%s: wiphy_register failed: %d\n", __func__, ret);
2017 wiphy_free(wiphy);
5e6e3a92 2018 return ret;
5e6e3a92 2019 }
9e04a7c6 2020 country_code = mwifiex_11d_code_2_region(priv->adapter->region_code);
77c8a14b
BZ
2021 if (country_code)
2022 dev_info(adapter->dev,
2023 "ignoring F/W country code %2.2s\n", country_code);
5e6e3a92 2024
d6bffe8b 2025 adapter->wiphy = wiphy;
5e6e3a92
BZ
2026 return ret;
2027}
This page took 0.338585 seconds and 5 git commands to generate.