if (!netif_running(dev))
                return -ENETDOWN;
 
-       /* XXX: get sta belonging to dev */
-       sta = sta_info_get(local, mac);
-       if (sta) {
-               sta_info_put(sta);
-               return -EEXIST;
-       }
-
        if (params->vlan) {
                sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 
                sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        sta = sta_info_add(local, dev, mac, GFP_KERNEL);
-       if (!sta)
-               return -ENOMEM;
+       if (IS_ERR(sta))
+               return PTR_ERR(sta);
 
        sta->dev = sdata->dev;
        if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN ||
 
        if (!sta) {
                struct ieee80211_sta_bss *bss;
                sta = sta_info_add(local, dev, ifsta->bssid, GFP_KERNEL);
-               if (!sta) {
+               if (IS_ERR(sta)) {
                        printk(KERN_DEBUG "%s: failed to add STA entry for the"
-                              " AP\n", dev->name);
+                              " AP (error %ld)\n", dev->name, PTR_ERR(sta));
                        return;
                }
                bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
               wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name);
 
        sta = sta_info_add(local, dev, addr, GFP_ATOMIC);
-       if (!sta)
+       if (IS_ERR(sta))
                return NULL;
 
        sta->flags |= WLAN_STA_AUTHORIZED;
 
        return -ENOENT;
 }
 
-struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
+/* must hold local->sta_lock */
+static struct sta_info *__sta_info_find(struct ieee80211_local *local,
+                                       u8 *addr)
 {
        struct sta_info *sta;
 
-       read_lock_bh(&local->sta_lock);
        sta = local->sta_hash[STA_HASH(addr)];
        while (sta) {
-               if (memcmp(sta->addr, addr, ETH_ALEN) == 0) {
-                       __sta_info_get(sta);
+               if (compare_ether_addr(sta->addr, addr) == 0)
                        break;
-               }
                sta = sta->hnext;
        }
+       return sta;
+}
+
+struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
+{
+       struct sta_info *sta;
+
+       read_lock_bh(&local->sta_lock);
+       sta = __sta_info_find(local, addr);
+       if (sta)
+               __sta_info_get(sta);
        read_unlock_bh(&local->sta_lock);
 
        return sta;
 EXPORT_SYMBOL(sta_info_put);
 
 
-struct sta_info * sta_info_add(struct ieee80211_local *local,
-                              struct net_device *dev, u8 *addr, gfp_t gfp)
+struct sta_info *sta_info_add(struct ieee80211_local *local,
+                             struct net_device *dev, u8 *addr, gfp_t gfp)
 {
        struct sta_info *sta;
        int i;
 
        sta = kzalloc(sizeof(*sta), gfp);
        if (!sta)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        kref_init(&sta->kref);
 
        if (!sta->rate_ctrl_priv) {
                rate_control_put(sta->rate_ctrl);
                kfree(sta);
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
        memcpy(sta->addr, addr, ETH_ALEN);
        }
        skb_queue_head_init(&sta->ps_tx_buf);
        skb_queue_head_init(&sta->tx_filtered);
-       __sta_info_get(sta);    /* sta used by caller, decremented by
-                                * sta_info_put() */
        write_lock_bh(&local->sta_lock);
+       /* mark sta as used (by caller) */
+       __sta_info_get(sta);
+       /* check if STA exists already */
+       if (__sta_info_find(local, addr)) {
+               write_unlock_bh(&local->sta_lock);
+               sta_info_put(sta);
+               return ERR_PTR(-EEXIST);
+       }
        list_add(&sta->list, &local->sta_list);
        local->num_sta++;
        sta_info_hash_add(local, sta);
 
 
 struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr);
 void sta_info_put(struct sta_info *sta);
-struct sta_info * sta_info_add(struct ieee80211_local *local,
-                              struct net_device *dev, u8 *addr, gfp_t gfp);
+struct sta_info *sta_info_add(struct ieee80211_local *local,
+                             struct net_device *dev, u8 *addr, gfp_t gfp);
 void sta_info_remove(struct sta_info *sta);
 void sta_info_free(struct sta_info *sta);
 void sta_info_init(struct ieee80211_local *local);