diff options
Diffstat (limited to 'net/wireless/core.c')
-rw-r--r-- | net/wireless/core.c | 49 |
1 files changed, 36 insertions, 13 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index f1da0b93bc56..5031db7b275b 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * This is the linux wireless configuration interface. | 2 | * This is the linux wireless configuration interface. |
3 | * | 3 | * |
4 | * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/if.h> | 7 | #include <linux/if.h> |
@@ -19,6 +19,7 @@ | |||
19 | #include "nl80211.h" | 19 | #include "nl80211.h" |
20 | #include "core.h" | 20 | #include "core.h" |
21 | #include "sysfs.h" | 21 | #include "sysfs.h" |
22 | #include "reg.h" | ||
22 | 23 | ||
23 | /* name for sysfs, %d is appended */ | 24 | /* name for sysfs, %d is appended */ |
24 | #define PHY_NAME "phy" | 25 | #define PHY_NAME "phy" |
@@ -32,7 +33,6 @@ MODULE_DESCRIPTION("wireless configuration support"); | |||
32 | * often because we need to do it for each command */ | 33 | * often because we need to do it for each command */ |
33 | LIST_HEAD(cfg80211_drv_list); | 34 | LIST_HEAD(cfg80211_drv_list); |
34 | DEFINE_MUTEX(cfg80211_drv_mutex); | 35 | DEFINE_MUTEX(cfg80211_drv_mutex); |
35 | static int wiphy_counter; | ||
36 | 36 | ||
37 | /* for debugfs */ | 37 | /* for debugfs */ |
38 | static struct dentry *ieee80211_debugfs_dir; | 38 | static struct dentry *ieee80211_debugfs_dir; |
@@ -184,7 +184,8 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, | |||
184 | if (result) | 184 | if (result) |
185 | goto out_unlock; | 185 | goto out_unlock; |
186 | 186 | ||
187 | if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent, | 187 | if (rdev->wiphy.debugfsdir && |
188 | !debugfs_rename(rdev->wiphy.debugfsdir->d_parent, | ||
188 | rdev->wiphy.debugfsdir, | 189 | rdev->wiphy.debugfsdir, |
189 | rdev->wiphy.debugfsdir->d_parent, | 190 | rdev->wiphy.debugfsdir->d_parent, |
190 | newname)) | 191 | newname)) |
@@ -204,6 +205,8 @@ out_unlock: | |||
204 | 205 | ||
205 | struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) | 206 | struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) |
206 | { | 207 | { |
208 | static int wiphy_counter; | ||
209 | |||
207 | struct cfg80211_registered_device *drv; | 210 | struct cfg80211_registered_device *drv; |
208 | int alloc_size; | 211 | int alloc_size; |
209 | 212 | ||
@@ -220,21 +223,18 @@ struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) | |||
220 | 223 | ||
221 | mutex_lock(&cfg80211_drv_mutex); | 224 | mutex_lock(&cfg80211_drv_mutex); |
222 | 225 | ||
223 | drv->idx = wiphy_counter; | 226 | drv->idx = wiphy_counter++; |
224 | |||
225 | /* now increase counter for the next device unless | ||
226 | * it has wrapped previously */ | ||
227 | if (wiphy_counter >= 0) | ||
228 | wiphy_counter++; | ||
229 | |||
230 | mutex_unlock(&cfg80211_drv_mutex); | ||
231 | 227 | ||
232 | if (unlikely(drv->idx < 0)) { | 228 | if (unlikely(drv->idx < 0)) { |
229 | wiphy_counter--; | ||
230 | mutex_unlock(&cfg80211_drv_mutex); | ||
233 | /* ugh, wrapped! */ | 231 | /* ugh, wrapped! */ |
234 | kfree(drv); | 232 | kfree(drv); |
235 | return NULL; | 233 | return NULL; |
236 | } | 234 | } |
237 | 235 | ||
236 | mutex_unlock(&cfg80211_drv_mutex); | ||
237 | |||
238 | /* give it a proper name */ | 238 | /* give it a proper name */ |
239 | snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE, | 239 | snprintf(drv->wiphy.dev.bus_id, BUS_ID_SIZE, |
240 | PHY_NAME "%d", drv->idx); | 240 | PHY_NAME "%d", drv->idx); |
@@ -259,6 +259,13 @@ int wiphy_register(struct wiphy *wiphy) | |||
259 | struct ieee80211_supported_band *sband; | 259 | struct ieee80211_supported_band *sband; |
260 | bool have_band = false; | 260 | bool have_band = false; |
261 | int i; | 261 | int i; |
262 | u16 ifmodes = wiphy->interface_modes; | ||
263 | |||
264 | /* sanity check ifmodes */ | ||
265 | WARN_ON(!ifmodes); | ||
266 | ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; | ||
267 | if (WARN_ON(ifmodes != wiphy->interface_modes)) | ||
268 | wiphy->interface_modes = ifmodes; | ||
262 | 269 | ||
263 | /* sanity check supported bands/channels */ | 270 | /* sanity check supported bands/channels */ |
264 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 271 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
@@ -295,7 +302,9 @@ int wiphy_register(struct wiphy *wiphy) | |||
295 | ieee80211_set_bitrate_flags(wiphy); | 302 | ieee80211_set_bitrate_flags(wiphy); |
296 | 303 | ||
297 | /* set up regulatory info */ | 304 | /* set up regulatory info */ |
298 | wiphy_update_regulatory(wiphy); | 305 | mutex_lock(&cfg80211_reg_mutex); |
306 | wiphy_update_regulatory(wiphy, REGDOM_SET_BY_CORE); | ||
307 | mutex_unlock(&cfg80211_reg_mutex); | ||
299 | 308 | ||
300 | mutex_lock(&cfg80211_drv_mutex); | 309 | mutex_lock(&cfg80211_drv_mutex); |
301 | 310 | ||
@@ -309,6 +318,8 @@ int wiphy_register(struct wiphy *wiphy) | |||
309 | drv->wiphy.debugfsdir = | 318 | drv->wiphy.debugfsdir = |
310 | debugfs_create_dir(wiphy_name(&drv->wiphy), | 319 | debugfs_create_dir(wiphy_name(&drv->wiphy), |
311 | ieee80211_debugfs_dir); | 320 | ieee80211_debugfs_dir); |
321 | if (IS_ERR(drv->wiphy.debugfsdir)) | ||
322 | drv->wiphy.debugfsdir = NULL; | ||
312 | 323 | ||
313 | res = 0; | 324 | res = 0; |
314 | out_unlock: | 325 | out_unlock: |
@@ -373,6 +384,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
373 | 384 | ||
374 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); | 385 | rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy); |
375 | 386 | ||
387 | WARN_ON(dev->ieee80211_ptr->iftype == NL80211_IFTYPE_UNSPECIFIED); | ||
388 | |||
376 | switch (state) { | 389 | switch (state) { |
377 | case NETDEV_REGISTER: | 390 | case NETDEV_REGISTER: |
378 | mutex_lock(&rdev->devlist_mtx); | 391 | mutex_lock(&rdev->devlist_mtx); |
@@ -404,7 +417,9 @@ static struct notifier_block cfg80211_netdev_notifier = { | |||
404 | 417 | ||
405 | static int cfg80211_init(void) | 418 | static int cfg80211_init(void) |
406 | { | 419 | { |
407 | int err = wiphy_sysfs_init(); | 420 | int err; |
421 | |||
422 | err = wiphy_sysfs_init(); | ||
408 | if (err) | 423 | if (err) |
409 | goto out_fail_sysfs; | 424 | goto out_fail_sysfs; |
410 | 425 | ||
@@ -418,8 +433,14 @@ static int cfg80211_init(void) | |||
418 | 433 | ||
419 | ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL); | 434 | ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL); |
420 | 435 | ||
436 | err = regulatory_init(); | ||
437 | if (err) | ||
438 | goto out_fail_reg; | ||
439 | |||
421 | return 0; | 440 | return 0; |
422 | 441 | ||
442 | out_fail_reg: | ||
443 | debugfs_remove(ieee80211_debugfs_dir); | ||
423 | out_fail_nl80211: | 444 | out_fail_nl80211: |
424 | unregister_netdevice_notifier(&cfg80211_netdev_notifier); | 445 | unregister_netdevice_notifier(&cfg80211_netdev_notifier); |
425 | out_fail_notifier: | 446 | out_fail_notifier: |
@@ -427,6 +448,7 @@ out_fail_notifier: | |||
427 | out_fail_sysfs: | 448 | out_fail_sysfs: |
428 | return err; | 449 | return err; |
429 | } | 450 | } |
451 | |||
430 | subsys_initcall(cfg80211_init); | 452 | subsys_initcall(cfg80211_init); |
431 | 453 | ||
432 | static void cfg80211_exit(void) | 454 | static void cfg80211_exit(void) |
@@ -435,5 +457,6 @@ static void cfg80211_exit(void) | |||
435 | nl80211_exit(); | 457 | nl80211_exit(); |
436 | unregister_netdevice_notifier(&cfg80211_netdev_notifier); | 458 | unregister_netdevice_notifier(&cfg80211_netdev_notifier); |
437 | wiphy_sysfs_exit(); | 459 | wiphy_sysfs_exit(); |
460 | regulatory_exit(); | ||
438 | } | 461 | } |
439 | module_exit(cfg80211_exit); | 462 | module_exit(cfg80211_exit); |