staging: brcm80211: Added support to change scan times from brcmfmac driver
[pandora-kernel.git] / drivers / staging / brcm80211 / brcmfmac / wl_cfg80211.c
index 991463f..450e072 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
-#include <osl.h>
 
 #include <bcmutils.h>
-#include <bcmendian.h>
-#include <proto/ethernet.h>
 
 #include <asm/uaccess.h>
 
 #include <linux/firmware.h>
 #include <wl_cfg80211.h>
 
+void sdioh_sdio_set_host_pm_flags(int flag);
+
 static struct sdio_func *cfg80211_sdio_func;
 static struct wl_dev *wl_cfg80211_dev;
+static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
 
 u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
 
@@ -87,8 +87,8 @@ static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
                                      s32 dbm);
 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
-                                           struct net_device *dev,
-                                           u8 key_idx);
+                                         struct net_device *dev, u8 key_idx,
+                                         bool unicast, bool multicast);
 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                                 u8 key_idx, bool pairwise, const u8 *mac_addr,
                                 struct key_params *params);
@@ -182,41 +182,34 @@ static void wl_init_prof(struct wl_profile *prof);
 ** cfg80211 connect utilites
 */
 static s32 wl_set_wpa_version(struct net_device *dev,
-                               struct cfg80211_connect_params *sme);
+                       struct cfg80211_connect_params *sme);
 static s32 wl_set_auth_type(struct net_device *dev,
-                             struct cfg80211_connect_params *sme);
+                       struct cfg80211_connect_params *sme);
 static s32 wl_set_set_cipher(struct net_device *dev,
-                              struct cfg80211_connect_params *sme);
+                       struct cfg80211_connect_params *sme);
 static s32 wl_set_key_mgmt(struct net_device *dev,
-                            struct cfg80211_connect_params *sme);
+                       struct cfg80211_connect_params *sme);
 static s32 wl_set_set_sharedkey(struct net_device *dev,
-                                 struct cfg80211_connect_params *sme);
+                       struct cfg80211_connect_params *sme);
 static s32 wl_get_assoc_ies(struct wl_priv *wl);
+static void wl_clear_assoc_ies(struct wl_priv *wl);
 static void wl_ch_to_chanspec(int ch,
        struct wl_join_params *join_params, size_t *join_params_size);
 
 /*
 ** information element utilities
 */
-static void wl_rst_ie(struct wl_priv *wl);
 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
-static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size);
-static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size);
-static u32 wl_get_ielen(struct wl_priv *wl);
-
 static s32 wl_mode_to_nl80211_iftype(s32 mode);
-
 static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface,
-                                         struct device *dev);
+                       struct device *dev);
 static void wl_free_wdev(struct wl_priv *wl);
-
 static s32 wl_inform_bss(struct wl_priv *wl);
 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
 static s32 wl_update_bss_info(struct wl_priv *wl);
-
 static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
-                          u8 key_idx, const u8 *mac_addr,
-                          struct key_params *params);
+                       u8 key_idx, const u8 *mac_addr,
+                       struct key_params *params);
 
 /*
 ** key indianess swap utilities
@@ -242,7 +235,6 @@ static void *wl_get_drvdata(struct wl_dev *dev);
 ** ibss mode utilities
 */
 static bool wl_is_ibssmode(struct wl_priv *wl);
-static bool wl_is_ibssstarter(struct wl_priv *wl);
 
 /*
 ** dongle up/down , default configuration utilities
@@ -250,7 +242,6 @@ static bool wl_is_ibssstarter(struct wl_priv *wl);
 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e);
 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
-static void wl_link_up(struct wl_priv *wl);
 static void wl_link_down(struct wl_priv *wl);
 static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype);
 static s32 __wl_cfg80211_up(struct wl_priv *wl);
@@ -268,18 +259,19 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up);
 static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode);
 static s32 wl_dongle_glom(struct net_device *ndev, u32 glom,
                            u32 dongle_align);
-static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar,
-                           u32 bcn_timeout);
-static s32 wl_dongle_eventmsg(struct net_device *ndev);
-static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
-                               s32 scan_unassoc_time);
 static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe,
                               s32 arp_ol);
 static s32 wl_pattern_atoh(s8 *src, s8 *dst);
 static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode);
 static s32 wl_update_wiphybands(struct wl_priv *wl);
 #endif                         /* !EMBEDDED_PLATFORM */
+
+static s32 wl_dongle_eventmsg(struct net_device *ndev);
+static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
+                               s32 scan_unassoc_time, s32 scan_passive_time);
 static s32 wl_config_dongle(struct wl_priv *wl, bool need_lock);
+static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar,
+                           u32 bcn_timeout);
 
 /*
 ** iscan handler
@@ -555,24 +547,24 @@ static const u32 __wl_cipher_suites[] = {
 
 static void swap_key_from_BE(struct wl_wsec_key *key)
 {
-       key->index = htod32(key->index);
-       key->len = htod32(key->len);
-       key->algo = htod32(key->algo);
-       key->flags = htod32(key->flags);
-       key->rxiv.hi = htod32(key->rxiv.hi);
-       key->rxiv.lo = htod16(key->rxiv.lo);
-       key->iv_initialized = htod32(key->iv_initialized);
+       key->index = cpu_to_le32(key->index);
+       key->len = cpu_to_le32(key->len);
+       key->algo = cpu_to_le32(key->algo);
+       key->flags = cpu_to_le32(key->flags);
+       key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
+       key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
+       key->iv_initialized = cpu_to_le32(key->iv_initialized);
 }
 
 static void swap_key_to_BE(struct wl_wsec_key *key)
 {
-       key->index = dtoh32(key->index);
-       key->len = dtoh32(key->len);
-       key->algo = dtoh32(key->algo);
-       key->flags = dtoh32(key->flags);
-       key->rxiv.hi = dtoh32(key->rxiv.hi);
-       key->rxiv.lo = dtoh16(key->rxiv.lo);
-       key->iv_initialized = dtoh32(key->iv_initialized);
+       key->index = le32_to_cpu(key->index);
+       key->len = le32_to_cpu(key->len);
+       key->algo = le32_to_cpu(key->algo);
+       key->flags = le32_to_cpu(key->flags);
+       key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
+       key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
+       key->iv_initialized = le32_to_cpu(key->iv_initialized);
 }
 
 static s32
@@ -606,10 +598,10 @@ wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
        struct wl_priv *wl = wiphy_to_wl(wiphy);
        struct wireless_dev *wdev;
        s32 infra = 0;
-       s32 ap = 0;
        s32 err = 0;
 
        CHECK_SYS_UP();
+
        switch (type) {
        case NL80211_IFTYPE_MONITOR:
        case NL80211_IFTYPE_WDS:
@@ -618,37 +610,37 @@ wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
                return -EOPNOTSUPP;
        case NL80211_IFTYPE_ADHOC:
                wl->conf->mode = WL_MODE_IBSS;
+               infra = 0;
                break;
        case NL80211_IFTYPE_STATION:
                wl->conf->mode = WL_MODE_BSS;
                infra = 1;
                break;
        default:
-               return -EINVAL;
+               err = -EINVAL;
+               goto done;
        }
-       infra = htod32(infra);
-       ap = htod32(ap);
-       wdev = ndev->ieee80211_ptr;
-       wdev->iftype = type;
-       WL_DBG("%s : ap (%d), infra (%d)\n", ndev->name, ap, infra);
+
+       infra = cpu_to_le32(infra);
        err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
        if (unlikely(err)) {
                WL_ERR("WLC_SET_INFRA error (%d)\n", err);
-               return err;
-       }
-       err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
-       if (unlikely(err)) {
-               WL_ERR("WLC_SET_AP error (%d)\n", err);
-               return err;
+               err = -EAGAIN;
+       } else {
+               wdev = ndev->ieee80211_ptr;
+               wdev->iftype = type;
        }
 
-       /* -EINPROGRESS: Call commit handler */
-       return -EINPROGRESS;
+       WL_INFO("IF Type = %s\n",
+               (wl->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra");
+
+done:
+       return err;
 }
 
 static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
 {
-       memcpy(&params->bssid, &ether_bcast, ETH_ALEN);
+       memcpy(params->bssid, ether_bcast, ETH_ALEN);
        params->bss_type = DOT11_BSSTYPE_ANY;
        params->scan_type = 0;
        params->nprobes = -1;
@@ -657,10 +649,10 @@ static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
        params->home_time = -1;
        params->channel_num = 0;
 
-       params->nprobes = htod32(params->nprobes);
-       params->active_time = htod32(params->active_time);
-       params->passive_time = htod32(params->passive_time);
-       params->home_time = htod32(params->home_time);
+       params->nprobes = cpu_to_le32(params->nprobes);
+       params->active_time = cpu_to_le32(params->active_time);
+       params->passive_time = cpu_to_le32(params->passive_time);
+       params->home_time = cpu_to_le32(params->home_time);
        if (ssid && ssid->SSID_len)
                memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
 
@@ -673,7 +665,7 @@ wl_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
        s32 iolen;
 
        iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-       BUG_ON(unlikely(!iolen));
+       BUG_ON(!iolen);
 
        return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
 }
@@ -685,7 +677,7 @@ wl_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
        s32 iolen;
 
        iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-       BUG_ON(unlikely(!iolen));
+       BUG_ON(!iolen);
 
        return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
 }
@@ -703,14 +695,13 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
        params = kzalloc(params_size, GFP_KERNEL);
        if (unlikely(!params))
                return -ENOMEM;
-       memset(params, 0, params_size);
-       BUG_ON(unlikely(params_size >= WLC_IOCTL_SMLEN));
+       BUG_ON(params_size >= WLC_IOCTL_SMLEN);
 
        wl_iscan_prep(&params->params, ssid);
 
-       params->version = htod32(ISCAN_REQ_VERSION);
-       params->action = htod16(action);
-       params->scan_duration = htod16(0);
+       params->version = cpu_to_le32(ISCAN_REQ_VERSION);
+       params->action = cpu_to_le16(action);
+       params->scan_duration = cpu_to_le16(0);
 
        /* params_size += offsetof(wl_iscan_params_t, params); */
        err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
@@ -813,7 +804,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                            min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
                if (sr->ssid.SSID_len) {
                        memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
-                       sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
+                       sr->ssid.SSID_len = cpu_to_le32(sr->ssid.SSID_len);
                        WL_DBG("Specific scan ssid=\"%s\" len=%d\n",
                               sr->ssid.SSID, sr->ssid.SSID_len);
                        spec_scan = true;
@@ -873,9 +864,9 @@ static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
        u32 len;
        s32 err = 0;
 
-       val = htod32(val);
+       val = cpu_to_le32(val);
        len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
-       BUG_ON(unlikely(!len));
+       BUG_ON(!len);
 
        err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
        if (unlikely(err)) {
@@ -899,12 +890,12 @@ wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
        len =
            bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
                        sizeof(var.buf));
-       BUG_ON(unlikely(!len));
+       BUG_ON(!len);
        err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
        if (unlikely(err)) {
                WL_ERR("error (%d)\n", err);
        }
-       *retval = dtoh32(var.val);
+       *retval = le32_to_cpu(var.val);
 
        return err;
 }
@@ -938,7 +929,7 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
        s32 err = 0;
        u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
 
-       retry = htod32(retry);
+       retry = cpu_to_le32(retry);
        err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
        if (unlikely(err)) {
                WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
@@ -992,68 +983,137 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
                      struct cfg80211_ibss_params *params)
 {
        struct wl_priv *wl = wiphy_to_wl(wiphy);
-       struct cfg80211_bss *bss;
-       struct ieee80211_channel *chan;
        struct wl_join_params join_params;
-       struct cfg80211_ssid ssid;
-       s32 scan_retry = 0;
+       size_t join_params_size = 0;
        s32 err = 0;
+       s32 wsec = 0;
+       s32 bcnprd;
 
        CHECK_SYS_UP();
-       if (params->bssid) {
-               WL_ERR("Invalid bssid\n");
+
+       if (params->ssid)
+               WL_DBG("SSID: %s\n", params->ssid);
+       else {
+               WL_DBG("SSID: NULL, Not supported\n");
                return -EOPNOTSUPP;
        }
-       bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
-       if (!bss) {
-               memcpy(ssid.ssid, params->ssid, params->ssid_len);
-               ssid.ssid_len = params->ssid_len;
-               do {
-                       if (unlikely
-                           (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
-                            -EBUSY)) {
-                               wl_delay(150);
-                       } else {
-                               break;
-                       }
-               } while (++scan_retry < WL_SCAN_RETRY_MAX);
-               rtnl_unlock();  /* to allow scan_inform to paropagate
-                                        to cfg80211 plane */
-               schedule_timeout_interruptible(4 * HZ); /* wait 4 secons
-                                                till scan done.... */
-               rtnl_lock();
-               bss = cfg80211_get_ibss(wiphy, NULL,
-                                       params->ssid, params->ssid_len);
+
+       if (params->bssid)
+               WL_DBG("BSSID: %02X %02X %02X %02X %02X %02X\n",
+               params->bssid[0], params->bssid[1], params->bssid[2],
+               params->bssid[3], params->bssid[4], params->bssid[5]);
+       else
+               WL_DBG("No BSSID specified\n");
+
+       if (params->channel)
+               WL_DBG("channel: %d\n", params->channel->center_freq);
+       else
+               WL_DBG("no channel specified\n");
+
+       if (params->channel_fixed)
+               WL_DBG("fixed channel required\n");
+       else
+               WL_DBG("no fixed channel required\n");
+
+       if (params->ie && params->ie_len)
+               WL_DBG("ie len: %d\n", params->ie_len);
+       else
+               WL_DBG("no ie specified\n");
+
+       if (params->beacon_interval)
+               WL_DBG("beacon interval: %d\n", params->beacon_interval);
+       else
+               WL_DBG("no beacon interval specified\n");
+
+       if (params->basic_rates)
+               WL_DBG("basic rates: %08X\n", params->basic_rates);
+       else
+               WL_DBG("no basic rates specified\n");
+
+       if (params->privacy)
+               WL_DBG("privacy required\n");
+       else
+               WL_DBG("no privacy required\n");
+
+       /* Configure Privacy for starter */
+       if (params->privacy)
+               wsec |= WEP_ENABLED;
+
+       err = wl_dev_intvar_set(dev, "wsec", wsec);
+       if (unlikely(err)) {
+               WL_ERR("wsec failed (%d)\n", err);
+               goto done;
+       }
+
+       /* Configure Beacon Interval for starter */
+       if (params->beacon_interval)
+               bcnprd = cpu_to_le32(params->beacon_interval);
+       else
+               bcnprd = cpu_to_le32(100);
+
+       err = wl_dev_ioctl(dev, WLC_SET_BCNPRD, &bcnprd, sizeof(bcnprd));
+       if (unlikely(err)) {
+               WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err);
+               goto done;
        }
-       if (bss) {
-               wl->ibss_starter = false;
-               WL_DBG("Found IBSS\n");
+
+       /* Configure required join parameter */
+       memset(&join_params, 0, sizeof(wl_join_params_t));
+
+       /* SSID */
+       join_params.ssid.SSID_len =
+                       (params->ssid_len > 32) ? 32 : params->ssid_len;
+       memcpy(join_params.ssid.SSID, params->ssid, join_params.ssid.SSID_len);
+       join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
+       join_params_size = sizeof(join_params.ssid);
+       wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
+
+       /* BSSID */
+       if (params->bssid) {
+               memcpy(join_params.params.bssid, params->bssid, ETH_ALEN);
+               join_params_size =
+                       sizeof(join_params.ssid) + WL_ASSOC_PARAMS_FIXED_SIZE;
        } else {
-               wl->ibss_starter = true;
+               memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
        }
-       chan = params->channel;
-       if (chan)
-               wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
-       /*
-        ** Join with specific BSSID and cached SSID
-        ** If SSID is zero join based on BSSID only
-        */
-       memset(&join_params, 0, sizeof(join_params));
-       memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
-              params->ssid_len);
-       join_params.ssid.SSID_len = htod32(params->ssid_len);
-       if (params->bssid)
-               memcpy(&join_params.params.bssid, params->bssid,
-                      ETH_ALEN);
-       else
-               memset(&join_params.params.bssid, 0, ETH_ALEN);
+       wl_update_prof(wl, NULL, &join_params.params.bssid, WL_PROF_BSSID);
+
+       /* Channel */
+       if (params->channel) {
+               u32 target_channel;
 
-       err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params,
-                       sizeof(join_params));
+               wl->channel =
+                       ieee80211_frequency_to_channel(
+                               params->channel->center_freq);
+               if (params->channel_fixed) {
+                       /* adding chanspec */
+                       wl_ch_to_chanspec(wl->channel,
+                               &join_params, &join_params_size);
+               }
+
+               /* set channel for starter */
+               target_channel = cpu_to_le32(wl->channel);
+               err = wl_dev_ioctl(dev, WLC_SET_CHANNEL,
+                       &target_channel, sizeof(target_channel));
+               if (unlikely(err)) {
+                       WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err);
+                       goto done;
+               }
+       } else
+               wl->channel = 0;
+
+       wl->ibss_starter = false;
+
+
+       err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
        if (unlikely(err)) {
-               WL_ERR("Error (%d)\n", err);
-               return err;
+               WL_ERR("WLC_SET_SSID failed (%d)\n", err);
+               goto done;
        }
+
+       set_bit(WL_STATUS_CONNECTING, &wl->status);
+
+done:
        return err;
 }
 
@@ -1336,10 +1396,12 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                return -EOPNOTSUPP;
        }
        if (chan) {
-               wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
+               wl->channel =
+                       ieee80211_frequency_to_channel(chan->center_freq);
                WL_DBG("channel (%d), center_req (%d)\n",
-                      wl->channel, chan->center_freq);
-       }
+                       wl->channel, chan->center_freq);
+       } else
+               wl->channel = 0;
        WL_DBG("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len);
        err = wl_set_wpa_version(dev, sme);
        if (unlikely(err))
@@ -1371,17 +1433,20 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 
        join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
        memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
-       join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
+       join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
        wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
-       memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
 
-       wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
-       WL_DBG("join_param_size %d\n", join_params_size);
+       if (sme->bssid)
+               memcpy(join_params.params.bssid, sme->bssid, ETH_ALEN);
+       else
+               memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
 
        if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
                WL_DBG("ssid \"%s\", len (%d)\n",
                       join_params.ssid.SSID, join_params.ssid.SSID_len);
        }
+
+       wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
        err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
        if (unlikely(err)) {
                WL_ERR("error (%d)\n", err);
@@ -1398,23 +1463,22 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 {
        struct wl_priv *wl = wiphy_to_wl(wiphy);
        scb_val_t scbval;
-       bool act = false;
        s32 err = 0;
 
        WL_DBG("Reason %d\n", reason_code);
        CHECK_SYS_UP();
-       act = *(bool *) wl_read_prof(wl, WL_PROF_ACT);
-       if (likely(act)) {
-               scbval.val = reason_code;
-               memcpy(&scbval.ea, &wl->bssid, ETH_ALEN);
-               scbval.val = htod32(scbval.val);
-               err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
-                               sizeof(scb_val_t));
-               if (unlikely(err)) {
-                       WL_ERR("error (%d)\n", err);
-                       return err;
-               }
-       }
+
+       clear_bit(WL_STATUS_CONNECTED, &wl->status);
+
+       scbval.val = reason_code;
+       memcpy(&scbval.ea, wl_read_prof(wl, WL_PROF_BSSID), ETH_ALEN);
+       scbval.val = cpu_to_le32(scbval.val);
+       err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
+                       sizeof(scb_val_t));
+       if (unlikely(err))
+               WL_ERR("error (%d)\n", err);
+
+       wl->link_up = false;
 
        return err;
 }
@@ -1449,7 +1513,7 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy,
        }
        /* Make sure radio is off or on as far as software is concerned */
        disable = WL_RADIO_SW_DISABLE << 16;
-       disable = htod32(disable);
+       disable = cpu_to_le32(disable);
        err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
        if (unlikely(err)) {
                WL_ERR("WLC_SET_RADIO error (%d)\n", err);
@@ -1493,7 +1557,7 @@ static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
 
 static s32
 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
-                              u8 key_idx)
+                              u8 key_idx, bool unicast, bool multicast)
 {
        u32 index;
        s32 wsec;
@@ -1507,11 +1571,11 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
                WL_ERR("WLC_GET_WSEC error (%d)\n", err);
                return err;
        }
-       wsec = dtoh32(wsec);
+       wsec = le32_to_cpu(wsec);
        if (wsec & WEP_ENABLED) {
                /* Just select a new current key */
                index = (u32) key_idx;
-               index = htod32(index);
+               index = cpu_to_le32(index);
                err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
                                sizeof(index));
                if (unlikely(err)) {
@@ -1617,6 +1681,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        s32 val;
        s32 wsec;
        s32 err = 0;
+       u8 keybuf[8];
 
        WL_DBG("key index (%d)\n", key_idx);
        CHECK_SYS_UP();
@@ -1645,6 +1710,9 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                WL_DBG("WLAN_CIPHER_SUITE_WEP104\n");
                break;
        case WLAN_CIPHER_SUITE_TKIP:
+               memcpy(keybuf, &key.data[24], sizeof(keybuf));
+               memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
+               memcpy(&key.data[16], keybuf, sizeof(keybuf));
                key.algo = CRYPTO_ALGO_TKIP;
                WL_DBG("WLAN_CIPHER_SUITE_TKIP\n");
                break;
@@ -1684,7 +1752,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        }
 
        val = 1;                /* assume shared key. otherwise 0 */
-       val = htod32(val);
+       val = cpu_to_le32(val);
        err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
        if (unlikely(err)) {
                WL_ERR("WLC_SET_AUTH error (%d)\n", err);
@@ -1740,7 +1808,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
        }
 
        val = 0;                /* assume open key. otherwise 1 */
-       val = htod32(val);
+       val = cpu_to_le32(val);
        err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
        if (unlikely(err)) {
                WL_ERR("WLC_SET_AUTH error (%d)\n", err);
@@ -1768,7 +1836,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
        key.index = key_idx;
        swap_key_to_BE(&key);
        memset(&params, 0, sizeof(params));
-       params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
+       params.key_len = (u8) min_t(u8, WLAN_MAX_KEY_LEN, key.len);
        memcpy(params.key, key.data, params.key_len);
 
        err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
@@ -1776,7 +1844,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
                WL_ERR("WLC_GET_WSEC error (%d)\n", err);
                return err;
        }
-       wsec = dtoh32(wsec);
+       wsec = le32_to_cpu(wsec);
        switch (wsec) {
        case WEP_ENABLED:
                sec = wl_read_prof(wl, WL_PROF_SEC);
@@ -1836,7 +1904,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
        if (err) {
                WL_ERR("Could not get rate (%d)\n", err);
        } else {
-               rate = dtoh32(rate);
+               rate = le32_to_cpu(rate);
                sinfo->filled |= STATION_INFO_TX_BITRATE;
                sinfo->txrate.legacy = rate * 5;
                WL_DBG("Rate %d Mbps\n", rate / 2);
@@ -1850,7 +1918,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
                        WL_ERR("Could not get rssi (%d)\n", err);
                        return err;
                }
-               rssi = dtoh32(scb_val.val);
+               rssi = le32_to_cpu(scb_val.val);
                sinfo->filled |= STATION_INFO_SIGNAL;
                sinfo->signal = rssi;
                WL_DBG("RSSI %d dBm\n", rssi);
@@ -1868,7 +1936,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 
        CHECK_SYS_UP();
        pm = enabled ? PM_FAST : PM_OFF;
-       pm = htod32(pm);
+       pm = cpu_to_le32(pm);
        WL_DBG("power save %s\n", (pm ? "enabled" : "disabled"));
        err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
        if (unlikely(err)) {
@@ -1931,7 +1999,7 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
                return err;
        }
 
-       rateset.count = dtoh32(rateset.count);
+       rateset.count = le32_to_cpu(rateset.count);
 
        legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
        if (!legacy)
@@ -1966,34 +2034,91 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
 
 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
 {
-       s32 err = 0;
+       struct wl_priv *wl = wiphy_to_wl(wiphy);
+       struct net_device *ndev = wl_to_ndev(wl);
 
-       CHECK_SYS_UP();
-       wl_invoke_iscan(wiphy_to_wl(wiphy));
+       /*
+        * Check for WL_STATUS_READY before any function call which
+        * could result is bus access. Don't block the resume for
+        * any driver error conditions
+        */
 
-       return err;
+#if defined(CONFIG_PM_SLEEP)
+       atomic_set(&dhd_mmc_suspend, false);
+#endif /*  defined(CONFIG_PM_SLEEP) */
+
+       if (test_bit(WL_STATUS_READY, &wl->status)) {
+               /* Turn on Watchdog timer */
+               wl_os_wd_timer(ndev, dhd_watchdog_ms);
+               wl_invoke_iscan(wiphy_to_wl(wiphy));
+       }
+
+       return 0;
 }
 
 static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
 {
        struct wl_priv *wl = wiphy_to_wl(wiphy);
        struct net_device *ndev = wl_to_ndev(wl);
-       s32 err = 0;
 
-       CHECK_SYS_UP();
+
+       /*
+        * Check for WL_STATUS_READY before any function call which
+        * could result is bus access. Don't block the suspend for
+        * any driver error conditions
+        */
+
+       /*
+        * While going to suspend if associated with AP disassociate
+        * from AP to save power while system is in suspended state
+        */
+       if (test_bit(WL_STATUS_CONNECTED, &wl->status) &&
+               test_bit(WL_STATUS_READY, &wl->status)) {
+               WL_INFO("Disassociating from AP"
+                       " while entering suspend state\n");
+               wl_link_down(wl);
+
+               /*
+                * Make sure WPA_Supplicant receives all the event
+                * generated due to DISASSOC call to the fw to keep
+                * the state fw and WPA_Supplicant state consistent
+                */
+               rtnl_unlock();
+               wl_delay(500);
+               rtnl_lock();
+       }
 
        set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
-       wl_term_iscan(wl);
+       if (test_bit(WL_STATUS_READY, &wl->status))
+               wl_term_iscan(wl);
+
        if (wl->scan_request) {
-               cfg80211_scan_done(wl->scan_request, true);     /* true means
-                                                                abort */
-               wl_set_mpc(ndev, 1);
+               /* Indidate scan abort to cfg80211 layer */
+               WL_INFO("Terminating scan in progress\n");
+               cfg80211_scan_done(wl->scan_request, true);
                wl->scan_request = NULL;
        }
        clear_bit(WL_STATUS_SCANNING, &wl->status);
        clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
+       clear_bit(WL_STATUS_CONNECTING, &wl->status);
+       clear_bit(WL_STATUS_CONNECTED, &wl->status);
 
-       return err;
+       /* Inform SDIO stack not to switch off power to the chip */
+       sdioh_sdio_set_host_pm_flags(MMC_PM_KEEP_POWER);
+
+       /* Turn off watchdog timer */
+       if (test_bit(WL_STATUS_READY, &wl->status)) {
+               WL_INFO("Terminate watchdog timer and enable MPC\n");
+               wl_set_mpc(ndev, 1);
+               wl_os_wd_timer(ndev, 0);
+       }
+
+#if defined(CONFIG_PM_SLEEP)
+       atomic_set(&dhd_mmc_suspend, true);
+#endif /*  defined(CONFIG_PM_SLEEP) */
+
+
+       return 0;
 }
 
 static __used s32
@@ -2005,8 +2130,8 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
        WL_DBG("No of elements %d\n", pmk_list->pmkids.npmkid);
        for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
                WL_DBG("PMKID[%d]: %pM =\n", i,
-                      &pmk_list->pmkids.pmkid[i].BSSID);
-               for (j = 0; j < WPA2_PMKID_LEN; j++) {
+                       &pmk_list->pmkids.pmkid[i].BSSID);
+               for (j = 0; j < WLAN_PMKID_LEN; j++) {
                        WL_DBG("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
                }
        }
@@ -2035,7 +2160,7 @@ wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
                memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
                       ETH_ALEN);
                memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
-                      WPA2_PMKID_LEN);
+                      WLAN_PMKID_LEN);
                if (i == wl->pmk_list->pmkids.npmkid)
                        wl->pmk_list->pmkids.npmkid++;
        } else {
@@ -2043,7 +2168,7 @@ wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
        }
        WL_DBG("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
               &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID);
-       for (i = 0; i < WPA2_PMKID_LEN; i++) {
+       for (i = 0; i < WLAN_PMKID_LEN; i++) {
                WL_DBG("%02x\n",
                       wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].
                       PMKID[i]);
@@ -2065,11 +2190,11 @@ wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
 
        CHECK_SYS_UP();
        memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
-       memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+       memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
 
        WL_DBG("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
               &pmkid.pmkid[0].BSSID);
-       for (i = 0; i < WPA2_PMKID_LEN; i++) {
+       for (i = 0; i < WLAN_PMKID_LEN; i++) {
                WL_DBG("%02x\n", pmkid.pmkid[0].PMKID[i]);
        }
 
@@ -2088,7 +2213,7 @@ wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
                               ETH_ALEN);
                        memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
                               &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
-                              WPA2_PMKID_LEN);
+                              WLAN_PMKID_LEN);
                }
                wl->pmk_list->pmkids.npmkid--;
        } else {
@@ -2250,105 +2375,146 @@ static s32 wl_inform_bss(struct wl_priv *wl)
        return err;
 }
 
+
 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 {
        struct wiphy *wiphy = wl_to_wiphy(wl);
-       struct ieee80211_mgmt *mgmt;
-       struct ieee80211_channel *channel;
+       struct ieee80211_channel *notify_channel;
+       struct cfg80211_bss *bss;
        struct ieee80211_supported_band *band;
-       struct wl_cfg80211_bss_info *notif_bss_info;
-       struct wl_scan_req *sr = wl_to_sr(wl);
-       struct beacon_proberesp *beacon_proberesp;
-       s32 mgmt_type;
-       u32 signal;
-       u32 freq;
        s32 err = 0;
-
-       if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
-               WL_DBG("Beacon is larger than buffer. Discarding\n");
-               return err;
-       }
-       notif_bss_info =
-           kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(u8) +
-                   WL_BSS_INFO_MAX, GFP_KERNEL);
-       if (unlikely(!notif_bss_info)) {
-               WL_ERR("notif_bss_info alloc failed\n");
-               return -ENOMEM;
+       u16 channel;
+       u32 freq;
+       u64 notify_timestamp;
+       u16 notify_capability;
+       u16 notify_interval;
+       u8 *notify_ie;
+       size_t notify_ielen;
+       s32 notify_signal;
+
+       if (unlikely(le32_to_cpu(bi->length) > WL_BSS_INFO_MAX)) {
+               WL_ERR("Bss info is larger than buffer. Discarding\n");
+               return 0;
        }
-       mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
-       notif_bss_info->channel =
-               bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(bi->chanspec);
 
-       if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
+       channel = bi->ctl_ch ? bi->ctl_ch :
+                               CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+
+       if (channel <= CH_MAX_2G_CHANNEL)
                band = wiphy->bands[IEEE80211_BAND_2GHZ];
        else
                band = wiphy->bands[IEEE80211_BAND_5GHZ];
-       notif_bss_info->rssi = bi->RSSI;
-       memcpy(mgmt->bssid, &bi->BSSID, ETH_ALEN);
-       mgmt_type = wl->active_scan ?
-               IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
-       if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
-               mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
-                                                       mgmt_type);
-       }
-       beacon_proberesp = wl->active_scan ?
-               (struct beacon_proberesp *)&mgmt->u.probe_resp :
-               (struct beacon_proberesp *)&mgmt->u.beacon;
-       beacon_proberesp->timestamp = 0;
-       beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
-       beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
-       wl_rst_ie(wl);
-       /*
-       * wl_add_ie is not necessary because it can only add duplicated
-       * SSID, rate information to frame_buf
-       */
-       /*
-       * wl_add_ie(wl, WLAN_EID_SSID, bi->SSID_len, bi->SSID);
-       * wl_add_ie(wl, WLAN_EID_SUPP_RATES, bi->rateset.count,
-       * bi->rateset.rates);
-       */
-       wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
-       wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
-                offsetof(struct wl_cfg80211_bss_info, frame_buf));
-       notif_bss_info->frame_len =
-           offsetof(struct ieee80211_mgmt,
-                    u.beacon.variable) + wl_get_ielen(wl);
-       freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
-       channel = ieee80211_get_channel(wiphy, freq);
-
-       WL_DBG("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
-              bi->SSID,
-              notif_bss_info->rssi, notif_bss_info->channel,
-              mgmt->u.beacon.capab_info, &bi->BSSID);
-
-       signal = notif_bss_info->rssi * 100;
-       if (unlikely(!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
-                                               le16_to_cpu
-                                               (notif_bss_info->frame_len),
-                                               signal, GFP_KERNEL))) {
+
+       freq = ieee80211_channel_to_frequency(channel, band->band);
+       notify_channel = ieee80211_get_channel(wiphy, freq);
+
+       notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
+       notify_capability = le16_to_cpu(bi->capability);
+       notify_interval = le16_to_cpu(bi->beacon_period);
+       notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+       notify_ielen = le16_to_cpu(bi->ie_length);
+       notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
+
+       WL_DBG("bssid: %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X\n",
+                       bi->BSSID[0], bi->BSSID[1], bi->BSSID[2],
+                       bi->BSSID[3], bi->BSSID[4], bi->BSSID[5]);
+       WL_DBG("Channel: %d(%d)\n", channel, freq);
+       WL_DBG("Capability: %X\n", notify_capability);
+       WL_DBG("Beacon interval: %d\n", notify_interval);
+       WL_DBG("Signal: %d\n", notify_signal);
+       WL_DBG("notify_timestamp: %#018llx\n", notify_timestamp);
+
+       bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
+               notify_timestamp, notify_capability, notify_interval, notify_ie,
+               notify_ielen, notify_signal, GFP_KERNEL);
+
+       if (unlikely(!bss)) {
                WL_ERR("cfg80211_inform_bss_frame error\n");
-               kfree(notif_bss_info);
                return -EINVAL;
        }
-       kfree(notif_bss_info);
+
+       return err;
+}
+
+static s32
+wl_inform_ibss(struct wl_priv *wl, struct net_device *dev, const u8 *bssid)
+{
+       struct wiphy *wiphy = wl_to_wiphy(wl);
+       struct ieee80211_channel *notify_channel;
+       struct wl_bss_info *bi = NULL;
+       struct ieee80211_supported_band *band;
+       u8 *buf = NULL;
+       s32 err = 0;
+       u16 channel;
+       u32 freq;
+       u64 notify_timestamp;
+       u16 notify_capability;
+       u16 notify_interval;
+       u8 *notify_ie;
+       size_t notify_ielen;
+       s32 notify_signal;
+
+       buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+       if (buf == NULL) {
+               WL_ERR("kzalloc() failed\n");
+               err = -ENOMEM;
+               goto CleanUp;
+       }
+
+       *(u32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
+
+       err = wl_dev_ioctl(dev, WLC_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+       if (unlikely(err)) {
+               WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err);
+               goto CleanUp;
+       }
+
+       bi = (wl_bss_info_t *)(buf + 4);
+
+       channel = bi->ctl_ch ? bi->ctl_ch :
+                               CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
+
+       if (channel <= CH_MAX_2G_CHANNEL)
+               band = wiphy->bands[IEEE80211_BAND_2GHZ];
+       else
+               band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+       freq = ieee80211_channel_to_frequency(channel, band->band);
+       notify_channel = ieee80211_get_channel(wiphy, freq);
+
+       notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
+       notify_capability = le16_to_cpu(bi->capability);
+       notify_interval = le16_to_cpu(bi->beacon_period);
+       notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
+       notify_ielen = le16_to_cpu(bi->ie_length);
+       notify_signal = (s16)le16_to_cpu(bi->RSSI) * 100;
+
+       WL_DBG("channel: %d(%d)\n", channel, freq);
+       WL_DBG("capability: %X\n", notify_capability);
+       WL_DBG("beacon interval: %d\n", notify_interval);
+       WL_DBG("signal: %d\n", notify_signal);
+       WL_DBG("notify_timestamp: %#018llx\n", notify_timestamp);
+
+       cfg80211_inform_bss(wiphy, notify_channel, bssid,
+               notify_timestamp, notify_capability, notify_interval,
+               notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
+
+CleanUp:
+
+       kfree(buf);
 
        return err;
 }
 
 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
 {
-       u32 event = ntoh32(e->event_type);
-       u16 flags = ntoh16(e->flags);
+       u32 event = be32_to_cpu(e->event_type);
+       u32 status = be32_to_cpu(e->status);
 
-       if (event == WLC_E_LINK) {
-               if (flags & WLC_EVENT_MSG_LINK) {
-                       if (wl_is_ibssmode(wl)) {
-                               if (wl_is_ibssstarter(wl)) {
-                               }
-                       } else {
-                               return true;
-                       }
-               }
+       if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) {
+               WL_DBG("Processing set ssid\n");
+               wl->link_up = true;
+               return true;
        }
 
        return false;
@@ -2356,27 +2522,31 @@ static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
 
 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
 {
-       u32 event = ntoh32(e->event_type);
-       u16 flags = ntoh16(e->flags);
+       u32 event = be32_to_cpu(e->event_type);
+       u16 flags = be16_to_cpu(e->flags);
 
-       if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
+       if (event == WLC_E_LINK && (!(flags & WLC_EVENT_MSG_LINK))) {
+               WL_DBG("Processing link down\n");
                return true;
-       } else if (event == WLC_E_LINK) {
-               if (!(flags & WLC_EVENT_MSG_LINK))
-                       return true;
        }
-
        return false;
 }
 
 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
 {
-       u32 event = ntoh32(e->event_type);
-       u32 status = ntoh32(e->status);
+       u32 event = be32_to_cpu(e->event_type);
+       u32 status = be32_to_cpu(e->status);
+       u16 flags = be16_to_cpu(e->flags);
 
-       if (event == WLC_E_SET_SSID || event == WLC_E_LINK) {
-               if (status == WLC_E_STATUS_NO_NETWORKS)
-                       return true;
+       if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS) {
+               WL_DBG("Processing Link %s & no network found\n",
+                               flags & WLC_EVENT_MSG_LINK ? "up" : "down");
+               return true;
+       }
+
+       if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS) {
+               WL_DBG("Processing connecting & no network found\n");
+               return true;
        }
 
        return false;
@@ -2386,30 +2556,39 @@ static s32
 wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
                         const wl_event_msg_t *e, void *data)
 {
-       bool act;
        s32 err = 0;
 
        if (wl_is_linkup(wl, e)) {
-               wl_link_up(wl);
+               WL_DBG("Linkup\n");
                if (wl_is_ibssmode(wl)) {
-                       cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
-                                            GFP_KERNEL);
-                       WL_DBG("joined in IBSS network\n");
-               } else {
+                       wl_update_prof(wl, NULL, (void *)e->addr,
+                               WL_PROF_BSSID);
+                       wl_inform_ibss(wl, ndev, e->addr);
+                       cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
+                       clear_bit(WL_STATUS_CONNECTING, &wl->status);
+                       set_bit(WL_STATUS_CONNECTED, &wl->status);
+               } else
                        wl_bss_connect_done(wl, ndev, e, data, true);
-                       WL_DBG("joined in BSS network \"%s\"\n",
-                              ((struct wlc_ssid *)
-                               wl_read_prof(wl, WL_PROF_SSID))->SSID);
-               }
-               act = true;
-               wl_update_prof(wl, e, &act, WL_PROF_ACT);
        } else if (wl_is_linkdown(wl, e)) {
-               cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
-               clear_bit(WL_STATUS_CONNECTED, &wl->status);
-               wl_link_down(wl);
+               WL_DBG("Linkdown\n");
+               if (wl_is_ibssmode(wl)) {
+                       if (test_and_clear_bit(WL_STATUS_CONNECTED,
+                               &wl->status))
+                               wl_link_down(wl);
+               } else {
+                       if (test_and_clear_bit(WL_STATUS_CONNECTED,
+                               &wl->status)) {
+                               cfg80211_disconnected(ndev, 0, NULL, 0,
+                                       GFP_KERNEL);
+                               wl_link_down(wl);
+                       }
+               }
                wl_init_prof(wl->profile);
        } else if (wl_is_nonetwork(wl, e)) {
-               wl_bss_connect_done(wl, ndev, e, data, false);
+               if (wl_is_ibssmode(wl))
+                       clear_bit(WL_STATUS_CONNECTING, &wl->status);
+               else
+                       wl_bss_connect_done(wl, ndev, e, data, false);
        }
 
        return err;
@@ -2419,12 +2598,16 @@ static s32
 wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev,
                         const wl_event_msg_t *e, void *data)
 {
-       bool act;
        s32 err = 0;
+       u32 event = be32_to_cpu(e->event_type);
+       u32 status = be32_to_cpu(e->status);
 
-       wl_bss_roaming_done(wl, ndev, e, data);
-       act = true;
-       wl_update_prof(wl, e, &act, WL_PROF_ACT);
+       if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) {
+               if (test_bit(WL_STATUS_CONNECTED, &wl->status))
+                       wl_bss_roaming_done(wl, ndev, e, data);
+               else
+                       wl_bss_connect_done(wl, ndev, e, data, true);
+       }
 
        return err;
 }
@@ -2436,7 +2619,7 @@ wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
        u32 buflen;
 
        buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
-       BUG_ON(unlikely(!buflen));
+       BUG_ON(!buflen);
 
        return wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
 }
@@ -2450,7 +2633,7 @@ wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
        s32 err = 0;
 
        len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
-       BUG_ON(unlikely(!len));
+       BUG_ON(!len);
        err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
                        WL_IOCTL_LEN_MAX);
        if (unlikely(err)) {
@@ -2471,6 +2654,8 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl)
        u32 resp_len;
        s32 err = 0;
 
+       wl_clear_assoc_ies(wl);
+
        err = wl_dev_bufvar_get(ndev, "assoc_info", wl->extra_buf,
                                WL_ASSOC_INFO_MAX);
        if (unlikely(err)) {
@@ -2514,6 +2699,19 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl)
        return err;
 }
 
+static void wl_clear_assoc_ies(struct wl_priv *wl)
+{
+       struct wl_connect_info *conn_info = wl_to_conn(wl);
+
+       kfree(conn_info->req_ie);
+       conn_info->req_ie = NULL;
+       conn_info->req_ie_len = 0;
+       kfree(conn_info->resp_ie);
+       conn_info->resp_ie = NULL;
+       conn_info->resp_ie_len = 0;
+}
+
+
 static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
        size_t *join_params_size)
 {
@@ -2523,7 +2721,7 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
                join_params->params.chanspec_num = 1;
                join_params->params.chanspec_list[0] = ch;
 
-               if (join_params->params.chanspec_list[0])
+               if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
                        chanspec |= WL_CHANSPEC_BAND_2G;
                else
                        chanspec |= WL_CHANSPEC_BAND_5G;
@@ -2537,10 +2735,10 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
                join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
                join_params->params.chanspec_list[0] |= chanspec;
                join_params->params.chanspec_list[0] =
-               htodchanspec(join_params->params.chanspec_list[0]);
+               cpu_to_le16(join_params->params.chanspec_list[0]);
 
                join_params->params.chanspec_num =
-                       htod32(join_params->params.chanspec_num);
+                       cpu_to_le32(join_params->params.chanspec_num);
 
                WL_DBG("join_params->params.chanspec_list[0]= %#X, channel %d, chanspec %#X\n",
                       join_params->params.chanspec_list[0], ch, chanspec);
@@ -2549,7 +2747,6 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
 
 static s32 wl_update_bss_info(struct wl_priv *wl)
 {
-       struct cfg80211_bss *bss;
        struct wl_bss_info *bi;
        struct wlc_ssid *ssid;
        struct bcm_tlv *tim;
@@ -2563,63 +2760,46 @@ static s32 wl_update_bss_info(struct wl_priv *wl)
                return err;
 
        ssid = (struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID);
-       bss =
-           cfg80211_get_bss(wl_to_wiphy(wl), NULL, (s8 *)&wl->bssid,
-                            ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
-                            WLAN_CAPABILITY_ESS);
-
-       rtnl_lock();
-       if (unlikely(!bss)) {
-               WL_DBG("Could not find the AP\n");
-               *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
-               err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO,
-                               wl->extra_buf, WL_EXTRA_BUF_MAX);
-               if (unlikely(err)) {
-                       WL_ERR("Could not get bss info %d\n", err);
-                       goto update_bss_info_out;
-               }
-               bi = (struct wl_bss_info *)(wl->extra_buf + 4);
-               if (unlikely(memcmp(&bi->BSSID, &wl->bssid, ETH_ALEN))) {
-                       err = -EIO;
-                       goto update_bss_info_out;
-               }
-               err = wl_inform_single_bss(wl, bi);
-               if (unlikely(err))
-                       goto update_bss_info_out;
 
-               ie = ((u8 *)bi) + bi->ie_offset;
-               ie_len = bi->ie_length;
-               beacon_interval = cpu_to_le16(bi->beacon_period);
-       } else {
-               WL_DBG("Found the AP in the list - BSSID %pM\n", bss->bssid);
-               ie = bss->information_elements;
-               ie_len = bss->len_information_elements;
-               beacon_interval = bss->beacon_interval;
-               cfg80211_put_bss(bss);
+       *(u32 *)wl->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
+       err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO,
+                       wl->extra_buf, WL_EXTRA_BUF_MAX);
+       if (unlikely(err)) {
+               WL_ERR("Could not get bss info %d\n", err);
+               goto update_bss_info_out;
        }
 
+       bi = (struct wl_bss_info *)(wl->extra_buf + 4);
+       err = wl_inform_single_bss(wl, bi);
+       if (unlikely(err))
+               goto update_bss_info_out;
+
+       ie = ((u8 *)bi) + bi->ie_offset;
+       ie_len = bi->ie_length;
+       beacon_interval = cpu_to_le16(bi->beacon_period);
+
        tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
-       if (tim) {
+       if (tim)
                dtim_period = tim->data[1];
-       else {
+       else {
                /*
                * active scan was done so we could not get dtim
                * information out of probe response.
                * so we speficially query dtim information to dongle.
                */
-               err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_DTIMPRD,
-                       &dtim_period, sizeof(dtim_period));
+               u32 var;
+               err = wl_dev_intvar_get(wl_to_ndev(wl), "dtim_assoc", &var);
                if (unlikely(err)) {
-                       WL_ERR("WLC_GET_DTIMPRD error (%d)\n", err);
+                       WL_ERR("wl dtim_assoc failed (%d)\n", err);
                        goto update_bss_info_out;
                }
+               dtim_period = (u8)var;
        }
 
        wl_update_prof(wl, NULL, &beacon_interval, WL_PROF_BEACONINT);
        wl_update_prof(wl, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
 
 update_bss_info_out:
-       rtnl_unlock();
        return err;
 }
 
@@ -2631,10 +2811,11 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
        s32 err = 0;
 
        wl_get_assoc_ies(wl);
-       memcpy(&wl->bssid, &e->addr, ETH_ALEN);
+       wl_update_prof(wl, NULL, &e->addr, WL_PROF_BSSID);
        wl_update_bss_info(wl);
+
        cfg80211_roamed(ndev,
-                       (u8 *)&wl->bssid,
+                       (u8 *)wl_read_prof(wl, WL_PROF_BSSID),
                        conn_info->req_ie, conn_info->req_ie_len,
                        conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
        WL_DBG("Report roaming result\n");
@@ -2651,30 +2832,26 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
        struct wl_connect_info *conn_info = wl_to_conn(wl);
        s32 err = 0;
 
-       wl_get_assoc_ies(wl);
-       memcpy(&wl->bssid, &e->addr, ETH_ALEN);
-       wl_update_bss_info(wl);
+
        if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) {
+               if (completed) {
+                       wl_get_assoc_ies(wl);
+                       wl_update_prof(wl, NULL, &e->addr, WL_PROF_BSSID);
+                       wl_update_bss_info(wl);
+               }
                cfg80211_connect_result(ndev,
-                                       (u8 *)&wl->bssid,
+                                       (u8 *)wl_read_prof(wl, WL_PROF_BSSID),
                                        conn_info->req_ie,
                                        conn_info->req_ie_len,
                                        conn_info->resp_ie,
                                        conn_info->resp_ie_len,
                                        completed ? WLAN_STATUS_SUCCESS : WLAN_STATUS_AUTH_TIMEOUT,
                                        GFP_KERNEL);
+               if (completed)
+                       set_bit(WL_STATUS_CONNECTED, &wl->status);
                WL_DBG("Report connect result - connection %s\n",
-                      completed ? "succeeded" : "failed");
-       } else {
-               cfg80211_roamed(ndev,
-                               (u8 *)&wl->bssid,
-                               conn_info->req_ie, conn_info->req_ie_len,
-                               conn_info->resp_ie, conn_info->resp_ie_len,
-                               GFP_KERNEL);
-               WL_DBG("Report roaming result\n");
+                               completed ? "succeeded" : "failed");
        }
-       set_bit(WL_STATUS_CONNECTED, &wl->status);
-
        return err;
 }
 
@@ -2682,7 +2859,7 @@ static s32
 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
                     const wl_event_msg_t *e, void *data)
 {
-       u16 flags = ntoh16(e->flags);
+       u16 flags = be16_to_cpu(e->flags);
        enum nl80211_key_type key_type;
 
        rtnl_lock();
@@ -2723,7 +2900,7 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
                WL_ERR("scan busy (%d)\n", err);
                goto scan_done_out;
        }
-       channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
+       channel_inform.scan_channel = le32_to_cpu(channel_inform.scan_channel);
        if (unlikely(channel_inform.scan_channel)) {
 
                WL_DBG("channel_inform.scan_channel (%d)\n",
@@ -2732,16 +2909,16 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
        wl->bss_list = wl->scan_results;
        bss_list = wl->bss_list;
        memset(bss_list, 0, len);
-       bss_list->buflen = htod32(len);
+       bss_list->buflen = cpu_to_le32(len);
        err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len);
        if (unlikely(err)) {
                WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
                err = -EINVAL;
                goto scan_done_out;
        }
-       bss_list->buflen = dtoh32(bss_list->buflen);
-       bss_list->version = dtoh32(bss_list->version);
-       bss_list->count = dtoh32(bss_list->count);
+       bss_list->buflen = le32_to_cpu(bss_list->buflen);
+       bss_list->version = le32_to_cpu(bss_list->version);
+       bss_list->count = le32_to_cpu(bss_list->count);
 
        err = wl_inform_bss(wl);
        if (err)
@@ -2776,12 +2953,7 @@ static void wl_init_eloop_handler(struct wl_event_loop *el)
 {
        memset(el, 0, sizeof(*el));
        el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
-       el->handler[WLC_E_JOIN] = wl_notify_connect_status;
        el->handler[WLC_E_LINK] = wl_notify_connect_status;
-       el->handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
-       el->handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
-       el->handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
-       el->handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
        el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
        el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
        el->handler[WLC_E_SET_SSID] = wl_notify_connect_status;
@@ -2950,7 +3122,7 @@ wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
        results->count = 0;
 
        memset(&list, 0, sizeof(list));
-       list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
+       list.results.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
        err = wl_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
                                WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
                                WL_ISCAN_BUF_MAX);
@@ -2958,12 +3130,12 @@ wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
                WL_ERR("error (%d)\n", err);
                return err;
        }
-       results->buflen = dtoh32(results->buflen);
-       results->version = dtoh32(results->version);
-       results->count = dtoh32(results->count);
+       results->buflen = le32_to_cpu(results->buflen);
+       results->version = le32_to_cpu(results->version);
+       results->count = le32_to_cpu(results->count);
        WL_DBG("results->count = %d\n", results->count);
        WL_DBG("results->buflen = %d\n", results->buflen);
-       *status = dtoh32(list_buf->status);
+       *status = le32_to_cpu(list_buf->status);
        *bss_list = results;
 
        return err;
@@ -3274,7 +3446,7 @@ static s32 wl_event_handler(void *data)
 void
 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
 {
-       u32 event_type = ntoh32(e->event_type);
+       u32 event_type = be32_to_cpu(e->event_type);
        struct wl_priv *wl = ndev_to_wl(ndev);
 #if (WL_DBG_LEVEL > 0)
        s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
@@ -3373,7 +3545,6 @@ struct sdio_func *wl_cfg80211_get_sdio_func(void)
 static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
 {
        s32 infra = 0;
-       s32 ap = 0;
        s32 err = 0;
 
        switch (iftype) {
@@ -3384,6 +3555,7 @@ static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
                err = -EINVAL;
                return err;
        case NL80211_IFTYPE_ADHOC:
+               infra = 0;
                break;
        case NL80211_IFTYPE_STATION:
                infra = 1;
@@ -3393,21 +3565,14 @@ static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
                WL_ERR("invalid type (%d)\n", iftype);
                return err;
        }
-       infra = htod32(infra);
-       ap = htod32(ap);
-       WL_DBG("%s ap (%d), infra (%d)\n", ndev->name, ap, infra);
+       infra = cpu_to_le32(infra);
        err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
        if (unlikely(err)) {
                WL_ERR("WLC_SET_INFRA error (%d)\n", err);
                return err;
        }
-       err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
-       if (unlikely(err)) {
-               WL_ERR("WLC_SET_AP error (%d)\n", err);
-               return err;
-       }
 
-       return -EINPROGRESS;
+       return 0;
 }
 
 #ifndef EMBEDDED_PLATFORM
@@ -3468,120 +3633,10 @@ dongle_glom_out:
 }
 
 static s32
-wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
+wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol)
 {
        s8 iovbuf[WL_EVENTING_MASK_LEN + 12];   /*  Room for "event_msgs" +
-                                                '\0' + bitvec  */
-       s32 err = 0;
-
-       /* Setup timeout if Beacons are lost and roam is
-                off to report link down */
-       if (roamvar) {
-               bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
-                           sizeof(iovbuf));
-               err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-               if (unlikely(err)) {
-                       WL_ERR("bcn_timeout error (%d)\n", err);
-                       goto dongle_rom_out;
-               }
-       }
-       /* Enable/Disable built-in roaming to allow supplicant
-                to take care of roaming */
-       bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
-       err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-       if (unlikely(err)) {
-               WL_ERR("roam_off error (%d)\n", err);
-               goto dongle_rom_out;
-       }
-dongle_rom_out:
-       return err;
-}
-
-static s32 wl_dongle_eventmsg(struct net_device *ndev)
-{
-
-       s8 iovbuf[WL_EVENTING_MASK_LEN + 12];   /*  Room for "event_msgs" +
-                                                '\0' + bitvec  */
-       s8 eventmask[WL_EVENTING_MASK_LEN];
-       s32 err = 0;
-
-       /* Setup event_msgs */
-       bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
-                   sizeof(iovbuf));
-       err = wl_dev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
-       if (unlikely(err)) {
-               WL_ERR("Get event_msgs error (%d)\n", err);
-               goto dongle_eventmsg_out;
-       }
-       memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
-
-       setbit(eventmask, WLC_E_SET_SSID);
-       setbit(eventmask, WLC_E_PRUNE);
-       setbit(eventmask, WLC_E_AUTH);
-       setbit(eventmask, WLC_E_REASSOC);
-       setbit(eventmask, WLC_E_REASSOC_IND);
-       setbit(eventmask, WLC_E_DEAUTH_IND);
-       setbit(eventmask, WLC_E_DISASSOC_IND);
-       setbit(eventmask, WLC_E_DISASSOC);
-       setbit(eventmask, WLC_E_JOIN);
-       setbit(eventmask, WLC_E_ASSOC_IND);
-       setbit(eventmask, WLC_E_PSK_SUP);
-       setbit(eventmask, WLC_E_LINK);
-       setbit(eventmask, WLC_E_NDIS_LINK);
-       setbit(eventmask, WLC_E_MIC_ERROR);
-       setbit(eventmask, WLC_E_PMKID_CACHE);
-       setbit(eventmask, WLC_E_TXFAIL);
-       setbit(eventmask, WLC_E_JOIN_START);
-       setbit(eventmask, WLC_E_SCAN_COMPLETE);
-
-       bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
-                   sizeof(iovbuf));
-       err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
-       if (unlikely(err)) {
-               WL_ERR("Set event_msgs error (%d)\n", err);
-               goto dongle_eventmsg_out;
-       }
-
-dongle_eventmsg_out:
-       return err;
-}
-
-static s32
-wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
-                  s32 scan_unassoc_time)
-{
-       s32 err = 0;
-
-       err = wl_dev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
-                       sizeof(scan_assoc_time));
-       if (err) {
-               if (err == -EOPNOTSUPP) {
-                       WL_INFO("Scan assoc time is not supported\n");
-               } else {
-                       WL_ERR("Scan assoc time error (%d)\n", err);
-               }
-               goto dongle_scantime_out;
-       }
-       err = wl_dev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
-                       sizeof(scan_unassoc_time));
-       if (err) {
-               if (err == -EOPNOTSUPP) {
-                       WL_INFO("Scan unassoc time is not supported\n");
-               } else {
-                       WL_ERR("Scan unassoc time error (%d)\n", err);
-               }
-               goto dongle_scantime_out;
-       }
-
-dongle_scantime_out:
-       return err;
-}
-
-static s32
-wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol)
-{
-       s8 iovbuf[WL_EVENTING_MASK_LEN + 12];   /*  Room for "event_msgs" +
-                                                        '\0' + bitvec  */
+                                                        '\0' + bitvec  */
        s32 err = 0;
 
        /* Set ARP offload */
@@ -3656,26 +3711,28 @@ static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode)
        pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1);
 
        /* Parse packet filter id. */
-       pkt_filter.id = htod32(100);
+       pkt_filter.id = cpu_to_le32(100);
 
        /* Parse filter polarity. */
-       pkt_filter.negate_match = htod32(0);
+       pkt_filter.negate_match = cpu_to_le32(0);
 
        /* Parse filter type. */
-       pkt_filter.type = htod32(0);
+       pkt_filter.type = cpu_to_le32(0);
 
        /* Parse pattern filter offset. */
-       pkt_filter.u.pattern.offset = htod32(0);
+       pkt_filter.u.pattern.offset = cpu_to_le32(0);
 
        /* Parse pattern filter mask. */
-       mask_size = htod32(wl_pattern_atoh("0xff",
-                                          (char *)pkt_filterp->u.pattern.
-                                          mask_and_pattern));
+       mask_size = cpu_to_le32(wl_pattern_atoh("0xff",
+                                               (char *)pkt_filterp->u.pattern.
+                                               mask_and_pattern));
 
        /* Parse pattern filter pattern. */
-       pattern_size = htod32(wl_pattern_atoh("0x00",
-                                             (char *)&pkt_filterp->u.pattern.
-                                             mask_and_pattern[mask_size]));
+       pattern_size = cpu_to_le32(wl_pattern_atoh("0x00",
+                                                  (char *)&pkt_filterp->u.
+                                                  pattern.
+                                                  mask_and_pattern
+                                                  [mask_size]));
 
        if (mask_size != pattern_size) {
                WL_ERR("Mask and pattern not the same size\n");
@@ -3723,6 +3780,151 @@ dongle_filter_out:
 }
 #endif                         /* !EMBEDDED_PLATFORM */
 
+static s32 wl_dongle_eventmsg(struct net_device *ndev)
+{
+       s8 iovbuf[WL_EVENTING_MASK_LEN + 12];   /*  Room for "event_msgs" +
+                                                '\0' + bitvec  */
+       s8 eventmask[WL_EVENTING_MASK_LEN];
+       s32 err = 0;
+
+       /* Setup event_msgs */
+       bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
+                   sizeof(iovbuf));
+       err = wl_dev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
+       if (unlikely(err)) {
+               WL_ERR("Get event_msgs error (%d)\n", err);
+               goto dongle_eventmsg_out;
+       }
+       memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
+
+       setbit(eventmask, WLC_E_SET_SSID);
+       setbit(eventmask, WLC_E_ROAM);
+       setbit(eventmask, WLC_E_PRUNE);
+       setbit(eventmask, WLC_E_AUTH);
+       setbit(eventmask, WLC_E_REASSOC);
+       setbit(eventmask, WLC_E_REASSOC_IND);
+       setbit(eventmask, WLC_E_DEAUTH_IND);
+       setbit(eventmask, WLC_E_DISASSOC_IND);
+       setbit(eventmask, WLC_E_DISASSOC);
+       setbit(eventmask, WLC_E_JOIN);
+       setbit(eventmask, WLC_E_ASSOC_IND);
+       setbit(eventmask, WLC_E_PSK_SUP);
+       setbit(eventmask, WLC_E_LINK);
+       setbit(eventmask, WLC_E_NDIS_LINK);
+       setbit(eventmask, WLC_E_MIC_ERROR);
+       setbit(eventmask, WLC_E_PMKID_CACHE);
+       setbit(eventmask, WLC_E_TXFAIL);
+       setbit(eventmask, WLC_E_JOIN_START);
+       setbit(eventmask, WLC_E_SCAN_COMPLETE);
+
+       bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
+                   sizeof(iovbuf));
+       err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+       if (unlikely(err)) {
+               WL_ERR("Set event_msgs error (%d)\n", err);
+               goto dongle_eventmsg_out;
+       }
+
+dongle_eventmsg_out:
+       return err;
+}
+
+static s32
+wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
+{
+       s8 iovbuf[32];
+       s32 roamtrigger[2];
+       s32 roam_delta[2];
+       s32 err = 0;
+
+       /*
+        * Setup timeout if Beacons are lost and roam is
+        * off to report link down
+        */
+       if (roamvar) {
+               bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout,
+                       sizeof(bcn_timeout), iovbuf, sizeof(iovbuf));
+               err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+               if (unlikely(err)) {
+                       WL_ERR("bcn_timeout error (%d)\n", err);
+                       goto dongle_rom_out;
+               }
+       }
+
+       /*
+        * Enable/Disable built-in roaming to allow supplicant
+        * to take care of roaming
+        */
+       WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On");
+       bcm_mkiovar("roam_off", (char *)&roamvar,
+                               sizeof(roamvar), iovbuf, sizeof(iovbuf));
+       err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+       if (unlikely(err)) {
+               WL_ERR("roam_off error (%d)\n", err);
+               goto dongle_rom_out;
+       }
+
+       roamtrigger[0] = WL_ROAM_TRIGGER_LEVEL;
+       roamtrigger[1] = WLC_BAND_ALL;
+       err = wl_dev_ioctl(ndev, WLC_SET_ROAM_TRIGGER,
+                       (void *)roamtrigger, sizeof(roamtrigger));
+       if (unlikely(err)) {
+               WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
+               goto dongle_rom_out;
+       }
+
+       roam_delta[0] = WL_ROAM_DELTA;
+       roam_delta[1] = WLC_BAND_ALL;
+       err = wl_dev_ioctl(ndev, WLC_SET_ROAM_DELTA,
+                               (void *)roam_delta, sizeof(roam_delta));
+       if (unlikely(err)) {
+               WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err);
+               goto dongle_rom_out;
+       }
+
+dongle_rom_out:
+       return err;
+}
+
+static s32
+wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
+               s32 scan_unassoc_time, s32 scan_passive_time)
+{
+       s32 err = 0;
+
+       err = wl_dev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
+                       sizeof(scan_assoc_time));
+       if (err) {
+               if (err == -EOPNOTSUPP)
+                       WL_INFO("Scan assoc time is not supported\n");
+               else
+                       WL_ERR("Scan assoc time error (%d)\n", err);
+               goto dongle_scantime_out;
+       }
+       err = wl_dev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
+                       sizeof(scan_unassoc_time));
+       if (err) {
+               if (err == -EOPNOTSUPP)
+                       WL_INFO("Scan unassoc time is not supported\n");
+               else
+                       WL_ERR("Scan unassoc time error (%d)\n", err);
+               goto dongle_scantime_out;
+       }
+
+       err = wl_dev_ioctl(ndev, WLC_SET_SCAN_PASSIVE_TIME, &scan_passive_time,
+                       sizeof(scan_passive_time));
+       if (err) {
+               if (err == -EOPNOTSUPP)
+                       WL_INFO("Scan passive time is not supported\n");
+               else
+                       WL_ERR("Scan passive time error (%d)\n", err);
+               goto dongle_scantime_out;
+       }
+
+dongle_scantime_out:
+       return err;
+}
+
 s32 wl_config_dongle(struct wl_priv *wl, bool need_lock)
 {
 #ifndef DHD_SDALIGN
@@ -3751,20 +3953,22 @@ s32 wl_config_dongle(struct wl_priv *wl, bool need_lock)
        if (unlikely(err))
                goto default_conf_out;
        err = wl_dongle_glom(ndev, 0, DHD_SDALIGN);
-       if (unlikely(err))
-               goto default_conf_out;
-       err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3);
-       if (unlikely(err))
-               goto default_conf_out;
-       err = wl_dongle_eventmsg(ndev);
        if (unlikely(err))
                goto default_conf_out;
 
-       wl_dongle_scantime(ndev, 40, 80);
        wl_dongle_offload(ndev, 1, 0xf);
        wl_dongle_filter(ndev, 1);
-#endif                         /* !EMBEDDED_PLATFORM */
+#endif /* !EMBEDDED_PLATFORM */
+
+       wl_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
+                       WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
 
+       err = wl_dongle_eventmsg(ndev);
+       if (unlikely(err))
+               goto default_conf_out;
+       err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), WL_BEACON_TIMEOUT);
+       if (unlikely(err))
+               goto default_conf_out;
        err = wl_dongle_mode(ndev, wdev->iftype);
        if (unlikely(err && err != -EINPROGRESS))
                goto default_conf_out;
@@ -3967,18 +4171,6 @@ static bool wl_is_ibssmode(struct wl_priv *wl)
        return wl->conf->mode == WL_MODE_IBSS;
 }
 
-static bool wl_is_ibssstarter(struct wl_priv *wl)
-{
-       return wl->ibss_starter;
-}
-
-static void wl_rst_ie(struct wl_priv *wl)
-{
-       struct wl_ie *ie = wl_to_ie(wl);
-
-       ie->offset = 0;
-}
-
 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
 {
        struct wl_ie *ie = wl_to_ie(wl);
@@ -3996,58 +4188,22 @@ static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
        return err;
 }
 
-static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size)
-{
-       struct wl_ie *ie = wl_to_ie(wl);
-       s32 err = 0;
 
-       if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
-               WL_ERR("ei_stream crosses buffer boundary\n");
-               return -ENOSPC;
-       }
-       memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
-       ie->offset += ie_size;
-
-       return err;
-}
-
-static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size)
+static void wl_link_down(struct wl_priv *wl)
 {
-       struct wl_ie *ie = wl_to_ie(wl);
+       struct net_device *dev = NULL;
        s32 err = 0;
 
-       if (unlikely(ie->offset > dst_size)) {
-               WL_ERR("dst_size is not enough\n");
-               return -ENOSPC;
-       }
-       memcpy(dst, &ie->buf[0], ie->offset);
-
-       return err;
-}
-
-static u32 wl_get_ielen(struct wl_priv *wl)
-{
-       struct wl_ie *ie = wl_to_ie(wl);
-
-       return ie->offset;
-}
-
-static void wl_link_up(struct wl_priv *wl)
-{
-       wl->link_up = true;
-}
-
-static void wl_link_down(struct wl_priv *wl)
-{
-       struct wl_connect_info *conn_info = wl_to_conn(wl);
+       clear_bit(WL_STATUS_CONNECTED, &wl->status);
 
-       wl->link_up = false;
-       kfree(conn_info->req_ie);
-       conn_info->req_ie = NULL;
-       conn_info->req_ie_len = 0;
-       kfree(conn_info->resp_ie);
-       conn_info->resp_ie = NULL;
-       conn_info->resp_ie_len = 0;
+       if (wl->link_up) {
+               dev = wl_to_ndev(wl);
+               WL_INFO("Call WLC_DISASSOC to stop excess roaming\n ");
+               err = wl_dev_ioctl(dev, WLC_DISASSOC, NULL, 0);
+               if (unlikely(err))
+                       WL_ERR("WLC_DISASSOC failed (%d)\n", err);
+               wl->link_up = false;
+       }
 }
 
 static void wl_lock_eq(struct wl_priv *wl)