netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/12] d80211: use sysfs instead of procfs
@ 2006-06-08  7:49 Jiri Benc
  2006-06-08  7:49 ` [PATCH 1/12] d80211: deinit sysfs in case of an error Jiri Benc
                   ` (11 more replies)
  0 siblings, 12 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

The following series of patches makes d80211 to use sysfs instead of procfs.
This means that custom reference counting in most structures is replaced by
kobjects and nearly all informations from procfs files are converted to
sysfs attributes.

The only information missing in sysfs (compared to procfs) is channels and
rates info. Implementing this in a sysfs way (i. e. one information per
attribute rule) requires a lot of code and (more important) adding kobjects
to channel and rate structures. I doubt these informations are really so
useful to be worth such complications. If there are good arguments why these
informations should be exported via sysfs I will add them.

If you find a better name for some object (directory) or attribute (file) or
just consider some name wrong or ugly, let me know please.

The third patch ("separate allocation of ieee80211_local") touches the code
outside of net/d80211 - it adds ieee80211_ptr to net_device structure.

All of patches can be also obtained from 'master' branch of
git://git.kernel.org/pub/scm/linux/kernel/git/jbenc/dscape.git

---

Jiri Benc:
      d80211: deinit sysfs in case of an error
      d80211: better sysfs registration of symlinks to wiphy
      d80211: separate allocation of ieee80211_local
      d80211: fix Oops when writing to add_ and remove_iface
      d80211: wiphy sysfs attributes
      d80211: network interface sysfs attributes
      d80211: rename sta_info_relase to sta_info_put
      d80211: sysfs attributes for associated stations
      d80211: remove useless parameters
      d80211: rate_control sysfs attributes
      d80211: encryption keys sysfs attributes
      d80211: remove procfs files

 include/linux/netdevice.h        |    1 
 net/d80211/Makefile              |    2 
 net/d80211/ieee80211.c           |  206 +++++++---
 net/d80211/ieee80211_dev.c       |   17 +
 net/d80211/ieee80211_i.h         |   45 ++
 net/d80211/ieee80211_iface.c     |   43 +-
 net/d80211/ieee80211_ioctl.c     |  213 ++++++----
 net/d80211/ieee80211_key.h       |    2 
 net/d80211/ieee80211_proc.c      |  771 --------------------------------------
 net/d80211/ieee80211_proc.h      |   45 --
 net/d80211/ieee80211_scan.c      |   10 
 net/d80211/ieee80211_sta.c       |   68 ++-
 net/d80211/ieee80211_sysfs.c     |  706 +++++++++++++++++++++++++++++++++--
 net/d80211/ieee80211_sysfs_sta.c |  434 +++++++++++++++++++++
 net/d80211/rate_control.c        |   55 ++-
 net/d80211/rate_control.h        |   57 ++-
 net/d80211/sta_info.c            |  132 ++++---
 net/d80211/sta_info.h            |   16 -
 net/d80211/wme.c                 |   26 +
 19 files changed, 1663 insertions(+), 1186 deletions(-)


-- 
Jiri Benc
SUSE Labs

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/12] d80211: deinit sysfs in case of an error
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 2/12] d80211: better sysfs registration of symlinks to wiphy Jiri Benc
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

When ieee80211_wme_register fails in ieee80211_init, ieee80211 class was not
unregistered.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

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

3aed246a5117bd4d1a4f2d5f5074c583d9b4941e
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index b850fb7..f549098 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4462,6 +4462,7 @@ static int __init ieee80211_init(void)
 		if (ret) {
 			printk(KERN_DEBUG "ieee80211_init: failed to "
 			       "initialize WME (err=%d)\n", ret);
+			ieee80211_sysfs_deinit();
 			ieee80211_proc_deinit();
 			return ret;
 		}
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/12] d80211: better sysfs registration of symlinks to wiphy
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
  2006-06-08  7:49 ` [PATCH 1/12] d80211: deinit sysfs in case of an error Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 3/12] d80211: separate allocation of ieee80211_local Jiri Benc
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Lately, delayed sysfs registration of net_device (in netdev_run_todo) was
removed. This allows us to remove hack that used class interface for sysfs
registration.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c       |   18 +++++++++++++++--
 net/d80211/ieee80211_i.h     |    2 ++
 net/d80211/ieee80211_iface.c |   15 ++++++++++++++
 net/d80211/ieee80211_sysfs.c |   45 ++++++------------------------------------
 4 files changed, 39 insertions(+), 41 deletions(-)

beb1533d9181d1c6d195de5743517b3559bfd9f9
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index f549098..9724a49 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4197,9 +4197,21 @@ int ieee80211_register_hw(struct net_dev
 
 	if (hw->fraglist)
 		dev->features |= NETIF_F_FRAGLIST;
-	result = register_netdev(dev);
-	if (result < 0)
+	rtnl_lock();
+	result = dev_alloc_name(dev, dev->name);
+	if (result < 0) {
+		rtnl_unlock();
+		goto fail_dev;
+	}
+	result = register_netdevice(dev);
+	if (result < 0) {
+		rtnl_unlock();
 		goto fail_dev;
+	}
+	result = ieee80211_sysfs_add_netdevice(dev);
+	rtnl_unlock();
+	if (result < 0)
+		goto fail_if_sysfs;
 
 	if (rate_control_initialize(local) < 0) {
 		printk(KERN_DEBUG "%s: Failed to initialize rate control "
@@ -4223,6 +4235,8 @@ int ieee80211_register_hw(struct net_dev
 	return 0;
 
 fail_rate:
+	ieee80211_sysfs_remove_netdevice(dev);
+fail_if_sysfs:
 	unregister_netdev(dev);
 fail_dev:
 	sta_info_stop(local);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 94e151d..19d9d98 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -599,6 +599,8 @@ int ieee80211_if_add_mgmt(struct net_dev
 void ieee80211_if_del_mgmt(struct net_device *dev);
 
 /* ieee80211_sysfs.c */
+int ieee80211_sysfs_add_netdevice(struct net_device *dev);
+void ieee80211_sysfs_remove_netdevice(struct net_device *dev);
 int ieee80211_register_sysfs(struct ieee80211_local *local);
 void ieee80211_unregister_sysfs(struct ieee80211_local *local);
 int ieee80211_sysfs_init(void);
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 6631738..d534fe4 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -76,6 +76,13 @@ 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;
+	}
 
 	list_add(&sdata->list, &local->sub_if_list);
 	ieee80211_proc_init_virtual(ndev);
@@ -123,10 +130,16 @@ int ieee80211_if_add_mgmt(struct net_dev
 	ret = register_netdevice(ndev);
 	if (ret)
 		goto fail;
+	ret = ieee80211_sysfs_add_netdevice(ndev);
+	if (ret)
+		goto fail_sysfs;
 	if (local->open_count > 0)
 		dev_open(ndev);
 	local->apdev = ndev;
 	return 0;
+
+fail_sysfs:
+	unregister_netdevice(ndev);
 fail:
 	free_netdev(ndev);
 	return ret;
@@ -139,6 +152,7 @@ void ieee80211_if_del_mgmt(struct net_de
 
 	ASSERT_RTNL();
 	apdev = local->apdev;
+	ieee80211_sysfs_remove_netdevice(apdev);
 	local->apdev = NULL;
 	unregister_netdevice(apdev);
 }
@@ -293,6 +307,7 @@ void __ieee80211_if_del(struct ieee80211
 	ieee80211_if_reinit(dev);
 	list_del(&sdata->list);
 	ieee80211_proc_deinit_virtual(dev);
+	ieee80211_sysfs_remove_netdevice(dev);
 	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/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index 463f9aa..5c7af9f 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -98,60 +98,27 @@ void ieee80211_unregister_sysfs(struct i
 	class_device_del(&local->class_dev);
 }
 
-static int ieee80211_add_netdevice(struct class_device *cd,
-				   struct class_interface *cintf)
+int ieee80211_sysfs_add_netdevice(struct net_device *dev)
 {
-	struct net_device *dev = container_of(cd, struct net_device, class_dev);
 	struct ieee80211_local *local = dev->priv;
 
-	if (ieee80211_dev_find_index(local) < 0)
-		return 0;
-	return sysfs_create_link(&cd->kobj, &local->class_dev.kobj, "wiphy");
+	return sysfs_create_link(&dev->class_dev.kobj, &local->class_dev.kobj,
+				 "wiphy");
 }
 
-static void ieee80211_remove_netdevice(struct class_device *cd,
-				       struct class_interface *cintf)
+void ieee80211_sysfs_remove_netdevice(struct net_device *dev)
 {
-	struct net_device *dev = container_of(cd, struct net_device, class_dev);
 	struct ieee80211_local *local = dev->priv;
 
-	if (ieee80211_dev_find_index(local) >= 0)
-		sysfs_remove_link(&cd->kobj, "wiphy");
-}
-
-static struct class_interface ieee80211_wiphy_cintf = {
-	.add = ieee80211_add_netdevice,
-	.remove = ieee80211_remove_netdevice,
-};
-
-/* Adds class interface watching for new network devices and adding "wiphy"
- * attribute (symlink) to them. */
-static int ieee80211_register_wiphy_cintf(void)
-{
-	ieee80211_wiphy_cintf.class = loopback_dev.class_dev.class;
-	return class_interface_register(&ieee80211_wiphy_cintf);
-}
-
-static void ieee80211_unregister_wiphy_cintf(void)
-{
-	class_interface_unregister(&ieee80211_wiphy_cintf);
+	sysfs_remove_link(&dev->class_dev.kobj, "wiphy");
 }
 
 int ieee80211_sysfs_init(void)
 {
-	int result;
-
-	result = class_register(&ieee80211_class);
-	if (result)
-		return result;
-	result = ieee80211_register_wiphy_cintf();
-	if (result)
-		class_unregister(&ieee80211_class);
-	return result;
+	return class_register(&ieee80211_class);
 }
 
 void ieee80211_sysfs_deinit(void)
 {
-	ieee80211_unregister_wiphy_cintf();
 	class_unregister(&ieee80211_class);
 }
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/12] d80211: separate allocation of ieee80211_local
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
  2006-06-08  7:49 ` [PATCH 1/12] d80211: deinit sysfs in case of an error Jiri Benc
  2006-06-08  7:49 ` [PATCH 2/12] d80211: better sysfs registration of symlinks to wiphy Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-12 19:35   ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 4/12] d80211: fix Oops when writing to add_ and remove_iface Jiri Benc
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

ieee80211_local has a separate class_device. That means it has reference
counting independent of master net_device and can be freed at a different
time, therefore these two structures cannot be allocated together.

Solve this by adding ieee80211_ptr pointer to net_device structure (similar
to other pointers already presented there) and using it as a pointer to
independently allocated ieee80211_local.

This also allows is_ieee80211_device function to be nice finally.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 include/linux/netdevice.h    |    1 
 net/d80211/ieee80211.c       |  100 +++++++++++++++++++++---------------------
 net/d80211/ieee80211_dev.c   |   17 +++++++
 net/d80211/ieee80211_i.h     |    9 +++-
 net/d80211/ieee80211_iface.c |   20 ++++----
 net/d80211/ieee80211_ioctl.c |   92 +++++++++++++++++++--------------------
 net/d80211/ieee80211_proc.c  |    6 +--
 net/d80211/ieee80211_scan.c  |   10 ++--
 net/d80211/ieee80211_sta.c   |   58 ++++++++++++------------
 net/d80211/ieee80211_sysfs.c |   26 ++++++++---
 net/d80211/rate_control.c    |    4 +-
 net/d80211/rate_control.h    |    4 +-
 net/d80211/wme.c             |   26 +++++------
 13 files changed, 206 insertions(+), 167 deletions(-)

3085d33e38881f0987329c4258514f60ffe824af
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f4169bb..037e63a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -371,6 +371,7 @@ #define NETIF_F_UFO             8192    
 	void                    *ip6_ptr;       /* IPv6 specific data */
 	void			*ec_ptr;	/* Econet specific data	*/
 	void			*ax25_ptr;	/* AX.25 specific data */
+	void			*ieee80211_ptr;	/* IEEE 802.11 specific data */
 
 /*
  * Cache line mostly used on receive path (including eth_type_trans())
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 9724a49..4fc2e7d 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -110,7 +110,7 @@ static int rate_list_match(int *rate_lis
 
 void ieee80211_prepare_rates(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int i;
 
 	for (i = 0; i < local->num_curr_rates; i++) {
@@ -1059,7 +1059,7 @@ __ieee80211_tx_prepare(struct ieee80211_
 		       struct net_device *dev,
 		       struct ieee80211_tx_control *control)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	int hdrlen;
 
@@ -1095,12 +1095,9 @@ __ieee80211_tx_prepare(struct ieee80211_
 
 }
 
-/* FIXME: This is not nice but currently there doesn't exist more elegant way */
 static int inline is_ieee80211_device(struct net_device *dev)
 {
-	return (dev->wireless_handlers ==
-		(struct iw_handler_def *) &ieee80211_iw_handler_def) ||
-	       (dev->hard_start_xmit == ieee80211_mgmt_start_xmit);
+	return (dev->ieee80211_ptr != NULL);
 }
 
 /* Device in tx->dev has a reference added; use dev_put(tx->dev) when
@@ -1131,7 +1128,7 @@ static void inline ieee80211_tx_prepare(
 static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
 			struct ieee80211_tx_control *control, int mgmt)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sta_info *sta;
 	ieee80211_tx_handler *handler;
 	struct ieee80211_txrx_data tx;
@@ -1307,7 +1304,7 @@ #endif
 static int ieee80211_subif_start_xmit(struct sk_buff *skb,
 				      struct net_device *dev)
 {
-        struct ieee80211_local *local = (struct ieee80211_local *) dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_tx_packet_data *pkt_data;
         struct ieee80211_sub_if_data *sdata;
 	int ret = 1, head_need;
@@ -1613,7 +1610,7 @@ static void ieee80211_beacon_add_tim(str
 struct sk_buff * ieee80211_beacon_get(struct net_device *dev, int if_id,
 				      struct ieee80211_tx_control *control)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sk_buff *skb;
 	struct net_device *bdev;
 	struct ieee80211_sub_if_data *sdata = NULL;
@@ -1690,7 +1687,7 @@ struct sk_buff *
 ieee80211_get_buffered_bc(struct net_device *dev, int if_id,
 			  struct ieee80211_tx_control *control)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sk_buff *skb;
 	struct sta_info *sta;
 	ieee80211_tx_handler *handler;
@@ -1754,7 +1751,7 @@ ieee80211_get_buffered_bc(struct net_dev
 int ieee80211_if_config(struct net_device *dev)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_if_conf conf;
 
 	if (!local->hw->config_interface || !netif_running(dev))
@@ -1780,7 +1777,7 @@ int ieee80211_if_config(struct net_devic
 
 int ieee80211_hw_config(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int i, ret = 0;
 
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
@@ -1811,7 +1808,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
 struct ieee80211_conf *ieee80211_get_hw_conf(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
         return &local->conf;
 }
 
@@ -1854,7 +1851,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
 static void ieee80211_tx_timeout(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	printk(KERN_WARNING "%s: resetting interface.\n", dev->name);
 
@@ -1878,7 +1875,7 @@ static int ieee80211_set_mac_address(str
 
 static void ieee80211_set_multicast_list(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	unsigned short flags;
 
@@ -1920,7 +1917,7 @@ struct dev_mc_list *ieee80211_get_mc_lis
 					       struct dev_mc_list *prev,
 					       void **ptr)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata = *ptr;
 	struct dev_mc_list *mc;
 
@@ -1966,7 +1963,7 @@ static inline int identical_mac_addr_all
 
 static int ieee80211_master_open(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
 	int res = -EOPNOTSUPP;
 
@@ -1981,7 +1978,7 @@ static int ieee80211_master_open(struct 
 
 static int ieee80211_master_stop(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
 
 	list_for_each_entry(sdata, &local->sub_if_list, list) {
@@ -1993,7 +1990,7 @@ static int ieee80211_master_stop(struct 
 
 static int ieee80211_mgmt_open(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (!netif_running(local->mdev))
 		return -EOPNOTSUPP;
@@ -2038,7 +2035,7 @@ static void ieee80211_start_hard_monitor
 static int ieee80211_open(struct net_device *dev)
 {
 	struct ieee80211_sub_if_data *sdata, *nsdata;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_if_init_conf conf;
 	int res;
 
@@ -2117,7 +2114,7 @@ static int ieee80211_open(struct net_dev
 static int ieee80211_stop(struct net_device *dev)
 {
 	struct ieee80211_sub_if_data *sdata;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
@@ -2381,7 +2378,7 @@ void
 ieee80211_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
 		  struct ieee80211_rx_status *status, u32 msg_type)
 {
-        struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
         struct ieee80211_frame_info *fi;
         size_t hlen;
         struct ieee80211_sub_if_data *sdata;
@@ -2545,7 +2542,7 @@ #endif /* IEEE80211_VERBOSE_DEBUG_PS */
 
 static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sk_buff *skb;
 	int sent = 0;
 	struct ieee80211_sub_if_data *sdata;
@@ -3356,7 +3353,7 @@ static inline void ieee80211_invoke_rx_h
 void __ieee80211_rx(struct net_device *dev, struct sk_buff *skb,
 		    struct ieee80211_rx_status *status)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
 	struct sta_info *sta;
 	struct ieee80211_hdr *hdr;
@@ -3629,7 +3626,7 @@ static void ieee80211_stat_refresh(unsig
 void ieee80211_rx_irqsafe(struct net_device *dev, struct sk_buff *skb,
 			  struct ieee80211_rx_status *status)
 {
-        struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_rx_status *saved;
 
         skb->dev = dev;
@@ -3646,7 +3643,7 @@ void ieee80211_rx_irqsafe(struct net_dev
 void ieee80211_tx_status_irqsafe(struct net_device *dev, struct sk_buff *skb,
 				 struct ieee80211_tx_status *status)
 {
-        struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_tx_status *saved;
 	int tmp;
 
@@ -3786,7 +3783,7 @@ void ieee80211_tx_status(struct net_devi
 {
 	struct sk_buff *skb2;
         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-        struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	u16 frag, type;
 	u32 msg_type;
 
@@ -3974,7 +3971,7 @@ static ieee80211_tx_handler ieee80211_tx
 
 int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct sta_info *sta;
 
@@ -3998,7 +3995,7 @@ int ieee80211_if_update_wds(struct net_d
 
 static void ieee80211_if_init(struct net_device *dev)
 {
-        struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
         spin_lock_init(&local->sub_if_lock);
         INIT_LIST_HEAD(&local->sub_if_list);
@@ -4065,6 +4062,10 @@ struct net_device *ieee80211_alloc_hw(si
         struct ieee80211_sub_if_data *sdata;
 	int priv_size;
 
+	local = ieee80211_dev_alloc(GFP_KERNEL);
+	if (!local)
+		return NULL;
+
 	/* Ensure 32-byte alignment of our private data and hw private data.
 	 * Each net_device is followed by a sub_if_data which is used for
 	 * interface specific information.
@@ -4075,30 +4076,24 @@ struct net_device *ieee80211_alloc_hw(si
          *      * net_dev       *
 	 * 0160 *****************
          *      * sub_if        *
-	 * 0180 *****************
-         *      * local         *
 	 * 0b80 *****************
          *      * hw_priv       *
          * 1664 *****************
          */
 	priv_size = ((sizeof(struct ieee80211_sub_if_data) +
 		      NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
-		    ((sizeof(struct ieee80211_local) +
-		      NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST) +
 		    priv_data_len;
 	mdev = alloc_netdev(priv_size, "wmaster%d", ether_setup);
-	if (mdev == NULL)
+	if (mdev == NULL) {
+		ieee80211_dev_free(local);
 		return NULL;
+	}
 
-	mdev->priv = (char *)netdev_priv(mdev) +
-		     ((sizeof(struct ieee80211_sub_if_data) +
-		       NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
-	local = mdev->priv;
-	local->hw_priv = (char *)local +
-			 ((sizeof(struct ieee80211_local) +
+	mdev->ieee80211_ptr = local;
+	local->hw_priv = (char *)mdev->priv +
+			 ((sizeof(struct ieee80211_sub_if_data) +
 			   NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST);
 
-	local->dev_index = -1;
 	local->mdev = mdev;
         local->rx_handlers = ieee80211_rx_handlers;
         local->tx_handlers = ieee80211_tx_handlers;
@@ -4166,7 +4161,7 @@ struct net_device *ieee80211_alloc_hw(si
 
 int ieee80211_register_hw(struct net_device *dev, struct ieee80211_hw *hw)
 {
-        struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct net_device *sta_dev;
 	int result;
 
@@ -4185,7 +4180,7 @@ int ieee80211_register_hw(struct net_dev
 		return -1;
 
 	local->class_dev.dev = dev->class_dev.dev;
-	result = ieee80211_register_sysfs(local);
+	result = ieee80211_dev_sysfs_add(local);
 	if (result < 0)
 		goto fail_sysfs;
 
@@ -4240,7 +4235,7 @@ fail_if_sysfs:
 	unregister_netdev(dev);
 fail_dev:
 	sta_info_stop(local);
-	ieee80211_unregister_sysfs(local);
+	ieee80211_dev_sysfs_del(local);
 fail_sysfs:
 	ieee80211_dev_free_index(local);
 	return result;
@@ -4248,7 +4243,7 @@ fail_sysfs:
 
 int ieee80211_update_hw(struct net_device *dev, struct ieee80211_hw *hw)
 {
-        struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	local->hw = hw;
 
@@ -4280,7 +4275,7 @@ int ieee80211_update_hw(struct net_devic
 
 void ieee80211_unregister_hw(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
         struct list_head *ptr, *n;
 	int i;
 
@@ -4305,7 +4300,7 @@ void ieee80211_unregister_hw(struct net_
 	}
 
 	sta_info_stop(local);
-	ieee80211_unregister_sysfs(local);
+	ieee80211_dev_sysfs_del(local);
 
 	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
 		if (local->fragments[i].skb)
@@ -4330,14 +4325,21 @@ void ieee80211_unregister_hw(struct net_
 
 void ieee80211_free_hw(struct net_device *dev)
 {
+	struct ieee80211_local *local = dev->ieee80211_ptr;
+
 	free_netdev(dev);
+	ieee80211_dev_free(local);
 }
 
+void ieee80211_release_hw(struct ieee80211_local *local)
+{
+	kfree(local);
+}
 
 /* Perform netif operations on all configured interfaces */
 int ieee80211_netif_oper(struct net_device *sdev, Netif_Oper op)
 {
-        struct ieee80211_local *local = sdev->priv;
+	struct ieee80211_local *local = sdev->ieee80211_ptr;
         struct ieee80211_sub_if_data *sdata =  IEEE80211_DEV_TO_SUB_IF(sdev);
         struct net_device *dev = sdata->master;
 
@@ -4377,7 +4379,7 @@ #endif
 
 void * ieee80211_dev_hw_data(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	return local->hw_priv;
 }
 
diff --git a/net/d80211/ieee80211_dev.c b/net/d80211/ieee80211_dev.c
index 6278cfa..6c6ca91 100644
--- a/net/d80211/ieee80211_dev.c
+++ b/net/d80211/ieee80211_dev.c
@@ -99,3 +99,20 @@ int ieee80211_dev_find_index(struct ieee
 	spin_unlock(&dev_list_lock);
 	return index;
 }
+
+struct ieee80211_local *ieee80211_dev_alloc(gfp_t flags)
+{
+	struct ieee80211_local *local;
+
+	local = kzalloc(sizeof(struct ieee80211_local), flags);
+	if (!local)
+		return NULL;
+	local->dev_index = -1;
+	ieee80211_dev_sysfs_init(local);
+	return local;
+}
+
+void ieee80211_dev_free(struct ieee80211_local *local)
+{
+	ieee80211_dev_sysfs_put(local);
+}
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 19d9d98..84cc50e 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -505,6 +505,7 @@ #endif /* CONFIG_D80211_DEBUG_COUNTERS *
 
 
 /* ieee80211.c */
+void ieee80211_release_hw(struct ieee80211_local *local);
 int ieee80211_hw_config(struct net_device *dev);
 int ieee80211_if_config(struct net_device *dev);
 struct ieee80211_key_conf *
@@ -582,6 +583,8 @@ int ieee80211_dev_alloc_index(struct iee
 void ieee80211_dev_free_index(struct ieee80211_local *local);
 struct ieee80211_local *ieee80211_dev_find(int index);
 int ieee80211_dev_find_index(struct ieee80211_local *local);
+struct ieee80211_local *ieee80211_dev_alloc(gfp_t flags);
+void ieee80211_dev_free(struct ieee80211_local *local);
 
 /* ieee80211_iface.c */
 int ieee80211_if_add(struct net_device *dev, const char *name,
@@ -601,8 +604,10 @@ void ieee80211_if_del_mgmt(struct net_de
 /* ieee80211_sysfs.c */
 int ieee80211_sysfs_add_netdevice(struct net_device *dev);
 void ieee80211_sysfs_remove_netdevice(struct net_device *dev);
-int ieee80211_register_sysfs(struct ieee80211_local *local);
-void ieee80211_unregister_sysfs(struct ieee80211_local *local);
+void ieee80211_dev_sysfs_init(struct ieee80211_local *local);
+void ieee80211_dev_sysfs_put(struct ieee80211_local *local);
+int ieee80211_dev_sysfs_add(struct ieee80211_local *local);
+void ieee80211_dev_sysfs_del(struct ieee80211_local *local);
 int ieee80211_sysfs_init(void);
 void ieee80211_sysfs_deinit(void);
 
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index d534fe4..8ab2c07 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -29,7 +29,7 @@ int ieee80211_if_add(struct net_device *
 		     int format, struct net_device **new_dev)
 {
 	struct net_device *ndev, *tmp_dev;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata = NULL, *sdata_parent;
 	int ret;
 	int i;
@@ -40,7 +40,7 @@ int ieee80211_if_add(struct net_device *
 	if (ndev == NULL)
 		return -ENOMEM;
 
-	ndev->priv = local;
+	ndev->ieee80211_ptr = local;
 	if (strlen(name) == 0) {
 		i = 0;
 		do {
@@ -98,7 +98,7 @@ fail:
 int ieee80211_if_add_mgmt(struct net_device *dev)
 {
 	struct net_device *ndev;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata, *nsdata;
 	int ret;
 
@@ -113,7 +113,7 @@ int ieee80211_if_add_mgmt(struct net_dev
 	if (ret)
 		goto fail;
 
-	ndev->priv = local;
+	ndev->ieee80211_ptr = local;
 	memcpy(ndev->dev_addr, dev->dev_addr, ETH_ALEN);
 	ndev->base_addr = dev->base_addr;
 	ndev->irq = dev->irq;
@@ -147,7 +147,7 @@ fail:
 
 void ieee80211_if_del_mgmt(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct net_device *apdev;
 
 	ASSERT_RTNL();
@@ -207,7 +207,7 @@ void ieee80211_if_set_type(struct net_de
 /* Must be called with rtnl lock held. */
 void ieee80211_if_reinit(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct sta_info *sta;
 	int i;
@@ -316,7 +316,7 @@ void __ieee80211_if_del(struct ieee80211
 /* Must be called with rtnl lock held. */
 int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata, *n;
 
 	ASSERT_RTNL();
@@ -337,7 +337,7 @@ int ieee80211_if_remove(struct net_devic
 
 void ieee80211_if_free(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	BUG_ON(dev == local->mdev || dev == local->apdev);
 	free_netdev(dev);
@@ -346,7 +346,7 @@ void ieee80211_if_free(struct net_device
 /* Must be called with rtnl lock held. */
 void ieee80211_if_flush(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata, *n;
 
 	ASSERT_RTNL();
@@ -357,7 +357,7 @@ void ieee80211_if_flush(struct net_devic
 
 void ieee80211_if_del(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	rtnl_lock();
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 30dfc76..8d593e8 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -118,7 +118,7 @@ static int ieee80211_ioctl_get_hw_featur
 					   struct prism2_hostapd_param *param,
 					   int param_len)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	u8 *pos = param->u.hw_features.data;
 	int left = param_len - (pos - (u8 *) param);
 	int mode, i;
@@ -169,7 +169,7 @@ static int ieee80211_ioctl_get_hw_featur
 static int ieee80211_ioctl_scan(struct net_device *dev,
                                 struct prism2_hostapd_param *param)
 {
-        struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (local->hw->passive_scan == NULL)
 		return -EOPNOTSUPP;
@@ -209,7 +209,7 @@ static int ieee80211_ioctl_scan(struct n
 static int ieee80211_ioctl_flush(struct net_device *dev,
 				 struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	sta_info_flush(local, NULL);
 	return 0;
 }
@@ -218,7 +218,7 @@ static int ieee80211_ioctl_flush(struct 
 static int ieee80211_ioctl_add_sta(struct net_device *dev,
 				   struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sta_info *sta;
 	u32 rates;
 	int i, j;
@@ -303,7 +303,7 @@ static int ieee80211_ioctl_add_sta(struc
 static int ieee80211_ioctl_remove_sta(struct net_device *dev,
 				      struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sta_info *sta;
 
 	sta = sta_info_get(local, param->sta_addr);
@@ -319,7 +319,7 @@ static int ieee80211_ioctl_remove_sta(st
 static int ieee80211_ioctl_get_dot11counterstable(struct net_device *dev,
 					struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
         struct ieee80211_low_level_stats stats;
 
 	memset(&stats, 0, sizeof(stats));
@@ -351,7 +351,7 @@ static int ieee80211_ioctl_get_dot11coun
 static int ieee80211_ioctl_get_info_sta(struct net_device *dev,
 					struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sta_info *sta;
 
 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
@@ -402,7 +402,7 @@ static int ieee80211_ioctl_get_info_sta(
 static int ieee80211_ioctl_set_flags_sta(struct net_device *dev,
 					 struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sta_info *sta;
 
 	sta = sta_info_get(local, param->sta_addr);
@@ -433,7 +433,7 @@ int ieee80211_set_hw_encryption(struct n
 				struct ieee80211_key *key)
 {
 	struct ieee80211_key_conf *keyconf = NULL;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int rc = 0;
 
 	/* default to sw encryption; this will be cleared by low-level
@@ -467,7 +467,7 @@ static int ieee80211_set_encryption(stru
 				    int idx, int alg, int set_tx_key, int *err,
 				    const u8 *_key, size_t key_len)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int ret = 0;
 	struct sta_info *sta;
 	struct ieee80211_key **key;
@@ -706,7 +706,7 @@ static int ieee80211_ioctl_get_encryptio
 					  struct prism2_hostapd_param *param,
 					  int param_len)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int ret = 0;
 	struct sta_info *sta;
 	struct ieee80211_key **key;
@@ -823,7 +823,7 @@ #ifdef CONFIG_HOSTAPD_WPA_TESTING
 static int ieee80211_ioctl_wpa_trigger(struct net_device *dev,
 				       struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sta_info *sta;
 
 	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
@@ -852,7 +852,7 @@ static int ieee80211_ioctl_set_rate_sets
 					 struct prism2_hostapd_param *param,
 					 int param_len)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	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;
@@ -937,7 +937,7 @@ static int ieee80211_ioctl_add_if(struct
 		ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_WDS);
 		res = ieee80211_if_update_wds(new_dev, wds->remote_addr);
 		if (res)
-			__ieee80211_if_del(dev->priv,
+			__ieee80211_if_del(dev->ieee80211_ptr,
 					   IEEE80211_DEV_TO_SUB_IF(new_dev));
 		return res;
 	} else if (param->u.if_info.type == HOSTAP_IF_VLAN) {
@@ -951,7 +951,7 @@ static int ieee80211_ioctl_add_if(struct
 #if 0
 		res = ieee80211_if_update_vlan(new_dev, vlan->id);
 		if (res)
-			__ieee80211_if_del(dev->priv,
+			__ieee80211_if_del(dev->ieee80211_ptr,
 					   IEEE80211_DEV_TO_SUB_IF(new_dev));
 #endif
 		return res;
@@ -1013,7 +1013,7 @@ static int ieee80211_ioctl_update_if(str
 	if (param->u.if_info.type == HOSTAP_IF_WDS) {
 		struct hostapd_if_wds *wds =
 			(struct hostapd_if_wds *) param->u.if_info.data;
-		struct ieee80211_local *local = dev->priv;
+		struct ieee80211_local *local = dev->ieee80211_ptr;
 		struct net_device *wds_dev = NULL;
 		struct ieee80211_sub_if_data *sdata;
 
@@ -1050,7 +1050,7 @@ static int ieee80211_ioctl_scan_req(stru
 				    struct prism2_hostapd_param *param,
 				    int param_len)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	u8 *pos = param->u.scan_req.ssid;
 	int left = param_len - ((u8 *) pos - (u8 *) param);
 	int len = param->u.scan_req.ssid_len;
@@ -1082,7 +1082,7 @@ static int ieee80211_ioctl_sta_get_state
 static int ieee80211_ioctl_mlme(struct net_device *dev,
 				struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
 
 	if (local->user_space_mlme)
@@ -1105,7 +1105,7 @@ static int ieee80211_ioctl_mlme(struct n
 static int ieee80211_ioctl_get_load_stats(struct net_device *dev,
 					  struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	param->u.get_load_stats.channel_use = local->channel_use;
 /*	if (param->u.get_load_stats.flags & LOAD_STATS_CLEAR)
@@ -1118,7 +1118,7 @@ static int ieee80211_ioctl_get_load_stat
 static int ieee80211_ioctl_set_sta_vlan(struct net_device *dev,
                                         struct prism2_hostapd_param *param)
 {
-        struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
         struct sta_info *sta;
 
         sta = sta_info_get(local, param->sta_addr);
@@ -1146,7 +1146,7 @@ #endif
 static int ieee80211_set_gen_ie(struct net_device *dev, u8 *ie, size_t len)
 {
 	struct ieee80211_sub_if_data *sdata;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (local->user_space_mlme)
 		return -EOPNOTSUPP;
@@ -1206,7 +1206,7 @@ static int
 ieee80211_ioctl_set_tx_queue_params(struct net_device *dev,
 				    struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_tx_queue_params qparam;
 
 	if (!local->hw->conf_tx) {
@@ -1229,7 +1229,7 @@ ieee80211_ioctl_set_tx_queue_params(stru
 static int ieee80211_ioctl_get_tx_stats(struct net_device *dev,
 					struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_tx_queue_stats stats;
 	int ret, i;
 
@@ -1254,7 +1254,7 @@ static int ieee80211_ioctl_get_tx_stats(
 static int ieee80211_ioctl_set_channel_flag(struct net_device *dev,
 					    struct prism2_hostapd_param *param)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_hw_modes *mode = NULL;
 	struct ieee80211_channel *chan = NULL;
 	int i;
@@ -1445,7 +1445,7 @@ static int ieee80211_ioctl_giwname(struc
 				   struct iw_request_info *info,
 				   char *name, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	switch (local->conf.phymode) {
 	case MODE_IEEE80211A:
@@ -1589,7 +1589,7 @@ static void ieee80211_unmask_channel(str
 
 static int ieee80211_unmask_channels(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int m, c;
 
 	for (m = 0; m < local->hw->num_modes; m++) {
@@ -1690,7 +1690,7 @@ int ieee80211_ioctl_siwfreq(struct net_d
 			    struct iw_request_info *info,
 			    struct iw_freq *freq, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int m, c, nfreq, set = 0;
 
 	/* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */
@@ -1743,7 +1743,7 @@ static int ieee80211_ioctl_giwfreq(struc
 				   struct iw_request_info *info,
 				   struct iw_freq *freq, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	/* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level
 	 * driver for the current channel with firmware-based management */
@@ -1759,7 +1759,7 @@ static int ieee80211_ioctl_siwessid(stru
 				    struct iw_request_info *info,
 				    struct iw_point *data, char *ssid)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
         size_t len = data->length;
 
@@ -1827,7 +1827,7 @@ static int ieee80211_ioctl_siwap(struct 
 				 struct iw_request_info *info,
 				 struct sockaddr *ap_addr, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1876,7 +1876,7 @@ static int ieee80211_ioctl_siwscan(struc
 				   struct iw_request_info *info,
 				   struct iw_point *data, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	u8 *ssid = NULL;
 	size_t ssid_len = 0;
@@ -1901,7 +1901,7 @@ static int ieee80211_ioctl_giwscan(struc
 				   struct iw_point *data, char *extra)
 {
 	int res;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	if (local->sta_scanning)
 		return -EAGAIN;
 	res = ieee80211_sta_scan_results(dev, extra, IW_SCAN_MAX_DATA);
@@ -1918,7 +1918,7 @@ static int ieee80211_ioctl_siwrts(struct
 				  struct iw_request_info *info,
 				  struct iw_param *rts, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (rts->disabled)
 		local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
@@ -1941,7 +1941,7 @@ static int ieee80211_ioctl_giwrts(struct
 				  struct iw_request_info *info,
 				  struct iw_param *rts, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	rts->value = local->rts_threshold;
 	rts->disabled = (rts->value >= IEEE80211_MAX_RTS_THRESHOLD);
@@ -1955,7 +1955,7 @@ static int ieee80211_ioctl_siwfrag(struc
 				   struct iw_request_info *info,
 				   struct iw_param *frag, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (frag->disabled)
 		local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
@@ -1982,7 +1982,7 @@ static int ieee80211_ioctl_giwfrag(struc
 				   struct iw_request_info *info,
 				   struct iw_param *frag, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	frag->value = local->fragmentation_threshold;
 	frag->disabled = (frag->value >= IEEE80211_MAX_RTS_THRESHOLD);
@@ -1996,7 +1996,7 @@ static int ieee80211_ioctl_siwretry(stru
 				    struct iw_request_info *info,
 				    struct iw_param *retry, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (retry->disabled ||
 	    (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
@@ -2025,7 +2025,7 @@ static int ieee80211_ioctl_giwretry(stru
 				    struct iw_request_info *info,
 				    struct iw_param *retry, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	retry->disabled = 0;
 	if ((retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
@@ -2060,7 +2060,7 @@ static void ieee80211_ioctl_unmask_chann
 
 static int ieee80211_ioctl_test_mode(struct net_device *dev, int mode)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int ret = -EOPNOTSUPP;
 
 	if (mode == IEEE80211_TEST_UNMASK_CHANNELS) {
@@ -2077,7 +2077,7 @@ static int ieee80211_ioctl_test_mode(str
 
 static int ieee80211_ioctl_clear_keys(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_key_conf key;
 	struct list_head *ptr;
 	int i;
@@ -2138,7 +2138,7 @@ ieee80211_ioctl_force_unicast_rate(struc
 				   struct ieee80211_sub_if_data *sdata,
 				   int rate)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int i;
 
 	if (sdata->type != IEEE80211_IF_TYPE_AP)
@@ -2164,7 +2164,7 @@ ieee80211_ioctl_max_ratectrl_rate(struct
 				  struct ieee80211_sub_if_data *sdata,
 				  int rate)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int i;
 
 	if (sdata->type != IEEE80211_IF_TYPE_AP)
@@ -2254,7 +2254,7 @@ static int ieee80211_ioctl_prism2_param(
 					struct iw_request_info *info,
 					void *wrqu, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
 	int *i = (int *) extra;
 	int param = *i;
@@ -2524,7 +2524,7 @@ static int ieee80211_ioctl_get_prism2_pa
 					    struct iw_request_info *info,
 					    void *wrqu, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
 	int *param = (int *) extra;
 	int ret = 0;
@@ -2716,7 +2716,7 @@ static int ieee80211_ioctl_test_param(st
 				      struct iw_request_info *info,
 				      void *wrqu, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int *i = (int *) extra;
 	int param = *i;
 	int value = *(i + 1);
@@ -2849,7 +2849,7 @@ static int ieee80211_ioctl_siwauth(struc
 				   struct iw_request_info *info,
 				   struct iw_param *data, char *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	int ret = 0;
 
diff --git a/net/d80211/ieee80211_proc.c b/net/d80211/ieee80211_proc.c
index c9f5567..4f3a6b9 100644
--- a/net/d80211/ieee80211_proc.c
+++ b/net/d80211/ieee80211_proc.c
@@ -269,7 +269,7 @@ static int ieee80211_proc_sta_read(char 
 		     sta->tx_fragments, sta->tx_filtered_count);
 	p = ieee80211_proc_key(p, sta->key, 0, 1);
 
-	local = (struct ieee80211_local *) sta->dev->priv;
+	local = (struct ieee80211_local *) sta->dev->ieee80211_ptr;
 	if (sta->txrate >= 0 && sta->txrate < local->num_curr_rates) {
 		p += sprintf(p, "txrate=%d\n",
 			     local->curr_rates[sta->txrate].rate);
@@ -676,7 +676,7 @@ void ieee80211_proc_deinit_sta(struct ie
 void ieee80211_proc_init_virtual(struct net_device *dev)
 {
 	struct proc_dir_entry *entry;
-	struct ieee80211_local *local = (struct ieee80211_local *) dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (!local->proc_iface)
 		return;
@@ -690,7 +690,7 @@ void ieee80211_proc_init_virtual(struct 
 
 void ieee80211_proc_deinit_virtual(struct net_device *dev)
 {
-	struct ieee80211_local *local = (struct ieee80211_local *) dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (local->proc_iface)
 		remove_proc_entry(dev->name, local->proc_iface);
diff --git a/net/d80211/ieee80211_scan.c b/net/d80211/ieee80211_scan.c
index 9984fd6..4184abf 100644
--- a/net/d80211/ieee80211_scan.c
+++ b/net/d80211/ieee80211_scan.c
@@ -110,7 +110,7 @@ static void next_chan_all_modes(struct i
 static void ieee80211_scan_start(struct net_device *dev,
 				 struct ieee80211_scan_conf *conf)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int old_mode_idx = local->scan.mode_idx;
 	int old_chan_idx = local->scan.chan_idx;
 	struct ieee80211_hw_modes *mode = NULL;
@@ -209,7 +209,7 @@ #endif
 static void ieee80211_scan_stop(struct net_device *dev,
 				struct ieee80211_scan_conf *conf)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_hw_modes *mode;
 	struct ieee80211_channel *chan;
 	int wait;
@@ -258,7 +258,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 static void ieee80211_scan_handler(unsigned long uldev)
 {
         struct net_device *dev = (struct net_device *) uldev;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_scan_conf conf;
 
 	if (local->scan.interval == 0 && !local->scan.in_scan) {
@@ -286,7 +286,7 @@ static void ieee80211_scan_handler(unsig
 
 void ieee80211_init_scan(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_hdr hdr;
 	u16 fc;
 	int len = 10;
@@ -342,7 +342,7 @@ void ieee80211_init_scan(struct net_devi
 
 void ieee80211_stop_scan(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (local->hw->passive_scan != 0) {
 		del_timer_sync(&local->scan.timer);
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index af58013..66a4575 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -234,7 +234,7 @@ static void ieee80211_sta_wmm_params(str
 				     struct ieee80211_if_sta *ifsta,
 				     u8 *wmm_param, size_t wmm_param_len)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_tx_queue_params params;
 	size_t left;
 	int count;
@@ -468,7 +468,7 @@ static void ieee80211_authenticate(struc
 static void ieee80211_send_assoc(struct net_device *dev,
 				 struct ieee80211_if_sta *ifsta)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sk_buff *skb;
 	struct ieee80211_mgmt *mgmt;
 	u8 *pos, *ies;
@@ -688,7 +688,7 @@ static void ieee80211_associate(struct n
 static void ieee80211_associated(struct net_device *dev,
 				 struct ieee80211_if_sta *ifsta)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sta_info *sta;
 	int disassoc;
 
@@ -749,7 +749,7 @@ static void ieee80211_associated(struct 
 static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
 				     u8 *ssid, size_t ssid_len)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sk_buff *skb;
 	struct ieee80211_mgmt *mgmt;
 	u8 *pos, *supp_rates, *esupp_rates = NULL;
@@ -1079,7 +1079,7 @@ static void ieee80211_rx_mgmt_assoc_resp
 					 struct ieee80211_rx_status *rx_status,
 					 int reassoc)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct sta_info *sta;
 	u32 rates;
 	u16 capab_info, status_code, aid;
@@ -1210,7 +1210,7 @@ static void ieee80211_rx_mgmt_assoc_resp
 static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
 					struct ieee80211_sta_bss *bss)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	bss->hnext = local->sta_bss_hash[STA_HASH(bss->bssid)];
 	local->sta_bss_hash[STA_HASH(bss->bssid)] = bss;
 }
@@ -1220,7 +1220,7 @@ static void __ieee80211_rx_bss_hash_add(
 static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
 					struct ieee80211_sta_bss *bss)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sta_bss *b, *prev = NULL;
 	b = local->sta_bss_hash[STA_HASH(bss->bssid)];
 	while (b) {
@@ -1242,7 +1242,7 @@ static void __ieee80211_rx_bss_hash_del(
 static struct ieee80211_sta_bss *
 ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sta_bss *bss;
 
 	bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
@@ -1265,7 +1265,7 @@ ieee80211_rx_bss_add(struct net_device *
 static struct ieee80211_sta_bss *
 ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sta_bss *bss;
 
 	spin_lock_bh(&local->sta_bss_lock);
@@ -1294,7 +1294,7 @@ static void ieee80211_rx_bss_free(struct
 static void ieee80211_rx_bss_put(struct net_device *dev,
 				 struct ieee80211_sta_bss *bss)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	if (!atomic_dec_and_test(&bss->users))
 		return;
 
@@ -1308,7 +1308,7 @@ static void ieee80211_rx_bss_put(struct 
 
 void ieee80211_rx_bss_list_init(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	spin_lock_init(&local->sta_bss_lock);
 	INIT_LIST_HEAD(&local->sta_bss_list);
 }
@@ -1316,7 +1316,7 @@ void ieee80211_rx_bss_list_init(struct n
 
 void ieee80211_rx_bss_list_deinit(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sta_bss *bss;
 	struct list_head *ptr;
 
@@ -1336,7 +1336,7 @@ static void ieee80211_rx_bss_info(struct
 				  struct ieee80211_rx_status *rx_status,
 				  int beacon)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee802_11_elems elems;
 	size_t baselen;
 	int channel, invalid = 0, clen;
@@ -1587,7 +1587,7 @@ static void ieee80211_rx_mgmt_beacon(str
 				     size_t len,
 				     struct ieee80211_rx_status *rx_status)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_if_sta *ifsta;
 	int use_protection;
@@ -1645,7 +1645,7 @@ static void ieee80211_rx_mgmt_probe_req(
 					size_t len,
 					struct ieee80211_rx_status *rx_status)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	int tx_last_beacon;
 	struct sk_buff *skb;
@@ -1802,7 +1802,7 @@ void ieee80211_sta_rx_scan(struct net_de
 
 static int ieee80211_sta_active_ibss(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct list_head *ptr;
 	int active = 0;
 	struct sta_info *sta;
@@ -1825,7 +1825,7 @@ static int ieee80211_sta_active_ibss(str
 
 static void ieee80211_sta_expire(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct list_head *ptr, *n;
 	struct sta_info *sta;
 
@@ -1911,7 +1911,7 @@ void ieee80211_sta_timer(unsigned long p
 static void ieee80211_sta_new_auth(struct net_device *dev,
 				   struct ieee80211_if_sta *ifsta)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	if (sdata->type != IEEE80211_IF_TYPE_STA)
@@ -1972,7 +1972,7 @@ static int ieee80211_sta_join_ibss(struc
 				   struct ieee80211_if_sta *ifsta,
 				   struct ieee80211_sta_bss *bss)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct iw_freq rq;
 	int res, rates, i, j;
 	struct sk_buff *skb;
@@ -2132,7 +2132,7 @@ static int ieee80211_sta_join_ibss(struc
 static int ieee80211_sta_create_ibss(struct net_device *dev,
 				     struct ieee80211_if_sta *ifsta)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sta_bss *bss;
 	struct ieee80211_sub_if_data *sdata;
 	u8 bssid[ETH_ALEN], *pos;
@@ -2189,7 +2189,7 @@ #endif
 static int ieee80211_sta_find_ibss(struct net_device *dev,
 				   struct ieee80211_if_sta *ifsta)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sta_bss *bss;
 	int found = 0;
 	u8 bssid[ETH_ALEN];
@@ -2281,7 +2281,7 @@ int ieee80211_sta_set_ssid(struct net_de
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_if_sta *ifsta;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (len > IEEE80211_MAX_SSID_LEN)
 		return -EINVAL;
@@ -2376,7 +2376,7 @@ int ieee80211_sta_set_bssid(struct net_d
 
 static void ieee80211_sta_save_oper_chan(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	local->scan_oper_channel = local->conf.channel;
 	local->scan_oper_channel_val = local->conf.channel_val;
 	local->scan_oper_power_level = local->conf.power_level;
@@ -2388,7 +2388,7 @@ static void ieee80211_sta_save_oper_chan
 
 static int ieee80211_sta_restore_oper_chan(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	local->conf.channel = local->scan_oper_channel;
 	local->conf.channel_val = local->scan_oper_channel_val;
 	local->conf.power_level = local->scan_oper_power_level;
@@ -2425,7 +2425,7 @@ static int ieee80211_active_scan(struct 
 static void ieee80211_sta_scan_timer(unsigned long ptr)
 {
 	struct net_device *dev = (struct net_device *) ptr;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_hw_modes *mode;
 	struct ieee80211_channel *chan;
@@ -2526,7 +2526,7 @@ #endif
 
 int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	if (ssid_len > IEEE80211_MAX_SSID_LEN)
 		return -EINVAL;
@@ -2584,7 +2584,7 @@ ieee80211_sta_scan_result(struct net_dev
 			  struct ieee80211_sta_bss *bss,
 			  char *current_ev, char *end_buf)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct iw_event iwe;
 
 	if (time_after(jiffies,
@@ -2746,7 +2746,7 @@ ieee80211_sta_scan_result(struct net_dev
 
 int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct list_head *ptr;
 	char *current_ev = buf;
 	char *end_buf = buf + len;
@@ -2791,7 +2791,7 @@ struct sta_info * ieee80211_ibss_add_sta
 					 struct sk_buff *skb, u8 *bssid,
 					 u8 *addr)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct list_head *ptr;
 	struct sta_info *sta;
 	struct ieee80211_sub_if_data *sdata = NULL;
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index 5c7af9f..fb95e96 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -53,6 +53,11 @@ static ssize_t store_remove_iface(struct
 	return res < 0 ? res : len;
 }
 
+static void ieee80211_class_dev_release(struct class_device *dev)
+{
+	ieee80211_release_hw(to_ieee80211_local(dev));
+}
+
 #ifdef CONFIG_HOTPLUG
 static int ieee80211_uevent(struct class_device *cd, char **envp,
 			    int num_envp, char *buf, int size)
@@ -79,28 +84,39 @@ static struct class_device_attribute iee
 static struct class ieee80211_class = {
 	.name = "ieee80211",
 	.class_dev_attrs = ieee80211_class_dev_attrs,
+	.release = ieee80211_class_dev_release,
 #ifdef CONFIG_HOTPLUG
 	.uevent = ieee80211_uevent,
 #endif
 };
 
-int ieee80211_register_sysfs(struct ieee80211_local *local)
+void ieee80211_dev_sysfs_init(struct ieee80211_local *local)
 {
 	local->class_dev.class = &ieee80211_class;
 	local->class_dev.class_data = local;
+	class_device_initialize(&local->class_dev);
+}
+
+void ieee80211_dev_sysfs_put(struct ieee80211_local *local)
+{
+	class_device_put(&local->class_dev);
+}
+
+int ieee80211_dev_sysfs_add(struct ieee80211_local *local)
+{
 	snprintf(local->class_dev.class_id, BUS_ID_SIZE,
 		 "phy%d", local->dev_index);
-	return class_device_register(&local->class_dev);
+	return class_device_add(&local->class_dev);
 }
 
-void ieee80211_unregister_sysfs(struct ieee80211_local *local)
+void ieee80211_dev_sysfs_del(struct ieee80211_local *local)
 {
 	class_device_del(&local->class_dev);
 }
 
 int ieee80211_sysfs_add_netdevice(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 
 	return sysfs_create_link(&dev->class_dev.kobj, &local->class_dev.kobj,
 				 "wiphy");
@@ -108,8 +124,6 @@ int ieee80211_sysfs_add_netdevice(struct
 
 void ieee80211_sysfs_remove_netdevice(struct net_device *dev)
 {
-	struct ieee80211_local *local = dev->priv;
-
 	sysfs_remove_link(&dev->class_dev.kobj, "wiphy");
 }
 
diff --git a/net/d80211/rate_control.c b/net/d80211/rate_control.c
index 429ef2b..3485302 100644
--- a/net/d80211/rate_control.c
+++ b/net/d80211/rate_control.c
@@ -126,7 +126,7 @@ static void rate_control_simple_tx_statu
 					  struct sk_buff *skb,
 					  struct ieee80211_tx_status *status)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	struct sta_info *sta;
 	struct sta_rate_control *srctrl;
@@ -217,7 +217,7 @@ static struct ieee80211_rate *
 rate_control_simple_get_rate(struct net_device *dev, struct sk_buff *skb,
 			     struct rate_control_extra *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	struct sta_info *sta;
diff --git a/net/d80211/rate_control.h b/net/d80211/rate_control.h
index 26d3c0f..b509539 100644
--- a/net/d80211/rate_control.h
+++ b/net/d80211/rate_control.h
@@ -64,7 +64,7 @@ static inline void rate_control_tx_statu
 					  struct sk_buff *skb,
 					  struct ieee80211_tx_status *status)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	local->rate_ctrl->tx_status(dev, skb, status);
 }
 
@@ -73,7 +73,7 @@ static inline struct ieee80211_rate *
 rate_control_get_rate(struct net_device *dev, struct sk_buff *skb,
 		      struct rate_control_extra *extra)
 {
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	return local->rate_ctrl->get_rate(dev, skb, extra);
 }
 
diff --git a/net/d80211/wme.c b/net/d80211/wme.c
index f20d3e0..138f892 100644
--- a/net/d80211/wme.c
+++ b/net/d80211/wme.c
@@ -175,7 +175,7 @@ static inline int wme_downgrade_ac(struc
  * negative return value indicates to drop the frame */
 static inline int classify80211(struct sk_buff *skb, struct Qdisc *qd)
 {
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_tx_packet_data *pkt_data =
 		(struct ieee80211_tx_packet_data *) skb->cb;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -227,7 +227,7 @@ static inline int classify80211(struct s
 
 static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd)
 {
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_sched_data *q = qdisc_priv(qd);
 	struct ieee80211_tx_packet_data *pkt_data =
 		(struct ieee80211_tx_packet_data *) skb->cb;
@@ -314,7 +314,7 @@ static struct sk_buff *wme_qdiscop_deque
 {
 	struct ieee80211_sched_data *q = qdisc_priv(qd);
 	struct net_device *dev = qd->dev;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
 	struct ieee80211_tx_queue_stats stats;
 	struct sk_buff *skb;
@@ -351,7 +351,7 @@ static struct sk_buff *wme_qdiscop_deque
 static void wme_qdiscop_reset(struct Qdisc* qd)
 {
 	struct ieee80211_sched_data *q = qdisc_priv(qd);
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
 	int queue;
 
@@ -368,7 +368,7 @@ static void wme_qdiscop_reset(struct Qdi
 static void wme_qdiscop_destroy(struct Qdisc* qd)
 {
 	struct ieee80211_sched_data *q = qdisc_priv(qd);
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
 	struct tcf_proto *tp;
 	int queue;
@@ -409,7 +409,7 @@ static int wme_qdiscop_init(struct Qdisc
 {
 	struct ieee80211_sched_data *q = qdisc_priv(qd);
 	struct net_device *dev = qd->dev;
-	struct ieee80211_local *local = dev->priv;
+	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int queues = local->hw->queues;
 	int err = 0, i;
 
@@ -464,7 +464,7 @@ static int wme_classop_graft(struct Qdis
 			     struct Qdisc *new, struct Qdisc **old)
 {
 	struct ieee80211_sched_data *q = qdisc_priv(qd);
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
 	unsigned long queue = arg - 1;
 
@@ -488,7 +488,7 @@ static struct Qdisc *
 wme_classop_leaf(struct Qdisc *qd, unsigned long arg)
 {
 	struct ieee80211_sched_data *q = qdisc_priv(qd);
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
 	unsigned long queue = arg - 1;
 
@@ -501,7 +501,7 @@ wme_classop_leaf(struct Qdisc *qd, unsig
 
 static unsigned long wme_classop_get(struct Qdisc *qd, u32 classid)
 {
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
 	unsigned long queue = TC_H_MIN(classid);
 
@@ -529,7 +529,7 @@ static int wme_classop_change(struct Qdi
 			      struct rtattr **tca, unsigned long *arg)
 {
 	unsigned long cl = *arg;
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
 	/* printk(KERN_DEBUG "entering %s\n", __func__); */
 
@@ -547,7 +547,7 @@ static int wme_classop_change(struct Qdi
  * when we add WMM-SA support - TSPECs may be deleted here */
 static int wme_classop_delete(struct Qdisc *qd, unsigned long cl)
 {
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
 	/* printk(KERN_DEBUG "entering %s\n", __func__); */
 
@@ -561,7 +561,7 @@ static int wme_classop_dump_class(struct
 				  struct sk_buff *skb, struct tcmsg *tcm)
 {
 	struct ieee80211_sched_data *q = qdisc_priv(qd);
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
 	/* printk(KERN_DEBUG "entering %s\n", __func__); */
 
@@ -576,7 +576,7 @@ static int wme_classop_dump_class(struct
 
 static void wme_classop_walk(struct Qdisc *qd, struct qdisc_walker *arg)
 {
-	struct ieee80211_local *local = qd->dev->priv;
+	struct ieee80211_local *local = qd->dev->ieee80211_ptr;
 	struct ieee80211_hw *hw = local->hw;
 	int queue;
 	/* printk(KERN_DEBUG "entering %s\n", __func__); */
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/12] d80211: fix Oops when writing to add_ and remove_iface
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
                   ` (2 preceding siblings ...)
  2006-06-08  7:49 ` [PATCH 3/12] d80211: separate allocation of ieee80211_local Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 5/12] d80211: wiphy sysfs attributes Jiri Benc
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

When add_iface or remove_iface sysfs attribute is opened just before device
is unregistered and some data is written there afterwards, their handlers
try to access master net_device which is released at that point.

A similar problem can happen when ioctl is invoked during unregistering - it
is possible that interface the ioctl was called on is still there but master
interface has been already freed.

Fix these problems by:
- checking if the device is unregistered in sysfs handlers and
- releasing all interfaces under single rtnl lock.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c       |    9 +++++++--
 net/d80211/ieee80211_i.h     |    6 ++++++
 net/d80211/ieee80211_sysfs.c |   17 +++++++++++++++--
 3 files changed, 28 insertions(+), 4 deletions(-)

25dd82745a86401267b9954098b99ba4a60a71f6
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 4fc2e7d..c983d70 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4225,6 +4225,8 @@ int ieee80211_register_hw(struct net_dev
 	result = ieee80211_if_add(dev, "wlan%d", 1, &sta_dev);
 	if (result == 0)
 		ieee80211_if_set_type(sta_dev, IEEE80211_IF_TYPE_STA);
+
+	local->reg_state = IEEE80211_DEV_REGISTERED;
 	rtnl_unlock();
 
 	return 0;
@@ -4290,14 +4292,17 @@ void ieee80211_unregister_hw(struct net_
 		del_timer_sync(&local->scan_timer);
 	ieee80211_rx_bss_list_deinit(dev);
 
+	rtnl_lock();
+	local->reg_state = IEEE80211_DEV_UNREGISTERED;
 	if (local->apdev)
-		ieee80211_if_del(local->apdev);
+		ieee80211_if_del_mgmt(local->apdev);
 
 	list_for_each_safe(ptr, n, &local->sub_if_list) {
 		struct ieee80211_sub_if_data *sdata =
 			list_entry(ptr, struct ieee80211_sub_if_data, list);
-		ieee80211_if_del(sdata->dev);
+		__ieee80211_if_del(local, sdata);
 	}
+	rtnl_unlock();
 
 	sta_info_stop(local);
 	ieee80211_dev_sysfs_del(local);
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 84cc50e..9fabf17 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -321,6 +321,12 @@ struct ieee80211_local {
 	int dev_index;
 	struct class_device class_dev;
 
+	enum {
+		IEEE80211_DEV_UNITIALIZED = 0,
+		IEEE80211_DEV_REGISTERED,
+		IEEE80211_DEV_UNREGISTERED,
+	} reg_state;
+
 	/* Tasklet and skb queue to process calls from IRQ mode. All frames
 	 * added to skb_queue will be processed, but frames in
 	 * skb_queue_unreliable may be dropped if the total length of these
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index fb95e96..e799506 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -17,6 +17,15 @@ #include "ieee80211_i.h"
 
 #define to_ieee80211_local(class)	container_of(class, struct ieee80211_local, class_dev)
 
+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;
+}
 
 static ssize_t store_add_iface(struct class_device *dev,
 			       const char *buf, size_t len)
@@ -29,7 +38,9 @@ static ssize_t store_add_iface(struct cl
 		return -EPERM;
 	if (len > IFNAMSIZ)
 		return -EINVAL;
-	rtnl_lock();
+	res = rtnl_lock_local(local);
+	if (res)
+		return res;
 	res = ieee80211_if_add(local->mdev, buf, 0, &new_dev);
 	if (res == 0)
 		ieee80211_if_set_type(new_dev, IEEE80211_IF_TYPE_STA);
@@ -47,7 +58,9 @@ static ssize_t store_remove_iface(struct
 		return -EPERM;
 	if (len > IFNAMSIZ)
 		return -EINVAL;
-	rtnl_lock();
+	res = rtnl_lock_local(local);
+	if (res)
+		return res;
 	res = ieee80211_if_remove(local->mdev, buf, -1);
 	rtnl_unlock();
 	return res < 0 ? res : len;
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/12] d80211: wiphy sysfs attributes
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
                   ` (3 preceding siblings ...)
  2006-06-08  7:49 ` [PATCH 4/12] d80211: fix Oops when writing to add_ and remove_iface Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 6/12] d80211: network interface " Jiri Benc
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

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

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211_proc.c  |    4 -
 net/d80211/ieee80211_proc.h  |    3 
 net/d80211/ieee80211_sysfs.c |  304 +++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 302 insertions(+), 9 deletions(-)

b049b3afd8db895dd1f6985c1d1051eb733b887b
diff --git a/net/d80211/ieee80211_proc.c b/net/d80211/ieee80211_proc.c
index 4f3a6b9..581b583 100644
--- a/net/d80211/ieee80211_proc.c
+++ b/net/d80211/ieee80211_proc.c
@@ -442,7 +442,7 @@ #endif /* CONFIG_D80211_DEBUG_COUNTERS *
 }
 
 
-static const char * ieee80211_mode_str_short(int mode)
+const char *ieee80211_mode_str_short(int mode)
 {
 	switch (mode) {
 	case MODE_IEEE80211A:
@@ -459,7 +459,7 @@ static const char * ieee80211_mode_str_s
 }
 
 
-static const char * ieee80211_mode_str(int mode)
+const char *ieee80211_mode_str(int mode)
 {
 	switch (mode) {
 	case MODE_IEEE80211A:
diff --git a/net/d80211/ieee80211_proc.h b/net/d80211/ieee80211_proc.h
index 8c76560..4519d26 100644
--- a/net/d80211/ieee80211_proc.h
+++ b/net/d80211/ieee80211_proc.h
@@ -42,4 +42,7 @@ static inline void ieee80211_proc_init(v
 static inline void ieee80211_proc_deinit(void) {}
 #endif /* CONFIG_PROC_FS */
 
+const char *ieee80211_mode_str(int mode);
+const char *ieee80211_mode_str_short(int mode);
+
 #endif /* IEEE80211_PROC_H */
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index e799506..07a7036 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -14,6 +14,8 @@ #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <net/d80211.h>
 #include "ieee80211_i.h"
+#include "ieee80211_proc.h"
+#include "rate_control.h"
 
 #define to_ieee80211_local(class)	container_of(class, struct ieee80211_local, class_dev)
 
@@ -27,6 +29,8 @@ static inline int rtnl_lock_local(struct
 	return 0;
 }
 
+/* attributes in /sys/class/ieee80211/phyX/ */
+
 static ssize_t store_add_iface(struct class_device *dev,
 			       const char *buf, size_t len)
 {
@@ -66,6 +70,284 @@ static ssize_t store_remove_iface(struct
 	return res < 0 ? res : len;
 }
 
+static ssize_t ieee80211_local_show(struct class_device *dev, 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 class_device *cd,	\
+					   char *buf)			\
+{									\
+	return ieee80211_local_show(cd, 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, conf.channel, "%d");
+IEEE80211_LOCAL_SHOW(frequency, conf.freq, "%d");
+IEEE80211_LOCAL_SHOW(radar_detect, conf.radar_detect, "%d");
+IEEE80211_LOCAL_SHOW(antenna_sel, conf.antenna_sel, "%d");
+IEEE80211_LOCAL_SHOW(calib_int, conf.calib_int, "%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->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->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)
+{
+	int i;
+	struct ieee80211_hw_modes *mode;
+	char *p = buf;
+
+	/* FIXME: locking against ieee80211_update_hw? */
+	for (i = 0; i < local->hw->num_modes; i++) {
+		mode = &local->hw->modes[i];
+		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)
+{
+	if (local->rate_ctrl && local->rate_ctrl_priv)
+		return sprintf(buf, "%s\n", local->rate_ctrl->name);
+	return 0;
+}
+__IEEE80211_LOCAL_SHOW(rate_ctrl_alg);
+
+static struct class_device_attribute ieee80211_class_dev_attrs[] = {
+	__ATTR(add_iface, S_IWUSR, NULL, store_add_iface),
+	__ATTR(remove_iface, S_IWUSR, NULL, store_remove_iface),
+	__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, S_IRUGO, ieee80211_local_show_antenna_sel, NULL),
+	__ATTR(calib_int, S_IRUGO, ieee80211_local_show_calib_int, 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, ieee80211_local_show_rate_ctrl_alg, NULL),
+	{}
+};
+
+/* attributes in /sys/class/ieee80211/phyX/statistics/ */
+
+#define IEEE80211_LOCAL_ATTR(name, field, format)			\
+IEEE80211_LOCAL_SHOW(name, field, format)				\
+static CLASS_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_D80211_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_rate_limit, tx_handlers_drop_rate_limit, "%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 CLASS_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 CLASS_DEVICE_ATTR(wme_tx_queue, S_IRUGO,
+			 ieee80211_local_show_wme_tx_queue, NULL);
+#endif
+
+static ssize_t ieee80211_stats_show(struct class_device *dev, 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->hw->get_stats)
+		return -EOPNOTSUPP;
+	ret = rtnl_lock_local(local);
+	if (ret)
+		return ret;
+	ret = local->hw->get_stats(local->mdev, &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 class_device *cd,	\
+					   char *buf)			\
+{									\
+	return ieee80211_stats_show(cd, buf,				\
+				    ieee80211_stats_fmt_##name);	\
+}
+
+#define IEEE80211_STATS_ATTR(name, field, format)			\
+IEEE80211_STATS_FMT(name, field, format "\n")				\
+__IEEE80211_STATS_SHOW(name)						\
+static CLASS_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[] = {
+	&class_device_attr_transmitted_fragment_count.attr,
+	&class_device_attr_multicast_transmitted_frame_count.attr,
+	&class_device_attr_failed_count.attr,
+	&class_device_attr_retry_count.attr,
+	&class_device_attr_multiple_retry_count.attr,
+	&class_device_attr_frame_duplicate_count.attr,
+	&class_device_attr_received_fragment_count.attr,
+	&class_device_attr_multicast_received_frame_count.attr,
+	&class_device_attr_transmitted_frame_count.attr,
+	&class_device_attr_wep_undecryptable_count.attr,
+	&class_device_attr_ack_failure_count.attr,
+	&class_device_attr_rts_failure_count.attr,
+	&class_device_attr_fcs_error_count.attr,
+	&class_device_attr_rts_success_count.attr,
+	&class_device_attr_num_scans.attr,
+#ifdef CONFIG_D80211_DEBUG_COUNTERS
+	&class_device_attr_tx_handlers_drop.attr,
+	&class_device_attr_tx_handlers_queued.attr,
+	&class_device_attr_tx_handlers_drop_unencrypted.attr,
+	&class_device_attr_tx_handlers_drop_fragment.attr,
+	&class_device_attr_tx_handlers_drop_wep.attr,
+	&class_device_attr_tx_handlers_drop_rate_limit.attr,
+	&class_device_attr_tx_handlers_drop_not_assoc.attr,
+	&class_device_attr_tx_handlers_drop_unauth_port.attr,
+	&class_device_attr_rx_handlers_drop.attr,
+	&class_device_attr_rx_handlers_queued.attr,
+	&class_device_attr_rx_handlers_drop_nullfunc.attr,
+	&class_device_attr_rx_handlers_drop_defrag.attr,
+	&class_device_attr_rx_handlers_drop_short.attr,
+	&class_device_attr_rx_handlers_drop_passive_scan.attr,
+	&class_device_attr_tx_expand_skb_head.attr,
+	&class_device_attr_tx_expand_skb_head_cloned.attr,
+	&class_device_attr_rx_expand_skb_head.attr,
+	&class_device_attr_rx_expand_skb_head2.attr,
+	&class_device_attr_rx_handlers_fragments.attr,
+	&class_device_attr_tx_status_drop.attr,
+	&class_device_attr_wme_rx_queue.attr,
+	&class_device_attr_wme_tx_queue.attr,
+#endif
+	NULL,
+};
+
+static struct attribute_group ieee80211_stats_group = {
+	.name = "statistics",
+	.attrs = ieee80211_stats_attrs,
+};
+
+/* /sys/class/ieee80211/phyX functions */
+
 static void ieee80211_class_dev_release(struct class_device *dev)
 {
 	ieee80211_release_hw(to_ieee80211_local(dev));
@@ -88,12 +370,6 @@ static int ieee80211_uevent(struct class
 }
 #endif
 
-static struct class_device_attribute ieee80211_class_dev_attrs[] = {
-	__ATTR(add_iface, S_IWUSR, NULL, store_add_iface),
-	__ATTR(remove_iface, S_IWUSR, NULL, store_remove_iface),
-	{}
-};
-
 static struct class ieee80211_class = {
 	.name = "ieee80211",
 	.class_dev_attrs = ieee80211_class_dev_attrs,
@@ -117,16 +393,28 @@ void ieee80211_dev_sysfs_put(struct ieee
 
 int ieee80211_dev_sysfs_add(struct ieee80211_local *local)
 {
+	int res;
+
 	snprintf(local->class_dev.class_id, BUS_ID_SIZE,
 		 "phy%d", local->dev_index);
-	return class_device_add(&local->class_dev);
+	res = class_device_add(&local->class_dev);
+	if (res)
+		return res;
+	res = sysfs_create_group(&local->class_dev.kobj,
+				 &ieee80211_stats_group);
+	if (res)
+		class_device_del(&local->class_dev);
+	return res;
 }
 
 void ieee80211_dev_sysfs_del(struct ieee80211_local *local)
 {
+	sysfs_remove_group(&local->class_dev.kobj, &ieee80211_stats_group);
 	class_device_del(&local->class_dev);
 }
 
+/* /sys/class/net/X functions */
+
 int ieee80211_sysfs_add_netdevice(struct net_device *dev)
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
@@ -140,6 +428,8 @@ void ieee80211_sysfs_remove_netdevice(st
 	sysfs_remove_link(&dev->class_dev.kobj, "wiphy");
 }
 
+/* general module functions */
+
 int ieee80211_sysfs_init(void)
 {
 	return class_register(&ieee80211_class);
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/12] d80211: network interface sysfs attributes
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
                   ` (4 preceding siblings ...)
  2006-06-08  7:49 ` [PATCH 5/12] d80211: wiphy sysfs attributes Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 7/12] d80211: rename sta_info_relase to sta_info_put Jiri Benc
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Add /sys/class/net/X/* attributes for 802.11 interfaces.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211_i.h     |    3 
 net/d80211/ieee80211_iface.c |    1 
 net/d80211/ieee80211_sysfs.c |  299 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 301 insertions(+), 2 deletions(-)

ad13a53621edc97c9bfb41a513a674415186c392
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 9fabf17..7c1b621 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -305,6 +305,8 @@ #define NUM_DEFAULT_KEYS 4
         } u;
         int channel_use;
         int channel_use_raw;
+
+	struct attribute_group *sysfs_group;
 };
 
 #define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev)
@@ -616,5 +618,6 @@ int ieee80211_dev_sysfs_add(struct ieee8
 void ieee80211_dev_sysfs_del(struct ieee80211_local *local);
 int ieee80211_sysfs_init(void);
 void ieee80211_sysfs_deinit(void);
+int ieee80211_sysfs_change_if_type(struct net_device *dev);
 
 #endif /* IEEE80211_I_H */
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 8ab2c07..727b5e3 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -202,6 +202,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);
 }
 
 /* Must be called with rtnl lock held. */
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index 07a7036..12d16fd 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -18,6 +18,7 @@ #include "ieee80211_proc.h"
 #include "rate_control.h"
 
 #define to_ieee80211_local(class)	container_of(class, struct ieee80211_local, class_dev)
+#define to_net_dev(class)		container_of(class, struct net_device, class_dev)
 
 static inline int rtnl_lock_local(struct ieee80211_local *local)
 {
@@ -346,6 +347,238 @@ static struct attribute_group ieee80211_
 	.attrs = ieee80211_stats_attrs,
 };
 
+/* attributes in /sys/class/net/X/ */
+
+static ssize_t ieee80211_if_show(struct class_device *cd, char *buf,
+			ssize_t (*format)(const struct ieee80211_sub_if_data *,
+					  char *))
+{
+	struct net_device *dev = to_net_dev(cd);
+	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, MACSTR "\n", MAC2STR(sdata->field));	\
+}
+
+#define __IEEE80211_IF_SHOW(name)					\
+static ssize_t ieee80211_if_show_##name(struct class_device *cd,	\
+					char *buf)			\
+{									\
+	return ieee80211_if_show(cd, buf, ieee80211_if_fmt_##name);	\
+}									\
+static CLASS_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(max_aid, u.ap.max_aid, DEC);
+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->monitor_during_oper ||
+				     local->open_count == local->monitors) ?
+				    "hard" : "soft");
+}
+__IEEE80211_IF_SHOW(mode);
+
+static struct attribute *ieee80211_sta_attrs[] = {
+	&class_device_attr_channel_use.attr,
+	&class_device_attr_drop_unencrypted.attr,
+	&class_device_attr_eapol.attr,
+	&class_device_attr_ieee8021_x.attr,
+	&class_device_attr_state.attr,
+	&class_device_attr_bssid.attr,
+	&class_device_attr_prev_bssid.attr,
+	&class_device_attr_ssid_len.attr,
+	&class_device_attr_aid.attr,
+	&class_device_attr_ap_capab.attr,
+	&class_device_attr_capab.attr,
+	&class_device_attr_extra_ie_len.attr,
+	&class_device_attr_auth_tries.attr,
+	&class_device_attr_assoc_tries.attr,
+	&class_device_attr_auth_algs.attr,
+	&class_device_attr_auth_alg.attr,
+	&class_device_attr_auth_transaction.attr,
+	&class_device_attr_flags.attr,
+	NULL
+};
+
+static struct attribute *ieee80211_ap_attrs[] = {
+	&class_device_attr_channel_use.attr,
+	&class_device_attr_drop_unencrypted.attr,
+	&class_device_attr_eapol.attr,
+	&class_device_attr_ieee8021_x.attr,
+	&class_device_attr_max_aid.attr,
+	&class_device_attr_num_sta_ps.attr,
+	&class_device_attr_dtim_period.attr,
+	&class_device_attr_dtim_count.attr,
+	&class_device_attr_num_beacons.attr,
+	&class_device_attr_force_unicast_rateidx.attr,
+	&class_device_attr_max_ratectrl_rateidx.attr,
+	&class_device_attr_num_buffered_multicast.attr,
+	&class_device_attr_beacon_head_len.attr,
+	&class_device_attr_beacon_tail_len.attr,
+	NULL
+};
+
+static struct attribute *ieee80211_wds_attrs[] = {
+	&class_device_attr_channel_use.attr,
+	&class_device_attr_drop_unencrypted.attr,
+	&class_device_attr_eapol.attr,
+	&class_device_attr_ieee8021_x.attr,
+	&class_device_attr_peer.attr,
+	NULL
+};
+
+static struct attribute *ieee80211_vlan_attrs[] = {
+	&class_device_attr_channel_use.attr,
+	&class_device_attr_drop_unencrypted.attr,
+	&class_device_attr_eapol.attr,
+	&class_device_attr_ieee8021_x.attr,
+	&class_device_attr_vlan_id.attr,
+	NULL
+};
+
+static struct attribute *ieee80211_monitor_attrs[] = {
+	&class_device_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/ieee80211/phyX functions */
 
 static void ieee80211_class_dev_release(struct class_device *dev)
@@ -415,16 +648,78 @@ void ieee80211_dev_sysfs_del(struct ieee
 
 /* /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->class_dev.kobj, dev);
+}
+
 int ieee80211_sysfs_add_netdevice(struct net_device *dev)
 {
 	struct ieee80211_local *local = dev->ieee80211_ptr;
+	int res;
 
-	return sysfs_create_link(&dev->class_dev.kobj, &local->class_dev.kobj,
-				 "wiphy");
+	res = sysfs_create_link(&dev->class_dev.kobj, &local->class_dev.kobj,
+				"wiphy");
+	if (res)
+		goto out;
+	res = ieee80211_add_if_group(&dev->class_dev.kobj, dev);
+	if (res)
+		sysfs_remove_link(&dev->class_dev.kobj, "wiphy");
+out:
+	return res;
 }
 
 void ieee80211_sysfs_remove_netdevice(struct net_device *dev)
 {
+	ieee80211_remove_if_group(&dev->class_dev.kobj, dev);
 	sysfs_remove_link(&dev->class_dev.kobj, "wiphy");
 }
 
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/12] d80211: rename sta_info_relase to sta_info_put
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
                   ` (5 preceding siblings ...)
  2006-06-08  7:49 ` [PATCH 6/12] d80211: network interface " Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 8/12] d80211: sysfs attributes for associated stations Jiri Benc
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

sta_info structure has reference counting (will be converted to kobject in
next patch). Therefore, sta_info_release should be divided into two
functions - one for decrementing reference count and one for freeing the
structure when the count drops to zero. sta_info_release is the name
suitable for the second function.

This patch renames sta_info_release to sta_info_put to let next patch
introduce a new sta_info_release function.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c       |   18 +++++++++---------
 net/d80211/ieee80211_iface.c |    2 +-
 net/d80211/ieee80211_ioctl.c |   18 +++++++++---------
 net/d80211/ieee80211_sta.c   |    8 ++++----
 net/d80211/rate_control.c    |    4 ++--
 net/d80211/sta_info.c        |   10 +++++-----
 net/d80211/sta_info.h        |    2 +-
 7 files changed, 31 insertions(+), 31 deletions(-)

4ddde98ebbdede0d0b16a85156e1b9c192c0e764
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index c983d70..0c23607 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1153,7 +1153,7 @@ static int ieee80211_tx(struct net_devic
 	skb = tx.skb; /* handlers are allowed to change skb */
 
 	if (sta)
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 
 	if (unlikely(res == TXRX_DROP)) {
 		I802_DEBUG_INC(local->tx_handlers_drop);
@@ -1373,7 +1373,7 @@ static int ieee80211_subif_start_xmit(st
 			fc |= WLAN_FC_STYPE_QOS_DATA << 4;
 			hdrlen += 2;
 		}
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 	}
 
 	hdr.frame_control = cpu_to_le16(fc);
@@ -1743,7 +1743,7 @@ ieee80211_get_buffered_bc(struct net_dev
 	}
 
 	if (sta)
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 
 	return skb;
 }
@@ -2330,7 +2330,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 				skb = NULL;
 			}
 			if (dsta)
-				sta_info_release(local, dsta);
+				sta_info_put(local, dsta);
 		}
 	}
 
@@ -3469,7 +3469,7 @@ void __ieee80211_rx(struct net_device *d
 
   end:
 	if (sta)
-                sta_info_release(local, sta);
+		sta_info_put(local, sta);
 }
 
 
@@ -3806,7 +3806,7 @@ void ieee80211_tx_status(struct net_devi
 				status->excessive_retries = 0;
 				status->tx_filtered = 1;
 			}
-			sta_info_release(local, sta);
+			sta_info_put(local, sta);
 		}
 	}
 
@@ -3855,7 +3855,7 @@ void ieee80211_tx_status(struct net_devi
 				}
 				dev_kfree_skb(skb);
 			}
-			sta_info_release(local, sta);
+			sta_info_put(local, sta);
 			return;
 		}
 	} else {
@@ -3978,7 +3978,7 @@ int ieee80211_if_update_wds(struct net_d
 	/* Remove STA entry for the old peer */
 	sta = sta_info_get(local, sdata->u.wds.remote_addr);
 	if (sta) {
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 		sta_info_free(local, sta, 0);
 	} else {
 		printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
@@ -4522,7 +4522,7 @@ EXPORT_SYMBOL(ieee80211_get_hdrlen_from_
 EXPORT_SYMBOL(ieee80211_rate_control_register);
 EXPORT_SYMBOL(ieee80211_rate_control_unregister);
 EXPORT_SYMBOL(sta_info_get);
-EXPORT_SYMBOL(sta_info_release);
+EXPORT_SYMBOL(sta_info_put);
 EXPORT_SYMBOL(ieee80211_radar_status);
 EXPORT_SYMBOL(ieee80211_get_mc_list_item);
 
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 727b5e3..467dcba 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -261,7 +261,7 @@ #endif
 	case IEEE80211_IF_TYPE_WDS:
 		sta = sta_info_get(local, sdata->u.wds.remote_addr);
 		if (sta) {
-			sta_info_release(local, sta);
+			sta_info_put(local, sta);
 			sta_info_free(local, sta, 0);
 		} else {
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 8d593e8..e1bdc03 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -294,7 +294,7 @@ static int ieee80211_ioctl_add_sta(struc
 		}
 	}
 
-	sta_info_release(local, sta);
+	sta_info_put(local, sta);
 
 	return 0;
 }
@@ -308,7 +308,7 @@ static int ieee80211_ioctl_remove_sta(st
 
 	sta = sta_info_get(local, param->sta_addr);
 	if (sta) {
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 		sta_info_free(local, sta, 1);
 	}
 
@@ -393,7 +393,7 @@ static int ieee80211_ioctl_get_info_sta(
 	param->u.get_info_sta.last_rssi = sta->last_rssi;
 	param->u.get_info_sta.last_ack_rssi = sta->last_ack_rssi[2];
 
-	sta_info_release(local, sta);
+	sta_info_put(local, sta);
 
 	return 0;
 }
@@ -421,7 +421,7 @@ static int ieee80211_ioctl_set_flags_sta
 			printk(KERN_DEBUG "%s: failed to set low-level driver "
 			       "PAE state (unauthorized) for " MACSTR "\n",
 			       dev->name, MAC2STR(sta->addr));
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 	}
 
 	return sta ? 0 : -ENOENT;
@@ -563,7 +563,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 				if (sta->flags & WLAN_STA_WME) {
 					try_hwaccel = 0;
 				}
-				sta_info_release(local, sta);
+				sta_info_put(local, sta);
 				sta = NULL;
 			}
 		}
@@ -643,7 +643,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
  done:
 	if (sta)
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 
 	return ret;
 }
@@ -813,7 +813,7 @@ static int ieee80211_ioctl_get_encryptio
 	}
 
 	if (sta)
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 
 	return ret;
 }
@@ -842,7 +842,7 @@ static int ieee80211_ioctl_wpa_trigger(s
 
 	sta->wpa_trigger = param->u.wpa_trigger.trigger;
 
-	sta_info_release(local, sta);
+	sta_info_put(local, sta);
 	return 0;
 }
 #endif /* CONFIG_HOSTAPD_WPA_TESTING */
@@ -1136,7 +1136,7 @@ #endif
 			sta->vlan_id = param->u.set_sta_vlan.vlan_id;
                         dev_put(new_vlan_dev);
                 }
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 	}
 
 	return sta ? 0 : -ENOENT;
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index 66a4575..a42c387 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -730,7 +730,7 @@ static void ieee80211_associated(struct 
 							 ifsta->ssid_len);
 			}
 		}
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 	}
 	if (disassoc) {
 		union iwreq_data wrqu;
@@ -1200,7 +1200,7 @@ static void ieee80211_rx_mgmt_assoc_resp
 	}
 
 
-	sta_info_release(local, sta);
+	sta_info_put(local, sta);
 
 	ieee80211_associated(dev, ifsta);
 }
@@ -1443,7 +1443,7 @@ #endif /* IEEE80211_IBSS_DEBUG */
 			       dev->name, MAC2STR(sta->addr), prev_rates,
 			       supp_rates, sta->supp_rates);
 		}
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 	}
 
 	if (elems.ssid == NULL)
@@ -2834,7 +2834,7 @@ struct sta_info * ieee80211_ibss_add_sta
 
 	rate_control_rate_init(local, sta);
 
-	return sta; /* caller will call sta_info_release() */
+	return sta; /* caller will call sta_info_put() */
 }
 
 
diff --git a/net/d80211/rate_control.c b/net/d80211/rate_control.c
index 3485302..9bcb8fc 100644
--- a/net/d80211/rate_control.c
+++ b/net/d80211/rate_control.c
@@ -209,7 +209,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 		}
 	}
 
-	sta_info_release(local, sta);
+	sta_info_put(local, sta);
 }
 
 
@@ -260,7 +260,7 @@ rate_control_simple_get_rate(struct net_
 	extra->nonerp_idx = nonerp_idx;
 	extra->nonerp = &local->curr_rates[extra->nonerp_idx];
 
-	sta_info_release(local, sta);
+	sta_info_put(local, sta);
 
 	return &local->curr_rates[rateidx];
 }
diff --git a/net/d80211/sta_info.c b/net/d80211/sta_info.c
index de14821..9565c29 100644
--- a/net/d80211/sta_info.c
+++ b/net/d80211/sta_info.c
@@ -98,7 +98,7 @@ int sta_info_min_txrate_get(struct ieee8
 }
 
 
-void sta_info_release(struct ieee80211_local *local, struct sta_info *sta)
+void sta_info_put(struct ieee80211_local *local, struct sta_info *sta)
 {
 	struct sk_buff *skb;
 
@@ -145,7 +145,7 @@ struct sta_info * sta_info_add(struct ie
 	atomic_inc(&sta->users); /* sta in hashlist etc, decremented by
 				  * sta_info_free() */
 	atomic_inc(&sta->users); /* sta used by caller, decremented by
-				  * sta_info_release() */
+				  * sta_info_put() */
 	spin_lock_bh(&local->sta_lock);
 	list_add(&sta->list, &local->sta_list);
 	local->num_sta++;
@@ -237,13 +237,13 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 	if (atomic_read(&sta->users) != 1) {
 		/* This is OK, but printed for debugging. The station structure
 		 * will be removed when the other user of the data calls
-		 * sta_info_release(). */
+		 * sta_info_put(). */
 		printk(KERN_DEBUG "%s: STA " MACSTR " users count %d when "
 		       "removing it\n", local->mdev->name, MAC2STR(sta->addr),
 		       atomic_read(&sta->users));
 	}
 
-	sta_info_release(local, sta);
+	sta_info_put(local, sta);
 }
 
 
@@ -302,7 +302,7 @@ static void sta_info_cleanup(unsigned lo
 		struct sta_info *sta = (struct sta_info *) ptr;
 		atomic_inc(&sta->users);
 		sta_info_cleanup_expire_buffered(local, sta);
-		sta_info_release(local, sta);
+		sta_info_put(local, sta);
 		ptr = ptr->next;
 	}
 	spin_unlock_bh(&local->sta_lock);
diff --git a/net/d80211/sta_info.h b/net/d80211/sta_info.h
index 294cb0a..fddc80e 100644
--- a/net/d80211/sta_info.h
+++ b/net/d80211/sta_info.h
@@ -134,7 +134,7 @@ struct ieee80211_local;
 
 struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr);
 int sta_info_min_txrate_get(struct ieee80211_local *local);
-void sta_info_release(struct ieee80211_local *local, struct sta_info *sta);
+void sta_info_put(struct ieee80211_local *local, struct sta_info *sta);
 struct sta_info * sta_info_add(struct ieee80211_local *local,
 			       struct net_device *dev, u8 *addr);
 void sta_info_free(struct ieee80211_local *local, struct sta_info *sta,
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 8/12] d80211: sysfs attributes for associated stations
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
                   ` (6 preceding siblings ...)
  2006-06-08  7:49 ` [PATCH 7/12] d80211: rename sta_info_relase to sta_info_put Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 9/12] d80211: remove useless parameters Jiri Benc
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

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

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

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

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


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 9/12] d80211: remove useless parameters
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
                   ` (7 preceding siblings ...)
  2006-06-08  7:49 ` [PATCH 8/12] d80211: sysfs attributes for associated stations Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 10/12] d80211: rate_control sysfs attributes Jiri Benc
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

There is no necessity for passing ieee80211_local parameter to sta_info_put
and sta_info_free now.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c       |   18 +++++++++---------
 net/d80211/ieee80211_iface.c |    4 ++--
 net/d80211/ieee80211_ioctl.c |   20 ++++++++++----------
 net/d80211/ieee80211_sta.c   |    8 ++++----
 net/d80211/rate_control.c    |    4 ++--
 net/d80211/sta_info.c        |   16 ++++++++--------
 net/d80211/sta_info.h        |    5 ++---
 7 files changed, 37 insertions(+), 38 deletions(-)

bc9e55deef4924f5a4ba82487747726413636df6
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 15d43f8..75aaa99 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1153,7 +1153,7 @@ static int ieee80211_tx(struct net_devic
 	skb = tx.skb; /* handlers are allowed to change skb */
 
 	if (sta)
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 
 	if (unlikely(res == TXRX_DROP)) {
 		I802_DEBUG_INC(local->tx_handlers_drop);
@@ -1373,7 +1373,7 @@ static int ieee80211_subif_start_xmit(st
 			fc |= WLAN_FC_STYPE_QOS_DATA << 4;
 			hdrlen += 2;
 		}
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 	}
 
 	hdr.frame_control = cpu_to_le16(fc);
@@ -1743,7 +1743,7 @@ ieee80211_get_buffered_bc(struct net_dev
 	}
 
 	if (sta)
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 
 	return skb;
 }
@@ -2330,7 +2330,7 @@ ieee80211_rx_h_data(struct ieee80211_txr
 				skb = NULL;
 			}
 			if (dsta)
-				sta_info_put(local, dsta);
+				sta_info_put(dsta);
 		}
 	}
 
@@ -3469,7 +3469,7 @@ void __ieee80211_rx(struct net_device *d
 
   end:
 	if (sta)
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 }
 
 
@@ -3806,7 +3806,7 @@ void ieee80211_tx_status(struct net_devi
 				status->excessive_retries = 0;
 				status->tx_filtered = 1;
 			}
-			sta_info_put(local, sta);
+			sta_info_put(sta);
 		}
 	}
 
@@ -3855,7 +3855,7 @@ void ieee80211_tx_status(struct net_devi
 				}
 				dev_kfree_skb(skb);
 			}
-			sta_info_put(local, sta);
+			sta_info_put(sta);
 			return;
 		}
 	} else {
@@ -3978,8 +3978,8 @@ int ieee80211_if_update_wds(struct net_d
 	/* Remove STA entry for the old peer */
 	sta = sta_info_get(local, sdata->u.wds.remote_addr);
 	if (sta) {
-		sta_info_put(local, sta);
-		sta_info_free(local, sta, 0);
+		sta_info_put(sta);
+		sta_info_free(sta, 0);
 	} else {
 		printk(KERN_DEBUG "%s: could not find STA entry for WDS link "
 		       "peer " MACSTR "\n",
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 467dcba..960a90e 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -261,8 +261,8 @@ #endif
 	case IEEE80211_IF_TYPE_WDS:
 		sta = sta_info_get(local, sdata->u.wds.remote_addr);
 		if (sta) {
-			sta_info_put(local, sta);
-			sta_info_free(local, sta, 0);
+			sta_info_put(sta);
+			sta_info_free(sta, 0);
 		} else {
 #ifdef CONFIG_D80211_VERBOSE_DEBUG
 			printk(KERN_DEBUG "%s: Someone had deleted my STA "
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index e1bdc03..562b9f3 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -294,7 +294,7 @@ static int ieee80211_ioctl_add_sta(struc
 		}
 	}
 
-	sta_info_put(local, sta);
+	sta_info_put(sta);
 
 	return 0;
 }
@@ -308,8 +308,8 @@ static int ieee80211_ioctl_remove_sta(st
 
 	sta = sta_info_get(local, param->sta_addr);
 	if (sta) {
-		sta_info_put(local, sta);
-		sta_info_free(local, sta, 1);
+		sta_info_put(sta);
+		sta_info_free(sta, 1);
 	}
 
 	return sta ? 0 : -ENOENT;
@@ -393,7 +393,7 @@ static int ieee80211_ioctl_get_info_sta(
 	param->u.get_info_sta.last_rssi = sta->last_rssi;
 	param->u.get_info_sta.last_ack_rssi = sta->last_ack_rssi[2];
 
-	sta_info_put(local, sta);
+	sta_info_put(sta);
 
 	return 0;
 }
@@ -421,7 +421,7 @@ static int ieee80211_ioctl_set_flags_sta
 			printk(KERN_DEBUG "%s: failed to set low-level driver "
 			       "PAE state (unauthorized) for " MACSTR "\n",
 			       dev->name, MAC2STR(sta->addr));
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 	}
 
 	return sta ? 0 : -ENOENT;
@@ -563,7 +563,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 				if (sta->flags & WLAN_STA_WME) {
 					try_hwaccel = 0;
 				}
-				sta_info_put(local, sta);
+				sta_info_put(sta);
 				sta = NULL;
 			}
 		}
@@ -643,7 +643,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
  done:
 	if (sta)
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 
 	return ret;
 }
@@ -813,7 +813,7 @@ static int ieee80211_ioctl_get_encryptio
 	}
 
 	if (sta)
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 
 	return ret;
 }
@@ -842,7 +842,7 @@ static int ieee80211_ioctl_wpa_trigger(s
 
 	sta->wpa_trigger = param->u.wpa_trigger.trigger;
 
-	sta_info_put(local, sta);
+	sta_info_put(sta);
 	return 0;
 }
 #endif /* CONFIG_HOSTAPD_WPA_TESTING */
@@ -1136,7 +1136,7 @@ #endif
 			sta->vlan_id = param->u.set_sta_vlan.vlan_id;
                         dev_put(new_vlan_dev);
                 }
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 	}
 
 	return sta ? 0 : -ENOENT;
diff --git a/net/d80211/ieee80211_sta.c b/net/d80211/ieee80211_sta.c
index a42c387..37d40aa 100644
--- a/net/d80211/ieee80211_sta.c
+++ b/net/d80211/ieee80211_sta.c
@@ -730,7 +730,7 @@ static void ieee80211_associated(struct 
 							 ifsta->ssid_len);
 			}
 		}
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 	}
 	if (disassoc) {
 		union iwreq_data wrqu;
@@ -1200,7 +1200,7 @@ static void ieee80211_rx_mgmt_assoc_resp
 	}
 
 
-	sta_info_put(local, sta);
+	sta_info_put(sta);
 
 	ieee80211_associated(dev, ifsta);
 }
@@ -1443,7 +1443,7 @@ #endif /* IEEE80211_IBSS_DEBUG */
 			       dev->name, MAC2STR(sta->addr), prev_rates,
 			       supp_rates, sta->supp_rates);
 		}
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 	}
 
 	if (elems.ssid == NULL)
@@ -1836,7 +1836,7 @@ static void ieee80211_sta_expire(struct 
 			       IEEE80211_IBSS_INACTIVITY_LIMIT)) {
 			printk(KERN_DEBUG "%s: expiring inactive STA " MACSTR
 			       "\n", dev->name, MAC2STR(sta->addr));
-			sta_info_free(local, sta, 1);
+			sta_info_free(sta, 1);
 		}
 	}
 	spin_unlock_bh(&local->sta_lock);
diff --git a/net/d80211/rate_control.c b/net/d80211/rate_control.c
index 9bcb8fc..e7e6791 100644
--- a/net/d80211/rate_control.c
+++ b/net/d80211/rate_control.c
@@ -209,7 +209,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 		}
 	}
 
-	sta_info_put(local, sta);
+	sta_info_put(sta);
 }
 
 
@@ -260,7 +260,7 @@ rate_control_simple_get_rate(struct net_
 	extra->nonerp_idx = nonerp_idx;
 	extra->nonerp = &local->curr_rates[extra->nonerp_idx];
 
-	sta_info_put(local, sta);
+	sta_info_put(sta);
 
 	return &local->curr_rates[rateidx];
 }
diff --git a/net/d80211/sta_info.c b/net/d80211/sta_info.c
index bba4771..9c6adaa 100644
--- a/net/d80211/sta_info.c
+++ b/net/d80211/sta_info.c
@@ -102,7 +102,7 @@ int sta_info_min_txrate_get(struct ieee8
 }
 
 
-void sta_info_put(struct ieee80211_local *local, struct sta_info *sta)
+void sta_info_put(struct sta_info *sta)
 {
 	kobject_put(&sta->kobj);
 }
@@ -200,13 +200,13 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 	ieee80211_proc_deinit_sta(local, sta);
 	ieee80211_sta_sysfs_remove(sta);
 
-	sta_info_put(local, sta);
+	sta_info_put(sta);
 }
 
-void sta_info_free(struct ieee80211_local *local, struct sta_info *sta,
-		   int locked)
+void sta_info_free(struct sta_info *sta, int locked)
 {
 	struct sk_buff *skb;
+	struct ieee80211_local *local = sta->local;
 	struct ieee80211_sub_if_data *sdata;
 
 	if (!locked)
@@ -320,7 +320,7 @@ static void sta_info_cleanup(unsigned lo
 		struct sta_info *sta = (struct sta_info *) ptr;
 		__sta_info_get(sta);
 		sta_info_cleanup_expire_buffered(local, sta);
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 		ptr = ptr->next;
 	}
 	spin_unlock_bh(&local->sta_lock);
@@ -368,7 +368,7 @@ static void sta_info_proc_add_task(void 
 		sta->sysfs_registered = 1;
 		ieee80211_sta_sysfs_add(sta);
 		ieee80211_proc_init_sta(local, sta);
-		sta_info_put(local, sta);
+		sta_info_put(sta);
 	}
 }
 
@@ -412,7 +412,7 @@ void sta_info_stop(struct ieee80211_loca
 		 * parameter to ensure all sysfs sta entries are
 		 * unregistered. We don't need locking at this
 		 * point. */
-		sta_info_free(local, sta, 0);
+		sta_info_free(sta, 0);
 	}
 	ieee80211_sta_kset_sysfs_unregister(local);
 }
@@ -449,7 +449,7 @@ void sta_info_flush(struct ieee80211_loc
 	list_for_each_safe(ptr, n, &local->sta_list) {
 		struct sta_info *sta = list_entry(ptr, struct sta_info, list);
 		if (dev == NULL || dev == sta->dev)
-			sta_info_free(local, sta, 1);
+			sta_info_free(sta, 1);
 	}
 	spin_unlock_bh(&local->sta_lock);
 }
diff --git a/net/d80211/sta_info.h b/net/d80211/sta_info.h
index ddfe50e..70334e5 100644
--- a/net/d80211/sta_info.h
+++ b/net/d80211/sta_info.h
@@ -134,11 +134,10 @@ #define STA_INFO_CLEANUP_INTERVAL (10 * 
 
 struct sta_info * sta_info_get(struct ieee80211_local *local, u8 *addr);
 int sta_info_min_txrate_get(struct ieee80211_local *local);
-void sta_info_put(struct ieee80211_local *local, struct sta_info *sta);
+void sta_info_put(struct sta_info *sta);
 struct sta_info * sta_info_add(struct ieee80211_local *local,
 			       struct net_device *dev, u8 *addr);
-void sta_info_free(struct ieee80211_local *local, struct sta_info *sta,
-		   int locked);
+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);
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 10/12] d80211: rate_control sysfs attributes
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
                   ` (8 preceding siblings ...)
  2006-06-08  7:49 ` [PATCH 9/12] d80211: remove useless parameters Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 11/12] d80211: encryption keys " Jiri Benc
  2006-06-08  7:49 ` [PATCH 12/12] d80211: remove procfs files Jiri Benc
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Add support for sysfs attributes for rate_control modules.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c    |   13 ++++++++++++-
 net/d80211/rate_control.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 net/d80211/rate_control.h |   36 ++++++++++++++++++++++++++++++++++++
 net/d80211/sta_info.c     |    4 ++++
 4 files changed, 94 insertions(+), 1 deletions(-)

9acfab1d1a4e4a82dace4055a089d605d5efa97f
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 75aaa99..e4ac701 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -4215,6 +4215,13 @@ int ieee80211_register_hw(struct net_dev
 		       "algorithm\n", dev->name);
 		goto fail_rate;
 	}
+	result = rate_control_add_attrs(local, local->rate_ctrl_priv,
+					&local->class_dev.kobj);
+	if (result < 0) {
+		printk(KERN_DEBUG "%s: Failed to register sysfs attributes "
+		       "for rate control\n", dev->name);
+		goto fail_rate_attrs;
+	}
 
 	/* TODO: add rtnl locking around device creation and qdisc install */
 	ieee80211_install_qdisc(dev);
@@ -4233,6 +4240,8 @@ int ieee80211_register_hw(struct net_dev
 
 	return 0;
 
+fail_rate_attrs:
+	rate_control_free(local);
 fail_rate:
 	ieee80211_sysfs_remove_netdevice(dev);
 fail_if_sysfs:
@@ -4308,6 +4317,8 @@ void ieee80211_unregister_hw(struct net_
 	rtnl_unlock();
 
 	sta_info_stop(local);
+	rate_control_remove_attrs(local, local->rate_ctrl_priv,
+				  &local->class_dev.kobj);
 	ieee80211_dev_sysfs_del(local);
 
 	for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
@@ -4327,7 +4338,6 @@ void ieee80211_unregister_hw(struct net_
 	skb_queue_purge(&local->skb_queue);
 	skb_queue_purge(&local->skb_queue_unreliable);
 
-	rate_control_free(local);
 	ieee80211_dev_free_index(local);
 }
 
@@ -4341,6 +4351,7 @@ void ieee80211_free_hw(struct net_device
 
 void ieee80211_release_hw(struct ieee80211_local *local)
 {
+	rate_control_free(local);
 	kfree(local);
 }
 
diff --git a/net/d80211/rate_control.c b/net/d80211/rate_control.c
index e7e6791..33ba8e2 100644
--- a/net/d80211/rate_control.c
+++ b/net/d80211/rate_control.c
@@ -350,6 +350,46 @@ static int rate_control_simple_status_gl
 	return 0;
 }
 
+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;
+
+	return sprintf(buf, "%d\n", srctrl->tx_avg_rate_sum);
+}
+
+static ssize_t show_sta_tx_avg_rate_num(const struct sta_info *sta, char *buf)
+{
+	struct sta_rate_control *srctrl = sta->rate_ctrl_priv;
+
+	return sprintf(buf, "%d\n", srctrl->tx_avg_rate_num);
+}
+
+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 struct attribute_group rate_control_simple_sta_group = {
+	.name = "rate_control_simple",
+	.attrs = rate_control_simple_sta_attrs,
+};
+
+static int rate_control_simple_add_sta_attrs(void *priv, struct kobject *kobj)
+{
+	return sysfs_create_group(kobj, &rate_control_simple_sta_group);
+}
+
+static void rate_control_simple_remove_sta_attrs(void *priv,
+						 struct kobject *kobj)
+{
+	sysfs_remove_group(kobj, &rate_control_simple_sta_group);
+}
 
 static struct rate_control_ops rate_control_simple = {
 	.name = "simple",
@@ -363,6 +403,8 @@ 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,
 };
 
 
diff --git a/net/d80211/rate_control.h b/net/d80211/rate_control.h
index b509539..7705fb2 100644
--- a/net/d80211/rate_control.h
+++ b/net/d80211/rate_control.h
@@ -53,6 +53,11 @@ struct rate_control_ops {
 	void (*free)(void *priv);
 	void * (*alloc_sta)(void);
 	void (*free_sta)(void *priv);
+
+	int (*add_attrs)(void *priv, struct kobject *kobj);
+	void (*remove_attrs)(void *priv, struct kobject *kobj);
+	int (*add_sta_attrs)(void *priv, struct kobject *kobj);
+	void (*remove_sta_attrs)(void *priv, struct kobject *kobj);
 };
 
 
@@ -132,4 +137,35 @@ static inline void rate_control_free_sta
 	local->rate_ctrl->free_sta(priv);
 }
 
+static inline int rate_control_add_attrs(struct ieee80211_local *local,
+					 void *priv, struct kobject *kobj)
+{
+	if (local->rate_ctrl->add_attrs)
+		return local->rate_ctrl->add_attrs(priv, kobj);
+	return 0;
+}
+
+static inline void rate_control_remove_attrs(struct ieee80211_local *local,
+					     void *priv, struct kobject *kobj)
+{
+	if (local->rate_ctrl->remove_attrs)
+		local->rate_ctrl->remove_attrs(priv, kobj);
+}
+
+static inline int rate_control_add_sta_attrs(struct ieee80211_local *local,
+					     void *priv, struct kobject *kobj)
+{
+	if (local->rate_ctrl->add_sta_attrs)
+		return local->rate_ctrl->add_sta_attrs(priv, kobj);
+	return 0;
+}
+
+static inline void rate_control_remove_sta_attrs(struct ieee80211_local *local,
+						 void *priv,
+						 struct kobject *kobj)
+{
+	if (local->rate_ctrl->remove_sta_attrs)
+		local->rate_ctrl->remove_sta_attrs(priv, kobj);
+}
+
 #endif /* RATE_CONTROL */
diff --git a/net/d80211/sta_info.c b/net/d80211/sta_info.c
index 9c6adaa..96e8dc4 100644
--- a/net/d80211/sta_info.c
+++ b/net/d80211/sta_info.c
@@ -178,6 +178,8 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 	if (!in_interrupt()) {
 		sta->sysfs_registered = 1;
 		ieee80211_sta_sysfs_add(sta);
+		rate_control_add_sta_attrs(local, sta->rate_ctrl_priv,
+					   &sta->kobj);
 		ieee80211_proc_init_sta(local, sta);
 	} else {
 		/* procfs entry adding might sleep, so schedule process context
@@ -197,6 +199,7 @@ #ifdef CONFIG_D80211_VERBOSE_DEBUG
 	       local->mdev->name, MAC2STR(sta->addr));
 #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
+	rate_control_remove_sta_attrs(local, sta->rate_ctrl_priv, &sta->kobj);
 	ieee80211_proc_deinit_sta(local, sta);
 	ieee80211_sta_sysfs_remove(sta);
 
@@ -367,6 +370,7 @@ static void sta_info_proc_add_task(void 
 
 		sta->sysfs_registered = 1;
 		ieee80211_sta_sysfs_add(sta);
+		rate_control_add_sta_attrs(local, sta->rate_ctrl_priv, &sta->kobj);
 		ieee80211_proc_init_sta(local, sta);
 		sta_info_put(sta);
 	}
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 11/12] d80211: encryption keys sysfs attributes
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
                   ` (9 preceding siblings ...)
  2006-06-08  7:49 ` [PATCH 10/12] d80211: rate_control sysfs attributes Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  2006-06-08  7:49 ` [PATCH 12/12] d80211: remove procfs files Jiri Benc
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Add /sys/class/ieee80211/phyX/sta/*/key/* and /sys/class/net/X/keys/[0-3]/*
attributes.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/ieee80211.c           |   33 ++++++
 net/d80211/ieee80211_i.h         |   11 ++
 net/d80211/ieee80211_ioctl.c     |  101 ++++++++++++-------
 net/d80211/ieee80211_key.h       |    2 
 net/d80211/ieee80211_sysfs.c     |   12 ++
 net/d80211/ieee80211_sysfs_sta.c |  206 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 326 insertions(+), 39 deletions(-)

9b2e2e2cc66e7fb3f1ae07d7e083ffa63dffbde7
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index e4ac701..1a03f07 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -84,15 +84,44 @@ ieee80211_key_data2conf(struct ieee80211
 	return conf;
 }
 
+struct ieee80211_key *ieee80211_key_alloc(struct ieee80211_sub_if_data *sdata,
+					  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);
+	return key;
+}
 
 void ieee80211_key_free(struct ieee80211_key *key)
 {
-	if (key && key->alg == ALG_CCMP)
+	if (key)
+		kobject_put(&key->kobj);
+}
+
+void ieee80211_key_release(struct kobject *kobj)
+{
+	struct ieee80211_key *key;
+
+	key = container_of(kobj, struct ieee80211_key, kobj);
+	if (key->alg == ALG_CCMP)
 		ieee80211_aes_key_free(key->u.ccmp.tfm);
 	kfree(key);
 }
 
-
 static int rate_list_match(int *rate_list, int rate)
 {
 	int i;
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 212d12f..c1d7422 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -294,6 +294,7 @@ 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 */
 
@@ -527,7 +528,10 @@ int ieee80211_if_config(struct net_devic
 struct ieee80211_key_conf *
 ieee80211_key_data2conf(struct ieee80211_local *local,
 			struct ieee80211_key *data);
+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 net_device *dev, struct sk_buff *skb,
 		       struct ieee80211_rx_status *status, u32 msg_type);
 void ieee80211_prepare_rates(struct net_device *dev);
@@ -633,5 +637,12 @@ int ieee80211_sta_kset_sysfs_register(st
 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/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index 562b9f3..7c2a847 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -470,7 +470,7 @@ static int ieee80211_set_encryption(stru
 	struct ieee80211_local *local = dev->ieee80211_ptr;
 	int ret = 0;
 	struct sta_info *sta;
-	struct ieee80211_key **key;
+	struct ieee80211_key *key, *old_key;
 	int try_hwaccel = 1;
         struct ieee80211_key_conf *keyconf;
         struct ieee80211_sub_if_data *sdata;
@@ -486,7 +486,7 @@ static int ieee80211_set_encryption(stru
 			       dev->name, idx);
 			return -EINVAL;
 		}
-		key = &sdata->keys[idx];
+		key = sdata->keys[idx];
 
 		/* Disable hwaccel for default keys when the interface is not
 		 * the default one.
@@ -525,7 +525,7 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 			return -ENOENT;
 		}
 
-		key = &sta->key;
+		key = sta->key;
 	}
 
 	/* FIX:
@@ -571,8 +571,8 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
 	if (alg == ALG_NONE) {
 		keyconf = NULL;
-		if (try_hwaccel && *key && local->hw->set_key &&
-		    (keyconf = ieee80211_key_data2conf(local, *key)) != NULL &&
+		if (try_hwaccel && key && local->hw->set_key &&
+		    (keyconf = ieee80211_key_data2conf(local, key)) != NULL &&
 		    local->hw->set_key(dev, DISABLE_KEY, sta_addr,
 				       keyconf, sta ? sta->aid : 0)) {
 			if (err)
@@ -583,68 +583,101 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 		}
 		kfree(keyconf);
 
-		if (sdata->default_key == *key)
+		if (key && sdata->default_key == key) {
+			ieee80211_key_sysfs_remove_default(sdata);
 			sdata->default_key = NULL;
-		ieee80211_key_free(*key);
-		*key = NULL;
+		}
+		ieee80211_key_sysfs_remove(key);
+		if (sta)
+			sta->key = NULL;
+		else
+			sdata->keys[idx] = NULL;
+		ieee80211_key_free(key);
+		key = NULL;
 	} else {
-		if (*key == NULL || (*key)->keylen < key_len) {
-			ieee80211_key_free(*key);
-			*key = kmalloc(sizeof(struct ieee80211_key) +
-				       key_len, GFP_ATOMIC);
-			if (*key == NULL) {
-				ret = -ENOMEM;
-				goto done;
-			}
+		old_key = key;
+		key = ieee80211_key_alloc(sta ? NULL : sdata, idx, key_len,
+					  GFP_KERNEL);
+		if (!key) {
+			ret = -ENOMEM;
+			goto err_out;
 		}
-		memset(*key, 0, sizeof(struct ieee80211_key) + key_len);
+
 		/* default to sw encryption; low-level driver sets these if the
 		 * requested encryption is supported */
-		(*key)->hw_key_idx = HW_KEY_IDX_INVALID;
-		(*key)->force_sw_encrypt = 1;
+		key->hw_key_idx = HW_KEY_IDX_INVALID;
+		key->force_sw_encrypt = 1;
 
-		(*key)->alg = alg;
-		(*key)->keyidx = idx;
-		(*key)->keylen = key_len;
-		memcpy((*key)->key, _key, key_len);
+		key->alg = alg;
+		key->keyidx = idx;
+		key->keylen = key_len;
+		memcpy(key->key, _key, key_len);
 		if (set_tx_key)
-			(*key)->default_tx_key = 1;
+			key->default_tx_key = 1;
 
 		if (alg == ALG_CCMP) {
 			/* Initialize AES key state here as an optimization
 			 * so that it does not need to be initialized for every
 			 * packet. */
-			(*key)->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
-				(*key)->key);
-			if ((*key)->u.ccmp.tfm == NULL) {
-				kfree(*key);
-				*key = NULL;
+			key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(
+				key->key);
+			if (key->u.ccmp.tfm == NULL) {
 				ret = -ENOMEM;
-				goto done;
+				goto err_free;
 			}
 		}
 
+		if (old_key && sdata->default_key == old_key) {
+			ieee80211_key_sysfs_remove_default(sdata);
+			sdata->default_key = NULL;
+		}
+		ieee80211_key_sysfs_remove(old_key);
+		if (sta)
+			sta->key = key;
+		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;
+
 		if (try_hwaccel &&
 		    (alg == ALG_WEP || alg == ALG_TKIP || alg == ALG_CCMP)) {
 			int e = ieee80211_set_hw_encryption(dev, sta, sta_addr,
-							    *key);
+							    key);
 			if (err)
 				*err = e;
 		}
 	}
 
-	if (set_tx_key || (sta == NULL && sdata->default_key == NULL)) {
-                sdata->default_key = *key;
+	if (set_tx_key || (sta == NULL && sdata->default_key == NULL && key)) {
+		sdata->default_key = key;
+		if (ieee80211_key_sysfs_add_default(sdata))
+			printk(KERN_WARNING "%s: cannot create symlink to "
+			       "default key\n", dev->name);
 		if (local->hw->set_key_idx &&
 		    local->hw->set_key_idx(dev, idx))
 			printk(KERN_DEBUG "%s: failed to set TX key idx for "
 			       "low-level driver\n", dev->name);
 	}
 
- done:
 	if (sta)
 		sta_info_put(sta);
 
+	return 0;
+
+err_null:
+	if (sta)
+		sta->key = NULL;
+	else
+		sdata->keys[idx] = NULL;
+err_free:
+	ieee80211_key_free(key);
+err_out:
+	if (sta)
+		sta_info_put(sta);
 	return ret;
 }
 
diff --git a/net/d80211/ieee80211_key.h b/net/d80211/ieee80211_key.h
index 4c688cd..64f2363 100644
--- a/net/d80211/ieee80211_key.h
+++ b/net/d80211/ieee80211_key.h
@@ -40,6 +40,8 @@ #define CCMP_PN_LEN 6
 #define NUM_RX_DATA_QUEUES 17
 
 struct ieee80211_key {
+	struct kobject kobj;
+
 	int hw_key_idx; /* filled and used by low-level driver */
 	ieee80211_key_alg alg;
 	union {
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index 12d16fd..10bf45c 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -709,16 +709,22 @@ int ieee80211_sysfs_add_netdevice(struct
 	res = sysfs_create_link(&dev->class_dev.kobj, &local->class_dev.kobj,
 				"wiphy");
 	if (res)
-		goto out;
+		goto err_out;
 	res = ieee80211_add_if_group(&dev->class_dev.kobj, dev);
 	if (res)
-		sysfs_remove_link(&dev->class_dev.kobj, "wiphy");
-out:
+		goto err_link;
+	res = ieee80211_key_kset_sysfs_register(IEEE80211_DEV_TO_SUB_IF(dev));
+	return res;
+
+err_link:
+	sysfs_remove_link(&dev->class_dev.kobj, "wiphy");
+err_out:
 	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->class_dev.kobj, dev);
 	sysfs_remove_link(&dev->class_dev.kobj, "wiphy");
 }
diff --git a/net/d80211/ieee80211_sysfs_sta.c b/net/d80211/ieee80211_sysfs_sta.c
index 07de564..94c6dd8 100644
--- a/net/d80211/ieee80211_sysfs_sta.c
+++ b/net/d80211/ieee80211_sysfs_sta.c
@@ -10,14 +10,22 @@
 #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)	\
 {									\
@@ -183,12 +191,153 @@ #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)
 {
@@ -200,6 +349,17 @@ static ssize_t sta_sysfs_show(struct kob
 	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;
@@ -217,6 +377,23 @@ void ieee80211_sta_kset_sysfs_unregister
 	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->class_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);
@@ -226,3 +403,32 @@ void ieee80211_sta_sysfs_remove(struct s
 {
 	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)
+{
+	sysfs_remove_link(&sdata->key_kset.kobj, "default");
+}
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 12/12] d80211: remove procfs files
  2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
                   ` (10 preceding siblings ...)
  2006-06-08  7:49 ` [PATCH 11/12] d80211: encryption keys " Jiri Benc
@ 2006-06-08  7:49 ` Jiri Benc
  11 siblings, 0 replies; 15+ messages in thread
From: Jiri Benc @ 2006-06-08  7:49 UTC (permalink / raw)
  To: netdev; +Cc: John W. Linville

Remove procfs support.

Signed-off-by: Jiri Benc <jbenc@suse.cz>

---

 net/d80211/Makefile          |    1 
 net/d80211/ieee80211.c       |    7 
 net/d80211/ieee80211_iface.c |    3 
 net/d80211/ieee80211_proc.c  |  768 ------------------------------------------
 net/d80211/ieee80211_proc.h  |   48 ---
 net/d80211/ieee80211_sysfs.c |   33 ++
 net/d80211/rate_control.c    |   25 -
 net/d80211/rate_control.h    |   17 -
 net/d80211/sta_info.c        |    4 
 9 files changed, 32 insertions(+), 874 deletions(-)
 delete mode 100644 net/d80211/ieee80211_proc.c
 delete mode 100644 net/d80211/ieee80211_proc.h

89c13fc02b12796d1f57c33c7fae1bcf875d846b
diff --git a/net/d80211/Makefile b/net/d80211/Makefile
index 7d1ec29..c21e882 100644
--- a/net/d80211/Makefile
+++ b/net/d80211/Makefile
@@ -6,7 +6,6 @@ obj-$(CONFIG_D80211) += 80211.o rate_con
 	sta_info.o \
 	wep.o \
 	wpa.o \
-	ieee80211_proc.o \
 	ieee80211_scan.o \
 	ieee80211_sta.o \
 	ieee80211_dev.o \
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 1a03f07..a8ca8d1 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -25,7 +25,6 @@ #include <net/d80211.h>
 #include <net/d80211_common.h>
 #include <net/d80211_mgmt.h>
 #include "ieee80211_i.h"
-#include "ieee80211_proc.h"
 #include "rate_control.h"
 #include "wep.h"
 #include "wpa.h"
@@ -4256,7 +4255,6 @@ int ieee80211_register_hw(struct net_dev
 	ieee80211_install_qdisc(dev);
 
         ieee80211_wep_init(local);
-	ieee80211_proc_init_interface(local);
 
 	/* add one default STA interface */
 	rtnl_lock();
@@ -4359,8 +4357,6 @@ void ieee80211_unregister_hw(struct net_
 		kfree(local->basic_rates[i]);
         }
 
-	ieee80211_proc_deinit_interface(local);
-
 	if (skb_queue_len(&local->skb_queue)
 			|| skb_queue_len(&local->skb_queue_unreliable))
 		printk(KERN_WARNING "%s: skb_queue not empty", dev->name);
@@ -4520,14 +4516,12 @@ static int __init ieee80211_init(void)
 		return ret;
 	}
 
-	ieee80211_proc_init();
 	{
 		ret = ieee80211_wme_register();
 		if (ret) {
 			printk(KERN_DEBUG "ieee80211_init: failed to "
 			       "initialize WME (err=%d)\n", ret);
 			ieee80211_sysfs_deinit();
-			ieee80211_proc_deinit();
 			return ret;
 		}
 	}
@@ -4539,7 +4533,6 @@ static int __init ieee80211_init(void)
 static void __exit ieee80211_exit(void)
 {
 	ieee80211_wme_unregister();
-	ieee80211_proc_deinit();
 	ieee80211_sysfs_deinit();
 }
 
diff --git a/net/d80211/ieee80211_iface.c b/net/d80211/ieee80211_iface.c
index 960a90e..5abd713 100644
--- a/net/d80211/ieee80211_iface.c
+++ b/net/d80211/ieee80211_iface.c
@@ -14,7 +14,6 @@ #include <linux/rtnetlink.h>
 #include <net/d80211.h>
 #include <net/d80211_mgmt.h>
 #include "ieee80211_i.h"
-#include "ieee80211_proc.h"
 #include "sta_info.h"
 
 void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
@@ -85,7 +84,6 @@ int ieee80211_if_add(struct net_device *
 	}
 
 	list_add(&sdata->list, &local->sub_if_list);
-	ieee80211_proc_init_virtual(ndev);
 
 	return 0;
 
@@ -307,7 +305,6 @@ void __ieee80211_if_del(struct ieee80211
 
 	ieee80211_if_reinit(dev);
 	list_del(&sdata->list);
-	ieee80211_proc_deinit_virtual(dev);
 	ieee80211_sysfs_remove_netdevice(dev);
 	unregister_netdevice(dev);
 	/* Except master interface, the net_device will be freed by
diff --git a/net/d80211/ieee80211_proc.c b/net/d80211/ieee80211_proc.c
deleted file mode 100644
index 4bb3179..0000000
--- a/net/d80211/ieee80211_proc.c
+++ /dev/null
@@ -1,768 +0,0 @@
-/*
- * Copyright 2003-2005, Devicescape Software, Inc.
- *
- * 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/config.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/delay.h>
-
-#ifdef CONFIG_PROC_FS
-
-#include <net/d80211.h>
-#include <net/d80211_common.h>
-#include <net/d80211_mgmt.h>
-#include "ieee80211_i.h"
-#include "sta_info.h"
-#include "ieee80211_proc.h"
-#include "rate_control.h"
-
-
-static struct proc_dir_entry *ieee80211_proc;
-
-#define PROC_LIMIT (PAGE_SIZE - 80)
-
-
-static char * ieee80211_proc_key(char *p, struct ieee80211_key *key,
-				 int idx, int def_key)
-{
-	int i;
-	u8 *tpn, *rpn;
-
-	if (!key)
-		return p;
-
-	p += sprintf(p, "key[%d]%s len=%d sw_encrypt=%d idx=%d hwidx=%d "
-		     "tx_rx_count=%d",
-		     idx, def_key ? "*" : "", key->keylen,
-		     key->force_sw_encrypt, key->keyidx, key->hw_key_idx,
-		     key->tx_rx_count);
-	switch (key->alg) {
-	case ALG_WEP:
-		p += sprintf(p, " alg=WEP");
-		break;
-	case ALG_TKIP:
-		p += sprintf(p, " alg=TKIP iv(tx)=%08x %04x",
-			     key->u.tkip.iv32, key->u.tkip.iv16);
-		for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
-			if (key->u.tkip.iv32_rx[i] == 0 &&
-			    key->u.tkip.iv16_rx[i] == 0)
-				continue;
-			p += sprintf(p, " iv(rx %d)=%08x %04x", i,
-				     key->u.tkip.iv32_rx[i],
-				     key->u.tkip.iv16_rx[i]);
-		}
-		break;
-	case ALG_CCMP:
-		tpn = key->u.ccmp.tx_pn;
-		p += sprintf(p, " alg=CCMP PN(tx)=%02x%02x%02x%02x%02x%02x",
-			     tpn[0], tpn[1], tpn[2], tpn[3], tpn[4], tpn[5]);
-		for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
-			rpn = key->u.ccmp.rx_pn[i];
-			if (memcmp(rpn, "\x00\x00\x00\x00\x00\x00", 6) == 0)
-				continue;
-			p += sprintf(p, " PN(rx %d)=%02x%02x%02x%02x%02x%02x",
-				     i, rpn[0], rpn[1], rpn[2], rpn[3], rpn[4],
-				     rpn[5]);
-		}
-		p += sprintf(p, " replays=%u", key->u.ccmp.replays);
-		break;
-	default:
-		break;
-	}
-
-	p += sprintf(p, " key=");
-	for (i = 0; i < key->keylen; i++)
-		p += sprintf(p, "%02x", key->key[i]);
-	p += sprintf(p, "\n");
-	return p;
-}
-
-
-static char * ieee80211_proc_sub_if_ap(char *p,
-				       struct ieee80211_if_ap *ap)
-{
-	p += sprintf(p, "type=ap\n");
-	if (ap->beacon_head)
-		p += sprintf(p, "beacon_head_len=%d\n", ap->beacon_head_len);
-	if (ap->beacon_tail)
-		p += sprintf(p, "beacon_tail_len=%d\n", ap->beacon_tail_len);
-	p += sprintf(p,
-		     "max_aid=%d\n"
-		     "num_sta_ps=%d\n"
-		     "num_buffered_multicast=%u\n"
-		     "dtim_period=%d\n"
-		     "dtim_count=%d\n"
-		     "num_beacons=%d\n"
-		     "force_unicast_rateidx=%d\n"
-		     "max_ratectrl_rateidx=%d\n",
-		     ap->max_aid, atomic_read(&ap->num_sta_ps),
-		     skb_queue_len(&ap->ps_bc_buf),
-		     ap->dtim_period, ap->dtim_count, ap->num_beacons,
-		     ap->force_unicast_rateidx, ap->max_ratectrl_rateidx);
-	return p;
-}
-
-
-static char * ieee80211_proc_sub_if_sta(char *p, int ibss,
-					struct ieee80211_if_sta *ifsta)
-{
-	if (ibss)
-		p += sprintf(p, "type=ibss\n");
-	else
-		p += sprintf(p, "type=sta\n");
-	p += sprintf(p,
-		     "state=%d\n"
-		     "bssid=" MACSTR "\n"
-		     "prev_bssid=" MACSTR "\n"
-		     "ssid_len=%zd\n"
-		     "aid=%d\n"
-		     "ap_capab=0x%x\n"
-		     "capab=0x%x\n"
-		     "extra_ie_len=%zd\n"
-		     "auth_tries=%d\n"
-		     "assoc_tries=%d\n"
-		     "flags=%s%s%s%s%s%s%s\n"
-		     "auth_algs=0x%x\n"
-		     "auth_alg=%d\n"
-		     "auth_transaction=%d\n",
-		     ifsta->state,
-		     MAC2STR(ifsta->bssid),
-		     MAC2STR(ifsta->prev_bssid),
-		     ifsta->ssid_len,
-		     ifsta->aid,
-		     ifsta->ap_capab,
-		     ifsta->capab,
-		     ifsta->extra_ie_len,
-		     ifsta->auth_tries,
-		     ifsta->assoc_tries,
-		     ifsta->ssid_set ? "[SSID]" : "",
-		     ifsta->bssid_set ? "[BSSID]" : "",
-		     ifsta->prev_bssid_set ? "[prev BSSID" : "",
-		     ifsta->authenticated ? "[AUTH]" : "",
-		     ifsta->associated ? "[ASSOC]" : "",
-		     ifsta->probereq_poll ? "[PROBEREQ POLL]" : "",
-		     ifsta->use_protection ? "[CTS prot]" : "",
-		     ifsta->auth_algs,
-		     ifsta->auth_alg,
-		     ifsta->auth_transaction);
-	return p;
-}
-
-
-static char * ieee80211_proc_sub_if(char *p,
-				    struct ieee80211_sub_if_data *sdata)
-{
-	if (sdata == NULL)
-		return p;
-
-	if (sdata->bss)
-		p += sprintf(p, "bss=%p\n", sdata->bss);
-
-	switch (sdata->type) {
-	case IEEE80211_IF_TYPE_AP:
-		p = ieee80211_proc_sub_if_ap(p, &sdata->u.ap);
-		break;
-	case IEEE80211_IF_TYPE_WDS:
-		p += sprintf(p, "type=wds\n");
-		p += sprintf(p, "wds.peer=" MACSTR "\n",
-			     MAC2STR(sdata->u.wds.remote_addr));
-		break;
-	case IEEE80211_IF_TYPE_VLAN:
-		p += sprintf(p, "type=vlan\n");
-		p += sprintf(p, "vlan.id=%d\n", sdata->u.vlan.id);
-		break;
-	case IEEE80211_IF_TYPE_STA:
-		p = ieee80211_proc_sub_if_sta(p, 0, &sdata->u.sta);
-		break;
-	case IEEE80211_IF_TYPE_IBSS:
-		p = ieee80211_proc_sub_if_sta(p, 1, &sdata->u.sta);
-		break;
-	}
-	p += sprintf(p, "channel_use=%d\n", sdata->channel_use);
-	p += sprintf(p, "drop_unencrypted=%d\n", sdata->drop_unencrypted);
-	p += sprintf(p, "eapol=%d\n", sdata->eapol);
-	p += sprintf(p, "ieee802_1x=%d\n", sdata->ieee802_1x);
-
-	return p;
-}
-
-
-static int ieee80211_proc_iface_read(char *page, char **start, off_t off,
-				     int count, int *eof, void *data)
-{
-	char *p = page;
-	struct net_device *dev = (struct net_device *) data;
-	struct ieee80211_sub_if_data *sdata;
-	int i;
-
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (!sdata)
-		return -1;
-
-        p = ieee80211_proc_sub_if(p, sdata);
-
-	for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-		if (sdata->keys[i] == NULL)
-			continue;
-
-		p = ieee80211_proc_key(p, sdata->keys[i], i,
-				       sdata->keys[i] == sdata->default_key);
-	}
-
-	return (p - page);
-}
-
-
-static int ieee80211_proc_sta_read(char *page, char **start, off_t off,
-				   int count, int *eof, void *data)
-{
-	char *p = page;
-	struct sta_info *sta = (struct sta_info *) data;
-	struct ieee80211_local *local;
-	int inactive, i;
-
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	if (!sta || !sta->dev)
-		return -1;
-
-	p += sprintf(p, "aid=%d\n", sta->aid);
-	p += sprintf(p, "flags=0x%x %s%s%s%s%s%s%s%s%s%s\n", sta->flags,
-		     sta->flags & WLAN_STA_AUTH ? "[AUTH]" : "",
-		     sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : "",
-		     sta->flags & WLAN_STA_PS ? "[PS]" : "",
-		     sta->flags & WLAN_STA_TIM ? "[TIM]" : "",
-		     sta->flags & WLAN_STA_PERM ? "[PERM]" : "",
-		     sta->flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : "",
-		     sta->flags & WLAN_STA_SHORT_PREAMBLE ?
-		     "[SHORT PREAMBLE]" : "",
-		     sta->flags & WLAN_STA_WME ? "[WME]" : "",
-		     sta->flags & WLAN_STA_WDS ? "[WDS]" : "",
-		     sta->flags & WLAN_STA_XR ? "[XR]" : "");
-	p += sprintf(p, "key_idx_compression=%d\n",
-		     sta->key_idx_compression);
-	p += sprintf(p, "dev=%s\n", sta->dev->name);
-	if (sta->vlan_id > 0)
-		p += sprintf(p, "vlan_id=%d\n", sta->vlan_id);
-	p += sprintf(p, "rx_packets=%lu\ntx_packets=%lu\nrx_bytes=%lu\n"
-		     "tx_bytes=%lu\nrx_duplicates=%lu\nrx_fragments=%lu\n"
-		     "rx_dropped=%lu\ntx_fragments=%lu\ntx_filtered=%lu\n",
-		     sta->rx_packets, sta->tx_packets,
-		     sta->rx_bytes, sta->tx_bytes,
-		     sta->num_duplicates, sta->rx_fragments, sta->rx_dropped,
-		     sta->tx_fragments, sta->tx_filtered_count);
-	p = ieee80211_proc_key(p, sta->key, 0, 1);
-
-	local = (struct ieee80211_local *) sta->dev->ieee80211_ptr;
-	if (sta->txrate >= 0 && sta->txrate < local->num_curr_rates) {
-		p += sprintf(p, "txrate=%d\n",
-			     local->curr_rates[sta->txrate].rate);
-	}
-	if (sta->last_txrate >= 0 &&
-	    sta->last_txrate < local->num_curr_rates) {
-		p += sprintf(p, "last_txrate=%d\n",
-			     local->curr_rates[sta->last_txrate].rate);
-	}
-	p += sprintf(p, "num_ps_buf_frames=%u\n",
-		     skb_queue_len(&sta->ps_tx_buf));
-	p += sprintf(p, "tx_retry_failed=%lu\n", sta->tx_retry_failed);
-	p += sprintf(p, "tx_retry_count=%lu\n", sta->tx_retry_count);
-	p += sprintf(p, "last_rssi=%d\n", sta->last_rssi);
-	p += sprintf(p, "last_ack_rssi=%d %d %d\n",
-		     sta->last_ack_rssi[0], sta->last_ack_rssi[1],
-		     sta->last_ack_rssi[2]);
-	if (sta->last_ack)
-		p += sprintf(p, "last_ack_ms=%d\n",
-			     jiffies_to_msecs(jiffies - sta->last_ack));
-	inactive = jiffies - sta->last_rx;
-	p += sprintf(p, "inactive_msec=%d\n", jiffies_to_msecs(inactive));
-	p += sprintf(p, "channel_use=%d\n", sta->channel_use);
-	p += sprintf(p, "wep_weak_iv_count=%d\n", sta->wep_weak_iv_count);
-#ifdef CONFIG_D80211_DEBUG_COUNTERS
-	p += sprintf(p, "wme_rx_queue=");
-	for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
-		p += sprintf(p, "%u ", sta->wme_rx_queue[i]);
-	p += sprintf(p, "\n");
-
-	p += sprintf(p, "wme_tx_queue=");
-	for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
-		p += sprintf(p, "%u ", sta->wme_tx_queue[i]);
-	p += sprintf(p, "\n");
-#endif /* CONFIG_D80211_DEBUG_COUNTERS */
-	p += sprintf(p, "last_seq_ctrl=");
-	for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
-			p += sprintf(p, "%x ", sta->last_seq_ctrl[i]);
-	}
-	p += sprintf(p, "\n");
-
-	p += rate_control_status_sta(local, sta, p);
-
-	return (p - page);
-}
-
-
-static int ieee80211_proc_counters_read(char *page, char **start, off_t off,
-					int count, int *eof, void *data)
-{
-	char *p = page;
-	struct ieee80211_local *local = (struct ieee80211_local *) data;
-        struct ieee80211_low_level_stats stats;
-
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	p += sprintf(p,
-		     "TransmittedFragmentCount=%u\n"
-		     "MulticastTransmittedFrameCount=%u\n"
-		     "FailedCount=%u\n"
-		     "RetryCount=%u\n"
-		     "MultipleRetryCount=%d\n"
-		     "FrameDuplicateCount=%d\n"
-		     "ReceivedFragmentCount=%u\n"
-		     "MulticastReceivedFrameCount=%u\n"
-		     "TransmittedFrameCount=%u\n"
-		     "WEPUndecryptableCount=%u\n",
-		     local->dot11TransmittedFragmentCount,
-		     local->dot11MulticastTransmittedFrameCount,
-		     local->dot11FailedCount,
-		     local->dot11RetryCount,
-		     local->dot11MultipleRetryCount,
-		     local->dot11FrameDuplicateCount,
-		     local->dot11ReceivedFragmentCount,
-		     local->dot11MulticastReceivedFrameCount,
-		     local->dot11TransmittedFrameCount,
-		     local->dot11WEPUndecryptableCount);
-
-	memset(&stats, 0, sizeof(stats));
-	if (local->hw->get_stats &&
-	    local->hw->get_stats(local->mdev, &stats) == 0) {
-		p += sprintf(p,
-			     "ACKFailureCount=%u\n"
-			     "RTSFailureCount=%u\n"
-			     "FCSErrorCount=%u\n"
-			     "RTSSuccessCount=%u\n",
-			     stats.dot11ACKFailureCount,
-			     stats.dot11RTSFailureCount,
-			     stats.dot11FCSErrorCount,
-			     stats.dot11RTSSuccessCount);
-	}
-
-	return (p - page);
-}
-
-
-static int ieee80211_proc_debug_read(char *page, char **start, off_t off,
-				     int count, int *eof, void *data)
-{
-	char *p = page;
-	struct ieee80211_local *local = (struct ieee80211_local *) data;
-
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-#ifdef CONFIG_D80211_DEBUG_COUNTERS
-	p += sprintf(p,
-		     "tx_handlers_drop=%u\n"
-		     "tx_handlers_queued=%u\n"
-		     "tx_handlers_drop_unencrypted=%u\n"
-		     "tx_handlers_drop_fragment=%u\n"
-		     "tx_handlers_drop_wep=%u\n"
-		     "tx_handlers_drop_rate_limit=%u\n"
-		     "tx_handlers_drop_not_assoc=%u\n"
-		     "tx_handlers_drop_unauth_port=%u\n"
-		     "rx_handlers_drop=%u\n"
-		     "rx_handlers_queued=%u\n"
-		     "rx_handlers_drop_nullfunc=%u\n"
-		     "rx_handlers_drop_defrag=%u\n"
-		     "rx_handlers_drop_short=%u\n"
-		     "rx_handlers_drop_passive_scan=%u\n"
-		     "tx_expand_skb_head=%u\n"
-		     "tx_expand_skb_head_cloned=%u\n"
-		     "rx_expand_skb_head=%u\n"
-		     "rx_expand_skb_head2=%u\n"
-		     "rx_handlers_fragments=%u\n"
-		     "tx_status_drop=%u\n",
-		     local->tx_handlers_drop,
-		     local->tx_handlers_queued,
-		     local->tx_handlers_drop_unencrypted,
-		     local->tx_handlers_drop_fragment,
-		     local->tx_handlers_drop_wep,
-		     local->tx_handlers_drop_rate_limit,
-		     local->tx_handlers_drop_not_assoc,
-		     local->tx_handlers_drop_unauth_port,
-		     local->rx_handlers_drop,
-		     local->rx_handlers_queued,
-		     local->rx_handlers_drop_nullfunc,
-		     local->rx_handlers_drop_defrag,
-		     local->rx_handlers_drop_short,
-		     local->rx_handlers_drop_passive_scan,
-		     local->tx_expand_skb_head,
-		     local->tx_expand_skb_head_cloned,
-		     local->rx_expand_skb_head,
-		     local->rx_expand_skb_head2,
-		     local->rx_handlers_fragments,
-		     local->tx_status_drop);
-	{
-		int i;
-		p += sprintf(p, "wme_rx_queue=");
-		for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
-			p += sprintf(p, " %u", local->wme_rx_queue[i]);
-		p += sprintf(p, "\n");
-
-		p += sprintf(p, "wme_tx_queue=");
-		for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
-			p += sprintf(p, " %u", local->wme_tx_queue[i]);
-		p += sprintf(p, "\n");
-	}
-#endif /* CONFIG_D80211_DEBUG_COUNTERS */
-
-	p += sprintf(p, "num_scans=%u\n", local->scan.num_scans);
-
-	return (p - page);
-}
-
-
-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";
-	}
-}
-
-
-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 int ieee80211_proc_info_read(char *page, char **start, off_t off,
-				    int count, int *eof, void *data)
-{
-	char *p = page;
-	struct ieee80211_local *local = (struct ieee80211_local *) data;
-	int m;
-	struct ieee80211_hw_modes *mode;
-
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	p += sprintf(p, "hw_name=%s\n", local->hw->name);
-	p += sprintf(p, "modes=");
-	for (m = 0; m < local->hw->num_modes; m++) {
-		mode = &local->hw->modes[m];
-		p += sprintf(p, "[%s]", ieee80211_mode_str_short(mode->mode));
-	}
-	p += sprintf(p, "\n");
-	if (local->rate_ctrl && local->rate_ctrl_priv)
-		p+= sprintf(p, "rate_ctrl_alg=%s\n", local->rate_ctrl->name);
-	return (p - page);
-}
-
-
-static int ieee80211_proc_config_read(char *page, char **start, off_t off,
-				      int count, int *eof, void *data)
-{
-	char *p = page;
-	struct ieee80211_local *local = (struct ieee80211_local *) data;
-
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	p += sprintf(p,
-		     "low_level_driver=%s\n"
-		     "channel=%d\n"
-		     "freq=%d\n"
-		     "mode=%s\n"
-			 "802.11h=%d\n"
-		     "wep_iv=0x%06x\n"
-		     "antenna_sel=%d\n"
-		     "calib_int=%d\n"
-		     "tx_power_reduction=%d.%d dBm\n"
-		     "bridge_packets=%d\n"
-		     "key_tx_rx_threshold=%d\n"
-		     "rts_threshold=%d\n"
-		     "fragmentation_threshold=%d\n"
-		     "short_retry_limit=%d\n"
-		     "long_retry_limit=%d\n"
-		     "total_ps_buffered=%d\n",
-		     local->hw->name ? local->hw->name : "N/A",
-		     local->conf.channel,
-		     local->conf.freq,
-		     ieee80211_mode_str(local->conf.phymode),
-			 local->conf.radar_detect,
-		     local->wep_iv & 0xffffff,
-		     local->conf.antenna_sel,
-		     local->conf.calib_int,
-		     local->conf.tx_power_reduction / 10,
-		     local->conf.tx_power_reduction % 10,
-		     local->bridge_packets,
-		     local->key_tx_rx_threshold,
-		     local->rts_threshold,
-		     local->fragmentation_threshold,
-		     local->short_retry_limit,
-		     local->long_retry_limit,
-		     local->total_ps_buffered);
-
-	return (p - page);
-}
-
-
-static int ieee80211_proc_channels_read(char *page, char **start, off_t off,
-					int count, int *eof, void *data)
-{
-	char *p = page;
-	struct ieee80211_local *local = (struct ieee80211_local *) data;
-	int m, c;
-	struct ieee80211_hw_modes *mode;
-	struct ieee80211_channel *chan;
-
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	p += sprintf(p, "MODE CHAN FREQ TXPOWER ANTMAX FLAGS\n");
-	for (m = 0; m < local->hw->num_modes; m++) {
-		mode = &local->hw->modes[m];
-		for (c = 0; c < mode->num_channels; c++) {
-			chan = &mode->channels[c];
-			p += sprintf(p, "%d %d %d %d %d %s%s%s\n",
-				     mode->mode, chan->chan, chan->freq,
-				     chan->power_level, chan->antenna_max,
-				     chan->flag & IEEE80211_CHAN_W_SCAN ?
-				     "[W_SCAN]" : "",
-				     chan->flag & IEEE80211_CHAN_W_ACTIVE_SCAN
-				     ? "[W_ACTIVE_SCAN]" : "",
-				     chan->flag & IEEE80211_CHAN_W_IBSS ?
-				     "[W_IBSS]" : "");
-		}
-	}
-	return (p - page);
-}
-
-
-static int ieee80211_proc_rates_read(char *page, char **start, off_t off,
-				     int count, int *eof, void *data)
-{
-	char *p = page;
-	struct ieee80211_local *local = (struct ieee80211_local *) data;
-	int r;
-	struct ieee80211_rate *rate;
-
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	p += sprintf(p, "RATE VAL VAL2 MIN_RSSI_ACK MIN_RSSI_ACK_DELTA "
-		     "FLAGS\n");
-	for (r = 0; r < local->num_curr_rates; r++) {
-		rate = &local->curr_rates[r];
-		p += sprintf(p, "%d %d %d %d %d 0x%x %s%s%s%s%s%s%s%s\n",
-			     rate->rate, rate->val, rate->val2,
-			     rate->min_rssi_ack, rate->min_rssi_ack_delta,
-			     rate->flags,
-			     rate->flags & IEEE80211_RATE_ERP ? "[ERP]" : "",
-			     rate->flags & IEEE80211_RATE_BASIC ?
-			     "[BASIC]" : "",
-			     rate->flags & IEEE80211_RATE_PREAMBLE2 ?
-			     "[PREAMBLE2]" : "",
-			     rate->flags & IEEE80211_RATE_SUPPORTED ?
-			     "[SUPPORTED]" : "",
-			     rate->flags & IEEE80211_RATE_OFDM ? "[OFDM]" : "",
-			     rate->flags & IEEE80211_RATE_CCK ? "[CCK]" : "",
-			     rate->flags & IEEE80211_RATE_TURBO ?
-			     "[TURBO]" : "",
-			     rate->flags & IEEE80211_RATE_MANDATORY ?
-			     "[MANDATORY]" : "");
-	}
-	return (p - page);
-}
-
-
-static int ieee80211_proc_multicast_read(char *page, char **start, off_t off,
-					 int count, int *eof, void *data)
-{
-	char *p = page;
-	struct ieee80211_local *local = (struct ieee80211_local *) data;
-
-	if (off != 0) {
-		*eof = 1;
-		return 0;
-	}
-
-	return rate_control_status_global(local, p);
-
-}
-
-
-void ieee80211_proc_init_sta(struct ieee80211_local *local,
-			     struct sta_info *sta)
-{
-	char buf[30];
-	struct proc_dir_entry *entry;
-
-	sprintf(buf, MACSTR, MAC2STR(sta->addr));
-
-	if (!local->proc_sta)
-		return;
-
-	entry = create_proc_read_entry(buf, 0, local->proc_sta,
-				       ieee80211_proc_sta_read, sta);
-	if (entry) {
-		entry->mode &= ~(S_IRWXG | S_IRWXO);
-	}
-}
-
-
-void ieee80211_proc_deinit_sta(struct ieee80211_local *local,
-			       struct sta_info *sta)
-{
-	char buf[30];
-	sprintf(buf, MACSTR, MAC2STR(sta->addr));
-	if (local->proc_sta) {
-		remove_proc_entry(buf, local->proc_sta);
-	}
-}
-
-
-void ieee80211_proc_init_virtual(struct net_device *dev)
-{
-	struct proc_dir_entry *entry;
-	struct ieee80211_local *local = dev->ieee80211_ptr;
-
-	if (!local->proc_iface)
-		return;
-
-	entry = create_proc_read_entry(dev->name, 0, local->proc_iface,
-				       ieee80211_proc_iface_read, dev);
-	if (entry)
-		entry->mode &= ~(S_IRWXG | S_IRWXO);
-}
-
-
-void ieee80211_proc_deinit_virtual(struct net_device *dev)
-{
-	struct ieee80211_local *local = dev->ieee80211_ptr;
-
-	if (local->proc_iface)
-		remove_proc_entry(dev->name, local->proc_iface);
-}
-
-
-void ieee80211_proc_init_interface(struct ieee80211_local *local)
-{
-	if (!ieee80211_proc)
-		return;
-
-	local->proc = proc_mkdir(local->mdev->name, ieee80211_proc);
-	if (!local->proc)
-		return;
-
-	local->proc_sta = proc_mkdir("sta", local->proc);
-	local->proc_iface = proc_mkdir("iface", local->proc);
-	create_proc_read_entry("counters", 0, local->proc,
-                               ieee80211_proc_counters_read, local);
-	create_proc_read_entry("config", 0, local->proc,
-                               ieee80211_proc_config_read, local);
-	create_proc_read_entry("channels", 0, local->proc,
-                               ieee80211_proc_channels_read, local);
-	create_proc_read_entry("rates", 0, local->proc,
-			       ieee80211_proc_rates_read, local);
-	create_proc_read_entry("multicast", 0, local->proc,
-			       ieee80211_proc_multicast_read, local);
-	create_proc_read_entry("debug", 0, local->proc,
-                               ieee80211_proc_debug_read, local);
-	create_proc_read_entry("info", 0, local->proc,
-			       ieee80211_proc_info_read, local);
-	ieee80211_proc_init_virtual(local->mdev);
-}
-
-
-void ieee80211_proc_deinit_interface(struct ieee80211_local *local)
-{
-	if (!local->proc)
-		return;
-
-	ieee80211_proc_deinit_virtual(local->mdev);
-	remove_proc_entry("iface", local->proc);
-	remove_proc_entry("sta", local->proc);
-        remove_proc_entry("counters", local->proc);
-        remove_proc_entry("debug", local->proc);
-        remove_proc_entry("config", local->proc);
-        remove_proc_entry("channels", local->proc);
-	remove_proc_entry("rates", local->proc);
-	remove_proc_entry("multicast", local->proc);
-	remove_proc_entry("info", local->proc);
-	local->proc = NULL;
-	remove_proc_entry(local->mdev->name, ieee80211_proc);
-}
-
-
-void ieee80211_proc_init(void)
-{
-	if (proc_net == NULL) {
-		ieee80211_proc = NULL;
-		return;
-	}
-
-	ieee80211_proc = proc_mkdir("ieee80211", proc_net);
-	if (!ieee80211_proc)
-		printk(KERN_WARNING "Failed to mkdir /proc/net/ieee80211\n");
-}
-
-
-void ieee80211_proc_deinit(void)
-{
-	if (!ieee80211_proc)
-		return;
-
-	ieee80211_proc = NULL;
-	remove_proc_entry("ieee80211", proc_net);
-}
-
-#endif /* CONFIG_PROC_FS */
diff --git a/net/d80211/ieee80211_proc.h b/net/d80211/ieee80211_proc.h
deleted file mode 100644
index 4519d26..0000000
--- a/net/d80211/ieee80211_proc.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2003-2004, Instant802 Networks, Inc.
- *
- * 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.
- */
-
-#ifndef IEEE80211_PROC_H
-#define IEEE80211_PROC_H
-
-#include <linux/netdevice.h>
-#include "ieee80211_i.h"
-#include "sta_info.h"
-
-#ifdef CONFIG_PROC_FS
-
-void ieee80211_proc_init_sta(struct ieee80211_local *local,
-			     struct sta_info *sta);
-void ieee80211_proc_deinit_sta(struct ieee80211_local *local,
-			       struct sta_info *sta);
-void ieee80211_proc_init_virtual(struct net_device *dev);
-void ieee80211_proc_deinit_virtual(struct net_device *dev);
-void ieee80211_proc_init_interface(struct ieee80211_local *local);
-void ieee80211_proc_deinit_interface(struct ieee80211_local *local);
-void ieee80211_proc_init(void);
-void ieee80211_proc_deinit(void);
-
-#else /* CONFIG_PROC_FS */
-
-static inline void ieee80211_proc_init_sta(struct ieee80211_local *local,
-					   struct sta_info *sta) {}
-static inline void ieee80211_proc_deinit_sta(struct ieee80211_local *local,
-					     struct sta_info *sta) {}
-static inline void ieee80211_proc_init_virtual(struct net_device *dev) {}
-static inline void ieee80211_proc_deinit_virtual(struct net_device *dev) {}
-static inline void
-ieee80211_proc_init_interface(struct ieee80211_local *local) {}
-static inline void
-ieee80211_proc_deinit_interface(struct ieee80211_local *local) {}
-static inline void ieee80211_proc_init(void) {}
-static inline void ieee80211_proc_deinit(void) {}
-#endif /* CONFIG_PROC_FS */
-
-const char *ieee80211_mode_str(int mode);
-const char *ieee80211_mode_str_short(int mode);
-
-#endif /* IEEE80211_PROC_H */
diff --git a/net/d80211/ieee80211_sysfs.c b/net/d80211/ieee80211_sysfs.c
index 10bf45c..fb1c6b5 100644
--- a/net/d80211/ieee80211_sysfs.c
+++ b/net/d80211/ieee80211_sysfs.c
@@ -14,7 +14,6 @@ #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <net/d80211.h>
 #include "ieee80211_i.h"
-#include "ieee80211_proc.h"
 #include "rate_control.h"
 
 #define to_ieee80211_local(class)	container_of(class, struct ieee80211_local, class_dev)
@@ -30,6 +29,38 @@ 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_add_iface(struct class_device *dev,
diff --git a/net/d80211/rate_control.c b/net/d80211/rate_control.c
index 33ba8e2..bf797ec 100644
--- a/net/d80211/rate_control.c
+++ b/net/d80211/rate_control.c
@@ -327,29 +327,6 @@ static void rate_control_simple_free_sta
 	kfree(rctrl);
 }
 
-
-static int rate_control_simple_status_sta(struct ieee80211_local *local,
-					  struct sta_info *sta, char *buf)
-{
-	char *p = buf;
-	struct sta_rate_control *srctrl = sta->rate_ctrl_priv;
-
-	p += sprintf(p, "tx_avg_rate_sum=%d\n", srctrl->tx_avg_rate_sum);
-	p += sprintf(p, "tx_avg_rate_num=%d\n", srctrl->tx_avg_rate_num);
-	if (srctrl->tx_avg_rate_num)
-		p += sprintf(p, "tx_avg_rate_avg=%d\n",
-			     srctrl->tx_avg_rate_sum /
-			     srctrl->tx_avg_rate_num);
-	return p - buf;
-}
-
-
-static int rate_control_simple_status_global(struct ieee80211_local *local,
-					     char *buf)
-{
-	return 0;
-}
-
 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;
@@ -397,8 +374,6 @@ static struct rate_control_ops rate_cont
 	.get_rate = rate_control_simple_get_rate,
 	.rate_init = rate_control_simple_rate_init,
 	.clear = rate_control_simple_clear,
-	.status_sta = rate_control_simple_status_sta,
-	.status_global = rate_control_simple_status_global,
 	.alloc = rate_control_simple_alloc,
 	.free = rate_control_simple_free,
 	.alloc_sta = rate_control_simple_alloc_sta,
diff --git a/net/d80211/rate_control.h b/net/d80211/rate_control.h
index 7705fb2..d8bdfed 100644
--- a/net/d80211/rate_control.h
+++ b/net/d80211/rate_control.h
@@ -45,9 +45,6 @@ struct rate_control_ops {
 		    struct rate_control_extra *extra);
 	void (*rate_init)(struct ieee80211_local *local, struct sta_info *sta);
 	void (*clear)(void *priv);
-	int (*status_sta)(struct ieee80211_local *local,
-			  struct sta_info *sta, char *buf);
-	int (*status_global)(struct ieee80211_local *local, char *buf);
 
 	void * (*alloc)(struct ieee80211_local *local);
 	void (*free)(void *priv);
@@ -96,20 +93,6 @@ static inline void rate_control_clear(st
 }
 
 
-static inline int rate_control_status_sta(struct ieee80211_local *local,
-					  struct sta_info *sta, char *buf)
-{
-	return local->rate_ctrl->status_sta(local, sta, buf);
-}
-
-
-static inline int rate_control_status_global(struct ieee80211_local *local,
-					     char *buf)
-{
-	return local->rate_ctrl->status_global(local, buf);
-}
-
-
 static inline void * rate_control_alloc(struct ieee80211_local *local)
 {
 	return local->rate_ctrl->alloc(local);
diff --git a/net/d80211/sta_info.c b/net/d80211/sta_info.c
index 96e8dc4..d3b4b42 100644
--- a/net/d80211/sta_info.c
+++ b/net/d80211/sta_info.c
@@ -19,7 +19,6 @@ #include <linux/if_arp.h>
 
 #include <net/d80211.h>
 #include "ieee80211_i.h"
-#include "ieee80211_proc.h"
 #include "rate_control.h"
 
 
@@ -180,7 +179,6 @@ #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 		ieee80211_sta_sysfs_add(sta);
 		rate_control_add_sta_attrs(local, sta->rate_ctrl_priv,
 					   &sta->kobj);
-		ieee80211_proc_init_sta(local, sta);
 	} else {
 		/* procfs entry adding might sleep, so schedule process context
 		 * task for adding proc entry for STAs that do not yet have
@@ -200,7 +198,6 @@ #ifdef CONFIG_D80211_VERBOSE_DEBUG
 #endif /* CONFIG_D80211_VERBOSE_DEBUG */
 
 	rate_control_remove_sta_attrs(local, sta->rate_ctrl_priv, &sta->kobj);
-	ieee80211_proc_deinit_sta(local, sta);
 	ieee80211_sta_sysfs_remove(sta);
 
 	sta_info_put(sta);
@@ -371,7 +368,6 @@ static void sta_info_proc_add_task(void 
 		sta->sysfs_registered = 1;
 		ieee80211_sta_sysfs_add(sta);
 		rate_control_add_sta_attrs(local, sta->rate_ctrl_priv, &sta->kobj);
-		ieee80211_proc_init_sta(local, sta);
 		sta_info_put(sta);
 	}
 }
-- 
1.3.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/12] d80211: separate allocation of ieee80211_local
  2006-06-08  7:49 ` [PATCH 3/12] d80211: separate allocation of ieee80211_local Jiri Benc
@ 2006-06-12 19:35   ` Jiri Benc
  2006-06-12 19:52     ` John W. Linville
  0 siblings, 1 reply; 15+ messages in thread
From: Jiri Benc @ 2006-06-12 19:35 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, John W. Linville

On Thu,  8 Jun 2006 09:49:07 +0200 (CEST), Jiri Benc wrote:
> ieee80211_local has a separate class_device. That means it has reference
> counting independent of master net_device and can be freed at a different
> time, therefore these two structures cannot be allocated together.
> 
> Solve this by adding ieee80211_ptr pointer to net_device structure (similar
> to other pointers already presented there) and using it as a pointer to
> independently allocated ieee80211_local.

I suppose approval from Dave will be needed for adding that pointer to
net_device, right?

> [...]
>  include/linux/netdevice.h    |    1 
>  net/d80211/ieee80211.c       |  100 +++++++++++++++++++++---------------------
>  net/d80211/ieee80211_dev.c   |   17 +++++++
>  net/d80211/ieee80211_i.h     |    9 +++-
>  net/d80211/ieee80211_iface.c |   20 ++++----
>  net/d80211/ieee80211_ioctl.c |   92 +++++++++++++++++++--------------------
>  net/d80211/ieee80211_proc.c  |    6 +--
>  net/d80211/ieee80211_scan.c  |   10 ++--
>  net/d80211/ieee80211_sta.c   |   58 ++++++++++++------------
>  net/d80211/ieee80211_sysfs.c |   26 ++++++++---
>  net/d80211/rate_control.c    |    4 +-
>  net/d80211/rate_control.h    |    4 +-
>  net/d80211/wme.c             |   26 +++++------
>  13 files changed, 206 insertions(+), 167 deletions(-)
> 
> [...]
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -371,6 +371,7 @@ #define NETIF_F_UFO             8192    
>  	void                    *ip6_ptr;       /* IPv6 specific data */
>  	void			*ec_ptr;	/* Econet specific data	*/
>  	void			*ax25_ptr;	/* AX.25 specific data */
> +	void			*ieee80211_ptr;	/* IEEE 802.11 specific data */
>  
>  /*
>   * Cache line mostly used on receive path (including eth_type_trans())
> [...]

Thanks,

-- 
Jiri Benc
SUSE Labs

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/12] d80211: separate allocation of ieee80211_local
  2006-06-12 19:35   ` Jiri Benc
@ 2006-06-12 19:52     ` John W. Linville
  0 siblings, 0 replies; 15+ messages in thread
From: John W. Linville @ 2006-06-12 19:52 UTC (permalink / raw)
  To: Jiri Benc; +Cc: David S. Miller, netdev

On Mon, Jun 12, 2006 at 09:35:23PM +0200, Jiri Benc wrote:
> On Thu,  8 Jun 2006 09:49:07 +0200 (CEST), Jiri Benc wrote:
> > ieee80211_local has a separate class_device. That means it has reference
> > counting independent of master net_device and can be freed at a different
> > time, therefore these two structures cannot be allocated together.
> > 
> > Solve this by adding ieee80211_ptr pointer to net_device structure (similar
> > to other pointers already presented there) and using it as a pointer to
> > independently allocated ieee80211_local.
> 
> I suppose approval from Dave will be needed for adding that pointer to
> net_device, right?

Ulitmately, yes. :-)

John
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2006-06-12 19:52 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-08  7:49 [PATCH 0/12] d80211: use sysfs instead of procfs Jiri Benc
2006-06-08  7:49 ` [PATCH 1/12] d80211: deinit sysfs in case of an error Jiri Benc
2006-06-08  7:49 ` [PATCH 2/12] d80211: better sysfs registration of symlinks to wiphy Jiri Benc
2006-06-08  7:49 ` [PATCH 3/12] d80211: separate allocation of ieee80211_local Jiri Benc
2006-06-12 19:35   ` Jiri Benc
2006-06-12 19:52     ` John W. Linville
2006-06-08  7:49 ` [PATCH 4/12] d80211: fix Oops when writing to add_ and remove_iface Jiri Benc
2006-06-08  7:49 ` [PATCH 5/12] d80211: wiphy sysfs attributes Jiri Benc
2006-06-08  7:49 ` [PATCH 6/12] d80211: network interface " Jiri Benc
2006-06-08  7:49 ` [PATCH 7/12] d80211: rename sta_info_relase to sta_info_put Jiri Benc
2006-06-08  7:49 ` [PATCH 8/12] d80211: sysfs attributes for associated stations Jiri Benc
2006-06-08  7:49 ` [PATCH 9/12] d80211: remove useless parameters Jiri Benc
2006-06-08  7:49 ` [PATCH 10/12] d80211: rate_control sysfs attributes Jiri Benc
2006-06-08  7:49 ` [PATCH 11/12] d80211: encryption keys " Jiri Benc
2006-06-08  7:49 ` [PATCH 12/12] d80211: remove procfs files Jiri Benc

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).