Add /sys/class/ieee80211/phyX/sta/* attributes.

Signed-off-by: Jiri Benc <[EMAIL PROTECTED]>

---

 net/d80211/Makefile              |    1 
 net/d80211/ieee80211.c           |    5 +
 net/d80211/ieee80211_i.h         |   14 ++
 net/d80211/ieee80211_proc.c      |    3 -
 net/d80211/ieee80211_sysfs_sta.c |  228 ++++++++++++++++++++++++++++++++++++++
 net/d80211/sta_info.c            |  114 +++++++++++++------
 net/d80211/sta_info.h            |   11 +-
 7 files changed, 331 insertions(+), 45 deletions(-)
 create mode 100644 net/d80211/ieee80211_sysfs_sta.c

ed88547db8f143b83cf336c93221400edc2b3d81
diff --git a/net/d80211/Makefile b/net/d80211/Makefile
index 66bfcff..7d1ec29 100644
--- a/net/d80211/Makefile
+++ b/net/d80211/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_D80211) += 80211.o rate_con
        ieee80211_dev.o \
        ieee80211_iface.o \
        ieee80211_sysfs.o \
+       ieee80211_sysfs_sta.o \
        michael.o \
        tkip.o \
        aes_ccm.o \
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 0c23607..15d43f8 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4188,7 +4188,9 @@ int ieee80211_register_hw(struct net_dev
 
        ieee80211_update_hw(dev, hw);   /* Don't care about the result. */
 
-       sta_info_start(local);
+       result = sta_info_start(local);
+       if (result < 0)
+               goto fail_sta_info;
 
        if (hw->fraglist)
                dev->features |= NETIF_F_FRAGLIST;
@@ -4237,6 +4239,7 @@ fail_if_sysfs:
        unregister_netdev(dev);
 fail_dev:
        sta_info_stop(local);
+fail_sta_info:
        ieee80211_dev_sysfs_del(local);
 fail_sysfs:
        ieee80211_dev_free_index(local);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 7c1b621..212d12f 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -344,9 +344,11 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
 
         spinlock_t generic_lock;
        /* Station data structures */
+       struct kset sta_kset;
        spinlock_t sta_lock; /* mutex for STA data structures */
        int num_sta; /* number of stations in sta_list */
        struct list_head sta_list;
+       struct list_head deleted_sta_list;
        struct sta_info *sta_hash[STA_HASH_SIZE];
        struct timer_list sta_cleanup;
 
@@ -511,6 +513,12 @@ #endif /* CONFIG_D80211_DEBUG_COUNTERS *
        int user_space_mlme;
 };
 
+struct sta_attribute {
+       struct attribute attr;
+       ssize_t (*show)(const struct sta_info *, char *buf);
+       ssize_t (*store)(struct sta_info *, const char *buf, size_t count);
+};
+
 
 /* ieee80211.c */
 void ieee80211_release_hw(struct ieee80211_local *local);
@@ -620,4 +628,10 @@ int ieee80211_sysfs_init(void);
 void ieee80211_sysfs_deinit(void);
 int ieee80211_sysfs_change_if_type(struct net_device *dev);
 
+/* ieee80211_sysfs_sta.c */
+int ieee80211_sta_kset_sysfs_register(struct ieee80211_local *local);
+void ieee80211_sta_kset_sysfs_unregister(struct ieee80211_local *local);
+int ieee80211_sta_sysfs_add(struct sta_info *sta);
+void ieee80211_sta_sysfs_remove(struct sta_info *sta);
+
 #endif /* IEEE80211_I_H */
diff --git a/net/d80211/ieee80211_proc.c b/net/d80211/ieee80211_proc.c
index 581b583..4bb3179 100644
--- a/net/d80211/ieee80211_proc.c
+++ b/net/d80211/ieee80211_proc.c
@@ -241,7 +241,6 @@ static int ieee80211_proc_sta_read(char 
        if (!sta || !sta->dev)
                return -1;
 
-       p += sprintf(p, "users=%d\n", atomic_read(&sta->users));
        p += sprintf(p, "aid=%d\n", sta->aid);
        p += sprintf(p, "flags=0x%x %s%s%s%s%s%s%s%s%s%s\n", sta->flags,
                     sta->flags & WLAN_STA_AUTH ? "[AUTH]" : "",
@@ -656,7 +655,6 @@ void ieee80211_proc_init_sta(struct ieee
                                       ieee80211_proc_sta_read, sta);
        if (entry) {
                entry->mode &= ~(S_IRWXG | S_IRWXO);
-               sta->proc_entry_added = 1;
        }
 }
 
@@ -668,7 +666,6 @@ void ieee80211_proc_deinit_sta(struct ie
        sprintf(buf, MACSTR, MAC2STR(sta->addr));
        if (local->proc_sta) {
                remove_proc_entry(buf, local->proc_sta);
-               sta->proc_entry_added = 0;
        }
 }
 
diff --git a/net/d80211/ieee80211_sysfs_sta.c b/net/d80211/ieee80211_sysfs_sta.c
new file mode 100644
index 0000000..07de564
--- /dev/null
+++ b/net/d80211/ieee80211_sysfs_sta.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2003-2005, Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include "ieee80211_i.h"
+#include "sta_info.h"
+
+static ssize_t sta_sysfs_show(struct kobject *, struct attribute *, char *);
+
+static struct sysfs_ops sta_ktype_ops = {
+       .show = sta_sysfs_show,
+};
+
+#define STA_SHOW(name, field, format_string)                           \
+static ssize_t show_sta_##name(const struct sta_info *sta, char *buf)  \
+{                                                                      \
+       return sprintf(buf, format_string, sta->field);                 \
+}
+#define STA_SHOW_D(name, field) STA_SHOW(name, field, "%d\n")
+#define STA_SHOW_U(name, field) STA_SHOW(name, field, "%u\n")
+#define STA_SHOW_LU(name, field) STA_SHOW(name, field, "%lu\n")
+#define STA_SHOW_S(name, field) STA_SHOW(name, field, "%s\n")
+
+#define STA_SHOW_RATE(name, field)                                     \
+static ssize_t show_sta_##name(const struct sta_info *sta, char *buf)  \
+{                                                                      \
+       struct ieee80211_local *local = sta->dev->ieee80211_ptr;        \
+       return sprintf(buf, "%d\n",                                     \
+                      (sta->field >= 0 &&                              \
+                       sta->field < local->num_curr_rates) ?           \
+                      local->curr_rates[sta->field].rate : -1);        \
+}
+
+#define __STA_ATTR(name)                                               \
+static struct sta_attribute sta_attr_##name =                          \
+       __ATTR(name, S_IRUSR, show_sta_##name, NULL)
+
+#define STA_ATTR(name, field, format)                                  \
+               STA_SHOW_##format(name, field)                          \
+               __STA_ATTR(name)
+
+STA_ATTR(aid, aid, D);
+STA_ATTR(key_idx_compression, key_idx_compression, D);
+STA_ATTR(dev, dev->name, S);
+STA_ATTR(vlan_id, vlan_id, D);
+STA_ATTR(rx_packets, rx_packets, LU);
+STA_ATTR(tx_packets, tx_packets, LU);
+STA_ATTR(rx_bytes, rx_bytes, LU);
+STA_ATTR(tx_bytes, tx_bytes, LU);
+STA_ATTR(rx_duplicates, num_duplicates, LU);
+STA_ATTR(rx_fragments, rx_fragments, LU);
+STA_ATTR(rx_dropped, rx_dropped, LU);
+STA_ATTR(tx_fragments, tx_fragments, LU);
+STA_ATTR(tx_filtered, tx_filtered_count, LU);
+STA_ATTR(txrate, txrate, RATE);
+STA_ATTR(last_txrate, last_txrate, RATE);
+STA_ATTR(tx_retry_failed, tx_retry_failed, LU);
+STA_ATTR(tx_retry_count, tx_retry_count, LU);
+STA_ATTR(last_rssi, last_rssi, D);
+STA_ATTR(channel_use, channel_use, D);
+STA_ATTR(wep_weak_iv_count, wep_weak_iv_count, D);
+
+static ssize_t show_sta_flags(const struct sta_info *sta, char *buf)
+{
+       return sprintf(buf, "%s%s%s%s%s%s%s%s%s%s",
+                      sta->flags & WLAN_STA_AUTH ? "AUTH\n" : "",
+                      sta->flags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
+                      sta->flags & WLAN_STA_PS ? "PS\n" : "",
+                      sta->flags & WLAN_STA_TIM ? "TIM\n" : "",
+                      sta->flags & WLAN_STA_PERM ? "PERM\n" : "",
+                      sta->flags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
+                      sta->flags & WLAN_STA_SHORT_PREAMBLE ?
+                      "SHORT PREAMBLE\n" : "",
+                      sta->flags & WLAN_STA_WME ? "WME\n" : "",
+                      sta->flags & WLAN_STA_WDS ? "WDS\n" : "",
+                      sta->flags & WLAN_STA_XR ? "XR\n" : "");
+}
+__STA_ATTR(flags);
+
+static ssize_t show_sta_num_ps_buf_frames(const struct sta_info *sta, char 
*buf)
+{
+       return sprintf(buf, "%u\n", skb_queue_len(&sta->ps_tx_buf));
+}
+__STA_ATTR(num_ps_buf_frames);
+
+static ssize_t show_sta_last_ack_rssi(const struct sta_info *sta, char *buf)
+{
+       return sprintf(buf, "%d %d %d\n", sta->last_ack_rssi[0],
+                      sta->last_ack_rssi[1], sta->last_ack_rssi[2]);
+}
+__STA_ATTR(last_ack_rssi);
+
+static ssize_t show_sta_last_ack_ms(const struct sta_info *sta, char *buf)
+{
+       return sprintf(buf, "%d\n", sta->last_ack ?
+                      jiffies_to_msecs(jiffies - sta->last_ack) : -1);
+}
+__STA_ATTR(last_ack_ms);
+
+static ssize_t show_sta_inactive_ms(const struct sta_info *sta, char *buf)
+{
+       return sprintf(buf, "%d\n", jiffies_to_msecs(jiffies - sta->last_rx));
+}
+__STA_ATTR(inactive_ms);
+
+static ssize_t show_sta_last_seq_ctrl(const struct sta_info *sta, char *buf)
+{
+       int i;
+       char *p = buf;
+
+       for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+               p += sprintf(p, "%x ", sta->last_seq_ctrl[i]);
+       p += sprintf(p, "\n");
+       return (p - buf);
+}
+__STA_ATTR(last_seq_ctrl);
+
+#ifdef CONFIG_D80211_DEBUG_COUNTERS
+static ssize_t show_sta_wme_rx_queue(const struct sta_info *sta, char *buf)
+{
+       int i;
+       char *p = buf;
+
+       for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+               p += sprintf(p, "%u ", sta->wme_rx_queue[i]);
+       p += sprintf(p, "\n");
+       return (p - buf);
+}
+__STA_ATTR(wme_rx_queue);
+
+static ssize_t show_sta_wme_tx_queue(const struct sta_info *sta, char *buf)
+{
+       int i;
+       char *p = buf;
+
+       for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+               p += sprintf(p, "%u ", sta->wme_tx_queue[i]);
+       p += sprintf(p, "\n");
+       return (p - buf);
+}
+__STA_ATTR(wme_tx_queue);
+#endif
+
+static struct attribute *sta_ktype_attrs[] = {
+       &sta_attr_aid.attr,
+       &sta_attr_key_idx_compression.attr,
+       &sta_attr_dev.attr,
+       &sta_attr_vlan_id.attr,
+       &sta_attr_rx_packets.attr,
+       &sta_attr_tx_packets.attr,
+       &sta_attr_rx_bytes.attr,
+       &sta_attr_tx_bytes.attr,
+       &sta_attr_rx_duplicates.attr,
+       &sta_attr_rx_fragments.attr,
+       &sta_attr_rx_dropped.attr,
+       &sta_attr_tx_fragments.attr,
+       &sta_attr_tx_filtered.attr,
+       &sta_attr_txrate.attr,
+       &sta_attr_last_txrate.attr,
+       &sta_attr_tx_retry_failed.attr,
+       &sta_attr_tx_retry_count.attr,
+       &sta_attr_last_rssi.attr,
+       &sta_attr_channel_use.attr,
+       &sta_attr_wep_weak_iv_count.attr,
+
+       &sta_attr_flags.attr,
+       &sta_attr_num_ps_buf_frames.attr,
+       &sta_attr_last_ack_rssi.attr,
+       &sta_attr_last_ack_ms.attr,
+       &sta_attr_inactive_ms.attr,
+       &sta_attr_last_seq_ctrl.attr,
+#ifdef CONFIG_D80211_DEBUG_COUNTERS
+       &sta_attr_wme_rx_queue.attr,
+       &sta_attr_wme_tx_queue.attr,
+#endif
+       NULL
+};
+
+static struct kobj_type sta_ktype = {
+       .release = sta_info_release,
+       .sysfs_ops = &sta_ktype_ops,
+       .default_attrs = sta_ktype_attrs,
+};
+
+static ssize_t sta_sysfs_show(struct kobject *kobj, struct attribute *attr,
+                             char *buf)
+{
+       struct sta_attribute *sta_attr;
+       struct sta_info *sta;
+
+       sta_attr = container_of(attr, struct sta_attribute, attr);
+       sta = container_of(kobj, struct sta_info, kobj);
+       return sta_attr->show(sta, buf);
+}
+
+int ieee80211_sta_kset_sysfs_register(struct ieee80211_local *local)
+{
+       int res;
+
+       res = kobject_set_name(&local->sta_kset.kobj, "sta");
+       if (res)
+               return res;
+       local->sta_kset.kobj.parent = &local->class_dev.kobj;
+       local->sta_kset.ktype = &sta_ktype;
+       return kset_register(&local->sta_kset);
+}
+
+void ieee80211_sta_kset_sysfs_unregister(struct ieee80211_local *local)
+{
+       kset_unregister(&local->sta_kset);
+}
+
+int ieee80211_sta_sysfs_add(struct sta_info *sta)
+{
+       return kobject_add(&sta->kobj);
+}
+
+void ieee80211_sta_sysfs_remove(struct sta_info *sta)
+{
+       kobject_del(&sta->kobj);
+}
diff --git a/net/d80211/sta_info.c b/net/d80211/sta_info.c
index 9565c29..bba4771 100644
--- a/net/d80211/sta_info.c
+++ b/net/d80211/sta_info.c
@@ -10,6 +10,7 @@ #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/kobject.h>
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/slab.h>
@@ -55,6 +56,10 @@ static void sta_info_hash_del(struct iee
                       "hash table\n", local->mdev->name, MAC2STR(sta->addr));
 }
 
+static inline struct sta_info *__sta_info_get(struct sta_info *sta)
+{
+       return kobject_get(&sta->kobj) ? sta : NULL;
+}
 
 struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr)
 {
@@ -64,7 +69,7 @@ struct sta_info * sta_info_get(struct ie
        sta = local->sta_hash[STA_HASH(addr)];
        while (sta) {
                if (memcmp(sta->addr, addr, ETH_ALEN) == 0) {
-                       atomic_inc(&sta->users);
+                       __sta_info_get(sta);
                        break;
                }
                sta = sta->hnext;
@@ -74,7 +79,6 @@ struct sta_info * sta_info_get(struct ie
        return sta;
 }
 
-
 int sta_info_min_txrate_get(struct ieee80211_local *local)
 {
        struct sta_info *sta;
@@ -100,10 +104,14 @@ int sta_info_min_txrate_get(struct ieee8
 
 void sta_info_put(struct ieee80211_local *local, struct sta_info *sta)
 {
-       struct sk_buff *skb;
+       kobject_put(&sta->kobj);
+}
 
-       if (!atomic_dec_and_test(&sta->users))
-               return;
+void sta_info_release(struct kobject *kobj)
+{
+       struct sta_info *sta = container_of(kobj, struct sta_info, kobj);
+       struct ieee80211_local *local = sta->local;
+       struct sk_buff *skb;
 
        /* free sta structure; it has already been removed from
         * hash table etc. external structures. Make sure that all
@@ -132,20 +140,27 @@ struct sta_info * sta_info_add(struct ie
 
        memset(sta, 0, sizeof(*sta));
 
+       if (kobject_set_name(&sta->kobj, MACSTR, MAC2STR(addr))) {
+               kfree(sta);
+               return NULL;
+       }
+       sta->kobj.kset = &local->sta_kset;
+       kobject_init(&sta->kobj);
+
        sta->rate_ctrl_priv = rate_control_alloc_sta(local);
        if (sta->rate_ctrl_priv == NULL) {
+               kobject_put(&sta->kobj);
                kfree(sta);
                return NULL;
        }
 
         memcpy(sta->addr, addr, ETH_ALEN);
+       sta->local = local;
         sta->dev = dev;
        skb_queue_head_init(&sta->ps_tx_buf);
        skb_queue_head_init(&sta->tx_filtered);
-       atomic_inc(&sta->users); /* sta in hashlist etc, decremented by
-                                 * sta_info_free() */
-       atomic_inc(&sta->users); /* sta used by caller, decremented by
-                                 * sta_info_put() */
+       __sta_info_get(sta);    /* sta used by caller, decremented by
+                                * sta_info_put() */
        spin_lock_bh(&local->sta_lock);
        list_add(&sta->list, &local->sta_list);
        local->num_sta++;
@@ -161,6 +176,8 @@ #ifdef CONFIG_D80211_VERBOSE_DEBUG
 #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
        if (!in_interrupt()) {
+               sta->sysfs_registered = 1;
+               ieee80211_sta_sysfs_add(sta);
                ieee80211_proc_init_sta(local, sta);
        } else {
                /* procfs entry adding might sleep, so schedule process context
@@ -172,6 +189,19 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
        return sta;
 }
 
+static void finish_sta_info_free(struct ieee80211_local *local,
+                                struct sta_info *sta)
+{
+#ifdef CONFIG_D80211_VERBOSE_DEBUG
+       printk(KERN_DEBUG "%s: Removed STA " MACSTR "\n",
+              local->mdev->name, MAC2STR(sta->addr));
+#endif /* CONFIG_D80211_VERBOSE_DEBUG */
+
+       ieee80211_proc_deinit_sta(local, sta);
+       ieee80211_sta_sysfs_remove(sta);
+
+       sta_info_put(local, sta);
+}
 
 void sta_info_free(struct ieee80211_local *local, struct sta_info *sta,
                   int locked)
@@ -227,23 +257,11 @@ void sta_info_free(struct ieee80211_loca
                sta->key_idx_compression = HW_KEY_IDX_INVALID;
        }
 
-#ifdef CONFIG_D80211_VERBOSE_DEBUG
-       printk(KERN_DEBUG "%s: Removed STA " MACSTR "\n",
-              local->mdev->name, MAC2STR(sta->addr));
-#endif /* CONFIG_D80211_VERBOSE_DEBUG */
-
-       ieee80211_proc_deinit_sta(local, sta);
-
-       if (atomic_read(&sta->users) != 1) {
-               /* This is OK, but printed for debugging. The station structure
-                * will be removed when the other user of the data calls
-                * sta_info_put(). */
-               printk(KERN_DEBUG "%s: STA " MACSTR " users count %d when "
-                      "removing it\n", local->mdev->name, MAC2STR(sta->addr),
-                      atomic_read(&sta->users));
-       }
-
-       sta_info_put(local, sta);
+       if (in_atomic()) {
+               list_add(&sta->list, &local->deleted_sta_list);
+               schedule_work(&local->sta_proc_add);
+       } else
+               finish_sta_info_free(local, sta);
 }
 
 
@@ -300,7 +318,7 @@ static void sta_info_cleanup(unsigned lo
        ptr = local->sta_list.next;
        while (ptr && ptr != &local->sta_list) {
                struct sta_info *sta = (struct sta_info *) ptr;
-               atomic_inc(&sta->users);
+               __sta_info_get(sta);
                sta_info_cleanup_expire_buffered(local, sta);
                sta_info_put(local, sta);
                ptr = ptr->next;
@@ -317,15 +335,27 @@ static void sta_info_proc_add_task(void 
        struct ieee80211_local *local = data;
        struct list_head *ptr;
        struct sta_info *sta;
-       int max_adds = 100;
 
-       while (max_adds > 0) {
-               sta = NULL;
+       while (1) {
+               spin_lock_bh(&local->sta_lock);
+               if (!list_empty(&local->deleted_sta_list)) {
+                       sta = list_entry(local->deleted_sta_list.next,
+                                        struct sta_info, list);
+                       list_del(local->deleted_sta_list.next);
+               } else
+                       sta = NULL;
+               spin_unlock_bh(&local->sta_lock);
+               if (!sta)
+                       break;
+               finish_sta_info_free(local, sta);
+       }
+
+       while (1) {
                spin_lock_bh(&local->sta_lock);
                list_for_each(ptr, &local->sta_list) {
                        sta = list_entry(ptr, struct sta_info, list);
-                       if (!sta->proc_entry_added) {
-                               atomic_inc(&sta->users);
+                       if (!sta->sysfs_registered) {
+                               __sta_info_get(sta);
                                break;
                        }
                        sta = NULL;
@@ -335,10 +365,10 @@ static void sta_info_proc_add_task(void 
                if (!sta)
                        break;
 
+               sta->sysfs_registered = 1;
+               ieee80211_sta_sysfs_add(sta);
                ieee80211_proc_init_sta(local, sta);
-               atomic_dec(&sta->users);
-
-               max_adds--;
+               sta_info_put(local, sta);
        }
 }
 
@@ -347,6 +377,7 @@ void sta_info_init(struct ieee80211_loca
 {
        spin_lock_init(&local->sta_lock);
        INIT_LIST_HEAD(&local->sta_list);
+       INIT_LIST_HEAD(&local->deleted_sta_list);
 
        init_timer(&local->sta_cleanup);
        local->sta_cleanup.expires = jiffies + STA_INFO_CLEANUP_INTERVAL;
@@ -356,9 +387,15 @@ void sta_info_init(struct ieee80211_loca
        INIT_WORK(&local->sta_proc_add, sta_info_proc_add_task, local);
 }
 
-void sta_info_start(struct ieee80211_local *local)
+int sta_info_start(struct ieee80211_local *local)
 {
+       int res;
+
+       res = ieee80211_sta_kset_sysfs_register(local);
+       if (res)
+               return res;
        add_timer(&local->sta_cleanup);
+       return 0;
 }
 
 void sta_info_stop(struct ieee80211_local *local)
@@ -371,8 +408,13 @@ void sta_info_stop(struct ieee80211_loca
        while (ptr && ptr != &local->sta_list) {
                struct sta_info *sta = (struct sta_info *) ptr;
                ptr = ptr->next;
+               /* sta_info_free must be called with 0 as the last
+                * parameter to ensure all sysfs sta entries are
+                * unregistered. We don't need locking at this
+                * point. */
                sta_info_free(local, sta, 0);
        }
+       ieee80211_sta_kset_sysfs_unregister(local);
 }
 
 
diff --git a/net/d80211/sta_info.h b/net/d80211/sta_info.h
index fddc80e..ddfe50e 100644
--- a/net/d80211/sta_info.h
+++ b/net/d80211/sta_info.h
@@ -32,8 +32,10 @@ #define WLAN_STA_WDS BIT(27)
 
 struct sta_info {
        struct list_head list;
+       struct kobject kobj;
        struct sta_info *hnext; /* next entry in hash table list */
-       atomic_t users; /* number of users (do not remove if > 0) */
+
+       struct ieee80211_local *local;
 
        u8 addr[ETH_ALEN];
        u16 aid; /* STA's unique AID (1..2007), 0 = not yet assigned */
@@ -92,7 +94,7 @@ struct sta_info {
                                  * filtering; used only if sta->key is not
                                  * set */
 
-       int proc_entry_added:1;
+       int sysfs_registered:1;
        int assoc_ap:1; /* whether this is an AP that we are associated with
                         * as a client */
 
@@ -130,8 +132,6 @@ #define STA_TX_BUFFER_EXPIRE (10 * HZ)
  */
 #define STA_INFO_CLEANUP_INTERVAL (10 * HZ)
 
-struct ieee80211_local;
-
 struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr);
 int sta_info_min_txrate_get(struct ieee80211_local *local);
 void sta_info_put(struct ieee80211_local *local, struct sta_info *sta);
@@ -139,8 +139,9 @@ struct sta_info * sta_info_add(struct ie
                               struct net_device *dev, u8 *addr);
 void sta_info_free(struct ieee80211_local *local, struct sta_info *sta,
                   int locked);
+void sta_info_release(struct kobject *kobj);
 void sta_info_init(struct ieee80211_local *local);
-void sta_info_start(struct ieee80211_local *local);
+int sta_info_start(struct ieee80211_local *local);
 void sta_info_stop(struct ieee80211_local *local);
 void sta_info_remove_aid_ptr(struct sta_info *sta);
 void sta_info_flush(struct ieee80211_local *local, struct net_device *dev);
-- 
1.3.0

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to