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