[go: nahoru, domu]

wl_cfg80211.c revision fd0142844efa85d89017c89227a0f03de1eee327
1/*
2 * Copyright (c) 2010 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
18
19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
20
21#include <linux/kernel.h>
22#include <linux/if_arp.h>
23#include <linux/sched.h>
24#include <linux/kthread.h>
25#include <linux/netdevice.h>
26#include <linux/bitops.h>
27#include <linux/etherdevice.h>
28#include <linux/ieee80211.h>
29#include <linux/uaccess.h>
30#include <net/cfg80211.h>
31
32#include <brcmu_utils.h>
33#include <defs.h>
34#include <brcmu_wifi.h>
35#include "dhd.h"
36#include "wl_cfg80211.h"
37
38#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
39	(sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
40
41static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
42
43static u32 brcmf_dbg_level = WL_DBG_ERR;
44
45static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data)
46{
47	dev->driver_data = data;
48}
49
50static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev)
51{
52	void *data = NULL;
53
54	if (dev)
55		data = dev->driver_data;
56	return data;
57}
58
59static
60struct brcmf_cfg80211_priv *brcmf_priv_get(struct brcmf_cfg80211_dev *cfg_dev)
61{
62	struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg_dev);
63	return ci->cfg_priv;
64}
65
66static bool check_sys_up(struct wiphy *wiphy)
67{
68	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
69	if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
70		WL_INFO("device is not ready : status (%d)\n",
71			(int)cfg_priv->status);
72		return false;
73	}
74	return true;
75}
76
77#define CHAN2G(_channel, _freq, _flags) {			\
78	.band			= IEEE80211_BAND_2GHZ,		\
79	.center_freq		= (_freq),			\
80	.hw_value		= (_channel),			\
81	.flags			= (_flags),			\
82	.max_antenna_gain	= 0,				\
83	.max_power		= 30,				\
84}
85
86#define CHAN5G(_channel, _flags) {				\
87	.band			= IEEE80211_BAND_5GHZ,		\
88	.center_freq		= 5000 + (5 * (_channel)),	\
89	.hw_value		= (_channel),			\
90	.flags			= (_flags),			\
91	.max_antenna_gain	= 0,				\
92	.max_power		= 30,				\
93}
94
95#define RATE_TO_BASE100KBPS(rate)   (((rate) * 10) / 2)
96#define RATETAB_ENT(_rateid, _flags) \
97	{                                                               \
98		.bitrate        = RATE_TO_BASE100KBPS(_rateid),     \
99		.hw_value       = (_rateid),                            \
100		.flags          = (_flags),                             \
101	}
102
103static struct ieee80211_rate __wl_rates[] = {
104	RATETAB_ENT(BRCM_RATE_1M, 0),
105	RATETAB_ENT(BRCM_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
106	RATETAB_ENT(BRCM_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
107	RATETAB_ENT(BRCM_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
108	RATETAB_ENT(BRCM_RATE_6M, 0),
109	RATETAB_ENT(BRCM_RATE_9M, 0),
110	RATETAB_ENT(BRCM_RATE_12M, 0),
111	RATETAB_ENT(BRCM_RATE_18M, 0),
112	RATETAB_ENT(BRCM_RATE_24M, 0),
113	RATETAB_ENT(BRCM_RATE_36M, 0),
114	RATETAB_ENT(BRCM_RATE_48M, 0),
115	RATETAB_ENT(BRCM_RATE_54M, 0),
116};
117
118#define wl_a_rates		(__wl_rates + 4)
119#define wl_a_rates_size	8
120#define wl_g_rates		(__wl_rates + 0)
121#define wl_g_rates_size	12
122
123static struct ieee80211_channel __wl_2ghz_channels[] = {
124	CHAN2G(1, 2412, 0),
125	CHAN2G(2, 2417, 0),
126	CHAN2G(3, 2422, 0),
127	CHAN2G(4, 2427, 0),
128	CHAN2G(5, 2432, 0),
129	CHAN2G(6, 2437, 0),
130	CHAN2G(7, 2442, 0),
131	CHAN2G(8, 2447, 0),
132	CHAN2G(9, 2452, 0),
133	CHAN2G(10, 2457, 0),
134	CHAN2G(11, 2462, 0),
135	CHAN2G(12, 2467, 0),
136	CHAN2G(13, 2472, 0),
137	CHAN2G(14, 2484, 0),
138};
139
140static struct ieee80211_channel __wl_5ghz_a_channels[] = {
141	CHAN5G(34, 0), CHAN5G(36, 0),
142	CHAN5G(38, 0), CHAN5G(40, 0),
143	CHAN5G(42, 0), CHAN5G(44, 0),
144	CHAN5G(46, 0), CHAN5G(48, 0),
145	CHAN5G(52, 0), CHAN5G(56, 0),
146	CHAN5G(60, 0), CHAN5G(64, 0),
147	CHAN5G(100, 0), CHAN5G(104, 0),
148	CHAN5G(108, 0), CHAN5G(112, 0),
149	CHAN5G(116, 0), CHAN5G(120, 0),
150	CHAN5G(124, 0), CHAN5G(128, 0),
151	CHAN5G(132, 0), CHAN5G(136, 0),
152	CHAN5G(140, 0), CHAN5G(149, 0),
153	CHAN5G(153, 0), CHAN5G(157, 0),
154	CHAN5G(161, 0), CHAN5G(165, 0),
155	CHAN5G(184, 0), CHAN5G(188, 0),
156	CHAN5G(192, 0), CHAN5G(196, 0),
157	CHAN5G(200, 0), CHAN5G(204, 0),
158	CHAN5G(208, 0), CHAN5G(212, 0),
159	CHAN5G(216, 0),
160};
161
162static struct ieee80211_channel __wl_5ghz_n_channels[] = {
163	CHAN5G(32, 0), CHAN5G(34, 0),
164	CHAN5G(36, 0), CHAN5G(38, 0),
165	CHAN5G(40, 0), CHAN5G(42, 0),
166	CHAN5G(44, 0), CHAN5G(46, 0),
167	CHAN5G(48, 0), CHAN5G(50, 0),
168	CHAN5G(52, 0), CHAN5G(54, 0),
169	CHAN5G(56, 0), CHAN5G(58, 0),
170	CHAN5G(60, 0), CHAN5G(62, 0),
171	CHAN5G(64, 0), CHAN5G(66, 0),
172	CHAN5G(68, 0), CHAN5G(70, 0),
173	CHAN5G(72, 0), CHAN5G(74, 0),
174	CHAN5G(76, 0), CHAN5G(78, 0),
175	CHAN5G(80, 0), CHAN5G(82, 0),
176	CHAN5G(84, 0), CHAN5G(86, 0),
177	CHAN5G(88, 0), CHAN5G(90, 0),
178	CHAN5G(92, 0), CHAN5G(94, 0),
179	CHAN5G(96, 0), CHAN5G(98, 0),
180	CHAN5G(100, 0), CHAN5G(102, 0),
181	CHAN5G(104, 0), CHAN5G(106, 0),
182	CHAN5G(108, 0), CHAN5G(110, 0),
183	CHAN5G(112, 0), CHAN5G(114, 0),
184	CHAN5G(116, 0), CHAN5G(118, 0),
185	CHAN5G(120, 0), CHAN5G(122, 0),
186	CHAN5G(124, 0), CHAN5G(126, 0),
187	CHAN5G(128, 0), CHAN5G(130, 0),
188	CHAN5G(132, 0), CHAN5G(134, 0),
189	CHAN5G(136, 0), CHAN5G(138, 0),
190	CHAN5G(140, 0), CHAN5G(142, 0),
191	CHAN5G(144, 0), CHAN5G(145, 0),
192	CHAN5G(146, 0), CHAN5G(147, 0),
193	CHAN5G(148, 0), CHAN5G(149, 0),
194	CHAN5G(150, 0), CHAN5G(151, 0),
195	CHAN5G(152, 0), CHAN5G(153, 0),
196	CHAN5G(154, 0), CHAN5G(155, 0),
197	CHAN5G(156, 0), CHAN5G(157, 0),
198	CHAN5G(158, 0), CHAN5G(159, 0),
199	CHAN5G(160, 0), CHAN5G(161, 0),
200	CHAN5G(162, 0), CHAN5G(163, 0),
201	CHAN5G(164, 0), CHAN5G(165, 0),
202	CHAN5G(166, 0), CHAN5G(168, 0),
203	CHAN5G(170, 0), CHAN5G(172, 0),
204	CHAN5G(174, 0), CHAN5G(176, 0),
205	CHAN5G(178, 0), CHAN5G(180, 0),
206	CHAN5G(182, 0), CHAN5G(184, 0),
207	CHAN5G(186, 0), CHAN5G(188, 0),
208	CHAN5G(190, 0), CHAN5G(192, 0),
209	CHAN5G(194, 0), CHAN5G(196, 0),
210	CHAN5G(198, 0), CHAN5G(200, 0),
211	CHAN5G(202, 0), CHAN5G(204, 0),
212	CHAN5G(206, 0), CHAN5G(208, 0),
213	CHAN5G(210, 0), CHAN5G(212, 0),
214	CHAN5G(214, 0), CHAN5G(216, 0),
215	CHAN5G(218, 0), CHAN5G(220, 0),
216	CHAN5G(222, 0), CHAN5G(224, 0),
217	CHAN5G(226, 0), CHAN5G(228, 0),
218};
219
220static struct ieee80211_supported_band __wl_band_2ghz = {
221	.band = IEEE80211_BAND_2GHZ,
222	.channels = __wl_2ghz_channels,
223	.n_channels = ARRAY_SIZE(__wl_2ghz_channels),
224	.bitrates = wl_g_rates,
225	.n_bitrates = wl_g_rates_size,
226};
227
228static struct ieee80211_supported_band __wl_band_5ghz_a = {
229	.band = IEEE80211_BAND_5GHZ,
230	.channels = __wl_5ghz_a_channels,
231	.n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
232	.bitrates = wl_a_rates,
233	.n_bitrates = wl_a_rates_size,
234};
235
236static struct ieee80211_supported_band __wl_band_5ghz_n = {
237	.band = IEEE80211_BAND_5GHZ,
238	.channels = __wl_5ghz_n_channels,
239	.n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
240	.bitrates = wl_a_rates,
241	.n_bitrates = wl_a_rates_size,
242};
243
244static const u32 __wl_cipher_suites[] = {
245	WLAN_CIPHER_SUITE_WEP40,
246	WLAN_CIPHER_SUITE_WEP104,
247	WLAN_CIPHER_SUITE_TKIP,
248	WLAN_CIPHER_SUITE_CCMP,
249	WLAN_CIPHER_SUITE_AES_CMAC,
250};
251
252/* tag_ID/length/value_buffer tuple */
253struct brcmf_tlv {
254	u8 id;
255	u8 len;
256	u8 data[1];
257};
258
259/* Quarter dBm units to mW
260 * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
261 * Table is offset so the last entry is largest mW value that fits in
262 * a u16.
263 */
264
265#define QDBM_OFFSET 153		/* Offset for first entry */
266#define QDBM_TABLE_LEN 40	/* Table size */
267
268/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
269 * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
270 */
271#define QDBM_TABLE_LOW_BOUND 6493	/* Low bound */
272
273/* Largest mW value that will round down to the last table entry,
274 * QDBM_OFFSET + QDBM_TABLE_LEN-1.
275 * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
276 * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
277 */
278#define QDBM_TABLE_HIGH_BOUND 64938	/* High bound */
279
280static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
281/* qdBm:	+0	+1	+2	+3	+4	+5	+6	+7 */
282/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
283/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
284/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
285/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
286/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
287};
288
289static u16 brcmf_qdbm_to_mw(u8 qdbm)
290{
291	uint factor = 1;
292	int idx = qdbm - QDBM_OFFSET;
293
294	if (idx >= QDBM_TABLE_LEN)
295		/* clamp to max u16 mW value */
296		return 0xFFFF;
297
298	/* scale the qdBm index up to the range of the table 0-40
299	 * where an offset of 40 qdBm equals a factor of 10 mW.
300	 */
301	while (idx < 0) {
302		idx += 40;
303		factor *= 10;
304	}
305
306	/* return the mW value scaled down to the correct factor of 10,
307	 * adding in factor/2 to get proper rounding.
308	 */
309	return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
310}
311
312static u8 brcmf_mw_to_qdbm(u16 mw)
313{
314	u8 qdbm;
315	int offset;
316	uint mw_uint = mw;
317	uint boundary;
318
319	/* handle boundary case */
320	if (mw_uint <= 1)
321		return 0;
322
323	offset = QDBM_OFFSET;
324
325	/* move mw into the range of the table */
326	while (mw_uint < QDBM_TABLE_LOW_BOUND) {
327		mw_uint *= 10;
328		offset -= 40;
329	}
330
331	for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
332		boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
333						    nqdBm_to_mW_map[qdbm]) / 2;
334		if (mw_uint < boundary)
335			break;
336	}
337
338	qdbm += (u8) offset;
339
340	return qdbm;
341}
342
343/* function for reading/writing a single u32 from/to the dongle */
344static int
345brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par)
346{
347	int err;
348	__le32 par_le = cpu_to_le32(*par);
349
350	err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32));
351	*par = le32_to_cpu(par_le);
352
353	return err;
354}
355
356static void convert_key_from_CPU(struct brcmf_wsec_key *key,
357				 struct brcmf_wsec_key_le *key_le)
358{
359	key_le->index = cpu_to_le32(key->index);
360	key_le->len = cpu_to_le32(key->len);
361	key_le->algo = cpu_to_le32(key->algo);
362	key_le->flags = cpu_to_le32(key->flags);
363	key_le->rxiv.hi = cpu_to_le32(key->rxiv.hi);
364	key_le->rxiv.lo = cpu_to_le16(key->rxiv.lo);
365	key_le->iv_initialized = cpu_to_le32(key->iv_initialized);
366	memcpy(key_le->data, key->data, sizeof(key->data));
367	memcpy(key_le->ea, key->ea, sizeof(key->ea));
368}
369
370static int send_key_to_dongle(struct net_device *ndev,
371			      struct brcmf_wsec_key *key)
372{
373	int err;
374	struct brcmf_wsec_key_le key_le;
375
376	convert_key_from_CPU(key, &key_le);
377	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, sizeof(key_le));
378	if (err)
379		WL_ERR("WLC_SET_KEY error (%d)\n", err);
380	return err;
381}
382
383static s32
384brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
385			 enum nl80211_iftype type, u32 *flags,
386			 struct vif_params *params)
387{
388	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
389	struct wireless_dev *wdev;
390	s32 infra = 0;
391	s32 err = 0;
392
393	WL_TRACE("Enter\n");
394	if (!check_sys_up(wiphy))
395		return -EIO;
396
397	switch (type) {
398	case NL80211_IFTYPE_MONITOR:
399	case NL80211_IFTYPE_WDS:
400		WL_ERR("type (%d) : currently we do not support this type\n",
401		       type);
402		return -EOPNOTSUPP;
403	case NL80211_IFTYPE_ADHOC:
404		cfg_priv->conf->mode = WL_MODE_IBSS;
405		infra = 0;
406		break;
407	case NL80211_IFTYPE_STATION:
408		cfg_priv->conf->mode = WL_MODE_BSS;
409		infra = 1;
410		break;
411	default:
412		err = -EINVAL;
413		goto done;
414	}
415
416	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
417	if (err) {
418		WL_ERR("WLC_SET_INFRA error (%d)\n", err);
419		err = -EAGAIN;
420	} else {
421		wdev = ndev->ieee80211_ptr;
422		wdev->iftype = type;
423	}
424
425	WL_INFO("IF Type = %s\n",
426		(cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
427
428done:
429	WL_TRACE("Exit\n");
430
431	return err;
432}
433
434static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val)
435{
436	s8 buf[BRCMF_DCMD_SMLEN];
437	u32 len;
438	s32 err = 0;
439	__le32 val_le;
440
441	val_le = cpu_to_le32(val);
442	len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf,
443			    sizeof(buf));
444	BUG_ON(!len);
445
446	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len);
447	if (err)
448		WL_ERR("error (%d)\n", err);
449
450	return err;
451}
452
453static s32
454brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval)
455{
456	union {
457		s8 buf[BRCMF_DCMD_SMLEN];
458		__le32 val;
459	} var;
460	u32 len;
461	u32 data_null;
462	s32 err = 0;
463
464	len =
465	    brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
466			sizeof(var.buf));
467	BUG_ON(!len);
468	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len);
469	if (err)
470		WL_ERR("error (%d)\n", err);
471
472	*retval = le32_to_cpu(var.val);
473
474	return err;
475}
476
477static void brcmf_set_mpc(struct net_device *ndev, int mpc)
478{
479	s32 err = 0;
480	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
481
482	if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
483		err = brcmf_dev_intvar_set(ndev, "mpc", mpc);
484		if (err) {
485			WL_ERR("fail to set mpc\n");
486			return;
487		}
488		WL_INFO("MPC : %d\n", mpc);
489	}
490}
491
492static void wl_iscan_prep(struct brcmf_scan_params_le *params_le,
493			  struct brcmf_ssid *ssid)
494{
495	memcpy(params_le->bssid, ether_bcast, ETH_ALEN);
496	params_le->bss_type = DOT11_BSSTYPE_ANY;
497	params_le->scan_type = 0;
498	params_le->channel_num = 0;
499	params_le->nprobes = cpu_to_le32(-1);
500	params_le->active_time = cpu_to_le32(-1);
501	params_le->passive_time = cpu_to_le32(-1);
502	params_le->home_time = cpu_to_le32(-1);
503	if (ssid && ssid->SSID_len)
504		memcpy(&params_le->ssid_le, ssid, sizeof(struct brcmf_ssid));
505}
506
507static s32
508brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param,
509		    s32 paramlen, void *bufptr, s32 buflen)
510{
511	s32 iolen;
512
513	iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
514	BUG_ON(!iolen);
515
516	return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen);
517}
518
519static s32
520brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param,
521		    s32 paramlen, void *bufptr, s32 buflen)
522{
523	s32 iolen;
524
525	iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen);
526	BUG_ON(!iolen);
527
528	return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen);
529}
530
531static s32
532brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan,
533		struct brcmf_ssid *ssid, u16 action)
534{
535	s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
536			  offsetof(struct brcmf_iscan_params_le, params_le);
537	struct brcmf_iscan_params_le *params;
538	s32 err = 0;
539
540	if (ssid && ssid->SSID_len)
541		params_size += sizeof(struct brcmf_ssid);
542	params = kzalloc(params_size, GFP_KERNEL);
543	if (!params)
544		return -ENOMEM;
545	BUG_ON(params_size >= BRCMF_DCMD_SMLEN);
546
547	wl_iscan_prep(&params->params_le, ssid);
548
549	params->version = cpu_to_le32(BRCMF_ISCAN_REQ_VERSION);
550	params->action = cpu_to_le16(action);
551	params->scan_duration = cpu_to_le16(0);
552
553	err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size,
554				     iscan->dcmd_buf, BRCMF_DCMD_SMLEN);
555	if (err) {
556		if (err == -EBUSY)
557			WL_INFO("system busy : iscan canceled\n");
558		else
559			WL_ERR("error (%d)\n", err);
560	}
561
562	kfree(params);
563	return err;
564}
565
566static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv)
567{
568	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
569	struct net_device *ndev = cfg_to_ndev(cfg_priv);
570	struct brcmf_ssid ssid;
571	__le32 passive_scan;
572	s32 err = 0;
573
574	/* Broadcast scan by default */
575	memset(&ssid, 0, sizeof(ssid));
576
577	iscan->state = WL_ISCAN_STATE_SCANING;
578
579	passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
580	err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN,
581			&passive_scan, sizeof(passive_scan));
582	if (err) {
583		WL_ERR("error (%d)\n", err);
584		return err;
585	}
586	brcmf_set_mpc(ndev, 0);
587	cfg_priv->iscan_kickstart = true;
588	err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START);
589	if (err) {
590		brcmf_set_mpc(ndev, 1);
591		cfg_priv->iscan_kickstart = false;
592		return err;
593	}
594	mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
595	iscan->timer_on = 1;
596	return err;
597}
598
599static s32
600__brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
601		   struct cfg80211_scan_request *request,
602		   struct cfg80211_ssid *this_ssid)
603{
604	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
605	struct cfg80211_ssid *ssids;
606	struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int;
607	__le32 passive_scan;
608	bool iscan_req;
609	bool spec_scan;
610	s32 err = 0;
611	u32 SSID_len;
612
613	if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
614		WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status);
615		return -EAGAIN;
616	}
617	if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) {
618		WL_ERR("Scanning being aborted : status (%lu)\n",
619		       cfg_priv->status);
620		return -EAGAIN;
621	}
622	if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
623		WL_ERR("Connecting : status (%lu)\n",
624		       cfg_priv->status);
625		return -EAGAIN;
626	}
627
628	iscan_req = false;
629	spec_scan = false;
630	if (request) {
631		/* scan bss */
632		ssids = request->ssids;
633		if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len))
634			iscan_req = true;
635	} else {
636		/* scan in ibss */
637		/* we don't do iscan in ibss */
638		ssids = this_ssid;
639	}
640
641	cfg_priv->scan_request = request;
642	set_bit(WL_STATUS_SCANNING, &cfg_priv->status);
643	if (iscan_req) {
644		err = brcmf_do_iscan(cfg_priv);
645		if (!err)
646			return err;
647		else
648			goto scan_out;
649	} else {
650		WL_SCAN("ssid \"%s\", ssid_len (%d)\n",
651		       ssids->ssid, ssids->ssid_len);
652		memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
653		SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
654		sr->ssid_le.SSID_len = cpu_to_le32(0);
655		if (SSID_len) {
656			memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
657			sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
658			spec_scan = true;
659		} else {
660			WL_SCAN("Broadcast scan\n");
661		}
662
663		passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1);
664		err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN,
665				&passive_scan, sizeof(passive_scan));
666		if (err) {
667			WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err);
668			goto scan_out;
669		}
670		brcmf_set_mpc(ndev, 0);
671		err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le,
672				      sizeof(sr->ssid_le));
673		if (err) {
674			if (err == -EBUSY)
675				WL_INFO("system busy : scan for \"%s\" "
676					"canceled\n", sr->ssid_le.SSID);
677			else
678				WL_ERR("WLC_SCAN error (%d)\n", err);
679
680			brcmf_set_mpc(ndev, 1);
681			goto scan_out;
682		}
683	}
684
685	return 0;
686
687scan_out:
688	clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
689	cfg_priv->scan_request = NULL;
690	return err;
691}
692
693static s32
694brcmf_cfg80211_scan(struct wiphy *wiphy,
695		 struct cfg80211_scan_request *request)
696{
697	struct net_device *ndev = request->wdev->netdev;
698	s32 err = 0;
699
700	WL_TRACE("Enter\n");
701
702	if (!check_sys_up(wiphy))
703		return -EIO;
704
705	err = __brcmf_cfg80211_scan(wiphy, ndev, request, NULL);
706	if (err)
707		WL_ERR("scan error (%d)\n", err);
708
709	WL_TRACE("Exit\n");
710	return err;
711}
712
713static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold)
714{
715	s32 err = 0;
716
717	err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold);
718	if (err)
719		WL_ERR("Error (%d)\n", err);
720
721	return err;
722}
723
724static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold)
725{
726	s32 err = 0;
727
728	err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold);
729	if (err)
730		WL_ERR("Error (%d)\n", err);
731
732	return err;
733}
734
735static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l)
736{
737	s32 err = 0;
738	u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL);
739
740	err = brcmf_exec_dcmd_u32(ndev, cmd, &retry);
741	if (err) {
742		WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
743		return err;
744	}
745	return err;
746}
747
748static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
749{
750	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
751	struct net_device *ndev = cfg_to_ndev(cfg_priv);
752	s32 err = 0;
753
754	WL_TRACE("Enter\n");
755	if (!check_sys_up(wiphy))
756		return -EIO;
757
758	if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
759	    (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) {
760		cfg_priv->conf->rts_threshold = wiphy->rts_threshold;
761		err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold);
762		if (!err)
763			goto done;
764	}
765	if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
766	    (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) {
767		cfg_priv->conf->frag_threshold = wiphy->frag_threshold;
768		err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold);
769		if (!err)
770			goto done;
771	}
772	if (changed & WIPHY_PARAM_RETRY_LONG
773	    && (cfg_priv->conf->retry_long != wiphy->retry_long)) {
774		cfg_priv->conf->retry_long = wiphy->retry_long;
775		err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true);
776		if (!err)
777			goto done;
778	}
779	if (changed & WIPHY_PARAM_RETRY_SHORT
780	    && (cfg_priv->conf->retry_short != wiphy->retry_short)) {
781		cfg_priv->conf->retry_short = wiphy->retry_short;
782		err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false);
783		if (!err)
784			goto done;
785	}
786
787done:
788	WL_TRACE("Exit\n");
789	return err;
790}
791
792static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item)
793{
794	switch (item) {
795	case WL_PROF_SEC:
796		return &cfg_priv->profile->sec;
797	case WL_PROF_BSSID:
798		return &cfg_priv->profile->bssid;
799	case WL_PROF_SSID:
800		return &cfg_priv->profile->ssid;
801	}
802	WL_ERR("invalid item (%d)\n", item);
803	return NULL;
804}
805
806static s32
807brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv,
808		  const struct brcmf_event_msg *e, void *data, s32 item)
809{
810	s32 err = 0;
811	struct brcmf_ssid *ssid;
812
813	switch (item) {
814	case WL_PROF_SSID:
815		ssid = (struct brcmf_ssid *) data;
816		memset(cfg_priv->profile->ssid.SSID, 0,
817		       sizeof(cfg_priv->profile->ssid.SSID));
818		memcpy(cfg_priv->profile->ssid.SSID,
819		       ssid->SSID, ssid->SSID_len);
820		cfg_priv->profile->ssid.SSID_len = ssid->SSID_len;
821		break;
822	case WL_PROF_BSSID:
823		if (data)
824			memcpy(cfg_priv->profile->bssid, data, ETH_ALEN);
825		else
826			memset(cfg_priv->profile->bssid, 0, ETH_ALEN);
827		break;
828	case WL_PROF_SEC:
829		memcpy(&cfg_priv->profile->sec, data,
830		       sizeof(cfg_priv->profile->sec));
831		break;
832	case WL_PROF_BEACONINT:
833		cfg_priv->profile->beacon_interval = *(u16 *)data;
834		break;
835	case WL_PROF_DTIMPERIOD:
836		cfg_priv->profile->dtim_period = *(u8 *)data;
837		break;
838	default:
839		WL_ERR("unsupported item (%d)\n", item);
840		err = -EOPNOTSUPP;
841		break;
842	}
843
844	return err;
845}
846
847static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof)
848{
849	memset(prof, 0, sizeof(*prof));
850}
851
852static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params,
853	size_t *join_params_size)
854{
855	u16 chanspec = 0;
856
857	if (ch != 0) {
858		if (ch <= CH_MAX_2G_CHANNEL)
859			chanspec |= WL_CHANSPEC_BAND_2G;
860		else
861			chanspec |= WL_CHANSPEC_BAND_5G;
862
863		chanspec |= WL_CHANSPEC_BW_20;
864		chanspec |= WL_CHANSPEC_CTL_SB_NONE;
865
866		*join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE +
867				     sizeof(u16);
868
869		chanspec |= (ch & WL_CHANSPEC_CHAN_MASK);
870		join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec);
871		join_params->params_le.chanspec_num = cpu_to_le32(1);
872
873		WL_CONN("join_params->params.chanspec_list[0]= %#X,"
874			"channel %d, chanspec %#X\n",
875			chanspec, ch, chanspec);
876	}
877}
878
879static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv)
880{
881	struct net_device *ndev = NULL;
882	s32 err = 0;
883
884	WL_TRACE("Enter\n");
885
886	if (cfg_priv->link_up) {
887		ndev = cfg_to_ndev(cfg_priv);
888		WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
889		err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0);
890		if (err)
891			WL_ERR("WLC_DISASSOC failed (%d)\n", err);
892		cfg_priv->link_up = false;
893	}
894	WL_TRACE("Exit\n");
895}
896
897static s32
898brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
899		      struct cfg80211_ibss_params *params)
900{
901	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
902	struct brcmf_join_params join_params;
903	size_t join_params_size = 0;
904	s32 err = 0;
905	s32 wsec = 0;
906	s32 bcnprd;
907	struct brcmf_ssid ssid;
908
909	WL_TRACE("Enter\n");
910	if (!check_sys_up(wiphy))
911		return -EIO;
912
913	if (params->ssid)
914		WL_CONN("SSID: %s\n", params->ssid);
915	else {
916		WL_CONN("SSID: NULL, Not supported\n");
917		return -EOPNOTSUPP;
918	}
919
920	set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
921
922	if (params->bssid)
923		WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n",
924		params->bssid[0], params->bssid[1], params->bssid[2],
925		params->bssid[3], params->bssid[4], params->bssid[5]);
926	else
927		WL_CONN("No BSSID specified\n");
928
929	if (params->channel)
930		WL_CONN("channel: %d\n", params->channel->center_freq);
931	else
932		WL_CONN("no channel specified\n");
933
934	if (params->channel_fixed)
935		WL_CONN("fixed channel required\n");
936	else
937		WL_CONN("no fixed channel required\n");
938
939	if (params->ie && params->ie_len)
940		WL_CONN("ie len: %d\n", params->ie_len);
941	else
942		WL_CONN("no ie specified\n");
943
944	if (params->beacon_interval)
945		WL_CONN("beacon interval: %d\n", params->beacon_interval);
946	else
947		WL_CONN("no beacon interval specified\n");
948
949	if (params->basic_rates)
950		WL_CONN("basic rates: %08X\n", params->basic_rates);
951	else
952		WL_CONN("no basic rates specified\n");
953
954	if (params->privacy)
955		WL_CONN("privacy required\n");
956	else
957		WL_CONN("no privacy required\n");
958
959	/* Configure Privacy for starter */
960	if (params->privacy)
961		wsec |= WEP_ENABLED;
962
963	err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
964	if (err) {
965		WL_ERR("wsec failed (%d)\n", err);
966		goto done;
967	}
968
969	/* Configure Beacon Interval for starter */
970	if (params->beacon_interval)
971		bcnprd = params->beacon_interval;
972	else
973		bcnprd = 100;
974
975	err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd);
976	if (err) {
977		WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
978		goto done;
979	}
980
981	/* Configure required join parameter */
982	memset(&join_params, 0, sizeof(struct brcmf_join_params));
983
984	/* SSID */
985	ssid.SSID_len = min_t(u32, params->ssid_len, 32);
986	memcpy(ssid.SSID, params->ssid, ssid.SSID_len);
987	memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len);
988	join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
989	join_params_size = sizeof(join_params.ssid_le);
990	brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
991
992	/* BSSID */
993	if (params->bssid) {
994		memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
995		join_params_size = sizeof(join_params.ssid_le) +
996				   BRCMF_ASSOC_PARAMS_FIXED_SIZE;
997	} else {
998		memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
999	}
1000
1001	brcmf_update_prof(cfg_priv, NULL,
1002			  &join_params.params_le.bssid, WL_PROF_BSSID);
1003
1004	/* Channel */
1005	if (params->channel) {
1006		u32 target_channel;
1007
1008		cfg_priv->channel =
1009			ieee80211_frequency_to_channel(
1010				params->channel->center_freq);
1011		if (params->channel_fixed) {
1012			/* adding chanspec */
1013			brcmf_ch_to_chanspec(cfg_priv->channel,
1014				&join_params, &join_params_size);
1015		}
1016
1017		/* set channel for starter */
1018		target_channel = cfg_priv->channel;
1019		err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL,
1020					  &target_channel);
1021		if (err) {
1022			WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
1023			goto done;
1024		}
1025	} else
1026		cfg_priv->channel = 0;
1027
1028	cfg_priv->ibss_starter = false;
1029
1030
1031	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
1032			   &join_params, join_params_size);
1033	if (err) {
1034		WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1035		goto done;
1036	}
1037
1038done:
1039	if (err)
1040		clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1041	WL_TRACE("Exit\n");
1042	return err;
1043}
1044
1045static s32
1046brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
1047{
1048	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1049	s32 err = 0;
1050
1051	WL_TRACE("Enter\n");
1052	if (!check_sys_up(wiphy))
1053		return -EIO;
1054
1055	brcmf_link_down(cfg_priv);
1056
1057	WL_TRACE("Exit\n");
1058
1059	return err;
1060}
1061
1062static s32 brcmf_set_wpa_version(struct net_device *ndev,
1063				 struct cfg80211_connect_params *sme)
1064{
1065	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1066	struct brcmf_cfg80211_security *sec;
1067	s32 val = 0;
1068	s32 err = 0;
1069
1070	if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1071		val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1072	else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1073		val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1074	else
1075		val = WPA_AUTH_DISABLED;
1076	WL_CONN("setting wpa_auth to 0x%0x\n", val);
1077	err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
1078	if (err) {
1079		WL_ERR("set wpa_auth failed (%d)\n", err);
1080		return err;
1081	}
1082	sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1083	sec->wpa_versions = sme->crypto.wpa_versions;
1084	return err;
1085}
1086
1087static s32 brcmf_set_auth_type(struct net_device *ndev,
1088			       struct cfg80211_connect_params *sme)
1089{
1090	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1091	struct brcmf_cfg80211_security *sec;
1092	s32 val = 0;
1093	s32 err = 0;
1094
1095	switch (sme->auth_type) {
1096	case NL80211_AUTHTYPE_OPEN_SYSTEM:
1097		val = 0;
1098		WL_CONN("open system\n");
1099		break;
1100	case NL80211_AUTHTYPE_SHARED_KEY:
1101		val = 1;
1102		WL_CONN("shared key\n");
1103		break;
1104	case NL80211_AUTHTYPE_AUTOMATIC:
1105		val = 2;
1106		WL_CONN("automatic\n");
1107		break;
1108	case NL80211_AUTHTYPE_NETWORK_EAP:
1109		WL_CONN("network eap\n");
1110	default:
1111		val = 2;
1112		WL_ERR("invalid auth type (%d)\n", sme->auth_type);
1113		break;
1114	}
1115
1116	err = brcmf_dev_intvar_set(ndev, "auth", val);
1117	if (err) {
1118		WL_ERR("set auth failed (%d)\n", err);
1119		return err;
1120	}
1121	sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1122	sec->auth_type = sme->auth_type;
1123	return err;
1124}
1125
1126static s32
1127brcmf_set_set_cipher(struct net_device *ndev,
1128		     struct cfg80211_connect_params *sme)
1129{
1130	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1131	struct brcmf_cfg80211_security *sec;
1132	s32 pval = 0;
1133	s32 gval = 0;
1134	s32 err = 0;
1135
1136	if (sme->crypto.n_ciphers_pairwise) {
1137		switch (sme->crypto.ciphers_pairwise[0]) {
1138		case WLAN_CIPHER_SUITE_WEP40:
1139		case WLAN_CIPHER_SUITE_WEP104:
1140			pval = WEP_ENABLED;
1141			break;
1142		case WLAN_CIPHER_SUITE_TKIP:
1143			pval = TKIP_ENABLED;
1144			break;
1145		case WLAN_CIPHER_SUITE_CCMP:
1146			pval = AES_ENABLED;
1147			break;
1148		case WLAN_CIPHER_SUITE_AES_CMAC:
1149			pval = AES_ENABLED;
1150			break;
1151		default:
1152			WL_ERR("invalid cipher pairwise (%d)\n",
1153			       sme->crypto.ciphers_pairwise[0]);
1154			return -EINVAL;
1155		}
1156	}
1157	if (sme->crypto.cipher_group) {
1158		switch (sme->crypto.cipher_group) {
1159		case WLAN_CIPHER_SUITE_WEP40:
1160		case WLAN_CIPHER_SUITE_WEP104:
1161			gval = WEP_ENABLED;
1162			break;
1163		case WLAN_CIPHER_SUITE_TKIP:
1164			gval = TKIP_ENABLED;
1165			break;
1166		case WLAN_CIPHER_SUITE_CCMP:
1167			gval = AES_ENABLED;
1168			break;
1169		case WLAN_CIPHER_SUITE_AES_CMAC:
1170			gval = AES_ENABLED;
1171			break;
1172		default:
1173			WL_ERR("invalid cipher group (%d)\n",
1174			       sme->crypto.cipher_group);
1175			return -EINVAL;
1176		}
1177	}
1178
1179	WL_CONN("pval (%d) gval (%d)\n", pval, gval);
1180	err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval);
1181	if (err) {
1182		WL_ERR("error (%d)\n", err);
1183		return err;
1184	}
1185
1186	sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1187	sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
1188	sec->cipher_group = sme->crypto.cipher_group;
1189
1190	return err;
1191}
1192
1193static s32
1194brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
1195{
1196	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1197	struct brcmf_cfg80211_security *sec;
1198	s32 val = 0;
1199	s32 err = 0;
1200
1201	if (sme->crypto.n_akm_suites) {
1202		err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val);
1203		if (err) {
1204			WL_ERR("could not get wpa_auth (%d)\n", err);
1205			return err;
1206		}
1207		if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
1208			switch (sme->crypto.akm_suites[0]) {
1209			case WLAN_AKM_SUITE_8021X:
1210				val = WPA_AUTH_UNSPECIFIED;
1211				break;
1212			case WLAN_AKM_SUITE_PSK:
1213				val = WPA_AUTH_PSK;
1214				break;
1215			default:
1216				WL_ERR("invalid cipher group (%d)\n",
1217				       sme->crypto.cipher_group);
1218				return -EINVAL;
1219			}
1220		} else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
1221			switch (sme->crypto.akm_suites[0]) {
1222			case WLAN_AKM_SUITE_8021X:
1223				val = WPA2_AUTH_UNSPECIFIED;
1224				break;
1225			case WLAN_AKM_SUITE_PSK:
1226				val = WPA2_AUTH_PSK;
1227				break;
1228			default:
1229				WL_ERR("invalid cipher group (%d)\n",
1230				       sme->crypto.cipher_group);
1231				return -EINVAL;
1232			}
1233		}
1234
1235		WL_CONN("setting wpa_auth to %d\n", val);
1236		err = brcmf_dev_intvar_set(ndev, "wpa_auth", val);
1237		if (err) {
1238			WL_ERR("could not set wpa_auth (%d)\n", err);
1239			return err;
1240		}
1241	}
1242	sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1243	sec->wpa_auth = sme->crypto.akm_suites[0];
1244
1245	return err;
1246}
1247
1248static s32
1249brcmf_set_wep_sharedkey(struct net_device *ndev,
1250		     struct cfg80211_connect_params *sme)
1251{
1252	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
1253	struct brcmf_cfg80211_security *sec;
1254	struct brcmf_wsec_key key;
1255	s32 val;
1256	s32 err = 0;
1257
1258	WL_CONN("key len (%d)\n", sme->key_len);
1259
1260	if (sme->key_len == 0)
1261		return 0;
1262
1263	sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1264	WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n",
1265		sec->wpa_versions, sec->cipher_pairwise);
1266
1267	if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2))
1268		return 0;
1269
1270	if (sec->cipher_pairwise &
1271	    (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)) {
1272		memset(&key, 0, sizeof(key));
1273		key.len = (u32) sme->key_len;
1274		key.index = (u32) sme->key_idx;
1275		if (key.len > sizeof(key.data)) {
1276			WL_ERR("Too long key length (%u)\n", key.len);
1277			return -EINVAL;
1278		}
1279		memcpy(key.data, sme->key, key.len);
1280		key.flags = BRCMF_PRIMARY_KEY;
1281		switch (sec->cipher_pairwise) {
1282		case WLAN_CIPHER_SUITE_WEP40:
1283			key.algo = CRYPTO_ALGO_WEP1;
1284			break;
1285		case WLAN_CIPHER_SUITE_WEP104:
1286			key.algo = CRYPTO_ALGO_WEP128;
1287			break;
1288		default:
1289			WL_ERR("Invalid algorithm (%d)\n",
1290			       sme->crypto.ciphers_pairwise[0]);
1291			return -EINVAL;
1292		}
1293		/* Set the new key/index */
1294		WL_CONN("key length (%d) key index (%d) algo (%d)\n",
1295			key.len, key.index, key.algo);
1296		WL_CONN("key \"%s\"\n", key.data);
1297		err = send_key_to_dongle(ndev, &key);
1298		if (err)
1299			return err;
1300
1301		if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
1302			WL_CONN("set auth_type to shared key\n");
1303			val = 1;	/* shared key */
1304			err = brcmf_dev_intvar_set(ndev, "auth", val);
1305			if (err) {
1306				WL_ERR("set auth failed (%d)\n", err);
1307				return err;
1308			}
1309		}
1310	}
1311	return err;
1312}
1313
1314static s32
1315brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
1316		    struct cfg80211_connect_params *sme)
1317{
1318	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1319	struct ieee80211_channel *chan = sme->channel;
1320	struct brcmf_join_params join_params;
1321	size_t join_params_size;
1322	struct brcmf_ssid ssid;
1323
1324	s32 err = 0;
1325
1326	WL_TRACE("Enter\n");
1327	if (!check_sys_up(wiphy))
1328		return -EIO;
1329
1330	if (!sme->ssid) {
1331		WL_ERR("Invalid ssid\n");
1332		return -EOPNOTSUPP;
1333	}
1334
1335	set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1336
1337	if (chan) {
1338		cfg_priv->channel =
1339			ieee80211_frequency_to_channel(chan->center_freq);
1340		WL_CONN("channel (%d), center_req (%d)\n",
1341				cfg_priv->channel, chan->center_freq);
1342	} else
1343		cfg_priv->channel = 0;
1344
1345	WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
1346
1347	err = brcmf_set_wpa_version(ndev, sme);
1348	if (err) {
1349		WL_ERR("wl_set_wpa_version failed (%d)\n", err);
1350		goto done;
1351	}
1352
1353	err = brcmf_set_auth_type(ndev, sme);
1354	if (err) {
1355		WL_ERR("wl_set_auth_type failed (%d)\n", err);
1356		goto done;
1357	}
1358
1359	err = brcmf_set_set_cipher(ndev, sme);
1360	if (err) {
1361		WL_ERR("wl_set_set_cipher failed (%d)\n", err);
1362		goto done;
1363	}
1364
1365	err = brcmf_set_key_mgmt(ndev, sme);
1366	if (err) {
1367		WL_ERR("wl_set_key_mgmt failed (%d)\n", err);
1368		goto done;
1369	}
1370
1371	err = brcmf_set_wep_sharedkey(ndev, sme);
1372	if (err) {
1373		WL_ERR("brcmf_set_wep_sharedkey failed (%d)\n", err);
1374		goto done;
1375	}
1376
1377	memset(&join_params, 0, sizeof(join_params));
1378	join_params_size = sizeof(join_params.ssid_le);
1379
1380	ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), (u32)sme->ssid_len);
1381	memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len);
1382	memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len);
1383	join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
1384	brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID);
1385
1386	memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN);
1387
1388	if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN)
1389		WL_CONN("ssid \"%s\", len (%d)\n",
1390		       ssid.SSID, ssid.SSID_len);
1391
1392	brcmf_ch_to_chanspec(cfg_priv->channel,
1393			     &join_params, &join_params_size);
1394	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID,
1395			   &join_params, join_params_size);
1396	if (err)
1397		WL_ERR("WLC_SET_SSID failed (%d)\n", err);
1398
1399done:
1400	if (err)
1401		clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
1402	WL_TRACE("Exit\n");
1403	return err;
1404}
1405
1406static s32
1407brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev,
1408		       u16 reason_code)
1409{
1410	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1411	struct brcmf_scb_val_le scbval;
1412	s32 err = 0;
1413
1414	WL_TRACE("Enter. Reason code = %d\n", reason_code);
1415	if (!check_sys_up(wiphy))
1416		return -EIO;
1417
1418	clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
1419
1420	memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN);
1421	scbval.val = cpu_to_le32(reason_code);
1422	err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval,
1423			      sizeof(struct brcmf_scb_val_le));
1424	if (err)
1425		WL_ERR("error (%d)\n", err);
1426
1427	cfg_priv->link_up = false;
1428
1429	WL_TRACE("Exit\n");
1430	return err;
1431}
1432
1433static s32
1434brcmf_cfg80211_set_tx_power(struct wiphy *wiphy,
1435			    enum nl80211_tx_power_setting type, s32 mbm)
1436{
1437
1438	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1439	struct net_device *ndev = cfg_to_ndev(cfg_priv);
1440	u16 txpwrmw;
1441	s32 err = 0;
1442	s32 disable = 0;
1443	s32 dbm = MBM_TO_DBM(mbm);
1444
1445	WL_TRACE("Enter\n");
1446	if (!check_sys_up(wiphy))
1447		return -EIO;
1448
1449	switch (type) {
1450	case NL80211_TX_POWER_AUTOMATIC:
1451		break;
1452	case NL80211_TX_POWER_LIMITED:
1453	case NL80211_TX_POWER_FIXED:
1454		if (dbm < 0) {
1455			WL_ERR("TX_POWER_FIXED - dbm is negative\n");
1456			err = -EINVAL;
1457			goto done;
1458		}
1459		break;
1460	}
1461	/* Make sure radio is off or on as far as software is concerned */
1462	disable = WL_RADIO_SW_DISABLE << 16;
1463	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable);
1464	if (err)
1465		WL_ERR("WLC_SET_RADIO error (%d)\n", err);
1466
1467	if (dbm > 0xffff)
1468		txpwrmw = 0xffff;
1469	else
1470		txpwrmw = (u16) dbm;
1471	err = brcmf_dev_intvar_set(ndev, "qtxpower",
1472			(s32) (brcmf_mw_to_qdbm(txpwrmw)));
1473	if (err)
1474		WL_ERR("qtxpower error (%d)\n", err);
1475	cfg_priv->conf->tx_power = dbm;
1476
1477done:
1478	WL_TRACE("Exit\n");
1479	return err;
1480}
1481
1482static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
1483{
1484	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1485	struct net_device *ndev = cfg_to_ndev(cfg_priv);
1486	s32 txpwrdbm;
1487	u8 result;
1488	s32 err = 0;
1489
1490	WL_TRACE("Enter\n");
1491	if (!check_sys_up(wiphy))
1492		return -EIO;
1493
1494	err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
1495	if (err) {
1496		WL_ERR("error (%d)\n", err);
1497		goto done;
1498	}
1499
1500	result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
1501	*dbm = (s32) brcmf_qdbm_to_mw(result);
1502
1503done:
1504	WL_TRACE("Exit\n");
1505	return err;
1506}
1507
1508static s32
1509brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
1510			       u8 key_idx, bool unicast, bool multicast)
1511{
1512	u32 index;
1513	u32 wsec;
1514	s32 err = 0;
1515
1516	WL_TRACE("Enter\n");
1517	WL_CONN("key index (%d)\n", key_idx);
1518	if (!check_sys_up(wiphy))
1519		return -EIO;
1520
1521	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec);
1522	if (err) {
1523		WL_ERR("WLC_GET_WSEC error (%d)\n", err);
1524		goto done;
1525	}
1526
1527	if (wsec & WEP_ENABLED) {
1528		/* Just select a new current key */
1529		index = key_idx;
1530		err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY,
1531					  &index);
1532		if (err)
1533			WL_ERR("error (%d)\n", err);
1534	}
1535done:
1536	WL_TRACE("Exit\n");
1537	return err;
1538}
1539
1540static s32
1541brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
1542	      u8 key_idx, const u8 *mac_addr, struct key_params *params)
1543{
1544	struct brcmf_wsec_key key;
1545	struct brcmf_wsec_key_le key_le;
1546	s32 err = 0;
1547
1548	memset(&key, 0, sizeof(key));
1549	key.index = (u32) key_idx;
1550	/* Instead of bcast for ea address for default wep keys,
1551		 driver needs it to be Null */
1552	if (!is_multicast_ether_addr(mac_addr))
1553		memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN);
1554	key.len = (u32) params->key_len;
1555	/* check for key index change */
1556	if (key.len == 0) {
1557		/* key delete */
1558		err = send_key_to_dongle(ndev, &key);
1559		if (err)
1560			return err;
1561	} else {
1562		if (key.len > sizeof(key.data)) {
1563			WL_ERR("Invalid key length (%d)\n", key.len);
1564			return -EINVAL;
1565		}
1566
1567		WL_CONN("Setting the key index %d\n", key.index);
1568		memcpy(key.data, params->key, key.len);
1569
1570		if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1571			u8 keybuf[8];
1572			memcpy(keybuf, &key.data[24], sizeof(keybuf));
1573			memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1574			memcpy(&key.data[16], keybuf, sizeof(keybuf));
1575		}
1576
1577		/* if IW_ENCODE_EXT_RX_SEQ_VALID set */
1578		if (params->seq && params->seq_len == 6) {
1579			/* rx iv */
1580			u8 *ivptr;
1581			ivptr = (u8 *) params->seq;
1582			key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
1583			    (ivptr[3] << 8) | ivptr[2];
1584			key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
1585			key.iv_initialized = true;
1586		}
1587
1588		switch (params->cipher) {
1589		case WLAN_CIPHER_SUITE_WEP40:
1590			key.algo = CRYPTO_ALGO_WEP1;
1591			WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1592			break;
1593		case WLAN_CIPHER_SUITE_WEP104:
1594			key.algo = CRYPTO_ALGO_WEP128;
1595			WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1596			break;
1597		case WLAN_CIPHER_SUITE_TKIP:
1598			key.algo = CRYPTO_ALGO_TKIP;
1599			WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1600			break;
1601		case WLAN_CIPHER_SUITE_AES_CMAC:
1602			key.algo = CRYPTO_ALGO_AES_CCM;
1603			WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1604			break;
1605		case WLAN_CIPHER_SUITE_CCMP:
1606			key.algo = CRYPTO_ALGO_AES_CCM;
1607			WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
1608			break;
1609		default:
1610			WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
1611			return -EINVAL;
1612		}
1613		convert_key_from_CPU(&key, &key_le);
1614
1615		brcmf_netdev_wait_pend8021x(ndev);
1616		err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le,
1617				      sizeof(key_le));
1618		if (err) {
1619			WL_ERR("WLC_SET_KEY error (%d)\n", err);
1620			return err;
1621		}
1622	}
1623	return err;
1624}
1625
1626static s32
1627brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
1628		    u8 key_idx, bool pairwise, const u8 *mac_addr,
1629		    struct key_params *params)
1630{
1631	struct brcmf_wsec_key key;
1632	s32 val;
1633	s32 wsec;
1634	s32 err = 0;
1635	u8 keybuf[8];
1636
1637	WL_TRACE("Enter\n");
1638	WL_CONN("key index (%d)\n", key_idx);
1639	if (!check_sys_up(wiphy))
1640		return -EIO;
1641
1642	if (mac_addr) {
1643		WL_TRACE("Exit");
1644		return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
1645	}
1646	memset(&key, 0, sizeof(key));
1647
1648	key.len = (u32) params->key_len;
1649	key.index = (u32) key_idx;
1650
1651	if (key.len > sizeof(key.data)) {
1652		WL_ERR("Too long key length (%u)\n", key.len);
1653		err = -EINVAL;
1654		goto done;
1655	}
1656	memcpy(key.data, params->key, key.len);
1657
1658	key.flags = BRCMF_PRIMARY_KEY;
1659	switch (params->cipher) {
1660	case WLAN_CIPHER_SUITE_WEP40:
1661		key.algo = CRYPTO_ALGO_WEP1;
1662		WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1663		break;
1664	case WLAN_CIPHER_SUITE_WEP104:
1665		key.algo = CRYPTO_ALGO_WEP128;
1666		WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1667		break;
1668	case WLAN_CIPHER_SUITE_TKIP:
1669		memcpy(keybuf, &key.data[24], sizeof(keybuf));
1670		memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1671		memcpy(&key.data[16], keybuf, sizeof(keybuf));
1672		key.algo = CRYPTO_ALGO_TKIP;
1673		WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1674		break;
1675	case WLAN_CIPHER_SUITE_AES_CMAC:
1676		key.algo = CRYPTO_ALGO_AES_CCM;
1677		WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1678		break;
1679	case WLAN_CIPHER_SUITE_CCMP:
1680		key.algo = CRYPTO_ALGO_AES_CCM;
1681		WL_CONN("WLAN_CIPHER_SUITE_CCMP\n");
1682		break;
1683	default:
1684		WL_ERR("Invalid cipher (0x%x)\n", params->cipher);
1685		err = -EINVAL;
1686		goto done;
1687	}
1688
1689	err = send_key_to_dongle(ndev, &key); /* Set the new key/index */
1690	if (err)
1691		goto done;
1692
1693	val = WEP_ENABLED;
1694	err = brcmf_dev_intvar_get(ndev, "wsec", &wsec);
1695	if (err) {
1696		WL_ERR("get wsec error (%d)\n", err);
1697		goto done;
1698	}
1699	wsec &= ~(WEP_ENABLED);
1700	wsec |= val;
1701	err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
1702	if (err) {
1703		WL_ERR("set wsec error (%d)\n", err);
1704		goto done;
1705	}
1706
1707	val = 1;		/* assume shared key. otherwise 0 */
1708	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val);
1709	if (err)
1710		WL_ERR("WLC_SET_AUTH error (%d)\n", err);
1711done:
1712	WL_TRACE("Exit\n");
1713	return err;
1714}
1715
1716static s32
1717brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
1718		    u8 key_idx, bool pairwise, const u8 *mac_addr)
1719{
1720	struct brcmf_wsec_key key;
1721	s32 err = 0;
1722	s32 val;
1723	s32 wsec;
1724
1725	WL_TRACE("Enter\n");
1726	if (!check_sys_up(wiphy))
1727		return -EIO;
1728
1729	memset(&key, 0, sizeof(key));
1730
1731	key.index = (u32) key_idx;
1732	key.flags = BRCMF_PRIMARY_KEY;
1733	key.algo = CRYPTO_ALGO_OFF;
1734
1735	WL_CONN("key index (%d)\n", key_idx);
1736
1737	/* Set the new key/index */
1738	err = send_key_to_dongle(ndev, &key);
1739	if (err) {
1740		if (err == -EINVAL) {
1741			if (key.index >= DOT11_MAX_DEFAULT_KEYS)
1742				/* we ignore this key index in this case */
1743				WL_ERR("invalid key index (%d)\n", key_idx);
1744		}
1745		/* Ignore this error, may happen during DISASSOC */
1746		err = -EAGAIN;
1747		goto done;
1748	}
1749
1750	val = 0;
1751	err = brcmf_dev_intvar_get(ndev, "wsec", &wsec);
1752	if (err) {
1753		WL_ERR("get wsec error (%d)\n", err);
1754		/* Ignore this error, may happen during DISASSOC */
1755		err = -EAGAIN;
1756		goto done;
1757	}
1758	wsec &= ~(WEP_ENABLED);
1759	wsec |= val;
1760	err = brcmf_dev_intvar_set(ndev, "wsec", wsec);
1761	if (err) {
1762		WL_ERR("set wsec error (%d)\n", err);
1763		/* Ignore this error, may happen during DISASSOC */
1764		err = -EAGAIN;
1765		goto done;
1766	}
1767
1768	val = 0;		/* assume open key. otherwise 1 */
1769	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val);
1770	if (err) {
1771		WL_ERR("WLC_SET_AUTH error (%d)\n", err);
1772		/* Ignore this error, may happen during DISASSOC */
1773		err = -EAGAIN;
1774	}
1775done:
1776	WL_TRACE("Exit\n");
1777	return err;
1778}
1779
1780static s32
1781brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
1782		    u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
1783		    void (*callback) (void *cookie, struct key_params * params))
1784{
1785	struct key_params params;
1786	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1787	struct brcmf_cfg80211_security *sec;
1788	s32 wsec;
1789	s32 err = 0;
1790
1791	WL_TRACE("Enter\n");
1792	WL_CONN("key index (%d)\n", key_idx);
1793	if (!check_sys_up(wiphy))
1794		return -EIO;
1795
1796	memset(&params, 0, sizeof(params));
1797
1798	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec);
1799	if (err) {
1800		WL_ERR("WLC_GET_WSEC error (%d)\n", err);
1801		/* Ignore this error, may happen during DISASSOC */
1802		err = -EAGAIN;
1803		goto done;
1804	}
1805	switch (wsec) {
1806	case WEP_ENABLED:
1807		sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC);
1808		if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
1809			params.cipher = WLAN_CIPHER_SUITE_WEP40;
1810			WL_CONN("WLAN_CIPHER_SUITE_WEP40\n");
1811		} else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
1812			params.cipher = WLAN_CIPHER_SUITE_WEP104;
1813			WL_CONN("WLAN_CIPHER_SUITE_WEP104\n");
1814		}
1815		break;
1816	case TKIP_ENABLED:
1817		params.cipher = WLAN_CIPHER_SUITE_TKIP;
1818		WL_CONN("WLAN_CIPHER_SUITE_TKIP\n");
1819		break;
1820	case AES_ENABLED:
1821		params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
1822		WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n");
1823		break;
1824	default:
1825		WL_ERR("Invalid algo (0x%x)\n", wsec);
1826		err = -EINVAL;
1827		goto done;
1828	}
1829	callback(cookie, &params);
1830
1831done:
1832	WL_TRACE("Exit\n");
1833	return err;
1834}
1835
1836static s32
1837brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
1838				    struct net_device *ndev, u8 key_idx)
1839{
1840	WL_INFO("Not supported\n");
1841
1842	return -EOPNOTSUPP;
1843}
1844
1845static s32
1846brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
1847			u8 *mac, struct station_info *sinfo)
1848{
1849	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1850	struct brcmf_scb_val_le scb_val;
1851	int rssi;
1852	s32 rate;
1853	s32 err = 0;
1854	u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID);
1855
1856	WL_TRACE("Enter\n");
1857	if (!check_sys_up(wiphy))
1858		return -EIO;
1859
1860	if (memcmp(mac, bssid, ETH_ALEN)) {
1861		WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X"
1862			"wl_bssid-%X:%X:%X:%X:%X:%X\n",
1863			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
1864			bssid[0], bssid[1], bssid[2], bssid[3],
1865			bssid[4], bssid[5]);
1866		err = -ENOENT;
1867		goto done;
1868	}
1869
1870	/* Report the current tx rate */
1871	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate);
1872	if (err) {
1873		WL_ERR("Could not get rate (%d)\n", err);
1874	} else {
1875		sinfo->filled |= STATION_INFO_TX_BITRATE;
1876		sinfo->txrate.legacy = rate * 5;
1877		WL_CONN("Rate %d Mbps\n", rate / 2);
1878	}
1879
1880	if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
1881		scb_val.val = cpu_to_le32(0);
1882		err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
1883				      sizeof(struct brcmf_scb_val_le));
1884		if (err)
1885			WL_ERR("Could not get rssi (%d)\n", err);
1886
1887		rssi = le32_to_cpu(scb_val.val);
1888		sinfo->filled |= STATION_INFO_SIGNAL;
1889		sinfo->signal = rssi;
1890		WL_CONN("RSSI %d dBm\n", rssi);
1891	}
1892
1893done:
1894	WL_TRACE("Exit\n");
1895	return err;
1896}
1897
1898static s32
1899brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev,
1900			   bool enabled, s32 timeout)
1901{
1902	s32 pm;
1903	s32 err = 0;
1904	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
1905
1906	WL_TRACE("Enter\n");
1907
1908	/*
1909	 * Powersave enable/disable request is coming from the
1910	 * cfg80211 even before the interface is up. In that
1911	 * scenario, driver will be storing the power save
1912	 * preference in cfg_priv struct to apply this to
1913	 * FW later while initializing the dongle
1914	 */
1915	cfg_priv->pwr_save = enabled;
1916	if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) {
1917
1918		WL_INFO("Device is not ready,"
1919			"storing the value in cfg_priv struct\n");
1920		goto done;
1921	}
1922
1923	pm = enabled ? PM_FAST : PM_OFF;
1924	WL_INFO("power save %s\n", (pm ? "enabled" : "disabled"));
1925
1926	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm);
1927	if (err) {
1928		if (err == -ENODEV)
1929			WL_ERR("net_device is not ready yet\n");
1930		else
1931			WL_ERR("error (%d)\n", err);
1932	}
1933done:
1934	WL_TRACE("Exit\n");
1935	return err;
1936}
1937
1938static s32
1939brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
1940			     const u8 *addr,
1941			     const struct cfg80211_bitrate_mask *mask)
1942{
1943	struct brcm_rateset_le rateset_le;
1944	s32 rate;
1945	s32 val;
1946	s32 err_bg;
1947	s32 err_a;
1948	u32 legacy;
1949	s32 err = 0;
1950
1951	WL_TRACE("Enter\n");
1952	if (!check_sys_up(wiphy))
1953		return -EIO;
1954
1955	/* addr param is always NULL. ignore it */
1956	/* Get current rateset */
1957	err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le,
1958			      sizeof(rateset_le));
1959	if (err) {
1960		WL_ERR("could not get current rateset (%d)\n", err);
1961		goto done;
1962	}
1963
1964	legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF);
1965	if (!legacy)
1966		legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy &
1967			     0xFFFF);
1968
1969	val = wl_g_rates[legacy - 1].bitrate * 100000;
1970
1971	if (val < le32_to_cpu(rateset_le.count))
1972		/* Select rate by rateset index */
1973		rate = rateset_le.rates[val] & 0x7f;
1974	else
1975		/* Specified rate in bps */
1976		rate = val / 500000;
1977
1978	WL_CONN("rate %d mbps\n", rate / 2);
1979
1980	/*
1981	 *
1982	 *      Set rate override,
1983	 *      Since the is a/b/g-blind, both a/bg_rate are enforced.
1984	 */
1985	err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate);
1986	err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate);
1987	if (err_bg && err_a) {
1988		WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a);
1989		err = err_bg | err_a;
1990	}
1991
1992done:
1993	WL_TRACE("Exit\n");
1994	return err;
1995}
1996
1997static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
1998				   struct brcmf_bss_info_le *bi)
1999{
2000	struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2001	struct ieee80211_channel *notify_channel;
2002	struct cfg80211_bss *bss;
2003	struct ieee80211_supported_band *band;
2004	s32 err = 0;
2005	u16 channel;
2006	u32 freq;
2007	u16 notify_capability;
2008	u16 notify_interval;
2009	u8 *notify_ie;
2010	size_t notify_ielen;
2011	s32 notify_signal;
2012
2013	if (le32_to_cpu(bi->length) > WL_BSS_INFO_MAX) {
2014		WL_ERR("Bss info is larger than buffer. Discarding\n");
2015		return 0;
2016	}
2017
2018	channel = bi->ctl_ch ? bi->ctl_ch :
2019				CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2020
2021	if (channel <= CH_MAX_2G_CHANNEL)
2022		band = wiphy->bands[IEEE80211_BAND_2GHZ];
2023	else
2024		band = wiphy->bands[IEEE80211_BAND_5GHZ];
2025
2026	freq = ieee80211_channel_to_frequency(channel, band->band);
2027	notify_channel = ieee80211_get_channel(wiphy, freq);
2028
2029	notify_capability = le16_to_cpu(bi->capability);
2030	notify_interval = le16_to_cpu(bi->beacon_period);
2031	notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2032	notify_ielen = le32_to_cpu(bi->ie_length);
2033	notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2034
2035	WL_CONN("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
2036			bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
2037			bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
2038	WL_CONN("Channel: %d(%d)\n", channel, freq);
2039	WL_CONN("Capability: %X\n", notify_capability);
2040	WL_CONN("Beacon interval: %d\n", notify_interval);
2041	WL_CONN("Signal: %d\n", notify_signal);
2042
2043	bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
2044		0, notify_capability, notify_interval, notify_ie,
2045		notify_ielen, notify_signal, GFP_KERNEL);
2046
2047	if (!bss)
2048		return -ENOMEM;
2049
2050	cfg80211_put_bss(bss);
2051
2052	return err;
2053}
2054
2055static struct brcmf_bss_info_le *
2056next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
2057{
2058	if (bss == NULL)
2059		return list->bss_info_le;
2060	return (struct brcmf_bss_info_le *)((unsigned long)bss +
2061					    le32_to_cpu(bss->length));
2062}
2063
2064static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
2065{
2066	struct brcmf_scan_results *bss_list;
2067	struct brcmf_bss_info_le *bi = NULL;	/* must be initialized */
2068	s32 err = 0;
2069	int i;
2070
2071	bss_list = cfg_priv->bss_list;
2072	if (bss_list->version != BRCMF_BSS_INFO_VERSION) {
2073		WL_ERR("Version %d != WL_BSS_INFO_VERSION\n",
2074		       bss_list->version);
2075		return -EOPNOTSUPP;
2076	}
2077	WL_SCAN("scanned AP count (%d)\n", bss_list->count);
2078	for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
2079		bi = next_bss_le(bss_list, bi);
2080		err = brcmf_inform_single_bss(cfg_priv, bi);
2081		if (err)
2082			break;
2083	}
2084	return err;
2085}
2086
2087static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
2088			  struct net_device *ndev, const u8 *bssid)
2089{
2090	struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2091	struct ieee80211_channel *notify_channel;
2092	struct brcmf_bss_info_le *bi = NULL;
2093	struct ieee80211_supported_band *band;
2094	struct cfg80211_bss *bss;
2095	u8 *buf = NULL;
2096	s32 err = 0;
2097	u16 channel;
2098	u32 freq;
2099	u16 notify_capability;
2100	u16 notify_interval;
2101	u8 *notify_ie;
2102	size_t notify_ielen;
2103	s32 notify_signal;
2104
2105	WL_TRACE("Enter\n");
2106
2107	buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2108	if (buf == NULL) {
2109		err = -ENOMEM;
2110		goto CleanUp;
2111	}
2112
2113	*(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
2114
2115	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
2116	if (err) {
2117		WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
2118		goto CleanUp;
2119	}
2120
2121	bi = (struct brcmf_bss_info_le *)(buf + 4);
2122
2123	channel = bi->ctl_ch ? bi->ctl_ch :
2124				CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
2125
2126	if (channel <= CH_MAX_2G_CHANNEL)
2127		band = wiphy->bands[IEEE80211_BAND_2GHZ];
2128	else
2129		band = wiphy->bands[IEEE80211_BAND_5GHZ];
2130
2131	freq = ieee80211_channel_to_frequency(channel, band->band);
2132	notify_channel = ieee80211_get_channel(wiphy, freq);
2133
2134	notify_capability = le16_to_cpu(bi->capability);
2135	notify_interval = le16_to_cpu(bi->beacon_period);
2136	notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
2137	notify_ielen = le32_to_cpu(bi->ie_length);
2138	notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
2139
2140	WL_CONN("channel: %d(%d)\n", channel, freq);
2141	WL_CONN("capability: %X\n", notify_capability);
2142	WL_CONN("beacon interval: %d\n", notify_interval);
2143	WL_CONN("signal: %d\n", notify_signal);
2144
2145	bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
2146		0, notify_capability, notify_interval,
2147		notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
2148
2149	if (!bss) {
2150		err = -ENOMEM;
2151		goto CleanUp;
2152	}
2153
2154	cfg80211_put_bss(bss);
2155
2156CleanUp:
2157
2158	kfree(buf);
2159
2160	WL_TRACE("Exit\n");
2161
2162	return err;
2163}
2164
2165static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv)
2166{
2167	return cfg_priv->conf->mode == WL_MODE_IBSS;
2168}
2169
2170/*
2171 * Traverse a string of 1-byte tag/1-byte length/variable-length value
2172 * triples, returning a pointer to the substring whose first element
2173 * matches tag
2174 */
2175static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
2176{
2177	struct brcmf_tlv *elt;
2178	int totlen;
2179
2180	elt = (struct brcmf_tlv *) buf;
2181	totlen = buflen;
2182
2183	/* find tagged parameter */
2184	while (totlen >= 2) {
2185		int len = elt->len;
2186
2187		/* validate remaining totlen */
2188		if ((elt->id == key) && (totlen >= (len + 2)))
2189			return elt;
2190
2191		elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2));
2192		totlen -= (len + 2);
2193	}
2194
2195	return NULL;
2196}
2197
2198static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
2199{
2200	struct brcmf_bss_info_le *bi;
2201	struct brcmf_ssid *ssid;
2202	struct brcmf_tlv *tim;
2203	u16 beacon_interval;
2204	u8 dtim_period;
2205	size_t ie_len;
2206	u8 *ie;
2207	s32 err = 0;
2208
2209	WL_TRACE("Enter\n");
2210	if (brcmf_is_ibssmode(cfg_priv))
2211		return err;
2212
2213	ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID);
2214
2215	*(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
2216	err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO,
2217			cfg_priv->extra_buf, WL_EXTRA_BUF_MAX);
2218	if (err) {
2219		WL_ERR("Could not get bss info %d\n", err);
2220		goto update_bss_info_out;
2221	}
2222
2223	bi = (struct brcmf_bss_info_le *)(cfg_priv->extra_buf + 4);
2224	err = brcmf_inform_single_bss(cfg_priv, bi);
2225	if (err)
2226		goto update_bss_info_out;
2227
2228	ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset);
2229	ie_len = le32_to_cpu(bi->ie_length);
2230	beacon_interval = le16_to_cpu(bi->beacon_period);
2231
2232	tim = brcmf_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
2233	if (tim)
2234		dtim_period = tim->data[1];
2235	else {
2236		/*
2237		* active scan was done so we could not get dtim
2238		* information out of probe response.
2239		* so we speficially query dtim information to dongle.
2240		*/
2241		u32 var;
2242		err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv),
2243					   "dtim_assoc", &var);
2244		if (err) {
2245			WL_ERR("wl dtim_assoc failed (%d)\n", err);
2246			goto update_bss_info_out;
2247		}
2248		dtim_period = (u8)var;
2249	}
2250
2251	brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT);
2252	brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
2253
2254update_bss_info_out:
2255	WL_TRACE("Exit");
2256	return err;
2257}
2258
2259static void brcmf_term_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2260{
2261	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2262	struct brcmf_ssid ssid;
2263
2264	if (cfg_priv->iscan_on) {
2265		iscan->state = WL_ISCAN_STATE_IDLE;
2266
2267		if (iscan->timer_on) {
2268			del_timer_sync(&iscan->timer);
2269			iscan->timer_on = 0;
2270		}
2271
2272		cancel_work_sync(&iscan->work);
2273
2274		/* Abort iscan running in FW */
2275		memset(&ssid, 0, sizeof(ssid));
2276		brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT);
2277	}
2278}
2279
2280static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan,
2281					bool aborted)
2282{
2283	struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2284	struct net_device *ndev = cfg_to_ndev(cfg_priv);
2285
2286	if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
2287		WL_ERR("Scan complete while device not scanning\n");
2288		return;
2289	}
2290	if (cfg_priv->scan_request) {
2291		WL_SCAN("ISCAN Completed scan: %s\n",
2292				aborted ? "Aborted" : "Done");
2293		cfg80211_scan_done(cfg_priv->scan_request, aborted);
2294		brcmf_set_mpc(ndev, 1);
2295		cfg_priv->scan_request = NULL;
2296	}
2297	cfg_priv->iscan_kickstart = false;
2298}
2299
2300static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan)
2301{
2302	if (iscan->state != WL_ISCAN_STATE_IDLE) {
2303		WL_SCAN("wake up iscan\n");
2304		schedule_work(&iscan->work);
2305		return 0;
2306	}
2307
2308	return -EIO;
2309}
2310
2311static s32
2312brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status,
2313		     struct brcmf_scan_results **bss_list)
2314{
2315	struct brcmf_iscan_results list;
2316	struct brcmf_scan_results *results;
2317	struct brcmf_scan_results_le *results_le;
2318	struct brcmf_iscan_results *list_buf;
2319	s32 err = 0;
2320
2321	memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
2322	list_buf = (struct brcmf_iscan_results *)iscan->scan_buf;
2323	results = &list_buf->results;
2324	results_le = &list_buf->results_le;
2325	results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE;
2326	results->version = 0;
2327	results->count = 0;
2328
2329	memset(&list, 0, sizeof(list));
2330	list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
2331	err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list,
2332				     BRCMF_ISCAN_RESULTS_FIXED_SIZE,
2333				     iscan->scan_buf, WL_ISCAN_BUF_MAX);
2334	if (err) {
2335		WL_ERR("error (%d)\n", err);
2336		return err;
2337	}
2338	results->buflen = le32_to_cpu(results_le->buflen);
2339	results->version = le32_to_cpu(results_le->version);
2340	results->count = le32_to_cpu(results_le->count);
2341	WL_SCAN("results->count = %d\n", results_le->count);
2342	WL_SCAN("results->buflen = %d\n", results_le->buflen);
2343	*status = le32_to_cpu(list_buf->status_le);
2344	WL_SCAN("status = %d\n", *status);
2345	*bss_list = results;
2346
2347	return err;
2348}
2349
2350static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv)
2351{
2352	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2353	s32 err = 0;
2354
2355	iscan->state = WL_ISCAN_STATE_IDLE;
2356	brcmf_inform_bss(cfg_priv);
2357	brcmf_notify_iscan_complete(iscan, false);
2358
2359	return err;
2360}
2361
2362static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv)
2363{
2364	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2365	s32 err = 0;
2366
2367	/* Reschedule the timer */
2368	mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2369	iscan->timer_on = 1;
2370
2371	return err;
2372}
2373
2374static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv)
2375{
2376	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2377	s32 err = 0;
2378
2379	brcmf_inform_bss(cfg_priv);
2380	brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE);
2381	/* Reschedule the timer */
2382	mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2383	iscan->timer_on = 1;
2384
2385	return err;
2386}
2387
2388static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv)
2389{
2390	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan;
2391	s32 err = 0;
2392
2393	iscan->state = WL_ISCAN_STATE_IDLE;
2394	brcmf_notify_iscan_complete(iscan, true);
2395
2396	return err;
2397}
2398
2399static void brcmf_cfg80211_iscan_handler(struct work_struct *work)
2400{
2401	struct brcmf_cfg80211_iscan_ctrl *iscan =
2402			container_of(work, struct brcmf_cfg80211_iscan_ctrl,
2403				     work);
2404	struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan);
2405	struct brcmf_cfg80211_iscan_eloop *el = &iscan->el;
2406	u32 status = BRCMF_SCAN_RESULTS_PARTIAL;
2407
2408	if (iscan->timer_on) {
2409		del_timer_sync(&iscan->timer);
2410		iscan->timer_on = 0;
2411	}
2412
2413	if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) {
2414		status = BRCMF_SCAN_RESULTS_ABORTED;
2415		WL_ERR("Abort iscan\n");
2416	}
2417
2418	el->handler[status](cfg_priv);
2419}
2420
2421static void brcmf_iscan_timer(unsigned long data)
2422{
2423	struct brcmf_cfg80211_iscan_ctrl *iscan =
2424			(struct brcmf_cfg80211_iscan_ctrl *)data;
2425
2426	if (iscan) {
2427		iscan->timer_on = 0;
2428		WL_SCAN("timer expired\n");
2429		brcmf_wakeup_iscan(iscan);
2430	}
2431}
2432
2433static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2434{
2435	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2436
2437	if (cfg_priv->iscan_on) {
2438		iscan->state = WL_ISCAN_STATE_IDLE;
2439		INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler);
2440	}
2441
2442	return 0;
2443}
2444
2445static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el)
2446{
2447	memset(el, 0, sizeof(*el));
2448	el->handler[BRCMF_SCAN_RESULTS_SUCCESS] = brcmf_iscan_done;
2449	el->handler[BRCMF_SCAN_RESULTS_PARTIAL] = brcmf_iscan_inprogress;
2450	el->handler[BRCMF_SCAN_RESULTS_PENDING] = brcmf_iscan_pending;
2451	el->handler[BRCMF_SCAN_RESULTS_ABORTED] = brcmf_iscan_aborted;
2452	el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted;
2453}
2454
2455static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv)
2456{
2457	struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv);
2458	int err = 0;
2459
2460	if (cfg_priv->iscan_on) {
2461		iscan->ndev = cfg_to_ndev(cfg_priv);
2462		brcmf_init_iscan_eloop(&iscan->el);
2463		iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
2464		init_timer(&iscan->timer);
2465		iscan->timer.data = (unsigned long) iscan;
2466		iscan->timer.function = brcmf_iscan_timer;
2467		err = brcmf_invoke_iscan(cfg_priv);
2468		if (!err)
2469			iscan->data = cfg_priv;
2470	}
2471
2472	return err;
2473}
2474
2475static __always_inline void brcmf_delay(u32 ms)
2476{
2477	if (ms < 1000 / HZ) {
2478		cond_resched();
2479		mdelay(ms);
2480	} else {
2481		msleep(ms);
2482	}
2483}
2484
2485static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
2486{
2487	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2488
2489	/*
2490	 * Check for WL_STATUS_READY before any function call which
2491	 * could result is bus access. Don't block the resume for
2492	 * any driver error conditions
2493	 */
2494	WL_TRACE("Enter\n");
2495
2496	if (test_bit(WL_STATUS_READY, &cfg_priv->status))
2497		brcmf_invoke_iscan(wiphy_to_cfg(wiphy));
2498
2499	WL_TRACE("Exit\n");
2500	return 0;
2501}
2502
2503static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,
2504				  struct cfg80211_wowlan *wow)
2505{
2506	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2507	struct net_device *ndev = cfg_to_ndev(cfg_priv);
2508
2509	WL_TRACE("Enter\n");
2510
2511	/*
2512	 * Check for WL_STATUS_READY before any function call which
2513	 * could result is bus access. Don't block the suspend for
2514	 * any driver error conditions
2515	 */
2516
2517	/*
2518	 * While going to suspend if associated with AP disassociate
2519	 * from AP to save power while system is in suspended state
2520	 */
2521	if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
2522	     test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
2523	     test_bit(WL_STATUS_READY, &cfg_priv->status)) {
2524		WL_INFO("Disassociating from AP"
2525			" while entering suspend state\n");
2526		brcmf_link_down(cfg_priv);
2527
2528		/*
2529		 * Make sure WPA_Supplicant receives all the event
2530		 * generated due to DISASSOC call to the fw to keep
2531		 * the state fw and WPA_Supplicant state consistent
2532		 */
2533		brcmf_delay(500);
2534	}
2535
2536	set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
2537	if (test_bit(WL_STATUS_READY, &cfg_priv->status))
2538		brcmf_term_iscan(cfg_priv);
2539
2540	if (cfg_priv->scan_request) {
2541		/* Indidate scan abort to cfg80211 layer */
2542		WL_INFO("Terminating scan in progress\n");
2543		cfg80211_scan_done(cfg_priv->scan_request, true);
2544		cfg_priv->scan_request = NULL;
2545	}
2546	clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
2547	clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
2548
2549	/* Turn off watchdog timer */
2550	if (test_bit(WL_STATUS_READY, &cfg_priv->status)) {
2551		WL_INFO("Enable MPC\n");
2552		brcmf_set_mpc(ndev, 1);
2553	}
2554
2555	WL_TRACE("Exit\n");
2556
2557	return 0;
2558}
2559
2560static __used s32
2561brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len)
2562{
2563	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
2564	u32 buflen;
2565
2566	buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf,
2567			       WL_DCMD_LEN_MAX);
2568	BUG_ON(!buflen);
2569
2570	return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf,
2571			       buflen);
2572}
2573
2574static s32
2575brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf,
2576		  s32 buf_len)
2577{
2578	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
2579	u32 len;
2580	s32 err = 0;
2581
2582	len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf,
2583			    WL_DCMD_LEN_MAX);
2584	BUG_ON(!len);
2585	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf,
2586			      WL_DCMD_LEN_MAX);
2587	if (err) {
2588		WL_ERR("error (%d)\n", err);
2589		return err;
2590	}
2591	memcpy(buf, cfg_priv->dcmd_buf, buf_len);
2592
2593	return err;
2594}
2595
2596static __used s32
2597brcmf_update_pmklist(struct net_device *ndev,
2598		     struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
2599{
2600	int i, j;
2601	int pmkid_len;
2602
2603	pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
2604
2605	WL_CONN("No of elements %d\n", pmkid_len);
2606	for (i = 0; i < pmkid_len; i++) {
2607		WL_CONN("PMKID[%d]: %pM =\n", i,
2608			&pmk_list->pmkids.pmkid[i].BSSID);
2609		for (j = 0; j < WLAN_PMKID_LEN; j++)
2610			WL_CONN("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
2611	}
2612
2613	if (!err)
2614		brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list,
2615					sizeof(*pmk_list));
2616
2617	return err;
2618}
2619
2620static s32
2621brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2622			 struct cfg80211_pmksa *pmksa)
2623{
2624	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2625	struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids;
2626	s32 err = 0;
2627	int i;
2628	int pmkid_len;
2629
2630	WL_TRACE("Enter\n");
2631	if (!check_sys_up(wiphy))
2632		return -EIO;
2633
2634	pmkid_len = le32_to_cpu(pmkids->npmkid);
2635	for (i = 0; i < pmkid_len; i++)
2636		if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
2637			break;
2638	if (i < WL_NUM_PMKIDS_MAX) {
2639		memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
2640		memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2641		if (i == pmkid_len) {
2642			pmkid_len++;
2643			pmkids->npmkid = cpu_to_le32(pmkid_len);
2644		}
2645	} else
2646		err = -EINVAL;
2647
2648	WL_CONN("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
2649		pmkids->pmkid[pmkid_len].BSSID);
2650	for (i = 0; i < WLAN_PMKID_LEN; i++)
2651		WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
2652
2653	err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2654
2655	WL_TRACE("Exit\n");
2656	return err;
2657}
2658
2659static s32
2660brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
2661		      struct cfg80211_pmksa *pmksa)
2662{
2663	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2664	struct pmkid_list pmkid;
2665	s32 err = 0;
2666	int i, pmkid_len;
2667
2668	WL_TRACE("Enter\n");
2669	if (!check_sys_up(wiphy))
2670		return -EIO;
2671
2672	memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
2673	memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
2674
2675	WL_CONN("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
2676	       &pmkid.pmkid[0].BSSID);
2677	for (i = 0; i < WLAN_PMKID_LEN; i++)
2678		WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]);
2679
2680	pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid);
2681	for (i = 0; i < pmkid_len; i++)
2682		if (!memcmp
2683		    (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
2684		     ETH_ALEN))
2685			break;
2686
2687	if ((pmkid_len > 0)
2688	    && (i < pmkid_len)) {
2689		memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0,
2690		       sizeof(struct pmkid));
2691		for (; i < (pmkid_len - 1); i++) {
2692			memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID,
2693			       &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID,
2694			       ETH_ALEN);
2695			memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID,
2696			       &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID,
2697			       WLAN_PMKID_LEN);
2698		}
2699		cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
2700	} else
2701		err = -EINVAL;
2702
2703	err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2704
2705	WL_TRACE("Exit\n");
2706	return err;
2707
2708}
2709
2710static s32
2711brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
2712{
2713	struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy);
2714	s32 err = 0;
2715
2716	WL_TRACE("Enter\n");
2717	if (!check_sys_up(wiphy))
2718		return -EIO;
2719
2720	memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list));
2721	err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err);
2722
2723	WL_TRACE("Exit\n");
2724	return err;
2725
2726}
2727
2728static struct cfg80211_ops wl_cfg80211_ops = {
2729	.change_virtual_intf = brcmf_cfg80211_change_iface,
2730	.scan = brcmf_cfg80211_scan,
2731	.set_wiphy_params = brcmf_cfg80211_set_wiphy_params,
2732	.join_ibss = brcmf_cfg80211_join_ibss,
2733	.leave_ibss = brcmf_cfg80211_leave_ibss,
2734	.get_station = brcmf_cfg80211_get_station,
2735	.set_tx_power = brcmf_cfg80211_set_tx_power,
2736	.get_tx_power = brcmf_cfg80211_get_tx_power,
2737	.add_key = brcmf_cfg80211_add_key,
2738	.del_key = brcmf_cfg80211_del_key,
2739	.get_key = brcmf_cfg80211_get_key,
2740	.set_default_key = brcmf_cfg80211_config_default_key,
2741	.set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
2742	.set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
2743	.set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
2744	.connect = brcmf_cfg80211_connect,
2745	.disconnect = brcmf_cfg80211_disconnect,
2746	.suspend = brcmf_cfg80211_suspend,
2747	.resume = brcmf_cfg80211_resume,
2748	.set_pmksa = brcmf_cfg80211_set_pmksa,
2749	.del_pmksa = brcmf_cfg80211_del_pmksa,
2750	.flush_pmksa = brcmf_cfg80211_flush_pmksa
2751};
2752
2753static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
2754{
2755	s32 err = 0;
2756
2757	switch (mode) {
2758	case WL_MODE_BSS:
2759		return NL80211_IFTYPE_STATION;
2760	case WL_MODE_IBSS:
2761		return NL80211_IFTYPE_ADHOC;
2762	default:
2763		return NL80211_IFTYPE_UNSPECIFIED;
2764	}
2765
2766	return err;
2767}
2768
2769static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface,
2770					  struct device *ndev)
2771{
2772	struct wireless_dev *wdev;
2773	s32 err = 0;
2774
2775	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2776	if (!wdev)
2777		return ERR_PTR(-ENOMEM);
2778
2779	wdev->wiphy =
2780	    wiphy_new(&wl_cfg80211_ops,
2781		      sizeof(struct brcmf_cfg80211_priv) + sizeof_iface);
2782	if (!wdev->wiphy) {
2783		WL_ERR("Could not allocate wiphy device\n");
2784		err = -ENOMEM;
2785		goto wiphy_new_out;
2786	}
2787	set_wiphy_dev(wdev->wiphy, ndev);
2788	wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
2789	wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
2790	wdev->wiphy->interface_modes =
2791	    BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
2792	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
2793	wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;	/* Set
2794						* it as 11a by default.
2795						* This will be updated with
2796						* 11n phy tables in
2797						* "ifconfig up"
2798						* if phy has 11n capability
2799						*/
2800	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2801	wdev->wiphy->cipher_suites = __wl_cipher_suites;
2802	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
2803	wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;	/* enable power
2804								 * save mode
2805								 * by default
2806								 */
2807	err = wiphy_register(wdev->wiphy);
2808	if (err < 0) {
2809		WL_ERR("Could not register wiphy device (%d)\n", err);
2810		goto wiphy_register_out;
2811	}
2812	return wdev;
2813
2814wiphy_register_out:
2815	wiphy_free(wdev->wiphy);
2816
2817wiphy_new_out:
2818	kfree(wdev);
2819
2820	return ERR_PTR(err);
2821}
2822
2823static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv)
2824{
2825	struct wireless_dev *wdev = cfg_priv->wdev;
2826
2827	if (!wdev) {
2828		WL_ERR("wdev is invalid\n");
2829		return;
2830	}
2831	wiphy_unregister(wdev->wiphy);
2832	wiphy_free(wdev->wiphy);
2833	kfree(wdev);
2834	cfg_priv->wdev = NULL;
2835}
2836
2837static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv,
2838			    const struct brcmf_event_msg *e)
2839{
2840	u32 event = be32_to_cpu(e->event_type);
2841	u32 status = be32_to_cpu(e->status);
2842
2843	if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
2844		WL_CONN("Processing set ssid\n");
2845		cfg_priv->link_up = true;
2846		return true;
2847	}
2848
2849	return false;
2850}
2851
2852static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv,
2853			      const struct brcmf_event_msg *e)
2854{
2855	u32 event = be32_to_cpu(e->event_type);
2856	u16 flags = be16_to_cpu(e->flags);
2857
2858	if (event == BRCMF_E_LINK && (!(flags & BRCMF_EVENT_MSG_LINK))) {
2859		WL_CONN("Processing link down\n");
2860		return true;
2861	}
2862	return false;
2863}
2864
2865static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv,
2866			       const struct brcmf_event_msg *e)
2867{
2868	u32 event = be32_to_cpu(e->event_type);
2869	u32 status = be32_to_cpu(e->status);
2870
2871	if (event == BRCMF_E_LINK && status == BRCMF_E_STATUS_NO_NETWORKS) {
2872		WL_CONN("Processing Link %s & no network found\n",
2873				be16_to_cpu(e->flags) & BRCMF_EVENT_MSG_LINK ?
2874				"up" : "down");
2875		return true;
2876	}
2877
2878	if (event == BRCMF_E_SET_SSID && status != BRCMF_E_STATUS_SUCCESS) {
2879		WL_CONN("Processing connecting & no network found\n");
2880		return true;
2881	}
2882
2883	return false;
2884}
2885
2886static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
2887{
2888	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2889
2890	kfree(conn_info->req_ie);
2891	conn_info->req_ie = NULL;
2892	conn_info->req_ie_len = 0;
2893	kfree(conn_info->resp_ie);
2894	conn_info->resp_ie = NULL;
2895	conn_info->resp_ie_len = 0;
2896}
2897
2898static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv)
2899{
2900	struct net_device *ndev = cfg_to_ndev(cfg_priv);
2901	struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
2902	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2903	u32 req_len;
2904	u32 resp_len;
2905	s32 err = 0;
2906
2907	brcmf_clear_assoc_ies(cfg_priv);
2908
2909	err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf,
2910				WL_ASSOC_INFO_MAX);
2911	if (err) {
2912		WL_ERR("could not get assoc info (%d)\n", err);
2913		return err;
2914	}
2915	assoc_info =
2916		(struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf;
2917	req_len = le32_to_cpu(assoc_info->req_len);
2918	resp_len = le32_to_cpu(assoc_info->resp_len);
2919	if (req_len) {
2920		err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies",
2921					   cfg_priv->extra_buf,
2922					   WL_ASSOC_INFO_MAX);
2923		if (err) {
2924			WL_ERR("could not get assoc req (%d)\n", err);
2925			return err;
2926		}
2927		conn_info->req_ie_len = req_len;
2928		conn_info->req_ie =
2929		    kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len,
2930			    GFP_KERNEL);
2931	} else {
2932		conn_info->req_ie_len = 0;
2933		conn_info->req_ie = NULL;
2934	}
2935	if (resp_len) {
2936		err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies",
2937					   cfg_priv->extra_buf,
2938					   WL_ASSOC_INFO_MAX);
2939		if (err) {
2940			WL_ERR("could not get assoc resp (%d)\n", err);
2941			return err;
2942		}
2943		conn_info->resp_ie_len = resp_len;
2944		conn_info->resp_ie =
2945		    kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len,
2946			    GFP_KERNEL);
2947	} else {
2948		conn_info->resp_ie_len = 0;
2949		conn_info->resp_ie = NULL;
2950	}
2951	WL_CONN("req len (%d) resp len (%d)\n",
2952	       conn_info->req_ie_len, conn_info->resp_ie_len);
2953
2954	return err;
2955}
2956
2957static s32
2958brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv,
2959		       struct net_device *ndev,
2960		       const struct brcmf_event_msg *e)
2961{
2962	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
2963	struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
2964	struct brcmf_channel_info_le channel_le;
2965	struct ieee80211_channel *notify_channel;
2966	struct ieee80211_supported_band *band;
2967	u32 freq;
2968	s32 err = 0;
2969	u32 target_channel;
2970
2971	WL_TRACE("Enter\n");
2972
2973	brcmf_get_assoc_ies(cfg_priv);
2974	brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID);
2975	brcmf_update_bss_info(cfg_priv);
2976
2977	brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
2978			sizeof(channel_le));
2979
2980	target_channel = le32_to_cpu(channel_le.target_channel);
2981	WL_CONN("Roamed to channel %d\n", target_channel);
2982
2983	if (target_channel <= CH_MAX_2G_CHANNEL)
2984		band = wiphy->bands[IEEE80211_BAND_2GHZ];
2985	else
2986		band = wiphy->bands[IEEE80211_BAND_5GHZ];
2987
2988	freq = ieee80211_channel_to_frequency(target_channel, band->band);
2989	notify_channel = ieee80211_get_channel(wiphy, freq);
2990
2991	cfg80211_roamed(ndev, notify_channel,
2992			(u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID),
2993			conn_info->req_ie, conn_info->req_ie_len,
2994			conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
2995	WL_CONN("Report roaming result\n");
2996
2997	set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
2998	WL_TRACE("Exit\n");
2999	return err;
3000}
3001
3002static s32
3003brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv,
3004		       struct net_device *ndev, const struct brcmf_event_msg *e,
3005		       bool completed)
3006{
3007	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv);
3008	s32 err = 0;
3009
3010	WL_TRACE("Enter\n");
3011
3012	if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) {
3013		if (completed) {
3014			brcmf_get_assoc_ies(cfg_priv);
3015			brcmf_update_prof(cfg_priv, NULL, &e->addr,
3016					  WL_PROF_BSSID);
3017			brcmf_update_bss_info(cfg_priv);
3018		}
3019		cfg80211_connect_result(ndev,
3020					(u8 *)brcmf_read_prof(cfg_priv,
3021							      WL_PROF_BSSID),
3022					conn_info->req_ie,
3023					conn_info->req_ie_len,
3024					conn_info->resp_ie,
3025					conn_info->resp_ie_len,
3026					completed ? WLAN_STATUS_SUCCESS :
3027						    WLAN_STATUS_AUTH_TIMEOUT,
3028					GFP_KERNEL);
3029		if (completed)
3030			set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3031		WL_CONN("Report connect result - connection %s\n",
3032				completed ? "succeeded" : "failed");
3033	}
3034	WL_TRACE("Exit\n");
3035	return err;
3036}
3037
3038static s32
3039brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv,
3040			    struct net_device *ndev,
3041			    const struct brcmf_event_msg *e, void *data)
3042{
3043	s32 err = 0;
3044
3045	if (brcmf_is_linkup(cfg_priv, e)) {
3046		WL_CONN("Linkup\n");
3047		if (brcmf_is_ibssmode(cfg_priv)) {
3048			brcmf_update_prof(cfg_priv, NULL, (void *)e->addr,
3049				WL_PROF_BSSID);
3050			wl_inform_ibss(cfg_priv, ndev, e->addr);
3051			cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
3052			clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3053			set_bit(WL_STATUS_CONNECTED, &cfg_priv->status);
3054		} else
3055			brcmf_bss_connect_done(cfg_priv, ndev, e, true);
3056	} else if (brcmf_is_linkdown(cfg_priv, e)) {
3057		WL_CONN("Linkdown\n");
3058		if (brcmf_is_ibssmode(cfg_priv)) {
3059			clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3060			if (test_and_clear_bit(WL_STATUS_CONNECTED,
3061				&cfg_priv->status))
3062				brcmf_link_down(cfg_priv);
3063		} else {
3064			brcmf_bss_connect_done(cfg_priv, ndev, e, false);
3065			if (test_and_clear_bit(WL_STATUS_CONNECTED,
3066				&cfg_priv->status)) {
3067				cfg80211_disconnected(ndev, 0, NULL, 0,
3068					GFP_KERNEL);
3069				brcmf_link_down(cfg_priv);
3070			}
3071		}
3072		brcmf_init_prof(cfg_priv->profile);
3073	} else if (brcmf_is_nonetwork(cfg_priv, e)) {
3074		if (brcmf_is_ibssmode(cfg_priv))
3075			clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
3076		else
3077			brcmf_bss_connect_done(cfg_priv, ndev, e, false);
3078	}
3079
3080	return err;
3081}
3082
3083static s32
3084brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv,
3085			    struct net_device *ndev,
3086			    const struct brcmf_event_msg *e, void *data)
3087{
3088	s32 err = 0;
3089	u32 event = be32_to_cpu(e->event_type);
3090	u32 status = be32_to_cpu(e->status);
3091
3092	if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) {
3093		if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status))
3094			brcmf_bss_roaming_done(cfg_priv, ndev, e);
3095		else
3096			brcmf_bss_connect_done(cfg_priv, ndev, e, true);
3097	}
3098
3099	return err;
3100}
3101
3102static s32
3103brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv,
3104			struct net_device *ndev,
3105			const struct brcmf_event_msg *e, void *data)
3106{
3107	u16 flags = be16_to_cpu(e->flags);
3108	enum nl80211_key_type key_type;
3109
3110	if (flags & BRCMF_EVENT_MSG_GROUP)
3111		key_type = NL80211_KEYTYPE_GROUP;
3112	else
3113		key_type = NL80211_KEYTYPE_PAIRWISE;
3114
3115	cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
3116				     NULL, GFP_KERNEL);
3117
3118	return 0;
3119}
3120
3121static s32
3122brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv,
3123			 struct net_device *ndev,
3124			 const struct brcmf_event_msg *e, void *data)
3125{
3126	struct brcmf_channel_info_le channel_inform_le;
3127	struct brcmf_scan_results_le *bss_list_le;
3128	u32 len = WL_SCAN_BUF_MAX;
3129	s32 err = 0;
3130	bool scan_abort = false;
3131	u32 scan_channel;
3132
3133	WL_TRACE("Enter\n");
3134
3135	if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) {
3136		WL_TRACE("Exit\n");
3137		return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv));
3138	}
3139
3140	if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) {
3141		WL_ERR("Scan complete while device not scanning\n");
3142		scan_abort = true;
3143		err = -EINVAL;
3144		goto scan_done_out;
3145	}
3146
3147	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le,
3148			      sizeof(channel_inform_le));
3149	if (err) {
3150		WL_ERR("scan busy (%d)\n", err);
3151		scan_abort = true;
3152		goto scan_done_out;
3153	}
3154	scan_channel = le32_to_cpu(channel_inform_le.scan_channel);
3155	if (scan_channel)
3156		WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel);
3157	cfg_priv->bss_list = cfg_priv->scan_results;
3158	bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list;
3159
3160	memset(cfg_priv->scan_results, 0, len);
3161	bss_list_le->buflen = cpu_to_le32(len);
3162	err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS,
3163			      cfg_priv->scan_results, len);
3164	if (err) {
3165		WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
3166		err = -EINVAL;
3167		scan_abort = true;
3168		goto scan_done_out;
3169	}
3170	cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen);
3171	cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version);
3172	cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count);
3173
3174	err = brcmf_inform_bss(cfg_priv);
3175	if (err) {
3176		scan_abort = true;
3177		goto scan_done_out;
3178	}
3179
3180scan_done_out:
3181	if (cfg_priv->scan_request) {
3182		WL_SCAN("calling cfg80211_scan_done\n");
3183		cfg80211_scan_done(cfg_priv->scan_request, scan_abort);
3184		brcmf_set_mpc(ndev, 1);
3185		cfg_priv->scan_request = NULL;
3186	}
3187
3188	WL_TRACE("Exit\n");
3189
3190	return err;
3191}
3192
3193static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
3194{
3195	conf->mode = (u32)-1;
3196	conf->frag_threshold = (u32)-1;
3197	conf->rts_threshold = (u32)-1;
3198	conf->retry_short = (u32)-1;
3199	conf->retry_long = (u32)-1;
3200	conf->tx_power = -1;
3201}
3202
3203static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el)
3204{
3205	memset(el, 0, sizeof(*el));
3206	el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status;
3207	el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status;
3208	el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status;
3209	el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status;
3210	el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status;
3211}
3212
3213static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3214{
3215	kfree(cfg_priv->scan_results);
3216	cfg_priv->scan_results = NULL;
3217	kfree(cfg_priv->bss_info);
3218	cfg_priv->bss_info = NULL;
3219	kfree(cfg_priv->conf);
3220	cfg_priv->conf = NULL;
3221	kfree(cfg_priv->profile);
3222	cfg_priv->profile = NULL;
3223	kfree(cfg_priv->scan_req_int);
3224	cfg_priv->scan_req_int = NULL;
3225	kfree(cfg_priv->dcmd_buf);
3226	cfg_priv->dcmd_buf = NULL;
3227	kfree(cfg_priv->extra_buf);
3228	cfg_priv->extra_buf = NULL;
3229	kfree(cfg_priv->iscan);
3230	cfg_priv->iscan = NULL;
3231	kfree(cfg_priv->pmk_list);
3232	cfg_priv->pmk_list = NULL;
3233}
3234
3235static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv)
3236{
3237	cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
3238	if (!cfg_priv->scan_results)
3239		goto init_priv_mem_out;
3240	cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL);
3241	if (!cfg_priv->conf)
3242		goto init_priv_mem_out;
3243	cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL);
3244	if (!cfg_priv->profile)
3245		goto init_priv_mem_out;
3246	cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
3247	if (!cfg_priv->bss_info)
3248		goto init_priv_mem_out;
3249	cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int),
3250					 GFP_KERNEL);
3251	if (!cfg_priv->scan_req_int)
3252		goto init_priv_mem_out;
3253	cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL);
3254	if (!cfg_priv->dcmd_buf)
3255		goto init_priv_mem_out;
3256	cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
3257	if (!cfg_priv->extra_buf)
3258		goto init_priv_mem_out;
3259	cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL);
3260	if (!cfg_priv->iscan)
3261		goto init_priv_mem_out;
3262	cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL);
3263	if (!cfg_priv->pmk_list)
3264		goto init_priv_mem_out;
3265
3266	return 0;
3267
3268init_priv_mem_out:
3269	brcmf_deinit_priv_mem(cfg_priv);
3270
3271	return -ENOMEM;
3272}
3273
3274/*
3275* retrieve first queued event from head
3276*/
3277
3278static struct brcmf_cfg80211_event_q *brcmf_deq_event(
3279	struct brcmf_cfg80211_priv *cfg_priv)
3280{
3281	struct brcmf_cfg80211_event_q *e = NULL;
3282
3283	spin_lock_irq(&cfg_priv->evt_q_lock);
3284	if (!list_empty(&cfg_priv->evt_q_list)) {
3285		e = list_first_entry(&cfg_priv->evt_q_list,
3286				     struct brcmf_cfg80211_event_q, evt_q_list);
3287		list_del(&e->evt_q_list);
3288	}
3289	spin_unlock_irq(&cfg_priv->evt_q_lock);
3290
3291	return e;
3292}
3293
3294/*
3295*	push event to tail of the queue
3296*
3297*	remark: this function may not sleep as it is called in atomic context.
3298*/
3299
3300static s32
3301brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
3302		const struct brcmf_event_msg *msg)
3303{
3304	struct brcmf_cfg80211_event_q *e;
3305	s32 err = 0;
3306	ulong flags;
3307
3308	e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_ATOMIC);
3309	if (!e)
3310		return -ENOMEM;
3311
3312	e->etype = event;
3313	memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
3314
3315	spin_lock_irqsave(&cfg_priv->evt_q_lock, flags);
3316	list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
3317	spin_unlock_irqrestore(&cfg_priv->evt_q_lock, flags);
3318
3319	return err;
3320}
3321
3322static void brcmf_put_event(struct brcmf_cfg80211_event_q *e)
3323{
3324	kfree(e);
3325}
3326
3327static void brcmf_cfg80211_event_handler(struct work_struct *work)
3328{
3329	struct brcmf_cfg80211_priv *cfg_priv =
3330			container_of(work, struct brcmf_cfg80211_priv,
3331				     event_work);
3332	struct brcmf_cfg80211_event_q *e;
3333
3334	e = brcmf_deq_event(cfg_priv);
3335	if (unlikely(!e)) {
3336		WL_ERR("event queue empty...\n");
3337		return;
3338	}
3339
3340	do {
3341		WL_INFO("event type (%d)\n", e->etype);
3342		if (cfg_priv->el.handler[e->etype])
3343			cfg_priv->el.handler[e->etype](cfg_priv,
3344						       cfg_to_ndev(cfg_priv),
3345						       &e->emsg, e->edata);
3346		else
3347			WL_INFO("Unknown Event (%d): ignoring\n", e->etype);
3348		brcmf_put_event(e);
3349	} while ((e = brcmf_deq_event(cfg_priv)));
3350
3351}
3352
3353static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv)
3354{
3355	spin_lock_init(&cfg_priv->evt_q_lock);
3356	INIT_LIST_HEAD(&cfg_priv->evt_q_list);
3357}
3358
3359static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv)
3360{
3361	struct brcmf_cfg80211_event_q *e;
3362
3363	spin_lock_irq(&cfg_priv->evt_q_lock);
3364	while (!list_empty(&cfg_priv->evt_q_list)) {
3365		e = list_first_entry(&cfg_priv->evt_q_list,
3366				     struct brcmf_cfg80211_event_q, evt_q_list);
3367		list_del(&e->evt_q_list);
3368		kfree(e);
3369	}
3370	spin_unlock_irq(&cfg_priv->evt_q_lock);
3371}
3372
3373static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv)
3374{
3375	s32 err = 0;
3376
3377	cfg_priv->scan_request = NULL;
3378	cfg_priv->pwr_save = true;
3379	cfg_priv->iscan_on = true;	/* iscan on & off switch.
3380				 we enable iscan per default */
3381	cfg_priv->roam_on = true;	/* roam on & off switch.
3382				 we enable roam per default */
3383
3384	cfg_priv->iscan_kickstart = false;
3385	cfg_priv->active_scan = true;	/* we do active scan for
3386				 specific scan per default */
3387	cfg_priv->dongle_up = false;	/* dongle is not up yet */
3388	brcmf_init_eq(cfg_priv);
3389	err = brcmf_init_priv_mem(cfg_priv);
3390	if (err)
3391		return err;
3392	INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler);
3393	brcmf_init_eloop_handler(&cfg_priv->el);
3394	mutex_init(&cfg_priv->usr_sync);
3395	err = brcmf_init_iscan(cfg_priv);
3396	if (err)
3397		return err;
3398	brcmf_init_conf(cfg_priv->conf);
3399	brcmf_init_prof(cfg_priv->profile);
3400	brcmf_link_down(cfg_priv);
3401
3402	return err;
3403}
3404
3405static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv)
3406{
3407	cancel_work_sync(&cfg_priv->event_work);
3408	cfg_priv->dongle_up = false;	/* dongle down */
3409	brcmf_flush_eq(cfg_priv);
3410	brcmf_link_down(cfg_priv);
3411	brcmf_term_iscan(cfg_priv);
3412	brcmf_deinit_priv_mem(cfg_priv);
3413}
3414
3415struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
3416						 struct device *busdev,
3417						 void *data)
3418{
3419	struct wireless_dev *wdev;
3420	struct brcmf_cfg80211_priv *cfg_priv;
3421	struct brcmf_cfg80211_iface *ci;
3422	struct brcmf_cfg80211_dev *cfg_dev;
3423	s32 err = 0;
3424
3425	if (!ndev) {
3426		WL_ERR("ndev is invalid\n");
3427		return NULL;
3428	}
3429	cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL);
3430	if (!cfg_dev)
3431		return NULL;
3432
3433	wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev);
3434	if (IS_ERR(wdev)) {
3435		kfree(cfg_dev);
3436		return NULL;
3437	}
3438
3439	wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS);
3440	cfg_priv = wdev_to_cfg(wdev);
3441	cfg_priv->wdev = wdev;
3442	cfg_priv->pub = data;
3443	ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci;
3444	ci->cfg_priv = cfg_priv;
3445	ndev->ieee80211_ptr = wdev;
3446	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
3447	wdev->netdev = ndev;
3448	err = wl_init_priv(cfg_priv);
3449	if (err) {
3450		WL_ERR("Failed to init iwm_priv (%d)\n", err);
3451		goto cfg80211_attach_out;
3452	}
3453	brcmf_set_drvdata(cfg_dev, ci);
3454
3455	return cfg_dev;
3456
3457cfg80211_attach_out:
3458	brcmf_free_wdev(cfg_priv);
3459	kfree(cfg_dev);
3460	return NULL;
3461}
3462
3463void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev)
3464{
3465	struct brcmf_cfg80211_priv *cfg_priv;
3466
3467	cfg_priv = brcmf_priv_get(cfg_dev);
3468
3469	wl_deinit_priv(cfg_priv);
3470	brcmf_free_wdev(cfg_priv);
3471	brcmf_set_drvdata(cfg_dev, NULL);
3472	kfree(cfg_dev);
3473}
3474
3475void
3476brcmf_cfg80211_event(struct net_device *ndev,
3477		  const struct brcmf_event_msg *e, void *data)
3478{
3479	u32 event_type = be32_to_cpu(e->event_type);
3480	struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev);
3481
3482	if (!brcmf_enq_event(cfg_priv, event_type, e))
3483		schedule_work(&cfg_priv->event_work);
3484}
3485
3486static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
3487{
3488	s32 infra = 0;
3489	s32 err = 0;
3490
3491	switch (iftype) {
3492	case NL80211_IFTYPE_MONITOR:
3493	case NL80211_IFTYPE_WDS:
3494		WL_ERR("type (%d) : currently we do not support this mode\n",
3495		       iftype);
3496		err = -EINVAL;
3497		return err;
3498	case NL80211_IFTYPE_ADHOC:
3499		infra = 0;
3500		break;
3501	case NL80211_IFTYPE_STATION:
3502		infra = 1;
3503		break;
3504	default:
3505		err = -EINVAL;
3506		WL_ERR("invalid type (%d)\n", iftype);
3507		return err;
3508	}
3509	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
3510	if (err) {
3511		WL_ERR("WLC_SET_INFRA error (%d)\n", err);
3512		return err;
3513	}
3514
3515	return 0;
3516}
3517
3518static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
3519{
3520	/* Room for "event_msgs" + '\0' + bitvec */
3521	s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
3522	s8 eventmask[BRCMF_EVENTING_MASK_LEN];
3523	s32 err = 0;
3524
3525	WL_TRACE("Enter\n");
3526
3527	/* Setup event_msgs */
3528	brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
3529			iovbuf, sizeof(iovbuf));
3530	err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf));
3531	if (err) {
3532		WL_ERR("Get event_msgs error (%d)\n", err);
3533		goto dongle_eventmsg_out;
3534	}
3535	memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
3536
3537	setbit(eventmask, BRCMF_E_SET_SSID);
3538	setbit(eventmask, BRCMF_E_ROAM);
3539	setbit(eventmask, BRCMF_E_PRUNE);
3540	setbit(eventmask, BRCMF_E_AUTH);
3541	setbit(eventmask, BRCMF_E_REASSOC);
3542	setbit(eventmask, BRCMF_E_REASSOC_IND);
3543	setbit(eventmask, BRCMF_E_DEAUTH_IND);
3544	setbit(eventmask, BRCMF_E_DISASSOC_IND);
3545	setbit(eventmask, BRCMF_E_DISASSOC);
3546	setbit(eventmask, BRCMF_E_JOIN);
3547	setbit(eventmask, BRCMF_E_ASSOC_IND);
3548	setbit(eventmask, BRCMF_E_PSK_SUP);
3549	setbit(eventmask, BRCMF_E_LINK);
3550	setbit(eventmask, BRCMF_E_NDIS_LINK);
3551	setbit(eventmask, BRCMF_E_MIC_ERROR);
3552	setbit(eventmask, BRCMF_E_PMKID_CACHE);
3553	setbit(eventmask, BRCMF_E_TXFAIL);
3554	setbit(eventmask, BRCMF_E_JOIN_START);
3555	setbit(eventmask, BRCMF_E_SCAN_COMPLETE);
3556
3557	brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN,
3558			iovbuf, sizeof(iovbuf));
3559	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3560	if (err) {
3561		WL_ERR("Set event_msgs error (%d)\n", err);
3562		goto dongle_eventmsg_out;
3563	}
3564
3565dongle_eventmsg_out:
3566	WL_TRACE("Exit\n");
3567	return err;
3568}
3569
3570static s32
3571brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
3572{
3573	s8 iovbuf[32];
3574	s32 err = 0;
3575	__le32 roamtrigger[2];
3576	__le32 roam_delta[2];
3577	__le32 bcn_to_le;
3578	__le32 roamvar_le;
3579
3580	/*
3581	 * Setup timeout if Beacons are lost and roam is
3582	 * off to report link down
3583	 */
3584	if (roamvar) {
3585		bcn_to_le = cpu_to_le32(bcn_timeout);
3586		brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le,
3587			sizeof(bcn_to_le), iovbuf, sizeof(iovbuf));
3588		err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR,
3589				   iovbuf, sizeof(iovbuf));
3590		if (err) {
3591			WL_ERR("bcn_timeout error (%d)\n", err);
3592			goto dongle_rom_out;
3593		}
3594	}
3595
3596	/*
3597	 * Enable/Disable built-in roaming to allow supplicant
3598	 * to take care of roaming
3599	 */
3600	WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
3601	roamvar_le = cpu_to_le32(roamvar);
3602	brcmf_c_mkiovar("roam_off", (char *)&roamvar_le,
3603				sizeof(roamvar_le), iovbuf, sizeof(iovbuf));
3604	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf));
3605	if (err) {
3606		WL_ERR("roam_off error (%d)\n", err);
3607		goto dongle_rom_out;
3608	}
3609
3610	roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
3611	roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL);
3612	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER,
3613			(void *)roamtrigger, sizeof(roamtrigger));
3614	if (err) {
3615		WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
3616		goto dongle_rom_out;
3617	}
3618
3619	roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
3620	roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL);
3621	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA,
3622				(void *)roam_delta, sizeof(roam_delta));
3623	if (err) {
3624		WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
3625		goto dongle_rom_out;
3626	}
3627
3628dongle_rom_out:
3629	return err;
3630}
3631
3632static s32
3633brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
3634		      s32 scan_unassoc_time, s32 scan_passive_time)
3635{
3636	s32 err = 0;
3637	__le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time);
3638	__le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time);
3639	__le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time);
3640
3641	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME,
3642			   &scan_assoc_tm_le, sizeof(scan_assoc_tm_le));
3643	if (err) {
3644		if (err == -EOPNOTSUPP)
3645			WL_INFO("Scan assoc time is not supported\n");
3646		else
3647			WL_ERR("Scan assoc time error (%d)\n", err);
3648		goto dongle_scantime_out;
3649	}
3650	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME,
3651			   &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le));
3652	if (err) {
3653		if (err == -EOPNOTSUPP)
3654			WL_INFO("Scan unassoc time is not supported\n");
3655		else
3656			WL_ERR("Scan unassoc time error (%d)\n", err);
3657		goto dongle_scantime_out;
3658	}
3659
3660	err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME,
3661			   &scan_passive_tm_le, sizeof(scan_passive_tm_le));
3662	if (err) {
3663		if (err == -EOPNOTSUPP)
3664			WL_INFO("Scan passive time is not supported\n");
3665		else
3666			WL_ERR("Scan passive time error (%d)\n", err);
3667		goto dongle_scantime_out;
3668	}
3669
3670dongle_scantime_out:
3671	return err;
3672}
3673
3674static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv)
3675{
3676	struct wiphy *wiphy;
3677	s32 phy_list;
3678	s8 phy;
3679	s32 err = 0;
3680
3681	err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST,
3682			      &phy_list, sizeof(phy_list));
3683	if (err) {
3684		WL_ERR("error (%d)\n", err);
3685		return err;
3686	}
3687
3688	phy = ((char *)&phy_list)[1];
3689	WL_INFO("%c phy\n", phy);
3690	if (phy == 'n' || phy == 'a') {
3691		wiphy = cfg_to_wiphy(cfg_priv);
3692		wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
3693	}
3694
3695	return err;
3696}
3697
3698static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv)
3699{
3700	return wl_update_wiphybands(cfg_priv);
3701}
3702
3703static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv)
3704{
3705	struct net_device *ndev;
3706	struct wireless_dev *wdev;
3707	s32 power_mode;
3708	s32 err = 0;
3709
3710	if (cfg_priv->dongle_up)
3711		return err;
3712
3713	ndev = cfg_to_ndev(cfg_priv);
3714	wdev = ndev->ieee80211_ptr;
3715
3716	brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
3717			WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
3718
3719	err = brcmf_dongle_eventmsg(ndev);
3720	if (err)
3721		goto default_conf_out;
3722
3723	power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF;
3724	err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode);
3725	if (err)
3726		goto default_conf_out;
3727	WL_INFO("power save set to %s\n",
3728		(power_mode ? "enabled" : "disabled"));
3729
3730	err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1),
3731				WL_BEACON_TIMEOUT);
3732	if (err)
3733		goto default_conf_out;
3734	err = brcmf_dongle_mode(ndev, wdev->iftype);
3735	if (err && err != -EINPROGRESS)
3736		goto default_conf_out;
3737	err = brcmf_dongle_probecap(cfg_priv);
3738	if (err)
3739		goto default_conf_out;
3740
3741	/* -EINPROGRESS: Call commit handler */
3742
3743default_conf_out:
3744
3745	cfg_priv->dongle_up = true;
3746
3747	return err;
3748
3749}
3750
3751static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv)
3752{
3753	char buf[10+IFNAMSIZ];
3754	struct dentry *fd;
3755	s32 err = 0;
3756
3757	sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name);
3758	cfg_priv->debugfsdir = debugfs_create_dir(buf,
3759					cfg_to_wiphy(cfg_priv)->debugfsdir);
3760
3761	fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir,
3762		(u16 *)&cfg_priv->profile->beacon_interval);
3763	if (!fd) {
3764		err = -ENOMEM;
3765		goto err_out;
3766	}
3767
3768	fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir,
3769		(u8 *)&cfg_priv->profile->dtim_period);
3770	if (!fd) {
3771		err = -ENOMEM;
3772		goto err_out;
3773	}
3774
3775err_out:
3776	return err;
3777}
3778
3779static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv)
3780{
3781	debugfs_remove_recursive(cfg_priv->debugfsdir);
3782	cfg_priv->debugfsdir = NULL;
3783}
3784
3785static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv)
3786{
3787	s32 err = 0;
3788
3789	set_bit(WL_STATUS_READY, &cfg_priv->status);
3790
3791	brcmf_debugfs_add_netdev_params(cfg_priv);
3792
3793	err = brcmf_config_dongle(cfg_priv);
3794	if (err)
3795		return err;
3796
3797	brcmf_invoke_iscan(cfg_priv);
3798
3799	return err;
3800}
3801
3802static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv)
3803{
3804	/*
3805	 * While going down, if associated with AP disassociate
3806	 * from AP to save power
3807	 */
3808	if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) ||
3809	     test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) &&
3810	     test_bit(WL_STATUS_READY, &cfg_priv->status)) {
3811		WL_INFO("Disassociating from AP");
3812		brcmf_link_down(cfg_priv);
3813
3814		/* Make sure WPA_Supplicant receives all the event
3815		   generated due to DISASSOC call to the fw to keep
3816		   the state fw and WPA_Supplicant state consistent
3817		 */
3818		brcmf_delay(500);
3819	}
3820
3821	set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3822	brcmf_term_iscan(cfg_priv);
3823	if (cfg_priv->scan_request) {
3824		cfg80211_scan_done(cfg_priv->scan_request, true);
3825		/* May need to perform this to cover rmmod */
3826		/* wl_set_mpc(cfg_to_ndev(wl), 1); */
3827		cfg_priv->scan_request = NULL;
3828	}
3829	clear_bit(WL_STATUS_READY, &cfg_priv->status);
3830	clear_bit(WL_STATUS_SCANNING, &cfg_priv->status);
3831	clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status);
3832
3833	brcmf_debugfs_remove_netdev(cfg_priv);
3834
3835	return 0;
3836}
3837
3838s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev)
3839{
3840	struct brcmf_cfg80211_priv *cfg_priv;
3841	s32 err = 0;
3842
3843	cfg_priv = brcmf_priv_get(cfg_dev);
3844	mutex_lock(&cfg_priv->usr_sync);
3845	err = __brcmf_cfg80211_up(cfg_priv);
3846	mutex_unlock(&cfg_priv->usr_sync);
3847
3848	return err;
3849}
3850
3851s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev)
3852{
3853	struct brcmf_cfg80211_priv *cfg_priv;
3854	s32 err = 0;
3855
3856	cfg_priv = brcmf_priv_get(cfg_dev);
3857	mutex_lock(&cfg_priv->usr_sync);
3858	err = __brcmf_cfg80211_down(cfg_priv);
3859	mutex_unlock(&cfg_priv->usr_sync);
3860
3861	return err;
3862}
3863
3864static __used s32 brcmf_add_ie(struct brcmf_cfg80211_priv *cfg_priv,
3865			       u8 t, u8 l, u8 *v)
3866{
3867	struct brcmf_cfg80211_ie *ie = &cfg_priv->ie;
3868	s32 err = 0;
3869
3870	if (ie->offset + l + 2 > WL_TLV_INFO_MAX) {
3871		WL_ERR("ei crosses buffer boundary\n");
3872		return -ENOSPC;
3873	}
3874	ie->buf[ie->offset] = t;
3875	ie->buf[ie->offset + 1] = l;
3876	memcpy(&ie->buf[ie->offset + 2], v, l);
3877	ie->offset += l + 2;
3878
3879	return err;
3880}
3881