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);