[go: nahoru, domu]

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