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