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