From: Johannes Berg <johannes@sipsolutions.net>
To: John Linville <linville@tuxdriver.com>
Cc: linux-wireless <linux-wireless@vger.kernel.org>,
James Ketrenos <jketreno@linux.intel.com>
Subject: [PATCH] make cfg80211 manage wiphy netdev list
Date: Wed, 28 Feb 2007 00:18:17 +0100 [thread overview]
Message-ID: <1172618298.3681.3.camel@johannes.berg> (raw)
This patch makes cfg80211 handle the list of netdevices associated with
a wiphy. It does this by watching NETDEV_REGISTER/UNREGISTER events.
One effect of this patch is that cfg80211 users no longer need to
provide a list_devices hook. Another effect is that all cfg80211 users
will get a "phy80211" symlink in all their netdevices pointing to the
802.11 phy this netdev is associated to, thereby standardising this.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
James, are you ok with the "phy80211" name? The wiphy* names can be
changed too, but they shall ultimately be changeable from userspace so
people can have stable names there.
---
include/linux/netdevice.h | 3 +-
include/net/cfg80211.h | 7 ----
include/net/wireless.h | 3 ++
net/mac80211/ieee80211_cfg.c | 18 ------------
net/mac80211/ieee80211_sysfs.c | 13 +-------
net/wireless/core.c | 61 ++++++++++++++++++++++++++++++++++-------
net/wireless/core.h | 3 ++
net/wireless/nl80211.c | 42 ++++++++++++----------------
8 files changed, 80 insertions(+), 70 deletions(-)
--- wireless-dev.orig/include/linux/netdevice.h 2007-02-27 23:01:32.645643616 +0100
+++ wireless-dev/include/linux/netdevice.h 2007-02-27 23:02:06.065643616 +0100
@@ -401,7 +401,8 @@ struct net_device
void *ip6_ptr; /* IPv6 specific data */
void *ec_ptr; /* Econet specific data */
void *ax25_ptr; /* AX.25 specific data */
- struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data */
+ struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,
+ assign before registering */
/*
* Cache line mostly used on receive path (including eth_type_trans())
--- wireless-dev.orig/net/wireless/core.c 2007-02-27 23:03:44.625643616 +0100
+++ wireless-dev/net/wireless/core.c 2007-02-27 23:34:16.505643616 +0100
@@ -11,6 +11,7 @@
#include <linux/list.h>
#include <linux/nl80211.h>
#include <linux/debugfs.h>
+#include <linux/notifier.h>
#include <net/genetlink.h>
#include <net/cfg80211.h>
#include <net/wireless.h>
@@ -143,9 +144,6 @@ struct wiphy *wiphy_new(struct cfg80211_
struct cfg80211_registered_device *drv;
int alloc_size;
- if (!ops->list_interfaces)
- return NULL;
-
alloc_size = sizeof(*drv) + sizeof_priv;
drv = kzalloc(alloc_size, GFP_KERNEL);
@@ -172,6 +170,7 @@ struct wiphy *wiphy_new(struct cfg80211_
mutex_unlock(&cfg80211_drv_mutex);
mutex_init(&drv->mtx);
+ INIT_LIST_HEAD(&drv->netdev_list);
device_initialize(&drv->wiphy.dev);
drv->wiphy.dev.class = &ieee80211_class;
@@ -238,30 +237,73 @@ void wiphy_free(struct wiphy *wiphy)
}
EXPORT_SYMBOL(wiphy_free);
+static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
+ unsigned long state,
+ void *ndev)
+{
+ struct net_device *dev = ndev;
+ struct cfg80211_registered_device *rdev;
+
+ if (!dev->ieee80211_ptr)
+ return 0;
+
+ rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
+
+ switch (state) {
+ case NETDEV_REGISTER:
+ mutex_lock(&rdev->mtx);
+ list_add(&dev->ieee80211_ptr->list, &rdev->netdev_list);
+ if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
+ "phy80211")) {
+ printk(KERN_ERR "wireless: failed to add phy80211 symlink to netdev!\n");
+ }
+ dev->ieee80211_ptr->netdev = dev;
+ mutex_unlock(&rdev->mtx);
+ break;
+ case NETDEV_UNREGISTER:
+ mutex_lock(&rdev->mtx);
+ sysfs_remove_link(&dev->dev.kobj, "phy80211");
+ list_del(&dev->ieee80211_ptr->list);
+ mutex_unlock(&rdev->mtx);
+ break;
+ }
+
+ return 0;
+}
+
+static struct notifier_block cfg80211_netdev_notifier = {
+ .notifier_call = cfg80211_netdev_notifier_call,
+};
static int cfg80211_init(void)
{
int err = wiphy_sysfs_init();
if (err)
- return err;
+ goto out_fail_sysfs;
+
+ err = register_netdevice_notifier(&cfg80211_netdev_notifier);
+ if (err)
+ goto out_fail_notifier;
err = cfg80211_wext_init();
if (err)
- goto out_exit_sysfs;
+ goto out_fail_wext;
err = nl80211_init();
if (err)
- goto out_nl80211;
+ goto out_fail_nl80211;
ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);
return 0;
- out_nl80211:
+ out_fail_nl80211:
cfg80211_wext_exit();
- out_exit_sysfs:
+ out_fail_wext:
+ unregister_netdevice_notifier(&cfg80211_netdev_notifier);
+ out_fail_notifier:
wiphy_sysfs_exit();
-
+ out_fail_sysfs:
return err;
}
module_init(cfg80211_init);
@@ -271,6 +313,7 @@ static void cfg80211_exit(void)
debugfs_remove(ieee80211_debugfs_dir);
nl80211_exit();
cfg80211_wext_exit();
+ unregister_netdevice_notifier(&cfg80211_netdev_notifier);
wiphy_sysfs_exit();
}
module_exit(cfg80211_exit);
--- wireless-dev.orig/net/mac80211/ieee80211_sysfs.c 2007-02-27 23:09:43.335643616 +0100
+++ wireless-dev/net/mac80211/ieee80211_sysfs.c 2007-02-27 23:42:01.185643616 +0100
@@ -699,23 +699,15 @@ int ieee80211_sysfs_change_if_type(struc
int ieee80211_sysfs_add_netdevice(struct net_device *dev)
{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
int res;
- res = sysfs_create_link(&dev->dev.kobj,
- &local->hw.wiphy->dev.kobj,
- "wiphy");
- if (res)
- goto err_out;
res = ieee80211_add_if_group(&dev->dev.kobj, dev);
if (res)
- goto err_link;
+ goto err_fail_if_group;
res = ieee80211_key_kset_sysfs_register(IEEE80211_DEV_TO_SUB_IF(dev));
return res;
-err_link:
- sysfs_remove_link(&dev->dev.kobj, "wiphy");
-err_out:
+err_fail_if_group:
return res;
}
@@ -723,5 +715,4 @@ void ieee80211_sysfs_remove_netdevice(st
{
ieee80211_key_kset_sysfs_unregister(IEEE80211_DEV_TO_SUB_IF(dev));
ieee80211_remove_if_group(&dev->dev.kobj, dev);
- sysfs_remove_link(&dev->dev.kobj, "wiphy");
}
--- wireless-dev.orig/include/net/wireless.h 2007-02-27 23:01:22.395643616 +0100
+++ wireless-dev/include/net/wireless.h 2007-02-27 23:34:22.035643616 +0100
@@ -9,6 +9,7 @@
#include <linux/netdevice.h>
#include <linux/debugfs.h>
+#include <linux/list.h>
#include <net/cfg80211.h>
/**
@@ -48,6 +49,8 @@ struct wireless_dev {
/* private to the generic wireless code */
struct cfg80211_config pending_config;
+ struct list_head list;
+ struct net_device *netdev;
};
/**
--- wireless-dev.orig/net/wireless/core.h 2007-02-27 23:18:35.045643616 +0100
+++ wireless-dev/net/wireless/core.h 2007-02-27 23:40:02.925643616 +0100
@@ -24,6 +24,9 @@ struct cfg80211_registered_device {
/* wiphy index, internal only */
int idx;
+ /* associate netdev list */
+ struct list_head netdev_list;
+
/* must be last because of the way we do wiphy_priv(),
* and it should at least be aligned to NETDEV_ALIGN */
struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN)));
--- wireless-dev.orig/include/net/cfg80211.h 2007-02-27 23:22:55.315643616 +0100
+++ wireless-dev/include/net/cfg80211.h 2007-02-27 23:23:03.035643616 +0100
@@ -66,9 +66,6 @@ struct wiphy;
* All callbacks except where otherwise noted should return 0
* on success or a negative error code.
*
- * @list_interfaces: Call the one() function with the given data and the
- * ifindex for each interface belonging to the wiphy.
- * This callback is required.
* @inject_packet: inject the given frame with the NL80211_FLAG_*
* flags onto the given queue.
*
@@ -118,10 +115,6 @@ struct wiphy;
* is to be passed to that callback
*/
struct cfg80211_ops {
- int (*list_interfaces)(struct wiphy *wiphy, void *data,
- int (*one)(void *data, int ifindex));
-
-
int (*inject_packet)(struct wiphy *wiphy, void *frame, int framelen,
u32 flags, int queue);
--- wireless-dev.orig/net/mac80211/ieee80211_cfg.c 2007-02-27 23:22:36.495643616 +0100
+++ wireless-dev/net/mac80211/ieee80211_cfg.c 2007-02-27 23:22:48.195643616 +0100
@@ -24,23 +24,6 @@ static inline int rtnl_lock_local(struct
}
-static int ieee80211_list_interfaces(struct wiphy *wiphy, void *data,
- int (*one)(void *data, int ifindex))
-{
- struct ieee80211_local *local = wiphy_priv(wiphy);
- struct ieee80211_sub_if_data *subif;
- int err = 0;
-
- spin_lock_bh(&local->sub_if_lock);
- list_for_each_entry(subif, &local->sub_if_list, list) {
- err = one(data, subif->dev->ifindex);
- if (err)
- break;
- }
- spin_unlock_bh(&local->sub_if_lock);
- return err;
-}
-
static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
unsigned int type)
{
@@ -102,7 +85,6 @@ static int ieee80211_del_iface(struct wi
}
struct cfg80211_ops mac80211_config_ops = {
- .list_interfaces = ieee80211_list_interfaces,
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
};
--- wireless-dev.orig/net/wireless/nl80211.c 2007-02-27 23:23:19.825643616 +0100
+++ wireless-dev/net/wireless/nl80211.c 2007-02-27 23:40:36.735643616 +0100
@@ -197,31 +197,21 @@ static int nl80211_get_wiphys(struct sk_
return -ENOBUFS;
}
-struct add_cb_data {
- int idx;
- struct sk_buff *skb;
-};
-
-static int addifidx(void *data, int ifidx)
+static int addifidx(struct net_device *dev, struct sk_buff *skb, int *idx)
{
- struct add_cb_data *cb = data;
- struct net_device *dev = dev_get_by_index(ifidx);
int err = -ENOBUFS;
struct nlattr *start;
- /* not that this can happen, since the caller
- * should hold the device open... */
- if (!dev)
- return -ENODEV;
+ dev_hold(dev);
- start = nla_nest_start(cb->skb, cb->idx++);
+ start = nla_nest_start(skb, *idx++);
if (!start)
goto nla_put_failure;
- NLA_PUT_U32(cb->skb, NL80211_ATTR_IFINDEX, ifidx);
- NLA_PUT_STRING(cb->skb, NL80211_ATTR_IFNAME, dev->name);
+ NLA_PUT_U32(skb, NL80211_ATTR_IFINDEX, dev->ifindex);
+ NLA_PUT_STRING(skb, NL80211_ATTR_IFNAME, dev->name);
- nla_nest_end(cb->skb, start);
+ nla_nest_end(skb, start);
err = 0;
nla_put_failure:
@@ -234,9 +224,9 @@ static int nl80211_get_intfs(struct sk_b
struct cfg80211_registered_device *drv;
struct sk_buff *msg;
void *hdr;
- int err;
+ int err, array_idx;
struct nlattr *start;
- struct add_cb_data cb;
+ struct wireless_dev *wdev;
drv = cfg80211_get_dev_from_info(info);
if (IS_ERR(drv))
@@ -257,12 +247,11 @@ static int nl80211_get_intfs(struct sk_b
goto msg_free;
}
- cb.skb = msg;
- cb.idx = 1;
- err = drv->ops->list_interfaces(&drv->wiphy, &cb, addifidx);
- if (err)
- goto msg_free;
-
+ array_idx = 1;
+ list_for_each_entry(wdev, &drv->netdev_list, list) {
+ if (addifidx(wdev->netdev, msg, &array_idx))
+ goto msg_free;
+ }
nla_nest_end(msg, start);
genlmsg_end(msg, hdr);
@@ -718,6 +707,11 @@ static int nl80211_assoc_deauth(struct s
return err;
}
+struct add_cb_data {
+ int idx;
+ struct sk_buff *skb;
+};
+
static int add_bssid(void *data, u8 *bssid)
{
struct add_cb_data *cb = data;
reply other threads:[~2007-02-27 23:18 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1172618298.3681.3.camel@johannes.berg \
--to=johannes@sipsolutions.net \
--cc=jketreno@linux.intel.com \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox