2007-03-23 20:43:26

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 0/19] d80211: pull request

Sorry again for the long delay. I reviewed most of patches sent in last
three weeks, with one big exception of radiotap support (that's my task for
the next week :-)).

Please note that I renamed my tree to mac80211.git.

John, please pull from
git://git.kernel.org/pub/scm/linux/kernel/git/jbenc/mac80211.git master
to obtain following patches:

Hong Liu:
mac80211: fix wrong keyidx will change default key
mac80211: fix passing wrong pointer to ieee80211_dump_frame

Ivo van Doorn:
mac80211: Prevent unregistering of unregistered hw
mac80211: Add software sequence support

Jiri Benc:
mac80211: drop packets from nonexisting interfaces in PS mode
mac80211: remove useless callbacks from wmaster
mac80211: fix rtnl locking in ieee80211_register_hw

Johannes Berg:
mac80211: fix remaining sparse warnings

[email protected]:
mac80211: move PHY things to debugfs
mac80211: move sta dir to debugfs
mac80211: move per-netdev and key stuff to debugfs
mac80211 debugfs Kconfig

Michael Buesch:
mac80211: Fix pkt_type annotations
mac80211: Properly kill tasklets before shutdown

Michael Wu:
mac80211: Remove curr_rates and fix related concurrency issues
mac80211: Remove tx_timeout callback
mac80211: Set carrier status for STA interfaces
mac80211: Stop virtual interfaces during scan
mac80211: switch STA interfaces to PS mode during scan

include/net/mac80211.h | 7
net/mac80211/Kconfig | 9
net/mac80211/Makefile | 3
net/mac80211/debugfs.c | 436 ++++++++++++++++++++++
net/mac80211/debugfs.h | 16 +
net/mac80211/debugfs_key.c | 253 +++++++++++++
net/mac80211/debugfs_key.h | 34 ++
net/mac80211/debugfs_netdev.c | 440 ++++++++++++++++++++++
net/mac80211/debugfs_netdev.h | 30 ++
net/mac80211/debugfs_sta.c | 242 ++++++++++++
net/mac80211/debugfs_sta.h | 12 +
net/mac80211/ieee80211.c | 298 +++++++--------
net/mac80211/ieee80211_i.h | 162 +++++++-
net/mac80211/ieee80211_iface.c | 25 -
net/mac80211/ieee80211_ioctl.c | 129 +++---
net/mac80211/ieee80211_key.h | 21 +
net/mac80211/ieee80211_rate.h | 47 +-
net/mac80211/ieee80211_scan.c | 2
net/mac80211/ieee80211_sta.c | 138 +++++--
net/mac80211/ieee80211_sysfs.c | 718 ------------------------------------
net/mac80211/ieee80211_sysfs.h | 12 -
net/mac80211/ieee80211_sysfs_sta.c | 438 ----------------------
net/mac80211/rc80211_simple.c | 139 ++++---
net/mac80211/sta_info.c | 82 ++--
net/mac80211/sta_info.h | 18 +
25 files changed, 2102 insertions(+), 1609 deletions(-)

--
Jiri Benc
SUSE Labs


2007-03-23 20:43:39

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 12/19] mac80211 debugfs Kconfig

From: [email protected] <[email protected]>

This patch adds a configuration option to mac80211 that lets you
enable or disable the debugfs internal state export.

I intentionally made this option not depend on MAC80211_DEBUG
because that option always generates debug messages in the kernel
log; this way you can see the internal state without seeing any
debugging message.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/Kconfig | 9 +++++++++
net/mac80211/Makefile | 2 +-
net/mac80211/debugfs.h | 2 +-
net/mac80211/debugfs_key.h | 2 +-
net/mac80211/debugfs_netdev.h | 2 +-
net/mac80211/debugfs_sta.h | 2 +-
net/mac80211/ieee80211_i.h | 4 ++--
net/mac80211/ieee80211_key.h | 2 +-
net/mac80211/ieee80211_rate.h | 4 ++--
net/mac80211/rc80211_simple.c | 6 +++---
net/mac80211/sta_info.h | 2 +-
11 files changed, 23 insertions(+), 14 deletions(-)

7eb09815b60aba14a6e3e4bafb5841f13ae75c0f
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index a4f282b..ff2eca3 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -18,6 +18,15 @@ config MAC80211_LEDS
This option enables a few LED triggers for different
packet receive/transmit events.

+config MAC80211_DEBUGFS
+ bool "Export mac80211 internals in DebugFS"
+ depends on MAC80211 && DEBUG_FS
+ ---help---
+ Select this to see extensive information about
+ the internal state of mac80211 in debugfs.
+
+ Say N unless you know you need this.
+
config MAC80211_DEBUG
bool "Enable debugging output"
depends on MAC80211
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 15eff76..37f6f4c 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -1,7 +1,7 @@
obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o

mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
-mac80211-objs-$(CONFIG_DEBUG_FS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o
+mac80211-objs-$(CONFIG_MAC80211_DEBUGFS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o

mac80211-objs := \
ieee80211.o \
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h
index e2c7cbb..dd25419 100644
--- a/net/mac80211/debugfs.h
+++ b/net/mac80211/debugfs.h
@@ -1,7 +1,7 @@
#ifndef __MAC80211_DEBUGFS_H
#define __MAC80211_DEBUGFS_H

-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
extern void debugfs_hw_add(struct ieee80211_local *local);
extern void debugfs_hw_del(struct ieee80211_local *local);
extern int mac80211_open_file_generic(struct inode *inode, struct file *file);
diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h
index 5de3546..aecfce3 100644
--- a/net/mac80211/debugfs_key.h
+++ b/net/mac80211/debugfs_key.h
@@ -1,7 +1,7 @@
#ifndef __MAC80211_DEBUGFS_KEY_H
#define __MAC80211_DEBUGFS_KEY_H

-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
void ieee80211_debugfs_key_add(struct ieee80211_local *local,
struct ieee80211_key *key);
void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h
index 308a52a..96ebbdd 100644
--- a/net/mac80211/debugfs_netdev.h
+++ b/net/mac80211/debugfs_netdev.h
@@ -3,7 +3,7 @@
#ifndef __IEEE80211_SYSFS_H
#define __IEEE80211_SYSFS_H

-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/debugfs_sta.h b/net/mac80211/debugfs_sta.h
index 5a60cd5..574a1cd 100644
--- a/net/mac80211/debugfs_sta.h
+++ b/net/mac80211/debugfs_sta.h
@@ -1,7 +1,7 @@
#ifndef __MAC80211_DEBUGFS_STA_H
#define __MAC80211_DEBUGFS_STA_H

-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
void ieee80211_sta_debugfs_add(struct sta_info *sta);
void ieee80211_sta_debugfs_remove(struct sta_info *sta);
#else
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index baf927f..3c10152 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -337,7 +337,7 @@ #define NUM_DEFAULT_KEYS 4
int channel_use;
int channel_use_raw;

-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
struct dentry *debugfsdir;
union {
struct {
@@ -596,7 +596,7 @@ #endif /* CONFIG_MAC80211_DEBUG_COUNTERS

int user_space_mlme;

-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
struct local_debugfsdentries {
struct dentry *channel;
struct dentry *frequency;
diff --git a/net/mac80211/ieee80211_key.h b/net/mac80211/ieee80211_key.h
index cde2974..c333849 100644
--- a/net/mac80211/ieee80211_key.h
+++ b/net/mac80211/ieee80211_key.h
@@ -83,7 +83,7 @@ #endif
* (used only for broadcast keys). */
s8 keyidx; /* WEP key index */

-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
struct {
struct dentry *stalink;
struct dentry *dir;
diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h
index c0c32ae..f021a02 100644
--- a/net/mac80211/ieee80211_rate.h
+++ b/net/mac80211/ieee80211_rate.h
@@ -124,7 +124,7 @@ static inline void rate_control_free_sta

static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
{
-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
struct rate_control_ref *ref = sta->rate_ctrl;
if (sta->debugfs.dir && ref->ops->add_sta_debugfs)
ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
@@ -134,7 +134,7 @@ #endif

static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
{
-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
struct rate_control_ref *ref = sta->rate_ctrl;
if (ref->ops->remove_sta_debugfs)
ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
index 9702eae..2048cfd 100644
--- a/net/mac80211/rc80211_simple.c
+++ b/net/mac80211/rc80211_simple.c
@@ -123,7 +123,7 @@ struct sta_rate_control {
u32 tx_avg_rate_sum;
u32 tx_avg_rate_num;

-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
struct dentry *tx_avg_rate_sum_dentry;
struct dentry *tx_avg_rate_num_dentry;
#endif
@@ -333,7 +333,7 @@ static void rate_control_simple_free_sta
kfree(rctrl);
}

-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS

static int open_file_generic(struct inode *inode, struct file *file)
{
@@ -406,7 +406,7 @@ static struct rate_control_ops rate_cont
.free = rate_control_simple_free,
.alloc_sta = rate_control_simple_alloc_sta,
.free_sta = rate_control_simple_free_sta,
-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
.add_sta_debugfs = rate_control_simple_add_sta_debugfs,
.remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
#endif
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 5213d2c..ed7ca59 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -115,7 +115,7 @@ #endif /* CONFIG_MAC80211_DEBUG_COUNTERS

u16 listen_interval;

-#ifdef CONFIG_DEBUG_FS
+#ifdef CONFIG_MAC80211_DEBUGFS
struct sta_info_debugfsdentries {
struct dentry *dir;
struct dentry *flags;
--
1.3.0


2007-03-23 20:43:38

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 11/19] mac80211: move per-netdev and key stuff to debugfs

From: [email protected] <[email protected]>

This patch moves the remaining sysfs stuff from mac80211 into debugfs.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/Makefile | 4
net/mac80211/debugfs.c | 3
net/mac80211/debugfs_key.c | 253 +++++++++++++++++++++++
net/mac80211/debugfs_key.h | 34 +++
net/mac80211/debugfs_netdev.c | 440 ++++++++++++++++++++++++++++++++++++++++
net/mac80211/debugfs_netdev.h | 30 +++
net/mac80211/ieee80211.c | 49 ++--
net/mac80211/ieee80211_i.h | 65 ++++++
net/mac80211/ieee80211_iface.c | 25 +-
net/mac80211/ieee80211_ioctl.c | 31 +--
net/mac80211/ieee80211_key.h | 21 ++
net/mac80211/ieee80211_sysfs.c | 344 -------------------------------
net/mac80211/ieee80211_sysfs.h | 10 -
net/mac80211/key_sysfs.c | 217 --------------------
net/mac80211/key_sysfs.h | 12 -
net/mac80211/sta_info.c | 6 -
16 files changed, 891 insertions(+), 653 deletions(-)
create mode 100644 net/mac80211/debugfs_key.c
create mode 100644 net/mac80211/debugfs_key.h
create mode 100644 net/mac80211/debugfs_netdev.c
create mode 100644 net/mac80211/debugfs_netdev.h
delete mode 100644 net/mac80211/ieee80211_sysfs.c
delete mode 100644 net/mac80211/ieee80211_sysfs.h
delete mode 100644 net/mac80211/key_sysfs.c
delete mode 100644 net/mac80211/key_sysfs.h

a31d8e7a6e4789185ad35851a1f554b7ed29c439
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 8c00960..15eff76 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -1,7 +1,7 @@
obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o

mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
-mac80211-objs-$(CONFIG_DEBUG_FS) += debugfs.o debugfs_sta.o
+mac80211-objs-$(CONFIG_DEBUG_FS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o

mac80211-objs := \
ieee80211.o \
@@ -13,13 +13,11 @@ mac80211-objs := \
ieee80211_sta.o \
ieee80211_iface.o \
ieee80211_rate.o \
- ieee80211_sysfs.o \
michael.o \
tkip.o \
aes_ccm.o \
wme.o \
ieee80211_cfg.o \
- key_sysfs.o \
$(mac80211-objs-y)

ifeq ($(CONFIG_NET_SCHED),)
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index d78c8a6..419da6a 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -303,6 +303,7 @@ void debugfs_hw_add(struct ieee80211_loc
return;

local->debugfs.stations = debugfs_create_dir("stations", phyd);
+ local->debugfs.keys = debugfs_create_dir("keys", phyd);

DEBUGFS_ADD(channel);
DEBUGFS_ADD(frequency);
@@ -430,4 +431,6 @@ #endif
local->debugfs.statistics = NULL;
debugfs_remove(local->debugfs.stations);
local->debugfs.stations = NULL;
+ debugfs_remove(local->debugfs.keys);
+ local->debugfs.keys = NULL;
}
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
new file mode 100644
index 0000000..e90d2cf
--- /dev/null
+++ b/net/mac80211/debugfs_key.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2003-2005 Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <[email protected]>
+ * Copyright 2007 Johannes Berg <[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 "ieee80211_key.h"
+#include "debugfs.h"
+#include "debugfs_key.h"
+
+#define KEY_READ(name, buflen, format_string) \
+static ssize_t key_##name##_read(struct file *file, \
+ char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+{ \
+ char buf[buflen]; \
+ struct ieee80211_key *key = file->private_data; \
+ int res = scnprintf(buf, buflen, format_string, key->name); \
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+}
+#define KEY_READ_D(name) KEY_READ(name, 20, "%d\n")
+
+#define KEY_OPS(name) \
+static const struct file_operations key_ ##name## _ops = { \
+ .read = key_##name##_read, \
+ .open = mac80211_open_file_generic, \
+}
+
+#define KEY_FILE(name, format) \
+ KEY_READ_##format(name) \
+ KEY_OPS(name)
+
+KEY_FILE(keylen, D);
+KEY_FILE(force_sw_encrypt, D);
+KEY_FILE(keyidx, D);
+KEY_FILE(hw_key_idx, D);
+KEY_FILE(tx_rx_count, D);
+
+static ssize_t key_algorithm_read(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char *alg;
+ struct ieee80211_key *key = file->private_data;
+
+ switch (key->alg) {
+ case ALG_WEP:
+ alg = "WEP\n";
+ break;
+ case ALG_TKIP:
+ alg = "TKIP\n";
+ break;
+ case ALG_CCMP:
+ alg = "CCMP\n";
+ break;
+ default:
+ return 0;
+ }
+ return simple_read_from_buffer(userbuf, count, ppos, alg, strlen(alg));
+}
+KEY_OPS(algorithm);
+
+static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ const u8 *tpn;
+ char buf[20];
+ int len;
+ struct ieee80211_key *key = file->private_data;
+
+ switch (key->alg) {
+ case ALG_WEP:
+ len = scnprintf(buf, sizeof(buf), "\n");
+ case ALG_TKIP:
+ len = scnprintf(buf, sizeof(buf), "%08x %04x\n",
+ key->u.tkip.iv32,
+ key->u.tkip.iv16);
+ case ALG_CCMP:
+ tpn = key->u.ccmp.tx_pn;
+ len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
+ tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
+ default:
+ return 0;
+ }
+ return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(tx_spec);
+
+static ssize_t key_rx_spec_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_key *key = file->private_data;
+ char buf[14*NUM_RX_DATA_QUEUES+1], *p = buf;
+ int i, len;
+ const u8 *rpn;
+
+ switch (key->alg) {
+ case ALG_WEP:
+ len = scnprintf(buf, sizeof(buf), "\n");
+ case ALG_TKIP:
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ p += scnprintf(p, sizeof(buf)+buf-p,
+ "%08x %04x\n",
+ key->u.tkip.iv32_rx[i],
+ key->u.tkip.iv16_rx[i]);
+ len = p - buf;
+ case ALG_CCMP:
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
+ rpn = key->u.ccmp.rx_pn[i];
+ p += scnprintf(p, sizeof(buf)+buf-p,
+ "%02x%02x%02x%02x%02x%02x\n",
+ rpn[0], rpn[1], rpn[2],
+ rpn[3], rpn[4], rpn[5]);
+ }
+ len = p - buf;
+ default:
+ return 0;
+ }
+ return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(rx_spec);
+
+static ssize_t key_replays_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_key *key = file->private_data;
+ char buf[20];
+ int len;
+
+ if (key->alg != ALG_CCMP)
+ return 0;
+ len = scnprintf(buf, sizeof(buf), "%u\n", key->u.ccmp.replays);
+ return simple_read_from_buffer(userbuf, count, ppos, buf, len);
+}
+KEY_OPS(replays);
+
+static ssize_t key_key_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_key *key = file->private_data;
+ int i, res, bufsize = 2*key->keylen+2;
+ char *buf = kmalloc(bufsize, GFP_KERNEL);
+ char *p = buf;
+
+ for (i = 0; i < key->keylen; i++)
+ p += scnprintf(p, bufsize+buf-p, "%02x", key->key[i]);
+ p += scnprintf(p, bufsize+buf-p, "\n");
+ res = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+ kfree(buf);
+ return res;
+}
+KEY_OPS(key);
+
+#define DEBUGFS_ADD(name) \
+ key->debugfs.name = debugfs_create_file(#name, 0400,\
+ key->debugfs.dir, key, &key_##name##_ops);
+
+void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+ struct ieee80211_key *key)
+{
+ char buf[20];
+
+ if (!local->debugfs.keys)
+ return;
+
+ sprintf(buf, "%d", key->keyidx);
+ key->debugfs.dir = debugfs_create_dir(buf,
+ local->debugfs.keys);
+
+ if (!key->debugfs.dir)
+ return;
+
+ DEBUGFS_ADD(keylen);
+ DEBUGFS_ADD(force_sw_encrypt);
+ DEBUGFS_ADD(keyidx);
+ DEBUGFS_ADD(hw_key_idx);
+ DEBUGFS_ADD(tx_rx_count);
+ DEBUGFS_ADD(algorithm);
+ DEBUGFS_ADD(tx_spec);
+ DEBUGFS_ADD(rx_spec);
+ DEBUGFS_ADD(replays);
+ DEBUGFS_ADD(key);
+};
+
+#define DEBUGFS_DEL(name) \
+ debugfs_remove(key->debugfs.name); key->debugfs.name = NULL;
+
+void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
+{
+ if (!key)
+ return;
+
+ DEBUGFS_DEL(keylen);
+ DEBUGFS_DEL(force_sw_encrypt);
+ DEBUGFS_DEL(keyidx);
+ DEBUGFS_DEL(hw_key_idx);
+ DEBUGFS_DEL(tx_rx_count);
+ DEBUGFS_DEL(algorithm);
+ DEBUGFS_DEL(tx_spec);
+ DEBUGFS_DEL(rx_spec);
+ DEBUGFS_DEL(replays);
+ DEBUGFS_DEL(key);
+
+ debugfs_remove(key->debugfs.stalink);
+ key->debugfs.stalink = NULL;
+ debugfs_remove(key->debugfs.dir);
+ key->debugfs.dir = NULL;
+}
+void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
+{
+ char buf[50];
+
+ if (!sdata->debugfsdir)
+ return;
+
+ sprintf(buf, "../keys/%d", sdata->default_key->keyidx);
+ sdata->debugfs.default_key =
+ debugfs_create_symlink("default_key", sdata->debugfsdir, buf);
+}
+void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
+{
+ if (!sdata)
+ return;
+
+ debugfs_remove(sdata->debugfs.default_key);
+ sdata->debugfs.default_key = NULL;
+}
+void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
+ struct sta_info *sta)
+{
+ char buf[50];
+
+ if (!key->debugfs.dir)
+ return;
+
+ sprintf(buf, "../sta/" MAC_FMT, MAC_ARG(sta->addr));
+ key->debugfs.stalink =
+ debugfs_create_symlink("station", key->debugfs.dir, buf);
+}
+
+void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+ struct sta_info *sta)
+{
+ debugfs_remove(key->debugfs.stalink);
+ key->debugfs.stalink = NULL;
+}
diff --git a/net/mac80211/debugfs_key.h b/net/mac80211/debugfs_key.h
new file mode 100644
index 0000000..5de3546
--- /dev/null
+++ b/net/mac80211/debugfs_key.h
@@ -0,0 +1,34 @@
+#ifndef __MAC80211_DEBUGFS_KEY_H
+#define __MAC80211_DEBUGFS_KEY_H
+
+#ifdef CONFIG_DEBUG_FS
+void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+ struct ieee80211_key *key);
+void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
+void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
+ struct sta_info *sta);
+void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+ struct sta_info *sta);
+#else
+static inline void ieee80211_debugfs_key_add(struct ieee80211_local *local,
+ struct ieee80211_key *key)
+{}
+static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
+{}
+static inline void ieee80211_debugfs_key_add_default(
+ struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_key_remove_default(
+ struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_key_sta_link(
+ struct ieee80211_key *key, struct sta_info *sta)
+{}
+static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
+ struct sta_info *sta)
+{}
+#endif
+
+#endif /* __MAC80211_DEBUGFS_KEY_H */
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
new file mode 100644
index 0000000..7b713fb
--- /dev/null
+++ b/net/mac80211/debugfs_netdev.c
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2006 Jiri Benc <[email protected]>
+ * Copyright 2007 Johannes Berg <[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/kernel.h>
+#include <linux/device.h>
+#include <linux/if.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/notifier.h>
+#include <net/mac80211.h>
+#include <net/cfg80211.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "debugfs.h"
+#include "debugfs_netdev.h"
+
+static ssize_t ieee80211_if_read(
+ struct ieee80211_sub_if_data *sdata,
+ char __user *userbuf,
+ size_t count, loff_t *ppos,
+ ssize_t (*format)(const struct ieee80211_sub_if_data *, char *, int))
+{
+ char buf[70];
+ ssize_t ret = -EINVAL;
+
+ read_lock(&dev_base_lock);
+ if (sdata->dev->reg_state == NETREG_REGISTERED) {
+ ret = (*format)(sdata, buf, sizeof(buf));
+ ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
+ }
+ read_unlock(&dev_base_lock);
+ return ret;
+}
+
+#define IEEE80211_IF_FMT(name, field, format_string) \
+static ssize_t ieee80211_if_fmt_##name( \
+ const struct ieee80211_sub_if_data *sdata, char *buf, \
+ int buflen) \
+{ \
+ return scnprintf(buf, buflen, format_string, sdata->field); \
+}
+#define IEEE80211_IF_FMT_DEC(name, field) \
+ IEEE80211_IF_FMT(name, field, "%d\n")
+#define IEEE80211_IF_FMT_HEX(name, field) \
+ IEEE80211_IF_FMT(name, field, "%#x\n")
+#define IEEE80211_IF_FMT_SIZE(name, field) \
+ IEEE80211_IF_FMT(name, field, "%zd\n")
+
+#define IEEE80211_IF_FMT_ATOMIC(name, field) \
+static ssize_t ieee80211_if_fmt_##name( \
+ const struct ieee80211_sub_if_data *sdata, \
+ char *buf, int buflen) \
+{ \
+ return scnprintf(buf, buflen, "%d\n", atomic_read(&sdata->field));\
+}
+
+#define IEEE80211_IF_FMT_MAC(name, field) \
+static ssize_t ieee80211_if_fmt_##name( \
+ const struct ieee80211_sub_if_data *sdata, char *buf, \
+ int buflen) \
+{ \
+ return scnprintf(buf, buflen, MAC_FMT "\n", MAC_ARG(sdata->field));\
+}
+
+#define __IEEE80211_IF_FILE(name) \
+static ssize_t ieee80211_if_read_##name(struct file *file, \
+ char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+{ \
+ return ieee80211_if_read(file->private_data, \
+ userbuf, count, ppos, \
+ ieee80211_if_fmt_##name); \
+} \
+static const struct file_operations name##_ops = { \
+ .read = ieee80211_if_read_##name, \
+ .open = mac80211_open_file_generic, \
+}
+
+#define IEEE80211_IF_FILE(name, field, format) \
+ IEEE80211_IF_FMT_##format(name, field) \
+ __IEEE80211_IF_FILE(name)
+
+/* common attributes */
+IEEE80211_IF_FILE(channel_use, channel_use, DEC);
+IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
+IEEE80211_IF_FILE(eapol, eapol, DEC);
+IEEE80211_IF_FILE(ieee8021_x, ieee802_1x, DEC);
+
+/* STA/IBSS attributes */
+IEEE80211_IF_FILE(state, u.sta.state, DEC);
+IEEE80211_IF_FILE(bssid, u.sta.bssid, MAC);
+IEEE80211_IF_FILE(prev_bssid, u.sta.prev_bssid, MAC);
+IEEE80211_IF_FILE(ssid_len, u.sta.ssid_len, SIZE);
+IEEE80211_IF_FILE(aid, u.sta.aid, DEC);
+IEEE80211_IF_FILE(ap_capab, u.sta.ap_capab, HEX);
+IEEE80211_IF_FILE(capab, u.sta.capab, HEX);
+IEEE80211_IF_FILE(extra_ie_len, u.sta.extra_ie_len, SIZE);
+IEEE80211_IF_FILE(auth_tries, u.sta.auth_tries, DEC);
+IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC);
+IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX);
+IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC);
+IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC);
+
+static ssize_t ieee80211_if_fmt_flags(
+ const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+ return scnprintf(buf, buflen, "%s%s%s%s%s%s%s\n",
+ sdata->u.sta.ssid_set ? "SSID\n" : "",
+ sdata->u.sta.bssid_set ? "BSSID\n" : "",
+ sdata->u.sta.prev_bssid_set ? "prev BSSID\n" : "",
+ sdata->u.sta.authenticated ? "AUTH\n" : "",
+ sdata->u.sta.associated ? "ASSOC\n" : "",
+ sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
+ sdata->u.sta.use_protection ? "CTS prot\n" : "");
+}
+__IEEE80211_IF_FILE(flags);
+
+/* AP attributes */
+IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
+IEEE80211_IF_FILE(dtim_period, u.ap.dtim_period, DEC);
+IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
+IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
+IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
+IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
+
+static ssize_t ieee80211_if_fmt_num_buffered_multicast(
+ const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+ return scnprintf(buf, buflen, "%u\n",
+ skb_queue_len(&sdata->u.ap.ps_bc_buf));
+}
+__IEEE80211_IF_FILE(num_buffered_multicast);
+
+static ssize_t ieee80211_if_fmt_beacon_head_len(
+ const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+ if (sdata->u.ap.beacon_head)
+ return scnprintf(buf, buflen, "%d\n",
+ sdata->u.ap.beacon_head_len);
+ return scnprintf(buf, buflen, "\n");
+}
+__IEEE80211_IF_FILE(beacon_head_len);
+
+static ssize_t ieee80211_if_fmt_beacon_tail_len(
+ const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+ if (sdata->u.ap.beacon_tail)
+ return scnprintf(buf, buflen, "%d\n",
+ sdata->u.ap.beacon_tail_len);
+ return scnprintf(buf, buflen, "\n");
+}
+__IEEE80211_IF_FILE(beacon_tail_len);
+
+/* WDS attributes */
+IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
+
+/* VLAN attributes */
+IEEE80211_IF_FILE(vlan_id, u.vlan.id, DEC);
+
+/* MONITOR attributes */
+static ssize_t ieee80211_if_fmt_mode(
+ const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+ struct ieee80211_local *local = sdata->local;
+
+ return scnprintf(buf, buflen, "%s\n",
+ ((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) ||
+ local->open_count == local->monitors) ?
+ "hard" : "soft");
+}
+__IEEE80211_IF_FILE(mode);
+
+
+#define DEBUGFS_ADD(name, type)\
+ sdata->debugfs.type.name = debugfs_create_file(#name, 0444,\
+ sdata->debugfsdir, sdata, &name##_ops);
+
+static void add_sta_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_ADD(channel_use, sta);
+ DEBUGFS_ADD(drop_unencrypted, sta);
+ DEBUGFS_ADD(eapol, sta);
+ DEBUGFS_ADD(ieee8021_x, sta);
+ DEBUGFS_ADD(state, sta);
+ DEBUGFS_ADD(bssid, sta);
+ DEBUGFS_ADD(prev_bssid, sta);
+ DEBUGFS_ADD(ssid_len, sta);
+ DEBUGFS_ADD(aid, sta);
+ DEBUGFS_ADD(ap_capab, sta);
+ DEBUGFS_ADD(capab, sta);
+ DEBUGFS_ADD(extra_ie_len, sta);
+ DEBUGFS_ADD(auth_tries, sta);
+ DEBUGFS_ADD(assoc_tries, sta);
+ DEBUGFS_ADD(auth_algs, sta);
+ DEBUGFS_ADD(auth_alg, sta);
+ DEBUGFS_ADD(auth_transaction, sta);
+ DEBUGFS_ADD(flags, sta);
+}
+
+static void add_ap_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_ADD(channel_use, ap);
+ DEBUGFS_ADD(drop_unencrypted, ap);
+ DEBUGFS_ADD(eapol, ap);
+ DEBUGFS_ADD(ieee8021_x, ap);
+ DEBUGFS_ADD(num_sta_ps, ap);
+ DEBUGFS_ADD(dtim_period, ap);
+ DEBUGFS_ADD(dtim_count, ap);
+ DEBUGFS_ADD(num_beacons, ap);
+ DEBUGFS_ADD(force_unicast_rateidx, ap);
+ DEBUGFS_ADD(max_ratectrl_rateidx, ap);
+ DEBUGFS_ADD(num_buffered_multicast, ap);
+ DEBUGFS_ADD(beacon_head_len, ap);
+ DEBUGFS_ADD(beacon_tail_len, ap);
+}
+
+static void add_wds_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_ADD(channel_use, wds);
+ DEBUGFS_ADD(drop_unencrypted, wds);
+ DEBUGFS_ADD(eapol, wds);
+ DEBUGFS_ADD(ieee8021_x, wds);
+ DEBUGFS_ADD(peer, wds);
+}
+
+static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_ADD(channel_use, vlan);
+ DEBUGFS_ADD(drop_unencrypted, vlan);
+ DEBUGFS_ADD(eapol, vlan);
+ DEBUGFS_ADD(ieee8021_x, vlan);
+ DEBUGFS_ADD(vlan_id, vlan);
+}
+
+static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_ADD(mode, monitor);
+}
+
+void add_files(struct ieee80211_sub_if_data *sdata)
+{
+ if (!sdata->debugfsdir)
+ return;
+
+ switch (sdata->type) {
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_IBSS:
+ add_sta_files(sdata);
+ break;
+ case IEEE80211_IF_TYPE_AP:
+ add_ap_files(sdata);
+ break;
+ case IEEE80211_IF_TYPE_WDS:
+ add_wds_files(sdata);
+ break;
+ case IEEE80211_IF_TYPE_MNTR:
+ add_monitor_files(sdata);
+ break;
+ case IEEE80211_IF_TYPE_VLAN:
+ add_vlan_files(sdata);
+ break;
+ default:
+ break;
+ }
+}
+
+#define DEBUGFS_DEL(name, type)\
+ debugfs_remove(sdata->debugfs.type.name);\
+ sdata->debugfs.type.name = NULL;
+
+static void del_sta_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_DEL(channel_use, sta);
+ DEBUGFS_DEL(drop_unencrypted, sta);
+ DEBUGFS_DEL(eapol, sta);
+ DEBUGFS_DEL(ieee8021_x, sta);
+ DEBUGFS_DEL(state, sta);
+ DEBUGFS_DEL(bssid, sta);
+ DEBUGFS_DEL(prev_bssid, sta);
+ DEBUGFS_DEL(ssid_len, sta);
+ DEBUGFS_DEL(aid, sta);
+ DEBUGFS_DEL(ap_capab, sta);
+ DEBUGFS_DEL(capab, sta);
+ DEBUGFS_DEL(extra_ie_len, sta);
+ DEBUGFS_DEL(auth_tries, sta);
+ DEBUGFS_DEL(assoc_tries, sta);
+ DEBUGFS_DEL(auth_algs, sta);
+ DEBUGFS_DEL(auth_alg, sta);
+ DEBUGFS_DEL(auth_transaction, sta);
+ DEBUGFS_DEL(flags, sta);
+}
+
+static void del_ap_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_DEL(channel_use, ap);
+ DEBUGFS_DEL(drop_unencrypted, ap);
+ DEBUGFS_DEL(eapol, ap);
+ DEBUGFS_DEL(ieee8021_x, ap);
+ DEBUGFS_DEL(num_sta_ps, ap);
+ DEBUGFS_DEL(dtim_period, ap);
+ DEBUGFS_DEL(dtim_count, ap);
+ DEBUGFS_DEL(num_beacons, ap);
+ DEBUGFS_DEL(force_unicast_rateidx, ap);
+ DEBUGFS_DEL(max_ratectrl_rateidx, ap);
+ DEBUGFS_DEL(num_buffered_multicast, ap);
+ DEBUGFS_DEL(beacon_head_len, ap);
+ DEBUGFS_DEL(beacon_tail_len, ap);
+}
+
+static void del_wds_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_DEL(channel_use, wds);
+ DEBUGFS_DEL(drop_unencrypted, wds);
+ DEBUGFS_DEL(eapol, wds);
+ DEBUGFS_DEL(ieee8021_x, wds);
+ DEBUGFS_DEL(peer, wds);
+}
+
+static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_DEL(channel_use, vlan);
+ DEBUGFS_DEL(drop_unencrypted, vlan);
+ DEBUGFS_DEL(eapol, vlan);
+ DEBUGFS_DEL(ieee8021_x, vlan);
+ DEBUGFS_DEL(vlan_id, vlan);
+}
+
+static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
+{
+ DEBUGFS_DEL(mode, monitor);
+}
+
+void del_files(struct ieee80211_sub_if_data *sdata, int type)
+{
+ if (!sdata->debugfsdir)
+ return;
+
+ switch (type) {
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_IBSS:
+ del_sta_files(sdata);
+ break;
+ case IEEE80211_IF_TYPE_AP:
+ del_ap_files(sdata);
+ break;
+ case IEEE80211_IF_TYPE_WDS:
+ del_wds_files(sdata);
+ break;
+ case IEEE80211_IF_TYPE_MNTR:
+ del_monitor_files(sdata);
+ break;
+ case IEEE80211_IF_TYPE_VLAN:
+ del_vlan_files(sdata);
+ break;
+ default:
+ break;
+ }
+}
+
+static int notif_registered;
+
+void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
+{
+ char buf[10+IFNAMSIZ];
+
+ if (!notif_registered)
+ return;
+
+ sprintf(buf, "netdev:%s", sdata->dev->name);
+ sdata->debugfsdir = debugfs_create_dir(buf,
+ sdata->local->hw.wiphy->debugfsdir);
+}
+
+void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
+{
+ del_files(sdata, sdata->type);
+ debugfs_remove(sdata->debugfsdir);
+ sdata->debugfsdir = NULL;
+}
+
+void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
+ int oldtype)
+{
+ del_files(sdata, oldtype);
+ add_files(sdata);
+}
+
+static int netdev_notify(struct notifier_block * nb,
+ unsigned long state,
+ void *ndev)
+{
+ struct net_device *dev = ndev;
+ char buf[10+IFNAMSIZ];
+
+ if (state != NETDEV_CHANGENAME)
+ return 0;
+
+ if (!dev->ieee80211_ptr || !dev->ieee80211_ptr->wiphy)
+ return 0;
+
+ if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
+ return 0;
+
+ /* TODO
+ sprintf(buf, "netdev:%s", dev->name);
+ debugfs_rename(IEEE80211_DEV_TO_SUB_IF(dev)->debugfsdir, buf);
+ */
+
+ return 0;
+}
+
+static struct notifier_block mac80211_debugfs_netdev_notifier = {
+ .notifier_call = netdev_notify,
+};
+
+void ieee80211_debugfs_netdev_init(void)
+{
+ int err;
+
+ err = register_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
+ if (err) {
+ printk(KERN_ERR
+ "mac80211: failed to install netdev notifier,"
+ " disabling per-netdev debugfs!\n");
+ } else
+ notif_registered = 1;
+}
+
+void ieee80211_debugfs_netdev_exit(void)
+{
+ unregister_netdevice_notifier(&mac80211_debugfs_netdev_notifier);
+ notif_registered = 0;
+}
diff --git a/net/mac80211/debugfs_netdev.h b/net/mac80211/debugfs_netdev.h
new file mode 100644
index 0000000..308a52a
--- /dev/null
+++ b/net/mac80211/debugfs_netdev.h
@@ -0,0 +1,30 @@
+/* routines exported for sysfs handling */
+
+#ifndef __IEEE80211_SYSFS_H
+#define __IEEE80211_SYSFS_H
+
+#ifdef CONFIG_DEBUG_FS
+void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
+void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
+ int oldtype);
+void ieee80211_debugfs_netdev_init(void);
+void ieee80211_debugfs_netdev_exit(void);
+#else
+static inline void ieee80211_debugfs_add_netdev(
+ struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_remove_netdev(
+ struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_debugfs_change_if_type(
+ struct ieee80211_sub_if_data *sdata, int oldtype)
+{}
+static inline void ieee80211_debugfs_netdev_init(void)
+{}
+
+static inline void ieee80211_debugfs_netdev_exit(void)
+{}
+#endif
+
+#endif /* __IEEE80211_SYSFS_H */
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index c9e4cd0..db04fd8 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -33,9 +33,12 @@ #include "wme.h"
#include "aes_ccm.h"
#include "ieee80211_led.h"
#include "ieee80211_cfg.h"
-#include "ieee80211_sysfs.h"
#include "debugfs.h"
-#include "key_sysfs.h"
+#include "debugfs_netdev.h"
+#include "debugfs_key.h"
+
+/* privid for wiphys to determine whether they belong to us or not */
+void *mac80211_wiphy_privid = &mac80211_wiphy_privid;

/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
@@ -86,40 +89,31 @@ struct ieee80211_key *ieee80211_key_allo
int idx, size_t key_len, gfp_t flags)
{
struct ieee80211_key *key;
- int res;

key = kzalloc(sizeof(struct ieee80211_key) + key_len, flags);
if (!key)
return NULL;
- if (sdata)
- res = kobject_set_name(&key->kobj, "%d", idx);
- else
- res = kobject_set_name(&key->kobj, "key");
- if (res) {
- kfree(key);
- return NULL;
- }
- ieee80211_key_sysfs_set_kset(key, sdata ? &sdata->key_kset : NULL);
- kobject_init(&key->kobj);
+ kref_init(&key->kref);
return key;
}

-void ieee80211_key_free(struct ieee80211_key *key)
-{
- if (key)
- kobject_put(&key->kobj);
-}
-
-void ieee80211_key_release(struct kobject *kobj)
+void ieee80211_key_release(struct kref *kref)
{
struct ieee80211_key *key;

- key = container_of(kobj, struct ieee80211_key, kobj);
+ key = container_of(kref, struct ieee80211_key, kref);
if (key->alg == ALG_CCMP)
ieee80211_aes_key_free(key->u.ccmp.tfm);
+ ieee80211_debugfs_key_remove(key);
kfree(key);
}

+void ieee80211_key_free(struct ieee80211_key *key)
+{
+ if (key)
+ kref_put(&key->kref, ieee80211_key_release);
+}
+
static int rate_list_match(const int *rate_list, int rate)
{
int i;
@@ -4520,6 +4514,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(
if (!wiphy)
return NULL;

+ wiphy->privid = mac80211_wiphy_privid;
+
local = wiphy_priv(wiphy);
local->hw.wiphy = wiphy;

@@ -4645,9 +4641,8 @@ int ieee80211_register_hw(struct ieee802
result = register_netdevice(local->mdev);
if (result < 0)
goto fail_dev;
- result = ieee80211_sysfs_add_netdevice(local->mdev);
- if (result < 0)
- goto fail_if_sysfs;
+
+ ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));

result = ieee80211_init_rate_ctrl_alg(local, NULL);
if (result < 0) {
@@ -4682,8 +4677,7 @@ int ieee80211_register_hw(struct ieee802
fail_wep:
rate_control_deinitialize(local);
fail_rate:
- ieee80211_sysfs_remove_netdevice(local->mdev);
-fail_if_sysfs:
+ ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
unregister_netdevice(local->mdev);
fail_dev:
rtnl_unlock();
@@ -4895,6 +4889,8 @@ static int __init ieee80211_init(void)
return ret;
}

+ ieee80211_debugfs_netdev_init();
+
return 0;
}

@@ -4902,6 +4898,7 @@ static int __init ieee80211_init(void)
static void __exit ieee80211_exit(void)
{
ieee80211_wme_unregister();
+ ieee80211_debugfs_netdev_exit();
}


diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0bb08b0..baf927f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -325,7 +325,6 @@ struct ieee80211_sub_if_data {
#define NUM_DEFAULT_KEYS 4
struct ieee80211_key *keys[NUM_DEFAULT_KEYS];
struct ieee80211_key *default_key;
- struct kset key_kset;

struct ieee80211_if_ap *bss; /* BSS that this device belongs to */

@@ -338,7 +337,64 @@ #define NUM_DEFAULT_KEYS 4
int channel_use;
int channel_use_raw;

- struct attribute_group *sysfs_group;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfsdir;
+ union {
+ struct {
+ struct dentry *channel_use;
+ struct dentry *drop_unencrypted;
+ struct dentry *eapol;
+ struct dentry *ieee8021_x;
+ struct dentry *state;
+ struct dentry *bssid;
+ struct dentry *prev_bssid;
+ struct dentry *ssid_len;
+ struct dentry *aid;
+ struct dentry *ap_capab;
+ struct dentry *capab;
+ struct dentry *extra_ie_len;
+ struct dentry *auth_tries;
+ struct dentry *assoc_tries;
+ struct dentry *auth_algs;
+ struct dentry *auth_alg;
+ struct dentry *auth_transaction;
+ struct dentry *flags;
+ } sta;
+ struct {
+ struct dentry *channel_use;
+ struct dentry *drop_unencrypted;
+ struct dentry *eapol;
+ struct dentry *ieee8021_x;
+ struct dentry *num_sta_ps;
+ struct dentry *dtim_period;
+ struct dentry *dtim_count;
+ struct dentry *num_beacons;
+ struct dentry *force_unicast_rateidx;
+ struct dentry *max_ratectrl_rateidx;
+ struct dentry *num_buffered_multicast;
+ struct dentry *beacon_head_len;
+ struct dentry *beacon_tail_len;
+ } ap;
+ struct {
+ struct dentry *channel_use;
+ struct dentry *drop_unencrypted;
+ struct dentry *eapol;
+ struct dentry *ieee8021_x;
+ struct dentry *peer;
+ } wds;
+ struct {
+ struct dentry *channel_use;
+ struct dentry *drop_unencrypted;
+ struct dentry *eapol;
+ struct dentry *ieee8021_x;
+ struct dentry *vlan_id;
+ } vlan;
+ struct {
+ struct dentry *mode;
+ } monitor;
+ struct dentry *default_key;
+ } debugfs;
+#endif
};

#define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev)
@@ -600,6 +656,7 @@ #endif
struct dentry *wme_rx_queue;
} stats;
struct dentry *stations;
+ struct dentry *keys;
} debugfs;
#endif
};
@@ -671,7 +728,6 @@ ieee80211_key_data2conf(struct ieee80211
struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
int idx, size_t key_len, gfp_t flags);
void ieee80211_key_free(struct ieee80211_key *key);
-void ieee80211_key_release(struct kobject *kobj);
void ieee80211_rx_mgmt(struct ieee80211_local *local, struct sk_buff *skb,
struct ieee80211_rx_status *status, u32 msg_type);
void ieee80211_prepare_rates(struct ieee80211_local *local,
@@ -764,4 +820,7 @@ void ieee80211_if_sdata_init(struct ieee
int ieee80211_if_add_mgmt(struct ieee80211_local *local);
void ieee80211_if_del_mgmt(struct ieee80211_local *local);

+/* for wiphy privid */
+extern void *mac80211_wiphy_privid;
+
#endif /* IEEE80211_I_H */
diff --git a/net/mac80211/ieee80211_iface.c b/net/mac80211/ieee80211_iface.c
index 3e0b4fa..b1b20ba 100644
--- a/net/mac80211/ieee80211_iface.c
+++ b/net/mac80211/ieee80211_iface.c
@@ -14,7 +14,7 @@ #include <linux/rtnetlink.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "sta_info.h"
-#include "ieee80211_sysfs.h"
+#include "debugfs_netdev.h"

void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
{
@@ -81,14 +81,8 @@ int ieee80211_if_add(struct net_device *
ret = register_netdevice(ndev);
if (ret)
goto fail;
- ret = ieee80211_sysfs_add_netdevice(ndev);
- if (ret) {
- /* ndev will be freed by ndev->destructor */
- unregister_netdevice(ndev);
- *new_dev = NULL;
- return ret;
- }

+ ieee80211_debugfs_add_netdev(sdata);
list_add(&sdata->list, &local->sub_if_list);
ieee80211_update_default_wep_only(local);

@@ -130,16 +124,14 @@ int ieee80211_if_add_mgmt(struct ieee802
ret = register_netdevice(ndev);
if (ret)
goto fail;
- ret = ieee80211_sysfs_add_netdevice(ndev);
- if (ret)
- goto fail_sysfs;
+
+ ieee80211_debugfs_add_netdev(nsdata);
+
if (local->open_count > 0)
dev_open(ndev);
local->apdev = ndev;
return 0;

-fail_sysfs:
- unregister_netdevice(ndev);
fail:
free_netdev(ndev);
return ret;
@@ -151,7 +143,7 @@ void ieee80211_if_del_mgmt(struct ieee80

ASSERT_RTNL();
apdev = local->apdev;
- ieee80211_sysfs_remove_netdevice(apdev);
+ ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(apdev));
local->apdev = NULL;
unregister_netdevice(apdev);
}
@@ -160,6 +152,7 @@ void ieee80211_if_set_type(struct net_de
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ int oldtype = sdata->type;

sdata->type = type;
switch (type) {
@@ -205,7 +198,7 @@ void ieee80211_if_set_type(struct net_de
printk(KERN_WARNING "%s: %s: Unknown interface type 0x%x",
dev->name, __FUNCTION__, type);
}
- ieee80211_sysfs_change_if_type(dev);
+ ieee80211_debugfs_change_if_type(sdata, oldtype);
ieee80211_update_default_wep_only(local);
}

@@ -309,7 +302,7 @@ void __ieee80211_if_del(struct ieee80211
struct net_device *dev = sdata->dev;

list_del(&sdata->list);
- ieee80211_sysfs_remove_netdevice(dev);
+ ieee80211_debugfs_remove_netdev(sdata);
unregister_netdevice(dev);
/* Except master interface, the net_device will be freed by
* net_device->destructor (i. e. ieee80211_if_free). */
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 782c1cb..cb75015 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -25,7 +25,7 @@ #include "hostapd_ioctl.h"
#include "ieee80211_rate.h"
#include "wpa.h"
#include "aes_ccm.h"
-#include "key_sysfs.h"
+#include "debugfs_key.h"

static int ieee80211_regdom = 0x10; /* FCC */
module_param(ieee80211_regdom, int, 0444);
@@ -634,10 +634,10 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG
kfree(keyconf);

if (set_tx_key || sdata->default_key == key) {
- ieee80211_key_sysfs_remove_default(sdata);
+ ieee80211_debugfs_key_remove_default(sdata);
sdata->default_key = NULL;
}
- ieee80211_key_sysfs_remove(key);
+ ieee80211_debugfs_key_remove(key);
if (sta)
sta->key = NULL;
else
@@ -678,18 +678,18 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG
}

if (set_tx_key || sdata->default_key == old_key) {
- ieee80211_key_sysfs_remove_default(sdata);
+ ieee80211_debugfs_key_remove_default(sdata);
sdata->default_key = NULL;
}
- ieee80211_key_sysfs_remove(old_key);
+ ieee80211_debugfs_key_remove(old_key);
if (sta)
sta->key = key;
else
sdata->keys[idx] = key;
ieee80211_key_free(old_key);
- ret = ieee80211_key_sysfs_add(key);
- if (ret)
- goto err_null;
+ ieee80211_debugfs_key_add(local, key);
+ if (sta)
+ ieee80211_debugfs_key_sta_link(key, sta);

if (try_hwaccel &&
(alg == ALG_WEP || alg == ALG_TKIP || alg == ALG_CCMP)) {
@@ -702,9 +702,9 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG

if (set_tx_key || (!sta && !sdata->default_key && key)) {
sdata->default_key = key;
- if (key && ieee80211_key_sysfs_add_default(sdata))
- printk(KERN_WARNING "%s: cannot create symlink to "
- "default key\n", dev->name);
+ if (key)
+ ieee80211_debugfs_key_add_default(sdata);
+
if (local->ops->set_key_idx &&
local->ops->set_key_idx(local_to_hw(local), idx))
printk(KERN_DEBUG "%s: failed to set TX key idx for "
@@ -716,11 +716,6 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG

return 0;

-err_null:
- if (sta)
- sta->key = NULL;
- else
- sdata->keys[idx] = NULL;
err_free:
ieee80211_key_free(key);
err_out:
@@ -2949,10 +2944,10 @@ static int ieee80211_ioctl_siwencode(str
else if (erq->length == 0) {
/* No key data - just set the default TX key index */
if (sdata->default_key != sdata->keys[idx]) {
- ieee80211_key_sysfs_remove_default(sdata);
+ ieee80211_debugfs_key_remove_default(sdata);
sdata->default_key = sdata->keys[idx];
if (sdata->default_key)
- ieee80211_key_sysfs_add_default(sdata);
+ ieee80211_debugfs_key_add_default(sdata);
}
return 0;
}
diff --git a/net/mac80211/ieee80211_key.h b/net/mac80211/ieee80211_key.h
index 60c4339..cde2974 100644
--- a/net/mac80211/ieee80211_key.h
+++ b/net/mac80211/ieee80211_key.h
@@ -11,7 +11,7 @@ #ifndef IEEE80211_KEY_H
#define IEEE80211_KEY_H

#include <linux/types.h>
-#include <linux/kobject.h>
+#include <linux/kref.h>
#include <linux/crypto.h>
#include <net/mac80211.h>

@@ -42,7 +42,7 @@ #define CCMP_PN_LEN 6
#define NUM_RX_DATA_QUEUES 17

struct ieee80211_key {
- struct kobject kobj;
+ struct kref kref;

int hw_key_idx; /* filled and used by low-level driver */
ieee80211_key_alg alg;
@@ -83,6 +83,23 @@ #endif
* (used only for broadcast keys). */
s8 keyidx; /* WEP key index */

+#ifdef CONFIG_DEBUG_FS
+ struct {
+ struct dentry *stalink;
+ struct dentry *dir;
+ struct dentry *keylen;
+ struct dentry *force_sw_encrypt;
+ struct dentry *keyidx;
+ struct dentry *hw_key_idx;
+ struct dentry *tx_rx_count;
+ struct dentry *algorithm;
+ struct dentry *tx_spec;
+ struct dentry *rx_spec;
+ struct dentry *replays;
+ struct dentry *key;
+ } debugfs;
+#endif
+
u8 key[0];
};

diff --git a/net/mac80211/ieee80211_sysfs.c b/net/mac80211/ieee80211_sysfs.c
deleted file mode 100644
index 9fdc398..0000000
--- a/net/mac80211/ieee80211_sysfs.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * 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/kernel.h>
-#include <linux/device.h>
-#include <linux/if.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/rtnetlink.h>
-#include <net/mac80211.h>
-#include <net/cfg80211.h>
-#include "ieee80211_i.h"
-#include "ieee80211_rate.h"
-#include "ieee80211_sysfs.h"
-#include "key_sysfs.h"
-
-static inline struct ieee80211_local *to_ieee80211_local(struct device *dev)
-{
- struct wiphy *wiphy = container_of(dev, struct wiphy, dev);
- return wiphy_priv(wiphy);
-}
-
-static inline int rtnl_lock_local(struct ieee80211_local *local)
-{
- rtnl_lock();
- if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) {
- rtnl_unlock();
- return -ENODEV;
- }
- return 0;
-}
-
-/* attributes in /sys/class/net/X/ */
-
-static ssize_t ieee80211_if_show(struct device *d,
- struct device_attribute *attr, char *buf,
- ssize_t (*format)(const struct ieee80211_sub_if_data *,
- char *))
-{
- struct net_device *dev = to_net_dev(d);
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- ssize_t ret = -EINVAL;
-
- read_lock(&dev_base_lock);
- if (dev->reg_state == NETREG_REGISTERED) {
- ret = (*format)(sdata, buf);
- }
- read_unlock(&dev_base_lock);
- return ret;
-}
-
-#define IEEE80211_IF_FMT(name, field, format_string) \
-static ssize_t ieee80211_if_fmt_##name(const struct \
- ieee80211_sub_if_data *sdata, char *buf) \
-{ \
- return sprintf(buf, format_string, sdata->field); \
-}
-#define IEEE80211_IF_FMT_DEC(name, field) \
- IEEE80211_IF_FMT(name, field, "%d\n")
-#define IEEE80211_IF_FMT_HEX(name, field) \
- IEEE80211_IF_FMT(name, field, "%#x\n")
-#define IEEE80211_IF_FMT_SIZE(name, field) \
- IEEE80211_IF_FMT(name, field, "%zd\n")
-
-#define IEEE80211_IF_FMT_ATOMIC(name, field) \
-static ssize_t ieee80211_if_fmt_##name(const struct \
- ieee80211_sub_if_data *sdata, char *buf) \
-{ \
- return sprintf(buf, "%d\n", atomic_read(&sdata->field)); \
-}
-
-#define IEEE80211_IF_FMT_MAC(name, field) \
-static ssize_t ieee80211_if_fmt_##name(const struct \
- ieee80211_sub_if_data *sdata, char *buf) \
-{ \
- return sprintf(buf, MAC_FMT "\n", MAC_ARG(sdata->field)); \
-}
-
-#define __IEEE80211_IF_SHOW(name) \
-static ssize_t ieee80211_if_show_##name(struct device *d, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- return ieee80211_if_show(d, attr, buf, ieee80211_if_fmt_##name);\
-} \
-static DEVICE_ATTR(name, S_IRUGO, ieee80211_if_show_##name, NULL);
-
-#define IEEE80211_IF_SHOW(name, field, format) \
- IEEE80211_IF_FMT_##format(name, field) \
- __IEEE80211_IF_SHOW(name)
-
-/* common attributes */
-IEEE80211_IF_SHOW(channel_use, channel_use, DEC);
-IEEE80211_IF_SHOW(drop_unencrypted, drop_unencrypted, DEC);
-IEEE80211_IF_SHOW(eapol, eapol, DEC);
-IEEE80211_IF_SHOW(ieee8021_x, ieee802_1x, DEC);
-
-/* STA/IBSS attributes */
-IEEE80211_IF_SHOW(state, u.sta.state, DEC);
-IEEE80211_IF_SHOW(bssid, u.sta.bssid, MAC);
-IEEE80211_IF_SHOW(prev_bssid, u.sta.prev_bssid, MAC);
-IEEE80211_IF_SHOW(ssid_len, u.sta.ssid_len, SIZE);
-IEEE80211_IF_SHOW(aid, u.sta.aid, DEC);
-IEEE80211_IF_SHOW(ap_capab, u.sta.ap_capab, HEX);
-IEEE80211_IF_SHOW(capab, u.sta.capab, HEX);
-IEEE80211_IF_SHOW(extra_ie_len, u.sta.extra_ie_len, SIZE);
-IEEE80211_IF_SHOW(auth_tries, u.sta.auth_tries, DEC);
-IEEE80211_IF_SHOW(assoc_tries, u.sta.assoc_tries, DEC);
-IEEE80211_IF_SHOW(auth_algs, u.sta.auth_algs, HEX);
-IEEE80211_IF_SHOW(auth_alg, u.sta.auth_alg, DEC);
-IEEE80211_IF_SHOW(auth_transaction, u.sta.auth_transaction, DEC);
-
-static ssize_t ieee80211_if_fmt_flags(const struct
- ieee80211_sub_if_data *sdata, char *buf)
-{
- return sprintf(buf, "%s%s%s%s%s%s%s\n",
- sdata->u.sta.ssid_set ? "SSID\n" : "",
- sdata->u.sta.bssid_set ? "BSSID\n" : "",
- sdata->u.sta.prev_bssid_set ? "prev BSSID\n" : "",
- sdata->u.sta.authenticated ? "AUTH\n" : "",
- sdata->u.sta.associated ? "ASSOC\n" : "",
- sdata->u.sta.probereq_poll ? "PROBEREQ POLL\n" : "",
- sdata->u.sta.use_protection ? "CTS prot\n" : "");
-}
-__IEEE80211_IF_SHOW(flags);
-
-/* AP attributes */
-IEEE80211_IF_SHOW(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
-IEEE80211_IF_SHOW(dtim_period, u.ap.dtim_period, DEC);
-IEEE80211_IF_SHOW(dtim_count, u.ap.dtim_count, DEC);
-IEEE80211_IF_SHOW(num_beacons, u.ap.num_beacons, DEC);
-IEEE80211_IF_SHOW(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
-IEEE80211_IF_SHOW(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
-
-static ssize_t ieee80211_if_fmt_num_buffered_multicast(const struct
- ieee80211_sub_if_data *sdata, char *buf)
-{
- return sprintf(buf, "%u\n", skb_queue_len(&sdata->u.ap.ps_bc_buf));
-}
-__IEEE80211_IF_SHOW(num_buffered_multicast);
-
-static ssize_t ieee80211_if_fmt_beacon_head_len(const struct
- ieee80211_sub_if_data *sdata, char *buf)
-{
- if (sdata->u.ap.beacon_head)
- return sprintf(buf, "%d\n", sdata->u.ap.beacon_head_len);
- return sprintf(buf, "\n");
-}
-__IEEE80211_IF_SHOW(beacon_head_len);
-
-static ssize_t ieee80211_if_fmt_beacon_tail_len(const struct
- ieee80211_sub_if_data *sdata, char *buf)
-{
- if (sdata->u.ap.beacon_tail)
- return sprintf(buf, "%d\n", sdata->u.ap.beacon_tail_len);
- return sprintf(buf, "\n");
-}
-__IEEE80211_IF_SHOW(beacon_tail_len);
-
-/* WDS attributes */
-IEEE80211_IF_SHOW(peer, u.wds.remote_addr, MAC);
-
-/* VLAN attributes */
-IEEE80211_IF_SHOW(vlan_id, u.vlan.id, DEC);
-
-/* MONITOR attributes */
-static ssize_t ieee80211_if_fmt_mode(const struct
- ieee80211_sub_if_data *sdata, char *buf)
-{
- struct ieee80211_local *local = sdata->local;
-
- return sprintf(buf, "%s\n",
- ((local->hw.flags & IEEE80211_HW_MONITOR_DURING_OPER) ||
- local->open_count == local->monitors) ?
- "hard" : "soft");
-}
-__IEEE80211_IF_SHOW(mode);
-
-static struct attribute *ieee80211_sta_attrs[] = {
- &dev_attr_channel_use.attr,
- &dev_attr_drop_unencrypted.attr,
- &dev_attr_eapol.attr,
- &dev_attr_ieee8021_x.attr,
- &dev_attr_state.attr,
- &dev_attr_bssid.attr,
- &dev_attr_prev_bssid.attr,
- &dev_attr_ssid_len.attr,
- &dev_attr_aid.attr,
- &dev_attr_ap_capab.attr,
- &dev_attr_capab.attr,
- &dev_attr_extra_ie_len.attr,
- &dev_attr_auth_tries.attr,
- &dev_attr_assoc_tries.attr,
- &dev_attr_auth_algs.attr,
- &dev_attr_auth_alg.attr,
- &dev_attr_auth_transaction.attr,
- &dev_attr_flags.attr,
- NULL
-};
-
-static struct attribute *ieee80211_ap_attrs[] = {
- &dev_attr_channel_use.attr,
- &dev_attr_drop_unencrypted.attr,
- &dev_attr_eapol.attr,
- &dev_attr_ieee8021_x.attr,
- &dev_attr_num_sta_ps.attr,
- &dev_attr_dtim_period.attr,
- &dev_attr_dtim_count.attr,
- &dev_attr_num_beacons.attr,
- &dev_attr_force_unicast_rateidx.attr,
- &dev_attr_max_ratectrl_rateidx.attr,
- &dev_attr_num_buffered_multicast.attr,
- &dev_attr_beacon_head_len.attr,
- &dev_attr_beacon_tail_len.attr,
- NULL
-};
-
-static struct attribute *ieee80211_wds_attrs[] = {
- &dev_attr_channel_use.attr,
- &dev_attr_drop_unencrypted.attr,
- &dev_attr_eapol.attr,
- &dev_attr_ieee8021_x.attr,
- &dev_attr_peer.attr,
- NULL
-};
-
-static struct attribute *ieee80211_vlan_attrs[] = {
- &dev_attr_channel_use.attr,
- &dev_attr_drop_unencrypted.attr,
- &dev_attr_eapol.attr,
- &dev_attr_ieee8021_x.attr,
- &dev_attr_vlan_id.attr,
- NULL
-};
-
-static struct attribute *ieee80211_monitor_attrs[] = {
- &dev_attr_mode.attr,
- NULL
-};
-
-static struct attribute_group ieee80211_sta_group = {
- .name = "sta",
- .attrs = ieee80211_sta_attrs,
-};
-
-static struct attribute_group ieee80211_ap_group = {
- .name = "ap",
- .attrs = ieee80211_ap_attrs,
-};
-
-static struct attribute_group ieee80211_wds_group = {
- .name = "wds",
- .attrs = ieee80211_wds_attrs,
-};
-
-static struct attribute_group ieee80211_vlan_group = {
- .name = "vlan",
- .attrs = ieee80211_vlan_attrs,
-};
-
-static struct attribute_group ieee80211_monitor_group = {
- .name = "monitor",
- .attrs = ieee80211_monitor_attrs,
-};
-
-/* /sys/class/net/X functions */
-
-static void __ieee80211_remove_if_group(struct kobject *kobj,
- struct ieee80211_sub_if_data *sdata)
-{
- if (sdata->sysfs_group) {
- sysfs_remove_group(kobj, sdata->sysfs_group);
- sdata->sysfs_group = NULL;
- }
-}
-
-static inline void ieee80211_remove_if_group(struct kobject *kobj,
- struct net_device *dev)
-{
- __ieee80211_remove_if_group(kobj, IEEE80211_DEV_TO_SUB_IF(dev));
-}
-
-static int ieee80211_add_if_group(struct kobject *kobj,
- struct net_device *dev)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- int res = 0;
-
- __ieee80211_remove_if_group(kobj, sdata);
- switch (sdata->type) {
- case IEEE80211_IF_TYPE_STA:
- sdata->sysfs_group = &ieee80211_sta_group;
- break;
- case IEEE80211_IF_TYPE_AP:
- sdata->sysfs_group = &ieee80211_ap_group;
- break;
- case IEEE80211_IF_TYPE_WDS:
- sdata->sysfs_group = &ieee80211_wds_group;
- break;
- case IEEE80211_IF_TYPE_VLAN:
- sdata->sysfs_group = &ieee80211_vlan_group;
- break;
- case IEEE80211_IF_TYPE_MNTR:
- sdata->sysfs_group = &ieee80211_monitor_group;
- break;
- default:
- goto out;
- }
- res = sysfs_create_group(kobj, sdata->sysfs_group);
- if (res)
- sdata->sysfs_group = NULL;
-out:
- return res;
-}
-
-int ieee80211_sysfs_change_if_type(struct net_device *dev)
-{
- return ieee80211_add_if_group(&dev->dev.kobj, dev);
-}
-
-int ieee80211_sysfs_add_netdevice(struct net_device *dev)
-{
- int res;
-
- res = ieee80211_add_if_group(&dev->dev.kobj, dev);
- if (res)
- goto err_fail_if_group;
- res = ieee80211_key_kset_sysfs_register(IEEE80211_DEV_TO_SUB_IF(dev));
- return res;
-
-err_fail_if_group:
- return res;
-}
-
-void ieee80211_sysfs_remove_netdevice(struct net_device *dev)
-{
- ieee80211_key_kset_sysfs_unregister(IEEE80211_DEV_TO_SUB_IF(dev));
- ieee80211_remove_if_group(&dev->dev.kobj, dev);
-}
diff --git a/net/mac80211/ieee80211_sysfs.h b/net/mac80211/ieee80211_sysfs.h
deleted file mode 100644
index 1749cbd..0000000
--- a/net/mac80211/ieee80211_sysfs.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* routines exported for sysfs handling */
-
-#ifndef __IEEE80211_SYSFS_H
-#define __IEEE80211_SYSFS_H
-
-int ieee80211_sysfs_add_netdevice(struct net_device *dev);
-void ieee80211_sysfs_remove_netdevice(struct net_device *dev);
-int ieee80211_sysfs_change_if_type(struct net_device *dev);
-
-#endif /* __IEEE80211_SYSFS_H */
diff --git a/net/mac80211/key_sysfs.c b/net/mac80211/key_sysfs.c
deleted file mode 100644
index 6576659..0000000
--- a/net/mac80211/key_sysfs.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright 2003-2005 Devicescape Software, Inc.
- * Copyright (c) 2006 Jiri Benc <[email protected]>
- * Copyright 2007 Johannes Berg <[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 "ieee80211_key.h"
-
-/* keys attributtes */
-
-struct key_attribute {
- struct attribute attr;
- ssize_t (*show)(const struct ieee80211_key *, char *buf);
- ssize_t (*store)(struct ieee80211_key *, const char *buf,
- size_t count);
-};
-
-#define KEY_SHOW(name, field, format_string) \
-static ssize_t show_key_##name(const struct ieee80211_key *key, char *buf)\
-{ \
- return sprintf(buf, format_string, key->field); \
-}
-#define KEY_SHOW_D(name, field) KEY_SHOW(name, field, "%d\n")
-
-#define __KEY_ATTR(name) \
-static struct key_attribute key_attr_##name = \
- __ATTR(name, S_IRUSR, show_key_##name, NULL)
-
-#define KEY_ATTR(name, field, format) \
- KEY_SHOW_##format(name, field) \
- __KEY_ATTR(name)
-
-KEY_ATTR(length, keylen, D);
-KEY_ATTR(sw_encrypt, force_sw_encrypt, D);
-KEY_ATTR(index, keyidx, D);
-KEY_ATTR(hw_index, hw_key_idx, D);
-KEY_ATTR(tx_rx_count, tx_rx_count, D);
-
-static ssize_t show_key_algorithm(const struct ieee80211_key *key, char *buf)
-{
- char *alg;
-
- switch (key->alg) {
- case ALG_WEP:
- alg = "WEP";
- break;
- case ALG_TKIP:
- alg = "TKIP";
- break;
- case ALG_CCMP:
- alg = "CCMP";
- break;
- default:
- return 0;
- }
- return sprintf(buf, "%s\n", alg);
-}
-__KEY_ATTR(algorithm);
-
-static ssize_t show_key_tx_spec(const struct ieee80211_key *key, char *buf)
-{
- const u8 *tpn;
-
- switch (key->alg) {
- case ALG_WEP:
- return sprintf(buf, "\n");
- case ALG_TKIP:
- return sprintf(buf, "%08x %04x\n", key->u.tkip.iv32,
- key->u.tkip.iv16);
- case ALG_CCMP:
- tpn = key->u.ccmp.tx_pn;
- return sprintf(buf, "%02x%02x%02x%02x%02x%02x\n", tpn[0],
- tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
- default:
- return 0;
- }
-}
-__KEY_ATTR(tx_spec);
-
-static ssize_t show_key_rx_spec(const struct ieee80211_key *key, char *buf)
-{
- int i;
- const u8 *rpn;
- char *p = buf;
-
- switch (key->alg) {
- case ALG_WEP:
- return sprintf(buf, "\n");
- case ALG_TKIP:
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
- p += sprintf(p, "%08x %04x\n",
- key->u.tkip.iv32_rx[i],
- key->u.tkip.iv16_rx[i]);
- return (p - buf);
- case ALG_CCMP:
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
- rpn = key->u.ccmp.rx_pn[i];
- p += sprintf(p, "%02x%02x%02x%02x%02x%02x\n", rpn[0],
- rpn[1], rpn[2], rpn[3], rpn[4], rpn[5]);
- }
- return (p - buf);
- default:
- return 0;
- }
-}
-__KEY_ATTR(rx_spec);
-
-static ssize_t show_key_replays(const struct ieee80211_key *key, char *buf)
-{
- if (key->alg != ALG_CCMP)
- return 0;
- return sprintf(buf, "%u\n", key->u.ccmp.replays);
-}
-__KEY_ATTR(replays);
-
-static ssize_t show_key_key(const struct ieee80211_key *key, char *buf)
-{
- int i;
- char *p = buf;
-
- for (i = 0; i < key->keylen; i++)
- p += sprintf(p, "%02x", key->key[i]);
- p += sprintf(p, "\n");
- return (p - buf);
-}
-__KEY_ATTR(key);
-
-static struct attribute *key_ktype_attrs[] = {
- &key_attr_length.attr,
- &key_attr_sw_encrypt.attr,
- &key_attr_index.attr,
- &key_attr_hw_index.attr,
- &key_attr_tx_rx_count.attr,
- &key_attr_algorithm.attr,
- &key_attr_tx_spec.attr,
- &key_attr_rx_spec.attr,
- &key_attr_replays.attr,
- &key_attr_key.attr,
- NULL
-};
-
-/* structures and functions */
-
-static ssize_t key_sysfs_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct key_attribute *key_attr;
- struct ieee80211_key *key;
-
- key_attr = container_of(attr, struct key_attribute, attr);
- key = container_of(kobj, struct ieee80211_key, kobj);
- return key_attr->show(key, buf);
-}
-
-static struct sysfs_ops key_ktype_ops = {
- .show = key_sysfs_show,
-};
-
-static struct kobj_type key_ktype = {
- .release = ieee80211_key_release,
- .sysfs_ops = &key_ktype_ops,
- .default_attrs = key_ktype_attrs,
-};
-
-int ieee80211_key_kset_sysfs_register(struct ieee80211_sub_if_data *sdata)
-{
- int res;
-
- res = kobject_set_name(&sdata->key_kset.kobj, "keys");
- if (res)
- return res;
- sdata->key_kset.kobj.parent = &sdata->dev->dev.kobj;
- sdata->key_kset.ktype = &key_ktype;
- return kset_register(&sdata->key_kset);
-}
-
-void ieee80211_key_kset_sysfs_unregister(struct ieee80211_sub_if_data *sdata)
-{
- kset_unregister(&sdata->key_kset);
-}
-
-void ieee80211_key_sysfs_set_kset(struct ieee80211_key *key, struct kset *kset)
-{
- key->kobj.kset = kset;
- if (!kset)
- key->kobj.ktype = &key_ktype;
-}
-
-int ieee80211_key_sysfs_add(struct ieee80211_key *key)
-{
- return kobject_add(&key->kobj);
-}
-
-void ieee80211_key_sysfs_remove(struct ieee80211_key *key)
-{
- if (key)
- kobject_del(&key->kobj);
-}
-
-int ieee80211_key_sysfs_add_default(struct ieee80211_sub_if_data *sdata)
-{
- return sysfs_create_link(&sdata->key_kset.kobj,
- &sdata->default_key->kobj, "default");
-}
-
-void ieee80211_key_sysfs_remove_default(struct ieee80211_sub_if_data *sdata)
-{
- if (sdata->default_key)
- sysfs_remove_link(&sdata->key_kset.kobj, "default");
-}
diff --git a/net/mac80211/key_sysfs.h b/net/mac80211/key_sysfs.h
deleted file mode 100644
index 9ac9f2b..0000000
--- a/net/mac80211/key_sysfs.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __MAC80211_KEY_SYSFS_H
-#define __MAC80211_KEY_SYSFS_H
-
-int ieee80211_key_kset_sysfs_register(struct ieee80211_sub_if_data *sdata);
-void ieee80211_key_kset_sysfs_unregister(struct ieee80211_sub_if_data *sdata);
-void ieee80211_key_sysfs_set_kset(struct ieee80211_key *key, struct kset *kset);
-int ieee80211_key_sysfs_add(struct ieee80211_key *key);
-void ieee80211_key_sysfs_remove(struct ieee80211_key *key);
-int ieee80211_key_sysfs_add_default(struct ieee80211_sub_if_data *sdata);
-void ieee80211_key_sysfs_remove_default(struct ieee80211_sub_if_data *sdata);
-
-#endif /* __MAC80211_KEY_SYSFS_H */
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 37d83eb..dfbd369 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -18,7 +18,7 @@ #include <net/mac80211.h>
#include "ieee80211_i.h"
#include "ieee80211_rate.h"
#include "sta_info.h"
-#include "key_sysfs.h"
+#include "debugfs_key.h"
#include "debugfs_sta.h"

/* Caller must hold local->sta_lock */
@@ -121,6 +121,8 @@ void sta_info_release(struct kref *kref)
}
rate_control_free_sta(sta->rate_ctrl, sta->rate_ctrl_priv);
rate_control_put(sta->rate_ctrl);
+ if (sta->key)
+ ieee80211_debugfs_key_sta_del(sta->key, sta);
kfree(sta);
}

@@ -197,7 +199,7 @@ #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */

if (sta->key) {
- ieee80211_key_sysfs_remove(sta->key);
+ ieee80211_debugfs_key_remove(sta->key);
ieee80211_key_free(sta->key);
sta->key = NULL;
}
--
1.3.0


2007-03-23 20:43:45

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 18/19] mac80211: Prevent unregistering of unregistered hw

From: Ivo van Doorn <[email protected]>

At the moment it is possible to call ieee80211_unregister_hw()
for an unregistered hw structure. This will cause a big panic.
This patch will add a BUG_ON() line to warn about this situation.

Signed-off-by: Ivo van Doorn <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)

a6d266e59dd7d2f2c4bc439d47f21cf92d6df949
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index fb2ce3d..39468b8 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -4732,6 +4732,9 @@ void ieee80211_unregister_hw(struct ieee
tasklet_kill(&local->tasklet);

rtnl_lock();
+
+ BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
+
local->reg_state = IEEE80211_DEV_UNREGISTERED;
if (local->apdev)
ieee80211_if_del_mgmt(local);
--
1.3.0


2007-03-23 20:43:27

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 1/19] mac80211: drop packets from nonexisting interfaces in PS mode

In a power saving mode, packets queued by devices that meanwhile disappeared
has to be discarded.

Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 46 +++++++++++++++++++++++++---------------------
1 files changed, 25 insertions(+), 21 deletions(-)

c5ba64d9fc39c42ebc1ed38993dd6d3281708b8a
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 577dbe3..3d4fabe 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -1100,10 +1100,10 @@ static int inline is_ieee80211_device(st

/* Device in tx->dev has a reference added; use dev_put(tx->dev) when
* finished with it. */
-static void inline ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
- struct sk_buff *skb,
- struct net_device *mdev,
- struct ieee80211_tx_control *control)
+static int inline ieee80211_tx_prepare(struct ieee80211_txrx_data *tx,
+ struct sk_buff *skb,
+ struct net_device *mdev,
+ struct ieee80211_tx_control *control)
{
struct ieee80211_tx_packet_data *pkt_data;
struct net_device *dev;
@@ -1114,13 +1114,10 @@ static void inline ieee80211_tx_prepare(
dev_put(dev);
dev = NULL;
}
- if (unlikely(!dev)) {
- printk(KERN_WARNING "%s: NULL ifindex in pkt_data\n",
- mdev->name);
- dev = mdev;
- dev_hold(dev);
- }
+ if (unlikely(!dev))
+ return -ENODEV;
__ieee80211_tx_prepare(tx, skb, dev, control);
+ return 0;
}

static inline int __ieee80211_queue_stopped(const struct ieee80211_local *local,
@@ -1915,20 +1912,27 @@ ieee80211_get_buffered_bc(struct ieee802

if (bss->dtim_count != 0)
return NULL; /* send buffered bc/mc only after DTIM beacon */
- skb = skb_dequeue(&bss->ps_bc_buf);
memset(control, 0, sizeof(*control));
- if (!skb)
- return NULL;
- local->total_ps_buffered--;
+ while (1) {
+ skb = skb_dequeue(&bss->ps_bc_buf);
+ if (!skb)
+ return NULL;
+ local->total_ps_buffered--;

- if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- /* more buffered multicast/broadcast frames ==> set MoreData
- * flag in IEEE 802.11 header to inform PS STAs */
- hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
- }
+ if (!skb_queue_empty(&bss->ps_bc_buf) && skb->len >= 2) {
+ struct ieee80211_hdr *hdr =
+ (struct ieee80211_hdr *) skb->data;
+ /* more buffered multicast/broadcast frames ==> set
+ * MoreData flag in IEEE 802.11 header to inform PS
+ * STAs */
+ hdr->frame_control |=
+ cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ }

- ieee80211_tx_prepare(&tx, skb, local->mdev, control);
+ if (ieee80211_tx_prepare(&tx, skb, local->mdev, control) == 0)
+ break;
+ dev_kfree_skb_any(skb);
+ }
sta = tx.sta;
tx.u.tx.ps_buffered = 1;

--
1.3.0


2007-03-23 20:43:30

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 4/19] mac80211: Remove curr_rates and fix related concurrency issues

From: Michael Wu <[email protected]>

This switches the code from curr_rates and num_curr_rates to directly using
the mode and converts portions of the code to use pointers to rates instead
of indices to refer to rates. Two new fields are introduced in struct
ieee80211_conf which may replace the channel/frequency/channel_val/phymode
fields in the future. The rate control is now cleared only when the
operating channel is changed.

Signed-off-by: Michael Wu <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

include/net/mac80211.h | 7 ++
net/mac80211/ieee80211.c | 101 +++++++++++++++++-------------------
net/mac80211/ieee80211_i.h | 10 +---
net/mac80211/ieee80211_ioctl.c | 52 +++++++++++--------
net/mac80211/ieee80211_rate.h | 3 -
net/mac80211/ieee80211_scan.c | 2 -
net/mac80211/ieee80211_sta.c | 64 +++++++++++++----------
net/mac80211/ieee80211_sysfs_sta.c | 5 +-
net/mac80211/rc80211_simple.c | 57 +++++++++++---------
net/mac80211/sta_info.c | 4 +
10 files changed, 166 insertions(+), 139 deletions(-)

6daea49d5cb784819a81946260823c12129f1537
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 82ea43f..916b21b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -204,8 +204,9 @@ #define IEEE80211_TXCTL_TKIP_NEW_PHASE1_
u8 sw_retry_attempt; /* number of times hw has tried to
* transmit frame (not incl. hw retries) */

- int rateidx; /* internal 80211.o rateidx */
- int rts_rateidx; /* internal 80211.o rateidx for RTS/CTS */
+ struct ieee80211_rate *rate; /* internal 80211.o rate */
+ struct ieee80211_rate *rts_rate; /* internal 80211.o rate
+ * for RTS/CTS */
int alt_retry_rate; /* retry rate for the last retries, given as the
* hw specific value for the rate (from
* struct ieee80211_rate). To be used to limit
@@ -267,6 +268,8 @@ struct ieee80211_conf {
int channel_val; /* hw specific value for the channel */

int phymode; /* MODE_IEEE80211A, .. */
+ struct ieee80211_channel *chan;
+ struct ieee80211_hw_mode *mode;
unsigned int regulatory_domain;
int radio_enabled;

diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 9d95250..f3fc96b 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -133,19 +133,19 @@ static int rate_list_match(const int *ra
}


-void ieee80211_prepare_rates(struct ieee80211_local *local)
+void ieee80211_prepare_rates(struct ieee80211_local *local,
+ struct ieee80211_hw_mode *mode)
{
int i;

- for (i = 0; i < local->num_curr_rates; i++) {
- struct ieee80211_rate *rate = &local->curr_rates[i];
+ for (i = 0; i < mode->num_rates; i++) {
+ struct ieee80211_rate *rate = &mode->rates[i];

rate->flags &= ~(IEEE80211_RATE_SUPPORTED |
IEEE80211_RATE_BASIC);

- if (local->supp_rates[local->hw.conf.phymode]) {
- if (!rate_list_match(local->supp_rates
- [local->hw.conf.phymode],
+ if (local->supp_rates[mode->mode]) {
+ if (!rate_list_match(local->supp_rates[mode->mode],
rate->rate))
continue;
}
@@ -154,12 +154,11 @@ void ieee80211_prepare_rates(struct ieee

/* Use configured basic rate set if it is available. If not,
* use defaults that are sane for most cases. */
- if (local->basic_rates[local->hw.conf.phymode]) {
- if (rate_list_match(local->basic_rates
- [local->hw.conf.phymode],
+ if (local->basic_rates[mode->mode]) {
+ if (rate_list_match(local->basic_rates[mode->mode],
rate->rate))
rate->flags |= IEEE80211_RATE_BASIC;
- } else switch (local->hw.conf.phymode) {
+ } else switch (mode->mode) {
case MODE_IEEE80211A:
if (rate->rate == 60 || rate->rate == 120 ||
rate->rate == 240)
@@ -182,7 +181,7 @@ void ieee80211_prepare_rates(struct ieee
}

/* Set ERP and MANDATORY flags based on phymode */
- switch (local->hw.conf.phymode) {
+ switch (mode->mode) {
case MODE_IEEE80211A:
if (rate->rate == 60 || rate->rate == 120 ||
rate->rate == 240)
@@ -358,11 +357,10 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
struct rate_control_extra extra;

memset(&extra, 0, sizeof(extra));
+ extra.mode = tx->u.tx.mode;
extra.mgmt_data = tx->sdata &&
tx->sdata->type == IEEE80211_IF_TYPE_MGMT;
extra.ethertype = tx->ethertype;
- extra.startidx = 0;
- extra.endidx = tx->local->num_curr_rates;

tx->u.tx.rate = rate_control_get_rate(tx->local, tx->dev, tx->skb,
&extra);
@@ -376,20 +374,18 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021
}
if (!tx->u.tx.rate)
return TXRX_DROP;
- if (tx->local->hw.conf.phymode == MODE_IEEE80211G &&
+ if (tx->u.tx.mode->mode == MODE_IEEE80211G &&
tx->local->cts_protect_erp_frames && tx->fragmented &&
extra.nonerp) {
tx->u.tx.last_frag_rate = tx->u.tx.rate;
- tx->u.tx.last_frag_rateidx = extra.rateidx;
tx->u.tx.probe_last_frag = extra.probe ? 1 : 0;

tx->u.tx.rate = extra.nonerp;
- tx->u.tx.control->rateidx = extra.nonerp_idx;
+ tx->u.tx.control->rate = extra.nonerp;
tx->u.tx.control->flags &= ~IEEE80211_TXCTL_RATE_CTRL_PROBE;
} else {
tx->u.tx.last_frag_rate = tx->u.tx.rate;
- tx->u.tx.last_frag_rateidx = extra.rateidx;
- tx->u.tx.control->rateidx = extra.rateidx;
+ tx->u.tx.control->rate = tx->u.tx.rate;
}
tx->u.tx.control->tx_rate = tx->u.tx.rate->val;
if ((tx->u.tx.rate->flags & IEEE80211_RATE_PREAMBLE2) &&
@@ -657,6 +653,7 @@ static u16 ieee80211_duration(struct iee
int rate, mrate, erp, dur, i;
struct ieee80211_rate *txrate = tx->u.tx.rate;
struct ieee80211_local *local = tx->local;
+ struct ieee80211_hw_mode *mode = tx->u.tx.mode;

erp = txrate->flags & IEEE80211_RATE_ERP;

@@ -715,8 +712,8 @@ static u16 ieee80211_duration(struct iee
*/
rate = -1;
mrate = 10; /* use 1 Mbps if everything fails */
- for (i = 0; i < local->num_curr_rates; i++) {
- struct ieee80211_rate *r = &local->curr_rates[i];
+ for (i = 0; i < mode->num_rates; i++) {
+ struct ieee80211_rate *r = &mode->rates[i];
if (r->rate > txrate->rate)
break;

@@ -762,6 +759,7 @@ ieee80211_tx_h_misc(struct ieee80211_txr
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data;
u16 dur;
struct ieee80211_tx_control *control = tx->u.tx.control;
+ struct ieee80211_hw_mode *mode = tx->u.tx.mode;

if (!is_multicast_ether_addr(hdr->addr1)) {
if (tx->skb->len + FCS_LEN > tx->local->rts_threshold &&
@@ -788,7 +786,7 @@ ieee80211_tx_h_misc(struct ieee80211_txr
/* Use CTS protection for unicast frames sent using extended rates if
* there are associated non-ERP stations and RTS/CTS is not configured
* for the frame. */
- if (tx->local->hw.conf.phymode == MODE_IEEE80211G &&
+ if (mode->mode == MODE_IEEE80211G &&
(tx->u.tx.rate->flags & IEEE80211_RATE_ERP) &&
tx->u.tx.unicast &&
tx->local->cts_protect_erp_frames &&
@@ -812,12 +810,12 @@ ieee80211_tx_h_misc(struct ieee80211_txr

/* Use min(data rate, max base rate) as CTS/RTS rate */
rate = tx->u.tx.rate;
- while (rate > tx->local->curr_rates &&
+ while (rate > mode->rates &&
!(rate->flags & IEEE80211_RATE_BASIC))
rate--;

control->rts_cts_rate = rate->val;
- control->rts_rateidx = (int)(rate - tx->local->curr_rates);
+ control->rts_rate = rate;
}

if (tx->sta) {
@@ -1161,7 +1159,7 @@ static int __ieee80211_tx(struct ieee802
return IEEE80211_TX_FRAG_AGAIN;
if (i == tx->u.tx.num_extra_frag) {
control->tx_rate = tx->u.tx.last_frag_hwrate;
- control->rateidx = tx->u.tx.last_frag_rateidx;
+ control->rate = tx->u.tx.last_frag_rate;
if (tx->u.tx.probe_last_frag)
control->flags |=
IEEE80211_TXCTL_RATE_CTRL_PROBE;
@@ -1206,6 +1204,7 @@ static int ieee80211_tx(struct net_devic
__ieee80211_tx_prepare(&tx, skb, dev, control);
sta = tx.sta;
tx.u.tx.mgmt_interface = mgmt;
+ tx.u.tx.mode = local->hw.conf.mode;

for (handler = local->tx_handlers; *handler != NULL; handler++) {
res = (*handler)(&tx);
@@ -1278,7 +1277,7 @@ retry:
store->extra_frag = tx.u.tx.extra_frag;
store->num_extra_frag = tx.u.tx.num_extra_frag;
store->last_frag_hwrate = tx.u.tx.last_frag_hwrate;
- store->last_frag_rateidx = tx.u.tx.last_frag_rateidx;
+ store->last_frag_rate = tx.u.tx.last_frag_rate;
store->last_frag_rate_ctrl_probe = tx.u.tx.probe_last_frag;
}
return 0;
@@ -1314,7 +1313,7 @@ static void ieee80211_tx_pending(unsigne
tx.u.tx.extra_frag = store->extra_frag;
tx.u.tx.num_extra_frag = store->num_extra_frag;
tx.u.tx.last_frag_hwrate = store->last_frag_hwrate;
- tx.u.tx.last_frag_rateidx = store->last_frag_rateidx;
+ tx.u.tx.last_frag_rate = store->last_frag_rate;
tx.u.tx.probe_last_frag = store->last_frag_rate_ctrl_probe;
ret = __ieee80211_tx(local, store->skb, &tx);
if (ret) {
@@ -1775,7 +1774,7 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG

if (control) {
memset(&extra, 0, sizeof(extra));
- extra.endidx = local->num_curr_rates;
+ extra.mode = local->oper_hw_mode;

rate = rate_control_get_rate(local, local->mdev, skb, &extra);
if (!rate) {
@@ -1812,7 +1811,7 @@ __le16 ieee80211_rts_duration(struct iee
int erp;
u16 dur;

- rate = &(local->curr_rates[frame_txctl->rts_rateidx]);
+ rate = frame_txctl->rts_rate;
erp = !!(rate->flags & IEEE80211_RATE_ERP);

/* CTS duration */
@@ -1840,7 +1839,7 @@ __le16 ieee80211_ctstoself_duration(stru
int erp;
u16 dur;

- rate = &(local->curr_rates[frame_txctl->rts_rateidx]);
+ rate = frame_txctl->rts_rate;
erp = !!(rate->flags & IEEE80211_RATE_ERP);

/* Data frame duration */
@@ -2031,6 +2030,8 @@ int ieee80211_hw_config(struct ieee80211
local->hw.conf.freq = chan->freq;
local->hw.conf.phymode = mode->mode;
local->hw.conf.antenna_max = chan->antenna_max;
+ local->hw.conf.chan = chan;
+ local->hw.conf.mode = mode;

#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
printk(KERN_DEBUG "HW CONFIG: channel=%d freq=%d "
@@ -2041,12 +2042,6 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG
if (local->ops->config)
ret = local->ops->config(local_to_hw(local), &local->hw.conf);

- if (local->curr_rates != mode->rates)
- rate_control_clear(local);
- local->curr_rates = mode->rates;
- local->num_curr_rates = mode->num_rates;
- ieee80211_prepare_rates(local);
-
return ret;
}

@@ -3897,6 +3892,7 @@ static ieee80211_txrx_result
ieee80211_tx_h_load_stats(struct ieee80211_txrx_data *tx)
{
struct ieee80211_local *local = tx->local;
+ struct ieee80211_hw_mode *mode = tx->u.tx.mode;
struct sk_buff *skb = tx->skb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
u32 load = 0, hdrtime;
@@ -3910,10 +3906,10 @@ ieee80211_tx_h_load_stats(struct ieee802
/* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
* 1 usec = 1/8 * (1080 / 10) = 13.5 */

- if (local->hw.conf.phymode == MODE_IEEE80211A ||
- local->hw.conf.phymode == MODE_ATHEROS_TURBO ||
- local->hw.conf.phymode == MODE_ATHEROS_TURBOG ||
- (local->hw.conf.phymode == MODE_IEEE80211G &&
+ if (mode->mode == MODE_IEEE80211A ||
+ mode->mode == MODE_ATHEROS_TURBO ||
+ mode->mode == MODE_ATHEROS_TURBOG ||
+ (mode->mode == MODE_IEEE80211G &&
tx->u.tx.rate->flags & IEEE80211_RATE_ERP))
hdrtime = CHAN_UTIL_HDR_SHORT;
else
@@ -3958,17 +3954,18 @@ ieee80211_rx_h_load_stats(struct ieee802
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
u32 load = 0, hdrtime;
struct ieee80211_rate *rate;
+ struct ieee80211_hw_mode *mode = local->hw.conf.mode;
int i;

/* Estimate total channel use caused by this frame */

- if (unlikely(local->num_curr_rates < 0))
+ if (unlikely(mode->num_rates < 0))
return TXRX_CONTINUE;

- rate = &local->curr_rates[0];
- for (i = 0; i < local->num_curr_rates; i++) {
- if (local->curr_rates[i].val == rx->u.rx.status->rate) {
- rate = &local->curr_rates[i];
+ rate = &mode->rates[0];
+ for (i = 0; i < mode->num_rates; i++) {
+ if (mode->rates[i].val == rx->u.rx.status->rate) {
+ rate = &mode->rates[i];
break;
}
}
@@ -3976,10 +3973,10 @@ ieee80211_rx_h_load_stats(struct ieee802
/* 1 bit at 1 Mbit/s takes 1 usec; in channel_use values,
* 1 usec = 1/8 * (1080 / 10) = 13.5 */

- if (local->hw.conf.phymode == MODE_IEEE80211A ||
- local->hw.conf.phymode == MODE_ATHEROS_TURBO ||
- local->hw.conf.phymode == MODE_ATHEROS_TURBOG ||
- (local->hw.conf.phymode == MODE_IEEE80211G &&
+ if (mode->mode == MODE_IEEE80211A ||
+ mode->mode == MODE_ATHEROS_TURBO ||
+ mode->mode == MODE_ATHEROS_TURBOG ||
+ (mode->mode == MODE_IEEE80211G &&
rate->flags & IEEE80211_RATE_ERP))
hdrtime = CHAN_UTIL_HDR_SHORT;
else
@@ -4734,15 +4731,15 @@ int ieee80211_register_hwmode(struct iee
rate = &(mode->rates[i]);
rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate;
}
+ ieee80211_prepare_rates(local, mode);

- if (!local->curr_rates) {
+ if (!local->oper_hw_mode) {
/* Default to this mode */
local->hw.conf.phymode = mode->mode;
local->oper_hw_mode = local->scan_hw_mode = mode;
local->oper_channel = local->scan_channel = &mode->channels[0];
- local->curr_rates = mode->rates;
- local->num_curr_rates = mode->num_rates;
- ieee80211_prepare_rates(local);
+ local->hw.conf.mode = local->oper_hw_mode;
+ local->hw.conf.chan = local->oper_channel;
}

ieee80211_init_client(local->mdev);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4398453..cf37ce6 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -123,12 +123,12 @@ struct ieee80211_txrx_data {
unsigned int ps_buffered:1;
unsigned int short_preamble:1;
unsigned int probe_last_frag:1;
+ struct ieee80211_hw_mode *mode;
struct ieee80211_rate *rate;
/* use this rate (if set) for last fragment; rate can
* be set to lower rate for the first fragments, e.g.,
* when using CTS protection with IEEE 802.11g. */
struct ieee80211_rate *last_frag_rate;
- int last_frag_rateidx;
int last_frag_hwrate;
int mgmt_interface;

@@ -171,6 +171,7 @@ struct ieee80211_tx_stored_packet {
struct sk_buff **extra_frag;
int last_frag_rateidx;
int last_frag_hwrate;
+ struct ieee80211_rate *last_frag_rate;
unsigned int last_frag_rate_ctrl_probe:1;
};

@@ -396,10 +397,6 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
int iff_allmultis, iff_promiscs;
/* number of interfaces with corresponding IFF_ flags */

- /* Current rate table. This is a pointer to hw->modes structure. */
- struct ieee80211_rate *curr_rates;
- int num_curr_rates;
-
struct rate_control_ref *rate_ctrl;

int next_mode; /* MODE_IEEE80211*
@@ -614,7 +611,8 @@ void ieee80211_key_free(struct ieee80211
void ieee80211_key_release(struct kobject *kobj);
void ieee80211_rx_mgmt(struct ieee80211_local *local, struct sk_buff *skb,
struct ieee80211_rx_status *status, u32 msg_type);
-void ieee80211_prepare_rates(struct ieee80211_local *local);
+void ieee80211_prepare_rates(struct ieee80211_local *local,
+ struct ieee80211_hw_mode *mode);
void ieee80211_tx_set_iswep(struct ieee80211_txrx_data *tx);
int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
void ieee80211_if_setup(struct net_device *dev);
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 93a204b..3ba8dee 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -269,6 +269,7 @@ static int ieee80211_ioctl_add_sta(struc
u32 rates;
int i, j;
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_hw_mode *mode;
int add_key_entry = 1;

/* Prevent a race with changing the rate control algorithm */
@@ -306,13 +307,14 @@ static int ieee80211_ioctl_add_sta(struc
sta->listen_interval = param->u.add_sta.listen_interval;

rates = 0;
+ mode = local->oper_hw_mode;
for (i = 0; i < sizeof(param->u.add_sta.supp_rates); i++) {
int rate = (param->u.add_sta.supp_rates[i] & 0x7f) * 5;
- if (local->hw.conf.phymode == MODE_ATHEROS_TURBO ||
- local->hw.conf.phymode == MODE_ATHEROS_TURBOG)
+ if (mode->mode == MODE_ATHEROS_TURBO ||
+ mode->mode == MODE_ATHEROS_TURBOG)
rate *= 2;
- for (j = 0; j < local->num_curr_rates; j++) {
- if (local->curr_rates[j].rate == rate)
+ for (j = 0; j < mode->num_rates; j++) {
+ if (mode->rates[j].rate == rate)
rates |= BIT(j);
}

@@ -405,6 +407,7 @@ static int ieee80211_ioctl_get_info_sta(
struct prism2_hostapd_param *param)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_hw_mode *mode;
struct sta_info *sta;

if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
@@ -417,7 +420,7 @@ static int ieee80211_ioctl_get_info_sta(
param->u.get_info_sta.tx_bytes = stats->tx_bytes;
/* go through all STAs and get STA with lowest max. rate */
param->u.get_info_sta.current_tx_rate =
- local->curr_rates[sta_info_min_txrate_get(local)].rate;
+ sta_info_min_txrate_get(local);
return 0;
}

@@ -434,9 +437,10 @@ static int ieee80211_ioctl_get_info_sta(
param->u.get_info_sta.tx_bytes = sta->tx_bytes;
param->u.get_info_sta.channel_use = sta->channel_use;
param->u.get_info_sta.flags = sta->flags;
- if (sta->txrate >= 0 && sta->txrate < local->num_curr_rates)
+ mode = local->oper_hw_mode;
+ if (sta->txrate >= 0 && sta->txrate < mode->num_rates)
param->u.get_info_sta.current_tx_rate =
- local->curr_rates[sta->txrate].rate;
+ mode->rates[sta->txrate].rate;
param->u.get_info_sta.num_ps_buf_frames =
skb_queue_len(&sta->ps_tx_buf);
param->u.get_info_sta.tx_retry_failed = sta->tx_retry_failed;
@@ -936,6 +940,7 @@ static int ieee80211_ioctl_set_rate_sets
u16 *pos = (u16 *) param->u.set_rate_sets.data;
int left = param_len - ((u8 *) pos - (u8 *) param);
int i, mode, num_supp, num_basic, *supp, *basic, *prev;
+ struct ieee80211_hw_mode *hw_mode;

mode = param->u.set_rate_sets.mode;
num_supp = param->u.set_rate_sets.num_supported_rates;
@@ -983,12 +988,12 @@ static int ieee80211_ioctl_set_rate_sets
local->basic_rates[mode] = basic;
kfree(prev);

- if (mode == local->hw.conf.phymode) {
- /* TODO: should update STA TX rates and remove STAs if they
- * do not have any remaining supported rates after the change
- */
- ieee80211_prepare_rates(local);
- }
+ /* TODO: should update STA TX rates and remove STAs if they
+ * do not have any remaining supported rates after the change
+ */
+ list_for_each_entry(hw_mode, &local->modes_list, list)
+ if (hw_mode->mode == mode)
+ ieee80211_prepare_rates(local, hw_mode);

return 0;
}
@@ -1805,6 +1810,7 @@ int ieee80211_set_channel(struct ieee802
{
struct ieee80211_hw_mode *mode;
int c, set = 0;
+ int ret = -EINVAL;

list_for_each_entry(mode, &local->modes_list, list) {
if (!(local->enabled_modes & (1 << mode->mode)))
@@ -1827,12 +1833,14 @@ int ieee80211_set_channel(struct ieee802

if (set) {
if (local->sta_scanning)
- return 0;
+ ret = 0;
else
- return ieee80211_hw_config(local);
+ ret = ieee80211_hw_config(local);
+
+ rate_control_clear(local);
}

- return -EINVAL;
+ return ret;
}

static int ieee80211_ioctl_siwfreq(struct net_device *dev,
@@ -2283,6 +2291,7 @@ ieee80211_ioctl_force_unicast_rate(struc
int rate)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_hw_mode *mode;
int i;

if (sdata->type != IEEE80211_IF_TYPE_AP)
@@ -2293,8 +2302,9 @@ ieee80211_ioctl_force_unicast_rate(struc
return 0;
}

- for (i = 0; i < local->num_curr_rates; i++) {
- if (local->curr_rates[i].rate == rate) {
+ mode = local->oper_hw_mode;
+ for (i = 0; i < mode->num_rates; i++) {
+ if (mode->rates[i].rate == rate) {
sdata->u.ap.force_unicast_rateidx = i;
return 0;
}
@@ -2309,6 +2319,7 @@ ieee80211_ioctl_max_ratectrl_rate(struct
int rate)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_hw_mode *mode;
int i;

if (sdata->type != IEEE80211_IF_TYPE_AP)
@@ -2319,8 +2330,9 @@ ieee80211_ioctl_max_ratectrl_rate(struct
return 0;
}

- for (i = 0; i < local->num_curr_rates; i++) {
- if (local->curr_rates[i].rate == rate) {
+ mode = local->oper_hw_mode;
+ for (i = 0; i < mode->num_rates; i++) {
+ if (mode->rates[i].rate == rate) {
sdata->u.ap.max_ratectrl_rateidx = i;
return 0;
}
diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h
index 3f51594..3bb09f2 100644
--- a/net/mac80211/ieee80211_rate.h
+++ b/net/mac80211/ieee80211_rate.h
@@ -26,11 +26,10 @@ struct rate_control_extra {
/* values from rate_control_get_rate() to the caller: */
struct ieee80211_rate *probe; /* probe with this rate, or NULL for no
* probing */
- int startidx, endidx, rateidx;
struct ieee80211_rate *nonerp;
- int nonerp_idx;

/* parameters from the caller to rate_control_get_rate(): */
+ struct ieee80211_hw_mode *mode;
int mgmt_data; /* this is data frame that is used for management
* (e.g., IEEE 802.1X EAPOL) */
u16 ethertype;
diff --git a/net/mac80211/ieee80211_scan.c b/net/mac80211/ieee80211_scan.c
index f9b42d4..07f8d9a 100644
--- a/net/mac80211/ieee80211_scan.c
+++ b/net/mac80211/ieee80211_scan.c
@@ -326,7 +326,7 @@ void ieee80211_init_scan(struct ieee8021
local->scan.tx_control.key_idx = HW_KEY_IDX_INVALID;
local->scan.tx_control.flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT;
memset(&extra, 0, sizeof(extra));
- extra.endidx = local->num_curr_rates;
+ extra.mode = local->hw.conf.mode;
local->scan.tx_control.tx_rate =
rate_control_get_rate(local, local->mdev,
local->scan.skb, &extra)->val;
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 44646be..a264008 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -480,6 +480,7 @@ static void ieee80211_send_assoc(struct
struct ieee80211_if_sta *ifsta)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_hw_mode *mode;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u8 *pos, *ies;
@@ -498,8 +499,9 @@ static void ieee80211_send_assoc(struct
}
skb_reserve(skb, local->hw.extra_tx_headroom);

+ mode = local->oper_hw_mode;
capab = ifsta->capab;
- if (local->hw.conf.phymode == MODE_IEEE80211G) {
+ if (mode->mode == MODE_IEEE80211G) {
capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
WLAN_CAPABILITY_SHORT_PREAMBLE;
}
@@ -541,26 +543,26 @@ static void ieee80211_send_assoc(struct
*pos++ = ifsta->ssid_len;
memcpy(pos, ifsta->ssid, ifsta->ssid_len);

- len = local->num_curr_rates;
+ len = mode->num_rates;
if (len > 8)
len = 8;
pos = skb_put(skb, len + 2);
*pos++ = WLAN_EID_SUPP_RATES;
*pos++ = len;
for (i = 0; i < len; i++) {
- int rate = local->curr_rates[i].rate;
- if (local->hw.conf.phymode == MODE_ATHEROS_TURBO)
+ int rate = mode->rates[i].rate;
+ if (mode->mode == MODE_ATHEROS_TURBO)
rate /= 2;
*pos++ = (u8) (rate / 5);
}

- if (local->num_curr_rates > len) {
- pos = skb_put(skb, local->num_curr_rates - len + 2);
+ if (mode->num_rates > len) {
+ pos = skb_put(skb, mode->num_rates - len + 2);
*pos++ = WLAN_EID_EXT_SUPP_RATES;
- *pos++ = local->num_curr_rates - len;
- for (i = len; i < local->num_curr_rates; i++) {
- int rate = local->curr_rates[i].rate;
- if (local->hw.conf.phymode == MODE_ATHEROS_TURBO)
+ *pos++ = mode->num_rates - len;
+ for (i = len; i < mode->num_rates; i++) {
+ int rate = mode->rates[i].rate;
+ if (mode->mode == MODE_ATHEROS_TURBO)
rate /= 2;
*pos++ = (u8) (rate / 5);
}
@@ -771,6 +773,7 @@ static void ieee80211_send_probe_req(str
u8 *ssid, size_t ssid_len)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_hw_mode *mode;
struct sk_buff *skb;
struct ieee80211_mgmt *mgmt;
u8 *pos, *supp_rates, *esupp_rates = NULL;
@@ -804,8 +807,9 @@ static void ieee80211_send_probe_req(str
supp_rates = skb_put(skb, 2);
supp_rates[0] = WLAN_EID_SUPP_RATES;
supp_rates[1] = 0;
- for (i = 0; i < local->num_curr_rates; i++) {
- struct ieee80211_rate *rate = &local->curr_rates[i];
+ mode = local->oper_hw_mode;
+ for (i = 0; i < mode->num_rates; i++) {
+ struct ieee80211_rate *rate = &mode->rates[i];
if (!(rate->flags & IEEE80211_RATE_SUPPORTED))
continue;
if (esupp_rates) {
@@ -820,7 +824,7 @@ static void ieee80211_send_probe_req(str
pos = skb_put(skb, 1);
supp_rates[1]++;
}
- if (local->hw.conf.phymode == MODE_ATHEROS_TURBO)
+ if (mode->mode == MODE_ATHEROS_TURBO)
*pos = rate->rate / 10;
else
*pos = rate->rate / 5;
@@ -1096,6 +1100,7 @@ static void ieee80211_rx_mgmt_assoc_resp
int reassoc)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_hw_mode *mode;
struct sta_info *sta;
u32 rates;
u16 capab_info, status_code, aid;
@@ -1197,20 +1202,21 @@ static void ieee80211_rx_mgmt_assoc_resp
sta->assoc_ap = 1;

rates = 0;
+ mode = local->oper_hw_mode;
for (i = 0; i < elems.supp_rates_len; i++) {
int rate = (elems.supp_rates[i] & 0x7f) * 5;
- if (local->hw.conf.phymode == MODE_ATHEROS_TURBO)
+ if (mode->mode == MODE_ATHEROS_TURBO)
rate *= 2;
- for (j = 0; j < local->num_curr_rates; j++)
- if (local->curr_rates[j].rate == rate)
+ for (j = 0; j < mode->num_rates; j++)
+ if (mode->rates[j].rate == rate)
rates |= BIT(j);
}
for (i = 0; i < elems.ext_supp_rates_len; i++) {
int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
- if (local->hw.conf.phymode == MODE_ATHEROS_TURBO)
+ if (mode->mode == MODE_ATHEROS_TURBO)
rate *= 2;
- for (j = 0; j < local->num_curr_rates; j++)
- if (local->curr_rates[j].rate == rate)
+ for (j = 0; j < mode->num_rates; j++)
+ if (mode->rates[j].rate == rate)
rates |= BIT(j);
}
sta->supp_rates = rates;
@@ -2124,6 +2130,7 @@ static int ieee80211_sta_join_ibss(struc
struct ieee80211_mgmt *mgmt;
struct ieee80211_tx_control control;
struct ieee80211_rate *rate;
+ struct ieee80211_hw_mode *mode;
struct rate_control_extra extra;
u8 *pos;
struct ieee80211_sub_if_data *sdata;
@@ -2210,7 +2217,7 @@ static int ieee80211_sta_join_ibss(struc

memset(&control, 0, sizeof(control));
memset(&extra, 0, sizeof(extra));
- extra.endidx = local->num_curr_rates;
+ extra.mode = local->oper_hw_mode;
rate = rate_control_get_rate(local, dev, skb, &extra);
if (!rate) {
printk(KERN_DEBUG "%s: Failed to determine TX rate "
@@ -2246,12 +2253,13 @@ static int ieee80211_sta_join_ibss(struc
}

rates = 0;
+ mode = local->oper_hw_mode;
for (i = 0; i < bss->supp_rates_len; i++) {
int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
- if (local->hw.conf.phymode == MODE_ATHEROS_TURBO)
+ if (mode->mode == MODE_ATHEROS_TURBO)
bitrate *= 2;
- for (j = 0; j < local->num_curr_rates; j++)
- if (local->curr_rates[j].rate == bitrate)
+ for (j = 0; j < mode->num_rates; j++)
+ if (mode->rates[j].rate == bitrate)
rates |= BIT(j);
}
ifsta->supp_rates_bits = rates;
@@ -2278,6 +2286,7 @@ static int ieee80211_sta_create_ibss(str
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sta_bss *bss;
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_hw_mode *mode;
u8 bssid[ETH_ALEN], *pos;
int i;

@@ -2303,6 +2312,7 @@ #endif
return -ENOMEM;

sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ mode = local->oper_hw_mode;

if (local->hw.conf.beacon_int == 0)
local->hw.conf.beacon_int = 100;
@@ -2316,11 +2326,11 @@ #endif
bss->capability |= WLAN_CAPABILITY_PRIVACY;
} else
sdata->drop_unencrypted = 0;
- bss->supp_rates_len = local->num_curr_rates;
+ bss->supp_rates_len = mode->num_rates;
pos = bss->supp_rates;
- for (i = 0; i < local->num_curr_rates; i++) {
- int rate = local->curr_rates[i].rate;
- if (local->hw.conf.phymode == MODE_ATHEROS_TURBO)
+ for (i = 0; i < mode->num_rates; i++) {
+ int rate = mode->rates[i].rate;
+ if (mode->mode == MODE_ATHEROS_TURBO)
rate /= 2;
*pos++ = (u8) (rate / 5);
}
diff --git a/net/mac80211/ieee80211_sysfs_sta.c b/net/mac80211/ieee80211_sysfs_sta.c
index e3a6d32..ae62bcf 100644
--- a/net/mac80211/ieee80211_sysfs_sta.c
+++ b/net/mac80211/ieee80211_sysfs_sta.c
@@ -40,10 +40,11 @@ #define STA_SHOW_RATE(name, field) \
static ssize_t show_sta_##name(const struct sta_info *sta, char *buf) \
{ \
struct ieee80211_local *local = wdev_priv(sta->dev->ieee80211_ptr);\
+ struct ieee80211_hw_mode *mode = local->oper_hw_mode; \
return sprintf(buf, "%d\n", \
(sta->field >= 0 && \
- sta->field < local->num_curr_rates) ? \
- local->curr_rates[sta->field].rate : -1); \
+ sta->field < mode->num_rates) ? \
+ mode->rates[sta->field].rate : -1); \
}

#define __STA_ATTR(name) \
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
index 16bec51..1b5c82c 100644
--- a/net/mac80211/rc80211_simple.c
+++ b/net/mac80211/rc80211_simple.c
@@ -34,6 +34,7 @@ static void rate_control_rate_inc(struct
struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_hw_mode *mode;
int i = sta->txrate;
int maxrate;

@@ -43,15 +44,16 @@ static void rate_control_rate_inc(struct
return;
}

+ mode = local->oper_hw_mode;
maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1;

- if (i > local->num_curr_rates)
- i = local->num_curr_rates - 2;
+ if (i > mode->num_rates)
+ i = mode->num_rates - 2;

- while (i + 1 < local->num_curr_rates) {
+ while (i + 1 < mode->num_rates) {
i++;
if (sta->supp_rates & BIT(i) &&
- local->curr_rates[i].flags & IEEE80211_RATE_SUPPORTED &&
+ mode->rates[i].flags & IEEE80211_RATE_SUPPORTED &&
(maxrate < 0 || i <= maxrate)) {
sta->txrate = i;
break;
@@ -64,6 +66,7 @@ static void rate_control_rate_dec(struct
struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_hw_mode *mode;
int i = sta->txrate;

sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
@@ -72,13 +75,14 @@ static void rate_control_rate_dec(struct
return;
}

- if (i > local->num_curr_rates)
- i = local->num_curr_rates;
+ mode = local->oper_hw_mode;
+ if (i > mode->num_rates)
+ i = mode->num_rates;

while (i > 0) {
i--;
if (sta->supp_rates & BIT(i) &&
- local->curr_rates[i].flags & IEEE80211_RATE_SUPPORTED) {
+ mode->rates[i].flags & IEEE80211_RATE_SUPPORTED) {
sta->txrate = i;
break;
}
@@ -87,21 +91,21 @@ static void rate_control_rate_dec(struct


static struct ieee80211_rate *
-rate_control_lowest_rate(struct ieee80211_local *local)
+rate_control_lowest_rate(struct ieee80211_local *local,
+ struct ieee80211_hw_mode *mode)
{
int i;

- for (i = 0; i < local->num_curr_rates; i++) {
- struct ieee80211_rate *rate = &local->curr_rates[i];
+ for (i = 0; i < mode->num_rates; i++) {
+ struct ieee80211_rate *rate = &mode->rates[i];

- if (rate->flags & IEEE80211_RATE_SUPPORTED
- )
+ if (rate->flags & IEEE80211_RATE_SUPPORTED)
return rate;
}

printk(KERN_DEBUG "rate_control_lowest_rate - no supported rates "
"found\n");
- return &local->curr_rates[0];
+ return &mode->rates[0];
}


@@ -182,7 +186,7 @@ #endif
} else if (per_failed < local->rate_ctrl_num_up) {
rate_control_rate_inc(local, sta);
}
- srctrl->tx_avg_rate_sum += local->curr_rates[sta->txrate].rate;
+ srctrl->tx_avg_rate_sum += status->control.rate->rate;
srctrl->tx_avg_rate_num++;
srctrl->tx_num_failures = 0;
srctrl->tx_num_xmit = 0;
@@ -220,6 +224,7 @@ rate_control_simple_get_rate(void *priv,
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct ieee80211_sub_if_data *sdata;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_hw_mode *mode = extra->mode;
struct sta_info *sta;
int rateidx, nonerp_idx;
u16 fc;
@@ -232,13 +237,13 @@ rate_control_simple_get_rate(void *priv,
/* Send management frames and broadcast/multicast data using
* lowest rate. */
/* TODO: this could probably be improved.. */
- return rate_control_lowest_rate(local);
+ return rate_control_lowest_rate(local, mode);
}

sta = sta_info_get(local, hdr->addr1);

if (!sta)
- return rate_control_lowest_rate(local);
+ return rate_control_lowest_rate(local, mode);

sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
@@ -246,23 +251,21 @@ rate_control_simple_get_rate(void *priv,

rateidx = sta->txrate;

- if (rateidx >= local->num_curr_rates)
- rateidx = local->num_curr_rates - 1;
+ if (rateidx >= mode->num_rates)
+ rateidx = mode->num_rates - 1;

sta->last_txrate = rateidx;
nonerp_idx = rateidx;
while (nonerp_idx > 0 &&
- ((local->curr_rates[nonerp_idx].flags & IEEE80211_RATE_ERP) ||
- !(local->curr_rates[nonerp_idx].flags &
- IEEE80211_RATE_SUPPORTED) ||
+ ((mode->rates[nonerp_idx].flags & IEEE80211_RATE_ERP) ||
+ !(mode->rates[nonerp_idx].flags & IEEE80211_RATE_SUPPORTED) ||
!(sta->supp_rates & BIT(nonerp_idx))))
nonerp_idx--;
- extra->nonerp_idx = nonerp_idx;
- extra->nonerp = &local->curr_rates[extra->nonerp_idx];
+ extra->nonerp = &mode->rates[nonerp_idx];

sta_info_put(sta);

- return &local->curr_rates[rateidx];
+ return &mode->rates[rateidx];
}


@@ -270,15 +273,17 @@ static void rate_control_simple_rate_ini
struct ieee80211_local *local,
struct sta_info *sta)
{
+ struct ieee80211_hw_mode *mode;
int i;
sta->txrate = 0;
+ mode = local->oper_hw_mode;
/* TODO: what is a good starting rate for STA? About middle? Maybe not
* the lowest or the highest rate.. Could consider using RSSI from
* previous packets? Need to have IEEE 802.1X auth succeed immediately
* after assoc.. */
- for (i = 0; i < local->num_curr_rates; i++) {
+ for (i = 0; i < mode->num_rates; i++) {
if ((sta->supp_rates & BIT(i)) &&
- (local->curr_rates[i].flags & IEEE80211_RATE_SUPPORTED))
+ (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
sta->txrate = i;
}
}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 09554aa..2e258cf 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -80,10 +80,12 @@ EXPORT_SYMBOL(sta_info_get);
int sta_info_min_txrate_get(struct ieee80211_local *local)
{
struct sta_info *sta;
+ struct ieee80211_hw_mode *mode;
int min_txrate = 9999999;
int i;

spin_lock_bh(&local->sta_lock);
+ mode = local->oper_hw_mode;
for (i = 0; i < STA_HASH_SIZE; i++) {
sta = local->sta_hash[i];
while (sta) {
@@ -96,7 +98,7 @@ int sta_info_min_txrate_get(struct ieee8
if (min_txrate == 9999999)
min_txrate = 0;

- return min_txrate;
+ return mode->rates[min_txrate].rate;
}


--
1.3.0


2007-03-23 20:43:33

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 7/19] mac80211: Stop virtual interfaces during scan

From: Michael Wu <[email protected]>

This prevents data frames from being queued on the master device if it is
in the midst of a scan. It also makes both master and virtual interfaces
properly set trans_start when frames are sent. tx_queue_len is left as the
default on virtual interfaces to allow frames to be queued while the device
is scanning.

Signed-off-by: Michael Wu <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 5 +++--
net/mac80211/ieee80211_sta.c | 28 +++++++++++++++++++---------
2 files changed, 22 insertions(+), 11 deletions(-)

a24e7bbf06b53845f311f596203bc00e0564991d
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 30330b9..05c21d6 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -1145,6 +1145,7 @@ static int __ieee80211_tx(struct ieee802
ret = local->ops->tx(local_to_hw(local), skb, control);
if (ret)
return IEEE80211_TX_AGAIN;
+ local->mdev->trans_start = jiffies;
ieee80211_led_tx(local, 1);
}
if (tx->u.tx.extra_frag) {
@@ -1175,6 +1176,7 @@ static int __ieee80211_tx(struct ieee802
control);
if (ret)
return IEEE80211_TX_FRAG_AGAIN;
+ local->mdev->trans_start = jiffies;
ieee80211_led_tx(local, 1);
tx->u.tx.extra_frag[i] = NULL;
}
@@ -1585,6 +1587,7 @@ #endif
skb->nh.raw = skb->data + nh_pos;
skb->h.raw = skb->data + h_pos;

+ dev->trans_start = jiffies;
dev_queue_xmit(skb);

return 0;
@@ -4423,7 +4426,6 @@ void ieee80211_if_setup(struct net_devic
dev->get_stats = ieee80211_get_stats;
dev->open = ieee80211_open;
dev->stop = ieee80211_stop;
- dev->tx_queue_len = 0;
dev->uninit = ieee80211_if_reinit;
dev->destructor = ieee80211_if_free;
}
@@ -4438,7 +4440,6 @@ void ieee80211_if_mgmt_setup(struct net_
dev->stop = ieee80211_mgmt_stop;
dev->type = ARPHRD_IEEE80211_PRISM;
dev->hard_header_parse = header_parse_80211;
- dev->tx_queue_len = 0;
dev->uninit = ieee80211_if_reinit;
dev->destructor = ieee80211_if_free;
}
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 9d08a37..ce7dc28 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -1918,10 +1918,7 @@ void ieee80211_sta_work(struct work_stru
if (!netif_running(dev))
return;

- /* TODO: scan_dev check should be removed once scan_completed wakes
- * every STA interface */
- if (local->sta_scanning &&
- local->scan_dev == dev)
+ if (local->sta_scanning)
return;

sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -2527,7 +2524,7 @@ void ieee80211_scan_completed(struct iee
{
struct ieee80211_local *local = hw_to_local(hw);
struct net_device *dev = local->scan_dev;
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_sub_if_data *sdata;
union iwreq_data wrqu;

printk(KERN_DEBUG "%s: scan completed\n", dev->name);
@@ -2542,15 +2539,23 @@ void ieee80211_scan_completed(struct iee
memset(&wrqu, 0, sizeof(wrqu));
wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);

+ spin_lock_bh(&local->sub_if_lock);
+ list_for_each_entry(sdata, &local->sub_if_list, list) {
+ netif_wake_queue(sdata->dev);
+
+ if (sdata->type == IEEE80211_IF_TYPE_STA)
+ ieee80211_sta_timer((unsigned long)&sdata->u.sta);
+ }
+ spin_unlock_bh(&local->sub_if_lock);
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
if (!ifsta->bssid_set ||
(!ifsta->state == IEEE80211_IBSS_JOINED &&
!ieee80211_sta_active_ibss(dev)))
ieee80211_sta_find_ibss(dev, ifsta);
- /* TODO: need to wake every sta interface */
- } else if (sdata->type == IEEE80211_IF_TYPE_STA)
- ieee80211_sta_timer((unsigned long)&sdata->u.sta);
+ }
}
EXPORT_SYMBOL(ieee80211_scan_completed);

@@ -2637,6 +2642,7 @@ static int ieee80211_sta_start_scan(stru
u8 *ssid, size_t ssid_len)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_sub_if_data *sdata;

if (ssid_len > IEEE80211_MAX_SSID_LEN)
return -EINVAL;
@@ -2680,7 +2686,11 @@ static int ieee80211_sta_start_scan(stru
}

local->sta_scanning = 1;
- /* TODO: stop TX queue? */
+
+ spin_lock_bh(&local->sub_if_lock);
+ list_for_each_entry(sdata, &local->sub_if_list, list)
+ netif_stop_queue(sdata->dev);
+ spin_unlock_bh(&local->sub_if_lock);

if (ssid) {
local->scan_ssid_len = ssid_len;
--
1.3.0


2007-03-23 20:43:32

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 6/19] mac80211: Set carrier status for STA interfaces

From: Michael Wu <[email protected]>

This makes STA interfaces set the carrier status based on the current
association status.

Signed-off-by: Michael Wu <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 4 ++++
net/mac80211/ieee80211_sta.c | 3 +++
2 files changed, 7 insertions(+), 0 deletions(-)

22abe7f30c0e34ac94eda86e6aad66f74e582317
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 18caa2b..30330b9 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -2368,6 +2368,10 @@ static int ieee80211_open(struct net_dev
else
ieee80211_if_config(dev);

+ if (sdata->type == IEEE80211_IF_TYPE_STA &&
+ !local->user_space_mlme)
+ netif_carrier_off(dev);
+
netif_start_queue(dev);
return 0;
}
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index a264008..9d08a37 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -375,11 +375,13 @@ static void ieee80211_set_associated(str
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->type != IEEE80211_IF_TYPE_STA)
return;
+ netif_carrier_on(dev);
ifsta->prev_bssid_set = 1;
memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
ieee80211_sta_send_associnfo(dev, ifsta);
} else {
+ netif_carrier_off(dev);
memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
}
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
@@ -2007,6 +2009,7 @@ static void ieee80211_sta_reset_auth(str
ifsta->auth_alg);
ifsta->auth_transaction = -1;
ifsta->associated = ifsta->auth_tries = ifsta->assoc_tries = 0;
+ netif_carrier_off(dev);
}


--
1.3.0


2007-03-23 20:43:37

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 10/19] mac80211: move sta dir to debugfs

From: [email protected] <[email protected]>

This patch moves the "sta" dir to a new debugfs dir "stations".

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/Makefile | 4
net/mac80211/debugfs.c | 6
net/mac80211/debugfs.h | 1
net/mac80211/debugfs_sta.c | 242 ++++++++++++++++++++
net/mac80211/debugfs_sta.h | 12 +
net/mac80211/ieee80211.c | 1
net/mac80211/ieee80211_i.h | 15 -
net/mac80211/ieee80211_ioctl.c | 4
net/mac80211/ieee80211_rate.h | 29 +-
net/mac80211/ieee80211_sysfs.c | 1
net/mac80211/ieee80211_sysfs_sta.c | 439 ------------------------------------
net/mac80211/key_sysfs.c | 217 ++++++++++++++++++
net/mac80211/key_sysfs.h | 12 +
net/mac80211/rc80211_simple.c | 82 +++++--
net/mac80211/sta_info.c | 55 ++---
net/mac80211/sta_info.h | 18 +
16 files changed, 602 insertions(+), 536 deletions(-)
create mode 100644 net/mac80211/debugfs_sta.c
create mode 100644 net/mac80211/debugfs_sta.h
delete mode 100644 net/mac80211/ieee80211_sysfs_sta.c
create mode 100644 net/mac80211/key_sysfs.c
create mode 100644 net/mac80211/key_sysfs.h

06c54cc07ddcf8a2fcaa247f8c72c6a3c183d2bd
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 17c09d6..8c00960 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -1,7 +1,7 @@
obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o

mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
-mac80211-objs-$(CONFIG_DEBUG_FS) += debugfs.o
+mac80211-objs-$(CONFIG_DEBUG_FS) += debugfs.o debugfs_sta.o

mac80211-objs := \
ieee80211.o \
@@ -14,12 +14,12 @@ mac80211-objs := \
ieee80211_iface.o \
ieee80211_rate.o \
ieee80211_sysfs.o \
- ieee80211_sysfs_sta.o \
michael.o \
tkip.o \
aes_ccm.o \
wme.o \
ieee80211_cfg.o \
+ key_sysfs.o \
$(mac80211-objs-y)

ifeq ($(CONFIG_NET_SCHED),)
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index faa044d..d78c8a6 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -13,7 +13,7 @@ #include "ieee80211_i.h"
#include "ieee80211_rate.h"
#include "debugfs.h"

-static int mac80211_open_file_generic(struct inode *inode, struct file *file)
+int mac80211_open_file_generic(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
@@ -302,6 +302,8 @@ void debugfs_hw_add(struct ieee80211_loc
if (!phyd)
return;

+ local->debugfs.stations = debugfs_create_dir("stations", phyd);
+
DEBUGFS_ADD(channel);
DEBUGFS_ADD(frequency);
DEBUGFS_ADD(radar_detect);
@@ -426,4 +428,6 @@ #endif

debugfs_remove(local->debugfs.statistics);
local->debugfs.statistics = NULL;
+ debugfs_remove(local->debugfs.stations);
+ local->debugfs.stations = NULL;
}
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h
index 75df742..e2c7cbb 100644
--- a/net/mac80211/debugfs.h
+++ b/net/mac80211/debugfs.h
@@ -4,6 +4,7 @@ #define __MAC80211_DEBUGFS_H
#ifdef CONFIG_DEBUG_FS
extern void debugfs_hw_add(struct ieee80211_local *local);
extern void debugfs_hw_del(struct ieee80211_local *local);
+extern int mac80211_open_file_generic(struct inode *inode, struct file *file);
#else
static inline void debugfs_hw_add(struct ieee80211_local *local)
{
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
new file mode 100644
index 0000000..3012b9e
--- /dev/null
+++ b/net/mac80211/debugfs_sta.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2003-2005 Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <[email protected]>
+ * Copyright 2007 Johannes Berg <[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/debugfs.h>
+#include <linux/ieee80211.h>
+#include "ieee80211_i.h"
+#include "debugfs.h"
+#include "debugfs_sta.h"
+#include "sta_info.h"
+
+/* sta attributtes */
+
+#define STA_READ(name, buflen, field, format_string) \
+static ssize_t sta_ ##name## _read(struct file *file, \
+ char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+{ \
+ int res; \
+ struct sta_info *sta = file->private_data; \
+ char buf[buflen]; \
+ res = scnprintf(buf, buflen, format_string, sta->field); \
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+}
+#define STA_READ_D(name, field) STA_READ(name, 20, field, "%d\n")
+#define STA_READ_U(name, field) STA_READ(name, 20, field, "%u\n")
+#define STA_READ_LU(name, field) STA_READ(name, 20, field, "%lu\n")
+#define STA_READ_S(name, field) STA_READ(name, 20, field, "%s\n")
+
+#define STA_READ_RATE(name, field) \
+static ssize_t sta_##name##_read(struct file *file, \
+ char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+{ \
+ struct sta_info *sta = file->private_data; \
+ struct ieee80211_local *local = wdev_priv(sta->dev->ieee80211_ptr);\
+ struct ieee80211_hw_mode *mode = local->oper_hw_mode; \
+ char buf[20]; \
+ int res = scnprintf(buf, sizeof(buf), "%d\n", \
+ (sta->field >= 0 && \
+ sta->field < mode->num_rates) ? \
+ mode->rates[sta->field].rate : -1); \
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+}
+
+#define STA_OPS(name) \
+static const struct file_operations sta_ ##name## _ops = { \
+ .read = sta_##name##_read, \
+ .open = mac80211_open_file_generic, \
+}
+
+#define STA_FILE(name, field, format) \
+ STA_READ_##format(name, field) \
+ STA_OPS(name)
+
+STA_FILE(aid, aid, D);
+STA_FILE(key_idx_compression, key_idx_compression, D);
+STA_FILE(dev, dev->name, S);
+STA_FILE(vlan_id, vlan_id, D);
+STA_FILE(rx_packets, rx_packets, LU);
+STA_FILE(tx_packets, tx_packets, LU);
+STA_FILE(rx_bytes, rx_bytes, LU);
+STA_FILE(tx_bytes, tx_bytes, LU);
+STA_FILE(rx_duplicates, num_duplicates, LU);
+STA_FILE(rx_fragments, rx_fragments, LU);
+STA_FILE(rx_dropped, rx_dropped, LU);
+STA_FILE(tx_fragments, tx_fragments, LU);
+STA_FILE(tx_filtered, tx_filtered_count, LU);
+STA_FILE(txrate, txrate, RATE);
+STA_FILE(last_txrate, last_txrate, RATE);
+STA_FILE(tx_retry_failed, tx_retry_failed, LU);
+STA_FILE(tx_retry_count, tx_retry_count, LU);
+STA_FILE(last_rssi, last_rssi, D);
+STA_FILE(last_signal, last_signal, D);
+STA_FILE(last_noise, last_noise, D);
+STA_FILE(channel_use, channel_use, D);
+STA_FILE(wep_weak_iv_count, wep_weak_iv_count, D);
+
+static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[100];
+ struct sta_info *sta = file->private_data;
+ int res = scnprintf(buf, sizeof(buf), "%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" : "");
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(flags);
+
+static ssize_t sta_num_ps_buf_frames_read(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[20];
+ struct sta_info *sta = file->private_data;
+ int res = scnprintf(buf, sizeof(buf), "%u\n",
+ skb_queue_len(&sta->ps_tx_buf));
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(num_ps_buf_frames);
+
+static ssize_t sta_last_ack_rssi_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[100];
+ struct sta_info *sta = file->private_data;
+ int res = scnprintf(buf, sizeof(buf), "%d %d %d\n",
+ sta->last_ack_rssi[0],
+ sta->last_ack_rssi[1],
+ sta->last_ack_rssi[2]);
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(last_ack_rssi);
+
+static ssize_t sta_last_ack_ms_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[20];
+ struct sta_info *sta = file->private_data;
+ int res = scnprintf(buf, sizeof(buf), "%d\n",
+ sta->last_ack ?
+ jiffies_to_msecs(jiffies - sta->last_ack) : -1);
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(last_ack_ms);
+
+static ssize_t sta_inactive_ms_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[20];
+ struct sta_info *sta = file->private_data;
+ int res = scnprintf(buf, sizeof(buf), "%d\n",
+ jiffies_to_msecs(jiffies - sta->last_rx));
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+STA_OPS(inactive_ms);
+
+static ssize_t sta_last_seq_ctrl_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
+ int i;
+ struct sta_info *sta = file->private_data;
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ p += scnprintf(p, sizeof(buf)+buf-p, "%x ",
+ sta->last_seq_ctrl[i]);
+ p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+ return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(last_seq_ctrl);
+
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+static ssize_t sta_wme_rx_queue_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[15*NUM_RX_DATA_QUEUES], *p = buf;
+ int i;
+ struct sta_info *sta = file->private_data;
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
+ sta->wme_rx_queue[i]);
+ p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+ return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(wme_rx_queue);
+
+static ssize_t sta_wme_tx_queue_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ char buf[15*NUM_TX_DATA_QUEUES], *p = buf;
+ int i;
+ struct sta_info *sta = file->private_data;
+ for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
+ p += scnprintf(p, sizeof(buf)+buf-p, "%u ",
+ sta->wme_tx_queue[i]);
+ p += scnprintf(p, sizeof(buf)+buf-p, "\n");
+ return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+}
+STA_OPS(wme_tx_queue);
+#endif
+
+#define DEBUGFS_ADD(name) \
+ sta->debugfs.name = debugfs_create_file(#name, 0444, \
+ sta->debugfs.dir, sta, &sta_ ##name## _ops);
+
+#define DEBUGFS_DEL(name) \
+ debugfs_remove(sta->debugfs.name);\
+ sta->debugfs.name = NULL;
+
+
+void ieee80211_sta_debugfs_add(struct sta_info *sta)
+{
+ char buf[3*6];
+ struct dentry *stations_dir = sta->local->debugfs.stations;
+
+ if (!stations_dir)
+ return;
+
+ sprintf(buf, MAC_FMT, MAC_ARG(sta->addr));
+
+ sta->debugfs.dir = debugfs_create_dir(buf, stations_dir);
+ if (!sta->debugfs.dir)
+ return;
+
+ DEBUGFS_ADD(flags);
+ DEBUGFS_ADD(num_ps_buf_frames);
+ DEBUGFS_ADD(last_ack_rssi);
+ DEBUGFS_ADD(last_ack_ms);
+ DEBUGFS_ADD(inactive_ms);
+ DEBUGFS_ADD(last_seq_ctrl);
+ DEBUGFS_ADD(wme_rx_queue);
+ DEBUGFS_ADD(wme_tx_queue);
+}
+
+void ieee80211_sta_debugfs_remove(struct sta_info *sta)
+{
+ DEBUGFS_DEL(flags);
+ DEBUGFS_DEL(num_ps_buf_frames);
+ DEBUGFS_DEL(last_ack_rssi);
+ DEBUGFS_DEL(last_ack_ms);
+ DEBUGFS_DEL(inactive_ms);
+ DEBUGFS_DEL(last_seq_ctrl);
+ DEBUGFS_DEL(wme_rx_queue);
+ DEBUGFS_DEL(wme_tx_queue);
+
+ debugfs_remove(sta->debugfs.dir);
+ sta->debugfs.dir = NULL;
+}
diff --git a/net/mac80211/debugfs_sta.h b/net/mac80211/debugfs_sta.h
new file mode 100644
index 0000000..5a60cd5
--- /dev/null
+++ b/net/mac80211/debugfs_sta.h
@@ -0,0 +1,12 @@
+#ifndef __MAC80211_DEBUGFS_STA_H
+#define __MAC80211_DEBUGFS_STA_H
+
+#ifdef CONFIG_DEBUG_FS
+void ieee80211_sta_debugfs_add(struct sta_info *sta);
+void ieee80211_sta_debugfs_remove(struct sta_info *sta);
+#else
+static inline void ieee80211_sta_debugfs_add(struct sta_info *sta) {}
+static inline void ieee80211_sta_debugfs_remove(struct sta_info *sta) {}
+#endif
+
+#endif /* __MAC80211_DEBUGFS_STA_H */
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 78e68db..c9e4cd0 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -35,6 +35,7 @@ #include "ieee80211_led.h"
#include "ieee80211_cfg.h"
#include "ieee80211_sysfs.h"
#include "debugfs.h"
+#include "key_sysfs.h"

/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 18eeb86..0bb08b0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -382,7 +382,6 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
struct sk_buff_head skb_queue_unreliable;

/* 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;
@@ -600,6 +599,7 @@ #endif
struct dentry *wme_tx_queue;
struct dentry *wme_rx_queue;
} stats;
+ struct dentry *stations;
} debugfs;
#endif
};
@@ -764,17 +764,4 @@ void ieee80211_if_sdata_init(struct ieee
int ieee80211_if_add_mgmt(struct ieee80211_local *local);
void ieee80211_if_del_mgmt(struct ieee80211_local *local);

-/* 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);
-int ieee80211_key_kset_sysfs_register(struct ieee80211_sub_if_data *sdata);
-void ieee80211_key_kset_sysfs_unregister(struct ieee80211_sub_if_data *sdata);
-void ieee80211_key_sysfs_set_kset(struct ieee80211_key *key, struct kset *kset);
-int ieee80211_key_sysfs_add(struct ieee80211_key *key);
-void ieee80211_key_sysfs_remove(struct ieee80211_key *key);
-int ieee80211_key_sysfs_add_default(struct ieee80211_sub_if_data *sdata);
-void ieee80211_key_sysfs_remove_default(struct ieee80211_sub_if_data *sdata);
-
#endif /* IEEE80211_I_H */
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 3ba8dee..782c1cb 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -25,7 +25,7 @@ #include "hostapd_ioctl.h"
#include "ieee80211_rate.h"
#include "wpa.h"
#include "aes_ccm.h"
-
+#include "key_sysfs.h"

static int ieee80211_regdom = 0x10; /* FCC */
module_param(ieee80211_regdom, int, 0444);
@@ -687,8 +687,6 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG
else
sdata->keys[idx] = key;
ieee80211_key_free(old_key);
- if (sta)
- key->kobj.parent = &sta->kobj;
ret = ieee80211_key_sysfs_add(key);
if (ret)
goto err_null;
diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h
index b96a89d..c0c32ae 100644
--- a/net/mac80211/ieee80211_rate.h
+++ b/net/mac80211/ieee80211_rate.h
@@ -56,10 +56,9 @@ struct rate_control_ops {

int (*add_attrs)(void *priv, struct kobject *kobj);
void (*remove_attrs)(void *priv, struct kobject *kobj);
- int (*add_sta_attrs)(void *priv, void *priv_sta,
- struct kobject *kobj);
- void (*remove_sta_attrs)(void *priv, void *priv_sta,
- struct kobject *kobj);
+ void (*add_sta_debugfs)(void *priv, void *priv_sta,
+ struct dentry *dir);
+ void (*remove_sta_debugfs)(void *priv, void *priv_sta);
};

struct rate_control_ref {
@@ -123,23 +122,23 @@ static inline void rate_control_free_sta
ref->ops->free_sta(ref->priv, priv);
}

-static inline int rate_control_add_sta_attrs(struct sta_info *sta,
- struct kobject *kobj)
+static inline void rate_control_add_sta_debugfs(struct sta_info *sta)
{
+#ifdef CONFIG_DEBUG_FS
struct rate_control_ref *ref = sta->rate_ctrl;
- if (ref->ops->add_sta_attrs)
- return ref->ops->add_sta_attrs(ref->priv, sta->rate_ctrl_priv,
- kobj);
- return 0;
+ if (sta->debugfs.dir && ref->ops->add_sta_debugfs)
+ ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv,
+ sta->debugfs.dir);
+#endif
}

-static inline void rate_control_remove_sta_attrs(struct sta_info *sta,
- struct kobject *kobj)
+static inline void rate_control_remove_sta_debugfs(struct sta_info *sta)
{
+#ifdef CONFIG_DEBUG_FS
struct rate_control_ref *ref = sta->rate_ctrl;
- if (ref->ops->remove_sta_attrs)
- ref->ops->remove_sta_attrs(ref->priv, sta->rate_ctrl_priv,
- kobj);
+ if (ref->ops->remove_sta_debugfs)
+ ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv);
+#endif
}

#endif /* IEEE80211_RATE_H */
diff --git a/net/mac80211/ieee80211_sysfs.c b/net/mac80211/ieee80211_sysfs.c
index 8072617..9fdc398 100644
--- a/net/mac80211/ieee80211_sysfs.c
+++ b/net/mac80211/ieee80211_sysfs.c
@@ -17,6 +17,7 @@ #include <net/cfg80211.h>
#include "ieee80211_i.h"
#include "ieee80211_rate.h"
#include "ieee80211_sysfs.h"
+#include "key_sysfs.h"

static inline struct ieee80211_local *to_ieee80211_local(struct device *dev)
{
diff --git a/net/mac80211/ieee80211_sysfs_sta.c b/net/mac80211/ieee80211_sysfs_sta.c
deleted file mode 100644
index ae62bcf..0000000
--- a/net/mac80211/ieee80211_sysfs_sta.c
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * 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 "ieee80211_key.h"
-#include "sta_info.h"
-
-static ssize_t sta_sysfs_show(struct kobject *, struct attribute *, char *);
-static ssize_t key_sysfs_show(struct kobject *, struct attribute *, char *);
-
-static struct sysfs_ops sta_ktype_ops = {
- .show = sta_sysfs_show,
-};
-
-static struct sysfs_ops key_ktype_ops = {
- .show = key_sysfs_show,
-};
-
-/* sta attributtes */
-
-#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 = wdev_priv(sta->dev->ieee80211_ptr);\
- struct ieee80211_hw_mode *mode = local->oper_hw_mode; \
- return sprintf(buf, "%d\n", \
- (sta->field >= 0 && \
- sta->field < mode->num_rates) ? \
- mode->rates[sta->field].rate : -1); \
-}
-
-#define __STA_ATTR(name) \
-static struct sta_attribute sta_attr_##name = \
- __ATTR(name, S_IRUGO, 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(last_signal, last_signal, D);
-STA_ATTR(last_noise, last_noise, 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",
- 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_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_MAC80211_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_last_signal.attr,
- &sta_attr_last_noise.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_MAC80211_DEBUG_COUNTERS
- &sta_attr_wme_rx_queue.attr,
- &sta_attr_wme_tx_queue.attr,
-#endif
- NULL
-};
-
-/* keys attributtes */
-
-struct key_attribute {
- struct attribute attr;
- ssize_t (*show)(const struct ieee80211_key *, char *buf);
- ssize_t (*store)(struct ieee80211_key *, const char *buf,
- size_t count);
-};
-
-#define KEY_SHOW(name, field, format_string) \
-static ssize_t show_key_##name(const struct ieee80211_key *key, char *buf)\
-{ \
- return sprintf(buf, format_string, key->field); \
-}
-#define KEY_SHOW_D(name, field) KEY_SHOW(name, field, "%d\n")
-
-#define __KEY_ATTR(name) \
-static struct key_attribute key_attr_##name = \
- __ATTR(name, S_IRUSR, show_key_##name, NULL)
-
-#define KEY_ATTR(name, field, format) \
- KEY_SHOW_##format(name, field) \
- __KEY_ATTR(name)
-
-KEY_ATTR(length, keylen, D);
-KEY_ATTR(sw_encrypt, force_sw_encrypt, D);
-KEY_ATTR(index, keyidx, D);
-KEY_ATTR(hw_index, hw_key_idx, D);
-KEY_ATTR(tx_rx_count, tx_rx_count, D);
-
-static ssize_t show_key_algorithm(const struct ieee80211_key *key, char *buf)
-{
- char *alg;
-
- switch (key->alg) {
- case ALG_WEP:
- alg = "WEP";
- break;
- case ALG_TKIP:
- alg = "TKIP";
- break;
- case ALG_CCMP:
- alg = "CCMP";
- break;
- default:
- return 0;
- }
- return sprintf(buf, "%s\n", alg);
-}
-__KEY_ATTR(algorithm);
-
-static ssize_t show_key_tx_spec(const struct ieee80211_key *key, char *buf)
-{
- const u8 *tpn;
-
- switch (key->alg) {
- case ALG_WEP:
- return sprintf(buf, "\n");
- case ALG_TKIP:
- return sprintf(buf, "%08x %04x\n", key->u.tkip.iv32,
- key->u.tkip.iv16);
- case ALG_CCMP:
- tpn = key->u.ccmp.tx_pn;
- return sprintf(buf, "%02x%02x%02x%02x%02x%02x\n", tpn[0],
- tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
- default:
- return 0;
- }
-}
-__KEY_ATTR(tx_spec);
-
-static ssize_t show_key_rx_spec(const struct ieee80211_key *key, char *buf)
-{
- int i;
- const u8 *rpn;
- char *p = buf;
-
- switch (key->alg) {
- case ALG_WEP:
- return sprintf(buf, "\n");
- case ALG_TKIP:
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
- p += sprintf(p, "%08x %04x\n",
- key->u.tkip.iv32_rx[i],
- key->u.tkip.iv16_rx[i]);
- return (p - buf);
- case ALG_CCMP:
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
- rpn = key->u.ccmp.rx_pn[i];
- p += sprintf(p, "%02x%02x%02x%02x%02x%02x\n", rpn[0],
- rpn[1], rpn[2], rpn[3], rpn[4], rpn[5]);
- }
- return (p - buf);
- default:
- return 0;
- }
-}
-__KEY_ATTR(rx_spec);
-
-static ssize_t show_key_replays(const struct ieee80211_key *key, char *buf)
-{
- if (key->alg != ALG_CCMP)
- return 0;
- return sprintf(buf, "%u\n", key->u.ccmp.replays);
-}
-__KEY_ATTR(replays);
-
-static ssize_t show_key_key(const struct ieee80211_key *key, char *buf)
-{
- int i;
- char *p = buf;
-
- for (i = 0; i < key->keylen; i++)
- p += sprintf(p, "%02x", key->key[i]);
- p += sprintf(p, "\n");
- return (p - buf);
-}
-__KEY_ATTR(key);
-
-static struct attribute *key_ktype_attrs[] = {
- &key_attr_length.attr,
- &key_attr_sw_encrypt.attr,
- &key_attr_index.attr,
- &key_attr_hw_index.attr,
- &key_attr_tx_rx_count.attr,
- &key_attr_algorithm.attr,
- &key_attr_tx_spec.attr,
- &key_attr_rx_spec.attr,
- &key_attr_replays.attr,
- &key_attr_key.attr,
- NULL
-};
-
-/* structures and functions */
-
-static struct kobj_type sta_ktype = {
- .release = sta_info_release,
- .sysfs_ops = &sta_ktype_ops,
- .default_attrs = sta_ktype_attrs,
-};
-
-static struct kobj_type key_ktype = {
- .release = ieee80211_key_release,
- .sysfs_ops = &key_ktype_ops,
- .default_attrs = key_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);
-}
-
-static ssize_t key_sysfs_show(struct kobject *kobj, struct attribute *attr,
- char *buf)
-{
- struct key_attribute *key_attr;
- struct ieee80211_key *key;
-
- key_attr = container_of(attr, struct key_attribute, attr);
- key = container_of(kobj, struct ieee80211_key, kobj);
- return key_attr->show(key, 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->hw.wiphy->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_key_kset_sysfs_register(struct ieee80211_sub_if_data *sdata)
-{
- int res;
-
- res = kobject_set_name(&sdata->key_kset.kobj, "keys");
- if (res)
- return res;
- sdata->key_kset.kobj.parent = &sdata->dev->dev.kobj;
- sdata->key_kset.ktype = &key_ktype;
- return kset_register(&sdata->key_kset);
-}
-
-void ieee80211_key_kset_sysfs_unregister(struct ieee80211_sub_if_data *sdata)
-{
- kset_unregister(&sdata->key_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);
-}
-
-void ieee80211_key_sysfs_set_kset(struct ieee80211_key *key, struct kset *kset)
-{
- key->kobj.kset = kset;
- if (!kset)
- key->kobj.ktype = &key_ktype;
-}
-
-int ieee80211_key_sysfs_add(struct ieee80211_key *key)
-{
- return kobject_add(&key->kobj);
-}
-
-void ieee80211_key_sysfs_remove(struct ieee80211_key *key)
-{
- if (key)
- kobject_del(&key->kobj);
-}
-
-int ieee80211_key_sysfs_add_default(struct ieee80211_sub_if_data *sdata)
-{
- return sysfs_create_link(&sdata->key_kset.kobj,
- &sdata->default_key->kobj, "default");
-}
-
-void ieee80211_key_sysfs_remove_default(struct ieee80211_sub_if_data *sdata)
-{
- if (sdata->default_key)
- sysfs_remove_link(&sdata->key_kset.kobj, "default");
-}
diff --git a/net/mac80211/key_sysfs.c b/net/mac80211/key_sysfs.c
new file mode 100644
index 0000000..6576659
--- /dev/null
+++ b/net/mac80211/key_sysfs.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2003-2005 Devicescape Software, Inc.
+ * Copyright (c) 2006 Jiri Benc <[email protected]>
+ * Copyright 2007 Johannes Berg <[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 "ieee80211_key.h"
+
+/* keys attributtes */
+
+struct key_attribute {
+ struct attribute attr;
+ ssize_t (*show)(const struct ieee80211_key *, char *buf);
+ ssize_t (*store)(struct ieee80211_key *, const char *buf,
+ size_t count);
+};
+
+#define KEY_SHOW(name, field, format_string) \
+static ssize_t show_key_##name(const struct ieee80211_key *key, char *buf)\
+{ \
+ return sprintf(buf, format_string, key->field); \
+}
+#define KEY_SHOW_D(name, field) KEY_SHOW(name, field, "%d\n")
+
+#define __KEY_ATTR(name) \
+static struct key_attribute key_attr_##name = \
+ __ATTR(name, S_IRUSR, show_key_##name, NULL)
+
+#define KEY_ATTR(name, field, format) \
+ KEY_SHOW_##format(name, field) \
+ __KEY_ATTR(name)
+
+KEY_ATTR(length, keylen, D);
+KEY_ATTR(sw_encrypt, force_sw_encrypt, D);
+KEY_ATTR(index, keyidx, D);
+KEY_ATTR(hw_index, hw_key_idx, D);
+KEY_ATTR(tx_rx_count, tx_rx_count, D);
+
+static ssize_t show_key_algorithm(const struct ieee80211_key *key, char *buf)
+{
+ char *alg;
+
+ switch (key->alg) {
+ case ALG_WEP:
+ alg = "WEP";
+ break;
+ case ALG_TKIP:
+ alg = "TKIP";
+ break;
+ case ALG_CCMP:
+ alg = "CCMP";
+ break;
+ default:
+ return 0;
+ }
+ return sprintf(buf, "%s\n", alg);
+}
+__KEY_ATTR(algorithm);
+
+static ssize_t show_key_tx_spec(const struct ieee80211_key *key, char *buf)
+{
+ const u8 *tpn;
+
+ switch (key->alg) {
+ case ALG_WEP:
+ return sprintf(buf, "\n");
+ case ALG_TKIP:
+ return sprintf(buf, "%08x %04x\n", key->u.tkip.iv32,
+ key->u.tkip.iv16);
+ case ALG_CCMP:
+ tpn = key->u.ccmp.tx_pn;
+ return sprintf(buf, "%02x%02x%02x%02x%02x%02x\n", tpn[0],
+ tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
+ default:
+ return 0;
+ }
+}
+__KEY_ATTR(tx_spec);
+
+static ssize_t show_key_rx_spec(const struct ieee80211_key *key, char *buf)
+{
+ int i;
+ const u8 *rpn;
+ char *p = buf;
+
+ switch (key->alg) {
+ case ALG_WEP:
+ return sprintf(buf, "\n");
+ case ALG_TKIP:
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ p += sprintf(p, "%08x %04x\n",
+ key->u.tkip.iv32_rx[i],
+ key->u.tkip.iv16_rx[i]);
+ return (p - buf);
+ case ALG_CCMP:
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
+ rpn = key->u.ccmp.rx_pn[i];
+ p += sprintf(p, "%02x%02x%02x%02x%02x%02x\n", rpn[0],
+ rpn[1], rpn[2], rpn[3], rpn[4], rpn[5]);
+ }
+ return (p - buf);
+ default:
+ return 0;
+ }
+}
+__KEY_ATTR(rx_spec);
+
+static ssize_t show_key_replays(const struct ieee80211_key *key, char *buf)
+{
+ if (key->alg != ALG_CCMP)
+ return 0;
+ return sprintf(buf, "%u\n", key->u.ccmp.replays);
+}
+__KEY_ATTR(replays);
+
+static ssize_t show_key_key(const struct ieee80211_key *key, char *buf)
+{
+ int i;
+ char *p = buf;
+
+ for (i = 0; i < key->keylen; i++)
+ p += sprintf(p, "%02x", key->key[i]);
+ p += sprintf(p, "\n");
+ return (p - buf);
+}
+__KEY_ATTR(key);
+
+static struct attribute *key_ktype_attrs[] = {
+ &key_attr_length.attr,
+ &key_attr_sw_encrypt.attr,
+ &key_attr_index.attr,
+ &key_attr_hw_index.attr,
+ &key_attr_tx_rx_count.attr,
+ &key_attr_algorithm.attr,
+ &key_attr_tx_spec.attr,
+ &key_attr_rx_spec.attr,
+ &key_attr_replays.attr,
+ &key_attr_key.attr,
+ NULL
+};
+
+/* structures and functions */
+
+static ssize_t key_sysfs_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct key_attribute *key_attr;
+ struct ieee80211_key *key;
+
+ key_attr = container_of(attr, struct key_attribute, attr);
+ key = container_of(kobj, struct ieee80211_key, kobj);
+ return key_attr->show(key, buf);
+}
+
+static struct sysfs_ops key_ktype_ops = {
+ .show = key_sysfs_show,
+};
+
+static struct kobj_type key_ktype = {
+ .release = ieee80211_key_release,
+ .sysfs_ops = &key_ktype_ops,
+ .default_attrs = key_ktype_attrs,
+};
+
+int ieee80211_key_kset_sysfs_register(struct ieee80211_sub_if_data *sdata)
+{
+ int res;
+
+ res = kobject_set_name(&sdata->key_kset.kobj, "keys");
+ if (res)
+ return res;
+ sdata->key_kset.kobj.parent = &sdata->dev->dev.kobj;
+ sdata->key_kset.ktype = &key_ktype;
+ return kset_register(&sdata->key_kset);
+}
+
+void ieee80211_key_kset_sysfs_unregister(struct ieee80211_sub_if_data *sdata)
+{
+ kset_unregister(&sdata->key_kset);
+}
+
+void ieee80211_key_sysfs_set_kset(struct ieee80211_key *key, struct kset *kset)
+{
+ key->kobj.kset = kset;
+ if (!kset)
+ key->kobj.ktype = &key_ktype;
+}
+
+int ieee80211_key_sysfs_add(struct ieee80211_key *key)
+{
+ return kobject_add(&key->kobj);
+}
+
+void ieee80211_key_sysfs_remove(struct ieee80211_key *key)
+{
+ if (key)
+ kobject_del(&key->kobj);
+}
+
+int ieee80211_key_sysfs_add_default(struct ieee80211_sub_if_data *sdata)
+{
+ return sysfs_create_link(&sdata->key_kset.kobj,
+ &sdata->default_key->kobj, "default");
+}
+
+void ieee80211_key_sysfs_remove_default(struct ieee80211_sub_if_data *sdata)
+{
+ if (sdata->default_key)
+ sysfs_remove_link(&sdata->key_kset.kobj, "default");
+}
diff --git a/net/mac80211/key_sysfs.h b/net/mac80211/key_sysfs.h
new file mode 100644
index 0000000..9ac9f2b
--- /dev/null
+++ b/net/mac80211/key_sysfs.h
@@ -0,0 +1,12 @@
+#ifndef __MAC80211_KEY_SYSFS_H
+#define __MAC80211_KEY_SYSFS_H
+
+int ieee80211_key_kset_sysfs_register(struct ieee80211_sub_if_data *sdata);
+void ieee80211_key_kset_sysfs_unregister(struct ieee80211_sub_if_data *sdata);
+void ieee80211_key_sysfs_set_kset(struct ieee80211_key *key, struct kset *kset);
+int ieee80211_key_sysfs_add(struct ieee80211_key *key);
+void ieee80211_key_sysfs_remove(struct ieee80211_key *key);
+int ieee80211_key_sysfs_add_default(struct ieee80211_sub_if_data *sdata);
+void ieee80211_key_sysfs_remove_default(struct ieee80211_sub_if_data *sdata);
+
+#endif /* __MAC80211_KEY_SYSFS_H */
diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
index 1b5c82c..9702eae 100644
--- a/net/mac80211/rc80211_simple.c
+++ b/net/mac80211/rc80211_simple.c
@@ -18,6 +18,7 @@ #include <linux/compiler.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "ieee80211_rate.h"
+#include "debugfs.h"


/* This is a minimal implementation of TX rate controlling that can be used
@@ -121,6 +122,11 @@ struct sta_rate_control {
unsigned long avg_rate_update;
u32 tx_avg_rate_sum;
u32 tx_avg_rate_num;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *tx_avg_rate_sum_dentry;
+ struct dentry *tx_avg_rate_num_dentry;
+#endif
};


@@ -327,47 +333,67 @@ static void rate_control_simple_free_sta
kfree(rctrl);
}

-static ssize_t show_sta_tx_avg_rate_sum(const struct sta_info *sta, char *buf)
-{
- struct sta_rate_control *srctrl = sta->rate_ctrl_priv;
+#ifdef CONFIG_DEBUG_FS

- return sprintf(buf, "%d\n", srctrl->tx_avg_rate_sum);
+static int open_file_generic(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
}

-static ssize_t show_sta_tx_avg_rate_num(const struct sta_info *sta, char *buf)
+static ssize_t sta_tx_avg_rate_sum_read(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
{
- struct sta_rate_control *srctrl = sta->rate_ctrl_priv;
+ struct sta_rate_control *srctrl = file->private_data;
+ char buf[20];

- return sprintf(buf, "%d\n", srctrl->tx_avg_rate_num);
+ sprintf(buf, "%d\n", srctrl->tx_avg_rate_sum);
+ return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
}

-static struct sta_attribute sta_attr_tx_avg_rate_sum =
- __ATTR(tx_avg_rate_sum, S_IRUSR, show_sta_tx_avg_rate_sum, NULL);
-static struct sta_attribute sta_attr_tx_avg_rate_num =
- __ATTR(tx_avg_rate_num, S_IRUSR, show_sta_tx_avg_rate_num, NULL);
-
-static struct attribute *rate_control_simple_sta_attrs[] = {
- &sta_attr_tx_avg_rate_sum.attr,
- &sta_attr_tx_avg_rate_num.attr,
- NULL,
+static const struct file_operations sta_tx_avg_rate_sum_ops = {
+ .read = sta_tx_avg_rate_sum_read,
+ .open = open_file_generic,
};

-static struct attribute_group rate_control_simple_sta_group = {
- .name = "rate_control_simple",
- .attrs = rate_control_simple_sta_attrs,
+static ssize_t sta_tx_avg_rate_num_read(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct sta_rate_control *srctrl = file->private_data;
+ char buf[20];
+
+ sprintf(buf, "%d\n", srctrl->tx_avg_rate_num);
+ return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf));
+}
+
+static const struct file_operations sta_tx_avg_rate_num_ops = {
+ .read = sta_tx_avg_rate_num_read,
+ .open = open_file_generic,
};

-static int rate_control_simple_add_sta_attrs(void *priv, void *priv_sta,
- struct kobject *kobj)
+static void rate_control_simple_add_sta_debugfs(void *priv, void *priv_sta,
+ struct dentry *dir)
{
- return sysfs_create_group(kobj, &rate_control_simple_sta_group);
+ struct sta_rate_control *srctrl = priv_sta;
+
+ srctrl->tx_avg_rate_num_dentry =
+ debugfs_create_file("rc_simple_sta_tx_avg_rate_num", 0400,
+ dir, srctrl, &sta_tx_avg_rate_num_ops);
+ srctrl->tx_avg_rate_sum_dentry =
+ debugfs_create_file("rc_simple_sta_tx_avg_rate_sum", 0400,
+ dir, srctrl, &sta_tx_avg_rate_sum_ops);
}

-static void rate_control_simple_remove_sta_attrs(void *priv, void *priv_sta,
- struct kobject *kobj)
+static void rate_control_simple_remove_sta_debugfs(void *priv, void *priv_sta)
{
- sysfs_remove_group(kobj, &rate_control_simple_sta_group);
+ struct sta_rate_control *srctrl = priv_sta;
+
+ debugfs_remove(srctrl->tx_avg_rate_sum_dentry);
+ debugfs_remove(srctrl->tx_avg_rate_num_dentry);
}
+#endif

static struct rate_control_ops rate_control_simple = {
.module = THIS_MODULE,
@@ -380,8 +406,10 @@ static struct rate_control_ops rate_cont
.free = rate_control_simple_free,
.alloc_sta = rate_control_simple_alloc_sta,
.free_sta = rate_control_simple_free_sta,
- .add_sta_attrs = rate_control_simple_add_sta_attrs,
- .remove_sta_attrs = rate_control_simple_remove_sta_attrs,
+#ifdef CONFIG_DEBUG_FS
+ .add_sta_debugfs = rate_control_simple_add_sta_debugfs,
+ .remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
+#endif
};


diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 2e258cf..37d83eb 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -8,7 +8,6 @@

#include <linux/module.h>
#include <linux/init.h>
-#include <linux/kobject.h>
#include <linux/netdevice.h>
#include <linux/types.h>
#include <linux/slab.h>
@@ -19,7 +18,8 @@ #include <net/mac80211.h>
#include "ieee80211_i.h"
#include "ieee80211_rate.h"
#include "sta_info.h"
-
+#include "key_sysfs.h"
+#include "debugfs_sta.h"

/* Caller must hold local->sta_lock */
static void sta_info_hash_add(struct ieee80211_local *local,
@@ -53,12 +53,12 @@ static void sta_info_hash_del(struct iee
"hash table\n", local->mdev->name, MAC_ARG(sta->addr));
}

-static inline struct sta_info *__sta_info_get(struct sta_info *sta)
+static inline void __sta_info_get(struct sta_info *sta)
{
- return kobject_get(&sta->kobj) ? sta : NULL;
+ kref_get(&sta->kref);
}

-struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr)
+struct sta_info *sta_info_get(struct ieee80211_local *local, u8 *addr)
{
struct sta_info *sta;

@@ -102,15 +102,9 @@ int sta_info_min_txrate_get(struct ieee8
}


-void sta_info_put(struct sta_info *sta)
+void sta_info_release(struct kref *kref)
{
- kobject_put(&sta->kobj);
-}
-EXPORT_SYMBOL(sta_info_put);
-
-void sta_info_release(struct kobject *kobj)
-{
- struct sta_info *sta = container_of(kobj, struct sta_info, kobj);
+ struct sta_info *sta = container_of(kref, struct sta_info, kref);
struct ieee80211_local *local = sta->local;
struct sk_buff *skb;

@@ -131,6 +125,13 @@ void sta_info_release(struct kobject *ko
}


+void sta_info_put(struct sta_info *sta)
+{
+ kref_put(&sta->kref, sta_info_release);
+}
+EXPORT_SYMBOL(sta_info_put);
+
+
struct sta_info * sta_info_add(struct ieee80211_local *local,
struct net_device *dev, u8 *addr, gfp_t gfp)
{
@@ -140,18 +141,13 @@ struct sta_info * sta_info_add(struct ie
if (!sta)
return NULL;

- if (kobject_set_name(&sta->kobj, MAC_FMT, MAC_ARG(addr))) {
- kfree(sta);
- return NULL;
- }
- sta->kobj.kset = &local->sta_kset;
- kobject_init(&sta->kobj);
+ kref_init(&sta->kref);

sta->rate_ctrl = rate_control_get(local->rate_ctrl);
sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, gfp);
if (!sta->rate_ctrl_priv) {
rate_control_put(sta->rate_ctrl);
- kobject_put(&sta->kobj);
+ kref_put(&sta->kref, sta_info_release);
kfree(sta);
return NULL;
}
@@ -180,8 +176,8 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG

if (!in_interrupt()) {
sta->sysfs_registered = 1;
- ieee80211_sta_sysfs_add(sta);
- rate_control_add_sta_attrs(sta, &sta->kobj);
+ ieee80211_sta_debugfs_add(sta);
+ rate_control_add_sta_debugfs(sta);
} else {
/* procfs entry adding might sleep, so schedule process context
* task for adding proc entry for STAs that do not yet have
@@ -206,8 +202,8 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG
sta->key = NULL;
}

- rate_control_remove_sta_attrs(sta, &sta->kobj);
- ieee80211_sta_sysfs_remove(sta);
+ rate_control_remove_sta_debugfs(sta);
+ ieee80211_sta_debugfs_remove(sta);

sta_info_put(sta);
}
@@ -380,8 +376,8 @@ static void sta_info_proc_add_task(struc
break;

sta->sysfs_registered = 1;
- ieee80211_sta_sysfs_add(sta);
- rate_control_add_sta_attrs(sta, &sta->kobj);
+ ieee80211_sta_debugfs_add(sta);
+ rate_control_add_sta_debugfs(sta);
sta_info_put(sta);
}
}
@@ -403,11 +399,6 @@ void sta_info_init(struct ieee80211_loca

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;
}
@@ -425,10 +416,8 @@ void sta_info_stop(struct ieee80211_loca
* point. */
sta_info_free(sta, 0);
}
- ieee80211_sta_kset_sysfs_unregister(local);
}

-
void sta_info_remove_aid_ptr(struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 53b1625..5213d2c 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -12,6 +12,7 @@ #define STA_INFO_H
#include <linux/list.h>
#include <linux/types.h>
#include <linux/if_ether.h>
+#include <linux/kref.h>
#include "ieee80211_key.h"

/* Stations flags (struct sta_info::flags) */
@@ -30,8 +31,8 @@ #define WLAN_STA_WDS BIT(27)


struct sta_info {
+ struct kref kref;
struct list_head list;
- struct kobject kobj;
struct sta_info *hnext; /* next entry in hash table list */

struct ieee80211_local *local;
@@ -113,6 +114,20 @@ #endif /* CONFIG_MAC80211_DEBUG_COUNTERS
int vlan_id;

u16 listen_interval;
+
+#ifdef CONFIG_DEBUG_FS
+ struct sta_info_debugfsdentries {
+ struct dentry *dir;
+ struct dentry *flags;
+ struct dentry *num_ps_buf_frames;
+ struct dentry *last_ack_rssi;
+ struct dentry *last_ack_ms;
+ struct dentry *inactive_ms;
+ struct dentry *last_seq_ctrl;
+ struct dentry *wme_rx_queue;
+ struct dentry *wme_tx_queue;
+ } debugfs;
+#endif
};


@@ -140,7 +155,6 @@ 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);
void sta_info_free(struct sta_info *sta, int locked);
-void sta_info_release(struct kobject *kobj);
void sta_info_init(struct ieee80211_local *local);
int sta_info_start(struct ieee80211_local *local);
void sta_info_stop(struct ieee80211_local *local);
--
1.3.0


2007-03-23 20:43:40

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 13/19] mac80211: fix remaining sparse warnings

From: Johannes Berg <[email protected]>

This patch fixes the sparse warnings that remain after Michael Wu's
patches as well as those I might have introduced myself during the
debugfs restructuring...

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/debugfs_netdev.c | 4 ++--
net/mac80211/ieee80211.c | 2 +-
net/mac80211/ieee80211_ioctl.c | 2 +-
net/mac80211/sta_info.c | 21 +++++++++++++++------
4 files changed, 19 insertions(+), 10 deletions(-)

a290e1fe4bd5779b96e07cc9deff9c75b7887a54
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 7b713fb..9e39646 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -244,7 +244,7 @@ static void add_monitor_files(struct iee
DEBUGFS_ADD(mode, monitor);
}

-void add_files(struct ieee80211_sub_if_data *sdata)
+static void add_files(struct ieee80211_sub_if_data *sdata)
{
if (!sdata->debugfsdir)
return;
@@ -337,7 +337,7 @@ static void del_monitor_files(struct iee
DEBUGFS_DEL(mode, monitor);
}

-void del_files(struct ieee80211_sub_if_data *sdata, int type)
+static void del_files(struct ieee80211_sub_if_data *sdata, int type)
{
if (!sdata->debugfsdir)
return;
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index db04fd8..24cc3a0 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -97,7 +97,7 @@ struct ieee80211_key *ieee80211_key_allo
return key;
}

-void ieee80211_key_release(struct kref *kref)
+static void ieee80211_key_release(struct kref *kref)
{
struct ieee80211_key *key;

diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index cb75015..21a17eb 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -518,7 +518,7 @@ int ieee80211_set_hw_encryption(struct n


static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
- int idx, int alg, int set_tx_key, int *err,
+ int idx, int alg, int set_tx_key, u32 *err,
const u8 *_key, size_t key_len)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index dfbd369..4e341f6 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -102,7 +102,7 @@ int sta_info_min_txrate_get(struct ieee8
}


-void sta_info_release(struct kref *kref)
+static void sta_info_release(struct kref *kref)
{
struct sta_info *sta = container_of(kref, struct sta_info, kref);
struct ieee80211_local *local = sta->local;
@@ -210,14 +210,11 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG
sta_info_put(sta);
}

-void sta_info_free(struct sta_info *sta, int locked)
+static void sta_info_remove(struct sta_info *sta)
{
- struct sk_buff *skb;
struct ieee80211_local *local = sta->local;
struct ieee80211_sub_if_data *sdata;

- if (!locked)
- spin_lock_bh(&local->sta_lock);
sta_info_hash_del(local, sta);
list_del(&sta->list);
sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev);
@@ -228,8 +225,20 @@ void sta_info_free(struct sta_info *sta,
}
local->num_sta--;
sta_info_remove_aid_ptr(sta);
- if (!locked)
+}
+
+void sta_info_free(struct sta_info *sta, int locked)
+{
+ struct sk_buff *skb;
+ struct ieee80211_local *local = sta->local;
+
+ if (!locked) {
+ spin_lock_bh(&local->sta_lock);
+ sta_info_remove(sta);
spin_unlock_bh(&local->sta_lock);
+ } else {
+ sta_info_remove(sta);
+ }
if (local->ops->sta_table_notification)
local->ops->sta_table_notification(local_to_hw(local),
local->num_sta);
--
1.3.0


2007-03-23 20:43:42

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 16/19] mac80211: fix passing wrong pointer to ieee80211_dump_frame

From: Hong Liu <[email protected]>

Signed-off-by: Hong Liu <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)

0ddfc778426ba75c2ad71d23e9e2e48121264c70
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 24cc3a0..fccb0fe 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -1166,7 +1166,8 @@ static int __ieee80211_tx(struct ieee802
}

ieee80211_dump_frame(local->mdev->name,
- "TX to low-level driver", skb);
+ "TX to low-level driver",
+ tx->u.tx.extra_frag[i]);
ret = local->ops->tx(local_to_hw(local),
tx->u.tx.extra_frag[i],
control);
--
1.3.0


2007-03-23 20:43:31

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 5/19] mac80211: Remove tx_timeout callback

From: Michael Wu <[email protected]>

This never worked in the first place and we can't use the network watchdog
anyway since that checks if the queue is stopped, but wireless devices can
have many queues. TX timeouts on virtual interfaces don't really make sense
either since they can't stall.

Signed-off-by: Michael Wu <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 15 ---------------
1 files changed, 0 insertions(+), 15 deletions(-)

3dcfdf95493a7317b1373d6212f4e7b3461b465d
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index f3fc96b..18caa2b 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -2082,19 +2082,6 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG
}


-static void ieee80211_tx_timeout(struct net_device *dev)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-
- printk(KERN_WARNING "%s: resetting interface.\n", dev->name);
-
- if (local->ops->reset(local_to_hw(local)))
- printk(KERN_ERR "%s: failed to reset interface.\n", dev->name);
- else
- netif_wake_queue(dev);
-}
-
-
static int ieee80211_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *a = addr;
@@ -4429,7 +4416,6 @@ void ieee80211_if_setup(struct net_devic
dev->set_mac_address = ieee80211_set_mac_address;
dev->set_multicast_list = ieee80211_set_multicast_list;
dev->change_mtu = ieee80211_change_mtu;
- dev->tx_timeout = ieee80211_tx_timeout;
dev->get_stats = ieee80211_get_stats;
dev->open = ieee80211_open;
dev->stop = ieee80211_stop;
@@ -4594,7 +4580,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(
sta_info_init(local);

mdev->hard_start_xmit = ieee80211_master_start_xmit;
- mdev->tx_timeout = ieee80211_tx_timeout;
mdev->get_stats = ieee80211_get_stats;
mdev->open = ieee80211_master_open;
mdev->stop = ieee80211_master_stop;
--
1.3.0


2007-03-23 20:43:46

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 19/19] mac80211: Add software sequence support

From: Ivo van Doorn <[email protected]>

Most hardware can keep track of sequence numbers themselves,
unfortunately *most* doesn't cover all devices. ;)
This patch will keep track of the (per-bss) sequence number.

Signed-off-by: Ivo van Doorn <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 27 ++++++++++++++++++++++++++-
net/mac80211/ieee80211_i.h | 2 ++
2 files changed, 28 insertions(+), 1 deletions(-)

35262af661f8561e197b093581889e85ef6f5d74
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 39468b8..3bf0be4 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -59,6 +59,16 @@ static u8 * ieee80211_get_bssid(struct i
static int ieee80211_mgmt_start_xmit(struct sk_buff *skb,
struct net_device *dev);

+static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_hdr *hdr)
+{
+ /* Set the sequence number for this frame. */
+ hdr->seq_ctrl = cpu_to_le16(sdata->sequence);
+
+ /* Increase the sequence number. */
+ sdata->sequence = (sdata->sequence + 0x10) & IEEE80211_SCTL_SEQ;
+}
+
struct ieee80211_key_conf *
ieee80211_key_data2conf(struct ieee80211_local *local,
const struct ieee80211_key *data)
@@ -437,6 +447,7 @@ ieee80211_tx_h_fragment(struct ieee80211
size_t hdrlen, per_fragm, num_fragm, payload_len, left;
struct sk_buff **frags, *first, *frag;
int i;
+ u16 seq;
u8 *pos;
int frag_threshold = tx->local->fragmentation_threshold;

@@ -455,6 +466,7 @@ ieee80211_tx_h_fragment(struct ieee80211
goto fail;

hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
+ seq = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ;
pos = first->data + hdrlen + per_fragm;
left = payload_len - per_fragm;
for (i = 0; i < num_fragm - 1; i++) {
@@ -482,7 +494,7 @@ ieee80211_tx_h_fragment(struct ieee80211
memcpy(fhdr, first->data, hdrlen);
if (i == num_fragm - 2)
fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS);
- fhdr->seq_ctrl = cpu_to_le16(i + 1);
+ fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG));
copylen = left > per_fragm ? per_fragm : left;
memcpy(skb_put(frag, copylen), pos, copylen);

@@ -894,6 +906,16 @@ #endif
return TXRX_CONTINUE;
}

+static ieee80211_txrx_result
+ieee80211_tx_h_sequence(struct ieee80211_txrx_data *tx)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+
+ if (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)) >= 24)
+ ieee80211_include_sequence(tx->sdata, hdr);
+
+ return TXRX_CONTINUE;
+}

/* This function is called whenever the AP is about to exceed the maximum limit
* of buffered frames for power saving STAs. This situation should not really
@@ -1766,6 +1788,8 @@ #endif /* CONFIG_MAC80211_VERBOSE_DEBUG
skb_reserve(skb, local->hw.extra_tx_headroom);
memcpy(skb_put(skb, bh_len), b_head, bh_len);

+ ieee80211_include_sequence(sdata, (struct ieee80211_hdr *)skb->data);
+
ieee80211_beacon_add_tim(local, ap, skb);

if (b_tail) {
@@ -4373,6 +4397,7 @@ static ieee80211_rx_handler ieee80211_rx
static ieee80211_tx_handler ieee80211_tx_handlers[] =
{
ieee80211_tx_h_check_assoc,
+ ieee80211_tx_h_sequence,
ieee80211_tx_h_ps_buf,
ieee80211_tx_h_select_key,
ieee80211_tx_h_michael_mic_add,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 3c10152..561c976 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -318,6 +318,8 @@ struct ieee80211_sub_if_data {
int ieee802_1x; /* IEEE 802.1X PAE - drop packet to/from unauthorized
* port */

+ u16 sequence;
+
/* Fragment table for host-based reassembly */
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
unsigned int fragment_next;
--
1.3.0


2007-03-23 20:43:44

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 17/19] mac80211: Properly kill tasklets before shutdown

From: Michael Buesch <[email protected]>

We need to do tasklet_kill() on any tasklet on unregister
to make sure the tasklet is not running _and_ scheduled anymore.
(tasklet_disable() only ensures it's not running anymore).

This fixes the tasklet related crash that was reported some time ago.

Signed-off-by: Michael Buesch <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

baf56723a69d16311ad09db5ecee1f3e4c4d7ca1
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index fccb0fe..fb2ce3d 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -4728,8 +4728,8 @@ void ieee80211_unregister_hw(struct ieee
struct ieee80211_sub_if_data *sdata, *tmp;
int i;

- tasklet_disable(&local->tasklet);
- /* TODO: skb_queue should be empty here, no need to do anything? */
+ tasklet_kill(&local->tx_pending_tasklet);
+ tasklet_kill(&local->tasklet);

rtnl_lock();
local->reg_state = IEEE80211_DEV_UNREGISTERED;
--
1.3.0


2007-03-23 20:43:29

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 3/19] mac80211: fix rtnl locking in ieee80211_register_hw

rtnl locking in ieee80211_register_hw was racy. This patch fixes that.

Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 13 ++++---------
1 files changed, 4 insertions(+), 9 deletions(-)

9d0a7f4ed6daf144111954e2ecd70df78e7449d9
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index e7576c5..9d95250 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -4666,18 +4666,13 @@ int ieee80211_register_hw(struct ieee802
SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy));

result = register_netdevice(local->mdev);
- if (result < 0) {
- rtnl_unlock();
+ if (result < 0)
goto fail_dev;
- }
result = ieee80211_sysfs_add_netdevice(local->mdev);
- if (result < 0) {
- rtnl_unlock();
+ if (result < 0)
goto fail_if_sysfs;
- }

result = ieee80211_init_rate_ctrl_alg(local, NULL);
- rtnl_unlock();
if (result < 0) {
printk(KERN_DEBUG "%s: Failed to initialize rate control "
"algorithm\n", local->mdev->name);
@@ -4696,7 +4691,6 @@ int ieee80211_register_hw(struct ieee802
ieee80211_install_qdisc(local->mdev);

/* add one default STA interface */
- rtnl_lock();
result = ieee80211_if_add(local->mdev, "wlan%d", 1, &sta_dev);
if (result == 0)
ieee80211_if_set_type(sta_dev, IEEE80211_IF_TYPE_STA);
@@ -4713,8 +4707,9 @@ fail_wep:
fail_rate:
ieee80211_sysfs_remove_netdevice(local->mdev);
fail_if_sysfs:
- unregister_netdev(local->mdev);
+ unregister_netdevice(local->mdev);
fail_dev:
+ rtnl_unlock();
sta_info_stop(local);
fail_sta_info:
ieee80211_dev_sysfs_del(local);
--
1.3.0


2007-03-23 20:43:42

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 15/19] mac80211: fix wrong keyidx will change default key

From: Hong Liu <[email protected]>

Signed-off-by: Hong Liu <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211_ioctl.c | 22 ++++++++++------------
1 files changed, 10 insertions(+), 12 deletions(-)

1485998df4d688be3e0907423a774dadbf90a631
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 21a17eb..b28e794 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -2924,19 +2924,17 @@ static int ieee80211_ioctl_siwencode(str
sdata = IEEE80211_DEV_TO_SUB_IF(dev);

idx = erq->flags & IW_ENCODE_INDEX;
- if (idx < 1 || idx > 4) {
- idx = -1;
- if (!sdata->default_key)
- idx = 0;
- else for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
- if (sdata->default_key == sdata->keys[i]) {
- idx = i;
- break;
+ if (idx == 0) {
+ if (sdata->default_key)
+ for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+ if (sdata->default_key == sdata->keys[i]) {
+ idx = i;
+ break;
+ }
}
- }
- if (idx < 0)
- return -EINVAL;
- } else
+ } else if (idx < 1 || idx > 4)
+ return -EINVAL;
+ else
idx--;

if (erq->flags & IW_ENCODE_DISABLED)
--
1.3.0


2007-03-23 20:43:34

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 8/19] mac80211: Fix pkt_type annotations

From: Michael Buesch <[email protected]>

There is no need for an instance of the enum in ieee80211_local.
Remove it. Also make the constants uppercase to respect
kernel coding style.

Signed-off-by: Michael Buesch <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 8 ++++----
net/mac80211/ieee80211_i.h | 9 +++++----
2 files changed, 9 insertions(+), 8 deletions(-)

4eb6baed5808950d168cb935c426148ba8256366
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 05c21d6..17c0ef9 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -4046,7 +4046,7 @@ void ieee80211_rx_irqsafe(struct ieee802
skb->dev = local->mdev;
/* copy status into skb->cb for use by tasklet */
memcpy(skb->cb, status, sizeof(*status));
- skb->pkt_type = ieee80211_rx_msg;
+ skb->pkt_type = IEEE80211_RX_MSG;
skb_queue_tail(&local->skb_queue, skb);
tasklet_schedule(&local->tasklet);
}
@@ -4076,7 +4076,7 @@ void ieee80211_tx_status_irqsafe(struct
/* copy pointer to saved status into skb->cb for use by tasklet */
memcpy(skb->cb, &saved, sizeof(saved));

- skb->pkt_type = ieee80211_tx_status_msg;
+ skb->pkt_type = IEEE80211_TX_STATUS_MSG;
skb_queue_tail(status->control.flags & IEEE80211_TXCTL_REQ_TX_STATUS ?
&local->skb_queue : &local->skb_queue_unreliable, skb);
tmp = skb_queue_len(&local->skb_queue) +
@@ -4103,7 +4103,7 @@ static void ieee80211_tasklet_handler(un
while ((skb = skb_dequeue(&local->skb_queue)) ||
(skb = skb_dequeue(&local->skb_queue_unreliable))) {
switch (skb->pkt_type) {
- case ieee80211_rx_msg:
+ case IEEE80211_RX_MSG:
/* status is in skb->cb */
memcpy(&rx_status, skb->cb, sizeof(rx_status));
/* Clear skb->type in order to not confuse kernel
@@ -4111,7 +4111,7 @@ static void ieee80211_tasklet_handler(un
skb->pkt_type = 0;
__ieee80211_rx(local_to_hw(local), skb, &rx_status);
break;
- case ieee80211_tx_status_msg:
+ case IEEE80211_TX_STATUS_MSG:
/* get pointer to saved status out of skb->cb */
memcpy(&tx_status, skb->cb, sizeof(tx_status));
skb->pkt_type = 0;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index cf37ce6..9ea1005 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -343,6 +343,11 @@ #define NUM_DEFAULT_KEYS 4

#define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev)

+enum {
+ IEEE80211_RX_MSG = 1,
+ IEEE80211_TX_STATUS_MSG = 2,
+};
+
struct ieee80211_local {
/* embed the driver visible part.
* don't cast (use the static inlines below), but we keep
@@ -375,10 +380,6 @@ #define IEEE80211_IRQSAFE_QUEUE_LIMIT 12
struct tasklet_struct tasklet;
struct sk_buff_head skb_queue;
struct sk_buff_head skb_queue_unreliable;
- enum {
- ieee80211_rx_msg = 1,
- ieee80211_tx_status_msg = 2
- } ieee80211_msg_enum;

/* Station data structures */
struct kset sta_kset;
--
1.3.0


2007-03-23 20:43:40

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 14/19] mac80211: switch STA interfaces to PS mode during scan

From: Michael Wu <[email protected]>

This makes scans switch STA interfaces into PS mode so the AP queues frames
destined for us while we are scanning. This is achieved by sending a
nullfunc data frame with the PS mode bit set before scanning commences,
and a nullfunc data frame without the PS mode bit set after scanning is
completed.

Signed-off-by: Michael Wu <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211_sta.c | 51 +++++++++++++++++++++++++++++++++++-------
1 files changed, 43 insertions(+), 8 deletions(-)

202d728b6d56a44e1be0970ee3e3f0971fbd7c66
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index ce7dc28..087f176 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -2520,6 +2520,37 @@ int ieee80211_sta_set_bssid(struct net_d
}


+static void ieee80211_send_nullfunc(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ int powersave)
+{
+ struct sk_buff *skb;
+ struct ieee80211_hdr *nullfunc;
+ u16 fc;
+
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
+ if (!skb) {
+ printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
+ "frame\n", sdata->dev->name);
+ return;
+ }
+ skb_reserve(skb, local->hw.extra_tx_headroom);
+
+ nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
+ memset(nullfunc, 0, 24);
+ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
+ IEEE80211_FCTL_TODS;
+ if (powersave)
+ fc |= IEEE80211_FCTL_PM;
+ nullfunc->frame_control = cpu_to_le16(fc);
+ memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN);
+ memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
+ memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN);
+
+ ieee80211_sta_tx(sdata->dev, skb, 0);
+}
+
+
void ieee80211_scan_completed(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
@@ -2541,10 +2572,12 @@ void ieee80211_scan_completed(struct iee

spin_lock_bh(&local->sub_if_lock);
list_for_each_entry(sdata, &local->sub_if_list, list) {
- netif_wake_queue(sdata->dev);
-
- if (sdata->type == IEEE80211_IF_TYPE_STA)
+ if (sdata->type == IEEE80211_IF_TYPE_STA) {
+ if (sdata->u.sta.associated)
+ ieee80211_send_nullfunc(local, sdata, 0);
ieee80211_sta_timer((unsigned long)&sdata->u.sta);
+ }
+ netif_wake_queue(sdata->dev);
}
spin_unlock_bh(&local->sub_if_lock);

@@ -2664,9 +2697,6 @@ static int ieee80211_sta_start_scan(stru
* ResultCode: SUCCESS, INVALID_PARAMETERS
*/

- /* TODO: if assoc, move to power save mode for the duration of the
- * scan */
-
if (local->sta_scanning) {
if (local->scan_dev == dev)
return 0;
@@ -2688,8 +2718,12 @@ static int ieee80211_sta_start_scan(stru
local->sta_scanning = 1;

spin_lock_bh(&local->sub_if_lock);
- list_for_each_entry(sdata, &local->sub_if_list, list)
+ list_for_each_entry(sdata, &local->sub_if_list, list) {
netif_stop_queue(sdata->dev);
+ if (sdata->type == IEEE80211_IF_TYPE_STA &&
+ sdata->u.sta.associated)
+ ieee80211_send_nullfunc(local, sdata, 1);
+ }
spin_unlock_bh(&local->sub_if_lock);

if (ssid) {
@@ -2703,7 +2737,8 @@ static int ieee80211_sta_start_scan(stru
list);
local->scan_channel_idx = 0;
local->scan_dev = dev;
- schedule_delayed_work(&local->scan_work, 0);
+ /* TODO: start scan as soon as all nullfunc frames are ACKed */
+ schedule_delayed_work(&local->scan_work, IEEE80211_CHANNEL_TIME);

return 0;
}
--
1.3.0


2007-03-23 20:43:36

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 9/19] mac80211: move PHY things to debugfs

From: [email protected] <[email protected]>

This patch moves everything except the "sta" and "key" directories
from the phy sysfs to phy debugfs. Since the current rate control
algorithm isn't using any global sysfs entries it also removes the
ability for a rate control algorithm to do so. That can be re-added
to debugfs when necessary.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/Makefile | 1
net/mac80211/debugfs.c | 429 ++++++++++++++++++++++++++++++++++++++++
net/mac80211/debugfs.h | 15 +
net/mac80211/ieee80211.c | 20 --
net/mac80211/ieee80211_i.h | 62 ++++++
net/mac80211/ieee80211_rate.h | 15 -
net/mac80211/ieee80211_sysfs.c | 375 -----------------------------------
net/mac80211/ieee80211_sysfs.h | 2
8 files changed, 511 insertions(+), 408 deletions(-)
create mode 100644 net/mac80211/debugfs.c
create mode 100644 net/mac80211/debugfs.h

fc21c442d9236386b5c87ffee08cbc61a7f294dd
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index 3a40d6e..17c09d6 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o

mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
+mac80211-objs-$(CONFIG_DEBUG_FS) += debugfs.o

mac80211-objs := \
ieee80211.o \
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
new file mode 100644
index 0000000..faa044d
--- /dev/null
+++ b/net/mac80211/debugfs.c
@@ -0,0 +1,429 @@
+/*
+ * mac80211 debugfs for wireless PHYs
+ *
+ * Copyright 2007 Johannes Berg <[email protected]>
+ *
+ * GPLv2
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/rtnetlink.h>
+#include "ieee80211_i.h"
+#include "ieee80211_rate.h"
+#include "debugfs.h"
+
+static int mac80211_open_file_generic(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static const char *ieee80211_mode_str(int mode)
+{
+ switch (mode) {
+ case MODE_IEEE80211A:
+ return "IEEE 802.11a";
+ case MODE_IEEE80211B:
+ return "IEEE 802.11b";
+ case MODE_IEEE80211G:
+ return "IEEE 802.11g";
+ case MODE_ATHEROS_TURBO:
+ return "Atheros Turbo (5 GHz)";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static ssize_t modes_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_local *local = file->private_data;
+ struct ieee80211_hw_mode *mode;
+ char buf[150], *p = buf;
+
+ /* FIXME: locking! */
+ list_for_each_entry(mode, &local->modes_list, list) {
+ p += scnprintf(p, sizeof(buf)+buf-p,
+ "%s\n", ieee80211_mode_str(mode->mode));
+ }
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+}
+
+static const struct file_operations modes_ops = {
+ .read = modes_read,
+ .open = mac80211_open_file_generic,
+};
+
+#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
+static ssize_t name## _read(struct file *file, char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+{ \
+ struct ieee80211_local *local = file->private_data; \
+ char buf[buflen]; \
+ int res; \
+ \
+ res = scnprintf(buf, buflen, fmt "\n", ##value); \
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
+} \
+ \
+static const struct file_operations name## _ops = { \
+ .read = name## _read, \
+ .open = mac80211_open_file_generic, \
+};
+
+#define DEBUGFS_ADD(name) \
+ local->debugfs.name = debugfs_create_file(#name, 0444, phyd, \
+ local, &name## _ops);
+
+#define DEBUGFS_DEL(name) \
+ debugfs_remove(local->debugfs.name); \
+ local->debugfs.name = NULL;
+
+
+DEBUGFS_READONLY_FILE(channel, 20, "%d",
+ local->hw.conf.channel);
+DEBUGFS_READONLY_FILE(frequency, 20, "%d",
+ local->hw.conf.freq);
+DEBUGFS_READONLY_FILE(radar_detect, 20, "%d",
+ local->hw.conf.radar_detect);
+DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d",
+ local->hw.conf.antenna_sel_tx);
+DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d",
+ local->hw.conf.antenna_sel_rx);
+DEBUGFS_READONLY_FILE(bridge_packets, 20, "%d",
+ local->bridge_packets);
+DEBUGFS_READONLY_FILE(key_tx_rx_threshold, 20, "%d",
+ local->key_tx_rx_threshold);
+DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
+ local->rts_threshold);
+DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
+ local->fragmentation_threshold);
+DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
+ local->short_retry_limit);
+DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
+ local->long_retry_limit);
+DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
+ local->total_ps_buffered);
+DEBUGFS_READONLY_FILE(mode, 20, "%s",
+ ieee80211_mode_str(local->hw.conf.phymode));
+DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x",
+ local->wep_iv & 0xffffff);
+DEBUGFS_READONLY_FILE(tx_power_reduction, 20, "%d.%d dBm",
+ local->hw.conf.tx_power_reduction / 10,
+ local->hw.conf.tx_power_reduction & 10);
+DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
+ local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>");
+
+/* statistics stuff */
+
+static inline int rtnl_lock_local(struct ieee80211_local *local)
+{
+ rtnl_lock();
+ if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) {
+ rtnl_unlock();
+ return -ENODEV;
+ }
+ return 0;
+}
+
+#define DEBUGFS_STATS_FILE(name, buflen, fmt, value...) \
+ DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
+
+static ssize_t format_devstat_counter(struct ieee80211_local *local,
+ char __user *userbuf,
+ size_t count, loff_t *ppos,
+ int (*printvalue)(struct ieee80211_low_level_stats *stats, char *buf,
+ int buflen))
+{
+ struct ieee80211_low_level_stats stats;
+ char buf[20];
+ int res;
+
+ if (!local->ops->get_stats)
+ return -EOPNOTSUPP;
+
+ res = rtnl_lock_local(local);
+ if (res)
+ return res;
+
+ res = local->ops->get_stats(local_to_hw(local), &stats);
+ rtnl_unlock();
+ if (!res)
+ res = printvalue(&stats, buf, sizeof(buf));
+ return simple_read_from_buffer(userbuf, count, ppos, buf, res);
+}
+
+#define DEBUGFS_DEVSTATS_FILE(name) \
+static int print_devstats_##name(struct ieee80211_low_level_stats *stats,\
+ char *buf, int buflen) \
+{ \
+ return scnprintf(buf, buflen, "%u\n", stats->name); \
+} \
+static ssize_t stats_ ##name## _read(struct file *file, \
+ char __user *userbuf, \
+ size_t count, loff_t *ppos) \
+{ \
+ return format_devstat_counter(file->private_data, \
+ userbuf, \
+ count, \
+ ppos, \
+ print_devstats_##name); \
+} \
+ \
+static const struct file_operations stats_ ##name## _ops = { \
+ .read = stats_ ##name## _read, \
+ .open = mac80211_open_file_generic, \
+};
+
+#define DEBUGFS_STATS_ADD(name) \
+ local->debugfs.stats.name = debugfs_create_file(#name, 0444, statsd,\
+ local, &stats_ ##name## _ops);
+
+#define DEBUGFS_STATS_DEL(name) \
+ debugfs_remove(local->debugfs.stats.name); \
+ local->debugfs.stats.name = NULL;
+
+DEBUGFS_STATS_FILE(transmitted_fragment_count, 20, "%u",
+ local->dot11TransmittedFragmentCount);
+DEBUGFS_STATS_FILE(multicast_transmitted_frame_count, 20, "%u",
+ local->dot11MulticastTransmittedFrameCount);
+DEBUGFS_STATS_FILE(failed_count, 20, "%u",
+ local->dot11FailedCount);
+DEBUGFS_STATS_FILE(retry_count, 20, "%u",
+ local->dot11RetryCount);
+DEBUGFS_STATS_FILE(multiple_retry_count, 20, "%u",
+ local->dot11MultipleRetryCount);
+DEBUGFS_STATS_FILE(frame_duplicate_count, 20, "%u",
+ local->dot11FrameDuplicateCount);
+DEBUGFS_STATS_FILE(received_fragment_count, 20, "%u",
+ local->dot11ReceivedFragmentCount);
+DEBUGFS_STATS_FILE(multicast_received_frame_count, 20, "%u",
+ local->dot11MulticastReceivedFrameCount);
+DEBUGFS_STATS_FILE(transmitted_frame_count, 20, "%u",
+ local->dot11TransmittedFrameCount);
+DEBUGFS_STATS_FILE(wep_undecryptable_count, 20, "%u",
+ local->dot11WEPUndecryptableCount);
+DEBUGFS_STATS_FILE(num_scans, 20, "%u",
+ local->scan.num_scans);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+DEBUGFS_STATS_FILE(tx_handlers_drop, 20, "%u",
+ local->tx_handlers_drop);
+DEBUGFS_STATS_FILE(tx_handlers_queued, 20, "%u",
+ local->tx_handlers_queued);
+DEBUGFS_STATS_FILE(tx_handlers_drop_unencrypted, 20, "%u",
+ local->tx_handlers_drop_unencrypted);
+DEBUGFS_STATS_FILE(tx_handlers_drop_fragment, 20, "%u",
+ local->tx_handlers_drop_fragment);
+DEBUGFS_STATS_FILE(tx_handlers_drop_wep, 20, "%u",
+ local->tx_handlers_drop_wep);
+DEBUGFS_STATS_FILE(tx_handlers_drop_not_assoc, 20, "%u",
+ local->tx_handlers_drop_not_assoc);
+DEBUGFS_STATS_FILE(tx_handlers_drop_unauth_port, 20, "%u",
+ local->tx_handlers_drop_unauth_port);
+DEBUGFS_STATS_FILE(rx_handlers_drop, 20, "%u",
+ local->rx_handlers_drop);
+DEBUGFS_STATS_FILE(rx_handlers_queued, 20, "%u",
+ local->rx_handlers_queued);
+DEBUGFS_STATS_FILE(rx_handlers_drop_nullfunc, 20, "%u",
+ local->rx_handlers_drop_nullfunc);
+DEBUGFS_STATS_FILE(rx_handlers_drop_defrag, 20, "%u",
+ local->rx_handlers_drop_defrag);
+DEBUGFS_STATS_FILE(rx_handlers_drop_short, 20, "%u",
+ local->rx_handlers_drop_short);
+DEBUGFS_STATS_FILE(rx_handlers_drop_passive_scan, 20, "%u",
+ local->rx_handlers_drop_passive_scan);
+DEBUGFS_STATS_FILE(tx_expand_skb_head, 20, "%u",
+ local->tx_expand_skb_head);
+DEBUGFS_STATS_FILE(tx_expand_skb_head_cloned, 20, "%u",
+ local->tx_expand_skb_head_cloned);
+DEBUGFS_STATS_FILE(rx_expand_skb_head, 20, "%u",
+ local->rx_expand_skb_head);
+DEBUGFS_STATS_FILE(rx_expand_skb_head2, 20, "%u",
+ local->rx_expand_skb_head2);
+DEBUGFS_STATS_FILE(rx_handlers_fragments, 20, "%u",
+ local->rx_handlers_fragments);
+DEBUGFS_STATS_FILE(tx_status_drop, 20, "%u",
+ local->tx_status_drop);
+#endif
+
+DEBUGFS_DEVSTATS_FILE(dot11ACKFailureCount);
+DEBUGFS_DEVSTATS_FILE(dot11RTSFailureCount);
+DEBUGFS_DEVSTATS_FILE(dot11FCSErrorCount);
+DEBUGFS_DEVSTATS_FILE(dot11RTSSuccessCount);
+
+static ssize_t stats_wme_rx_queue_read(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_local *local = file->private_data;
+ char buf[NUM_RX_DATA_QUEUES*15], *p = buf;
+ int i;
+
+ for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
+ p += scnprintf(p, sizeof(buf)+buf-p,
+ "%u\n", local->wme_rx_queue[i]);
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+}
+
+static const struct file_operations stats_wme_rx_queue_ops = {
+ .read = stats_wme_rx_queue_read,
+ .open = mac80211_open_file_generic,
+};
+
+static ssize_t stats_wme_tx_queue_read(struct file *file,
+ char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ieee80211_local *local = file->private_data;
+ char buf[NUM_TX_DATA_QUEUES*15], *p = buf;
+ int i;
+
+ for (i = 0; i < NUM_TX_DATA_QUEUES; i++)
+ p += scnprintf(p, sizeof(buf)+buf-p,
+ "%u\n", local->wme_tx_queue[i]);
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, p-buf);
+}
+
+static const struct file_operations stats_wme_tx_queue_ops = {
+ .read = stats_wme_tx_queue_read,
+ .open = mac80211_open_file_generic,
+};
+
+
+void debugfs_hw_add(struct ieee80211_local *local)
+{
+ struct dentry *phyd = local->hw.wiphy->debugfsdir;
+ struct dentry *statsd;
+
+ if (!phyd)
+ return;
+
+ DEBUGFS_ADD(channel);
+ DEBUGFS_ADD(frequency);
+ DEBUGFS_ADD(radar_detect);
+ DEBUGFS_ADD(antenna_sel_tx);
+ DEBUGFS_ADD(antenna_sel_rx);
+ DEBUGFS_ADD(bridge_packets);
+ DEBUGFS_ADD(key_tx_rx_threshold);
+ DEBUGFS_ADD(rts_threshold);
+ DEBUGFS_ADD(fragmentation_threshold);
+ DEBUGFS_ADD(short_retry_limit);
+ DEBUGFS_ADD(long_retry_limit);
+ DEBUGFS_ADD(total_ps_buffered);
+ DEBUGFS_ADD(mode);
+ DEBUGFS_ADD(wep_iv);
+ DEBUGFS_ADD(tx_power_reduction);
+ DEBUGFS_ADD(modes);
+
+ statsd = debugfs_create_dir("statistics", phyd);
+ local->debugfs.statistics = statsd;
+
+ /* if the dir failed, don't put all the other things into the root! */
+ if (!statsd)
+ return;
+
+ DEBUGFS_STATS_ADD(transmitted_fragment_count);
+ DEBUGFS_STATS_ADD(multicast_transmitted_frame_count);
+ DEBUGFS_STATS_ADD(failed_count);
+ DEBUGFS_STATS_ADD(retry_count);
+ DEBUGFS_STATS_ADD(multiple_retry_count);
+ DEBUGFS_STATS_ADD(frame_duplicate_count);
+ DEBUGFS_STATS_ADD(received_fragment_count);
+ DEBUGFS_STATS_ADD(multicast_received_frame_count);
+ DEBUGFS_STATS_ADD(transmitted_frame_count);
+ DEBUGFS_STATS_ADD(wep_undecryptable_count);
+ DEBUGFS_STATS_ADD(num_scans);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ DEBUGFS_STATS_ADD(tx_handlers_drop);
+ DEBUGFS_STATS_ADD(tx_handlers_queued);
+ DEBUGFS_STATS_ADD(tx_handlers_drop_unencrypted);
+ DEBUGFS_STATS_ADD(tx_handlers_drop_fragment);
+ DEBUGFS_STATS_ADD(tx_handlers_drop_wep);
+ DEBUGFS_STATS_ADD(tx_handlers_drop_not_assoc);
+ DEBUGFS_STATS_ADD(tx_handlers_drop_unauth_port);
+ DEBUGFS_STATS_ADD(rx_handlers_drop);
+ DEBUGFS_STATS_ADD(rx_handlers_queued);
+ DEBUGFS_STATS_ADD(rx_handlers_drop_nullfunc);
+ DEBUGFS_STATS_ADD(rx_handlers_drop_defrag);
+ DEBUGFS_STATS_ADD(rx_handlers_drop_short);
+ DEBUGFS_STATS_ADD(rx_handlers_drop_passive_scan);
+ DEBUGFS_STATS_ADD(tx_expand_skb_head);
+ DEBUGFS_STATS_ADD(tx_expand_skb_head_cloned);
+ DEBUGFS_STATS_ADD(rx_expand_skb_head);
+ DEBUGFS_STATS_ADD(rx_expand_skb_head2);
+ DEBUGFS_STATS_ADD(rx_handlers_fragments);
+ DEBUGFS_STATS_ADD(tx_status_drop);
+#endif
+ DEBUGFS_STATS_ADD(dot11ACKFailureCount);
+ DEBUGFS_STATS_ADD(dot11RTSFailureCount);
+ DEBUGFS_STATS_ADD(dot11FCSErrorCount);
+ DEBUGFS_STATS_ADD(dot11RTSSuccessCount);
+ DEBUGFS_STATS_ADD(wme_tx_queue);
+ DEBUGFS_STATS_ADD(wme_rx_queue);
+}
+
+void debugfs_hw_del(struct ieee80211_local *local)
+{
+ DEBUGFS_DEL(channel);
+ DEBUGFS_DEL(frequency);
+ DEBUGFS_DEL(radar_detect);
+ DEBUGFS_DEL(antenna_sel_tx);
+ DEBUGFS_DEL(antenna_sel_rx);
+ DEBUGFS_DEL(bridge_packets);
+ DEBUGFS_DEL(key_tx_rx_threshold);
+ DEBUGFS_DEL(rts_threshold);
+ DEBUGFS_DEL(fragmentation_threshold);
+ DEBUGFS_DEL(short_retry_limit);
+ DEBUGFS_DEL(long_retry_limit);
+ DEBUGFS_DEL(total_ps_buffered);
+ DEBUGFS_DEL(mode);
+ DEBUGFS_DEL(wep_iv);
+ DEBUGFS_DEL(tx_power_reduction);
+ DEBUGFS_DEL(modes);
+
+ DEBUGFS_STATS_DEL(transmitted_fragment_count);
+ DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
+ DEBUGFS_STATS_DEL(failed_count);
+ DEBUGFS_STATS_DEL(retry_count);
+ DEBUGFS_STATS_DEL(multiple_retry_count);
+ DEBUGFS_STATS_DEL(frame_duplicate_count);
+ DEBUGFS_STATS_DEL(received_fragment_count);
+ DEBUGFS_STATS_DEL(multicast_received_frame_count);
+ DEBUGFS_STATS_DEL(transmitted_frame_count);
+ DEBUGFS_STATS_DEL(wep_undecryptable_count);
+ DEBUGFS_STATS_DEL(num_scans);
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ DEBUGFS_STATS_DEL(tx_handlers_drop);
+ DEBUGFS_STATS_DEL(tx_handlers_queued);
+ DEBUGFS_STATS_DEL(tx_handlers_drop_unencrypted);
+ DEBUGFS_STATS_DEL(tx_handlers_drop_fragment);
+ DEBUGFS_STATS_DEL(tx_handlers_drop_wep);
+ DEBUGFS_STATS_DEL(tx_handlers_drop_not_assoc);
+ DEBUGFS_STATS_DEL(tx_handlers_drop_unauth_port);
+ DEBUGFS_STATS_DEL(rx_handlers_drop);
+ DEBUGFS_STATS_DEL(rx_handlers_queued);
+ DEBUGFS_STATS_DEL(rx_handlers_drop_nullfunc);
+ DEBUGFS_STATS_DEL(rx_handlers_drop_defrag);
+ DEBUGFS_STATS_DEL(rx_handlers_drop_short);
+ DEBUGFS_STATS_DEL(rx_handlers_drop_passive_scan);
+ DEBUGFS_STATS_DEL(tx_expand_skb_head);
+ DEBUGFS_STATS_DEL(tx_expand_skb_head_cloned);
+ DEBUGFS_STATS_DEL(rx_expand_skb_head);
+ DEBUGFS_STATS_DEL(rx_expand_skb_head2);
+ DEBUGFS_STATS_DEL(rx_handlers_fragments);
+ DEBUGFS_STATS_DEL(tx_status_drop);
+#endif
+ DEBUGFS_STATS_DEL(dot11ACKFailureCount);
+ DEBUGFS_STATS_DEL(dot11RTSFailureCount);
+ DEBUGFS_STATS_DEL(dot11FCSErrorCount);
+ DEBUGFS_STATS_DEL(dot11RTSSuccessCount);
+ DEBUGFS_STATS_DEL(wme_tx_queue);
+ DEBUGFS_STATS_DEL(wme_rx_queue);
+
+ debugfs_remove(local->debugfs.statistics);
+ local->debugfs.statistics = NULL;
+}
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h
new file mode 100644
index 0000000..75df742
--- /dev/null
+++ b/net/mac80211/debugfs.h
@@ -0,0 +1,15 @@
+#ifndef __MAC80211_DEBUGFS_H
+#define __MAC80211_DEBUGFS_H
+
+#ifdef CONFIG_DEBUG_FS
+extern void debugfs_hw_add(struct ieee80211_local *local);
+extern void debugfs_hw_del(struct ieee80211_local *local);
+#else
+static inline void debugfs_hw_add(struct ieee80211_local *local)
+{
+ return;
+}
+static inline void debugfs_hw_del(struct ieee80211_local *local) {}
+#endif
+
+#endif /* __MAC80211_DEBUGFS_H */
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 17c0ef9..78e68db 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -34,6 +34,7 @@ #include "aes_ccm.h"
#include "ieee80211_led.h"
#include "ieee80211_cfg.h"
#include "ieee80211_sysfs.h"
+#include "debugfs.h"

/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
@@ -4448,7 +4449,6 @@ int ieee80211_init_rate_ctrl_alg(struct
const char *name)
{
struct rate_control_ref *ref, *old;
- int res;

ASSERT_RTNL();
if (local->open_count || netif_running(local->mdev) ||
@@ -4461,18 +4461,10 @@ int ieee80211_init_rate_ctrl_alg(struct
"algorithm\n", local->mdev->name);
return -ENOENT;
}
- res = rate_control_add_attrs(ref, &local->hw.wiphy->dev.kobj);
- if (res < 0) {
- printk(KERN_DEBUG "%s: Failed to register sysfs attributes "
- "for rate control\n", local->mdev->name);
- rate_control_put(ref);
- return res;
- }

old = local->rate_ctrl;
local->rate_ctrl = ref;
if (old) {
- rate_control_remove_attrs(ref, &local->hw.wiphy->dev.kobj);
rate_control_put(old);
sta_info_flush(local, NULL);
}
@@ -4491,7 +4483,6 @@ static void rate_control_deinitialize(st

ref = local->rate_ctrl;
local->rate_ctrl = NULL;
- rate_control_remove_attrs(ref, &local->hw.wiphy->dev.kobj);
rate_control_put(ref);
}

@@ -4623,9 +4614,7 @@ int ieee80211_register_hw(struct ieee802
if (result < 0)
return result;

- result = ieee80211_dev_sysfs_add(local);
- if (result < 0)
- goto fail_sysfs;
+ debugfs_hw_add(local);

local->hw.conf.beacon_int = 1000;

@@ -4699,8 +4688,7 @@ fail_dev:
rtnl_unlock();
sta_info_stop(local);
fail_sta_info:
- ieee80211_dev_sysfs_del(local);
-fail_sysfs:
+ debugfs_hw_del(local);
wiphy_unregister(local->hw.wiphy);
return result;
}
@@ -4773,7 +4761,7 @@ void ieee80211_unregister_hw(struct ieee
ieee80211_clear_tx_pending(local);
sta_info_stop(local);
rate_control_deinitialize(local);
- ieee80211_dev_sysfs_del(local);
+ debugfs_hw_del(local);

for (i = 0; i < NUM_IEEE80211_MODES; i++) {
kfree(local->supp_rates[i]);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9ea1005..18eeb86 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -540,6 +540,68 @@ #endif /* CONFIG_MAC80211_DEBUG_COUNTERS
* (1 << MODE_*) */

int user_space_mlme;
+
+#ifdef CONFIG_DEBUG_FS
+ struct local_debugfsdentries {
+ struct dentry *channel;
+ struct dentry *frequency;
+ struct dentry *radar_detect;
+ struct dentry *antenna_sel_tx;
+ struct dentry *antenna_sel_rx;
+ struct dentry *bridge_packets;
+ struct dentry *key_tx_rx_threshold;
+ struct dentry *rts_threshold;
+ struct dentry *fragmentation_threshold;
+ struct dentry *short_retry_limit;
+ struct dentry *long_retry_limit;
+ struct dentry *total_ps_buffered;
+ struct dentry *mode;
+ struct dentry *wep_iv;
+ struct dentry *tx_power_reduction;
+ struct dentry *modes;
+ struct dentry *statistics;
+ struct local_debugfsdentries_statsdentries {
+ struct dentry *transmitted_fragment_count;
+ struct dentry *multicast_transmitted_frame_count;
+ struct dentry *failed_count;
+ struct dentry *retry_count;
+ struct dentry *multiple_retry_count;
+ struct dentry *frame_duplicate_count;
+ struct dentry *received_fragment_count;
+ struct dentry *multicast_received_frame_count;
+ struct dentry *transmitted_frame_count;
+ struct dentry *wep_undecryptable_count;
+ struct dentry *num_scans;
+#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
+ struct dentry *tx_handlers_drop;
+ struct dentry *tx_handlers_queued;
+ struct dentry *tx_handlers_drop_unencrypted;
+ struct dentry *tx_handlers_drop_fragment;
+ struct dentry *tx_handlers_drop_wep;
+ struct dentry *tx_handlers_drop_not_assoc;
+ struct dentry *tx_handlers_drop_unauth_port;
+ struct dentry *rx_handlers_drop;
+ struct dentry *rx_handlers_queued;
+ struct dentry *rx_handlers_drop_nullfunc;
+ struct dentry *rx_handlers_drop_defrag;
+ struct dentry *rx_handlers_drop_short;
+ struct dentry *rx_handlers_drop_passive_scan;
+ struct dentry *tx_expand_skb_head;
+ struct dentry *tx_expand_skb_head_cloned;
+ struct dentry *rx_expand_skb_head;
+ struct dentry *rx_expand_skb_head2;
+ struct dentry *rx_handlers_fragments;
+ struct dentry *tx_status_drop;
+#endif
+ struct dentry *dot11ACKFailureCount;
+ struct dentry *dot11RTSFailureCount;
+ struct dentry *dot11FCSErrorCount;
+ struct dentry *dot11RTSSuccessCount;
+ struct dentry *wme_tx_queue;
+ struct dentry *wme_rx_queue;
+ } stats;
+ } debugfs;
+#endif
};

static inline struct ieee80211_local *hw_to_local(
diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h
index 3bb09f2..b96a89d 100644
--- a/net/mac80211/ieee80211_rate.h
+++ b/net/mac80211/ieee80211_rate.h
@@ -123,21 +123,6 @@ static inline void rate_control_free_sta
ref->ops->free_sta(ref->priv, priv);
}

-static inline int rate_control_add_attrs(struct rate_control_ref *ref,
- struct kobject *kobj)
-{
- if (ref->ops->add_attrs)
- return ref->ops->add_attrs(ref->priv, kobj);
- return 0;
-}
-
-static inline void rate_control_remove_attrs(struct rate_control_ref *ref,
- struct kobject *kobj)
-{
- if (ref->ops->remove_attrs)
- ref->ops->remove_attrs(ref->priv, kobj);
-}
-
static inline int rate_control_add_sta_attrs(struct sta_info *sta,
struct kobject *kobj)
{
diff --git a/net/mac80211/ieee80211_sysfs.c b/net/mac80211/ieee80211_sysfs.c
index 07dc073..8072617 100644
--- a/net/mac80211/ieee80211_sysfs.c
+++ b/net/mac80211/ieee80211_sysfs.c
@@ -34,334 +34,6 @@ static inline int rtnl_lock_local(struct
return 0;
}

-static const char *ieee80211_mode_str_short(int mode)
-{
- switch (mode) {
- case MODE_IEEE80211A:
- return "802.11a";
- case MODE_IEEE80211B:
- return "802.11b";
- case MODE_IEEE80211G:
- return "802.11g";
- case MODE_ATHEROS_TURBO:
- return "AtherosTurbo";
- default:
- return "UNKNOWN";
- }
-}
-
-static const char *ieee80211_mode_str(int mode)
-{
- switch (mode) {
- case MODE_IEEE80211A:
- return "IEEE 802.11a";
- case MODE_IEEE80211B:
- return "IEEE 802.11b";
- case MODE_IEEE80211G:
- return "IEEE 802.11g";
- case MODE_ATHEROS_TURBO:
- return "Atheros Turbo (5 GHz)";
- default:
- return "UNKNOWN";
- }
-}
-
-/* attributes in /sys/class/ieee80211/phyX/ */
-
-static ssize_t store_rate_ctrl_alg(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct ieee80211_local *local = to_ieee80211_local(dev);
- int res;
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- res = rtnl_lock_local(local);
- if (res)
- return res;
- res = ieee80211_init_rate_ctrl_alg(local, buf);
- rtnl_unlock();
- return res < 0 ? res : len;
-}
-
-static ssize_t ieee80211_local_show(
- struct device *dev,
- struct device_attribute *attr,
- char *buf,
- ssize_t (*format)(struct ieee80211_local *, char *))
-{
- struct ieee80211_local *local = to_ieee80211_local(dev);
- ssize_t ret = -EINVAL;
-
- if (local->reg_state == IEEE80211_DEV_REGISTERED)
- ret = (*format)(local, buf);
- return ret;
-}
-
-#define IEEE80211_LOCAL_FMT(name, field, format_string) \
-static ssize_t ieee80211_local_fmt_##name(struct ieee80211_local *local,\
- char *buf) \
-{ \
- return sprintf(buf, format_string, local->field); \
-}
-
-#define __IEEE80211_LOCAL_SHOW(name) \
-static ssize_t ieee80211_local_show_##name(struct device *dev, \
- struct device_attribute *attr,\
- char *buf) \
-{ \
- return ieee80211_local_show(dev, attr, buf, \
- ieee80211_local_fmt_##name); \
-}
-
-#define IEEE80211_LOCAL_SHOW(name, field, format) \
- IEEE80211_LOCAL_FMT(name, field, format "\n") \
- __IEEE80211_LOCAL_SHOW(name)
-
-IEEE80211_LOCAL_SHOW(channel, hw.conf.channel, "%d");
-IEEE80211_LOCAL_SHOW(frequency, hw.conf.freq, "%d");
-IEEE80211_LOCAL_SHOW(radar_detect, hw.conf.radar_detect, "%d");
-IEEE80211_LOCAL_SHOW(antenna_sel_tx, hw.conf.antenna_sel_tx, "%d");
-IEEE80211_LOCAL_SHOW(antenna_sel_rx, hw.conf.antenna_sel_rx, "%d");
-IEEE80211_LOCAL_SHOW(bridge_packets, bridge_packets, "%d");
-IEEE80211_LOCAL_SHOW(key_tx_rx_threshold, key_tx_rx_threshold, "%d");
-IEEE80211_LOCAL_SHOW(rts_threshold, rts_threshold, "%d");
-IEEE80211_LOCAL_SHOW(fragmentation_threshold, fragmentation_threshold, "%d");
-IEEE80211_LOCAL_SHOW(short_retry_limit, short_retry_limit, "%d");
-IEEE80211_LOCAL_SHOW(long_retry_limit, long_retry_limit, "%d");
-IEEE80211_LOCAL_SHOW(total_ps_buffered, total_ps_buffered, "%d");
-
-static ssize_t ieee80211_local_fmt_mode(struct ieee80211_local *local,
- char *buf)
-{
- return sprintf(buf, "%s\n", ieee80211_mode_str(local->hw.conf.phymode));
-}
-__IEEE80211_LOCAL_SHOW(mode);
-
-static ssize_t ieee80211_local_fmt_wep_iv(struct ieee80211_local *local,
- char *buf)
-{
- return sprintf(buf, "%#06x\n", local->wep_iv & 0xffffff);
-}
-__IEEE80211_LOCAL_SHOW(wep_iv);
-
-static ssize_t ieee80211_local_fmt_tx_power_reduction(struct ieee80211_local
- *local, char *buf)
-{
- short tx_power_reduction = local->hw.conf.tx_power_reduction;
-
- return sprintf(buf, "%d.%d dBm\n", tx_power_reduction / 10,
- tx_power_reduction % 10);
-}
-__IEEE80211_LOCAL_SHOW(tx_power_reduction);
-
-static ssize_t ieee80211_local_fmt_modes(struct ieee80211_local *local,
- char *buf)
-{
- struct ieee80211_hw_mode *mode;
- char *p = buf;
-
- /* FIXME: Locking? Could register a mode in the meantime. */
- list_for_each_entry(mode, &local->modes_list, list)
- p += sprintf(p, "%s\n", ieee80211_mode_str_short(mode->mode));
-
- return (p - buf);
-}
-__IEEE80211_LOCAL_SHOW(modes);
-
-static ssize_t ieee80211_local_fmt_rate_ctrl_alg(struct ieee80211_local *local,
- char *buf)
-{
- struct rate_control_ref *ref = local->rate_ctrl;
- if (ref)
- return sprintf(buf, "%s\n", ref->ops->name);
- return 0;
-}
-__IEEE80211_LOCAL_SHOW(rate_ctrl_alg);
-
-static struct device_attribute ieee80211_dev_attrs[] = {
- __ATTR(channel, S_IRUGO, ieee80211_local_show_channel, NULL),
- __ATTR(frequency, S_IRUGO, ieee80211_local_show_frequency, NULL),
- __ATTR(radar_detect, S_IRUGO, ieee80211_local_show_radar_detect, NULL),
- __ATTR(antenna_sel_tx, S_IRUGO, ieee80211_local_show_antenna_sel_tx, NULL),
- __ATTR(antenna_sel_rx, S_IRUGO, ieee80211_local_show_antenna_sel_rx, NULL),
- __ATTR(bridge_packets, S_IRUGO, ieee80211_local_show_bridge_packets, NULL),
- __ATTR(key_tx_rx_threshold, S_IRUGO, ieee80211_local_show_key_tx_rx_threshold, NULL),
- __ATTR(rts_threshold, S_IRUGO, ieee80211_local_show_rts_threshold, NULL),
- __ATTR(fragmentation_threshold, S_IRUGO, ieee80211_local_show_fragmentation_threshold, NULL),
- __ATTR(short_retry_limit, S_IRUGO, ieee80211_local_show_short_retry_limit, NULL),
- __ATTR(long_retry_limit, S_IRUGO, ieee80211_local_show_long_retry_limit, NULL),
- __ATTR(total_ps_buffered, S_IRUGO, ieee80211_local_show_total_ps_buffered, NULL),
- __ATTR(mode, S_IRUGO, ieee80211_local_show_mode, NULL),
- __ATTR(wep_iv, S_IRUGO, ieee80211_local_show_wep_iv, NULL),
- __ATTR(tx_power_reduction, S_IRUGO, ieee80211_local_show_tx_power_reduction, NULL),
- __ATTR(modes, S_IRUGO, ieee80211_local_show_modes, NULL),
- __ATTR(rate_ctrl_alg, S_IRUGO | S_IWUGO, ieee80211_local_show_rate_ctrl_alg, store_rate_ctrl_alg),
-};
-
-/* attributes in /sys/class/ieee80211/phyX/statistics/ */
-
-#define IEEE80211_LOCAL_ATTR(name, field, format) \
-IEEE80211_LOCAL_SHOW(name, field, format) \
-static DEVICE_ATTR(name, S_IRUGO, ieee80211_local_show_##name, NULL);
-
-IEEE80211_LOCAL_ATTR(transmitted_fragment_count, dot11TransmittedFragmentCount, "%u");
-IEEE80211_LOCAL_ATTR(multicast_transmitted_frame_count, dot11MulticastTransmittedFrameCount, "%u");
-IEEE80211_LOCAL_ATTR(failed_count, dot11FailedCount, "%u");
-IEEE80211_LOCAL_ATTR(retry_count, dot11RetryCount, "%u");
-IEEE80211_LOCAL_ATTR(multiple_retry_count, dot11MultipleRetryCount, "%u");
-IEEE80211_LOCAL_ATTR(frame_duplicate_count, dot11FrameDuplicateCount, "%u");
-IEEE80211_LOCAL_ATTR(received_fragment_count, dot11ReceivedFragmentCount, "%u");
-IEEE80211_LOCAL_ATTR(multicast_received_frame_count, dot11MulticastReceivedFrameCount, "%u");
-IEEE80211_LOCAL_ATTR(transmitted_frame_count, dot11TransmittedFrameCount, "%u");
-IEEE80211_LOCAL_ATTR(wep_undecryptable_count, dot11WEPUndecryptableCount, "%u");
-IEEE80211_LOCAL_ATTR(num_scans, scan.num_scans, "%u");
-
-#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
-IEEE80211_LOCAL_ATTR(tx_handlers_drop, tx_handlers_drop, "%u");
-IEEE80211_LOCAL_ATTR(tx_handlers_queued, tx_handlers_queued, "%u");
-IEEE80211_LOCAL_ATTR(tx_handlers_drop_unencrypted, tx_handlers_drop_unencrypted, "%u");
-IEEE80211_LOCAL_ATTR(tx_handlers_drop_fragment, tx_handlers_drop_fragment, "%u");
-IEEE80211_LOCAL_ATTR(tx_handlers_drop_wep, tx_handlers_drop_wep, "%u");
-IEEE80211_LOCAL_ATTR(tx_handlers_drop_not_assoc, tx_handlers_drop_not_assoc, "%u");
-IEEE80211_LOCAL_ATTR(tx_handlers_drop_unauth_port, tx_handlers_drop_unauth_port, "%u");
-IEEE80211_LOCAL_ATTR(rx_handlers_drop, rx_handlers_drop, "%u");
-IEEE80211_LOCAL_ATTR(rx_handlers_queued, rx_handlers_queued, "%u");
-IEEE80211_LOCAL_ATTR(rx_handlers_drop_nullfunc, rx_handlers_drop_nullfunc, "%u");
-IEEE80211_LOCAL_ATTR(rx_handlers_drop_defrag, rx_handlers_drop_defrag, "%u");
-IEEE80211_LOCAL_ATTR(rx_handlers_drop_short, rx_handlers_drop_short, "%u");
-IEEE80211_LOCAL_ATTR(rx_handlers_drop_passive_scan, rx_handlers_drop_passive_scan, "%u");
-IEEE80211_LOCAL_ATTR(tx_expand_skb_head, tx_expand_skb_head, "%u");
-IEEE80211_LOCAL_ATTR(tx_expand_skb_head_cloned, tx_expand_skb_head_cloned, "%u");
-IEEE80211_LOCAL_ATTR(rx_expand_skb_head, rx_expand_skb_head, "%u");
-IEEE80211_LOCAL_ATTR(rx_expand_skb_head2, rx_expand_skb_head2, "%u");
-IEEE80211_LOCAL_ATTR(rx_handlers_fragments, rx_handlers_fragments, "%u");
-IEEE80211_LOCAL_ATTR(tx_status_drop, tx_status_drop, "%u");
-
-static ssize_t ieee80211_local_fmt_wme_rx_queue(struct ieee80211_local *local,
- char *buf)
-{
- int i;
- char *p = buf;
-
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
- p += sprintf(p, "%u\n", local->wme_rx_queue[i]);
- return (p - buf);
-}
-__IEEE80211_LOCAL_SHOW(wme_rx_queue);
-static DEVICE_ATTR(wme_rx_queue, S_IRUGO,
- ieee80211_local_show_wme_rx_queue, NULL);
-
-static ssize_t ieee80211_local_fmt_wme_tx_queue(struct ieee80211_local *local,
- char *buf)
-{
- int i;
- char *p = buf;
-
- for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
- p += sprintf(p, "%u\n", local->wme_tx_queue[i]);
- return (p - buf);
-}
-__IEEE80211_LOCAL_SHOW(wme_tx_queue);
-static DEVICE_ATTR(wme_tx_queue, S_IRUGO,
- ieee80211_local_show_wme_tx_queue, NULL);
-#endif
-
-static ssize_t ieee80211_stats_show(struct device *dev,
- struct device_attribute *attr,
- char *buf,
- ssize_t (*format)(struct ieee80211_low_level_stats *, char *))
-{
- struct ieee80211_local *local = to_ieee80211_local(dev);
- struct ieee80211_low_level_stats stats;
- ssize_t ret = -EINVAL;
-
- if (!local->ops->get_stats)
- return -EOPNOTSUPP;
- ret = rtnl_lock_local(local);
- if (ret)
- return ret;
- ret = local->ops->get_stats(local_to_hw(local), &stats);
- rtnl_unlock();
- if (!ret)
- ret = (*format)(&stats, buf);
- return ret;
-}
-
-#define IEEE80211_STATS_FMT(name, field, format_string) \
-static ssize_t ieee80211_stats_fmt_##name(struct ieee80211_low_level_stats \
- *stats, char *buf) \
-{ \
- return sprintf(buf, format_string, stats->field); \
-}
-
-#define __IEEE80211_STATS_SHOW(name) \
-static ssize_t ieee80211_stats_show_##name(struct device *dev, \
- struct device_attribute *attr,\
- char *buf) \
-{ \
- return ieee80211_stats_show(dev, attr, buf, \
- ieee80211_stats_fmt_##name); \
-}
-
-#define IEEE80211_STATS_ATTR(name, field, format) \
-IEEE80211_STATS_FMT(name, field, format "\n") \
-__IEEE80211_STATS_SHOW(name) \
-static DEVICE_ATTR(name, S_IRUGO, ieee80211_stats_show_##name, NULL);
-
-IEEE80211_STATS_ATTR(ack_failure_count, dot11ACKFailureCount, "%u");
-IEEE80211_STATS_ATTR(rts_failure_count, dot11RTSFailureCount, "%u");
-IEEE80211_STATS_ATTR(fcs_error_count, dot11FCSErrorCount, "%u");
-IEEE80211_STATS_ATTR(rts_success_count, dot11RTSSuccessCount, "%u");
-
-static struct attribute *ieee80211_stats_attrs[] = {
- &dev_attr_transmitted_fragment_count.attr,
- &dev_attr_multicast_transmitted_frame_count.attr,
- &dev_attr_failed_count.attr,
- &dev_attr_retry_count.attr,
- &dev_attr_multiple_retry_count.attr,
- &dev_attr_frame_duplicate_count.attr,
- &dev_attr_received_fragment_count.attr,
- &dev_attr_multicast_received_frame_count.attr,
- &dev_attr_transmitted_frame_count.attr,
- &dev_attr_wep_undecryptable_count.attr,
- &dev_attr_ack_failure_count.attr,
- &dev_attr_rts_failure_count.attr,
- &dev_attr_fcs_error_count.attr,
- &dev_attr_rts_success_count.attr,
- &dev_attr_num_scans.attr,
-#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
- &dev_attr_tx_handlers_drop.attr,
- &dev_attr_tx_handlers_queued.attr,
- &dev_attr_tx_handlers_drop_unencrypted.attr,
- &dev_attr_tx_handlers_drop_fragment.attr,
- &dev_attr_tx_handlers_drop_wep.attr,
- &dev_attr_tx_handlers_drop_not_assoc.attr,
- &dev_attr_tx_handlers_drop_unauth_port.attr,
- &dev_attr_rx_handlers_drop.attr,
- &dev_attr_rx_handlers_queued.attr,
- &dev_attr_rx_handlers_drop_nullfunc.attr,
- &dev_attr_rx_handlers_drop_defrag.attr,
- &dev_attr_rx_handlers_drop_short.attr,
- &dev_attr_rx_handlers_drop_passive_scan.attr,
- &dev_attr_tx_expand_skb_head.attr,
- &dev_attr_tx_expand_skb_head_cloned.attr,
- &dev_attr_rx_expand_skb_head.attr,
- &dev_attr_rx_expand_skb_head2.attr,
- &dev_attr_rx_handlers_fragments.attr,
- &dev_attr_tx_status_drop.attr,
- &dev_attr_wme_rx_queue.attr,
- &dev_attr_wme_tx_queue.attr,
-#endif
- NULL,
-};
-
-static struct attribute_group ieee80211_stats_group = {
- .name = "statistics",
- .attrs = ieee80211_stats_attrs,
-};
-
/* attributes in /sys/class/net/X/ */

static ssize_t ieee80211_if_show(struct device *d,
@@ -595,53 +267,6 @@ static struct attribute_group ieee80211_
.attrs = ieee80211_monitor_attrs,
};

-int ieee80211_dev_sysfs_add(struct ieee80211_local *local)
-{
- const struct device_attribute *attr;
- int i, err;
-
- for (i = 0; i < ARRAY_SIZE(ieee80211_dev_attrs); i++) {
- attr = &ieee80211_dev_attrs[i];
- err = sysfs_create_file(&local->hw.wiphy->dev.kobj,
- &attr->attr);
- if (err)
- goto unwind;
- }
-
- err = sysfs_create_group(&local->hw.wiphy->dev.kobj,
- &ieee80211_stats_group);
-
- if (err == 0)
- return err;
-
- unwind:
- /* one after the failed/last one */
- i--;
- while (i >= 0) {
- attr = &ieee80211_dev_attrs[i];
- sysfs_remove_file(&local->hw.wiphy->dev.kobj,
- &attr->attr);
- i--;
- }
- return err;
-}
-
-void ieee80211_dev_sysfs_del(struct ieee80211_local *local)
-{
- const struct device_attribute *attr;
- int i;
-
- sysfs_remove_group(&local->hw.wiphy->dev.kobj,
- &ieee80211_stats_group);
-
- for (i = 0; i < ARRAY_SIZE(ieee80211_dev_attrs); i++) {
- attr = &ieee80211_dev_attrs[i];
- sysfs_remove_file(&local->hw.wiphy->dev.kobj,
- &attr->attr);
- }
-}
-
-
/* /sys/class/net/X functions */

static void __ieee80211_remove_if_group(struct kobject *kobj,
diff --git a/net/mac80211/ieee80211_sysfs.h b/net/mac80211/ieee80211_sysfs.h
index 3d00b6d..1749cbd 100644
--- a/net/mac80211/ieee80211_sysfs.h
+++ b/net/mac80211/ieee80211_sysfs.h
@@ -6,7 +6,5 @@ #define __IEEE80211_SYSFS_H
int ieee80211_sysfs_add_netdevice(struct net_device *dev);
void ieee80211_sysfs_remove_netdevice(struct net_device *dev);
int ieee80211_sysfs_change_if_type(struct net_device *dev);
-int ieee80211_dev_sysfs_add(struct ieee80211_local *local);
-void ieee80211_dev_sysfs_del(struct ieee80211_local *local);

#endif /* __IEEE80211_SYSFS_H */
--
1.3.0


2007-03-23 20:43:28

by Jiri Benc

[permalink] [raw]
Subject: [PATCH 2/19] mac80211: remove useless callbacks from wmaster

Wireless handlers (and other callbacks) on master interface only confuse
users. Let's get rid of them.

Signed-off-by: Jiri Benc <[email protected]>

---

net/mac80211/ieee80211.c | 3 ---
net/mac80211/ieee80211_i.h | 1 -
net/mac80211/ieee80211_ioctl.c | 22 ----------------------
3 files changed, 0 insertions(+), 26 deletions(-)

9e00ff1fabe362774319e9d24fe866a0140b0f34
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 3d4fabe..e7576c5 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -4597,9 +4597,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(
sta_info_init(local);

mdev->hard_start_xmit = ieee80211_master_start_xmit;
- mdev->wireless_handlers = &ieee80211_iw_master_handler_def;
- mdev->do_ioctl = ieee80211_ioctl;
- mdev->change_mtu = ieee80211_change_mtu;
mdev->tx_timeout = ieee80211_tx_timeout;
mdev->get_stats = ieee80211_get_stats;
mdev->open = ieee80211_master_open;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9df8ef0..4398453 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -627,7 +627,6 @@ struct net_device_stats *ieee80211_dev_s
/* ieee80211_ioctl.c */
int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
extern const struct iw_handler_def ieee80211_iw_handler_def;
-extern const struct iw_handler_def ieee80211_iw_master_handler_def;

/* Set hw encryption from ieee80211 */
int ieee80211_set_hw_encryption(struct net_device *dev,
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index ae224c6..93a204b 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -3280,25 +3280,3 @@ const struct iw_handler_def ieee80211_iw
.private_args = (struct iw_priv_args *) ieee80211_ioctl_priv,
.get_wireless_stats = ieee80211_get_wireless_stats,
};
-
-/* Wireless handlers for master interface */
-
-static const iw_handler ieee80211_master_handler[] =
-{
- [SIOCGIWNAME - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwname,
- [SIOCSIWFREQ - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwfreq,
- [SIOCGIWFREQ - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwfreq,
- [SIOCGIWRANGE - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwrange,
- [SIOCSIWRTS - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwrts,
- [SIOCGIWRTS - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwrts,
- [SIOCSIWFRAG - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwfrag,
- [SIOCGIWFRAG - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwfrag,
- [SIOCSIWRETRY - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwretry,
- [SIOCGIWRETRY - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwretry,
-};
-
-const struct iw_handler_def ieee80211_iw_master_handler_def =
-{
- .num_standard = sizeof(ieee80211_master_handler) / sizeof(iw_handler),
- .standard = ieee80211_master_handler,
-};
--
1.3.0