aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/core.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-04-23 15:20:05 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:29:41 -0400
commit704232c2718c9d4b3375ec15a14fc0397970c449 (patch)
tree6ffaa759ebaee36c4242bff6b7630f148efcaea3 /net/wireless/core.c
parent2a5e1c0eb9efe26eed1dd072fe08de5797a7efd5 (diff)
[WIRELESS] cfg80211: New wireless config infrastructure.
This patch creates the core cfg80211 code along with some sysfs bits. This is a stripped down version to allow mac80211 to function, but doesn't include any configuration yet except for creating and removing virtual interfaces. This patch includes the nl80211 header file but it only contains the interface types which the cfg80211 interface for creating virtual interfaces relies on. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/wireless/core.c')
-rw-r--r--net/wireless/core.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
new file mode 100644
index 000000000000..532e1e09e028
--- /dev/null
+++ b/net/wireless/core.c
@@ -0,0 +1,209 @@
1/*
2 * This is the linux wireless configuration interface.
3 *
4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
5 */
6
7#include <linux/if.h>
8#include <linux/module.h>
9#include <linux/err.h>
10#include <linux/mutex.h>
11#include <linux/list.h>
12#include <linux/nl80211.h>
13#include <linux/debugfs.h>
14#include <linux/notifier.h>
15#include <linux/device.h>
16#include <net/genetlink.h>
17#include <net/cfg80211.h>
18#include <net/wireless.h>
19#include "core.h"
20#include "sysfs.h"
21
22/* name for sysfs, %d is appended */
23#define PHY_NAME "phy"
24
25MODULE_AUTHOR("Johannes Berg");
26MODULE_LICENSE("GPL");
27MODULE_DESCRIPTION("wireless configuration support");
28
29/* RCU might be appropriate here since we usually
30 * only read the list, and that can happen quite
31 * often because we need to do it for each command */
32LIST_HEAD(cfg80211_drv_list);
33DEFINE_MUTEX(cfg80211_drv_mutex);
34static int wiphy_counter;
35
36/* for debugfs */
37static struct dentry *ieee80211_debugfs_dir;
38
39/* exported functions */
40
41struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv)
42{
43 struct cfg80211_registered_device *drv;
44 int alloc_size;
45
46 alloc_size = sizeof(*drv) + sizeof_priv;
47
48 drv = kzalloc(alloc_size, GFP_KERNEL);
49 if (!drv)
50 return NULL;
51
52 drv->ops = ops;
53
54 mutex_lock(&cfg80211_drv_mutex);
55
56 if (unlikely(wiphy_counter<0)) {
57 /* ugh, wrapped! */
58 kfree(drv);
59 return NULL;
60 }
61 drv->idx = wiphy_counter;
62
63 /* give it a proper name */
64 snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE,
65 PHY_NAME "%d", drv->idx);
66
67 /* now increase counter for the next time */
68 wiphy_counter++;
69 mutex_unlock(&cfg80211_drv_mutex);
70
71 mutex_init(&drv->mtx);
72 mutex_init(&drv->devlist_mtx);
73 INIT_LIST_HEAD(&drv->netdev_list);
74
75 device_initialize(&drv->wiphy.dev);
76 drv->wiphy.dev.class = &ieee80211_class;
77 drv->wiphy.dev.platform_data = drv;
78
79 return &drv->wiphy;
80}
81EXPORT_SYMBOL(wiphy_new);
82
83int wiphy_register(struct wiphy *wiphy)
84{
85 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
86 int res;
87
88 mutex_lock(&cfg80211_drv_mutex);
89
90
91 res = device_add(&drv->wiphy.dev);
92 if (res)
93 goto out_unlock;
94
95 list_add(&drv->list, &cfg80211_drv_list);
96
97 /* add to debugfs */
98 drv->wiphy.debugfsdir =
99 debugfs_create_dir(wiphy_name(&drv->wiphy),
100 ieee80211_debugfs_dir);
101
102 res = 0;
103out_unlock:
104 mutex_unlock(&cfg80211_drv_mutex);
105 return res;
106}
107EXPORT_SYMBOL(wiphy_register);
108
109void wiphy_unregister(struct wiphy *wiphy)
110{
111 struct cfg80211_registered_device *drv = wiphy_to_dev(wiphy);
112
113 mutex_lock(&cfg80211_drv_mutex);
114
115 /* hold registered driver mutex during list removal as well
116 * to make sure no commands are in progress at the moment */
117 mutex_lock(&drv->mtx);
118 list_del(&drv->list);
119 mutex_unlock(&drv->mtx);
120
121 device_del(&drv->wiphy.dev);
122 debugfs_remove(drv->wiphy.debugfsdir);
123
124 mutex_unlock(&cfg80211_drv_mutex);
125}
126EXPORT_SYMBOL(wiphy_unregister);
127
128void cfg80211_dev_free(struct cfg80211_registered_device *drv)
129{
130 mutex_destroy(&drv->mtx);
131 mutex_destroy(&drv->devlist_mtx);
132 kfree(drv);
133}
134
135void wiphy_free(struct wiphy *wiphy)
136{
137 put_device(&wiphy->dev);
138}
139EXPORT_SYMBOL(wiphy_free);
140
141static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
142 unsigned long state,
143 void *ndev)
144{
145 struct net_device *dev = ndev;
146 struct cfg80211_registered_device *rdev;
147
148 if (!dev->ieee80211_ptr)
149 return 0;
150
151 rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
152
153 switch (state) {
154 case NETDEV_REGISTER:
155 mutex_lock(&rdev->devlist_mtx);
156 list_add(&dev->ieee80211_ptr->list, &rdev->netdev_list);
157 if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj,
158 "phy80211")) {
159 printk(KERN_ERR "wireless: failed to add phy80211 "
160 "symlink to netdev!\n");
161 }
162 dev->ieee80211_ptr->netdev = dev;
163 mutex_unlock(&rdev->devlist_mtx);
164 break;
165 case NETDEV_UNREGISTER:
166 mutex_lock(&rdev->devlist_mtx);
167 if (!list_empty(&dev->ieee80211_ptr->list)) {
168 sysfs_remove_link(&dev->dev.kobj, "phy80211");
169 list_del_init(&dev->ieee80211_ptr->list);
170 }
171 mutex_unlock(&rdev->devlist_mtx);
172 break;
173 }
174
175 return 0;
176}
177
178static struct notifier_block cfg80211_netdev_notifier = {
179 .notifier_call = cfg80211_netdev_notifier_call,
180};
181
182static int cfg80211_init(void)
183{
184 int err = wiphy_sysfs_init();
185 if (err)
186 goto out_fail_sysfs;
187
188 err = register_netdevice_notifier(&cfg80211_netdev_notifier);
189 if (err)
190 goto out_fail_notifier;
191
192 ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);
193
194 return 0;
195
196out_fail_notifier:
197 wiphy_sysfs_exit();
198out_fail_sysfs:
199 return err;
200}
201module_init(cfg80211_init);
202
203static void cfg80211_exit(void)
204{
205 debugfs_remove(ieee80211_debugfs_dir);
206 unregister_netdevice_notifier(&cfg80211_netdev_notifier);
207 wiphy_sysfs_exit();
208}
209module_exit(cfg80211_exit);