return 0;
 }
 
+static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
+                                    struct cfg80211_bss *bss, bool assoc)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct sta_info *sta;
+       bool have_sta = false;
+       int err;
+
+       if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data))
+               return -EINVAL;
+
+       if (assoc) {
+               rcu_read_lock();
+               have_sta = sta_info_get(sdata, bss->bssid);
+               rcu_read_unlock();
+       }
+
+       if (!have_sta) {
+               sta = sta_info_alloc(sdata, bss->bssid, GFP_KERNEL);
+               if (!sta)
+                       return -ENOMEM;
+       }
+
+       mutex_lock(&local->mtx);
+       ieee80211_recalc_idle(sdata->local);
+       mutex_unlock(&local->mtx);
+
+       /* switch to the right channel */
+       local->oper_channel = bss->channel;
+       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+
+       if (!have_sta) {
+               /* set BSSID - if STA already there this will be set too */
+               memcpy(ifmgd->bssid, bss->bssid, ETH_ALEN);
+               ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+
+               if (assoc)
+                       sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
+
+               err = sta_info_insert(sta);
+               sta = NULL;
+               if (err) {
+                       printk(KERN_DEBUG
+                              "%s: failed to insert STA entry for the AP (error %d)\n",
+                              sdata->name, err);
+                       return err;
+               }
+       } else
+               WARN_ON_ONCE(compare_ether_addr(ifmgd->bssid, bss->bssid));
+
+       return 0;
+}
+
 /* config hooks */
 int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
                       struct cfg80211_auth_request *req)
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_mgd_auth_data *auth_data;
-       struct sta_info *sta;
        u16 auth_alg;
        int err;
 
        printk(KERN_DEBUG "%s: authenticate with %pM\n",
               sdata->name, req->bss->bssid);
 
-       mutex_lock(&local->mtx);
-       ieee80211_recalc_idle(sdata->local);
-       mutex_unlock(&local->mtx);
-
-       /* switch to the right channel */
-       local->oper_channel = req->bss->channel;
-       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-
-       /* set BSSID */
-       memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN);
-       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
-
-       /* add station entry */
-       sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL);
-       if (!sta) {
-               err = -ENOMEM;
-               goto err_clear;
-       }
-
-       err = sta_info_insert(sta);
-       if (err) {
-               printk(KERN_DEBUG
-                      "%s: failed to insert STA entry for the AP %pM (error %d)\n",
-                      sdata->name, req->bss->bssid, err);
+       err = ieee80211_prep_connection(sdata, req->bss, false);
+       if (err)
                goto err_clear;
-       }
 
        err = ieee80211_probe_auth(sdata);
        if (err) {
        struct ieee80211_bss *bss = (void *)req->bss->priv;
        struct ieee80211_mgd_assoc_data *assoc_data;
        struct ieee80211_supported_band *sband;
-       struct sta_info *sta;
        const u8 *ssidie;
        int i, err;
 
 
        ifmgd->assoc_data = assoc_data;
 
-       mutex_lock(&local->mtx);
-       ieee80211_recalc_idle(sdata->local);
-       mutex_unlock(&local->mtx);
-
-       /* switch to the right channel */
-       local->oper_channel = req->bss->channel;
-       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-
-       rcu_read_lock();
-       sta = sta_info_get(sdata, req->bss->bssid);
-       rcu_read_unlock();
-
-       if (!sta) {
-               /* set BSSID */
-               memcpy(ifmgd->bssid, req->bss->bssid, ETH_ALEN);
-               ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
-
-               sta = sta_info_alloc(sdata, req->bss->bssid, GFP_KERNEL);
-               if (!sta) {
-                       err = -ENOMEM;
-                       goto err_clear;
-               }
-
-               sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
-
-               err = sta_info_insert(sta);
-               sta = NULL;
-               if (err) {
-                       printk(KERN_DEBUG
-                              "%s: failed to insert STA entry for the AP (error %d)\n",
-                              sdata->name, err);
-                       goto err_clear;
-               }
-       } else
-               WARN_ON_ONCE(compare_ether_addr(ifmgd->bssid, req->bss->bssid));
+       err = ieee80211_prep_connection(sdata, req->bss, true);
+       if (err)
+               goto err_clear;
 
        if (!bss->dtim_period &&
            sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {