staging: brcm80211: wl_cfg80211.c: fix 'assignment in if condition'
[deliverable/linux.git] / drivers / staging / brcm80211 / brcmfmac / wl_cfg80211.c
CommitLineData
cf2b4488
HP
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#include <typedefs.h>
18#include <linuxver.h>
19#include <osl.h>
20
21#include <bcmutils.h>
22#include <bcmendian.h>
23#include <proto/ethernet.h>
24
25#include <linux/if_arp.h>
26#include <asm/uaccess.h>
27
28#include <dngl_stats.h>
29#include <dhd.h>
30#include <dhdioctl.h>
31#include <wlioctl.h>
32
33#include <proto/ethernet.h>
34#include <dngl_stats.h>
35#include <dhd.h>
36
37#include <linux/kernel.h>
38#include <linux/netdevice.h>
39#include <linux/sched.h>
40#include <linux/etherdevice.h>
41#include <linux/wireless.h>
42#include <linux/ieee80211.h>
43#include <net/cfg80211.h>
44
45#include <net/rtnetlink.h>
46#include <linux/mmc/sdio_func.h>
47#include <linux/firmware.h>
48#include <wl_cfg80211.h>
49
5f782dee
JC
50static struct sdio_func *cfg80211_sdio_func;
51static struct wl_dev *wl_cfg80211_dev;
cf2b4488
HP
52
53uint32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
54
55#define WL_4329_FW_FILE "brcm/bcm4329-fullmac-4-218-248-5.bin"
56#define WL_4329_NVRAM_FILE "brcm/bcm4329-fullmac-4-218-248-5.txt"
57
58/*
59** cfg80211_ops api/callback list
60*/
61static int32 wl_cfg80211_change_iface(struct wiphy *wiphy,
62 struct net_device *ndev,
63 enum nl80211_iftype type, uint32 *flags,
64 struct vif_params *params);
65static int32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
66 struct cfg80211_scan_request *request,
67 struct cfg80211_ssid *this_ssid);
68static int32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
69 struct cfg80211_scan_request *request);
70static int32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, uint32 changed);
71static int32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
72 struct cfg80211_ibss_params *params);
73static int32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
74 struct net_device *dev);
75static int32 wl_cfg80211_get_station(struct wiphy *wiphy,
3fd79f7c 76 struct net_device *dev, u8 *mac,
cf2b4488
HP
77 struct station_info *sinfo);
78static int32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
79 struct net_device *dev, bool enabled,
80 int32 timeout);
81static int32 wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
82 struct net_device *dev,
3fd79f7c 83 const u8 *addr,
cf2b4488
HP
84 const struct cfg80211_bitrate_mask
85 *mask);
86static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
87 struct cfg80211_connect_params *sme);
88static int32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
89 uint16 reason_code);
90static int32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
91 enum nl80211_tx_power_setting type,
92 int32 dbm);
93static int32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, int32 *dbm);
94static int32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
95 struct net_device *dev,
3fd79f7c 96 u8 key_idx);
cf2b4488 97static int32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 98 u8 key_idx, const u8 *mac_addr,
cf2b4488
HP
99 struct key_params *params);
100static int32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 101 u8 key_idx, const u8 *mac_addr);
cf2b4488 102static int32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 103 u8 key_idx, const u8 *mac_addr,
cf2b4488
HP
104 void *cookie, void (*callback) (void *cookie,
105 struct
106 key_params *
107 params));
108static int32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
109 struct net_device *dev,
3fd79f7c 110 u8 key_idx);
cf2b4488
HP
111static int32 wl_cfg80211_resume(struct wiphy *wiphy);
112static int32 wl_cfg80211_suspend(struct wiphy *wiphy);
113static int32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
114 struct cfg80211_pmksa *pmksa);
115static int32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
116 struct cfg80211_pmksa *pmksa);
117static int32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
118 struct net_device *dev);
119/*
120** event & event Q handlers for cfg80211 interfaces
121*/
122static int32 wl_create_event_handler(struct wl_priv *wl);
123static void wl_destroy_event_handler(struct wl_priv *wl);
124static int32 wl_event_handler(void *data);
125static void wl_init_eq(struct wl_priv *wl);
126static void wl_flush_eq(struct wl_priv *wl);
127static void wl_lock_eq(struct wl_priv *wl);
128static void wl_unlock_eq(struct wl_priv *wl);
129static void wl_init_eq_lock(struct wl_priv *wl);
130static void wl_init_eloop_handler(struct wl_event_loop *el);
131static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
132static int32 wl_enq_event(struct wl_priv *wl, uint32 type,
133 const wl_event_msg_t *msg, void *data);
134static void wl_put_event(struct wl_event_q *e);
135static void wl_wakeup_event(struct wl_priv *wl);
136static int32 wl_notify_connect_status(struct wl_priv *wl,
137 struct net_device *ndev,
138 const wl_event_msg_t *e, void *data);
139static int32 wl_notify_roaming_status(struct wl_priv *wl,
140 struct net_device *ndev,
141 const wl_event_msg_t *e, void *data);
142static int32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
143 const wl_event_msg_t *e, void *data);
144static int32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
b3164c71 145 const wl_event_msg_t *e, void *data,
146 bool completed);
cf2b4488
HP
147static int32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
148 const wl_event_msg_t *e, void *data);
149static int32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
150 const wl_event_msg_t *e, void *data);
151
152/*
153** register/deregister sdio function
154*/
93ad12cf 155struct sdio_func *wl_cfg80211_get_sdio_func(void);
cf2b4488
HP
156static void wl_clear_sdio_func(void);
157
158/*
159** ioctl utilites
160*/
562c8850 161static int32 wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
cf2b4488 162 int32 buf_len);
562c8850
GKH
163static __used int32 wl_dev_bufvar_set(struct net_device *dev, s8 *name,
164 s8 *buf, int32 len);
165static int32 wl_dev_intvar_set(struct net_device *dev, s8 *name, int32 val);
166static int32 wl_dev_intvar_get(struct net_device *dev, s8 *name,
cf2b4488
HP
167 int32 *retval);
168static int32 wl_dev_ioctl(struct net_device *dev, uint32 cmd, void *arg,
169 uint32 len);
170
171/*
172** cfg80211 set_wiphy_params utilities
173*/
174static int32 wl_set_frag(struct net_device *dev, uint32 frag_threshold);
175static int32 wl_set_rts(struct net_device *dev, uint32 frag_threshold);
176static int32 wl_set_retry(struct net_device *dev, uint32 retry, bool l);
177
178/*
179** wl profile utilities
180*/
181static int32 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e,
182 void *data, int32 item);
183static void *wl_read_prof(struct wl_priv *wl, int32 item);
184static void wl_init_prof(struct wl_profile *prof);
185
186/*
187** cfg80211 connect utilites
188*/
189static int32 wl_set_wpa_version(struct net_device *dev,
190 struct cfg80211_connect_params *sme);
191static int32 wl_set_auth_type(struct net_device *dev,
192 struct cfg80211_connect_params *sme);
193static int32 wl_set_set_cipher(struct net_device *dev,
194 struct cfg80211_connect_params *sme);
195static int32 wl_set_key_mgmt(struct net_device *dev,
196 struct cfg80211_connect_params *sme);
197static int32 wl_set_set_sharedkey(struct net_device *dev,
198 struct cfg80211_connect_params *sme);
199static int32 wl_get_assoc_ies(struct wl_priv *wl);
200
201/*
202** information element utilities
203*/
204static void wl_rst_ie(struct wl_priv *wl);
3fd79f7c
GKH
205static int32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
206static int32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, uint16 ie_size);
207static int32 wl_cp_ie(struct wl_priv *wl, u8 *dst, uint16 dst_size);
cf2b4488
HP
208static uint32 wl_get_ielen(struct wl_priv *wl);
209
210static int32 wl_mode_to_nl80211_iftype(int32 mode);
211
212static struct wireless_dev *wl_alloc_wdev(int32 sizeof_iface,
213 struct device *dev);
214static void wl_free_wdev(struct wl_priv *wl);
215
216static int32 wl_inform_bss(struct wl_priv *wl);
217static int32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
218static int32 wl_update_bss_info(struct wl_priv *wl);
219
220static int32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 221 u8 key_idx, const u8 *mac_addr,
cf2b4488
HP
222 struct key_params *params);
223
224/*
225** key indianess swap utilities
226*/
227static void swap_key_from_BE(struct wl_wsec_key *key);
228static void swap_key_to_BE(struct wl_wsec_key *key);
229
230/*
231** wl_priv memory init/deinit utilities
232*/
233static int32 wl_init_priv_mem(struct wl_priv *wl);
234static void wl_deinit_priv_mem(struct wl_priv *wl);
235
236static void wl_delay(uint32 ms);
237
238/*
239** store/restore cfg80211 instance data
240*/
241static void wl_set_drvdata(struct wl_dev *dev, void *data);
242static void *wl_get_drvdata(struct wl_dev *dev);
243
244/*
245** ibss mode utilities
246*/
247static bool wl_is_ibssmode(struct wl_priv *wl);
248static bool wl_is_ibssstarter(struct wl_priv *wl);
249
250/*
251** dongle up/down , default configuration utilities
252*/
253static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
254static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e);
b3164c71 255static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
cf2b4488
HP
256static void wl_link_up(struct wl_priv *wl);
257static void wl_link_down(struct wl_priv *wl);
258static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype);
259static int32 __wl_cfg80211_up(struct wl_priv *wl);
260static int32 __wl_cfg80211_down(struct wl_priv *wl);
261static int32 wl_dongle_probecap(struct wl_priv *wl);
262static void wl_init_conf(struct wl_conf *conf);
263
264/*
265** dongle configuration utilities
266*/
267#ifndef EMBEDDED_PLATFORM
268static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype);
3fd79f7c 269static int32 wl_dongle_country(struct net_device *ndev, u8 ccode);
cf2b4488
HP
270static int32 wl_dongle_up(struct net_device *ndev, uint32 up);
271static int32 wl_dongle_power(struct net_device *ndev, uint32 power_mode);
272static int32 wl_dongle_glom(struct net_device *ndev, uint32 glom,
273 uint32 dongle_align);
274static int32 wl_dongle_roam(struct net_device *ndev, uint32 roamvar,
275 uint32 bcn_timeout);
276static int32 wl_dongle_eventmsg(struct net_device *ndev);
277static int32 wl_dongle_scantime(struct net_device *ndev, int32 scan_assoc_time,
278 int32 scan_unassoc_time);
279static int32 wl_dongle_offload(struct net_device *ndev, int32 arpoe,
280 int32 arp_ol);
562c8850 281static int32 wl_pattern_atoh(s8 *src, s8 *dst);
cf2b4488
HP
282static int32 wl_dongle_filter(struct net_device *ndev, uint32 filter_mode);
283static int32 wl_update_wiphybands(struct wl_priv *wl);
284#endif /* !EMBEDDED_PLATFORM */
285static int32 wl_config_dongle(struct wl_priv *wl, bool need_lock);
286
287/*
288** iscan handler
289*/
3deea904 290static void wl_iscan_timer(unsigned long data);
cf2b4488
HP
291static void wl_term_iscan(struct wl_priv *wl);
292static int32 wl_init_iscan(struct wl_priv *wl);
293static int32 wl_iscan_thread(void *data);
562c8850 294static int32 wl_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
cf2b4488
HP
295 void *param, int32 paramlen, void *bufptr,
296 int32 buflen);
562c8850 297static int32 wl_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
cf2b4488
HP
298 void *param, int32 paramlen, void *bufptr,
299 int32 buflen);
300static int32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid,
301 uint16 action);
302static int32 wl_do_iscan(struct wl_priv *wl);
303static int32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
304static int32 wl_invoke_iscan(struct wl_priv *wl);
305static int32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, uint32 *status,
306 struct wl_scan_results **bss_list);
307static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
308static void wl_init_iscan_eloop(struct wl_iscan_eloop *el);
309static int32 wl_iscan_done(struct wl_priv *wl);
310static int32 wl_iscan_pending(struct wl_priv *wl);
311static int32 wl_iscan_inprogress(struct wl_priv *wl);
312static int32 wl_iscan_aborted(struct wl_priv *wl);
313
314/*
315** fw/nvram downloading handler
316*/
317static void wl_init_fw(struct wl_fw_ctrl *fw);
318
319/*
320* find most significant bit set
321*/
322static __used uint32 wl_find_msb(uint16 bit16);
323
324/*
325* update pmklist to dongle
326*/
327static __used int32 wl_update_pmklist(struct net_device *dev,
328 struct wl_pmk_list *pmk_list, int32 err);
329
330#define WL_PRIV_GET() \
331 ({ \
332 struct wl_iface *ci; \
333 if (unlikely(!(wl_cfg80211_dev && \
334 (ci = wl_get_drvdata(wl_cfg80211_dev))))) { \
335 WL_ERR(("wl_cfg80211_dev is unavailable\n")); \
336 BUG(); \
337 } \
338 ci_to_wl(ci); \
339})
340
341#define CHECK_SYS_UP() \
342do { \
343 struct wl_priv *wl = wiphy_to_wl(wiphy); \
344 if (unlikely(!test_bit(WL_STATUS_READY, &wl->status))) { \
345 WL_INFO(("device is not ready : status (%d)\n", \
346 (int)wl->status)); \
347 return -EIO; \
348 } \
349} while (0)
350
351extern int dhd_wait_pend8021x(struct net_device *dev);
352
353#if (WL_DBG_LEVEL > 0)
354#define WL_DBG_ESTR_MAX 32
562c8850 355static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
cf2b4488
HP
356 "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
357 "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
358 "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
359 "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
360 "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
361 "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
362 "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
363 "PFN_NET_LOST",
364 "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
365 "IBSS_ASSOC",
366 "RADIO", "PSM_WATCHDOG",
367 "PROBREQ_MSG",
368 "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
369 "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
370 "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
371 "IF",
372 "RSSI", "PFN_SCAN_COMPLETE", "ACTION_FRAME", "ACTION_FRAME_COMPLETE",
373};
374#endif /* WL_DBG_LEVEL */
375
376#define CHAN2G(_channel, _freq, _flags) { \
377 .band = IEEE80211_BAND_2GHZ, \
378 .center_freq = (_freq), \
379 .hw_value = (_channel), \
380 .flags = (_flags), \
381 .max_antenna_gain = 0, \
382 .max_power = 30, \
383}
384
385#define CHAN5G(_channel, _flags) { \
386 .band = IEEE80211_BAND_5GHZ, \
387 .center_freq = 5000 + (5 * (_channel)), \
388 .hw_value = (_channel), \
389 .flags = (_flags), \
390 .max_antenna_gain = 0, \
391 .max_power = 30, \
392}
393
394#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
395#define RATETAB_ENT(_rateid, _flags) \
396 { \
397 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
398 .hw_value = (_rateid), \
399 .flags = (_flags), \
400 }
401
402static struct ieee80211_rate __wl_rates[] = {
403 RATETAB_ENT(WLC_RATE_1M, 0),
404 RATETAB_ENT(WLC_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
405 RATETAB_ENT(WLC_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
406 RATETAB_ENT(WLC_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
407 RATETAB_ENT(WLC_RATE_6M, 0),
408 RATETAB_ENT(WLC_RATE_9M, 0),
409 RATETAB_ENT(WLC_RATE_12M, 0),
410 RATETAB_ENT(WLC_RATE_18M, 0),
411 RATETAB_ENT(WLC_RATE_24M, 0),
412 RATETAB_ENT(WLC_RATE_36M, 0),
413 RATETAB_ENT(WLC_RATE_48M, 0),
414 RATETAB_ENT(WLC_RATE_54M, 0),
415};
416
417#define wl_a_rates (__wl_rates + 4)
418#define wl_a_rates_size 8
419#define wl_g_rates (__wl_rates + 0)
420#define wl_g_rates_size 12
421
422static struct ieee80211_channel __wl_2ghz_channels[] = {
423 CHAN2G(1, 2412, 0),
424 CHAN2G(2, 2417, 0),
425 CHAN2G(3, 2422, 0),
426 CHAN2G(4, 2427, 0),
427 CHAN2G(5, 2432, 0),
428 CHAN2G(6, 2437, 0),
429 CHAN2G(7, 2442, 0),
430 CHAN2G(8, 2447, 0),
431 CHAN2G(9, 2452, 0),
432 CHAN2G(10, 2457, 0),
433 CHAN2G(11, 2462, 0),
434 CHAN2G(12, 2467, 0),
435 CHAN2G(13, 2472, 0),
436 CHAN2G(14, 2484, 0),
437};
438
439static struct ieee80211_channel __wl_5ghz_a_channels[] = {
440 CHAN5G(34, 0), CHAN5G(36, 0),
441 CHAN5G(38, 0), CHAN5G(40, 0),
442 CHAN5G(42, 0), CHAN5G(44, 0),
443 CHAN5G(46, 0), CHAN5G(48, 0),
444 CHAN5G(52, 0), CHAN5G(56, 0),
445 CHAN5G(60, 0), CHAN5G(64, 0),
446 CHAN5G(100, 0), CHAN5G(104, 0),
447 CHAN5G(108, 0), CHAN5G(112, 0),
448 CHAN5G(116, 0), CHAN5G(120, 0),
449 CHAN5G(124, 0), CHAN5G(128, 0),
450 CHAN5G(132, 0), CHAN5G(136, 0),
451 CHAN5G(140, 0), CHAN5G(149, 0),
452 CHAN5G(153, 0), CHAN5G(157, 0),
453 CHAN5G(161, 0), CHAN5G(165, 0),
454 CHAN5G(184, 0), CHAN5G(188, 0),
455 CHAN5G(192, 0), CHAN5G(196, 0),
456 CHAN5G(200, 0), CHAN5G(204, 0),
457 CHAN5G(208, 0), CHAN5G(212, 0),
458 CHAN5G(216, 0),
459};
460
461static struct ieee80211_channel __wl_5ghz_n_channels[] = {
462 CHAN5G(32, 0), CHAN5G(34, 0),
463 CHAN5G(36, 0), CHAN5G(38, 0),
464 CHAN5G(40, 0), CHAN5G(42, 0),
465 CHAN5G(44, 0), CHAN5G(46, 0),
466 CHAN5G(48, 0), CHAN5G(50, 0),
467 CHAN5G(52, 0), CHAN5G(54, 0),
468 CHAN5G(56, 0), CHAN5G(58, 0),
469 CHAN5G(60, 0), CHAN5G(62, 0),
470 CHAN5G(64, 0), CHAN5G(66, 0),
471 CHAN5G(68, 0), CHAN5G(70, 0),
472 CHAN5G(72, 0), CHAN5G(74, 0),
473 CHAN5G(76, 0), CHAN5G(78, 0),
474 CHAN5G(80, 0), CHAN5G(82, 0),
475 CHAN5G(84, 0), CHAN5G(86, 0),
476 CHAN5G(88, 0), CHAN5G(90, 0),
477 CHAN5G(92, 0), CHAN5G(94, 0),
478 CHAN5G(96, 0), CHAN5G(98, 0),
479 CHAN5G(100, 0), CHAN5G(102, 0),
480 CHAN5G(104, 0), CHAN5G(106, 0),
481 CHAN5G(108, 0), CHAN5G(110, 0),
482 CHAN5G(112, 0), CHAN5G(114, 0),
483 CHAN5G(116, 0), CHAN5G(118, 0),
484 CHAN5G(120, 0), CHAN5G(122, 0),
485 CHAN5G(124, 0), CHAN5G(126, 0),
486 CHAN5G(128, 0), CHAN5G(130, 0),
487 CHAN5G(132, 0), CHAN5G(134, 0),
488 CHAN5G(136, 0), CHAN5G(138, 0),
489 CHAN5G(140, 0), CHAN5G(142, 0),
490 CHAN5G(144, 0), CHAN5G(145, 0),
491 CHAN5G(146, 0), CHAN5G(147, 0),
492 CHAN5G(148, 0), CHAN5G(149, 0),
493 CHAN5G(150, 0), CHAN5G(151, 0),
494 CHAN5G(152, 0), CHAN5G(153, 0),
495 CHAN5G(154, 0), CHAN5G(155, 0),
496 CHAN5G(156, 0), CHAN5G(157, 0),
497 CHAN5G(158, 0), CHAN5G(159, 0),
498 CHAN5G(160, 0), CHAN5G(161, 0),
499 CHAN5G(162, 0), CHAN5G(163, 0),
500 CHAN5G(164, 0), CHAN5G(165, 0),
501 CHAN5G(166, 0), CHAN5G(168, 0),
502 CHAN5G(170, 0), CHAN5G(172, 0),
503 CHAN5G(174, 0), CHAN5G(176, 0),
504 CHAN5G(178, 0), CHAN5G(180, 0),
505 CHAN5G(182, 0), CHAN5G(184, 0),
506 CHAN5G(186, 0), CHAN5G(188, 0),
507 CHAN5G(190, 0), CHAN5G(192, 0),
508 CHAN5G(194, 0), CHAN5G(196, 0),
509 CHAN5G(198, 0), CHAN5G(200, 0),
510 CHAN5G(202, 0), CHAN5G(204, 0),
511 CHAN5G(206, 0), CHAN5G(208, 0),
512 CHAN5G(210, 0), CHAN5G(212, 0),
513 CHAN5G(214, 0), CHAN5G(216, 0),
514 CHAN5G(218, 0), CHAN5G(220, 0),
515 CHAN5G(222, 0), CHAN5G(224, 0),
516 CHAN5G(226, 0), CHAN5G(228, 0),
517};
518
519static struct ieee80211_supported_band __wl_band_2ghz = {
520 .band = IEEE80211_BAND_2GHZ,
521 .channels = __wl_2ghz_channels,
522 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
523 .bitrates = wl_g_rates,
524 .n_bitrates = wl_g_rates_size,
525};
526
527static struct ieee80211_supported_band __wl_band_5ghz_a = {
528 .band = IEEE80211_BAND_5GHZ,
529 .channels = __wl_5ghz_a_channels,
530 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
531 .bitrates = wl_a_rates,
532 .n_bitrates = wl_a_rates_size,
533};
534
535static struct ieee80211_supported_band __wl_band_5ghz_n = {
536 .band = IEEE80211_BAND_5GHZ,
537 .channels = __wl_5ghz_n_channels,
538 .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
539 .bitrates = wl_a_rates,
540 .n_bitrates = wl_a_rates_size,
541};
542
543static const uint32 __wl_cipher_suites[] = {
544 WLAN_CIPHER_SUITE_WEP40,
545 WLAN_CIPHER_SUITE_WEP104,
546 WLAN_CIPHER_SUITE_TKIP,
547 WLAN_CIPHER_SUITE_CCMP,
548 WLAN_CIPHER_SUITE_AES_CMAC,
549};
550
551static void swap_key_from_BE(struct wl_wsec_key *key)
552{
553 key->index = htod32(key->index);
554 key->len = htod32(key->len);
555 key->algo = htod32(key->algo);
556 key->flags = htod32(key->flags);
557 key->rxiv.hi = htod32(key->rxiv.hi);
558 key->rxiv.lo = htod16(key->rxiv.lo);
559 key->iv_initialized = htod32(key->iv_initialized);
560}
561
562static void swap_key_to_BE(struct wl_wsec_key *key)
563{
564 key->index = dtoh32(key->index);
565 key->len = dtoh32(key->len);
566 key->algo = dtoh32(key->algo);
567 key->flags = dtoh32(key->flags);
568 key->rxiv.hi = dtoh32(key->rxiv.hi);
569 key->rxiv.lo = dtoh16(key->rxiv.lo);
570 key->iv_initialized = dtoh32(key->iv_initialized);
571}
572
573static int32
574wl_dev_ioctl(struct net_device *dev, uint32 cmd, void *arg, uint32 len)
575{
576 struct ifreq ifr;
577 struct wl_ioctl ioc;
578 mm_segment_t fs;
579 int32 err = 0;
580
581 memset(&ioc, 0, sizeof(ioc));
582 ioc.cmd = cmd;
583 ioc.buf = arg;
584 ioc.len = len;
585 strcpy(ifr.ifr_name, dev->name);
586 ifr.ifr_data = (caddr_t)&ioc;
587
588 fs = get_fs();
589 set_fs(get_ds());
590 err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
591 set_fs(fs);
592
593 return err;
594}
595
596static int32
597wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
598 enum nl80211_iftype type, uint32 *flags,
599 struct vif_params *params)
600{
601 struct wl_priv *wl = wiphy_to_wl(wiphy);
602 struct wireless_dev *wdev;
603 int32 infra = 0;
604 int32 ap = 0;
605 int32 err = 0;
606
607 CHECK_SYS_UP();
608 switch (type) {
609 case NL80211_IFTYPE_MONITOR:
610 case NL80211_IFTYPE_WDS:
611 WL_ERR(("type (%d) : currently we do not support this type\n",
612 type));
613 return -EOPNOTSUPP;
614 case NL80211_IFTYPE_ADHOC:
615 wl->conf->mode = WL_MODE_IBSS;
616 break;
617 case NL80211_IFTYPE_STATION:
618 wl->conf->mode = WL_MODE_BSS;
619 infra = 1;
620 break;
621 default:
622 return -EINVAL;
623 }
624 infra = htod32(infra);
625 ap = htod32(ap);
626 wdev = ndev->ieee80211_ptr;
627 wdev->iftype = type;
628 WL_DBG(("%s : ap (%d), infra (%d)\n", ndev->name, ap, infra));
76c06459
JC
629 err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
630 if (unlikely(err)) {
631 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
632 return err;
633 }
634 err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
635 if (unlikely(err)) {
636 WL_ERR(("WLC_SET_AP error (%d)\n", err));
cf2b4488
HP
637 return err;
638 }
76c06459 639
cf2b4488
HP
640 /* -EINPROGRESS: Call commit handler */
641 return -EINPROGRESS;
642}
643
644static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
645{
646 memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
647 params->bss_type = DOT11_BSSTYPE_ANY;
648 params->scan_type = 0;
649 params->nprobes = -1;
650 params->active_time = -1;
651 params->passive_time = -1;
652 params->home_time = -1;
653 params->channel_num = 0;
654
655 params->nprobes = htod32(params->nprobes);
656 params->active_time = htod32(params->active_time);
657 params->passive_time = htod32(params->passive_time);
658 params->home_time = htod32(params->home_time);
659 if (ssid && ssid->SSID_len)
660 memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
661
662}
663
664static int32
562c8850 665wl_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
cf2b4488
HP
666 int32 paramlen, void *bufptr, int32 buflen)
667{
668 int32 iolen;
669
670 iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
671 BUG_ON(unlikely(!iolen));
672
673 return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
674}
675
676static int32
562c8850 677wl_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
cf2b4488
HP
678 int32 paramlen, void *bufptr, int32 buflen)
679{
680 int32 iolen;
681
682 iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
683 BUG_ON(unlikely(!iolen));
684
685 return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
686}
687
688static int32
689wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, uint16 action)
690{
691 int32 params_size =
692 (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
693 struct wl_iscan_params *params;
694 int32 err = 0;
695
696 if (ssid && ssid->SSID_len)
697 params_size += sizeof(struct wlc_ssid);
698 params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
699 if (unlikely(!params))
700 return -ENOMEM;
701 memset(params, 0, params_size);
702 BUG_ON(unlikely(params_size >= WLC_IOCTL_SMLEN));
703
704 wl_iscan_prep(&params->params, ssid);
705
706 params->version = htod32(ISCAN_REQ_VERSION);
707 params->action = htod16(action);
708 params->scan_duration = htod16(0);
709
710 /* params_size += OFFSETOF(wl_iscan_params_t, params); */
76c06459
JC
711 err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
712 iscan->ioctl_buf, WLC_IOCTL_SMLEN);
713 if (unlikely(err)) {
cf2b4488
HP
714 if (err == -EBUSY) {
715 WL_INFO(("system busy : iscan canceled\n"));
716 } else {
717 WL_ERR(("error (%d)\n", err));
718 }
719 }
720 kfree(params);
721 return err;
722}
723
724static int32 wl_do_iscan(struct wl_priv *wl)
725{
726 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
727 struct wlc_ssid ssid;
728 int32 err = 0;
729
730 /* Broadcast scan by default */
731 memset(&ssid, 0, sizeof(ssid));
732
733 iscan->state = WL_ISCAN_STATE_SCANING;
734
735 if (wl->active_scan) {
736 int32 passive_scan = 0;
737 /* make it active scan */
76c06459
JC
738 err = wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN,
739 &passive_scan, sizeof(passive_scan));
740 if (unlikely(err)) {
cf2b4488
HP
741 WL_DBG(("error (%d)\n", err));
742 return err;
743 }
744 }
745 wl->iscan_kickstart = TRUE;
746 wl_run_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
747 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
748 iscan->timer_on = 1;
749
750 return err;
751}
752
753static int32
754__wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
755 struct cfg80211_scan_request *request,
756 struct cfg80211_ssid *this_ssid)
757{
758 struct wl_priv *wl = ndev_to_wl(ndev);
759 struct cfg80211_ssid *ssids;
760 struct wl_scan_req *sr = wl_to_sr(wl);
cf2b4488
HP
761 bool iscan_req;
762 bool spec_scan;
763 int32 err = 0;
764
765 if (unlikely(test_bit(WL_STATUS_SCANNING, &wl->status))) {
766 WL_ERR(("Scanning already : status (%d)\n", (int)wl->status));
767 return -EAGAIN;
768 }
769 if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &wl->status))) {
770 WL_ERR(("Scanning being aborted : status (%d)\n",
771 (int)wl->status));
772 return -EAGAIN;
773 }
774
775 iscan_req = FALSE;
776 spec_scan = FALSE;
777 if (request) { /* scan bss */
778 ssids = request->ssids;
93ad12cf 779 if (wl->iscan_on && (!ssids || !ssids->ssid_len)) { /* for
cf2b4488
HP
780 * specific scan,
781 * ssids->ssid_len has
782 * non-zero(ssid string)
783 * length.
784 * Otherwise this is 0.
785 * we do not iscan for
786 * specific scan request
787 */
788 iscan_req = TRUE;
789 }
790 } else { /* scan in ibss */
791 /* we don't do iscan in ibss */
792 ssids = this_ssid;
cf2b4488
HP
793 }
794 wl->scan_request = request;
795 set_bit(WL_STATUS_SCANNING, &wl->status);
796 if (iscan_req) {
76c06459
JC
797 err = wl_do_iscan(wl);
798 if (unlikely(err))
cf2b4488
HP
799 return err;
800 else
801 goto scan_out;
802 } else {
93ad12cf 803 WL_DBG(("ssid \"%s\", ssid_len (%d)\n",
804 ssids->ssid, ssids->ssid_len));
cf2b4488 805 memset(&sr->ssid, 0, sizeof(sr->ssid));
93ad12cf 806 sr->ssid.SSID_len =
cf2b4488 807 MIN(sizeof(sr->ssid.SSID), ssids->ssid_len);
93ad12cf 808 if (sr->ssid.SSID_len) {
809 memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
810 sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
811 WL_DBG(("Specific scan ssid=\"%s\" len=%d\n",
cf2b4488 812 sr->ssid.SSID, sr->ssid.SSID_len));
93ad12cf 813 spec_scan = TRUE;
cf2b4488 814 } else {
cf2b4488
HP
815 WL_DBG(("Broadcast scan\n"));
816 }
817 WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
818 if (wl->active_scan) {
819 int32 pssive_scan = 0;
820 /* make it active scan */
76c06459
JC
821 err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
822 &pssive_scan, sizeof(pssive_scan));
823 if (unlikely(err)) {
cf2b4488
HP
824 WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n",
825 err));
826 goto scan_out;
827 }
828 }
76c06459
JC
829 err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid,
830 sizeof(sr->ssid));
831 if (err) {
cf2b4488
HP
832 if (err == -EBUSY) {
833 WL_INFO(("system busy : scan for \"%s\" "
834 "canceled\n", sr->ssid.SSID));
835 } else {
836 WL_ERR(("WLC_SCAN error (%d)\n", err));
837 }
838 goto scan_out;
839 }
840 }
841
842 return 0;
843
844scan_out:
845 clear_bit(WL_STATUS_SCANNING, &wl->status);
846 wl->scan_request = NULL;
847 return err;
848}
849
850static int32
851wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
852 struct cfg80211_scan_request *request)
853{
854 int32 err = 0;
855
856 CHECK_SYS_UP();
76c06459
JC
857 err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
858 if (unlikely(err)) {
cf2b4488
HP
859 WL_DBG(("scan error (%d)\n", err));
860 return err;
861 }
862
863 return err;
864}
865
562c8850 866static int32 wl_dev_intvar_set(struct net_device *dev, s8 *name, int32 val)
cf2b4488 867{
562c8850 868 s8 buf[WLC_IOCTL_SMLEN];
cf2b4488
HP
869 uint32 len;
870 int32 err = 0;
871
872 val = htod32(val);
873 len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
874 BUG_ON(unlikely(!len));
875
76c06459
JC
876 err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
877 if (unlikely(err)) {
cf2b4488
HP
878 WL_ERR(("error (%d)\n", err));
879 }
880
881 return err;
882}
883
884static int32
562c8850 885wl_dev_intvar_get(struct net_device *dev, s8 *name, int32 *retval)
cf2b4488
HP
886{
887 union {
562c8850 888 s8 buf[WLC_IOCTL_SMLEN];
cf2b4488
HP
889 int32 val;
890 } var;
891 uint32 len;
892 uint32 data_null;
893 int32 err = 0;
894
895 len =
896 bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
897 sizeof(var.buf));
898 BUG_ON(unlikely(!len));
76c06459
JC
899 err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
900 if (unlikely(err)) {
cf2b4488
HP
901 WL_ERR(("error (%d)\n", err));
902 }
903 *retval = dtoh32(var.val);
904
905 return err;
906}
907
908static int32 wl_set_rts(struct net_device *dev, uint32 rts_threshold)
909{
910 int32 err = 0;
911
76c06459
JC
912 err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold);
913 if (unlikely(err)) {
cf2b4488
HP
914 WL_ERR(("Error (%d)\n", err));
915 return err;
916 }
917 return err;
918}
919
920static int32 wl_set_frag(struct net_device *dev, uint32 frag_threshold)
921{
922 int32 err = 0;
923
76c06459
JC
924 err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold);
925 if (unlikely(err)) {
cf2b4488
HP
926 WL_ERR(("Error (%d)\n", err));
927 return err;
928 }
929 return err;
930}
931
932static int32 wl_set_retry(struct net_device *dev, uint32 retry, bool l)
933{
934 int32 err = 0;
935 uint32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
936
937 retry = htod32(retry);
76c06459
JC
938 err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
939 if (unlikely(err)) {
cf2b4488
HP
940 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
941 return err;
942 }
943 return err;
944}
945
946static int32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, uint32 changed)
947{
948 struct wl_priv *wl = wiphy_to_wl(wiphy);
949 struct net_device *ndev = wl_to_ndev(wl);
950 int32 err = 0;
951
952 CHECK_SYS_UP();
953 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
954 (wl->conf->rts_threshold != wiphy->rts_threshold)) {
955 wl->conf->rts_threshold = wiphy->rts_threshold;
76c06459
JC
956 err = wl_set_rts(ndev, wl->conf->rts_threshold);
957 if (!err)
cf2b4488
HP
958 return err;
959 }
960 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
961 (wl->conf->frag_threshold != wiphy->frag_threshold)) {
962 wl->conf->frag_threshold = wiphy->frag_threshold;
76c06459
JC
963 err = wl_set_frag(ndev, wl->conf->frag_threshold);
964 if (!err)
cf2b4488
HP
965 return err;
966 }
967 if (changed & WIPHY_PARAM_RETRY_LONG
968 && (wl->conf->retry_long != wiphy->retry_long)) {
969 wl->conf->retry_long = wiphy->retry_long;
76c06459
JC
970 err = wl_set_retry(ndev, wl->conf->retry_long, TRUE);
971 if (!err)
cf2b4488
HP
972 return err;
973 }
974 if (changed & WIPHY_PARAM_RETRY_SHORT
975 && (wl->conf->retry_short != wiphy->retry_short)) {
976 wl->conf->retry_short = wiphy->retry_short;
76c06459
JC
977 err = wl_set_retry(ndev, wl->conf->retry_short, FALSE);
978 if (!err) {
cf2b4488
HP
979 return err;
980 }
981 }
982
983 return err;
984}
985
986static int32
987wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
988 struct cfg80211_ibss_params *params)
989{
990 struct wl_priv *wl = wiphy_to_wl(wiphy);
991 struct cfg80211_bss *bss;
992 struct ieee80211_channel *chan;
993 struct wl_join_params join_params;
994 struct cfg80211_ssid ssid;
995 int32 scan_retry = 0;
996 int32 err = 0;
997
998 CHECK_SYS_UP();
999 if (params->bssid) {
1000 WL_ERR(("Invalid bssid\n"));
1001 return -EOPNOTSUPP;
1002 }
1003 bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
1004 if (!bss) {
1005 memcpy(ssid.ssid, params->ssid, params->ssid_len);
1006 ssid.ssid_len = params->ssid_len;
1007 do {
1008 if (unlikely
1009 (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
1010 -EBUSY)) {
1011 wl_delay(150);
1012 } else {
1013 break;
1014 }
1015 } while (++scan_retry < WL_SCAN_RETRY_MAX);
1016 rtnl_unlock(); /* to allow scan_inform to paropagate
1017 to cfg80211 plane */
1018 schedule_timeout_interruptible(4 * HZ); /* wait 4 secons
1019 till scan done.... */
1020 rtnl_lock();
1021 bss = cfg80211_get_ibss(wiphy, NULL,
1022 params->ssid, params->ssid_len);
1023 }
1024 if (bss) {
1025 wl->ibss_starter = FALSE;
1026 WL_DBG(("Found IBSS\n"));
1027 } else {
1028 wl->ibss_starter = TRUE;
1029 }
76c06459
JC
1030 chan = params->channel;
1031 if (chan)
cf2b4488
HP
1032 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
1033 /*
1034 ** Join with specific BSSID and cached SSID
1035 ** If SSID is zero join based on BSSID only
1036 */
1037 memset(&join_params, 0, sizeof(join_params));
1038 memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
1039 params->ssid_len);
1040 join_params.ssid.SSID_len = htod32(params->ssid_len);
1041 if (params->bssid)
1042 memcpy(&join_params.params.bssid, params->bssid,
1043 ETHER_ADDR_LEN);
1044 else
1045 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
1046
76c06459
JC
1047 err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params,
1048 sizeof(join_params));
1049 if (unlikely(err)) {
cf2b4488
HP
1050 WL_ERR(("Error (%d)\n", err));
1051 return err;
1052 }
1053 return err;
1054}
1055
1056static int32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1057{
1058 struct wl_priv *wl = wiphy_to_wl(wiphy);
1059 int32 err = 0;
1060
1061 CHECK_SYS_UP();
1062 wl_link_down(wl);
1063
1064 return err;
1065}
1066
1067static int32
1068wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
1069{
1070 struct wl_priv *wl = ndev_to_wl(dev);
1071 struct wl_security *sec;
1072 int32 val = 0;
1073 int32 err = 0;
1074
1075 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1076 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1077 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1078 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1079 else
1080 val = WPA_AUTH_DISABLED;
1081 WL_DBG(("setting wpa_auth to 0x%0x\n", val));
76c06459
JC
1082 err = wl_dev_intvar_set(dev, "wpa_auth", val);
1083 if (unlikely(err)) {
cf2b4488
HP
1084 WL_ERR(("set wpa_auth failed (%d)\n", err));
1085 return err;
1086 }
1087 sec = wl_read_prof(wl, WL_PROF_SEC);
1088 sec->wpa_versions = sme->crypto.wpa_versions;
1089 return err;
1090}
1091
1092static int32
1093wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
1094{
1095 struct wl_priv *wl = ndev_to_wl(dev);
1096 struct wl_security *sec;
1097 int32 val = 0;
1098 int32 err = 0;
1099
1100 switch (sme->auth_type) {
1101 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1102 val = 0;
1103 WL_DBG(("open system\n"));
1104 break;
1105 case NL80211_AUTHTYPE_SHARED_KEY:
1106 val = 1;
1107 WL_DBG(("shared key\n"));
1108 break;
1109 case NL80211_AUTHTYPE_AUTOMATIC:
1110 val = 2;
1111 WL_DBG(("automatic\n"));
1112 break;
1113 case NL80211_AUTHTYPE_NETWORK_EAP:
1114 WL_DBG(("network eap\n"));
1115 default:
1116 val = 2;
1117 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
1118 break;
1119 }
1120
76c06459
JC
1121 err = wl_dev_intvar_set(dev, "auth", val);
1122 if (unlikely(err)) {
cf2b4488
HP
1123 WL_ERR(("set auth failed (%d)\n", err));
1124 return err;
1125 }
1126 sec = wl_read_prof(wl, WL_PROF_SEC);
1127 sec->auth_type = sme->auth_type;
1128 return err;
1129}
1130
1131static int32
1132wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
1133{
1134 struct wl_priv *wl = ndev_to_wl(dev);
1135 struct wl_security *sec;
1136 int32 pval = 0;
1137 int32 gval = 0;
1138 int32 err = 0;
1139
1140 if (sme->crypto.n_ciphers_pairwise) {
1141 switch (sme->crypto.ciphers_pairwise[0]) {
1142 case WLAN_CIPHER_SUITE_WEP40:
1143 case WLAN_CIPHER_SUITE_WEP104:
1144 pval = WEP_ENABLED;
1145 break;
1146 case WLAN_CIPHER_SUITE_TKIP:
1147 pval = TKIP_ENABLED;
1148 break;
1149 case WLAN_CIPHER_SUITE_CCMP:
1150 pval = AES_ENABLED;
1151 break;
1152 case WLAN_CIPHER_SUITE_AES_CMAC:
1153 pval = AES_ENABLED;
1154 break;
1155 default:
1156 WL_ERR(("invalid cipher pairwise (%d)\n",
1157 sme->crypto.ciphers_pairwise[0]));
1158 return -EINVAL;
1159 }
1160 }
1161 if (sme->crypto.cipher_group) {
1162 switch (sme->crypto.cipher_group) {
1163 case WLAN_CIPHER_SUITE_WEP40:
1164 case WLAN_CIPHER_SUITE_WEP104:
1165 gval = WEP_ENABLED;
1166 break;
1167 case WLAN_CIPHER_SUITE_TKIP:
1168 gval = TKIP_ENABLED;
1169 break;
1170 case WLAN_CIPHER_SUITE_CCMP:
1171 gval = AES_ENABLED;
1172 break;
1173 case WLAN_CIPHER_SUITE_AES_CMAC:
1174 gval = AES_ENABLED;
1175 break;
1176 default:
1177 WL_ERR(("invalid cipher group (%d)\n",
1178 sme->crypto.cipher_group));
1179 return -EINVAL;
1180 }
1181 }
1182
1183 WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
76c06459
JC
1184 err = wl_dev_intvar_set(dev, "wsec", pval | gval);
1185 if (unlikely(err)) {
cf2b4488
HP
1186 WL_ERR(("error (%d)\n", err));
1187 return err;
1188 }
1189
1190 sec = wl_read_prof(wl, WL_PROF_SEC);
1191 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
1192 sec->cipher_group = sme->crypto.cipher_group;
1193
1194 return err;
1195}
1196
1197static int32
1198wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
1199{
1200 struct wl_priv *wl = ndev_to_wl(dev);
1201 struct wl_security *sec;
1202 int32 val = 0;
1203 int32 err = 0;
1204
1205 if (sme->crypto.n_akm_suites) {
76c06459
JC
1206 err = wl_dev_intvar_get(dev, "wpa_auth", &val);
1207 if (unlikely(err)) {
cf2b4488
HP
1208 WL_ERR(("could not get wpa_auth (%d)\n", err));
1209 return err;
1210 }
1211 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
1212 switch (sme->crypto.akm_suites[0]) {
1213 case WLAN_AKM_SUITE_8021X:
1214 val = WPA_AUTH_UNSPECIFIED;
1215 break;
1216 case WLAN_AKM_SUITE_PSK:
1217 val = WPA_AUTH_PSK;
1218 break;
1219 default:
1220 WL_ERR(("invalid cipher group (%d)\n",
1221 sme->crypto.cipher_group));
1222 return -EINVAL;
1223 }
1224 } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
1225 switch (sme->crypto.akm_suites[0]) {
1226 case WLAN_AKM_SUITE_8021X:
1227 val = WPA2_AUTH_UNSPECIFIED;
1228 break;
1229 case WLAN_AKM_SUITE_PSK:
1230 val = WPA2_AUTH_PSK;
1231 break;
1232 default:
1233 WL_ERR(("invalid cipher group (%d)\n",
1234 sme->crypto.cipher_group));
1235 return -EINVAL;
1236 }
1237 }
1238
1239 WL_DBG(("setting wpa_auth to %d\n", val));
76c06459
JC
1240 err = wl_dev_intvar_set(dev, "wpa_auth", val);
1241 if (unlikely(err)) {
cf2b4488
HP
1242 WL_ERR(("could not set wpa_auth (%d)\n", err));
1243 return err;
1244 }
1245 }
1246 sec = wl_read_prof(wl, WL_PROF_SEC);
1247 sec->wpa_auth = sme->crypto.akm_suites[0];
1248
1249 return err;
1250}
1251
1252static int32
1253wl_set_set_sharedkey(struct net_device *dev,
1254 struct cfg80211_connect_params *sme)
1255{
1256 struct wl_priv *wl = ndev_to_wl(dev);
1257 struct wl_security *sec;
1258 struct wl_wsec_key key;
1259 int32 val;
1260 int32 err = 0;
1261
1262 WL_DBG(("key len (%d)\n", sme->key_len));
1263 if (sme->key_len) {
1264 sec = wl_read_prof(wl, WL_PROF_SEC);
1265 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
1266 sec->wpa_versions, sec->cipher_pairwise));
1267 if (!
1268 (sec->wpa_versions & (NL80211_WPA_VERSION_1 |
1269 NL80211_WPA_VERSION_2))
1270&& (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
1271 WLAN_CIPHER_SUITE_WEP104))) {
1272 memset(&key, 0, sizeof(key));
1273 key.len = (uint32) sme->key_len;
1274 key.index = (uint32) sme->key_idx;
1275 if (unlikely(key.len > sizeof(key.data))) {
1276 WL_ERR(("Too long key length (%u)\n", key.len));
1277 return -EINVAL;
1278 }
1279 memcpy(key.data, sme->key, key.len);
1280 key.flags = WL_PRIMARY_KEY;
1281 switch (sec->cipher_pairwise) {
1282 case WLAN_CIPHER_SUITE_WEP40:
1283 key.algo = CRYPTO_ALGO_WEP1;
1284 break;
1285 case WLAN_CIPHER_SUITE_WEP104:
1286 key.algo = CRYPTO_ALGO_WEP128;
1287 break;
1288 default:
1289 WL_ERR(("Invalid algorithm (%d)\n",
1290 sme->crypto.ciphers_pairwise[0]));
1291 return -EINVAL;
1292 }
1293 /* Set the new key/index */
1294 WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
1295 key.len, key.index, key.algo));
1296 WL_DBG(("key \"%s\"\n", key.data));
1297 swap_key_from_BE(&key);
76c06459
JC
1298 err = wl_dev_ioctl(dev, WLC_SET_KEY, &key,
1299 sizeof(key));
1300 if (unlikely(err)) {
cf2b4488
HP
1301 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
1302 return err;
1303 }
1304 if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
1305 WL_DBG(("set auth_type to shared key\n"));
1306 val = 1; /* shared key */
76c06459
JC
1307 err = wl_dev_intvar_set(dev, "auth", val);
1308 if (unlikely(err)) {
cf2b4488
HP
1309 WL_ERR(("set auth failed (%d)\n", err));
1310 return err;
1311 }
1312 }
1313 }
1314 }
1315 return err;
1316}
1317
1318static int32
1319wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
1320 struct cfg80211_connect_params *sme)
1321{
1322 struct wl_priv *wl = wiphy_to_wl(wiphy);
1323 struct ieee80211_channel *chan = sme->channel;
1324 struct wlc_ssid ssid;
1325 int32 err = 0;
1326
1327 CHECK_SYS_UP();
1328 if (unlikely(!sme->ssid)) {
1329 WL_ERR(("Invalid ssid\n"));
1330 return -EOPNOTSUPP;
1331 }
1332 if (chan) {
1333 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
1334 WL_DBG(("channel (%d), center_req (%d)\n", wl->channel,
1335 chan->center_freq));
1336 }
1337 WL_DBG(("ie (%p), ie_len (%d)\n", sme->ie, sme->ie_len));
76c06459
JC
1338 err = wl_set_wpa_version(dev, sme);
1339 if (unlikely(err))
cf2b4488
HP
1340 return err;
1341
76c06459
JC
1342 err = wl_set_auth_type(dev, sme);
1343 if (unlikely(err))
cf2b4488
HP
1344 return err;
1345
76c06459
JC
1346 err = wl_set_set_cipher(dev, sme);
1347 if (unlikely(err))
cf2b4488
HP
1348 return err;
1349
76c06459
JC
1350 err = wl_set_key_mgmt(dev, sme);
1351 if (unlikely(err))
cf2b4488
HP
1352 return err;
1353
76c06459
JC
1354 err = wl_set_set_sharedkey(dev, sme);
1355 if (unlikely(err))
cf2b4488
HP
1356 return err;
1357
1358 wl_update_prof(wl, NULL, sme->bssid, WL_PROF_BSSID);
1359 /*
1360 ** Join with specific BSSID and cached SSID
1361 ** If SSID is zero join based on BSSID only
1362 */
1363 memset(&ssid, 0, sizeof(ssid));
1364 ssid.SSID_len = MIN(sizeof(ssid.SSID), sme->ssid_len);
1365 memcpy(ssid.SSID, sme->ssid, ssid.SSID_len);
1366 ssid.SSID_len = htod32(ssid.SSID_len);
1367 wl_update_prof(wl, NULL, &ssid, WL_PROF_SSID);
1368 if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
1369 WL_DBG(("ssid \"%s\", len (%d)\n", ssid.SSID, ssid.SSID_len));
1370 }
76c06459
JC
1371 err = wl_dev_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid));
1372 if (unlikely(err)) {
cf2b4488
HP
1373 WL_ERR(("error (%d)\n", err));
1374 return err;
1375 }
1376 set_bit(WL_STATUS_CONNECTING, &wl->status);
1377
1378 return err;
1379}
1380
1381static int32
1382wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
1383 uint16 reason_code)
1384{
1385 struct wl_priv *wl = wiphy_to_wl(wiphy);
1386 scb_val_t scbval;
1387 bool act = FALSE;
1388 int32 err = 0;
1389
1390 WL_DBG(("Reason %d\n", reason_code));
1391 CHECK_SYS_UP();
76c06459
JC
1392 act = *(bool *) wl_read_prof(wl, WL_PROF_ACT);
1393 if (likely(act)) {
cf2b4488
HP
1394 scbval.val = reason_code;
1395 memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
1396 scbval.val = htod32(scbval.val);
76c06459
JC
1397 err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
1398 sizeof(scb_val_t));
1399 if (unlikely(err)) {
cf2b4488
HP
1400 WL_ERR(("error (%d)\n", err));
1401 return err;
1402 }
1403 }
1404
1405 return err;
1406}
1407
1408static int32
1409wl_cfg80211_set_tx_power(struct wiphy *wiphy,
1410 enum nl80211_tx_power_setting type, int32 dbm)
1411{
1412
1413 struct wl_priv *wl = wiphy_to_wl(wiphy);
1414 struct net_device *ndev = wl_to_ndev(wl);
1415 uint16 txpwrmw;
1416 int32 err = 0;
1417 int32 disable = 0;
1418
1419 CHECK_SYS_UP();
1420 switch (type) {
1421 case NL80211_TX_POWER_AUTOMATIC:
1422 break;
1423 case NL80211_TX_POWER_LIMITED:
1424 if (dbm < 0) {
1425 WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
1426 return -EINVAL;
1427 }
1428 break;
1429 case NL80211_TX_POWER_FIXED:
1430 if (dbm < 0) {
1431 WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
1432 return -EINVAL;
1433 }
1434 break;
1435 }
1436 /* Make sure radio is off or on as far as software is concerned */
1437 disable = WL_RADIO_SW_DISABLE << 16;
1438 disable = htod32(disable);
76c06459
JC
1439 err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
1440 if (unlikely(err)) {
cf2b4488
HP
1441 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
1442 return err;
1443 }
1444
1445 if (dbm > 0xffff)
1446 txpwrmw = 0xffff;
1447 else
1448 txpwrmw = (uint16) dbm;
76c06459
JC
1449 err = wl_dev_intvar_set(ndev, "qtxpower",
1450 (int32) (bcm_mw_to_qdbm(txpwrmw)));
1451 if (unlikely(err)) {
cf2b4488
HP
1452 WL_ERR(("qtxpower error (%d)\n", err));
1453 return err;
1454 }
1455 wl->conf->tx_power = dbm;
1456
1457 return err;
1458}
1459
1460static int32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, int32 *dbm)
1461{
1462 struct wl_priv *wl = wiphy_to_wl(wiphy);
1463 struct net_device *ndev = wl_to_ndev(wl);
1464 int32 txpwrdbm;
3fd79f7c 1465 u8 result;
cf2b4488
HP
1466 int32 err = 0;
1467
1468 CHECK_SYS_UP();
76c06459
JC
1469 err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm);
1470 if (unlikely(err)) {
cf2b4488
HP
1471 WL_ERR(("error (%d)\n", err));
1472 return err;
1473 }
3fd79f7c 1474 result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
cf2b4488
HP
1475 *dbm = (int32) bcm_qdbm_to_mw(result);
1476
1477 return err;
1478}
1479
1480static int32
1481wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 1482 u8 key_idx)
cf2b4488
HP
1483{
1484 uint32 index;
1485 int32 wsec;
1486 int32 err = 0;
1487
1488 WL_DBG(("key index (%d)\n", key_idx));
1489 CHECK_SYS_UP();
1490
76c06459
JC
1491 err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
1492 if (unlikely(err)) {
cf2b4488
HP
1493 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
1494 return err;
1495 }
1496 wsec = dtoh32(wsec);
1497 if (wsec & WEP_ENABLED) {
1498 /* Just select a new current key */
1499 index = (uint32) key_idx;
1500 index = htod32(index);
76c06459
JC
1501 err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
1502 sizeof(index));
1503 if (unlikely(err)) {
cf2b4488
HP
1504 WL_ERR(("error (%d)\n", err));
1505 }
1506 }
1507 return err;
1508}
1509
1510static int32
1511wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 1512 u8 key_idx, const u8 *mac_addr, struct key_params *params)
cf2b4488
HP
1513{
1514 struct wl_wsec_key key;
1515 int32 err = 0;
1516
1517 memset(&key, 0, sizeof(key));
1518 key.index = (uint32) key_idx;
1519 /* Instead of bcast for ea address for default wep keys,
1520 driver needs it to be Null */
1521 if (!ETHER_ISMULTI(mac_addr))
1522 memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
1523 key.len = (uint32) params->key_len;
1524 /* check for key index change */
1525 if (key.len == 0) {
1526 /* key delete */
1527 swap_key_from_BE(&key);
76c06459
JC
1528 err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
1529 if (unlikely(err)) {
cf2b4488
HP
1530 WL_ERR(("key delete error (%d)\n", err));
1531 return err;
1532 }
1533 } else {
1534 if (key.len > sizeof(key.data)) {
1535 WL_ERR(("Invalid key length (%d)\n", key.len));
1536 return -EINVAL;
1537 }
1538
1539 WL_DBG(("Setting the key index %d\n", key.index));
1540 memcpy(key.data, params->key, key.len);
1541
1542 if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
3fd79f7c 1543 u8 keybuf[8];
cf2b4488
HP
1544 memcpy(keybuf, &key.data[24], sizeof(keybuf));
1545 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1546 memcpy(&key.data[16], keybuf, sizeof(keybuf));
1547 }
1548
1549 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
1550 if (params->seq && params->seq_len == 6) {
1551 /* rx iv */
3fd79f7c
GKH
1552 u8 *ivptr;
1553 ivptr = (u8 *) params->seq;
cf2b4488
HP
1554 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
1555 (ivptr[3] << 8) | ivptr[2];
1556 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
1557 key.iv_initialized = TRUE;
1558 }
1559
1560 switch (params->cipher) {
1561 case WLAN_CIPHER_SUITE_WEP40:
1562 key.algo = CRYPTO_ALGO_WEP1;
1563 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
1564 break;
1565 case WLAN_CIPHER_SUITE_WEP104:
1566 key.algo = CRYPTO_ALGO_WEP128;
1567 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
1568 break;
1569 case WLAN_CIPHER_SUITE_TKIP:
1570 key.algo = CRYPTO_ALGO_TKIP;
1571 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
1572 break;
1573 case WLAN_CIPHER_SUITE_AES_CMAC:
1574 key.algo = CRYPTO_ALGO_AES_CCM;
1575 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
1576 break;
1577 case WLAN_CIPHER_SUITE_CCMP:
1578 key.algo = CRYPTO_ALGO_AES_CCM;
1579 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
1580 break;
1581 default:
1582 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
1583 return -EINVAL;
1584 }
1585 swap_key_from_BE(&key);
1586
1587 dhd_wait_pend8021x(dev);
76c06459
JC
1588 err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
1589 if (unlikely(err)) {
cf2b4488
HP
1590 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
1591 return err;
1592 }
1593 }
1594 return err;
1595}
1596
1597static int32
1598wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 1599 u8 key_idx, const u8 *mac_addr,
cf2b4488
HP
1600 struct key_params *params)
1601{
1602 struct wl_wsec_key key;
1603 int32 val;
1604 int32 wsec;
1605 int32 err = 0;
1606
1607 WL_DBG(("key index (%d)\n", key_idx));
1608 CHECK_SYS_UP();
1609
1610 if (mac_addr)
1611 return wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
1612 memset(&key, 0, sizeof(key));
1613
1614 key.len = (uint32) params->key_len;
1615 key.index = (uint32) key_idx;
1616
1617 if (unlikely(key.len > sizeof(key.data))) {
1618 WL_ERR(("Too long key length (%u)\n", key.len));
1619 return -EINVAL;
1620 }
1621 memcpy(key.data, params->key, key.len);
1622
1623 key.flags = WL_PRIMARY_KEY;
1624 switch (params->cipher) {
1625 case WLAN_CIPHER_SUITE_WEP40:
1626 key.algo = CRYPTO_ALGO_WEP1;
1627 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
1628 break;
1629 case WLAN_CIPHER_SUITE_WEP104:
1630 key.algo = CRYPTO_ALGO_WEP128;
1631 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
1632 break;
1633 case WLAN_CIPHER_SUITE_TKIP:
1634 key.algo = CRYPTO_ALGO_TKIP;
1635 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
1636 break;
1637 case WLAN_CIPHER_SUITE_AES_CMAC:
1638 key.algo = CRYPTO_ALGO_AES_CCM;
1639 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
1640 break;
1641 case WLAN_CIPHER_SUITE_CCMP:
1642 key.algo = CRYPTO_ALGO_AES_CCM;
1643 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
1644 break;
1645 default:
1646 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
1647 return -EINVAL;
1648 }
1649
1650 /* Set the new key/index */
1651 swap_key_from_BE(&key);
76c06459
JC
1652 err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
1653 if (unlikely(err)) {
cf2b4488
HP
1654 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
1655 return err;
1656 }
1657
1658 val = WEP_ENABLED;
76c06459
JC
1659 err = wl_dev_intvar_get(dev, "wsec", &wsec);
1660 if (unlikely(err)) {
cf2b4488
HP
1661 WL_ERR(("get wsec error (%d)\n", err));
1662 return err;
1663 }
1664 wsec &= ~(WEP_ENABLED);
1665 wsec |= val;
76c06459
JC
1666 err = wl_dev_intvar_set(dev, "wsec", wsec);
1667 if (unlikely(err)) {
cf2b4488
HP
1668 WL_ERR(("set wsec error (%d)\n", err));
1669 return err;
1670 }
1671
1672 val = 1; /* assume shared key. otherwise 0 */
1673 val = htod32(val);
76c06459
JC
1674 err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
1675 if (unlikely(err)) {
cf2b4488
HP
1676 WL_ERR(("WLC_SET_AUTH error (%d)\n", err));
1677 return err;
1678 }
1679 return err;
1680}
1681
1682static int32
1683wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 1684 u8 key_idx, const u8 *mac_addr)
cf2b4488
HP
1685{
1686 struct wl_wsec_key key;
1687 int32 err = 0;
1688 int32 val;
1689 int32 wsec;
1690
1691 CHECK_SYS_UP();
1692 memset(&key, 0, sizeof(key));
1693
1694 key.index = (uint32) key_idx;
1695 key.flags = WL_PRIMARY_KEY;
1696 key.algo = CRYPTO_ALGO_OFF;
1697
1698 WL_DBG(("key index (%d)\n", key_idx));
1699 /* Set the new key/index */
1700 swap_key_from_BE(&key);
76c06459
JC
1701 err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key));
1702 if (unlikely(err)) {
cf2b4488
HP
1703 if (err == -EINVAL) {
1704 if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
1705 /* we ignore this key index in this case */
1706 WL_DBG(("invalid key index (%d)\n", key_idx));
1707 }
1708 } else {
1709 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
1710 }
1711 return err;
1712 }
1713
1714 val = 0;
76c06459
JC
1715 err = wl_dev_intvar_get(dev, "wsec", &wsec);
1716 if (unlikely(err)) {
cf2b4488
HP
1717 WL_ERR(("get wsec error (%d)\n", err));
1718 return err;
1719 }
1720 wsec &= ~(WEP_ENABLED);
1721 wsec |= val;
76c06459
JC
1722 err = wl_dev_intvar_set(dev, "wsec", wsec);
1723 if (unlikely(err)) {
cf2b4488
HP
1724 WL_ERR(("set wsec error (%d)\n", err));
1725 return err;
1726 }
1727
1728 val = 0; /* assume open key. otherwise 1 */
1729 val = htod32(val);
76c06459
JC
1730 err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
1731 if (unlikely(err)) {
cf2b4488
HP
1732 WL_ERR(("WLC_SET_AUTH error (%d)\n", err));
1733 return err;
1734 }
1735 return err;
1736}
1737
1738static int32
1739wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 1740 u8 key_idx, const u8 *mac_addr, void *cookie,
cf2b4488
HP
1741 void (*callback) (void *cookie, struct key_params * params))
1742{
1743 struct key_params params;
1744 struct wl_wsec_key key;
1745 struct wl_priv *wl = wiphy_to_wl(wiphy);
1746 struct wl_security *sec;
1747 int32 wsec;
1748 int32 err = 0;
1749
1750 WL_DBG(("key index (%d)\n", key_idx));
1751 CHECK_SYS_UP();
1752
1753 memset(&key, 0, sizeof(key));
1754 key.index = key_idx;
1755 swap_key_to_BE(&key);
1756 memset(&params, 0, sizeof(params));
3fd79f7c 1757 params.key_len = (u8) MIN(DOT11_MAX_KEY_SIZE, key.len);
cf2b4488
HP
1758 memcpy(params.key, key.data, params.key_len);
1759
76c06459
JC
1760 err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
1761 if (unlikely(err)) {
cf2b4488
HP
1762 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
1763 return err;
1764 }
1765 wsec = dtoh32(wsec);
1766 switch (wsec) {
1767 case WEP_ENABLED:
1768 sec = wl_read_prof(wl, WL_PROF_SEC);
1769 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
1770 params.cipher = WLAN_CIPHER_SUITE_WEP40;
1771 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
1772 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
1773 params.cipher = WLAN_CIPHER_SUITE_WEP104;
1774 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
1775 }
1776 break;
1777 case TKIP_ENABLED:
1778 params.cipher = WLAN_CIPHER_SUITE_TKIP;
1779 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
1780 break;
1781 case AES_ENABLED:
1782 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
1783 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
1784 break;
1785 default:
1786 WL_ERR(("Invalid algo (0x%x)\n", wsec));
1787 return -EINVAL;
1788 }
1789
1790 callback(cookie, &params);
1791 return err;
1792}
1793
1794static int32
1795wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
3fd79f7c 1796 struct net_device *dev, u8 key_idx)
cf2b4488
HP
1797{
1798 WL_INFO(("Not supported\n"));
1799 CHECK_SYS_UP();
1800 return -EOPNOTSUPP;
1801}
1802
1803static int32
1804wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 1805 u8 *mac, struct station_info *sinfo)
cf2b4488
HP
1806{
1807 struct wl_priv *wl = wiphy_to_wl(wiphy);
1808 scb_val_t scb_val;
1809 int rssi;
1810 int32 rate;
1811 int32 err = 0;
1812
1813 CHECK_SYS_UP();
1814 if (unlikely
1815 (memcmp(mac, wl_read_prof(wl, WL_PROF_BSSID), ETHER_ADDR_LEN))) {
1816 WL_ERR(("Wrong Mac address\n"));
1817 return -ENOENT;
1818 }
1819
1820 /* Report the current tx rate */
76c06459
JC
1821 err = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
1822 if (err) {
cf2b4488
HP
1823 WL_ERR(("Could not get rate (%d)\n", err));
1824 } else {
1825 rate = dtoh32(rate);
1826 sinfo->filled |= STATION_INFO_TX_BITRATE;
1827 sinfo->txrate.legacy = rate * 5;
1828 WL_DBG(("Rate %d Mbps\n", (rate / 2)));
1829 }
1830
1831 if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
1832 scb_val.val = 0;
76c06459
JC
1833 err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val,
1834 sizeof(scb_val_t));
1835 if (unlikely(err)) {
cf2b4488
HP
1836 WL_ERR(("Could not get rssi (%d)\n", err));
1837 return err;
1838 }
1839 rssi = dtoh32(scb_val.val);
1840 sinfo->filled |= STATION_INFO_SIGNAL;
1841 sinfo->signal = rssi;
1842 WL_DBG(("RSSI %d dBm\n", rssi));
1843 }
1844
1845 return err;
1846}
1847
1848static int32
1849wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1850 bool enabled, int32 timeout)
1851{
1852 int32 pm;
1853 int32 err = 0;
1854
1855 CHECK_SYS_UP();
1856 pm = enabled ? PM_FAST : PM_OFF;
1857 pm = htod32(pm);
1858 WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
76c06459
JC
1859 err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
1860 if (unlikely(err)) {
cf2b4488
HP
1861 if (err == -ENODEV)
1862 WL_DBG(("net_device is not ready yet\n"));
1863 else
1864 WL_ERR(("error (%d)\n", err));
1865 return err;
1866 }
1867 return err;
1868}
1869
1870static __used uint32 wl_find_msb(uint16 bit16)
1871{
1872 uint32 ret = 0;
1873
1874 if (bit16 & 0xff00) {
1875 ret += 8;
1876 bit16 >>= 8;
1877 }
1878
1879 if (bit16 & 0xf0) {
1880 ret += 4;
1881 bit16 >>= 4;
1882 }
1883
1884 if (bit16 & 0xc) {
1885 ret += 2;
1886 bit16 >>= 2;
1887 }
1888
1889 if (bit16 & 2)
1890 ret += bit16 & 2;
1891 else if (bit16)
1892 ret += bit16;
1893
1894 return ret;
1895}
1896
1897static int32
1898wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
3fd79f7c 1899 const u8 *addr,
cf2b4488
HP
1900 const struct cfg80211_bitrate_mask *mask)
1901{
1902 struct wl_rateset rateset;
1903 int32 rate;
1904 int32 val;
1905 int32 err_bg;
1906 int32 err_a;
1907 uint32 legacy;
1908 int32 err = 0;
1909
1910 CHECK_SYS_UP();
1911 /* addr param is always NULL. ignore it */
1912 /* Get current rateset */
76c06459
JC
1913 err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
1914 sizeof(rateset));
1915 if (unlikely(err)) {
cf2b4488
HP
1916 WL_ERR(("could not get current rateset (%d)\n", err));
1917 return err;
1918 }
1919
1920 rateset.count = dtoh32(rateset.count);
1921
76c06459
JC
1922 legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
1923 if (!legacy)
cf2b4488
HP
1924 legacy = wl_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
1925
1926 val = wl_g_rates[legacy - 1].bitrate * 100000;
1927
1928 if (val < rateset.count) {
1929 /* Select rate by rateset index */
1930 rate = rateset.rates[val] & 0x7f;
1931 } else {
1932 /* Specified rate in bps */
1933 rate = val / 500000;
1934 }
1935
1936 WL_DBG(("rate %d mbps\n", (rate / 2)));
1937
1938 /*
1939 *
1940 * Set rate override,
1941 * Since the is a/b/g-blind, both a/bg_rate are enforced.
1942 */
1943 err_bg = wl_dev_intvar_set(dev, "bg_rate", rate);
1944 err_a = wl_dev_intvar_set(dev, "a_rate", rate);
1945 if (unlikely(err_bg && err_a)) {
1946 WL_ERR(("could not set fixed rate (%d) (%d)\n", err_bg, err_a));
1947 return err_bg | err_a;
1948 }
1949
1950 return err;
1951}
1952
1953static int32 wl_cfg80211_resume(struct wiphy *wiphy)
1954{
1955 int32 err = 0;
1956
1957 CHECK_SYS_UP();
1958 wl_invoke_iscan(wiphy_to_wl(wiphy));
1959
1960 return err;
1961}
1962
1963static int32 wl_cfg80211_suspend(struct wiphy *wiphy)
1964{
1965 struct wl_priv *wl = wiphy_to_wl(wiphy);
1966 int32 err = 0;
1967
1968 CHECK_SYS_UP();
1969
1970 set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
1971 wl_term_iscan(wl);
1972 if (wl->scan_request) {
1973 cfg80211_scan_done(wl->scan_request, TRUE); /* TRUE means
1974 abort */
1975 wl->scan_request = NULL;
1976 }
1977 clear_bit(WL_STATUS_SCANNING, &wl->status);
1978 clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
1979
1980 return err;
1981}
1982
1983static __used int32
1984wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
1985 int32 err)
1986{
562c8850 1987 s8 eabuf[ETHER_ADDR_STR_LEN];
cf2b4488
HP
1988 int i, j;
1989
1990 memset(eabuf, 0, ETHER_ADDR_STR_LEN);
1991
1992 WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
1993 for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
1994 WL_DBG(("PMKID[%d]: %s =\n", i,
1995 bcm_ether_ntoa(&pmk_list->pmkids.pmkid[i].BSSID,
1996 eabuf)));
1997 for (j = 0; j < WPA2_PMKID_LEN; j++) {
1998 WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
1999 }
2000 }
2001 if (likely(!err)) {
2002 err = wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
2003 sizeof(*pmk_list));
2004 }
2005
2006 return err;
2007}
2008
2009static int32
2010wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
2011 struct cfg80211_pmksa *pmksa)
2012{
2013 struct wl_priv *wl = wiphy_to_wl(wiphy);
562c8850 2014 s8 eabuf[ETHER_ADDR_STR_LEN];
cf2b4488
HP
2015 int32 err = 0;
2016 int i;
2017
2018 CHECK_SYS_UP();
2019 memset(eabuf, 0, ETHER_ADDR_STR_LEN);
2020 for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
2021 if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
2022 ETHER_ADDR_LEN))
2023 break;
2024 if (i < WL_NUM_PMKIDS_MAX) {
2025 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
2026 ETHER_ADDR_LEN);
2027 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
2028 WPA2_PMKID_LEN);
2029 if (i == wl->pmk_list->pmkids.npmkid)
2030 wl->pmk_list->pmkids.npmkid++;
2031 } else {
2032 err = -EINVAL;
2033 }
2034 WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %s =\n",
2035 bcm_ether_ntoa(&wl->pmk_list->pmkids.
2036 pmkid[wl->pmk_list->pmkids.npmkid].BSSID,
2037 eabuf)));
2038 for (i = 0; i < WPA2_PMKID_LEN; i++) {
2039 WL_DBG(("%02x\n",
2040 wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].
2041 PMKID[i]));
2042 }
2043
2044 err = wl_update_pmklist(dev, wl->pmk_list, err);
2045
2046 return err;
2047}
2048
2049static int32
2050wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
2051 struct cfg80211_pmksa *pmksa)
2052{
2053 struct wl_priv *wl = wiphy_to_wl(wiphy);
562c8850 2054 s8 eabuf[ETHER_ADDR_STR_LEN];
cf2b4488
HP
2055 struct _pmkid_list pmkid;
2056 int32 err = 0;
2057 int i;
2058
2059 CHECK_SYS_UP();
2060 memset(eabuf, 0, ETHER_ADDR_STR_LEN);
2061 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
2062 memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
2063
2064 WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %s =\n",
2065 bcm_ether_ntoa(&pmkid.pmkid[0].BSSID, eabuf)));
2066 for (i = 0; i < WPA2_PMKID_LEN; i++) {
2067 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
2068 }
2069
2070 for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
2071 if (!memcmp
2072 (pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
2073 ETHER_ADDR_LEN))
2074 break;
2075
2076 if ((wl->pmk_list->pmkids.npmkid > 0)
2077 && (i < wl->pmk_list->pmkids.npmkid)) {
2078 memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
2079 for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
2080 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
2081 &wl->pmk_list->pmkids.pmkid[i + 1].BSSID,
2082 ETHER_ADDR_LEN);
2083 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
2084 &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
2085 WPA2_PMKID_LEN);
2086 }
2087 wl->pmk_list->pmkids.npmkid--;
2088 } else {
2089 err = -EINVAL;
2090 }
2091
2092 err = wl_update_pmklist(dev, wl->pmk_list, err);
2093
2094 return err;
2095
2096}
2097
2098static int32
2099wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
2100{
2101 struct wl_priv *wl = wiphy_to_wl(wiphy);
2102 int32 err = 0;
2103
2104 CHECK_SYS_UP();
2105 memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
2106 err = wl_update_pmklist(dev, wl->pmk_list, err);
2107 return err;
2108
2109}
2110
2111static struct cfg80211_ops wl_cfg80211_ops = {
2112 .change_virtual_intf = wl_cfg80211_change_iface,
2113 .scan = wl_cfg80211_scan,
2114 .set_wiphy_params = wl_cfg80211_set_wiphy_params,
2115 .join_ibss = wl_cfg80211_join_ibss,
2116 .leave_ibss = wl_cfg80211_leave_ibss,
2117 .get_station = wl_cfg80211_get_station,
2118 .set_tx_power = wl_cfg80211_set_tx_power,
2119 .get_tx_power = wl_cfg80211_get_tx_power,
2120 .add_key = wl_cfg80211_add_key,
2121 .del_key = wl_cfg80211_del_key,
2122 .get_key = wl_cfg80211_get_key,
2123 .set_default_key = wl_cfg80211_config_default_key,
2124 .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
2125 .set_power_mgmt = wl_cfg80211_set_power_mgmt,
2126 .set_bitrate_mask = wl_cfg80211_set_bitrate_mask,
2127 .connect = wl_cfg80211_connect,
2128 .disconnect = wl_cfg80211_disconnect,
2129 .suspend = wl_cfg80211_suspend,
2130 .resume = wl_cfg80211_resume,
2131 .set_pmksa = wl_cfg80211_set_pmksa,
2132 .del_pmksa = wl_cfg80211_del_pmksa,
2133 .flush_pmksa = wl_cfg80211_flush_pmksa
2134};
2135
2136static int32 wl_mode_to_nl80211_iftype(int32 mode)
2137{
2138 int32 err = 0;
2139
2140 switch (mode) {
2141 case WL_MODE_BSS:
2142 return NL80211_IFTYPE_STATION;
2143 case WL_MODE_IBSS:
2144 return NL80211_IFTYPE_ADHOC;
2145 default:
2146 return NL80211_IFTYPE_UNSPECIFIED;
2147 }
2148
2149 return err;
2150}
2151
2152static struct wireless_dev *wl_alloc_wdev(int32 sizeof_iface,
2153 struct device *dev)
2154{
2155 struct wireless_dev *wdev;
2156 int32 err = 0;
2157
2158 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2159 if (unlikely(!wdev)) {
2160 WL_ERR(("Could not allocate wireless device\n"));
2161 return ERR_PTR(-ENOMEM);
2162 }
2163 wdev->wiphy =
2164 wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv) + sizeof_iface);
2165 if (unlikely(!wdev->wiphy)) {
2166 WL_ERR(("Couldn not allocate wiphy device\n"));
2167 err = -ENOMEM;
2168 goto wiphy_new_out;
2169 }
2170 set_wiphy_dev(wdev->wiphy, dev);
2171 wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
2172 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
2173 wdev->wiphy->interface_modes =
2174 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
2175 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
2176 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
2177 * it as 11a by default.
2178 * This will be updated with
2179 * 11n phy tables in
2180 * "ifconfig up"
2181 * if phy has 11n capability
2182 */
2183 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2184 wdev->wiphy->cipher_suites = __wl_cipher_suites;
2185 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
2186#ifndef WL_POWERSAVE_DISABLED
2187 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
2188 * save mode
2189 * by default
2190 */
2191#else
2192 wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
2193#endif /* !WL_POWERSAVE_DISABLED */
76c06459
JC
2194 err = wiphy_register(wdev->wiphy);
2195 if (unlikely(err < 0)) {
cf2b4488
HP
2196 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
2197 goto wiphy_register_out;
2198 }
2199 return wdev;
2200
2201wiphy_register_out:
2202 wiphy_free(wdev->wiphy);
2203
2204wiphy_new_out:
2205 kfree(wdev);
2206
2207 return ERR_PTR(err);
2208}
2209
2210static void wl_free_wdev(struct wl_priv *wl)
2211{
2212 struct wireless_dev *wdev = wl_to_wdev(wl);
2213
2214 if (unlikely(!wdev)) {
2215 WL_ERR(("wdev is invalid\n"));
2216 return;
2217 }
2218 wiphy_unregister(wdev->wiphy);
2219 wiphy_free(wdev->wiphy);
2220 kfree(wdev);
2221 wl_to_wdev(wl) = NULL;
2222}
2223
2224static int32 wl_inform_bss(struct wl_priv *wl)
2225{
2226 struct wl_scan_results *bss_list;
2227 struct wl_bss_info *bi = NULL; /* must be initialized */
2228 int32 err = 0;
2229 int i;
2230
2231 bss_list = wl->bss_list;
2232 if (unlikely(bss_list->version != WL_BSS_INFO_VERSION)) {
2233 WL_ERR(("Version %d != WL_BSS_INFO_VERSION\n",
2234 bss_list->version));
2235 return -EOPNOTSUPP;
2236 }
2237 WL_DBG(("scanned AP count (%d)\n", bss_list->count));
2238 bi = next_bss(bss_list, bi);
2239 for_each_bss(bss_list, bi, i) {
76c06459
JC
2240 err = wl_inform_single_bss(wl, bi);
2241 if (unlikely(err))
cf2b4488
HP
2242 break;
2243 }
2244 return err;
2245}
2246
2247static int32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
2248{
2249 struct wiphy *wiphy = wl_to_wiphy(wl);
2250 struct ieee80211_mgmt *mgmt;
2251 struct ieee80211_channel *channel;
2252 struct ieee80211_supported_band *band;
2253 struct wl_cfg80211_bss_info *notif_bss_info;
2254 struct wl_scan_req *sr = wl_to_sr(wl);
2255 uint32 signal;
2256 uint32 freq;
2257 int32 err = 0;
2258
2259 if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
2260 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
2261 return err;
2262 }
2263 notif_bss_info =
3fd79f7c 2264 kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(u8) +
cf2b4488
HP
2265 WL_BSS_INFO_MAX, GFP_KERNEL);
2266 if (unlikely(!notif_bss_info)) {
2267 WL_ERR(("notif_bss_info alloc failed\n"));
2268 return -ENOMEM;
2269 }
2270 mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
2271 notif_bss_info->channel = CHSPEC_CHANNEL(bi->chanspec);
2272 if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
2273 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2274 else
2275 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2276 notif_bss_info->rssi = bi->RSSI;
2277 memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
2278 if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
2279 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2280 IEEE80211_STYPE_PROBE_RESP);
2281 }
2282 mgmt->u.probe_resp.timestamp = 0;
2283 mgmt->u.probe_resp.beacon_int = cpu_to_le16(bi->beacon_period);
2284 mgmt->u.probe_resp.capab_info = cpu_to_le16(bi->capability);
2285 wl_rst_ie(wl);
2286 wl_add_ie(wl, WLAN_EID_SSID, bi->SSID_len, bi->SSID);
2287 wl_add_ie(wl, WLAN_EID_SUPP_RATES, bi->rateset.count,
2288 bi->rateset.rates);
3fd79f7c 2289 wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
cf2b4488
HP
2290 wl_cp_ie(wl, mgmt->u.probe_resp.variable, WL_BSS_INFO_MAX -
2291 offsetof(struct wl_cfg80211_bss_info, frame_buf));
2292 notif_bss_info->frame_len =
2293 offsetof(struct ieee80211_mgmt,
2294 u.probe_resp.variable) + wl_get_ielen(wl);
2295 freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
2296 channel = ieee80211_get_channel(wiphy, freq);
2297
b3164c71 2298 WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x\n",
2299 bi->SSID,
2300 notif_bss_info->rssi, notif_bss_info->channel,
2301 mgmt->u.probe_resp.capab_info));
cf2b4488
HP
2302
2303 signal = notif_bss_info->rssi * 100;
2304 if (unlikely(!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
2305 le16_to_cpu
2306 (notif_bss_info->frame_len),
2307 signal, GFP_KERNEL))) {
2308 WL_ERR(("cfg80211_inform_bss_frame error\n"));
2309 kfree(notif_bss_info);
2310 return -EINVAL;
2311 }
2312 kfree(notif_bss_info);
2313
2314 return err;
2315}
2316
2317static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
2318{
2319 uint32 event = ntoh32(e->event_type);
2320 uint16 flags = ntoh16(e->flags);
2321
2322 if (event == WLC_E_JOIN || event == WLC_E_ASSOC_IND
2323 || event == WLC_E_REASSOC_IND) {
2324 return TRUE;
2325 } else if (event == WLC_E_LINK) {
2326 if (flags & WLC_EVENT_MSG_LINK) {
2327 if (wl_is_ibssmode(wl)) {
2328 if (wl_is_ibssstarter(wl)) {
2329 }
2330 } else {
2331
2332 }
2333 }
2334 }
2335
2336 return FALSE;
2337}
2338
2339static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
2340{
2341 uint32 event = ntoh32(e->event_type);
2342 uint16 flags = ntoh16(e->flags);
2343
2344 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
2345 return TRUE;
2346 } else if (event == WLC_E_LINK) {
2347 if (!(flags & WLC_EVENT_MSG_LINK))
2348 return TRUE;
2349 }
2350
2351 return FALSE;
2352}
2353
b3164c71 2354static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
2355{
2356 uint32 event = ntoh32(e->event_type);
2357 uint32 status = ntoh32(e->status);
2358
2359 if (event == WLC_E_SET_SSID || event == WLC_E_LINK) {
2360 if (status == WLC_E_STATUS_NO_NETWORKS)
2361 return TRUE;
2362 }
2363
2364 return FALSE;
2365}
2366
cf2b4488
HP
2367static int32
2368wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
2369 const wl_event_msg_t *e, void *data)
2370{
2371 bool act;
2372 int32 err = 0;
2373
2374 if (wl_is_linkup(wl, e)) {
2375 wl_link_up(wl);
2376 if (wl_is_ibssmode(wl)) {
562c8850 2377 cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
cf2b4488
HP
2378 GFP_KERNEL);
2379 WL_DBG(("joined in IBSS network\n"));
2380 } else {
b3164c71 2381 wl_bss_connect_done(wl, ndev, e, data, TRUE);
cf2b4488
HP
2382 WL_DBG(("joined in BSS network \"%s\"\n",
2383 ((struct wlc_ssid *)
2384 wl_read_prof(wl, WL_PROF_SSID))->SSID));
2385 }
2386 act = TRUE;
2387 wl_update_prof(wl, e, &act, WL_PROF_ACT);
2388 } else if (wl_is_linkdown(wl, e)) {
2389 cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
2390 clear_bit(WL_STATUS_CONNECTED, &wl->status);
2391 wl_link_down(wl);
2392 wl_init_prof(wl->profile);
b3164c71 2393 } else if (wl_is_nonetwork(wl, e)) {
2394 wl_bss_connect_done(wl, ndev, e, data, FALSE);
cf2b4488
HP
2395 }
2396
2397 return err;
2398}
2399
2400static int32
2401wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev,
2402 const wl_event_msg_t *e, void *data)
2403{
2404 bool act;
2405 int32 err = 0;
2406
2407 wl_bss_roaming_done(wl, ndev, e, data);
2408 act = TRUE;
2409 wl_update_prof(wl, e, &act, WL_PROF_ACT);
2410
2411 return err;
2412}
2413
2414static __used int32
562c8850 2415wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, int32 len)
cf2b4488
HP
2416{
2417 struct wl_priv *wl = ndev_to_wl(dev);
2418 uint32 buflen;
2419
2420 buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
2421 BUG_ON(unlikely(!buflen));
2422
2423 return wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
2424}
2425
2426static int32
562c8850 2427wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
cf2b4488
HP
2428 int32 buf_len)
2429{
2430 struct wl_priv *wl = ndev_to_wl(dev);
2431 uint32 len;
2432 int32 err = 0;
2433
2434 len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
2435 BUG_ON(unlikely(!len));
76c06459
JC
2436 err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
2437 WL_IOCTL_LEN_MAX);
2438 if (unlikely(err)) {
cf2b4488
HP
2439 WL_ERR(("error (%d)\n", err));
2440 return err;
2441 }
2442 memcpy(buf, wl->ioctl_buf, buf_len);
2443
2444 return err;
2445}
2446
2447static int32 wl_get_assoc_ies(struct wl_priv *wl)
2448{
2449 struct net_device *ndev = wl_to_ndev(wl);
2450 struct wl_assoc_ielen *assoc_info;
2451 struct wl_connect_info *conn_info = wl_to_conn(wl);
2452 uint32 req_len;
2453 uint32 resp_len;
2454 int32 err = 0;
2455
76c06459
JC
2456 err = wl_dev_bufvar_get(ndev, "assoc_info", wl->extra_buf,
2457 WL_ASSOC_INFO_MAX);
2458 if (unlikely(err)) {
cf2b4488
HP
2459 WL_ERR(("could not get assoc info (%d)\n", err));
2460 return err;
2461 }
2462 assoc_info = (struct wl_assoc_ielen *)wl->extra_buf;
2463 req_len = assoc_info->req_len;
2464 resp_len = assoc_info->resp_len;
2465 if (req_len) {
76c06459
JC
2466 err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf,
2467 WL_ASSOC_INFO_MAX);
2468 if (unlikely(err)) {
cf2b4488
HP
2469 WL_ERR(("could not get assoc req (%d)\n", err));
2470 return err;
2471 }
2472 conn_info->req_ie_len = req_len;
2473 conn_info->req_ie =
2474 kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL);
2475 } else {
2476 conn_info->req_ie_len = 0;
2477 conn_info->req_ie = NULL;
2478 }
2479 if (resp_len) {
76c06459
JC
2480 err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf,
2481 WL_ASSOC_INFO_MAX);
2482 if (unlikely(err)) {
cf2b4488
HP
2483 WL_ERR(("could not get assoc resp (%d)\n", err));
2484 return err;
2485 }
2486 conn_info->resp_ie_len = resp_len;
2487 conn_info->resp_ie =
2488 kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL);
2489 } else {
2490 conn_info->resp_ie_len = 0;
2491 conn_info->resp_ie = NULL;
2492 }
2493 WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
2494 conn_info->resp_ie_len));
2495
2496 return err;
2497}
2498
2499static int32 wl_update_bss_info(struct wl_priv *wl)
2500{
2501 struct cfg80211_bss *bss;
2502 struct wl_bss_info *bi;
2503 struct wlc_ssid *ssid;
2504 int32 err = 0;
2505
2506 if (wl_is_ibssmode(wl))
2507 return err;
2508
2509 ssid = (struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID);
2510 bss =
562c8850 2511 cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid,
cf2b4488
HP
2512 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
2513 WLAN_CAPABILITY_ESS);
2514
2515 rtnl_lock();
2516 if (unlikely(!bss)) {
2517 WL_DBG(("Could not find the AP\n"));
2518 *(uint32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
76c06459
JC
2519 err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO,
2520 wl->extra_buf, WL_EXTRA_BUF_MAX);
2521 if (unlikely(err)) {
cf2b4488
HP
2522 WL_ERR(("Could not get bss info %d\n", err));
2523 goto update_bss_info_out;
2524 }
2525 bi = (struct wl_bss_info *)(wl->extra_buf + 4);
2526 if (unlikely(memcmp(&bi->BSSID, &wl->bssid, ETHER_ADDR_LEN))) {
2527 err = -EIO;
2528 goto update_bss_info_out;
2529 }
76c06459
JC
2530 err = wl_inform_single_bss(wl, bi);
2531 if (unlikely(err))
cf2b4488
HP
2532 goto update_bss_info_out;
2533 } else {
2534 WL_DBG(("Found the AP in the list - "
2535 "BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
2536 bss->bssid[0], bss->bssid[1], bss->bssid[2],
2537 bss->bssid[3], bss->bssid[4], bss->bssid[5]));
2538 cfg80211_put_bss(bss);
2539 }
2540
2541update_bss_info_out:
2542 rtnl_unlock();
2543 return err;
2544}
2545
2546static int32
2547wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
2548 const wl_event_msg_t *e, void *data)
2549{
2550 struct wl_connect_info *conn_info = wl_to_conn(wl);
2551 int32 err = 0;
2552
2553 wl_get_assoc_ies(wl);
2554 memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
2555 wl_update_bss_info(wl);
2556 cfg80211_roamed(ndev,
3fd79f7c 2557 (u8 *)&wl->bssid,
cf2b4488
HP
2558 conn_info->req_ie, conn_info->req_ie_len,
2559 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
2560 WL_DBG(("Report roaming result\n"));
2561
2562 set_bit(WL_STATUS_CONNECTED, &wl->status);
2563
2564 return err;
2565}
2566
2567static int32
2568wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
b3164c71 2569 const wl_event_msg_t *e, void *data, bool completed)
cf2b4488
HP
2570{
2571 struct wl_connect_info *conn_info = wl_to_conn(wl);
2572 int32 err = 0;
2573
2574 wl_get_assoc_ies(wl);
2575 memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
2576 wl_update_bss_info(wl);
2577 if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) {
2578 cfg80211_connect_result(ndev,
3fd79f7c 2579 (u8 *)&wl->bssid,
cf2b4488
HP
2580 conn_info->req_ie,
2581 conn_info->req_ie_len,
2582 conn_info->resp_ie,
2583 conn_info->resp_ie_len,
b3164c71 2584 completed ? WLAN_STATUS_SUCCESS : WLAN_STATUS_AUTH_TIMEOUT,
2585 GFP_KERNEL);
2586 WL_DBG(("Report connect result - connection %s\n",
2587 completed ? "succeeded" : "failed"));
cf2b4488
HP
2588 } else {
2589 cfg80211_roamed(ndev,
3fd79f7c 2590 (u8 *)&wl->bssid,
cf2b4488
HP
2591 conn_info->req_ie, conn_info->req_ie_len,
2592 conn_info->resp_ie, conn_info->resp_ie_len,
2593 GFP_KERNEL);
2594 WL_DBG(("Report roaming result\n"));
2595 }
2596 set_bit(WL_STATUS_CONNECTED, &wl->status);
2597
2598 return err;
2599}
2600
2601static int32
2602wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
2603 const wl_event_msg_t *e, void *data)
2604{
2605 uint16 flags = ntoh16(e->flags);
2606 enum nl80211_key_type key_type;
2607
2608 rtnl_lock();
2609 if (flags & WLC_EVENT_MSG_GROUP)
2610 key_type = NL80211_KEYTYPE_GROUP;
2611 else
2612 key_type = NL80211_KEYTYPE_PAIRWISE;
2613
3fd79f7c 2614 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
cf2b4488
HP
2615 NULL, GFP_KERNEL);
2616 rtnl_unlock();
2617
2618 return 0;
2619}
2620
2621static int32
2622wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
2623 const wl_event_msg_t *e, void *data)
2624{
2625 struct channel_info channel_inform;
2626 struct wl_scan_results *bss_list;
2627 uint32 len = WL_SCAN_BUF_MAX;
2628 int32 err = 0;
2629
2630 if (wl->iscan_on && wl->iscan_kickstart)
2631 return wl_wakeup_iscan(wl_to_iscan(wl));
2632
2633 if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
2634 WL_ERR(("Scan complete while device not scanning\n"));
2635 return -EINVAL;
2636 }
2637 if (unlikely(!wl->scan_request)) {
2638 }
2639 rtnl_lock();
76c06459
JC
2640 err = wl_dev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
2641 sizeof(channel_inform));
2642 if (unlikely(err)) {
cf2b4488
HP
2643 WL_ERR(("scan busy (%d)\n", err));
2644 goto scan_done_out;
2645 }
2646 channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
2647 if (unlikely(channel_inform.scan_channel)) {
2648
2649 WL_DBG(("channel_inform.scan_channel (%d)\n",
2650 channel_inform.scan_channel));
2651 }
2652 wl->bss_list = wl->scan_results;
2653 bss_list = wl->bss_list;
2654 memset(bss_list, 0, len);
2655 bss_list->buflen = htod32(len);
76c06459
JC
2656 err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len);
2657 if (unlikely(err)) {
cf2b4488
HP
2658 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
2659 err = -EINVAL;
2660 goto scan_done_out;
2661 }
2662 bss_list->buflen = dtoh32(bss_list->buflen);
2663 bss_list->version = dtoh32(bss_list->version);
2664 bss_list->count = dtoh32(bss_list->count);
2665
76c06459
JC
2666 err = wl_inform_bss(wl);
2667 if (err)
cf2b4488
HP
2668 goto scan_done_out;
2669
2670scan_done_out:
2671 if (wl->scan_request) {
2672 cfg80211_scan_done(wl->scan_request, FALSE);
2673 wl->scan_request = NULL;
2674 }
2675 rtnl_unlock();
2676 return err;
2677}
2678
2679static void wl_init_conf(struct wl_conf *conf)
2680{
2681 conf->mode = (uint32)-1;
2682 conf->frag_threshold = (uint32)-1;
2683 conf->rts_threshold = (uint32)-1;
2684 conf->retry_short = (uint32)-1;
2685 conf->retry_long = (uint32)-1;
e9887c9d 2686 conf->tx_power = -1;
cf2b4488
HP
2687}
2688
2689static void wl_init_prof(struct wl_profile *prof)
2690{
2691 memset(prof, 0, sizeof(*prof));
2692}
2693
2694static void wl_init_eloop_handler(struct wl_event_loop *el)
2695{
2696 memset(el, 0, sizeof(*el));
2697 el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
2698 el->handler[WLC_E_JOIN] = wl_notify_connect_status;
2699 el->handler[WLC_E_LINK] = wl_notify_connect_status;
2700 el->handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
2701 el->handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
2702 el->handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
2703 el->handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
2704 el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
2705 el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
b3164c71 2706 el->handler[WLC_E_SET_SSID] = wl_notify_connect_status;
cf2b4488
HP
2707}
2708
2709static int32 wl_init_priv_mem(struct wl_priv *wl)
2710{
2711 wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
2712 if (unlikely(!wl->scan_results)) {
2713 WL_ERR(("Scan results alloc failed\n"));
2714 goto init_priv_mem_out;
2715 }
2716 wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
2717 if (unlikely(!wl->conf)) {
2718 WL_ERR(("wl_conf alloc failed\n"));
2719 goto init_priv_mem_out;
2720 }
2721 wl->profile = (void *)kzalloc(sizeof(*wl->profile), GFP_KERNEL);
2722 if (unlikely(!wl->profile)) {
2723 WL_ERR(("wl_profile alloc failed\n"));
2724 goto init_priv_mem_out;
2725 }
2726 wl->bss_info = (void *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2727 if (unlikely(!wl->bss_info)) {
2728 WL_ERR(("Bss information alloc failed\n"));
2729 goto init_priv_mem_out;
2730 }
2731 wl->scan_req_int =
2732 (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
2733 if (unlikely(!wl->scan_req_int)) {
2734 WL_ERR(("Scan req alloc failed\n"));
2735 goto init_priv_mem_out;
2736 }
2737 wl->ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
2738 if (unlikely(!wl->ioctl_buf)) {
2739 WL_ERR(("Ioctl buf alloc failed\n"));
2740 goto init_priv_mem_out;
2741 }
2742 wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
2743 if (unlikely(!wl->extra_buf)) {
2744 WL_ERR(("Extra buf alloc failed\n"));
2745 goto init_priv_mem_out;
2746 }
2747 wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
2748 if (unlikely(!wl->iscan)) {
2749 WL_ERR(("Iscan buf alloc failed\n"));
2750 goto init_priv_mem_out;
2751 }
2752 wl->fw = (void *)kzalloc(sizeof(*wl->fw), GFP_KERNEL);
2753 if (unlikely(!wl->fw)) {
2754 WL_ERR(("fw object alloc failed\n"));
2755 goto init_priv_mem_out;
2756 }
2757 wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
2758 if (unlikely(!wl->pmk_list)) {
2759 WL_ERR(("pmk list alloc failed\n"));
2760 goto init_priv_mem_out;
2761 }
2762
2763 return 0;
2764
2765init_priv_mem_out:
2766 wl_deinit_priv_mem(wl);
2767
2768 return -ENOMEM;
2769}
2770
2771static void wl_deinit_priv_mem(struct wl_priv *wl)
2772{
2773 kfree(wl->scan_results);
2774 wl->scan_results = NULL;
2775 kfree(wl->bss_info);
2776 wl->bss_info = NULL;
2777 kfree(wl->conf);
2778 wl->conf = NULL;
2779 kfree(wl->profile);
2780 wl->profile = NULL;
2781 kfree(wl->scan_req_int);
2782 wl->scan_req_int = NULL;
2783 kfree(wl->ioctl_buf);
2784 wl->ioctl_buf = NULL;
2785 kfree(wl->extra_buf);
2786 wl->extra_buf = NULL;
2787 kfree(wl->iscan);
2788 wl->iscan = NULL;
2789 kfree(wl->fw);
2790 wl->fw = NULL;
2791 kfree(wl->pmk_list);
2792 wl->pmk_list = NULL;
2793}
2794
2795static int32 wl_create_event_handler(struct wl_priv *wl)
2796{
2797 sema_init(&wl->event_sync, 0);
2798 init_completion(&wl->event_exit);
76c06459
JC
2799 wl->event_pid = kernel_thread(wl_event_handler, wl, 0);
2800 if (unlikely(wl->event_pid < 0)) {
cf2b4488
HP
2801 WL_ERR(("failed to create event thread\n"));
2802 return -ENOMEM;
2803 }
2804 WL_DBG(("pid %d\n", wl->event_pid));
2805 return 0;
2806}
2807
2808static void wl_destroy_event_handler(struct wl_priv *wl)
2809{
2810 if (wl->event_pid >= 0) {
2811 KILL_PROC(wl->event_pid, SIGTERM);
2812 wait_for_completion(&wl->event_exit);
2813 }
2814}
2815
2816static void wl_term_iscan(struct wl_priv *wl)
2817{
2818 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
2819
2820 if (wl->iscan_on && iscan->pid >= 0) {
2821 iscan->state = WL_ISCAN_STATE_IDLE;
2822 KILL_PROC(iscan->pid, SIGTERM);
2823 wait_for_completion(&iscan->exited);
2824 iscan->pid = -1;
2825 }
2826}
2827
2828static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
2829{
2830 struct wl_priv *wl = iscan_to_wl(iscan);
2831
2832 if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
2833 WL_ERR(("Scan complete while device not scanning\n"));
2834 return;
2835 }
2836 if (likely(wl->scan_request)) {
2837 cfg80211_scan_done(wl->scan_request, aborted);
2838 wl->scan_request = NULL;
2839 }
2840 wl->iscan_kickstart = FALSE;
2841}
2842
2843static int32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
2844{
2845 if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
2846 WL_DBG(("wake up iscan\n"));
2847 up(&iscan->sync);
2848 return 0;
2849 }
2850
2851 return -EIO;
2852}
2853
2854static int32
2855wl_get_iscan_results(struct wl_iscan_ctrl *iscan, uint32 *status,
2856 struct wl_scan_results **bss_list)
2857{
2858 struct wl_iscan_results list;
2859 struct wl_scan_results *results;
2860 struct wl_iscan_results *list_buf;
2861 int32 err = 0;
2862
2863 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
2864 list_buf = (struct wl_iscan_results *)iscan->scan_buf;
2865 results = &list_buf->results;
2866 results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
2867 results->version = 0;
2868 results->count = 0;
2869
2870 memset(&list, 0, sizeof(list));
2871 list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
76c06459
JC
2872 err = wl_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
2873 WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
2874 WL_ISCAN_BUF_MAX);
2875 if (unlikely(err)) {
cf2b4488
HP
2876 WL_ERR(("error (%d)\n", err));
2877 return err;
2878 }
2879 results->buflen = dtoh32(results->buflen);
2880 results->version = dtoh32(results->version);
2881 results->count = dtoh32(results->count);
2882 WL_DBG(("results->count = %d\n", results->count));
2883 WL_DBG(("results->buflen = %d\n", results->buflen));
2884 *status = dtoh32(list_buf->status);
2885 *bss_list = results;
2886
2887 return err;
2888}
2889
2890static int32 wl_iscan_done(struct wl_priv *wl)
2891{
2892 struct wl_iscan_ctrl *iscan = wl->iscan;
2893 int32 err = 0;
2894
2895 iscan->state = WL_ISCAN_STATE_IDLE;
2896 rtnl_lock();
2897 wl_inform_bss(wl);
2898 wl_notify_iscan_complete(iscan, FALSE);
2899 rtnl_unlock();
2900
2901 return err;
2902}
2903
2904static int32 wl_iscan_pending(struct wl_priv *wl)
2905{
2906 struct wl_iscan_ctrl *iscan = wl->iscan;
2907 int32 err = 0;
2908
2909 /* Reschedule the timer */
2910 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2911 iscan->timer_on = 1;
2912
2913 return err;
2914}
2915
2916static int32 wl_iscan_inprogress(struct wl_priv *wl)
2917{
2918 struct wl_iscan_ctrl *iscan = wl->iscan;
2919 int32 err = 0;
2920
2921 rtnl_lock();
2922 wl_inform_bss(wl);
2923 wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
2924 rtnl_unlock();
2925 /* Reschedule the timer */
2926 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2927 iscan->timer_on = 1;
2928
2929 return err;
2930}
2931
2932static int32 wl_iscan_aborted(struct wl_priv *wl)
2933{
2934 struct wl_iscan_ctrl *iscan = wl->iscan;
2935 int32 err = 0;
2936
2937 iscan->state = WL_ISCAN_STATE_IDLE;
2938 rtnl_lock();
2939 wl_notify_iscan_complete(iscan, TRUE);
2940 rtnl_unlock();
2941
2942 return err;
2943}
2944
2945static int32 wl_iscan_thread(void *data)
2946{
2947 struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
2948 struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
2949 struct wl_priv *wl = iscan_to_wl(iscan);
2950 struct wl_iscan_eloop *el = &iscan->el;
2951 uint32 status;
2952 int err = 0;
2953
2954 sched_setscheduler(current, SCHED_FIFO, &param);
2955 status = WL_SCAN_RESULTS_PARTIAL;
2956 while (likely(!down_interruptible(&iscan->sync))) {
2957 if (iscan->timer_on) {
2958 del_timer_sync(&iscan->timer);
2959 iscan->timer_on = 0;
2960 }
2961 rtnl_lock();
76c06459
JC
2962 err = wl_get_iscan_results(iscan, &status, &wl->bss_list);
2963 if (unlikely(err)) {
cf2b4488
HP
2964 status = WL_SCAN_RESULTS_ABORTED;
2965 WL_ERR(("Abort iscan\n"));
2966 }
2967 rtnl_unlock();
2968 el->handler[status] (wl);
2969 }
2970 if (iscan->timer_on) {
2971 del_timer_sync(&iscan->timer);
2972 iscan->timer_on = 0;
2973 }
2974 complete_and_exit(&iscan->exited, 0);
2975
2976 return 0;
2977}
2978
3deea904 2979static void wl_iscan_timer(unsigned long data)
cf2b4488
HP
2980{
2981 struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
2982
2983 if (iscan) {
2984 iscan->timer_on = 0;
2985 WL_DBG(("timer expired\n"));
2986 wl_wakeup_iscan(iscan);
2987 }
2988}
2989
2990static int32 wl_invoke_iscan(struct wl_priv *wl)
2991{
2992 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
2993 int err = 0;
2994
2995 if (wl->iscan_on && iscan->pid < 0) {
2996 iscan->state = WL_ISCAN_STATE_IDLE;
2997 sema_init(&iscan->sync, 0);
2998 init_completion(&iscan->exited);
2999 iscan->pid = kernel_thread(wl_iscan_thread, iscan, 0);
3000 if (unlikely(iscan->pid < 0)) {
3001 WL_ERR(("Could not create iscan thread\n"));
3002 return -ENOMEM;
3003 }
3004 }
3005
3006 return err;
3007}
3008
3009static void wl_init_iscan_eloop(struct wl_iscan_eloop *el)
3010{
3011 memset(el, 0, sizeof(*el));
3012 el->handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
3013 el->handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
3014 el->handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
3015 el->handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
3016 el->handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
3017}
3018
3019static int32 wl_init_iscan(struct wl_priv *wl)
3020{
3021 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
3022 int err = 0;
3023
3024 if (wl->iscan_on) {
3025 iscan->dev = wl_to_ndev(wl);
3026 iscan->state = WL_ISCAN_STATE_IDLE;
3027 wl_init_iscan_eloop(&iscan->el);
3028 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
3029 init_timer(&iscan->timer);
3deea904 3030 iscan->timer.data = (unsigned long) iscan;
cf2b4488
HP
3031 iscan->timer.function = wl_iscan_timer;
3032 sema_init(&iscan->sync, 0);
3033 init_completion(&iscan->exited);
3034 iscan->pid = kernel_thread(wl_iscan_thread, iscan, 0);
3035 if (unlikely(iscan->pid < 0)) {
3036 WL_ERR(("Could not create iscan thread\n"));
3037 return -ENOMEM;
3038 }
3039 iscan->data = wl;
3040 }
3041
3042 return err;
3043}
3044
3045static void wl_init_fw(struct wl_fw_ctrl *fw)
3046{
3047 fw->status = 0; /* init fw loading status.
3048 0 means nothing was loaded yet */
3049}
3050
3051static int32 wl_init_priv(struct wl_priv *wl)
3052{
3053 struct wiphy *wiphy = wl_to_wiphy(wl);
3054 int32 err = 0;
3055
3056 wl->scan_request = NULL;
3057 wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
3058#ifndef WL_ISCAN_DISABLED
3059 wl->iscan_on = TRUE; /* iscan on & off switch.
3060 we enable iscan per default */
3061#else
3062 wl->iscan_on = FALSE;
3063#endif /* WL_ISCAN_DISABLED */
3064#ifndef WL_ROAM_DISABLED
3065 wl->roam_on = TRUE; /* roam on & off switch.
3066 we enable roam per default */
3067#else
3068 wl->roam_on = FALSE;
3069#endif /* WL_ROAM_DISABLED */
3070
3071 wl->iscan_kickstart = FALSE;
3072 wl->active_scan = TRUE; /* we do active scan for
3073 specific scan per default */
3074 wl->dongle_up = FALSE; /* dongle is not up yet */
3075 wl_init_eq(wl);
76c06459
JC
3076 err = wl_init_priv_mem(wl);
3077 if (unlikely(err))
cf2b4488
HP
3078 return err;
3079 if (unlikely(wl_create_event_handler(wl)))
3080 return -ENOMEM;
3081 wl_init_eloop_handler(&wl->el);
3082 mutex_init(&wl->usr_sync);
76c06459
JC
3083 err = wl_init_iscan(wl);
3084 if (unlikely(err))
cf2b4488
HP
3085 return err;
3086 wl_init_fw(wl->fw);
3087 wl_init_conf(wl->conf);
3088 wl_init_prof(wl->profile);
3089 wl_link_down(wl);
3090
3091 return err;
3092}
3093
3094static void wl_deinit_priv(struct wl_priv *wl)
3095{
3096 wl_destroy_event_handler(wl);
3097 wl->dongle_up = FALSE; /* dongle down */
3098 wl_flush_eq(wl);
3099 wl_link_down(wl);
3100 wl_term_iscan(wl);
3101 wl_deinit_priv_mem(wl);
3102}
3103
3104int32 wl_cfg80211_attach(struct net_device *ndev, void *data)
3105{
3106 struct wireless_dev *wdev;
3107 struct wl_priv *wl;
3108 struct wl_iface *ci;
3109 int32 err = 0;
3110
3111 if (unlikely(!ndev)) {
3112 WL_ERR(("ndev is invaild\n"));
3113 return -ENODEV;
3114 }
3115 wl_cfg80211_dev = kzalloc(sizeof(struct wl_dev), GFP_KERNEL);
3116 if (unlikely(!wl_cfg80211_dev)) {
3117 WL_ERR(("wl_cfg80211_dev is invalid\n"));
3118 return -ENOMEM;
3119 }
93ad12cf 3120 WL_DBG(("func %p\n", wl_cfg80211_get_sdio_func()));
3121 wdev = wl_alloc_wdev(sizeof(struct wl_iface), &wl_cfg80211_get_sdio_func()->dev);
cf2b4488
HP
3122 if (unlikely(IS_ERR(wdev)))
3123 return -ENOMEM;
3124
3125 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
3126 wl = wdev_to_wl(wdev);
3127 wl->wdev = wdev;
3128 wl->pub = data;
3129 ci = (struct wl_iface *)wl_to_ci(wl);
3130 ci->wl = wl;
3131 ndev->ieee80211_ptr = wdev;
3132 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
3133 wdev->netdev = ndev;
76c06459
JC
3134 err = wl_init_priv(wl);
3135 if (unlikely(err)) {
cf2b4488
HP
3136 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
3137 goto cfg80211_attach_out;
3138 }
3139 wl_set_drvdata(wl_cfg80211_dev, ci);
3140 set_bit(WL_STATUS_READY, &wl->status);
3141
3142 return err;
3143
3144cfg80211_attach_out:
3145 wl_free_wdev(wl);
3146 return err;
3147}
3148
3149void wl_cfg80211_detach(void)
3150{
3151 struct wl_priv *wl;
3152
3153 wl = WL_PRIV_GET();
3154
3155 wl_deinit_priv(wl);
3156 wl_free_wdev(wl);
3157 wl_set_drvdata(wl_cfg80211_dev, NULL);
3158 kfree(wl_cfg80211_dev);
3159 wl_cfg80211_dev = NULL;
3160 wl_clear_sdio_func();
3161}
3162
3163static void wl_wakeup_event(struct wl_priv *wl)
3164{
3165 up(&wl->event_sync);
3166}
3167
3168static int32 wl_event_handler(void *data)
3169{
3170 struct wl_priv *wl = (struct wl_priv *)data;
3171 struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
3172 struct wl_event_q *e;
3173
3174 sched_setscheduler(current, SCHED_FIFO, &param);
3175 while (likely(!down_interruptible(&wl->event_sync))) {
76c06459
JC
3176 e = wl_deq_event(wl);
3177 if (unlikely(!e)) {
cf2b4488
HP
3178 WL_ERR(("eqeue empty..\n"));
3179 BUG();
3180 }
3181 WL_DBG(("event type (%d)\n", e->etype));
3182 if (wl->el.handler[e->etype]) {
3183 wl->el.handler[e->etype] (wl, wl_to_ndev(wl), &e->emsg,
3184 e->edata);
3185 } else {
3186 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
3187 }
3188 wl_put_event(e);
3189 }
3190 complete_and_exit(&wl->event_exit, 0);
3191}
3192
3193void
3194wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
3195{
3196 uint32 event_type = ntoh32(e->event_type);
3197 struct wl_priv *wl = ndev_to_wl(ndev);
3198#if (WL_DBG_LEVEL > 0)
562c8850
GKH
3199 s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
3200 wl_dbg_estr[event_type] : (s8 *) "Unknown";
cf2b4488
HP
3201#endif /* (WL_DBG_LEVEL > 0) */
3202 WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
3203 if (likely(!wl_enq_event(wl, event_type, e, data)))
3204 wl_wakeup_event(wl);
3205}
3206
3207static void wl_init_eq(struct wl_priv *wl)
3208{
3209 wl_init_eq_lock(wl);
3210 INIT_LIST_HEAD(&wl->eq_list);
3211}
3212
3213static void wl_flush_eq(struct wl_priv *wl)
3214{
3215 struct wl_event_q *e;
3216
3217 wl_lock_eq(wl);
3218 while (!list_empty(&wl->eq_list)) {
3219 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
3220 list_del(&e->eq_list);
3221 kfree(e);
3222 }
3223 wl_unlock_eq(wl);
3224}
3225
3226/*
3227* retrieve first queued event from head
3228*/
3229
3230static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
3231{
3232 struct wl_event_q *e = NULL;
3233
3234 wl_lock_eq(wl);
3235 if (likely(!list_empty(&wl->eq_list))) {
3236 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
3237 list_del(&e->eq_list);
3238 }
3239 wl_unlock_eq(wl);
3240
3241 return e;
3242}
3243
3244/*
3245** push event to tail of the queue
3246*/
3247
3248static int32
3249wl_enq_event(struct wl_priv *wl, uint32 event, const wl_event_msg_t *msg,
3250 void *data)
3251{
3252 struct wl_event_q *e;
3253 int32 err = 0;
3254
76c06459
JC
3255 e = kzalloc(sizeof(struct wl_event_q), GFP_KERNEL);
3256 if (unlikely(!e)) {
cf2b4488
HP
3257 WL_ERR(("event alloc failed\n"));
3258 return -ENOMEM;
3259 }
3260
3261 e->etype = event;
3262 memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
3263 if (data) {
3264 }
3265 wl_lock_eq(wl);
3266 list_add_tail(&e->eq_list, &wl->eq_list);
3267 wl_unlock_eq(wl);
3268
3269 return err;
3270}
3271
3272static void wl_put_event(struct wl_event_q *e)
3273{
3274 kfree(e);
3275}
3276
3277void wl_cfg80211_sdio_func(void *func)
3278{
3279 cfg80211_sdio_func = (struct sdio_func *)func;
3280}
3281
3282static void wl_clear_sdio_func(void)
3283{
3284 cfg80211_sdio_func = NULL;
3285}
3286
93ad12cf 3287struct sdio_func *wl_cfg80211_get_sdio_func(void)
cf2b4488
HP
3288{
3289 return cfg80211_sdio_func;
3290}
3291
3292static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype)
3293{
3294 int32 infra = 0;
3295 int32 ap = 0;
3296 int32 err = 0;
3297
3298 switch (iftype) {
3299 case NL80211_IFTYPE_MONITOR:
3300 case NL80211_IFTYPE_WDS:
3301 WL_ERR(("type (%d) : currently we do not support this mode\n",
3302 iftype));
3303 err = -EINVAL;
3304 return err;
3305 case NL80211_IFTYPE_ADHOC:
3306 break;
3307 case NL80211_IFTYPE_STATION:
3308 infra = 1;
3309 break;
3310 default:
3311 err = -EINVAL;
3312 WL_ERR(("invalid type (%d)\n", iftype));
3313 return err;
3314 }
3315 infra = htod32(infra);
3316 ap = htod32(ap);
3317 WL_DBG(("%s ap (%d), infra (%d)\n", ndev->name, ap, infra));
76c06459
JC
3318 err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
3319 if (unlikely(err)) {
cf2b4488
HP
3320 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
3321 return err;
3322 }
76c06459
JC
3323 err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
3324 if (unlikely(err)) {
3325 WL_ERR(("WLC_SET_AP error (%d)\n", err));
3326 return err;
3327 }
cf2b4488
HP
3328
3329 return -EINPROGRESS;
3330}
3331
3332#ifndef EMBEDDED_PLATFORM
3fd79f7c 3333static int32 wl_dongle_country(struct net_device *ndev, u8 ccode)
cf2b4488
HP
3334{
3335
3336 int32 err = 0;
3337
3338 return err;
3339}
3340
3341static int32 wl_dongle_up(struct net_device *ndev, uint32 up)
3342{
3343 int32 err = 0;
3344
76c06459
JC
3345 err = wl_dev_ioctl(ndev, WLC_UP, &up, sizeof(up));
3346 if (unlikely(err)) {
cf2b4488
HP
3347 WL_ERR(("WLC_UP error (%d)\n", err));
3348 }
3349 return err;
3350}
3351
3352static int32 wl_dongle_power(struct net_device *ndev, uint32 power_mode)
3353{
3354 int32 err = 0;
3355
76c06459
JC
3356 err = wl_dev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode));
3357 if (unlikely(err)) {
cf2b4488
HP
3358 WL_ERR(("WLC_SET_PM error (%d)\n", err));
3359 }
3360 return err;
3361}
3362
3363static int32
3364wl_dongle_glom(struct net_device *ndev, uint32 glom, uint32 dongle_align)
3365{
562c8850 3366 s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
cf2b4488
HP
3367 '\0' + bitvec */
3368 int32 err = 0;
3369
3370 /* Match Host and Dongle rx alignment */
3371 bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
3372 sizeof(iovbuf));
76c06459
JC
3373 err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
3374 if (unlikely(err)) {
cf2b4488
HP
3375 WL_ERR(("txglomalign error (%d)\n", err));
3376 goto dongle_glom_out;
3377 }
3378 /* disable glom option per default */
3379 bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
76c06459
JC
3380 err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
3381 if (unlikely(err)) {
cf2b4488
HP
3382 WL_ERR(("txglom error (%d)\n", err));
3383 goto dongle_glom_out;
3384 }
3385dongle_glom_out:
3386 return err;
3387}
3388
3389static int32
3390wl_dongle_roam(struct net_device *ndev, uint32 roamvar, uint32 bcn_timeout)
3391{
562c8850 3392 s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
cf2b4488
HP
3393 '\0' + bitvec */
3394 int32 err = 0;
3395
3396 /* Setup timeout if Beacons are lost and roam is
3397 off to report link down */
3398 if (roamvar) {
3399 bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
3400 sizeof(iovbuf));
76c06459
JC
3401 err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
3402 if (unlikely(err)) {
cf2b4488
HP
3403 WL_ERR(("bcn_timeout error (%d)\n", err));
3404 goto dongle_rom_out;
3405 }
3406 }
3407 /* Enable/Disable built-in roaming to allow supplicant
3408 to take care of roaming */
3409 bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
76c06459
JC
3410 err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
3411 if (unlikely(err)) {
cf2b4488
HP
3412 WL_ERR(("roam_off error (%d)\n", err));
3413 goto dongle_rom_out;
3414 }
3415dongle_rom_out:
3416 return err;
3417}
3418
3419static int32 wl_dongle_eventmsg(struct net_device *ndev)
3420{
3421
562c8850 3422 s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
cf2b4488 3423 '\0' + bitvec */
562c8850 3424 s8 eventmask[WL_EVENTING_MASK_LEN];
cf2b4488
HP
3425 int32 err = 0;
3426
3427 /* Setup event_msgs */
3428 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
3429 sizeof(iovbuf));
76c06459
JC
3430 err = wl_dev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
3431 if (unlikely(err)) {
cf2b4488
HP
3432 WL_ERR(("Get event_msgs error (%d)\n", err));
3433 goto dongle_eventmsg_out;
3434 }
3435 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
3436
3437 setbit(eventmask, WLC_E_SET_SSID);
3438 setbit(eventmask, WLC_E_PRUNE);
3439 setbit(eventmask, WLC_E_AUTH);
3440 setbit(eventmask, WLC_E_REASSOC);
3441 setbit(eventmask, WLC_E_REASSOC_IND);
3442 setbit(eventmask, WLC_E_DEAUTH_IND);
3443 setbit(eventmask, WLC_E_DISASSOC_IND);
3444 setbit(eventmask, WLC_E_DISASSOC);
3445 setbit(eventmask, WLC_E_JOIN);
3446 setbit(eventmask, WLC_E_ASSOC_IND);
3447 setbit(eventmask, WLC_E_PSK_SUP);
3448 setbit(eventmask, WLC_E_LINK);
3449 setbit(eventmask, WLC_E_NDIS_LINK);
3450 setbit(eventmask, WLC_E_MIC_ERROR);
3451 setbit(eventmask, WLC_E_PMKID_CACHE);
3452 setbit(eventmask, WLC_E_TXFAIL);
3453 setbit(eventmask, WLC_E_JOIN_START);
3454 setbit(eventmask, WLC_E_SCAN_COMPLETE);
3455
3456 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
3457 sizeof(iovbuf));
76c06459
JC
3458 err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
3459 if (unlikely(err)) {
cf2b4488
HP
3460 WL_ERR(("Set event_msgs error (%d)\n", err));
3461 goto dongle_eventmsg_out;
3462 }
3463
3464dongle_eventmsg_out:
3465 return err;
3466}
3467
3468static int32
3469wl_dongle_scantime(struct net_device *ndev, int32 scan_assoc_time,
3470 int32 scan_unassoc_time)
3471{
3472 int32 err = 0;
3473
76c06459
JC
3474 err = wl_dev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
3475 sizeof(scan_assoc_time));
3476 if (err) {
cf2b4488
HP
3477 if (err == -EOPNOTSUPP) {
3478 WL_INFO(("Scan assoc time is not supported\n"));
3479 } else {
3480 WL_ERR(("Scan assoc time error (%d)\n", err));
3481 }
3482 goto dongle_scantime_out;
3483 }
76c06459
JC
3484 err = wl_dev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
3485 sizeof(scan_unassoc_time));
3486 if (err) {
cf2b4488
HP
3487 if (err == -EOPNOTSUPP) {
3488 WL_INFO(("Scan unassoc time is not supported\n"));
3489 } else {
3490 WL_ERR(("Scan unassoc time error (%d)\n", err));
3491 }
3492 goto dongle_scantime_out;
3493 }
3494
3495dongle_scantime_out:
3496 return err;
3497}
3498
3499static int32
3500wl_dongle_offload(struct net_device *ndev, int32 arpoe, int32 arp_ol)
3501{
562c8850 3502 s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
cf2b4488
HP
3503 '\0' + bitvec */
3504 int32 err = 0;
3505
3506 /* Set ARP offload */
3507 bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf));
76c06459
JC
3508 err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
3509 if (err) {
cf2b4488
HP
3510 if (err == -EOPNOTSUPP)
3511 WL_INFO(("arpoe is not supported\n"));
3512 else
3513 WL_ERR(("arpoe error (%d)\n", err));
3514
3515 goto dongle_offload_out;
3516 }
3517 bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf));
76c06459
JC
3518 err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
3519 if (err) {
cf2b4488
HP
3520 if (err == -EOPNOTSUPP)
3521 WL_INFO(("arp_ol is not supported\n"));
3522 else
3523 WL_ERR(("arp_ol error (%d)\n", err));
3524
3525 goto dongle_offload_out;
3526 }
3527
3528dongle_offload_out:
3529 return err;
3530}
3531
562c8850 3532static int32 wl_pattern_atoh(s8 *src, s8 *dst)
cf2b4488
HP
3533{
3534#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
3535 int i;
3536 if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
3537 WL_ERR(("Mask invalid format. Needs to start with 0x\n"));
3538 return -1;
3539 }
3540 src = src + 2; /* Skip past 0x */
3541 if (strlen(src) % 2 != 0) {
3542 WL_ERR(("Mask invalid format. Needs to be of even length\n"));
3543 return -1;
3544 }
3545 for (i = 0; *src != '\0'; i++) {
3546 char num[3];
3547 strncpy(num, src, 2);
3548 num[2] = '\0';
3fd79f7c 3549 dst[i] = (u8) strtoul(num, NULL, 16);
cf2b4488
HP
3550 src += 2;
3551 }
3552 return i;
3553}
3554
3555static int32 wl_dongle_filter(struct net_device *ndev, uint32 filter_mode)
3556{
562c8850 3557 s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
cf2b4488 3558 '\0' + bitvec */
562c8850 3559 const s8 *str;
cf2b4488
HP
3560 struct wl_pkt_filter pkt_filter;
3561 struct wl_pkt_filter *pkt_filterp;
3562 int32 buf_len;
3563 int32 str_len;
3564 uint32 mask_size;
3565 uint32 pattern_size;
562c8850 3566 s8 buf[256];
cf2b4488
HP
3567 int32 err = 0;
3568
3569/* add a default packet filter pattern */
3570 str = "pkt_filter_add";
3571 str_len = strlen(str);
3572 strncpy(buf, str, str_len);
3573 buf[str_len] = '\0';
3574 buf_len = str_len + 1;
3575
3576 pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1);
3577
3578 /* Parse packet filter id. */
3579 pkt_filter.id = htod32(100);
3580
3581 /* Parse filter polarity. */
3582 pkt_filter.negate_match = htod32(0);
3583
3584 /* Parse filter type. */
3585 pkt_filter.type = htod32(0);
3586
3587 /* Parse pattern filter offset. */
3588 pkt_filter.u.pattern.offset = htod32(0);
3589
3590 /* Parse pattern filter mask. */
3591 mask_size = htod32(wl_pattern_atoh("0xff",
3592 (char *)pkt_filterp->u.pattern.
3593 mask_and_pattern));
3594
3595 /* Parse pattern filter pattern. */
3596 pattern_size = htod32(wl_pattern_atoh("0x00",
3597 (char *)&pkt_filterp->u.pattern.
3598 mask_and_pattern[mask_size]));
3599
3600 if (mask_size != pattern_size) {
3601 WL_ERR(("Mask and pattern not the same size\n"));
3602 err = -EINVAL;
3603 goto dongle_filter_out;
3604 }
3605
3606 pkt_filter.u.pattern.size_bytes = mask_size;
3607 buf_len += WL_PKT_FILTER_FIXED_LEN;
3608 buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
3609
3610 /* Keep-alive attributes are set in local
3611 * variable (keep_alive_pkt), and
3612 * then memcpy'ed into buffer (keep_alive_pktp) since there is no
3613 * guarantee that the buffer is properly aligned.
3614 */
3615 memcpy((char *)pkt_filterp, &pkt_filter,
3616 WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
3617
76c06459
JC
3618 err = wl_dev_ioctl(ndev, WLC_SET_VAR, buf, buf_len);
3619 if (err) {
cf2b4488
HP
3620 if (err == -EOPNOTSUPP) {
3621 WL_INFO(("filter not supported\n"));
3622 } else {
3623 WL_ERR(("filter (%d)\n", err));
3624 }
3625 goto dongle_filter_out;
3626 }
3627
3628 /* set mode to allow pattern */
3629 bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf,
3630 sizeof(iovbuf));
76c06459
JC
3631 err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
3632 if (err) {
cf2b4488
HP
3633 if (err == -EOPNOTSUPP) {
3634 WL_INFO(("filter_mode not supported\n"));
3635 } else {
3636 WL_ERR(("filter_mode (%d)\n", err));
3637 }
3638 goto dongle_filter_out;
3639 }
3640
3641dongle_filter_out:
3642 return err;
3643}
3644#endif /* !EMBEDDED_PLATFORM */
3645
3646int32 wl_config_dongle(struct wl_priv *wl, bool need_lock)
3647{
3648#ifndef DHD_SDALIGN
3649#define DHD_SDALIGN 32
3650#endif
3651 struct net_device *ndev;
3652 struct wireless_dev *wdev;
3653 int32 err = 0;
3654
3655 if (wl->dongle_up)
3656 return err;
3657
3658 ndev = wl_to_ndev(wl);
3659 wdev = ndev->ieee80211_ptr;
3660 if (need_lock)
3661 rtnl_lock();
3662
3663#ifndef EMBEDDED_PLATFORM
76c06459
JC
3664 err = wl_dongle_up(ndev, 0);
3665 if (unlikely(err))
cf2b4488 3666 goto default_conf_out;
76c06459
JC
3667 err = wl_dongle_country(ndev, 0);
3668 if (unlikely(err))
cf2b4488 3669 goto default_conf_out;
76c06459
JC
3670 err = wl_dongle_power(ndev, PM_FAST);
3671 if (unlikely(err))
cf2b4488 3672 goto default_conf_out;
76c06459
JC
3673 err = wl_dongle_glom(ndev, 0, DHD_SDALIGN);
3674 if (unlikely(err))
cf2b4488 3675 goto default_conf_out;
76c06459
JC
3676 err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3);
3677 if (unlikely(err))
cf2b4488 3678 goto default_conf_out;
76c06459
JC
3679 err = wl_dongle_eventmsg(ndev);
3680 if (unlikely(err))
cf2b4488
HP
3681 goto default_conf_out;
3682
3683 wl_dongle_scantime(ndev, 40, 80);
3684 wl_dongle_offload(ndev, 1, 0xf);
3685 wl_dongle_filter(ndev, 1);
3686#endif /* !EMBEDDED_PLATFORM */
3687
3688 err = wl_dongle_mode(ndev, wdev->iftype);
3689 if (unlikely(err && err != -EINPROGRESS))
3690 goto default_conf_out;
76c06459
JC
3691 err = wl_dongle_probecap(wl);
3692 if (unlikely(err))
cf2b4488
HP
3693 goto default_conf_out;
3694
3695 /* -EINPROGRESS: Call commit handler */
3696
3697default_conf_out:
3698 if (need_lock)
3699 rtnl_unlock();
3700
3701 wl->dongle_up = TRUE;
3702
3703 return err;
3704
3705}
3706
3707static int32 wl_update_wiphybands(struct wl_priv *wl)
3708{
3709 struct wiphy *wiphy;
3710 int32 phy_list;
562c8850 3711 s8 phy;
cf2b4488
HP
3712 int32 err = 0;
3713
76c06459
JC
3714 err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_PHYLIST, &phy_list,
3715 sizeof(phy_list));
3716 if (unlikely(err)) {
cf2b4488
HP
3717 WL_ERR(("error (%d)\n", err));
3718 return err;
3719 }
3720
3721 phy = ((char *)&phy_list)[1];
3722 WL_DBG(("%c phy\n", phy));
3723 if (phy == 'n' || phy == 'a') {
3724 wiphy = wl_to_wiphy(wl);
3725 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
3726 }
3727
3728 return err;
3729}
3730
3731static int32 __wl_cfg80211_up(struct wl_priv *wl)
3732{
3733 int32 err = 0;
3734
76c06459
JC
3735 err = wl_config_dongle(wl, FALSE);
3736 if (unlikely(err))
cf2b4488
HP
3737 return err;
3738
3739 wl_invoke_iscan(wl);
3740 set_bit(WL_STATUS_READY, &wl->status);
3741 return err;
3742}
3743
3744static int32 __wl_cfg80211_down(struct wl_priv *wl)
3745{
3746 int32 err = 0;
3747
3748 /* Check if cfg80211 interface is already down */
3749 if (!test_bit(WL_STATUS_READY, &wl->status))
3750 return err; /* it is even not ready */
3751
3752 set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
3753 wl_term_iscan(wl);
3754 if (wl->scan_request) {
3755 cfg80211_scan_done(wl->scan_request, TRUE); /* TRUE
3756 means abort */
3757 wl->scan_request = NULL;
3758 }
3759 clear_bit(WL_STATUS_READY, &wl->status);
3760 clear_bit(WL_STATUS_SCANNING, &wl->status);
3761 clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
3762 clear_bit(WL_STATUS_CONNECTED, &wl->status);
3763
3764 return err;
3765}
3766
3767int32 wl_cfg80211_up(void)
3768{
3769 struct wl_priv *wl;
3770 int32 err = 0;
3771
3772 wl = WL_PRIV_GET();
3773 mutex_lock(&wl->usr_sync);
3774 err = __wl_cfg80211_up(wl);
3775 mutex_unlock(&wl->usr_sync);
3776
3777 return err;
3778}
3779
3780int32 wl_cfg80211_down(void)
3781{
3782 struct wl_priv *wl;
3783 int32 err = 0;
3784
3785 wl = WL_PRIV_GET();
3786 mutex_lock(&wl->usr_sync);
3787 err = __wl_cfg80211_down(wl);
3788 mutex_unlock(&wl->usr_sync);
3789
3790 return err;
3791}
3792
3793static int32 wl_dongle_probecap(struct wl_priv *wl)
3794{
3795 int32 err = 0;
3796
76c06459
JC
3797 err = wl_update_wiphybands(wl);
3798 if (unlikely(err))
cf2b4488
HP
3799 return err;
3800
3801 return err;
3802}
3803
3804static void *wl_read_prof(struct wl_priv *wl, int32 item)
3805{
3806 switch (item) {
3807 case WL_PROF_SEC:
3808 return &wl->profile->sec;
3809 case WL_PROF_ACT:
3810 return &wl->profile->active;
3811 case WL_PROF_BSSID:
3812 return &wl->profile->bssid;
3813 case WL_PROF_SSID:
3814 return &wl->profile->ssid;
3815 }
3816 WL_ERR(("invalid item (%d)\n", item));
3817 return NULL;
3818}
3819
3820static int32
3821wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data,
3822 int32 item)
3823{
3824 int32 err = 0;
3825 struct wlc_ssid *ssid;
3826
3827 switch (item) {
3828 case WL_PROF_SSID:
3829 ssid = (wlc_ssid_t *) data;
3830 memset(wl->profile->ssid.SSID, 0,
3831 sizeof(wl->profile->ssid.SSID));
3832 memcpy(wl->profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
3833 wl->profile->ssid.SSID_len = ssid->SSID_len;
3834 break;
3835 case WL_PROF_BSSID:
3836 if (data)
3837 memcpy(wl->profile->bssid, data, ETHER_ADDR_LEN);
3838 else
3839 memset(wl->profile->bssid, 0, ETHER_ADDR_LEN);
3840 break;
3841 case WL_PROF_SEC:
3842 memcpy(&wl->profile->sec, data, sizeof(wl->profile->sec));
3843 break;
3844 case WL_PROF_ACT:
3845 wl->profile->active = *(bool *) data;
3846 break;
3847 default:
3848 WL_ERR(("unsupported item (%d)\n", item));
3849 err = -EOPNOTSUPP;
3850 break;
3851 }
3852
3853 return err;
3854}
3855
3856void wl_cfg80211_dbg_level(uint32 level)
3857{
b3164c71 3858 /*
3859 * prohibit to change debug level
3860 * by insmod parameter.
3861 * eventually debug level will be configured
3862 * in compile time by using CONFIG_XXX
3863 */
3864 /* wl_dbg_level = level; */
cf2b4488
HP
3865}
3866
3867static bool wl_is_ibssmode(struct wl_priv *wl)
3868{
3869 return wl->conf->mode == WL_MODE_IBSS;
3870}
3871
3872static bool wl_is_ibssstarter(struct wl_priv *wl)
3873{
3874 return wl->ibss_starter;
3875}
3876
3877static void wl_rst_ie(struct wl_priv *wl)
3878{
3879 struct wl_ie *ie = wl_to_ie(wl);
3880
3881 ie->offset = 0;
3882}
3883
3fd79f7c 3884static int32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
cf2b4488
HP
3885{
3886 struct wl_ie *ie = wl_to_ie(wl);
3887 int32 err = 0;
3888
3889 if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
3890 WL_ERR(("ei crosses buffer boundary\n"));
3891 return -ENOSPC;
3892 }
3893 ie->buf[ie->offset] = t;
3894 ie->buf[ie->offset + 1] = l;
3895 memcpy(&ie->buf[ie->offset + 2], v, l);
3896 ie->offset += l + 2;
3897
3898 return err;
3899}
3900
3fd79f7c 3901static int32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, uint16 ie_size)
cf2b4488
HP
3902{
3903 struct wl_ie *ie = wl_to_ie(wl);
3904 int32 err = 0;
3905
3906 if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
3907 WL_ERR(("ei_stream crosses buffer boundary\n"));
3908 return -ENOSPC;
3909 }
3910 memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
3911 ie->offset += ie_size;
3912
3913 return err;
3914}
3915
3fd79f7c 3916static int32 wl_cp_ie(struct wl_priv *wl, u8 *dst, uint16 dst_size)
cf2b4488
HP
3917{
3918 struct wl_ie *ie = wl_to_ie(wl);
3919 int32 err = 0;
3920
3921 if (unlikely(ie->offset > dst_size)) {
3922 WL_ERR(("dst_size is not enough\n"));
3923 return -ENOSPC;
3924 }
3925 memcpy(dst, &ie->buf[0], ie->offset);
3926
3927 return err;
3928}
3929
3930static uint32 wl_get_ielen(struct wl_priv *wl)
3931{
3932 struct wl_ie *ie = wl_to_ie(wl);
3933
3934 return ie->offset;
3935}
3936
3937static void wl_link_up(struct wl_priv *wl)
3938{
3939 wl->link_up = TRUE;
3940}
3941
3942static void wl_link_down(struct wl_priv *wl)
3943{
3944 struct wl_connect_info *conn_info = wl_to_conn(wl);
3945
3946 wl->link_up = FALSE;
3947 kfree(conn_info->req_ie);
3948 conn_info->req_ie = NULL;
3949 conn_info->req_ie_len = 0;
3950 kfree(conn_info->resp_ie);
3951 conn_info->resp_ie = NULL;
3952 conn_info->resp_ie_len = 0;
3953}
3954
3955static void wl_lock_eq(struct wl_priv *wl)
3956{
3957 spin_lock_irq(&wl->eq_lock);
3958}
3959
3960static void wl_unlock_eq(struct wl_priv *wl)
3961{
3962 spin_unlock_irq(&wl->eq_lock);
3963}
3964
3965static void wl_init_eq_lock(struct wl_priv *wl)
3966{
3967 spin_lock_init(&wl->eq_lock);
3968}
3969
3970static void wl_delay(uint32 ms)
3971{
3972 if (ms < 1000 / HZ) {
3973 cond_resched();
3974 mdelay(ms);
3975 } else {
3976 msleep(ms);
3977 }
3978}
3979
3980static void wl_set_drvdata(struct wl_dev *dev, void *data)
3981{
3982 dev->driver_data = data;
3983}
3984
3985static void *wl_get_drvdata(struct wl_dev *dev)
3986{
3987 return dev->driver_data;
3988}
3989
562c8850 3990int32 wl_cfg80211_read_fw(s8 *buf, uint32 size)
cf2b4488
HP
3991{
3992 const struct firmware *fw_entry;
3993 struct wl_priv *wl;
3994
3995 wl = WL_PRIV_GET();
3996
3997 fw_entry = wl->fw->fw_entry;
3998
3999 if (fw_entry->size < wl->fw->ptr + size)
4000 size = fw_entry->size - wl->fw->ptr;
4001
4002 memcpy(buf, &fw_entry->data[wl->fw->ptr], size);
4003 wl->fw->ptr += size;
4004 return size;
4005}
4006
4007void wl_cfg80211_release_fw(void)
4008{
4009 struct wl_priv *wl;
4010
4011 wl = WL_PRIV_GET();
4012 release_firmware(wl->fw->fw_entry);
4013 wl->fw->ptr = 0;
4014}
4015
562c8850 4016void *wl_cfg80211_request_fw(s8 *file_name)
cf2b4488
HP
4017{
4018 struct wl_priv *wl;
4019 const struct firmware *fw_entry = NULL;
4020 int32 err = 0;
4021
4022 WL_DBG(("file name : \"%s\"\n", file_name));
4023 wl = WL_PRIV_GET();
4024
4025 if (!test_bit(WL_FW_LOADING_DONE, &wl->fw->status)) {
76c06459
JC
4026 err = request_firmware(&wl->fw->fw_entry, file_name,
4027 &wl_cfg80211_get_sdio_func()->dev);
4028 if (unlikely(err)) {
cf2b4488
HP
4029 WL_ERR(("Could not download fw (%d)\n", err));
4030 goto req_fw_out;
4031 }
4032 set_bit(WL_FW_LOADING_DONE, &wl->fw->status);
4033 fw_entry = wl->fw->fw_entry;
4034 if (fw_entry) {
4035 WL_DBG(("fw size (%d), data (%p)\n", fw_entry->size,
4036 fw_entry->data));
4037 }
4038 } else if (!test_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status)) {
76c06459
JC
4039 err = request_firmware(&wl->fw->fw_entry, file_name,
4040 &wl_cfg80211_get_sdio_func()->dev);
4041 if (unlikely(err)) {
cf2b4488
HP
4042 WL_ERR(("Could not download nvram (%d)\n", err));
4043 goto req_fw_out;
4044 }
4045 set_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status);
4046 fw_entry = wl->fw->fw_entry;
4047 if (fw_entry) {
4048 WL_DBG(("nvram size (%d), data (%p)\n", fw_entry->size,
4049 fw_entry->data));
4050 }
4051 } else {
4052 WL_DBG(("Downloading already done. Nothing to do more\n"));
4053 err = -EPERM;
4054 }
4055
4056req_fw_out:
4057 if (unlikely(err)) {
4058 return NULL;
4059 }
4060 wl->fw->ptr = 0;
4061 return (void *)fw_entry->data;
4062}
4063
562c8850 4064s8 *wl_cfg80211_get_fwname(void)
cf2b4488
HP
4065{
4066 struct wl_priv *wl;
4067
4068 wl = WL_PRIV_GET();
4069 strcpy(wl->fw->fw_name, WL_4329_FW_FILE);
4070 return wl->fw->fw_name;
4071}
4072
562c8850 4073s8 *wl_cfg80211_get_nvramname(void)
cf2b4488
HP
4074{
4075 struct wl_priv *wl;
4076
4077 wl = WL_PRIV_GET();
4078 strcpy(wl->fw->nvram_name, WL_4329_NVRAM_FILE);
4079 return wl->fw->nvram_name;
4080}
This page took 0.203559 seconds and 5 git commands to generate.