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