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