check_sdata_in_driver(sdata);
 
        trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
-       if (local->ops->sta_state)
+       if (local->ops->sta_state) {
                ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta,
                                            old_state, new_state);
+       } else if (old_state == IEEE80211_STA_AUTH &&
+                  new_state == IEEE80211_STA_ASSOC) {
+               ret = drv_sta_add(local, sdata, &sta->sta);
+               if (ret == 0)
+                       sta->uploaded = true;
+       } else if (old_state == IEEE80211_STA_ASSOC &&
+                  new_state == IEEE80211_STA_AUTH) {
+               drv_sta_remove(local, sdata, &sta->sta);
+       }
        trace_drv_return_int(local, ret);
        return ret;
 }
 
                if (sta->uploaded) {
                        enum ieee80211_sta_state state;
 
-                       drv_sta_remove(local, sta->sdata, &sta->sta);
-
                        state = sta->sta_state;
                        for (; state > IEEE80211_STA_NOTEXIST; state--)
                                WARN_ON(drv_sta_state(local, sdata, sta,
 
        }
 
        if (!err) {
-               sta->uploaded = true;
+               /*
+                * Drivers using legacy sta_add/sta_remove callbacks only
+                * get uploaded set to true after sta_add is called.
+                */
+               if (!local->ops->sta_add)
+                       sta->uploaded = true;
                return 0;
        }
 
 
        if (!sta->dummy || dummy_reinsert) {
                /* notify driver */
-               err = drv_sta_add(local, sdata, &sta->sta);
-               if (err) {
-                       if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
-                               goto out_err;
-                       printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to "
-                                         "driver (%d) - keeping it anyway.\n",
-                              sdata->name, sta->sta.addr, err);
-               } else {
-                       err = sta_info_insert_drv_state(local, sdata, sta);
-                       if (err)
-                               goto out_err;
-               }
+               err = sta_info_insert_drv_state(local, sdata, sta);
+               if (err)
+                       goto out_err;
        }
 
        if (!dummy_reinsert) {
        }
 
        if (sta->uploaded) {
-               drv_sta_remove(local, sdata, &sta->sta);
                ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE,
                                    IEEE80211_STA_NOTEXIST);
                WARN_ON_ONCE(ret != 0);
 
                if (sta->uploaded) {
                        enum ieee80211_sta_state state;
 
-                       WARN_ON(drv_sta_add(local, sta->sdata, &sta->sta));
-
                        for (state = IEEE80211_STA_NOTEXIST;
                             state < sta->sta_state - 1; state++)
                                WARN_ON(drv_sta_state(local, sta->sdata, sta,