Staging: brcm80211: s/ulong/unsigned long/
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / brcm80211 / brcmfmac / wl_cfg80211.c
blobf8d07a5522b32034bafeec9f09a057fd699aca64
1 /*
2 * Copyright (c) 2010 Broadcom Corporation
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.
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.
17 #include <typedefs.h>
18 #include <linuxver.h>
19 #include <osl.h>
21 #include <bcmutils.h>
22 #include <bcmendian.h>
23 #include <proto/ethernet.h>
25 #include <linux/if_arp.h>
26 #include <asm/uaccess.h>
28 #include <dngl_stats.h>
29 #include <dhd.h>
30 #include <dhdioctl.h>
31 #include <wlioctl.h>
33 #include <proto/ethernet.h>
34 #include <dngl_stats.h>
35 #include <dhd.h>
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>
45 #include <net/rtnetlink.h>
46 #include <linux/mmc/sdio_func.h>
47 #include <linux/firmware.h>
48 #include <wl_cfg80211.h>
50 static struct sdio_func *cfg80211_sdio_func = NULL;
51 static struct wl_dev *wl_cfg80211_dev = NULL;
53 uint32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
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"
59 ** cfg80211_ops api/callback list
61 static 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);
65 static int32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
66 struct cfg80211_scan_request *request,
67 struct cfg80211_ssid *this_ssid);
68 static int32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
69 struct cfg80211_scan_request *request);
70 static int32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, uint32 changed);
71 static int32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
72 struct cfg80211_ibss_params *params);
73 static int32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
74 struct net_device *dev);
75 static int32 wl_cfg80211_get_station(struct wiphy *wiphy,
76 struct net_device *dev, u8 *mac,
77 struct station_info *sinfo);
78 static int32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
79 struct net_device *dev, bool enabled,
80 int32 timeout);
81 static int32 wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
82 struct net_device *dev,
83 const u8 *addr,
84 const struct cfg80211_bitrate_mask
85 *mask);
86 static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
87 struct cfg80211_connect_params *sme);
88 static int32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
89 uint16 reason_code);
90 static int32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
91 enum nl80211_tx_power_setting type,
92 int32 dbm);
93 static int32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, int32 *dbm);
94 static int32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
95 struct net_device *dev,
96 u8 key_idx);
97 static int32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
98 u8 key_idx, const u8 *mac_addr,
99 struct key_params *params);
100 static int32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
101 u8 key_idx, const u8 *mac_addr);
102 static int32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
103 u8 key_idx, const u8 *mac_addr,
104 void *cookie, void (*callback) (void *cookie,
105 struct
106 key_params *
107 params));
108 static int32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
109 struct net_device *dev,
110 u8 key_idx);
111 static int32 wl_cfg80211_resume(struct wiphy *wiphy);
112 static int32 wl_cfg80211_suspend(struct wiphy *wiphy);
113 static int32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
114 struct cfg80211_pmksa *pmksa);
115 static int32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
116 struct cfg80211_pmksa *pmksa);
117 static int32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
118 struct net_device *dev);
120 ** event & event Q handlers for cfg80211 interfaces
122 static int32 wl_create_event_handler(struct wl_priv *wl);
123 static void wl_destroy_event_handler(struct wl_priv *wl);
124 static int32 wl_event_handler(void *data);
125 static void wl_init_eq(struct wl_priv *wl);
126 static void wl_flush_eq(struct wl_priv *wl);
127 static void wl_lock_eq(struct wl_priv *wl);
128 static void wl_unlock_eq(struct wl_priv *wl);
129 static void wl_init_eq_lock(struct wl_priv *wl);
130 static void wl_init_eloop_handler(struct wl_event_loop *el);
131 static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
132 static int32 wl_enq_event(struct wl_priv *wl, uint32 type,
133 const wl_event_msg_t *msg, void *data);
134 static void wl_put_event(struct wl_event_q *e);
135 static void wl_wakeup_event(struct wl_priv *wl);
136 static int32 wl_notify_connect_status(struct wl_priv *wl,
137 struct net_device *ndev,
138 const wl_event_msg_t *e, void *data);
139 static int32 wl_notify_roaming_status(struct wl_priv *wl,
140 struct net_device *ndev,
141 const wl_event_msg_t *e, void *data);
142 static int32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
143 const wl_event_msg_t *e, void *data);
144 static int32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
145 const wl_event_msg_t *e, void *data);
146 static int32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
147 const wl_event_msg_t *e, void *data);
148 static int32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
149 const wl_event_msg_t *e, void *data);
152 ** register/deregister sdio function
154 static struct sdio_func *wl_sdio_func(void);
155 static void wl_clear_sdio_func(void);
158 ** ioctl utilites
160 static int32 wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
161 int32 buf_len);
162 static __used int32 wl_dev_bufvar_set(struct net_device *dev, s8 *name,
163 s8 *buf, int32 len);
164 static int32 wl_dev_intvar_set(struct net_device *dev, s8 *name, int32 val);
165 static int32 wl_dev_intvar_get(struct net_device *dev, s8 *name,
166 int32 *retval);
167 static int32 wl_dev_ioctl(struct net_device *dev, uint32 cmd, void *arg,
168 uint32 len);
171 ** cfg80211 set_wiphy_params utilities
173 static int32 wl_set_frag(struct net_device *dev, uint32 frag_threshold);
174 static int32 wl_set_rts(struct net_device *dev, uint32 frag_threshold);
175 static int32 wl_set_retry(struct net_device *dev, uint32 retry, bool l);
178 ** wl profile utilities
180 static int32 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e,
181 void *data, int32 item);
182 static void *wl_read_prof(struct wl_priv *wl, int32 item);
183 static void wl_init_prof(struct wl_profile *prof);
186 ** cfg80211 connect utilites
188 static int32 wl_set_wpa_version(struct net_device *dev,
189 struct cfg80211_connect_params *sme);
190 static int32 wl_set_auth_type(struct net_device *dev,
191 struct cfg80211_connect_params *sme);
192 static int32 wl_set_set_cipher(struct net_device *dev,
193 struct cfg80211_connect_params *sme);
194 static int32 wl_set_key_mgmt(struct net_device *dev,
195 struct cfg80211_connect_params *sme);
196 static int32 wl_set_set_sharedkey(struct net_device *dev,
197 struct cfg80211_connect_params *sme);
198 static int32 wl_get_assoc_ies(struct wl_priv *wl);
201 ** information element utilities
203 static void wl_rst_ie(struct wl_priv *wl);
204 static int32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
205 static int32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, uint16 ie_size);
206 static int32 wl_cp_ie(struct wl_priv *wl, u8 *dst, uint16 dst_size);
207 static uint32 wl_get_ielen(struct wl_priv *wl);
209 static int32 wl_mode_to_nl80211_iftype(int32 mode);
211 static struct wireless_dev *wl_alloc_wdev(int32 sizeof_iface,
212 struct device *dev);
213 static void wl_free_wdev(struct wl_priv *wl);
215 static int32 wl_inform_bss(struct wl_priv *wl);
216 static int32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
217 static int32 wl_update_bss_info(struct wl_priv *wl);
219 static int32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
220 u8 key_idx, const u8 *mac_addr,
221 struct key_params *params);
224 ** key indianess swap utilities
226 static void swap_key_from_BE(struct wl_wsec_key *key);
227 static void swap_key_to_BE(struct wl_wsec_key *key);
230 ** wl_priv memory init/deinit utilities
232 static int32 wl_init_priv_mem(struct wl_priv *wl);
233 static void wl_deinit_priv_mem(struct wl_priv *wl);
235 static void wl_delay(uint32 ms);
238 ** store/restore cfg80211 instance data
240 static void wl_set_drvdata(struct wl_dev *dev, void *data);
241 static void *wl_get_drvdata(struct wl_dev *dev);
244 ** ibss mode utilities
246 static bool wl_is_ibssmode(struct wl_priv *wl);
247 static bool wl_is_ibssstarter(struct wl_priv *wl);
250 ** dongle up/down , default configuration utilities
252 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
253 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e);
254 static void wl_link_up(struct wl_priv *wl);
255 static void wl_link_down(struct wl_priv *wl);
256 static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype);
257 static int32 __wl_cfg80211_up(struct wl_priv *wl);
258 static int32 __wl_cfg80211_down(struct wl_priv *wl);
259 static int32 wl_dongle_probecap(struct wl_priv *wl);
260 static void wl_init_conf(struct wl_conf *conf);
263 ** dongle configuration utilities
265 #ifndef EMBEDDED_PLATFORM
266 static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype);
267 static int32 wl_dongle_country(struct net_device *ndev, u8 ccode);
268 static int32 wl_dongle_up(struct net_device *ndev, uint32 up);
269 static int32 wl_dongle_power(struct net_device *ndev, uint32 power_mode);
270 static int32 wl_dongle_glom(struct net_device *ndev, uint32 glom,
271 uint32 dongle_align);
272 static int32 wl_dongle_roam(struct net_device *ndev, uint32 roamvar,
273 uint32 bcn_timeout);
274 static int32 wl_dongle_eventmsg(struct net_device *ndev);
275 static int32 wl_dongle_scantime(struct net_device *ndev, int32 scan_assoc_time,
276 int32 scan_unassoc_time);
277 static int32 wl_dongle_offload(struct net_device *ndev, int32 arpoe,
278 int32 arp_ol);
279 static int32 wl_pattern_atoh(s8 *src, s8 *dst);
280 static int32 wl_dongle_filter(struct net_device *ndev, uint32 filter_mode);
281 static int32 wl_update_wiphybands(struct wl_priv *wl);
282 #endif /* !EMBEDDED_PLATFORM */
283 static int32 wl_config_dongle(struct wl_priv *wl, bool need_lock);
286 ** iscan handler
288 static void wl_iscan_timer(unsigned long data);
289 static void wl_term_iscan(struct wl_priv *wl);
290 static int32 wl_init_iscan(struct wl_priv *wl);
291 static int32 wl_iscan_thread(void *data);
292 static int32 wl_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
293 void *param, int32 paramlen, void *bufptr,
294 int32 buflen);
295 static int32 wl_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
296 void *param, int32 paramlen, void *bufptr,
297 int32 buflen);
298 static int32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid,
299 uint16 action);
300 static int32 wl_do_iscan(struct wl_priv *wl);
301 static int32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
302 static int32 wl_invoke_iscan(struct wl_priv *wl);
303 static int32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, uint32 *status,
304 struct wl_scan_results **bss_list);
305 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
306 static void wl_init_iscan_eloop(struct wl_iscan_eloop *el);
307 static int32 wl_iscan_done(struct wl_priv *wl);
308 static int32 wl_iscan_pending(struct wl_priv *wl);
309 static int32 wl_iscan_inprogress(struct wl_priv *wl);
310 static int32 wl_iscan_aborted(struct wl_priv *wl);
313 ** fw/nvram downloading handler
315 static void wl_init_fw(struct wl_fw_ctrl *fw);
318 * find most significant bit set
320 static __used uint32 wl_find_msb(uint16 bit16);
323 * update pmklist to dongle
325 static __used int32 wl_update_pmklist(struct net_device *dev,
326 struct wl_pmk_list *pmk_list, int32 err);
328 #define WL_PRIV_GET() \
329 ({ \
330 struct wl_iface *ci; \
331 if (unlikely(!(wl_cfg80211_dev && \
332 (ci = wl_get_drvdata(wl_cfg80211_dev))))) { \
333 WL_ERR(("wl_cfg80211_dev is unavailable\n")); \
334 BUG(); \
336 ci_to_wl(ci); \
339 #define CHECK_SYS_UP() \
340 do { \
341 struct wl_priv *wl = wiphy_to_wl(wiphy); \
342 if (unlikely(!test_bit(WL_STATUS_READY, &wl->status))) { \
343 WL_INFO(("device is not ready : status (%d)\n", \
344 (int)wl->status)); \
345 return -EIO; \
347 } while (0)
349 extern int dhd_wait_pend8021x(struct net_device *dev);
351 #if (WL_DBG_LEVEL > 0)
352 #define WL_DBG_ESTR_MAX 32
353 static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
354 "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
355 "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
356 "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
357 "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
358 "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
359 "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
360 "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
361 "PFN_NET_LOST",
362 "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
363 "IBSS_ASSOC",
364 "RADIO", "PSM_WATCHDOG",
365 "PROBREQ_MSG",
366 "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
367 "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
368 "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
369 "IF",
370 "RSSI", "PFN_SCAN_COMPLETE", "ACTION_FRAME", "ACTION_FRAME_COMPLETE",
372 #endif /* WL_DBG_LEVEL */
374 #define CHAN2G(_channel, _freq, _flags) { \
375 .band = IEEE80211_BAND_2GHZ, \
376 .center_freq = (_freq), \
377 .hw_value = (_channel), \
378 .flags = (_flags), \
379 .max_antenna_gain = 0, \
380 .max_power = 30, \
383 #define CHAN5G(_channel, _flags) { \
384 .band = IEEE80211_BAND_5GHZ, \
385 .center_freq = 5000 + (5 * (_channel)), \
386 .hw_value = (_channel), \
387 .flags = (_flags), \
388 .max_antenna_gain = 0, \
389 .max_power = 30, \
392 #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
393 #define RATETAB_ENT(_rateid, _flags) \
395 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
396 .hw_value = (_rateid), \
397 .flags = (_flags), \
400 static struct ieee80211_rate __wl_rates[] = {
401 RATETAB_ENT(WLC_RATE_1M, 0),
402 RATETAB_ENT(WLC_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
403 RATETAB_ENT(WLC_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
404 RATETAB_ENT(WLC_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
405 RATETAB_ENT(WLC_RATE_6M, 0),
406 RATETAB_ENT(WLC_RATE_9M, 0),
407 RATETAB_ENT(WLC_RATE_12M, 0),
408 RATETAB_ENT(WLC_RATE_18M, 0),
409 RATETAB_ENT(WLC_RATE_24M, 0),
410 RATETAB_ENT(WLC_RATE_36M, 0),
411 RATETAB_ENT(WLC_RATE_48M, 0),
412 RATETAB_ENT(WLC_RATE_54M, 0),
415 #define wl_a_rates (__wl_rates + 4)
416 #define wl_a_rates_size 8
417 #define wl_g_rates (__wl_rates + 0)
418 #define wl_g_rates_size 12
420 static struct ieee80211_channel __wl_2ghz_channels[] = {
421 CHAN2G(1, 2412, 0),
422 CHAN2G(2, 2417, 0),
423 CHAN2G(3, 2422, 0),
424 CHAN2G(4, 2427, 0),
425 CHAN2G(5, 2432, 0),
426 CHAN2G(6, 2437, 0),
427 CHAN2G(7, 2442, 0),
428 CHAN2G(8, 2447, 0),
429 CHAN2G(9, 2452, 0),
430 CHAN2G(10, 2457, 0),
431 CHAN2G(11, 2462, 0),
432 CHAN2G(12, 2467, 0),
433 CHAN2G(13, 2472, 0),
434 CHAN2G(14, 2484, 0),
437 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
438 CHAN5G(34, 0), CHAN5G(36, 0),
439 CHAN5G(38, 0), CHAN5G(40, 0),
440 CHAN5G(42, 0), CHAN5G(44, 0),
441 CHAN5G(46, 0), CHAN5G(48, 0),
442 CHAN5G(52, 0), CHAN5G(56, 0),
443 CHAN5G(60, 0), CHAN5G(64, 0),
444 CHAN5G(100, 0), CHAN5G(104, 0),
445 CHAN5G(108, 0), CHAN5G(112, 0),
446 CHAN5G(116, 0), CHAN5G(120, 0),
447 CHAN5G(124, 0), CHAN5G(128, 0),
448 CHAN5G(132, 0), CHAN5G(136, 0),
449 CHAN5G(140, 0), CHAN5G(149, 0),
450 CHAN5G(153, 0), CHAN5G(157, 0),
451 CHAN5G(161, 0), CHAN5G(165, 0),
452 CHAN5G(184, 0), CHAN5G(188, 0),
453 CHAN5G(192, 0), CHAN5G(196, 0),
454 CHAN5G(200, 0), CHAN5G(204, 0),
455 CHAN5G(208, 0), CHAN5G(212, 0),
456 CHAN5G(216, 0),
459 static struct ieee80211_channel __wl_5ghz_n_channels[] = {
460 CHAN5G(32, 0), CHAN5G(34, 0),
461 CHAN5G(36, 0), CHAN5G(38, 0),
462 CHAN5G(40, 0), CHAN5G(42, 0),
463 CHAN5G(44, 0), CHAN5G(46, 0),
464 CHAN5G(48, 0), CHAN5G(50, 0),
465 CHAN5G(52, 0), CHAN5G(54, 0),
466 CHAN5G(56, 0), CHAN5G(58, 0),
467 CHAN5G(60, 0), CHAN5G(62, 0),
468 CHAN5G(64, 0), CHAN5G(66, 0),
469 CHAN5G(68, 0), CHAN5G(70, 0),
470 CHAN5G(72, 0), CHAN5G(74, 0),
471 CHAN5G(76, 0), CHAN5G(78, 0),
472 CHAN5G(80, 0), CHAN5G(82, 0),
473 CHAN5G(84, 0), CHAN5G(86, 0),
474 CHAN5G(88, 0), CHAN5G(90, 0),
475 CHAN5G(92, 0), CHAN5G(94, 0),
476 CHAN5G(96, 0), CHAN5G(98, 0),
477 CHAN5G(100, 0), CHAN5G(102, 0),
478 CHAN5G(104, 0), CHAN5G(106, 0),
479 CHAN5G(108, 0), CHAN5G(110, 0),
480 CHAN5G(112, 0), CHAN5G(114, 0),
481 CHAN5G(116, 0), CHAN5G(118, 0),
482 CHAN5G(120, 0), CHAN5G(122, 0),
483 CHAN5G(124, 0), CHAN5G(126, 0),
484 CHAN5G(128, 0), CHAN5G(130, 0),
485 CHAN5G(132, 0), CHAN5G(134, 0),
486 CHAN5G(136, 0), CHAN5G(138, 0),
487 CHAN5G(140, 0), CHAN5G(142, 0),
488 CHAN5G(144, 0), CHAN5G(145, 0),
489 CHAN5G(146, 0), CHAN5G(147, 0),
490 CHAN5G(148, 0), CHAN5G(149, 0),
491 CHAN5G(150, 0), CHAN5G(151, 0),
492 CHAN5G(152, 0), CHAN5G(153, 0),
493 CHAN5G(154, 0), CHAN5G(155, 0),
494 CHAN5G(156, 0), CHAN5G(157, 0),
495 CHAN5G(158, 0), CHAN5G(159, 0),
496 CHAN5G(160, 0), CHAN5G(161, 0),
497 CHAN5G(162, 0), CHAN5G(163, 0),
498 CHAN5G(164, 0), CHAN5G(165, 0),
499 CHAN5G(166, 0), CHAN5G(168, 0),
500 CHAN5G(170, 0), CHAN5G(172, 0),
501 CHAN5G(174, 0), CHAN5G(176, 0),
502 CHAN5G(178, 0), CHAN5G(180, 0),
503 CHAN5G(182, 0), CHAN5G(184, 0),
504 CHAN5G(186, 0), CHAN5G(188, 0),
505 CHAN5G(190, 0), CHAN5G(192, 0),
506 CHAN5G(194, 0), CHAN5G(196, 0),
507 CHAN5G(198, 0), CHAN5G(200, 0),
508 CHAN5G(202, 0), CHAN5G(204, 0),
509 CHAN5G(206, 0), CHAN5G(208, 0),
510 CHAN5G(210, 0), CHAN5G(212, 0),
511 CHAN5G(214, 0), CHAN5G(216, 0),
512 CHAN5G(218, 0), CHAN5G(220, 0),
513 CHAN5G(222, 0), CHAN5G(224, 0),
514 CHAN5G(226, 0), CHAN5G(228, 0),
517 static struct ieee80211_supported_band __wl_band_2ghz = {
518 .band = IEEE80211_BAND_2GHZ,
519 .channels = __wl_2ghz_channels,
520 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
521 .bitrates = wl_g_rates,
522 .n_bitrates = wl_g_rates_size,
525 static struct ieee80211_supported_band __wl_band_5ghz_a = {
526 .band = IEEE80211_BAND_5GHZ,
527 .channels = __wl_5ghz_a_channels,
528 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
529 .bitrates = wl_a_rates,
530 .n_bitrates = wl_a_rates_size,
533 static struct ieee80211_supported_band __wl_band_5ghz_n = {
534 .band = IEEE80211_BAND_5GHZ,
535 .channels = __wl_5ghz_n_channels,
536 .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
537 .bitrates = wl_a_rates,
538 .n_bitrates = wl_a_rates_size,
541 static const uint32 __wl_cipher_suites[] = {
542 WLAN_CIPHER_SUITE_WEP40,
543 WLAN_CIPHER_SUITE_WEP104,
544 WLAN_CIPHER_SUITE_TKIP,
545 WLAN_CIPHER_SUITE_CCMP,
546 WLAN_CIPHER_SUITE_AES_CMAC,
549 static void swap_key_from_BE(struct wl_wsec_key *key)
551 key->index = htod32(key->index);
552 key->len = htod32(key->len);
553 key->algo = htod32(key->algo);
554 key->flags = htod32(key->flags);
555 key->rxiv.hi = htod32(key->rxiv.hi);
556 key->rxiv.lo = htod16(key->rxiv.lo);
557 key->iv_initialized = htod32(key->iv_initialized);
560 static void swap_key_to_BE(struct wl_wsec_key *key)
562 key->index = dtoh32(key->index);
563 key->len = dtoh32(key->len);
564 key->algo = dtoh32(key->algo);
565 key->flags = dtoh32(key->flags);
566 key->rxiv.hi = dtoh32(key->rxiv.hi);
567 key->rxiv.lo = dtoh16(key->rxiv.lo);
568 key->iv_initialized = dtoh32(key->iv_initialized);
571 static int32
572 wl_dev_ioctl(struct net_device *dev, uint32 cmd, void *arg, uint32 len)
574 struct ifreq ifr;
575 struct wl_ioctl ioc;
576 mm_segment_t fs;
577 int32 err = 0;
579 memset(&ioc, 0, sizeof(ioc));
580 ioc.cmd = cmd;
581 ioc.buf = arg;
582 ioc.len = len;
583 strcpy(ifr.ifr_name, dev->name);
584 ifr.ifr_data = (caddr_t)&ioc;
586 fs = get_fs();
587 set_fs(get_ds());
588 err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
589 set_fs(fs);
591 return err;
594 static int32
595 wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
596 enum nl80211_iftype type, uint32 *flags,
597 struct vif_params *params)
599 struct wl_priv *wl = wiphy_to_wl(wiphy);
600 struct wireless_dev *wdev;
601 int32 infra = 0;
602 int32 ap = 0;
603 int32 err = 0;
605 CHECK_SYS_UP();
606 switch (type) {
607 case NL80211_IFTYPE_MONITOR:
608 case NL80211_IFTYPE_WDS:
609 WL_ERR(("type (%d) : currently we do not support this type\n",
610 type));
611 return -EOPNOTSUPP;
612 case NL80211_IFTYPE_ADHOC:
613 wl->conf->mode = WL_MODE_IBSS;
614 break;
615 case NL80211_IFTYPE_STATION:
616 wl->conf->mode = WL_MODE_BSS;
617 infra = 1;
618 break;
619 default:
620 return -EINVAL;
622 infra = htod32(infra);
623 ap = htod32(ap);
624 wdev = ndev->ieee80211_ptr;
625 wdev->iftype = type;
626 WL_DBG(("%s : ap (%d), infra (%d)\n", ndev->name, ap, infra));
627 if (unlikely
628 ((err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra))))
630 unlikely((err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap))))) {
631 WL_ERR(("Error (%d)\n", err));
632 return err;
634 /* -EINPROGRESS: Call commit handler */
635 return -EINPROGRESS;
638 static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
640 memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
641 params->bss_type = DOT11_BSSTYPE_ANY;
642 params->scan_type = 0;
643 params->nprobes = -1;
644 params->active_time = -1;
645 params->passive_time = -1;
646 params->home_time = -1;
647 params->channel_num = 0;
649 params->nprobes = htod32(params->nprobes);
650 params->active_time = htod32(params->active_time);
651 params->passive_time = htod32(params->passive_time);
652 params->home_time = htod32(params->home_time);
653 if (ssid && ssid->SSID_len)
654 memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
658 static int32
659 wl_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
660 int32 paramlen, void *bufptr, int32 buflen)
662 int32 iolen;
664 iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
665 BUG_ON(unlikely(!iolen));
667 return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
670 static int32
671 wl_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
672 int32 paramlen, void *bufptr, int32 buflen)
674 int32 iolen;
676 iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
677 BUG_ON(unlikely(!iolen));
679 return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
682 static int32
683 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, uint16 action)
685 int32 params_size =
686 (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params));
687 struct wl_iscan_params *params;
688 int32 err = 0;
690 if (ssid && ssid->SSID_len)
691 params_size += sizeof(struct wlc_ssid);
692 params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
693 if (unlikely(!params))
694 return -ENOMEM;
695 memset(params, 0, params_size);
696 BUG_ON(unlikely(params_size >= WLC_IOCTL_SMLEN));
698 wl_iscan_prep(&params->params, ssid);
700 params->version = htod32(ISCAN_REQ_VERSION);
701 params->action = htod16(action);
702 params->scan_duration = htod16(0);
704 /* params_size += OFFSETOF(wl_iscan_params_t, params); */
705 if (unlikely
706 ((err =
707 wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
708 iscan->ioctl_buf, WLC_IOCTL_SMLEN)))) {
709 if (err == -EBUSY) {
710 WL_INFO(("system busy : iscan canceled\n"));
711 } else {
712 WL_ERR(("error (%d)\n", err));
715 kfree(params);
716 return err;
719 static int32 wl_do_iscan(struct wl_priv *wl)
721 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
722 struct wlc_ssid ssid;
723 int32 err = 0;
725 /* Broadcast scan by default */
726 memset(&ssid, 0, sizeof(ssid));
728 iscan->state = WL_ISCAN_STATE_SCANING;
730 if (wl->active_scan) {
731 int32 passive_scan = 0;
732 /* make it active scan */
733 if (unlikely
734 ((err =
735 wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN,
736 &passive_scan, sizeof(passive_scan))))) {
737 WL_DBG(("error (%d)\n", err));
738 return err;
741 wl->iscan_kickstart = TRUE;
742 wl_run_iscan(iscan, &ssid, WL_SCAN_ACTION_START);
743 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
744 iscan->timer_on = 1;
746 return err;
749 static int32
750 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
751 struct cfg80211_scan_request *request,
752 struct cfg80211_ssid *this_ssid)
754 struct wl_priv *wl = ndev_to_wl(ndev);
755 struct cfg80211_ssid *ssids;
756 struct wl_scan_req *sr = wl_to_sr(wl);
757 uint32 n_ssids;
758 bool iscan_req;
759 bool spec_scan;
760 int32 err = 0;
762 if (unlikely(test_bit(WL_STATUS_SCANNING, &wl->status))) {
763 WL_ERR(("Scanning already : status (%d)\n", (int)wl->status));
764 return -EAGAIN;
766 if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &wl->status))) {
767 WL_ERR(("Scanning being aborted : status (%d)\n",
768 (int)wl->status));
769 return -EAGAIN;
772 iscan_req = FALSE;
773 spec_scan = FALSE;
774 if (request) { /* scan bss */
775 ssids = request->ssids;
776 n_ssids = min(request->n_ssids, WL_NUM_SCAN_MAX);
777 if (wl->iscan_on && n_ssids && !ssids->ssid_len) { /* for
778 * specific scan,
779 * ssids->ssid_len has
780 * non-zero(ssid string)
781 * length.
782 * Otherwise this is 0.
783 * we do not iscan for
784 * specific scan request
786 iscan_req = TRUE;
788 } else { /* scan in ibss */
789 /* we don't do iscan in ibss */
790 ssids = this_ssid;
791 n_ssids = 1;
793 wl->scan_request = request;
794 set_bit(WL_STATUS_SCANNING, &wl->status);
795 if (iscan_req) {
796 if (likely(!(err = wl_do_iscan(wl))))
797 return err;
798 else
799 goto scan_out;
800 } else {
801 WL_DBG(("n_ssid (%d), ssid \"%s\", ssid_len (%d)\n",
802 n_ssids, ssids->ssid, ssids->ssid_len));
803 memset(&sr->ssid, 0, sizeof(sr->ssid));
804 if (n_ssids) {
805 sr->ssid.SSID_len =
806 MIN(sizeof(sr->ssid.SSID), ssids->ssid_len);
807 if (sr->ssid.SSID_len) {
808 memcpy(sr->ssid.SSID, ssids->ssid,
809 sr->ssid.SSID_len);
810 sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
811 WL_DBG(("Specific scan ssid=\"%s\" len=%d\n",
812 sr->ssid.SSID, sr->ssid.SSID_len));
813 spec_scan = TRUE;
814 } else {
815 WL_DBG(("Broadcast scan\n"));
817 } else {
818 /* broadcast scan */
819 WL_DBG(("Broadcast scan\n"));
821 WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
822 if (wl->active_scan) {
823 int32 pssive_scan = 0;
824 /* make it active scan */
825 if (unlikely
826 ((err =
827 wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
828 &pssive_scan,
829 sizeof(pssive_scan))))) {
830 WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n",
831 err));
832 goto scan_out;
835 if ((err =
836 wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid,
837 sizeof(sr->ssid)))) {
838 if (err == -EBUSY) {
839 WL_INFO(("system busy : scan for \"%s\" "
840 "canceled\n", sr->ssid.SSID));
841 } else {
842 WL_ERR(("WLC_SCAN error (%d)\n", err));
844 goto scan_out;
848 return 0;
850 scan_out:
851 clear_bit(WL_STATUS_SCANNING, &wl->status);
852 wl->scan_request = NULL;
853 return err;
856 static int32
857 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
858 struct cfg80211_scan_request *request)
860 int32 err = 0;
862 CHECK_SYS_UP();
863 if (unlikely((err = __wl_cfg80211_scan(wiphy, ndev, request, NULL)))) {
864 WL_DBG(("scan error (%d)\n", err));
865 return err;
868 return err;
871 static int32 wl_dev_intvar_set(struct net_device *dev, s8 *name, int32 val)
873 s8 buf[WLC_IOCTL_SMLEN];
874 uint32 len;
875 int32 err = 0;
877 val = htod32(val);
878 len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
879 BUG_ON(unlikely(!len));
881 if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len)))) {
882 WL_ERR(("error (%d)\n", err));
885 return err;
888 static int32
889 wl_dev_intvar_get(struct net_device *dev, s8 *name, int32 *retval)
891 union {
892 s8 buf[WLC_IOCTL_SMLEN];
893 int32 val;
894 } var;
895 uint32 len;
896 uint32 data_null;
897 int32 err = 0;
899 len =
900 bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
901 sizeof(var.buf));
902 BUG_ON(unlikely(!len));
903 if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len)))) {
904 WL_ERR(("error (%d)\n", err));
906 *retval = dtoh32(var.val);
908 return err;
911 static int32 wl_set_rts(struct net_device *dev, uint32 rts_threshold)
913 int32 err = 0;
915 if (unlikely
916 ((err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold)))) {
917 WL_ERR(("Error (%d)\n", err));
918 return err;
920 return err;
923 static int32 wl_set_frag(struct net_device *dev, uint32 frag_threshold)
925 int32 err = 0;
927 if (unlikely
928 ((err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold)))) {
929 WL_ERR(("Error (%d)\n", err));
930 return err;
932 return err;
935 static int32 wl_set_retry(struct net_device *dev, uint32 retry, bool l)
937 int32 err = 0;
938 uint32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
940 retry = htod32(retry);
941 if (unlikely((err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry))))) {
942 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
943 return err;
945 return err;
948 static int32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, uint32 changed)
950 struct wl_priv *wl = wiphy_to_wl(wiphy);
951 struct net_device *ndev = wl_to_ndev(wl);
952 int32 err = 0;
954 CHECK_SYS_UP();
955 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
956 (wl->conf->rts_threshold != wiphy->rts_threshold)) {
957 wl->conf->rts_threshold = wiphy->rts_threshold;
958 if (!(err = wl_set_rts(ndev, wl->conf->rts_threshold)))
959 return err;
961 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
962 (wl->conf->frag_threshold != wiphy->frag_threshold)) {
963 wl->conf->frag_threshold = wiphy->frag_threshold;
964 if (!(err = wl_set_frag(ndev, wl->conf->frag_threshold)))
965 return err;
967 if (changed & WIPHY_PARAM_RETRY_LONG
968 && (wl->conf->retry_long != wiphy->retry_long)) {
969 wl->conf->retry_long = wiphy->retry_long;
970 if (!(err = wl_set_retry(ndev, wl->conf->retry_long, TRUE)))
971 return err;
973 if (changed & WIPHY_PARAM_RETRY_SHORT
974 && (wl->conf->retry_short != wiphy->retry_short)) {
975 wl->conf->retry_short = wiphy->retry_short;
976 if (!(err = wl_set_retry(ndev, wl->conf->retry_short, FALSE))) {
977 return err;
981 return err;
984 static int32
985 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
986 struct cfg80211_ibss_params *params)
988 struct wl_priv *wl = wiphy_to_wl(wiphy);
989 struct cfg80211_bss *bss;
990 struct ieee80211_channel *chan;
991 struct wl_join_params join_params;
992 struct cfg80211_ssid ssid;
993 int32 scan_retry = 0;
994 int32 err = 0;
996 CHECK_SYS_UP();
997 if (params->bssid) {
998 WL_ERR(("Invalid bssid\n"));
999 return -EOPNOTSUPP;
1001 bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
1002 if (!bss) {
1003 memcpy(ssid.ssid, params->ssid, params->ssid_len);
1004 ssid.ssid_len = params->ssid_len;
1005 do {
1006 if (unlikely
1007 (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
1008 -EBUSY)) {
1009 wl_delay(150);
1010 } else {
1011 break;
1013 } while (++scan_retry < WL_SCAN_RETRY_MAX);
1014 rtnl_unlock(); /* to allow scan_inform to paropagate
1015 to cfg80211 plane */
1016 schedule_timeout_interruptible(4 * HZ); /* wait 4 secons
1017 till scan done.... */
1018 rtnl_lock();
1019 bss = cfg80211_get_ibss(wiphy, NULL,
1020 params->ssid, params->ssid_len);
1022 if (bss) {
1023 wl->ibss_starter = FALSE;
1024 WL_DBG(("Found IBSS\n"));
1025 } else {
1026 wl->ibss_starter = TRUE;
1028 if ((chan = params->channel))
1029 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
1031 ** Join with specific BSSID and cached SSID
1032 ** If SSID is zero join based on BSSID only
1034 memset(&join_params, 0, sizeof(join_params));
1035 memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
1036 params->ssid_len);
1037 join_params.ssid.SSID_len = htod32(params->ssid_len);
1038 if (params->bssid)
1039 memcpy(&join_params.params.bssid, params->bssid,
1040 ETHER_ADDR_LEN);
1041 else
1042 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
1044 if (unlikely
1045 ((err =
1046 wl_dev_ioctl(dev, WLC_SET_SSID, &join_params,
1047 sizeof(join_params))))) {
1048 WL_ERR(("Error (%d)\n", err));
1049 return err;
1051 return err;
1054 static int32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1056 struct wl_priv *wl = wiphy_to_wl(wiphy);
1057 int32 err = 0;
1059 CHECK_SYS_UP();
1060 wl_link_down(wl);
1062 return err;
1065 static int32
1066 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
1068 struct wl_priv *wl = ndev_to_wl(dev);
1069 struct wl_security *sec;
1070 int32 val = 0;
1071 int32 err = 0;
1073 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1074 val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED;
1075 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1076 val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED;
1077 else
1078 val = WPA_AUTH_DISABLED;
1079 WL_DBG(("setting wpa_auth to 0x%0x\n", val));
1080 if (unlikely((err = wl_dev_intvar_set(dev, "wpa_auth", val)))) {
1081 WL_ERR(("set wpa_auth failed (%d)\n", err));
1082 return err;
1084 sec = wl_read_prof(wl, WL_PROF_SEC);
1085 sec->wpa_versions = sme->crypto.wpa_versions;
1086 return err;
1089 static int32
1090 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
1092 struct wl_priv *wl = ndev_to_wl(dev);
1093 struct wl_security *sec;
1094 int32 val = 0;
1095 int32 err = 0;
1097 switch (sme->auth_type) {
1098 case NL80211_AUTHTYPE_OPEN_SYSTEM:
1099 val = 0;
1100 WL_DBG(("open system\n"));
1101 break;
1102 case NL80211_AUTHTYPE_SHARED_KEY:
1103 val = 1;
1104 WL_DBG(("shared key\n"));
1105 break;
1106 case NL80211_AUTHTYPE_AUTOMATIC:
1107 val = 2;
1108 WL_DBG(("automatic\n"));
1109 break;
1110 case NL80211_AUTHTYPE_NETWORK_EAP:
1111 WL_DBG(("network eap\n"));
1112 default:
1113 val = 2;
1114 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
1115 break;
1118 if (unlikely((err = wl_dev_intvar_set(dev, "auth", val)))) {
1119 WL_ERR(("set auth failed (%d)\n", err));
1120 return err;
1122 sec = wl_read_prof(wl, WL_PROF_SEC);
1123 sec->auth_type = sme->auth_type;
1124 return err;
1127 static int32
1128 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
1130 struct wl_priv *wl = ndev_to_wl(dev);
1131 struct wl_security *sec;
1132 int32 pval = 0;
1133 int32 gval = 0;
1134 int32 err = 0;
1136 if (sme->crypto.n_ciphers_pairwise) {
1137 switch (sme->crypto.ciphers_pairwise[0]) {
1138 case WLAN_CIPHER_SUITE_WEP40:
1139 case WLAN_CIPHER_SUITE_WEP104:
1140 pval = WEP_ENABLED;
1141 break;
1142 case WLAN_CIPHER_SUITE_TKIP:
1143 pval = TKIP_ENABLED;
1144 break;
1145 case WLAN_CIPHER_SUITE_CCMP:
1146 pval = AES_ENABLED;
1147 break;
1148 case WLAN_CIPHER_SUITE_AES_CMAC:
1149 pval = AES_ENABLED;
1150 break;
1151 default:
1152 WL_ERR(("invalid cipher pairwise (%d)\n",
1153 sme->crypto.ciphers_pairwise[0]));
1154 return -EINVAL;
1157 if (sme->crypto.cipher_group) {
1158 switch (sme->crypto.cipher_group) {
1159 case WLAN_CIPHER_SUITE_WEP40:
1160 case WLAN_CIPHER_SUITE_WEP104:
1161 gval = WEP_ENABLED;
1162 break;
1163 case WLAN_CIPHER_SUITE_TKIP:
1164 gval = TKIP_ENABLED;
1165 break;
1166 case WLAN_CIPHER_SUITE_CCMP:
1167 gval = AES_ENABLED;
1168 break;
1169 case WLAN_CIPHER_SUITE_AES_CMAC:
1170 gval = AES_ENABLED;
1171 break;
1172 default:
1173 WL_ERR(("invalid cipher group (%d)\n",
1174 sme->crypto.cipher_group));
1175 return -EINVAL;
1179 WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
1180 if (unlikely((err = wl_dev_intvar_set(dev, "wsec", pval | gval)))) {
1181 WL_ERR(("error (%d)\n", err));
1182 return err;
1185 sec = wl_read_prof(wl, WL_PROF_SEC);
1186 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
1187 sec->cipher_group = sme->crypto.cipher_group;
1189 return err;
1192 static int32
1193 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
1195 struct wl_priv *wl = ndev_to_wl(dev);
1196 struct wl_security *sec;
1197 int32 val = 0;
1198 int32 err = 0;
1200 if (sme->crypto.n_akm_suites) {
1201 if (unlikely((err = wl_dev_intvar_get(dev, "wpa_auth", &val)))) {
1202 WL_ERR(("could not get wpa_auth (%d)\n", err));
1203 return err;
1205 if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) {
1206 switch (sme->crypto.akm_suites[0]) {
1207 case WLAN_AKM_SUITE_8021X:
1208 val = WPA_AUTH_UNSPECIFIED;
1209 break;
1210 case WLAN_AKM_SUITE_PSK:
1211 val = WPA_AUTH_PSK;
1212 break;
1213 default:
1214 WL_ERR(("invalid cipher group (%d)\n",
1215 sme->crypto.cipher_group));
1216 return -EINVAL;
1218 } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
1219 switch (sme->crypto.akm_suites[0]) {
1220 case WLAN_AKM_SUITE_8021X:
1221 val = WPA2_AUTH_UNSPECIFIED;
1222 break;
1223 case WLAN_AKM_SUITE_PSK:
1224 val = WPA2_AUTH_PSK;
1225 break;
1226 default:
1227 WL_ERR(("invalid cipher group (%d)\n",
1228 sme->crypto.cipher_group));
1229 return -EINVAL;
1233 WL_DBG(("setting wpa_auth to %d\n", val));
1234 if (unlikely((err = wl_dev_intvar_set(dev, "wpa_auth", val)))) {
1235 WL_ERR(("could not set wpa_auth (%d)\n", err));
1236 return err;
1239 sec = wl_read_prof(wl, WL_PROF_SEC);
1240 sec->wpa_auth = sme->crypto.akm_suites[0];
1242 return err;
1245 static int32
1246 wl_set_set_sharedkey(struct net_device *dev,
1247 struct cfg80211_connect_params *sme)
1249 struct wl_priv *wl = ndev_to_wl(dev);
1250 struct wl_security *sec;
1251 struct wl_wsec_key key;
1252 int32 val;
1253 int32 err = 0;
1255 WL_DBG(("key len (%d)\n", sme->key_len));
1256 if (sme->key_len) {
1257 sec = wl_read_prof(wl, WL_PROF_SEC);
1258 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
1259 sec->wpa_versions, sec->cipher_pairwise));
1260 if (!
1261 (sec->wpa_versions & (NL80211_WPA_VERSION_1 |
1262 NL80211_WPA_VERSION_2))
1263 && (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
1264 WLAN_CIPHER_SUITE_WEP104))) {
1265 memset(&key, 0, sizeof(key));
1266 key.len = (uint32) sme->key_len;
1267 key.index = (uint32) sme->key_idx;
1268 if (unlikely(key.len > sizeof(key.data))) {
1269 WL_ERR(("Too long key length (%u)\n", key.len));
1270 return -EINVAL;
1272 memcpy(key.data, sme->key, key.len);
1273 key.flags = WL_PRIMARY_KEY;
1274 switch (sec->cipher_pairwise) {
1275 case WLAN_CIPHER_SUITE_WEP40:
1276 key.algo = CRYPTO_ALGO_WEP1;
1277 break;
1278 case WLAN_CIPHER_SUITE_WEP104:
1279 key.algo = CRYPTO_ALGO_WEP128;
1280 break;
1281 default:
1282 WL_ERR(("Invalid algorithm (%d)\n",
1283 sme->crypto.ciphers_pairwise[0]));
1284 return -EINVAL;
1286 /* Set the new key/index */
1287 WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
1288 key.len, key.index, key.algo));
1289 WL_DBG(("key \"%s\"\n", key.data));
1290 swap_key_from_BE(&key);
1291 if (unlikely
1292 ((err =
1293 wl_dev_ioctl(dev, WLC_SET_KEY, &key,
1294 sizeof(key))))) {
1295 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
1296 return err;
1298 if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
1299 WL_DBG(("set auth_type to shared key\n"));
1300 val = 1; /* shared key */
1301 if (unlikely
1302 ((err =
1303 wl_dev_intvar_set(dev, "auth", val)))) {
1304 WL_ERR(("set auth failed (%d)\n", err));
1305 return err;
1310 return err;
1313 static int32
1314 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
1315 struct cfg80211_connect_params *sme)
1317 struct wl_priv *wl = wiphy_to_wl(wiphy);
1318 struct ieee80211_channel *chan = sme->channel;
1319 struct wlc_ssid ssid;
1320 int32 err = 0;
1322 CHECK_SYS_UP();
1323 if (unlikely(!sme->ssid)) {
1324 WL_ERR(("Invalid ssid\n"));
1325 return -EOPNOTSUPP;
1327 if (chan) {
1328 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
1329 WL_DBG(("channel (%d), center_req (%d)\n", wl->channel,
1330 chan->center_freq));
1332 WL_DBG(("ie (%p), ie_len (%d)\n", sme->ie, sme->ie_len));
1333 if (unlikely((err = wl_set_wpa_version(dev, sme))))
1334 return err;
1336 if (unlikely((err = wl_set_auth_type(dev, sme))))
1337 return err;
1339 if (unlikely((err = wl_set_set_cipher(dev, sme))))
1340 return err;
1342 if (unlikely((err = wl_set_key_mgmt(dev, sme))))
1343 return err;
1345 if (unlikely((err = wl_set_set_sharedkey(dev, sme))))
1346 return err;
1348 wl_update_prof(wl, NULL, sme->bssid, WL_PROF_BSSID);
1350 ** Join with specific BSSID and cached SSID
1351 ** If SSID is zero join based on BSSID only
1353 memset(&ssid, 0, sizeof(ssid));
1354 ssid.SSID_len = MIN(sizeof(ssid.SSID), sme->ssid_len);
1355 memcpy(ssid.SSID, sme->ssid, ssid.SSID_len);
1356 ssid.SSID_len = htod32(ssid.SSID_len);
1357 wl_update_prof(wl, NULL, &ssid, WL_PROF_SSID);
1358 if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
1359 WL_DBG(("ssid \"%s\", len (%d)\n", ssid.SSID, ssid.SSID_len));
1361 if (unlikely
1362 ((err = wl_dev_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid))))) {
1363 WL_ERR(("error (%d)\n", err));
1364 return err;
1366 set_bit(WL_STATUS_CONNECTING, &wl->status);
1368 return err;
1371 static int32
1372 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
1373 uint16 reason_code)
1375 struct wl_priv *wl = wiphy_to_wl(wiphy);
1376 scb_val_t scbval;
1377 bool act = FALSE;
1378 int32 err = 0;
1380 WL_DBG(("Reason %d\n", reason_code));
1381 CHECK_SYS_UP();
1382 if (likely((act = *(bool *) wl_read_prof(wl, WL_PROF_ACT)))) {
1383 scbval.val = reason_code;
1384 memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
1385 scbval.val = htod32(scbval.val);
1386 if (unlikely((err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
1387 sizeof(scb_val_t))))) {
1388 WL_ERR(("error (%d)\n", err));
1389 return err;
1393 return err;
1396 static int32
1397 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
1398 enum nl80211_tx_power_setting type, int32 dbm)
1401 struct wl_priv *wl = wiphy_to_wl(wiphy);
1402 struct net_device *ndev = wl_to_ndev(wl);
1403 uint16 txpwrmw;
1404 int32 err = 0;
1405 int32 disable = 0;
1407 CHECK_SYS_UP();
1408 switch (type) {
1409 case NL80211_TX_POWER_AUTOMATIC:
1410 break;
1411 case NL80211_TX_POWER_LIMITED:
1412 if (dbm < 0) {
1413 WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
1414 return -EINVAL;
1416 break;
1417 case NL80211_TX_POWER_FIXED:
1418 if (dbm < 0) {
1419 WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
1420 return -EINVAL;
1422 break;
1424 /* Make sure radio is off or on as far as software is concerned */
1425 disable = WL_RADIO_SW_DISABLE << 16;
1426 disable = htod32(disable);
1427 if (unlikely
1428 ((err =
1429 wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable))))) {
1430 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
1431 return err;
1434 if (dbm > 0xffff)
1435 txpwrmw = 0xffff;
1436 else
1437 txpwrmw = (uint16) dbm;
1438 if (unlikely((err = wl_dev_intvar_set(ndev, "qtxpower",
1439 (int32) (bcm_mw_to_qdbm
1440 (txpwrmw)))))) {
1441 WL_ERR(("qtxpower error (%d)\n", err));
1442 return err;
1444 wl->conf->tx_power = dbm;
1446 return err;
1449 static int32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, int32 *dbm)
1451 struct wl_priv *wl = wiphy_to_wl(wiphy);
1452 struct net_device *ndev = wl_to_ndev(wl);
1453 int32 txpwrdbm;
1454 u8 result;
1455 int32 err = 0;
1457 CHECK_SYS_UP();
1458 if (unlikely((err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm)))) {
1459 WL_ERR(("error (%d)\n", err));
1460 return err;
1462 result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
1463 *dbm = (int32) bcm_qdbm_to_mw(result);
1465 return err;
1468 static int32
1469 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
1470 u8 key_idx)
1472 uint32 index;
1473 int32 wsec;
1474 int32 err = 0;
1476 WL_DBG(("key index (%d)\n", key_idx));
1477 CHECK_SYS_UP();
1479 if (unlikely
1480 (err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) {
1481 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
1482 return err;
1484 wsec = dtoh32(wsec);
1485 if (wsec & WEP_ENABLED) {
1486 /* Just select a new current key */
1487 index = (uint32) key_idx;
1488 index = htod32(index);
1489 if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY,
1490 &index, sizeof(index))))) {
1491 WL_ERR(("error (%d)\n", err));
1494 return err;
1497 static int32
1498 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
1499 u8 key_idx, const u8 *mac_addr, struct key_params *params)
1501 struct wl_wsec_key key;
1502 int32 err = 0;
1504 memset(&key, 0, sizeof(key));
1505 key.index = (uint32) key_idx;
1506 /* Instead of bcast for ea address for default wep keys,
1507 driver needs it to be Null */
1508 if (!ETHER_ISMULTI(mac_addr))
1509 memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
1510 key.len = (uint32) params->key_len;
1511 /* check for key index change */
1512 if (key.len == 0) {
1513 /* key delete */
1514 swap_key_from_BE(&key);
1515 if (unlikely
1516 ((err =
1517 wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) {
1518 WL_ERR(("key delete error (%d)\n", err));
1519 return err;
1521 } else {
1522 if (key.len > sizeof(key.data)) {
1523 WL_ERR(("Invalid key length (%d)\n", key.len));
1524 return -EINVAL;
1527 WL_DBG(("Setting the key index %d\n", key.index));
1528 memcpy(key.data, params->key, key.len);
1530 if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
1531 u8 keybuf[8];
1532 memcpy(keybuf, &key.data[24], sizeof(keybuf));
1533 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
1534 memcpy(&key.data[16], keybuf, sizeof(keybuf));
1537 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
1538 if (params->seq && params->seq_len == 6) {
1539 /* rx iv */
1540 u8 *ivptr;
1541 ivptr = (u8 *) params->seq;
1542 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
1543 (ivptr[3] << 8) | ivptr[2];
1544 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
1545 key.iv_initialized = TRUE;
1548 switch (params->cipher) {
1549 case WLAN_CIPHER_SUITE_WEP40:
1550 key.algo = CRYPTO_ALGO_WEP1;
1551 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
1552 break;
1553 case WLAN_CIPHER_SUITE_WEP104:
1554 key.algo = CRYPTO_ALGO_WEP128;
1555 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
1556 break;
1557 case WLAN_CIPHER_SUITE_TKIP:
1558 key.algo = CRYPTO_ALGO_TKIP;
1559 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
1560 break;
1561 case WLAN_CIPHER_SUITE_AES_CMAC:
1562 key.algo = CRYPTO_ALGO_AES_CCM;
1563 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
1564 break;
1565 case WLAN_CIPHER_SUITE_CCMP:
1566 key.algo = CRYPTO_ALGO_AES_CCM;
1567 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
1568 break;
1569 default:
1570 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
1571 return -EINVAL;
1573 swap_key_from_BE(&key);
1575 dhd_wait_pend8021x(dev);
1576 if (unlikely
1577 ((err =
1578 wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) {
1579 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
1580 return err;
1583 return err;
1586 static int32
1587 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
1588 u8 key_idx, const u8 *mac_addr,
1589 struct key_params *params)
1591 struct wl_wsec_key key;
1592 int32 val;
1593 int32 wsec;
1594 int32 err = 0;
1596 WL_DBG(("key index (%d)\n", key_idx));
1597 CHECK_SYS_UP();
1599 if (mac_addr)
1600 return wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
1601 memset(&key, 0, sizeof(key));
1603 key.len = (uint32) params->key_len;
1604 key.index = (uint32) key_idx;
1606 if (unlikely(key.len > sizeof(key.data))) {
1607 WL_ERR(("Too long key length (%u)\n", key.len));
1608 return -EINVAL;
1610 memcpy(key.data, params->key, key.len);
1612 key.flags = WL_PRIMARY_KEY;
1613 switch (params->cipher) {
1614 case WLAN_CIPHER_SUITE_WEP40:
1615 key.algo = CRYPTO_ALGO_WEP1;
1616 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
1617 break;
1618 case WLAN_CIPHER_SUITE_WEP104:
1619 key.algo = CRYPTO_ALGO_WEP128;
1620 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
1621 break;
1622 case WLAN_CIPHER_SUITE_TKIP:
1623 key.algo = CRYPTO_ALGO_TKIP;
1624 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
1625 break;
1626 case WLAN_CIPHER_SUITE_AES_CMAC:
1627 key.algo = CRYPTO_ALGO_AES_CCM;
1628 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
1629 break;
1630 case WLAN_CIPHER_SUITE_CCMP:
1631 key.algo = CRYPTO_ALGO_AES_CCM;
1632 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
1633 break;
1634 default:
1635 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
1636 return -EINVAL;
1639 /* Set the new key/index */
1640 swap_key_from_BE(&key);
1641 if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY,
1642 &key, sizeof(key))))) {
1643 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
1644 return err;
1647 val = WEP_ENABLED;
1648 if (unlikely((err = wl_dev_intvar_get(dev, "wsec", &wsec)))) {
1649 WL_ERR(("get wsec error (%d)\n", err));
1650 return err;
1652 wsec &= ~(WEP_ENABLED);
1653 wsec |= val;
1654 if (unlikely((err = wl_dev_intvar_set(dev, "wsec", wsec)))) {
1655 WL_ERR(("set wsec error (%d)\n", err));
1656 return err;
1659 val = 1; /* assume shared key. otherwise 0 */
1660 val = htod32(val);
1661 if (unlikely
1662 ((err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))) {
1663 WL_ERR(("WLC_SET_AUTH error (%d)\n", err));
1664 return err;
1666 return err;
1669 static int32
1670 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
1671 u8 key_idx, const u8 *mac_addr)
1673 struct wl_wsec_key key;
1674 int32 err = 0;
1675 int32 val;
1676 int32 wsec;
1678 CHECK_SYS_UP();
1679 memset(&key, 0, sizeof(key));
1681 key.index = (uint32) key_idx;
1682 key.flags = WL_PRIMARY_KEY;
1683 key.algo = CRYPTO_ALGO_OFF;
1685 WL_DBG(("key index (%d)\n", key_idx));
1686 /* Set the new key/index */
1687 swap_key_from_BE(&key);
1688 if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY,
1689 &key, sizeof(key))))) {
1690 if (err == -EINVAL) {
1691 if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
1692 /* we ignore this key index in this case */
1693 WL_DBG(("invalid key index (%d)\n", key_idx));
1695 } else {
1696 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
1698 return err;
1701 val = 0;
1702 if (unlikely((err = wl_dev_intvar_get(dev, "wsec", &wsec)))) {
1703 WL_ERR(("get wsec error (%d)\n", err));
1704 return err;
1706 wsec &= ~(WEP_ENABLED);
1707 wsec |= val;
1708 if (unlikely((err = wl_dev_intvar_set(dev, "wsec", wsec)))) {
1709 WL_ERR(("set wsec error (%d)\n", err));
1710 return err;
1713 val = 0; /* assume open key. otherwise 1 */
1714 val = htod32(val);
1715 if (unlikely
1716 ((err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))) {
1717 WL_ERR(("WLC_SET_AUTH error (%d)\n", err));
1718 return err;
1720 return err;
1723 static int32
1724 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
1725 u8 key_idx, const u8 *mac_addr, void *cookie,
1726 void (*callback) (void *cookie, struct key_params * params))
1728 struct key_params params;
1729 struct wl_wsec_key key;
1730 struct wl_priv *wl = wiphy_to_wl(wiphy);
1731 struct wl_security *sec;
1732 int32 wsec;
1733 int32 err = 0;
1735 WL_DBG(("key index (%d)\n", key_idx));
1736 CHECK_SYS_UP();
1738 memset(&key, 0, sizeof(key));
1739 key.index = key_idx;
1740 swap_key_to_BE(&key);
1741 memset(&params, 0, sizeof(params));
1742 params.key_len = (u8) MIN(DOT11_MAX_KEY_SIZE, key.len);
1743 memcpy(params.key, key.data, params.key_len);
1745 if (unlikely
1746 (err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) {
1747 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
1748 return err;
1750 wsec = dtoh32(wsec);
1751 switch (wsec) {
1752 case WEP_ENABLED:
1753 sec = wl_read_prof(wl, WL_PROF_SEC);
1754 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
1755 params.cipher = WLAN_CIPHER_SUITE_WEP40;
1756 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
1757 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
1758 params.cipher = WLAN_CIPHER_SUITE_WEP104;
1759 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
1761 break;
1762 case TKIP_ENABLED:
1763 params.cipher = WLAN_CIPHER_SUITE_TKIP;
1764 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
1765 break;
1766 case AES_ENABLED:
1767 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
1768 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
1769 break;
1770 default:
1771 WL_ERR(("Invalid algo (0x%x)\n", wsec));
1772 return -EINVAL;
1775 callback(cookie, &params);
1776 return err;
1779 static int32
1780 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
1781 struct net_device *dev, u8 key_idx)
1783 WL_INFO(("Not supported\n"));
1784 CHECK_SYS_UP();
1785 return -EOPNOTSUPP;
1788 static int32
1789 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
1790 u8 *mac, struct station_info *sinfo)
1792 struct wl_priv *wl = wiphy_to_wl(wiphy);
1793 scb_val_t scb_val;
1794 int rssi;
1795 int32 rate;
1796 int32 err = 0;
1798 CHECK_SYS_UP();
1799 if (unlikely
1800 (memcmp(mac, wl_read_prof(wl, WL_PROF_BSSID), ETHER_ADDR_LEN))) {
1801 WL_ERR(("Wrong Mac address\n"));
1802 return -ENOENT;
1805 /* Report the current tx rate */
1806 if ((err = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate)))) {
1807 WL_ERR(("Could not get rate (%d)\n", err));
1808 } else {
1809 rate = dtoh32(rate);
1810 sinfo->filled |= STATION_INFO_TX_BITRATE;
1811 sinfo->txrate.legacy = rate * 5;
1812 WL_DBG(("Rate %d Mbps\n", (rate / 2)));
1815 if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
1816 scb_val.val = 0;
1817 if (unlikely
1818 (err =
1819 wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val,
1820 sizeof(scb_val_t)))) {
1821 WL_ERR(("Could not get rssi (%d)\n", err));
1822 return err;
1824 rssi = dtoh32(scb_val.val);
1825 sinfo->filled |= STATION_INFO_SIGNAL;
1826 sinfo->signal = rssi;
1827 WL_DBG(("RSSI %d dBm\n", rssi));
1830 return err;
1833 static int32
1834 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
1835 bool enabled, int32 timeout)
1837 int32 pm;
1838 int32 err = 0;
1840 CHECK_SYS_UP();
1841 pm = enabled ? PM_FAST : PM_OFF;
1842 pm = htod32(pm);
1843 WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
1844 if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))) {
1845 if (err == -ENODEV)
1846 WL_DBG(("net_device is not ready yet\n"));
1847 else
1848 WL_ERR(("error (%d)\n", err));
1849 return err;
1851 return err;
1854 static __used uint32 wl_find_msb(uint16 bit16)
1856 uint32 ret = 0;
1858 if (bit16 & 0xff00) {
1859 ret += 8;
1860 bit16 >>= 8;
1863 if (bit16 & 0xf0) {
1864 ret += 4;
1865 bit16 >>= 4;
1868 if (bit16 & 0xc) {
1869 ret += 2;
1870 bit16 >>= 2;
1873 if (bit16 & 2)
1874 ret += bit16 & 2;
1875 else if (bit16)
1876 ret += bit16;
1878 return ret;
1881 static int32
1882 wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
1883 const u8 *addr,
1884 const struct cfg80211_bitrate_mask *mask)
1886 struct wl_rateset rateset;
1887 int32 rate;
1888 int32 val;
1889 int32 err_bg;
1890 int32 err_a;
1891 uint32 legacy;
1892 int32 err = 0;
1894 CHECK_SYS_UP();
1895 /* addr param is always NULL. ignore it */
1896 /* Get current rateset */
1897 if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
1898 sizeof(rateset))))) {
1899 WL_ERR(("could not get current rateset (%d)\n", err));
1900 return err;
1903 rateset.count = dtoh32(rateset.count);
1905 if (!(legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy)))
1906 legacy = wl_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy);
1908 val = wl_g_rates[legacy - 1].bitrate * 100000;
1910 if (val < rateset.count) {
1911 /* Select rate by rateset index */
1912 rate = rateset.rates[val] & 0x7f;
1913 } else {
1914 /* Specified rate in bps */
1915 rate = val / 500000;
1918 WL_DBG(("rate %d mbps\n", (rate / 2)));
1922 * Set rate override,
1923 * Since the is a/b/g-blind, both a/bg_rate are enforced.
1925 err_bg = wl_dev_intvar_set(dev, "bg_rate", rate);
1926 err_a = wl_dev_intvar_set(dev, "a_rate", rate);
1927 if (unlikely(err_bg && err_a)) {
1928 WL_ERR(("could not set fixed rate (%d) (%d)\n", err_bg, err_a));
1929 return err_bg | err_a;
1932 return err;
1935 static int32 wl_cfg80211_resume(struct wiphy *wiphy)
1937 int32 err = 0;
1939 CHECK_SYS_UP();
1940 wl_invoke_iscan(wiphy_to_wl(wiphy));
1942 return err;
1945 static int32 wl_cfg80211_suspend(struct wiphy *wiphy)
1947 struct wl_priv *wl = wiphy_to_wl(wiphy);
1948 int32 err = 0;
1950 CHECK_SYS_UP();
1952 set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
1953 wl_term_iscan(wl);
1954 if (wl->scan_request) {
1955 cfg80211_scan_done(wl->scan_request, TRUE); /* TRUE means
1956 abort */
1957 wl->scan_request = NULL;
1959 clear_bit(WL_STATUS_SCANNING, &wl->status);
1960 clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
1962 return err;
1965 static __used int32
1966 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
1967 int32 err)
1969 s8 eabuf[ETHER_ADDR_STR_LEN];
1970 int i, j;
1972 memset(eabuf, 0, ETHER_ADDR_STR_LEN);
1974 WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
1975 for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
1976 WL_DBG(("PMKID[%d]: %s =\n", i,
1977 bcm_ether_ntoa(&pmk_list->pmkids.pmkid[i].BSSID,
1978 eabuf)));
1979 for (j = 0; j < WPA2_PMKID_LEN; j++) {
1980 WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
1983 if (likely(!err)) {
1984 err = wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list,
1985 sizeof(*pmk_list));
1988 return err;
1991 static int32
1992 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
1993 struct cfg80211_pmksa *pmksa)
1995 struct wl_priv *wl = wiphy_to_wl(wiphy);
1996 s8 eabuf[ETHER_ADDR_STR_LEN];
1997 int32 err = 0;
1998 int i;
2000 CHECK_SYS_UP();
2001 memset(eabuf, 0, ETHER_ADDR_STR_LEN);
2002 for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
2003 if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
2004 ETHER_ADDR_LEN))
2005 break;
2006 if (i < WL_NUM_PMKIDS_MAX) {
2007 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
2008 ETHER_ADDR_LEN);
2009 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
2010 WPA2_PMKID_LEN);
2011 if (i == wl->pmk_list->pmkids.npmkid)
2012 wl->pmk_list->pmkids.npmkid++;
2013 } else {
2014 err = -EINVAL;
2016 WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %s =\n",
2017 bcm_ether_ntoa(&wl->pmk_list->pmkids.
2018 pmkid[wl->pmk_list->pmkids.npmkid].BSSID,
2019 eabuf)));
2020 for (i = 0; i < WPA2_PMKID_LEN; i++) {
2021 WL_DBG(("%02x\n",
2022 wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].
2023 PMKID[i]));
2026 err = wl_update_pmklist(dev, wl->pmk_list, err);
2028 return err;
2031 static int32
2032 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
2033 struct cfg80211_pmksa *pmksa)
2035 struct wl_priv *wl = wiphy_to_wl(wiphy);
2036 s8 eabuf[ETHER_ADDR_STR_LEN];
2037 struct _pmkid_list pmkid;
2038 int32 err = 0;
2039 int i;
2041 CHECK_SYS_UP();
2042 memset(eabuf, 0, ETHER_ADDR_STR_LEN);
2043 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
2044 memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
2046 WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %s =\n",
2047 bcm_ether_ntoa(&pmkid.pmkid[0].BSSID, eabuf)));
2048 for (i = 0; i < WPA2_PMKID_LEN; i++) {
2049 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
2052 for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
2053 if (!memcmp
2054 (pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
2055 ETHER_ADDR_LEN))
2056 break;
2058 if ((wl->pmk_list->pmkids.npmkid > 0)
2059 && (i < wl->pmk_list->pmkids.npmkid)) {
2060 memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
2061 for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
2062 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
2063 &wl->pmk_list->pmkids.pmkid[i + 1].BSSID,
2064 ETHER_ADDR_LEN);
2065 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
2066 &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
2067 WPA2_PMKID_LEN);
2069 wl->pmk_list->pmkids.npmkid--;
2070 } else {
2071 err = -EINVAL;
2074 err = wl_update_pmklist(dev, wl->pmk_list, err);
2076 return err;
2080 static int32
2081 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
2083 struct wl_priv *wl = wiphy_to_wl(wiphy);
2084 int32 err = 0;
2086 CHECK_SYS_UP();
2087 memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
2088 err = wl_update_pmklist(dev, wl->pmk_list, err);
2089 return err;
2093 static struct cfg80211_ops wl_cfg80211_ops = {
2094 .change_virtual_intf = wl_cfg80211_change_iface,
2095 .scan = wl_cfg80211_scan,
2096 .set_wiphy_params = wl_cfg80211_set_wiphy_params,
2097 .join_ibss = wl_cfg80211_join_ibss,
2098 .leave_ibss = wl_cfg80211_leave_ibss,
2099 .get_station = wl_cfg80211_get_station,
2100 .set_tx_power = wl_cfg80211_set_tx_power,
2101 .get_tx_power = wl_cfg80211_get_tx_power,
2102 .add_key = wl_cfg80211_add_key,
2103 .del_key = wl_cfg80211_del_key,
2104 .get_key = wl_cfg80211_get_key,
2105 .set_default_key = wl_cfg80211_config_default_key,
2106 .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
2107 .set_power_mgmt = wl_cfg80211_set_power_mgmt,
2108 .set_bitrate_mask = wl_cfg80211_set_bitrate_mask,
2109 .connect = wl_cfg80211_connect,
2110 .disconnect = wl_cfg80211_disconnect,
2111 .suspend = wl_cfg80211_suspend,
2112 .resume = wl_cfg80211_resume,
2113 .set_pmksa = wl_cfg80211_set_pmksa,
2114 .del_pmksa = wl_cfg80211_del_pmksa,
2115 .flush_pmksa = wl_cfg80211_flush_pmksa
2118 static int32 wl_mode_to_nl80211_iftype(int32 mode)
2120 int32 err = 0;
2122 switch (mode) {
2123 case WL_MODE_BSS:
2124 return NL80211_IFTYPE_STATION;
2125 case WL_MODE_IBSS:
2126 return NL80211_IFTYPE_ADHOC;
2127 default:
2128 return NL80211_IFTYPE_UNSPECIFIED;
2131 return err;
2134 static struct wireless_dev *wl_alloc_wdev(int32 sizeof_iface,
2135 struct device *dev)
2137 struct wireless_dev *wdev;
2138 int32 err = 0;
2140 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
2141 if (unlikely(!wdev)) {
2142 WL_ERR(("Could not allocate wireless device\n"));
2143 return ERR_PTR(-ENOMEM);
2145 wdev->wiphy =
2146 wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv) + sizeof_iface);
2147 if (unlikely(!wdev->wiphy)) {
2148 WL_ERR(("Couldn not allocate wiphy device\n"));
2149 err = -ENOMEM;
2150 goto wiphy_new_out;
2152 set_wiphy_dev(wdev->wiphy, dev);
2153 wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
2154 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
2155 wdev->wiphy->interface_modes =
2156 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
2157 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
2158 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set
2159 * it as 11a by default.
2160 * This will be updated with
2161 * 11n phy tables in
2162 * "ifconfig up"
2163 * if phy has 11n capability
2165 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
2166 wdev->wiphy->cipher_suites = __wl_cipher_suites;
2167 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
2168 #ifndef WL_POWERSAVE_DISABLED
2169 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power
2170 * save mode
2171 * by default
2173 #else
2174 wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
2175 #endif /* !WL_POWERSAVE_DISABLED */
2176 if (unlikely(((err = wiphy_register(wdev->wiphy)) < 0))) {
2177 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
2178 goto wiphy_register_out;
2180 return wdev;
2182 wiphy_register_out:
2183 wiphy_free(wdev->wiphy);
2185 wiphy_new_out:
2186 kfree(wdev);
2188 return ERR_PTR(err);
2191 static void wl_free_wdev(struct wl_priv *wl)
2193 struct wireless_dev *wdev = wl_to_wdev(wl);
2195 if (unlikely(!wdev)) {
2196 WL_ERR(("wdev is invalid\n"));
2197 return;
2199 wiphy_unregister(wdev->wiphy);
2200 wiphy_free(wdev->wiphy);
2201 kfree(wdev);
2202 wl_to_wdev(wl) = NULL;
2205 static int32 wl_inform_bss(struct wl_priv *wl)
2207 struct wl_scan_results *bss_list;
2208 struct wl_bss_info *bi = NULL; /* must be initialized */
2209 int32 err = 0;
2210 int i;
2212 bss_list = wl->bss_list;
2213 if (unlikely(bss_list->version != WL_BSS_INFO_VERSION)) {
2214 WL_ERR(("Version %d != WL_BSS_INFO_VERSION\n",
2215 bss_list->version));
2216 return -EOPNOTSUPP;
2218 WL_DBG(("scanned AP count (%d)\n", bss_list->count));
2219 bi = next_bss(bss_list, bi);
2220 for_each_bss(bss_list, bi, i) {
2221 if (unlikely(err = wl_inform_single_bss(wl, bi)))
2222 break;
2224 return err;
2227 static int32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
2229 struct wiphy *wiphy = wl_to_wiphy(wl);
2230 struct ieee80211_mgmt *mgmt;
2231 struct ieee80211_channel *channel;
2232 struct ieee80211_supported_band *band;
2233 struct wl_cfg80211_bss_info *notif_bss_info;
2234 struct wl_scan_req *sr = wl_to_sr(wl);
2235 uint32 signal;
2236 uint32 freq;
2237 int32 err = 0;
2239 if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
2240 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
2241 return err;
2243 notif_bss_info =
2244 kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(u8) +
2245 WL_BSS_INFO_MAX, GFP_KERNEL);
2246 if (unlikely(!notif_bss_info)) {
2247 WL_ERR(("notif_bss_info alloc failed\n"));
2248 return -ENOMEM;
2250 mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
2251 notif_bss_info->channel = CHSPEC_CHANNEL(bi->chanspec);
2252 if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
2253 band = wiphy->bands[IEEE80211_BAND_2GHZ];
2254 else
2255 band = wiphy->bands[IEEE80211_BAND_5GHZ];
2256 notif_bss_info->rssi = bi->RSSI;
2257 memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
2258 if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
2259 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2260 IEEE80211_STYPE_PROBE_RESP);
2262 mgmt->u.probe_resp.timestamp = 0;
2263 mgmt->u.probe_resp.beacon_int = cpu_to_le16(bi->beacon_period);
2264 mgmt->u.probe_resp.capab_info = cpu_to_le16(bi->capability);
2265 wl_rst_ie(wl);
2266 wl_add_ie(wl, WLAN_EID_SSID, bi->SSID_len, bi->SSID);
2267 wl_add_ie(wl, WLAN_EID_SUPP_RATES, bi->rateset.count,
2268 bi->rateset.rates);
2269 wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
2270 wl_cp_ie(wl, mgmt->u.probe_resp.variable, WL_BSS_INFO_MAX -
2271 offsetof(struct wl_cfg80211_bss_info, frame_buf));
2272 notif_bss_info->frame_len =
2273 offsetof(struct ieee80211_mgmt,
2274 u.probe_resp.variable) + wl_get_ielen(wl);
2275 freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
2276 channel = ieee80211_get_channel(wiphy, freq);
2278 WL_DBG(("SSID : \"%s\", rssi (%d), capability : 0x04%x\n", bi->SSID,
2279 notif_bss_info->rssi, mgmt->u.probe_resp.capab_info));
2281 signal = notif_bss_info->rssi * 100;
2282 if (unlikely(!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
2283 le16_to_cpu
2284 (notif_bss_info->frame_len),
2285 signal, GFP_KERNEL))) {
2286 WL_ERR(("cfg80211_inform_bss_frame error\n"));
2287 kfree(notif_bss_info);
2288 return -EINVAL;
2290 kfree(notif_bss_info);
2292 return err;
2295 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
2297 uint32 event = ntoh32(e->event_type);
2298 uint16 flags = ntoh16(e->flags);
2300 if (event == WLC_E_JOIN || event == WLC_E_ASSOC_IND
2301 || event == WLC_E_REASSOC_IND) {
2302 return TRUE;
2303 } else if (event == WLC_E_LINK) {
2304 if (flags & WLC_EVENT_MSG_LINK) {
2305 if (wl_is_ibssmode(wl)) {
2306 if (wl_is_ibssstarter(wl)) {
2308 } else {
2314 return FALSE;
2317 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
2319 uint32 event = ntoh32(e->event_type);
2320 uint16 flags = ntoh16(e->flags);
2322 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
2323 return TRUE;
2324 } else if (event == WLC_E_LINK) {
2325 if (!(flags & WLC_EVENT_MSG_LINK))
2326 return TRUE;
2329 return FALSE;
2332 static int32
2333 wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
2334 const wl_event_msg_t *e, void *data)
2336 bool act;
2337 int32 err = 0;
2339 if (wl_is_linkup(wl, e)) {
2340 wl_link_up(wl);
2341 if (wl_is_ibssmode(wl)) {
2342 cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
2343 GFP_KERNEL);
2344 WL_DBG(("joined in IBSS network\n"));
2345 } else {
2346 wl_bss_connect_done(wl, ndev, e, data);
2347 WL_DBG(("joined in BSS network \"%s\"\n",
2348 ((struct wlc_ssid *)
2349 wl_read_prof(wl, WL_PROF_SSID))->SSID));
2351 act = TRUE;
2352 wl_update_prof(wl, e, &act, WL_PROF_ACT);
2353 } else if (wl_is_linkdown(wl, e)) {
2354 cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
2355 clear_bit(WL_STATUS_CONNECTED, &wl->status);
2356 wl_link_down(wl);
2357 wl_init_prof(wl->profile);
2360 return err;
2363 static int32
2364 wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev,
2365 const wl_event_msg_t *e, void *data)
2367 bool act;
2368 int32 err = 0;
2370 wl_bss_roaming_done(wl, ndev, e, data);
2371 act = TRUE;
2372 wl_update_prof(wl, e, &act, WL_PROF_ACT);
2374 return err;
2377 static __used int32
2378 wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, int32 len)
2380 struct wl_priv *wl = ndev_to_wl(dev);
2381 uint32 buflen;
2383 buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
2384 BUG_ON(unlikely(!buflen));
2386 return wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
2389 static int32
2390 wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
2391 int32 buf_len)
2393 struct wl_priv *wl = ndev_to_wl(dev);
2394 uint32 len;
2395 int32 err = 0;
2397 len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
2398 BUG_ON(unlikely(!len));
2399 if (unlikely
2400 ((err =
2401 wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
2402 WL_IOCTL_LEN_MAX)))) {
2403 WL_ERR(("error (%d)\n", err));
2404 return err;
2406 memcpy(buf, wl->ioctl_buf, buf_len);
2408 return err;
2411 static int32 wl_get_assoc_ies(struct wl_priv *wl)
2413 struct net_device *ndev = wl_to_ndev(wl);
2414 struct wl_assoc_ielen *assoc_info;
2415 struct wl_connect_info *conn_info = wl_to_conn(wl);
2416 uint32 req_len;
2417 uint32 resp_len;
2418 int32 err = 0;
2420 if (unlikely(err = wl_dev_bufvar_get(ndev, "assoc_info", wl->extra_buf,
2421 WL_ASSOC_INFO_MAX))) {
2422 WL_ERR(("could not get assoc info (%d)\n", err));
2423 return err;
2425 assoc_info = (struct wl_assoc_ielen *)wl->extra_buf;
2426 req_len = assoc_info->req_len;
2427 resp_len = assoc_info->resp_len;
2428 if (req_len) {
2429 if (unlikely
2430 (err =
2431 wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf,
2432 WL_ASSOC_INFO_MAX))) {
2433 WL_ERR(("could not get assoc req (%d)\n", err));
2434 return err;
2436 conn_info->req_ie_len = req_len;
2437 conn_info->req_ie =
2438 kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL);
2439 } else {
2440 conn_info->req_ie_len = 0;
2441 conn_info->req_ie = NULL;
2443 if (resp_len) {
2444 if (unlikely
2445 (err =
2446 wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf,
2447 WL_ASSOC_INFO_MAX))) {
2448 WL_ERR(("could not get assoc resp (%d)\n", err));
2449 return err;
2451 conn_info->resp_ie_len = resp_len;
2452 conn_info->resp_ie =
2453 kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL);
2454 } else {
2455 conn_info->resp_ie_len = 0;
2456 conn_info->resp_ie = NULL;
2458 WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
2459 conn_info->resp_ie_len));
2461 return err;
2464 static int32 wl_update_bss_info(struct wl_priv *wl)
2466 struct cfg80211_bss *bss;
2467 struct wl_bss_info *bi;
2468 struct wlc_ssid *ssid;
2469 int32 err = 0;
2471 if (wl_is_ibssmode(wl))
2472 return err;
2474 ssid = (struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID);
2475 bss =
2476 cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid,
2477 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
2478 WLAN_CAPABILITY_ESS);
2480 rtnl_lock();
2481 if (unlikely(!bss)) {
2482 WL_DBG(("Could not find the AP\n"));
2483 *(uint32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
2484 if (unlikely
2485 (err =
2486 wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO,
2487 wl->extra_buf, WL_EXTRA_BUF_MAX))) {
2488 WL_ERR(("Could not get bss info %d\n", err));
2489 goto update_bss_info_out;
2491 bi = (struct wl_bss_info *)(wl->extra_buf + 4);
2492 if (unlikely(memcmp(&bi->BSSID, &wl->bssid, ETHER_ADDR_LEN))) {
2493 err = -EIO;
2494 goto update_bss_info_out;
2496 if (unlikely((err = wl_inform_single_bss(wl, bi))))
2497 goto update_bss_info_out;
2498 } else {
2499 WL_DBG(("Found the AP in the list - "
2500 "BSSID %02x:%02x:%02x:%02x:%02x:%02x\n",
2501 bss->bssid[0], bss->bssid[1], bss->bssid[2],
2502 bss->bssid[3], bss->bssid[4], bss->bssid[5]));
2503 cfg80211_put_bss(bss);
2506 update_bss_info_out:
2507 rtnl_unlock();
2508 return err;
2511 static int32
2512 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
2513 const wl_event_msg_t *e, void *data)
2515 struct wl_connect_info *conn_info = wl_to_conn(wl);
2516 int32 err = 0;
2518 wl_get_assoc_ies(wl);
2519 memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
2520 wl_update_bss_info(wl);
2521 cfg80211_roamed(ndev,
2522 (u8 *)&wl->bssid,
2523 conn_info->req_ie, conn_info->req_ie_len,
2524 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
2525 WL_DBG(("Report roaming result\n"));
2527 set_bit(WL_STATUS_CONNECTED, &wl->status);
2529 return err;
2532 static int32
2533 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
2534 const wl_event_msg_t *e, void *data)
2536 struct wl_connect_info *conn_info = wl_to_conn(wl);
2537 int32 err = 0;
2539 wl_get_assoc_ies(wl);
2540 memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
2541 wl_update_bss_info(wl);
2542 if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) {
2543 cfg80211_connect_result(ndev,
2544 (u8 *)&wl->bssid,
2545 conn_info->req_ie,
2546 conn_info->req_ie_len,
2547 conn_info->resp_ie,
2548 conn_info->resp_ie_len,
2549 WLAN_STATUS_SUCCESS, GFP_KERNEL);
2550 WL_DBG(("Report connect result\n"));
2551 } else {
2552 cfg80211_roamed(ndev,
2553 (u8 *)&wl->bssid,
2554 conn_info->req_ie, conn_info->req_ie_len,
2555 conn_info->resp_ie, conn_info->resp_ie_len,
2556 GFP_KERNEL);
2557 WL_DBG(("Report roaming result\n"));
2559 set_bit(WL_STATUS_CONNECTED, &wl->status);
2561 return err;
2564 static int32
2565 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
2566 const wl_event_msg_t *e, void *data)
2568 uint16 flags = ntoh16(e->flags);
2569 enum nl80211_key_type key_type;
2571 rtnl_lock();
2572 if (flags & WLC_EVENT_MSG_GROUP)
2573 key_type = NL80211_KEYTYPE_GROUP;
2574 else
2575 key_type = NL80211_KEYTYPE_PAIRWISE;
2577 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
2578 NULL, GFP_KERNEL);
2579 rtnl_unlock();
2581 return 0;
2584 static int32
2585 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
2586 const wl_event_msg_t *e, void *data)
2588 struct channel_info channel_inform;
2589 struct wl_scan_results *bss_list;
2590 uint32 len = WL_SCAN_BUF_MAX;
2591 int32 err = 0;
2593 if (wl->iscan_on && wl->iscan_kickstart)
2594 return wl_wakeup_iscan(wl_to_iscan(wl));
2596 if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
2597 WL_ERR(("Scan complete while device not scanning\n"));
2598 return -EINVAL;
2600 if (unlikely(!wl->scan_request)) {
2602 rtnl_lock();
2603 if (unlikely((err = wl_dev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
2604 sizeof(channel_inform))))) {
2605 WL_ERR(("scan busy (%d)\n", err));
2606 goto scan_done_out;
2608 channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
2609 if (unlikely(channel_inform.scan_channel)) {
2611 WL_DBG(("channel_inform.scan_channel (%d)\n",
2612 channel_inform.scan_channel));
2614 wl->bss_list = wl->scan_results;
2615 bss_list = wl->bss_list;
2616 memset(bss_list, 0, len);
2617 bss_list->buflen = htod32(len);
2618 if (unlikely
2619 ((err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len)))) {
2620 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
2621 err = -EINVAL;
2622 goto scan_done_out;
2624 bss_list->buflen = dtoh32(bss_list->buflen);
2625 bss_list->version = dtoh32(bss_list->version);
2626 bss_list->count = dtoh32(bss_list->count);
2628 if ((err = wl_inform_bss(wl)))
2629 goto scan_done_out;
2631 scan_done_out:
2632 if (wl->scan_request) {
2633 cfg80211_scan_done(wl->scan_request, FALSE);
2634 wl->scan_request = NULL;
2636 rtnl_unlock();
2637 return err;
2640 static void wl_init_conf(struct wl_conf *conf)
2642 conf->mode = (uint32)-1;
2643 conf->frag_threshold = (uint32)-1;
2644 conf->rts_threshold = (uint32)-1;
2645 conf->retry_short = (uint32)-1;
2646 conf->retry_long = (uint32)-1;
2647 conf->tx_power =-1;
2650 static void wl_init_prof(struct wl_profile *prof)
2652 memset(prof, 0, sizeof(*prof));
2655 static void wl_init_eloop_handler(struct wl_event_loop *el)
2657 memset(el, 0, sizeof(*el));
2658 el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
2659 el->handler[WLC_E_JOIN] = wl_notify_connect_status;
2660 el->handler[WLC_E_LINK] = wl_notify_connect_status;
2661 el->handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
2662 el->handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
2663 el->handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
2664 el->handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
2665 el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
2666 el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
2669 static int32 wl_init_priv_mem(struct wl_priv *wl)
2671 wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
2672 if (unlikely(!wl->scan_results)) {
2673 WL_ERR(("Scan results alloc failed\n"));
2674 goto init_priv_mem_out;
2676 wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
2677 if (unlikely(!wl->conf)) {
2678 WL_ERR(("wl_conf alloc failed\n"));
2679 goto init_priv_mem_out;
2681 wl->profile = (void *)kzalloc(sizeof(*wl->profile), GFP_KERNEL);
2682 if (unlikely(!wl->profile)) {
2683 WL_ERR(("wl_profile alloc failed\n"));
2684 goto init_priv_mem_out;
2686 wl->bss_info = (void *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
2687 if (unlikely(!wl->bss_info)) {
2688 WL_ERR(("Bss information alloc failed\n"));
2689 goto init_priv_mem_out;
2691 wl->scan_req_int =
2692 (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
2693 if (unlikely(!wl->scan_req_int)) {
2694 WL_ERR(("Scan req alloc failed\n"));
2695 goto init_priv_mem_out;
2697 wl->ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL);
2698 if (unlikely(!wl->ioctl_buf)) {
2699 WL_ERR(("Ioctl buf alloc failed\n"));
2700 goto init_priv_mem_out;
2702 wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
2703 if (unlikely(!wl->extra_buf)) {
2704 WL_ERR(("Extra buf alloc failed\n"));
2705 goto init_priv_mem_out;
2707 wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
2708 if (unlikely(!wl->iscan)) {
2709 WL_ERR(("Iscan buf alloc failed\n"));
2710 goto init_priv_mem_out;
2712 wl->fw = (void *)kzalloc(sizeof(*wl->fw), GFP_KERNEL);
2713 if (unlikely(!wl->fw)) {
2714 WL_ERR(("fw object alloc failed\n"));
2715 goto init_priv_mem_out;
2717 wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
2718 if (unlikely(!wl->pmk_list)) {
2719 WL_ERR(("pmk list alloc failed\n"));
2720 goto init_priv_mem_out;
2723 return 0;
2725 init_priv_mem_out:
2726 wl_deinit_priv_mem(wl);
2728 return -ENOMEM;
2731 static void wl_deinit_priv_mem(struct wl_priv *wl)
2733 kfree(wl->scan_results);
2734 wl->scan_results = NULL;
2735 kfree(wl->bss_info);
2736 wl->bss_info = NULL;
2737 kfree(wl->conf);
2738 wl->conf = NULL;
2739 kfree(wl->profile);
2740 wl->profile = NULL;
2741 kfree(wl->scan_req_int);
2742 wl->scan_req_int = NULL;
2743 kfree(wl->ioctl_buf);
2744 wl->ioctl_buf = NULL;
2745 kfree(wl->extra_buf);
2746 wl->extra_buf = NULL;
2747 kfree(wl->iscan);
2748 wl->iscan = NULL;
2749 kfree(wl->fw);
2750 wl->fw = NULL;
2751 kfree(wl->pmk_list);
2752 wl->pmk_list = NULL;
2755 static int32 wl_create_event_handler(struct wl_priv *wl)
2757 sema_init(&wl->event_sync, 0);
2758 init_completion(&wl->event_exit);
2759 if (unlikely
2760 (((wl->event_pid = kernel_thread(wl_event_handler, wl, 0)) < 0))) {
2761 WL_ERR(("failed to create event thread\n"));
2762 return -ENOMEM;
2764 WL_DBG(("pid %d\n", wl->event_pid));
2765 return 0;
2768 static void wl_destroy_event_handler(struct wl_priv *wl)
2770 if (wl->event_pid >= 0) {
2771 KILL_PROC(wl->event_pid, SIGTERM);
2772 wait_for_completion(&wl->event_exit);
2776 static void wl_term_iscan(struct wl_priv *wl)
2778 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
2780 if (wl->iscan_on && iscan->pid >= 0) {
2781 iscan->state = WL_ISCAN_STATE_IDLE;
2782 KILL_PROC(iscan->pid, SIGTERM);
2783 wait_for_completion(&iscan->exited);
2784 iscan->pid = -1;
2788 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
2790 struct wl_priv *wl = iscan_to_wl(iscan);
2792 if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
2793 WL_ERR(("Scan complete while device not scanning\n"));
2794 return;
2796 if (likely(wl->scan_request)) {
2797 cfg80211_scan_done(wl->scan_request, aborted);
2798 wl->scan_request = NULL;
2800 wl->iscan_kickstart = FALSE;
2803 static int32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
2805 if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
2806 WL_DBG(("wake up iscan\n"));
2807 up(&iscan->sync);
2808 return 0;
2811 return -EIO;
2814 static int32
2815 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, uint32 *status,
2816 struct wl_scan_results **bss_list)
2818 struct wl_iscan_results list;
2819 struct wl_scan_results *results;
2820 struct wl_iscan_results *list_buf;
2821 int32 err = 0;
2823 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
2824 list_buf = (struct wl_iscan_results *)iscan->scan_buf;
2825 results = &list_buf->results;
2826 results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
2827 results->version = 0;
2828 results->count = 0;
2830 memset(&list, 0, sizeof(list));
2831 list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
2832 if (unlikely((err = wl_dev_iovar_getbuf(iscan->dev,
2833 "iscanresults",
2834 &list,
2835 WL_ISCAN_RESULTS_FIXED_SIZE,
2836 iscan->scan_buf,
2837 WL_ISCAN_BUF_MAX)))) {
2838 WL_ERR(("error (%d)\n", err));
2839 return err;
2841 results->buflen = dtoh32(results->buflen);
2842 results->version = dtoh32(results->version);
2843 results->count = dtoh32(results->count);
2844 WL_DBG(("results->count = %d\n", results->count));
2845 WL_DBG(("results->buflen = %d\n", results->buflen));
2846 *status = dtoh32(list_buf->status);
2847 *bss_list = results;
2849 return err;
2852 static int32 wl_iscan_done(struct wl_priv *wl)
2854 struct wl_iscan_ctrl *iscan = wl->iscan;
2855 int32 err = 0;
2857 iscan->state = WL_ISCAN_STATE_IDLE;
2858 rtnl_lock();
2859 wl_inform_bss(wl);
2860 wl_notify_iscan_complete(iscan, FALSE);
2861 rtnl_unlock();
2863 return err;
2866 static int32 wl_iscan_pending(struct wl_priv *wl)
2868 struct wl_iscan_ctrl *iscan = wl->iscan;
2869 int32 err = 0;
2871 /* Reschedule the timer */
2872 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2873 iscan->timer_on = 1;
2875 return err;
2878 static int32 wl_iscan_inprogress(struct wl_priv *wl)
2880 struct wl_iscan_ctrl *iscan = wl->iscan;
2881 int32 err = 0;
2883 rtnl_lock();
2884 wl_inform_bss(wl);
2885 wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
2886 rtnl_unlock();
2887 /* Reschedule the timer */
2888 mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000);
2889 iscan->timer_on = 1;
2891 return err;
2894 static int32 wl_iscan_aborted(struct wl_priv *wl)
2896 struct wl_iscan_ctrl *iscan = wl->iscan;
2897 int32 err = 0;
2899 iscan->state = WL_ISCAN_STATE_IDLE;
2900 rtnl_lock();
2901 wl_notify_iscan_complete(iscan, TRUE);
2902 rtnl_unlock();
2904 return err;
2907 static int32 wl_iscan_thread(void *data)
2909 struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
2910 struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
2911 struct wl_priv *wl = iscan_to_wl(iscan);
2912 struct wl_iscan_eloop *el = &iscan->el;
2913 uint32 status;
2914 int err = 0;
2916 sched_setscheduler(current, SCHED_FIFO, &param);
2917 status = WL_SCAN_RESULTS_PARTIAL;
2918 while (likely(!down_interruptible(&iscan->sync))) {
2919 if (iscan->timer_on) {
2920 del_timer_sync(&iscan->timer);
2921 iscan->timer_on = 0;
2923 rtnl_lock();
2924 if (unlikely
2925 ((err =
2926 wl_get_iscan_results(iscan, &status, &wl->bss_list)))) {
2927 status = WL_SCAN_RESULTS_ABORTED;
2928 WL_ERR(("Abort iscan\n"));
2930 rtnl_unlock();
2931 el->handler[status] (wl);
2933 if (iscan->timer_on) {
2934 del_timer_sync(&iscan->timer);
2935 iscan->timer_on = 0;
2937 complete_and_exit(&iscan->exited, 0);
2939 return 0;
2942 static void wl_iscan_timer(unsigned long data)
2944 struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
2946 if (iscan) {
2947 iscan->timer_on = 0;
2948 WL_DBG(("timer expired\n"));
2949 wl_wakeup_iscan(iscan);
2953 static int32 wl_invoke_iscan(struct wl_priv *wl)
2955 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
2956 int err = 0;
2958 if (wl->iscan_on && iscan->pid < 0) {
2959 iscan->state = WL_ISCAN_STATE_IDLE;
2960 sema_init(&iscan->sync, 0);
2961 init_completion(&iscan->exited);
2962 iscan->pid = kernel_thread(wl_iscan_thread, iscan, 0);
2963 if (unlikely(iscan->pid < 0)) {
2964 WL_ERR(("Could not create iscan thread\n"));
2965 return -ENOMEM;
2969 return err;
2972 static void wl_init_iscan_eloop(struct wl_iscan_eloop *el)
2974 memset(el, 0, sizeof(*el));
2975 el->handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
2976 el->handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
2977 el->handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
2978 el->handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
2979 el->handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
2982 static int32 wl_init_iscan(struct wl_priv *wl)
2984 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
2985 int err = 0;
2987 if (wl->iscan_on) {
2988 iscan->dev = wl_to_ndev(wl);
2989 iscan->state = WL_ISCAN_STATE_IDLE;
2990 wl_init_iscan_eloop(&iscan->el);
2991 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
2992 init_timer(&iscan->timer);
2993 iscan->timer.data = (unsigned long) iscan;
2994 iscan->timer.function = wl_iscan_timer;
2995 sema_init(&iscan->sync, 0);
2996 init_completion(&iscan->exited);
2997 iscan->pid = kernel_thread(wl_iscan_thread, iscan, 0);
2998 if (unlikely(iscan->pid < 0)) {
2999 WL_ERR(("Could not create iscan thread\n"));
3000 return -ENOMEM;
3002 iscan->data = wl;
3005 return err;
3008 static void wl_init_fw(struct wl_fw_ctrl *fw)
3010 fw->status = 0; /* init fw loading status.
3011 0 means nothing was loaded yet */
3014 static int32 wl_init_priv(struct wl_priv *wl)
3016 struct wiphy *wiphy = wl_to_wiphy(wl);
3017 int32 err = 0;
3019 wl->scan_request = NULL;
3020 wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
3021 #ifndef WL_ISCAN_DISABLED
3022 wl->iscan_on = TRUE; /* iscan on & off switch.
3023 we enable iscan per default */
3024 #else
3025 wl->iscan_on = FALSE;
3026 #endif /* WL_ISCAN_DISABLED */
3027 #ifndef WL_ROAM_DISABLED
3028 wl->roam_on = TRUE; /* roam on & off switch.
3029 we enable roam per default */
3030 #else
3031 wl->roam_on = FALSE;
3032 #endif /* WL_ROAM_DISABLED */
3034 wl->iscan_kickstart = FALSE;
3035 wl->active_scan = TRUE; /* we do active scan for
3036 specific scan per default */
3037 wl->dongle_up = FALSE; /* dongle is not up yet */
3038 wl_init_eq(wl);
3039 if (unlikely((err = wl_init_priv_mem(wl))))
3040 return err;
3041 if (unlikely(wl_create_event_handler(wl)))
3042 return -ENOMEM;
3043 wl_init_eloop_handler(&wl->el);
3044 mutex_init(&wl->usr_sync);
3045 if (unlikely((err = wl_init_iscan(wl))))
3046 return err;
3047 wl_init_fw(wl->fw);
3048 wl_init_conf(wl->conf);
3049 wl_init_prof(wl->profile);
3050 wl_link_down(wl);
3052 return err;
3055 static void wl_deinit_priv(struct wl_priv *wl)
3057 wl_destroy_event_handler(wl);
3058 wl->dongle_up = FALSE; /* dongle down */
3059 wl_flush_eq(wl);
3060 wl_link_down(wl);
3061 wl_term_iscan(wl);
3062 wl_deinit_priv_mem(wl);
3065 int32 wl_cfg80211_attach(struct net_device *ndev, void *data)
3067 struct wireless_dev *wdev;
3068 struct wl_priv *wl;
3069 struct wl_iface *ci;
3070 int32 err = 0;
3072 if (unlikely(!ndev)) {
3073 WL_ERR(("ndev is invaild\n"));
3074 return -ENODEV;
3076 wl_cfg80211_dev = kzalloc(sizeof(struct wl_dev), GFP_KERNEL);
3077 if (unlikely(!wl_cfg80211_dev)) {
3078 WL_ERR(("wl_cfg80211_dev is invalid\n"));
3079 return -ENOMEM;
3081 WL_DBG(("func %p\n", wl_sdio_func()));
3082 wdev = wl_alloc_wdev(sizeof(struct wl_iface), &wl_sdio_func()->dev);
3083 if (unlikely(IS_ERR(wdev)))
3084 return -ENOMEM;
3086 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
3087 wl = wdev_to_wl(wdev);
3088 wl->wdev = wdev;
3089 wl->pub = data;
3090 ci = (struct wl_iface *)wl_to_ci(wl);
3091 ci->wl = wl;
3092 ndev->ieee80211_ptr = wdev;
3093 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
3094 wdev->netdev = ndev;
3095 if (unlikely((err = wl_init_priv(wl)))) {
3096 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
3097 goto cfg80211_attach_out;
3099 wl_set_drvdata(wl_cfg80211_dev, ci);
3100 set_bit(WL_STATUS_READY, &wl->status);
3102 return err;
3104 cfg80211_attach_out:
3105 wl_free_wdev(wl);
3106 return err;
3109 void wl_cfg80211_detach(void)
3111 struct wl_priv *wl;
3113 wl = WL_PRIV_GET();
3115 wl_deinit_priv(wl);
3116 wl_free_wdev(wl);
3117 wl_set_drvdata(wl_cfg80211_dev, NULL);
3118 kfree(wl_cfg80211_dev);
3119 wl_cfg80211_dev = NULL;
3120 wl_clear_sdio_func();
3123 static void wl_wakeup_event(struct wl_priv *wl)
3125 up(&wl->event_sync);
3128 static int32 wl_event_handler(void *data)
3130 struct wl_priv *wl = (struct wl_priv *)data;
3131 struct sched_param param = {.sched_priority = MAX_RT_PRIO - 1 };
3132 struct wl_event_q *e;
3134 sched_setscheduler(current, SCHED_FIFO, &param);
3135 while (likely(!down_interruptible(&wl->event_sync))) {
3136 if (unlikely(!(e = wl_deq_event(wl)))) {
3137 WL_ERR(("eqeue empty..\n"));
3138 BUG();
3140 WL_DBG(("event type (%d)\n", e->etype));
3141 if (wl->el.handler[e->etype]) {
3142 wl->el.handler[e->etype] (wl, wl_to_ndev(wl), &e->emsg,
3143 e->edata);
3144 } else {
3145 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
3147 wl_put_event(e);
3149 complete_and_exit(&wl->event_exit, 0);
3152 void
3153 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
3155 uint32 event_type = ntoh32(e->event_type);
3156 struct wl_priv *wl = ndev_to_wl(ndev);
3157 #if (WL_DBG_LEVEL > 0)
3158 s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
3159 wl_dbg_estr[event_type] : (s8 *) "Unknown";
3160 #endif /* (WL_DBG_LEVEL > 0) */
3161 WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
3162 if (likely(!wl_enq_event(wl, event_type, e, data)))
3163 wl_wakeup_event(wl);
3166 static void wl_init_eq(struct wl_priv *wl)
3168 wl_init_eq_lock(wl);
3169 INIT_LIST_HEAD(&wl->eq_list);
3172 static void wl_flush_eq(struct wl_priv *wl)
3174 struct wl_event_q *e;
3176 wl_lock_eq(wl);
3177 while (!list_empty(&wl->eq_list)) {
3178 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
3179 list_del(&e->eq_list);
3180 kfree(e);
3182 wl_unlock_eq(wl);
3186 * retrieve first queued event from head
3189 static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
3191 struct wl_event_q *e = NULL;
3193 wl_lock_eq(wl);
3194 if (likely(!list_empty(&wl->eq_list))) {
3195 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
3196 list_del(&e->eq_list);
3198 wl_unlock_eq(wl);
3200 return e;
3204 ** push event to tail of the queue
3207 static int32
3208 wl_enq_event(struct wl_priv *wl, uint32 event, const wl_event_msg_t *msg,
3209 void *data)
3211 struct wl_event_q *e;
3212 int32 err = 0;
3214 if (unlikely(!(e = kzalloc(sizeof(struct wl_event_q), GFP_KERNEL)))) {
3215 WL_ERR(("event alloc failed\n"));
3216 return -ENOMEM;
3219 e->etype = event;
3220 memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
3221 if (data) {
3223 wl_lock_eq(wl);
3224 list_add_tail(&e->eq_list, &wl->eq_list);
3225 wl_unlock_eq(wl);
3227 return err;
3230 static void wl_put_event(struct wl_event_q *e)
3232 kfree(e);
3235 void wl_cfg80211_sdio_func(void *func)
3237 cfg80211_sdio_func = (struct sdio_func *)func;
3240 static void wl_clear_sdio_func(void)
3242 cfg80211_sdio_func = NULL;
3245 static struct sdio_func *wl_sdio_func(void)
3247 return cfg80211_sdio_func;
3250 static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype)
3252 int32 infra = 0;
3253 int32 ap = 0;
3254 int32 err = 0;
3256 switch (iftype) {
3257 case NL80211_IFTYPE_MONITOR:
3258 case NL80211_IFTYPE_WDS:
3259 WL_ERR(("type (%d) : currently we do not support this mode\n",
3260 iftype));
3261 err = -EINVAL;
3262 return err;
3263 case NL80211_IFTYPE_ADHOC:
3264 break;
3265 case NL80211_IFTYPE_STATION:
3266 infra = 1;
3267 break;
3268 default:
3269 err = -EINVAL;
3270 WL_ERR(("invalid type (%d)\n", iftype));
3271 return err;
3273 infra = htod32(infra);
3274 ap = htod32(ap);
3275 WL_DBG(("%s ap (%d), infra (%d)\n", ndev->name, ap, infra));
3276 if (unlikely
3277 (err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra)))
3278 || unlikely
3279 (err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap)))) {
3280 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
3281 return err;
3284 return -EINPROGRESS;
3287 #ifndef EMBEDDED_PLATFORM
3288 static int32 wl_dongle_country(struct net_device *ndev, u8 ccode)
3291 int32 err = 0;
3293 return err;
3296 static int32 wl_dongle_up(struct net_device *ndev, uint32 up)
3298 int32 err = 0;
3300 if (unlikely(err = wl_dev_ioctl(ndev, WLC_UP, &up, sizeof(up)))) {
3301 WL_ERR(("WLC_UP error (%d)\n", err));
3303 return err;
3306 static int32 wl_dongle_power(struct net_device *ndev, uint32 power_mode)
3308 int32 err = 0;
3310 if (unlikely
3311 (err =
3312 wl_dev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode)))) {
3313 WL_ERR(("WLC_SET_PM error (%d)\n", err));
3315 return err;
3318 static int32
3319 wl_dongle_glom(struct net_device *ndev, uint32 glom, uint32 dongle_align)
3321 s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
3322 '\0' + bitvec */
3323 int32 err = 0;
3325 /* Match Host and Dongle rx alignment */
3326 bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
3327 sizeof(iovbuf));
3328 if (unlikely
3329 (err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
3330 WL_ERR(("txglomalign error (%d)\n", err));
3331 goto dongle_glom_out;
3333 /* disable glom option per default */
3334 bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
3335 if (unlikely
3336 (err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
3337 WL_ERR(("txglom error (%d)\n", err));
3338 goto dongle_glom_out;
3340 dongle_glom_out:
3341 return err;
3344 static int32
3345 wl_dongle_roam(struct net_device *ndev, uint32 roamvar, uint32 bcn_timeout)
3347 s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
3348 '\0' + bitvec */
3349 int32 err = 0;
3351 /* Setup timeout if Beacons are lost and roam is
3352 off to report link down */
3353 if (roamvar) {
3354 bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
3355 sizeof(iovbuf));
3356 if (unlikely
3357 (err =
3358 wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
3359 WL_ERR(("bcn_timeout error (%d)\n", err));
3360 goto dongle_rom_out;
3363 /* Enable/Disable built-in roaming to allow supplicant
3364 to take care of roaming */
3365 bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
3366 if (unlikely
3367 (err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
3368 WL_ERR(("roam_off error (%d)\n", err));
3369 goto dongle_rom_out;
3371 dongle_rom_out:
3372 return err;
3375 static int32 wl_dongle_eventmsg(struct net_device *ndev)
3378 s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
3379 '\0' + bitvec */
3380 s8 eventmask[WL_EVENTING_MASK_LEN];
3381 int32 err = 0;
3383 /* Setup event_msgs */
3384 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
3385 sizeof(iovbuf));
3386 if (unlikely
3387 (err = wl_dev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf)))) {
3388 WL_ERR(("Get event_msgs error (%d)\n", err));
3389 goto dongle_eventmsg_out;
3391 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
3393 setbit(eventmask, WLC_E_SET_SSID);
3394 setbit(eventmask, WLC_E_PRUNE);
3395 setbit(eventmask, WLC_E_AUTH);
3396 setbit(eventmask, WLC_E_REASSOC);
3397 setbit(eventmask, WLC_E_REASSOC_IND);
3398 setbit(eventmask, WLC_E_DEAUTH_IND);
3399 setbit(eventmask, WLC_E_DISASSOC_IND);
3400 setbit(eventmask, WLC_E_DISASSOC);
3401 setbit(eventmask, WLC_E_JOIN);
3402 setbit(eventmask, WLC_E_ASSOC_IND);
3403 setbit(eventmask, WLC_E_PSK_SUP);
3404 setbit(eventmask, WLC_E_LINK);
3405 setbit(eventmask, WLC_E_NDIS_LINK);
3406 setbit(eventmask, WLC_E_MIC_ERROR);
3407 setbit(eventmask, WLC_E_PMKID_CACHE);
3408 setbit(eventmask, WLC_E_TXFAIL);
3409 setbit(eventmask, WLC_E_JOIN_START);
3410 setbit(eventmask, WLC_E_SCAN_COMPLETE);
3412 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
3413 sizeof(iovbuf));
3414 if (unlikely
3415 (err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
3416 WL_ERR(("Set event_msgs error (%d)\n", err));
3417 goto dongle_eventmsg_out;
3420 dongle_eventmsg_out:
3421 return err;
3424 static int32
3425 wl_dongle_scantime(struct net_device *ndev, int32 scan_assoc_time,
3426 int32 scan_unassoc_time)
3428 int32 err = 0;
3430 if ((err =
3431 wl_dev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
3432 sizeof(scan_assoc_time)))) {
3433 if (err == -EOPNOTSUPP) {
3434 WL_INFO(("Scan assoc time is not supported\n"));
3435 } else {
3436 WL_ERR(("Scan assoc time error (%d)\n", err));
3438 goto dongle_scantime_out;
3440 if ((err =
3441 wl_dev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
3442 sizeof(scan_unassoc_time)))) {
3443 if (err == -EOPNOTSUPP) {
3444 WL_INFO(("Scan unassoc time is not supported\n"));
3445 } else {
3446 WL_ERR(("Scan unassoc time error (%d)\n", err));
3448 goto dongle_scantime_out;
3451 dongle_scantime_out:
3452 return err;
3455 static int32
3456 wl_dongle_offload(struct net_device *ndev, int32 arpoe, int32 arp_ol)
3458 s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
3459 '\0' + bitvec */
3460 int32 err = 0;
3462 /* Set ARP offload */
3463 bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf));
3464 if ((err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
3465 if (err == -EOPNOTSUPP)
3466 WL_INFO(("arpoe is not supported\n"));
3467 else
3468 WL_ERR(("arpoe error (%d)\n", err));
3470 goto dongle_offload_out;
3472 bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf));
3473 if ((err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
3474 if (err == -EOPNOTSUPP)
3475 WL_INFO(("arp_ol is not supported\n"));
3476 else
3477 WL_ERR(("arp_ol error (%d)\n", err));
3479 goto dongle_offload_out;
3482 dongle_offload_out:
3483 return err;
3486 static int32 wl_pattern_atoh(s8 *src, s8 *dst)
3488 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
3489 int i;
3490 if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) {
3491 WL_ERR(("Mask invalid format. Needs to start with 0x\n"));
3492 return -1;
3494 src = src + 2; /* Skip past 0x */
3495 if (strlen(src) % 2 != 0) {
3496 WL_ERR(("Mask invalid format. Needs to be of even length\n"));
3497 return -1;
3499 for (i = 0; *src != '\0'; i++) {
3500 char num[3];
3501 strncpy(num, src, 2);
3502 num[2] = '\0';
3503 dst[i] = (u8) strtoul(num, NULL, 16);
3504 src += 2;
3506 return i;
3509 static int32 wl_dongle_filter(struct net_device *ndev, uint32 filter_mode)
3511 s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" +
3512 '\0' + bitvec */
3513 const s8 *str;
3514 struct wl_pkt_filter pkt_filter;
3515 struct wl_pkt_filter *pkt_filterp;
3516 int32 buf_len;
3517 int32 str_len;
3518 uint32 mask_size;
3519 uint32 pattern_size;
3520 s8 buf[256];
3521 int32 err = 0;
3523 /* add a default packet filter pattern */
3524 str = "pkt_filter_add";
3525 str_len = strlen(str);
3526 strncpy(buf, str, str_len);
3527 buf[str_len] = '\0';
3528 buf_len = str_len + 1;
3530 pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1);
3532 /* Parse packet filter id. */
3533 pkt_filter.id = htod32(100);
3535 /* Parse filter polarity. */
3536 pkt_filter.negate_match = htod32(0);
3538 /* Parse filter type. */
3539 pkt_filter.type = htod32(0);
3541 /* Parse pattern filter offset. */
3542 pkt_filter.u.pattern.offset = htod32(0);
3544 /* Parse pattern filter mask. */
3545 mask_size = htod32(wl_pattern_atoh("0xff",
3546 (char *)pkt_filterp->u.pattern.
3547 mask_and_pattern));
3549 /* Parse pattern filter pattern. */
3550 pattern_size = htod32(wl_pattern_atoh("0x00",
3551 (char *)&pkt_filterp->u.pattern.
3552 mask_and_pattern[mask_size]));
3554 if (mask_size != pattern_size) {
3555 WL_ERR(("Mask and pattern not the same size\n"));
3556 err = -EINVAL;
3557 goto dongle_filter_out;
3560 pkt_filter.u.pattern.size_bytes = mask_size;
3561 buf_len += WL_PKT_FILTER_FIXED_LEN;
3562 buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
3564 /* Keep-alive attributes are set in local
3565 * variable (keep_alive_pkt), and
3566 * then memcpy'ed into buffer (keep_alive_pktp) since there is no
3567 * guarantee that the buffer is properly aligned.
3569 memcpy((char *)pkt_filterp, &pkt_filter,
3570 WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
3572 if ((err = wl_dev_ioctl(ndev, WLC_SET_VAR, buf, buf_len))) {
3573 if (err == -EOPNOTSUPP) {
3574 WL_INFO(("filter not supported\n"));
3575 } else {
3576 WL_ERR(("filter (%d)\n", err));
3578 goto dongle_filter_out;
3581 /* set mode to allow pattern */
3582 bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf,
3583 sizeof(iovbuf));
3584 if ((err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) {
3585 if (err == -EOPNOTSUPP) {
3586 WL_INFO(("filter_mode not supported\n"));
3587 } else {
3588 WL_ERR(("filter_mode (%d)\n", err));
3590 goto dongle_filter_out;
3593 dongle_filter_out:
3594 return err;
3596 #endif /* !EMBEDDED_PLATFORM */
3598 int32 wl_config_dongle(struct wl_priv *wl, bool need_lock)
3600 #ifndef DHD_SDALIGN
3601 #define DHD_SDALIGN 32
3602 #endif
3603 struct net_device *ndev;
3604 struct wireless_dev *wdev;
3605 int32 err = 0;
3607 if (wl->dongle_up)
3608 return err;
3610 ndev = wl_to_ndev(wl);
3611 wdev = ndev->ieee80211_ptr;
3612 if (need_lock)
3613 rtnl_lock();
3615 #ifndef EMBEDDED_PLATFORM
3616 if (unlikely((err = wl_dongle_up(ndev, 0))))
3617 goto default_conf_out;
3618 if (unlikely((err = wl_dongle_country(ndev, 0))))
3619 goto default_conf_out;
3620 if (unlikely((err = wl_dongle_power(ndev, PM_FAST))))
3621 goto default_conf_out;
3622 if (unlikely((err = wl_dongle_glom(ndev, 0, DHD_SDALIGN))))
3623 goto default_conf_out;
3624 if (unlikely((err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3))))
3625 goto default_conf_out;
3626 if (unlikely((err = wl_dongle_eventmsg(ndev))))
3627 goto default_conf_out;
3629 wl_dongle_scantime(ndev, 40, 80);
3630 wl_dongle_offload(ndev, 1, 0xf);
3631 wl_dongle_filter(ndev, 1);
3632 #endif /* !EMBEDDED_PLATFORM */
3634 err = wl_dongle_mode(ndev, wdev->iftype);
3635 if (unlikely(err && err != -EINPROGRESS))
3636 goto default_conf_out;
3637 if (unlikely((err = wl_dongle_probecap(wl))))
3638 goto default_conf_out;
3640 /* -EINPROGRESS: Call commit handler */
3642 default_conf_out:
3643 if (need_lock)
3644 rtnl_unlock();
3646 wl->dongle_up = TRUE;
3648 return err;
3652 static int32 wl_update_wiphybands(struct wl_priv *wl)
3654 struct wiphy *wiphy;
3655 int32 phy_list;
3656 s8 phy;
3657 int32 err = 0;
3659 if (unlikely
3660 (err =
3661 wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_PHYLIST, &phy_list,
3662 sizeof(phy_list)))) {
3663 WL_ERR(("error (%d)\n", err));
3664 return err;
3667 phy = ((char *)&phy_list)[1];
3668 WL_DBG(("%c phy\n", phy));
3669 if (phy == 'n' || phy == 'a') {
3670 wiphy = wl_to_wiphy(wl);
3671 wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n;
3674 return err;
3677 static int32 __wl_cfg80211_up(struct wl_priv *wl)
3679 int32 err = 0;
3681 if (unlikely(err = wl_config_dongle(wl, FALSE)))
3682 return err;
3684 wl_invoke_iscan(wl);
3685 set_bit(WL_STATUS_READY, &wl->status);
3686 return err;
3689 static int32 __wl_cfg80211_down(struct wl_priv *wl)
3691 int32 err = 0;
3693 /* Check if cfg80211 interface is already down */
3694 if (!test_bit(WL_STATUS_READY, &wl->status))
3695 return err; /* it is even not ready */
3697 set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
3698 wl_term_iscan(wl);
3699 if (wl->scan_request) {
3700 cfg80211_scan_done(wl->scan_request, TRUE); /* TRUE
3701 means abort */
3702 wl->scan_request = NULL;
3704 clear_bit(WL_STATUS_READY, &wl->status);
3705 clear_bit(WL_STATUS_SCANNING, &wl->status);
3706 clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
3707 clear_bit(WL_STATUS_CONNECTED, &wl->status);
3709 return err;
3712 int32 wl_cfg80211_up(void)
3714 struct wl_priv *wl;
3715 int32 err = 0;
3717 wl = WL_PRIV_GET();
3718 mutex_lock(&wl->usr_sync);
3719 err = __wl_cfg80211_up(wl);
3720 mutex_unlock(&wl->usr_sync);
3722 return err;
3725 int32 wl_cfg80211_down(void)
3727 struct wl_priv *wl;
3728 int32 err = 0;
3730 wl = WL_PRIV_GET();
3731 mutex_lock(&wl->usr_sync);
3732 err = __wl_cfg80211_down(wl);
3733 mutex_unlock(&wl->usr_sync);
3735 return err;
3738 static int32 wl_dongle_probecap(struct wl_priv *wl)
3740 int32 err = 0;
3742 if (unlikely((err = wl_update_wiphybands(wl))))
3743 return err;
3745 return err;
3748 static void *wl_read_prof(struct wl_priv *wl, int32 item)
3750 switch (item) {
3751 case WL_PROF_SEC:
3752 return &wl->profile->sec;
3753 case WL_PROF_ACT:
3754 return &wl->profile->active;
3755 case WL_PROF_BSSID:
3756 return &wl->profile->bssid;
3757 case WL_PROF_SSID:
3758 return &wl->profile->ssid;
3760 WL_ERR(("invalid item (%d)\n", item));
3761 return NULL;
3764 static int32
3765 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data,
3766 int32 item)
3768 int32 err = 0;
3769 struct wlc_ssid *ssid;
3771 switch (item) {
3772 case WL_PROF_SSID:
3773 ssid = (wlc_ssid_t *) data;
3774 memset(wl->profile->ssid.SSID, 0,
3775 sizeof(wl->profile->ssid.SSID));
3776 memcpy(wl->profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
3777 wl->profile->ssid.SSID_len = ssid->SSID_len;
3778 break;
3779 case WL_PROF_BSSID:
3780 if (data)
3781 memcpy(wl->profile->bssid, data, ETHER_ADDR_LEN);
3782 else
3783 memset(wl->profile->bssid, 0, ETHER_ADDR_LEN);
3784 break;
3785 case WL_PROF_SEC:
3786 memcpy(&wl->profile->sec, data, sizeof(wl->profile->sec));
3787 break;
3788 case WL_PROF_ACT:
3789 wl->profile->active = *(bool *) data;
3790 break;
3791 default:
3792 WL_ERR(("unsupported item (%d)\n", item));
3793 err = -EOPNOTSUPP;
3794 break;
3797 return err;
3800 void wl_cfg80211_dbg_level(uint32 level)
3802 wl_dbg_level = level;
3805 static bool wl_is_ibssmode(struct wl_priv *wl)
3807 return wl->conf->mode == WL_MODE_IBSS;
3810 static bool wl_is_ibssstarter(struct wl_priv *wl)
3812 return wl->ibss_starter;
3815 static void wl_rst_ie(struct wl_priv *wl)
3817 struct wl_ie *ie = wl_to_ie(wl);
3819 ie->offset = 0;
3822 static int32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
3824 struct wl_ie *ie = wl_to_ie(wl);
3825 int32 err = 0;
3827 if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
3828 WL_ERR(("ei crosses buffer boundary\n"));
3829 return -ENOSPC;
3831 ie->buf[ie->offset] = t;
3832 ie->buf[ie->offset + 1] = l;
3833 memcpy(&ie->buf[ie->offset + 2], v, l);
3834 ie->offset += l + 2;
3836 return err;
3839 static int32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, uint16 ie_size)
3841 struct wl_ie *ie = wl_to_ie(wl);
3842 int32 err = 0;
3844 if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
3845 WL_ERR(("ei_stream crosses buffer boundary\n"));
3846 return -ENOSPC;
3848 memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
3849 ie->offset += ie_size;
3851 return err;
3854 static int32 wl_cp_ie(struct wl_priv *wl, u8 *dst, uint16 dst_size)
3856 struct wl_ie *ie = wl_to_ie(wl);
3857 int32 err = 0;
3859 if (unlikely(ie->offset > dst_size)) {
3860 WL_ERR(("dst_size is not enough\n"));
3861 return -ENOSPC;
3863 memcpy(dst, &ie->buf[0], ie->offset);
3865 return err;
3868 static uint32 wl_get_ielen(struct wl_priv *wl)
3870 struct wl_ie *ie = wl_to_ie(wl);
3872 return ie->offset;
3875 static void wl_link_up(struct wl_priv *wl)
3877 wl->link_up = TRUE;
3880 static void wl_link_down(struct wl_priv *wl)
3882 struct wl_connect_info *conn_info = wl_to_conn(wl);
3884 wl->link_up = FALSE;
3885 kfree(conn_info->req_ie);
3886 conn_info->req_ie = NULL;
3887 conn_info->req_ie_len = 0;
3888 kfree(conn_info->resp_ie);
3889 conn_info->resp_ie = NULL;
3890 conn_info->resp_ie_len = 0;
3893 static void wl_lock_eq(struct wl_priv *wl)
3895 spin_lock_irq(&wl->eq_lock);
3898 static void wl_unlock_eq(struct wl_priv *wl)
3900 spin_unlock_irq(&wl->eq_lock);
3903 static void wl_init_eq_lock(struct wl_priv *wl)
3905 spin_lock_init(&wl->eq_lock);
3908 static void wl_delay(uint32 ms)
3910 if (ms < 1000 / HZ) {
3911 cond_resched();
3912 mdelay(ms);
3913 } else {
3914 msleep(ms);
3918 static void wl_set_drvdata(struct wl_dev *dev, void *data)
3920 dev->driver_data = data;
3923 static void *wl_get_drvdata(struct wl_dev *dev)
3925 return dev->driver_data;
3928 int32 wl_cfg80211_read_fw(s8 *buf, uint32 size)
3930 const struct firmware *fw_entry;
3931 struct wl_priv *wl;
3933 wl = WL_PRIV_GET();
3935 fw_entry = wl->fw->fw_entry;
3937 if (fw_entry->size < wl->fw->ptr + size)
3938 size = fw_entry->size - wl->fw->ptr;
3940 memcpy(buf, &fw_entry->data[wl->fw->ptr], size);
3941 wl->fw->ptr += size;
3942 return size;
3945 void wl_cfg80211_release_fw(void)
3947 struct wl_priv *wl;
3949 wl = WL_PRIV_GET();
3950 release_firmware(wl->fw->fw_entry);
3951 wl->fw->ptr = 0;
3954 void *wl_cfg80211_request_fw(s8 *file_name)
3956 struct wl_priv *wl;
3957 const struct firmware *fw_entry = NULL;
3958 int32 err = 0;
3960 WL_DBG(("file name : \"%s\"\n", file_name));
3961 wl = WL_PRIV_GET();
3963 if (!test_bit(WL_FW_LOADING_DONE, &wl->fw->status)) {
3964 if (unlikely
3965 (err =
3966 request_firmware(&wl->fw->fw_entry, file_name,
3967 &wl_sdio_func()->dev))) {
3968 WL_ERR(("Could not download fw (%d)\n", err));
3969 goto req_fw_out;
3971 set_bit(WL_FW_LOADING_DONE, &wl->fw->status);
3972 fw_entry = wl->fw->fw_entry;
3973 if (fw_entry) {
3974 WL_DBG(("fw size (%d), data (%p)\n", fw_entry->size,
3975 fw_entry->data));
3977 } else if (!test_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status)) {
3978 if (unlikely
3979 (err =
3980 request_firmware(&wl->fw->fw_entry, file_name,
3981 &wl_sdio_func()->dev))) {
3982 WL_ERR(("Could not download nvram (%d)\n", err));
3983 goto req_fw_out;
3985 set_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status);
3986 fw_entry = wl->fw->fw_entry;
3987 if (fw_entry) {
3988 WL_DBG(("nvram size (%d), data (%p)\n", fw_entry->size,
3989 fw_entry->data));
3991 } else {
3992 WL_DBG(("Downloading already done. Nothing to do more\n"));
3993 err = -EPERM;
3996 req_fw_out:
3997 if (unlikely(err)) {
3998 return NULL;
4000 wl->fw->ptr = 0;
4001 return (void *)fw_entry->data;
4004 s8 *wl_cfg80211_get_fwname(void)
4006 struct wl_priv *wl;
4008 wl = WL_PRIV_GET();
4009 strcpy(wl->fw->fw_name, WL_4329_FW_FILE);
4010 return wl->fw->fw_name;
4013 s8 *wl_cfg80211_get_nvramname(void)
4015 struct wl_priv *wl;
4017 wl = WL_PRIV_GET();
4018 strcpy(wl->fw->nvram_name, WL_4329_NVRAM_FILE);
4019 return wl->fw->nvram_name;