aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/core.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /net/wireless/core.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/wireless/core.c')
-rw-r--r--net/wireless/core.c114
1 files changed, 84 insertions, 30 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index a595f712b5bf..6ac70c101523 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1,13 +1,14 @@
1/* 1/*
2 * This is the linux wireless configuration interface. 2 * This is the linux wireless configuration interface.
3 * 3 *
4 * Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6 6
7#include <linux/if.h> 7#include <linux/if.h>
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/err.h> 9#include <linux/err.h>
10#include <linux/list.h> 10#include <linux/list.h>
11#include <linux/slab.h>
11#include <linux/nl80211.h> 12#include <linux/nl80211.h>
12#include <linux/debugfs.h> 13#include <linux/debugfs.h>
13#include <linux/notifier.h> 14#include <linux/notifier.h>
@@ -22,6 +23,7 @@
22#include "sysfs.h" 23#include "sysfs.h"
23#include "debugfs.h" 24#include "debugfs.h"
24#include "wext-compat.h" 25#include "wext-compat.h"
26#include "ethtool.h"
25 27
26/* name for sysfs, %d is appended */ 28/* name for sysfs, %d is appended */
27#define PHY_NAME "phy" 29#define PHY_NAME "phy"
@@ -30,20 +32,18 @@ MODULE_AUTHOR("Johannes Berg");
30MODULE_LICENSE("GPL"); 32MODULE_LICENSE("GPL");
31MODULE_DESCRIPTION("wireless configuration support"); 33MODULE_DESCRIPTION("wireless configuration support");
32 34
33/* RCU might be appropriate here since we usually 35/* RCU-protected (and cfg80211_mutex for writers) */
34 * only read the list, and that can happen quite
35 * often because we need to do it for each command */
36LIST_HEAD(cfg80211_rdev_list); 36LIST_HEAD(cfg80211_rdev_list);
37int cfg80211_rdev_list_generation; 37int cfg80211_rdev_list_generation;
38 38
39/*
40 * This is used to protect the cfg80211_rdev_list
41 */
42DEFINE_MUTEX(cfg80211_mutex); 39DEFINE_MUTEX(cfg80211_mutex);
43 40
44/* for debugfs */ 41/* for debugfs */
45static struct dentry *ieee80211_debugfs_dir; 42static struct dentry *ieee80211_debugfs_dir;
46 43
44/* for the cleanup, scan and event works */
45struct workqueue_struct *cfg80211_wq;
46
47/* requires cfg80211_mutex to be held! */ 47/* requires cfg80211_mutex to be held! */
48struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) 48struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
49{ 49{
@@ -230,7 +230,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
230 struct wireless_dev *wdev; 230 struct wireless_dev *wdev;
231 int err = 0; 231 int err = 0;
232 232
233 if (!rdev->wiphy.netnsok) 233 if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK))
234 return -EOPNOTSUPP; 234 return -EOPNOTSUPP;
235 235
236 list_for_each_entry(wdev, &rdev->netdev_list, list) { 236 list_for_each_entry(wdev, &rdev->netdev_list, list) {
@@ -359,11 +359,17 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
359 INIT_LIST_HEAD(&rdev->bss_list); 359 INIT_LIST_HEAD(&rdev->bss_list);
360 INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); 360 INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done);
361 361
362#ifdef CONFIG_CFG80211_WEXT
363 rdev->wiphy.wext = &cfg80211_wext_handler;
364#endif
365
362 device_initialize(&rdev->wiphy.dev); 366 device_initialize(&rdev->wiphy.dev);
363 rdev->wiphy.dev.class = &ieee80211_class; 367 rdev->wiphy.dev.class = &ieee80211_class;
364 rdev->wiphy.dev.platform_data = rdev; 368 rdev->wiphy.dev.platform_data = rdev;
365 369
366 rdev->wiphy.ps_default = CONFIG_CFG80211_DEFAULT_PS_VALUE; 370#ifdef CONFIG_CFG80211_DEFAULT_PS
371 rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
372#endif
367 373
368 wiphy_net_set(&rdev->wiphy, &init_net); 374 wiphy_net_set(&rdev->wiphy, &init_net);
369 375
@@ -392,6 +398,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
392 rdev->wiphy.retry_long = 4; 398 rdev->wiphy.retry_long = 4;
393 rdev->wiphy.frag_threshold = (u32) -1; 399 rdev->wiphy.frag_threshold = (u32) -1;
394 rdev->wiphy.rts_threshold = (u32) -1; 400 rdev->wiphy.rts_threshold = (u32) -1;
401 rdev->wiphy.coverage_class = 0;
395 402
396 return &rdev->wiphy; 403 return &rdev->wiphy;
397} 404}
@@ -407,6 +414,18 @@ int wiphy_register(struct wiphy *wiphy)
407 int i; 414 int i;
408 u16 ifmodes = wiphy->interface_modes; 415 u16 ifmodes = wiphy->interface_modes;
409 416
417 if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
418 return -EINVAL;
419
420 if (WARN_ON(wiphy->addresses &&
421 !is_zero_ether_addr(wiphy->perm_addr) &&
422 memcmp(wiphy->perm_addr, wiphy->addresses[0].addr,
423 ETH_ALEN)))
424 return -EINVAL;
425
426 if (wiphy->addresses)
427 memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
428
410 /* sanity check ifmodes */ 429 /* sanity check ifmodes */
411 WARN_ON(!ifmodes); 430 WARN_ON(!ifmodes);
412 ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1; 431 ifmodes &= ((1 << __NL80211_IFTYPE_AFTER_LAST) - 1) & ~1;
@@ -466,7 +485,7 @@ int wiphy_register(struct wiphy *wiphy)
466 /* set up regulatory info */ 485 /* set up regulatory info */
467 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); 486 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
468 487
469 list_add(&rdev->list, &cfg80211_rdev_list); 488 list_add_rcu(&rdev->list, &cfg80211_rdev_list);
470 cfg80211_rdev_list_generation++; 489 cfg80211_rdev_list_generation++;
471 490
472 mutex_unlock(&cfg80211_mutex); 491 mutex_unlock(&cfg80211_mutex);
@@ -478,7 +497,7 @@ int wiphy_register(struct wiphy *wiphy)
478 if (IS_ERR(rdev->wiphy.debugfsdir)) 497 if (IS_ERR(rdev->wiphy.debugfsdir))
479 rdev->wiphy.debugfsdir = NULL; 498 rdev->wiphy.debugfsdir = NULL;
480 499
481 if (wiphy->custom_regulatory) { 500 if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) {
482 struct regulatory_request request; 501 struct regulatory_request request;
483 502
484 request.wiphy_idx = get_wiphy_idx(wiphy); 503 request.wiphy_idx = get_wiphy_idx(wiphy);
@@ -542,8 +561,9 @@ void wiphy_unregister(struct wiphy *wiphy)
542 * First remove the hardware from everywhere, this makes 561 * First remove the hardware from everywhere, this makes
543 * it impossible to find from userspace. 562 * it impossible to find from userspace.
544 */ 563 */
545 cfg80211_debugfs_rdev_del(rdev); 564 debugfs_remove_recursive(rdev->wiphy.debugfsdir);
546 list_del(&rdev->list); 565 list_del_rcu(&rdev->list);
566 synchronize_rcu();
547 567
548 /* 568 /*
549 * Try to grab rdev->mtx. If a command is still in progress, 569 * Try to grab rdev->mtx. If a command is still in progress,
@@ -565,7 +585,6 @@ void wiphy_unregister(struct wiphy *wiphy)
565 585
566 cfg80211_rdev_list_generation++; 586 cfg80211_rdev_list_generation++;
567 device_del(&rdev->wiphy.dev); 587 device_del(&rdev->wiphy.dev);
568 debugfs_remove(rdev->wiphy.debugfsdir);
569 588
570 mutex_unlock(&cfg80211_mutex); 589 mutex_unlock(&cfg80211_mutex);
571 590
@@ -626,6 +645,10 @@ static void wdev_cleanup_work(struct work_struct *work)
626 dev_put(wdev->netdev); 645 dev_put(wdev->netdev);
627} 646}
628 647
648static struct device_type wiphy_type = {
649 .name = "wlan",
650};
651
629static int cfg80211_netdev_notifier_call(struct notifier_block * nb, 652static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
630 unsigned long state, 653 unsigned long state,
631 void *ndev) 654 void *ndev)
@@ -642,6 +665,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
642 WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED); 665 WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED);
643 666
644 switch (state) { 667 switch (state) {
668 case NETDEV_POST_INIT:
669 SET_NETDEV_DEVTYPE(dev, &wiphy_type);
670 break;
645 case NETDEV_REGISTER: 671 case NETDEV_REGISTER:
646 /* 672 /*
647 * NB: cannot take rdev->mtx here because this may be 673 * NB: cannot take rdev->mtx here because this may be
@@ -652,8 +678,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
652 INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); 678 INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
653 INIT_LIST_HEAD(&wdev->event_list); 679 INIT_LIST_HEAD(&wdev->event_list);
654 spin_lock_init(&wdev->event_lock); 680 spin_lock_init(&wdev->event_lock);
681 INIT_LIST_HEAD(&wdev->action_registrations);
682 spin_lock_init(&wdev->action_registrations_lock);
683
655 mutex_lock(&rdev->devlist_mtx); 684 mutex_lock(&rdev->devlist_mtx);
656 list_add(&wdev->list, &rdev->netdev_list); 685 list_add_rcu(&wdev->list, &rdev->netdev_list);
657 rdev->devlist_generation++; 686 rdev->devlist_generation++;
658 /* can only change netns with wiphy */ 687 /* can only change netns with wiphy */
659 dev->features |= NETIF_F_NETNS_LOCAL; 688 dev->features |= NETIF_F_NETNS_LOCAL;
@@ -666,22 +695,31 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
666 wdev->netdev = dev; 695 wdev->netdev = dev;
667 wdev->sme_state = CFG80211_SME_IDLE; 696 wdev->sme_state = CFG80211_SME_IDLE;
668 mutex_unlock(&rdev->devlist_mtx); 697 mutex_unlock(&rdev->devlist_mtx);
669#ifdef CONFIG_WIRELESS_EXT 698#ifdef CONFIG_CFG80211_WEXT
670 if (!dev->wireless_handlers)
671 dev->wireless_handlers = &cfg80211_wext_handler;
672 wdev->wext.default_key = -1; 699 wdev->wext.default_key = -1;
673 wdev->wext.default_mgmt_key = -1; 700 wdev->wext.default_mgmt_key = -1;
674 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; 701 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
675 wdev->wext.ps = wdev->wiphy->ps_default; 702#endif
676 wdev->wext.ps_timeout = 100; 703
704 if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
705 wdev->ps = true;
706 else
707 wdev->ps = false;
708 wdev->ps_timeout = 100;
677 if (rdev->ops->set_power_mgmt) 709 if (rdev->ops->set_power_mgmt)
678 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, 710 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
679 wdev->wext.ps, 711 wdev->ps,
680 wdev->wext.ps_timeout)) { 712 wdev->ps_timeout)) {
681 /* assume this means it's off */ 713 /* assume this means it's off */
682 wdev->wext.ps = false; 714 wdev->ps = false;
683 } 715 }
684#endif 716
717 if (!dev->ethtool_ops)
718 dev->ethtool_ops = &cfg80211_ethtool_ops;
719
720 if ((wdev->iftype == NL80211_IFTYPE_STATION ||
721 wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
722 dev->priv_flags |= IFF_DONT_BRIDGE;
685 break; 723 break;
686 case NETDEV_GOING_DOWN: 724 case NETDEV_GOING_DOWN:
687 switch (wdev->iftype) { 725 switch (wdev->iftype) {
@@ -690,7 +728,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
690 break; 728 break;
691 case NL80211_IFTYPE_STATION: 729 case NL80211_IFTYPE_STATION:
692 wdev_lock(wdev); 730 wdev_lock(wdev);
693#ifdef CONFIG_WIRELESS_EXT 731#ifdef CONFIG_CFG80211_WEXT
694 kfree(wdev->wext.ie); 732 kfree(wdev->wext.ie);
695 wdev->wext.ie = NULL; 733 wdev->wext.ie = NULL;
696 wdev->wext.ie_len = 0; 734 wdev->wext.ie_len = 0;
@@ -707,7 +745,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
707 break; 745 break;
708 case NETDEV_DOWN: 746 case NETDEV_DOWN:
709 dev_hold(dev); 747 dev_hold(dev);
710 schedule_work(&wdev->cleanup_work); 748 queue_work(cfg80211_wq, &wdev->cleanup_work);
711 break; 749 break;
712 case NETDEV_UP: 750 case NETDEV_UP:
713 /* 751 /*
@@ -722,9 +760,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
722 mutex_unlock(&rdev->devlist_mtx); 760 mutex_unlock(&rdev->devlist_mtx);
723 dev_put(dev); 761 dev_put(dev);
724 } 762 }
725#ifdef CONFIG_WIRELESS_EXT
726 cfg80211_lock_rdev(rdev); 763 cfg80211_lock_rdev(rdev);
727 mutex_lock(&rdev->devlist_mtx); 764 mutex_lock(&rdev->devlist_mtx);
765#ifdef CONFIG_CFG80211_WEXT
728 wdev_lock(wdev); 766 wdev_lock(wdev);
729 switch (wdev->iftype) { 767 switch (wdev->iftype) {
730 case NL80211_IFTYPE_ADHOC: 768 case NL80211_IFTYPE_ADHOC:
@@ -737,10 +775,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
737 break; 775 break;
738 } 776 }
739 wdev_unlock(wdev); 777 wdev_unlock(wdev);
778#endif
740 rdev->opencount++; 779 rdev->opencount++;
741 mutex_unlock(&rdev->devlist_mtx); 780 mutex_unlock(&rdev->devlist_mtx);
742 cfg80211_unlock_rdev(rdev); 781 cfg80211_unlock_rdev(rdev);
743#endif
744 break; 782 break;
745 case NETDEV_UNREGISTER: 783 case NETDEV_UNREGISTER:
746 /* 784 /*
@@ -758,13 +796,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
758 */ 796 */
759 if (!list_empty(&wdev->list)) { 797 if (!list_empty(&wdev->list)) {
760 sysfs_remove_link(&dev->dev.kobj, "phy80211"); 798 sysfs_remove_link(&dev->dev.kobj, "phy80211");
761 list_del_init(&wdev->list); 799 list_del_rcu(&wdev->list);
762 rdev->devlist_generation++; 800 rdev->devlist_generation++;
763#ifdef CONFIG_WIRELESS_EXT 801 cfg80211_mlme_purge_actions(wdev);
802#ifdef CONFIG_CFG80211_WEXT
764 kfree(wdev->wext.keys); 803 kfree(wdev->wext.keys);
765#endif 804#endif
766 } 805 }
767 mutex_unlock(&rdev->devlist_mtx); 806 mutex_unlock(&rdev->devlist_mtx);
807 /*
808 * synchronise (so that we won't find this netdev
809 * from other code any more) and then clear the list
810 * head so that the above code can safely check for
811 * !list_empty() to avoid double-cleanup.
812 */
813 synchronize_rcu();
814 INIT_LIST_HEAD(&wdev->list);
768 break; 815 break;
769 case NETDEV_PRE_UP: 816 case NETDEV_PRE_UP:
770 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) 817 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
@@ -825,8 +872,14 @@ static int __init cfg80211_init(void)
825 if (err) 872 if (err)
826 goto out_fail_reg; 873 goto out_fail_reg;
827 874
875 cfg80211_wq = create_singlethread_workqueue("cfg80211");
876 if (!cfg80211_wq)
877 goto out_fail_wq;
878
828 return 0; 879 return 0;
829 880
881out_fail_wq:
882 regulatory_exit();
830out_fail_reg: 883out_fail_reg:
831 debugfs_remove(ieee80211_debugfs_dir); 884 debugfs_remove(ieee80211_debugfs_dir);
832out_fail_nl80211: 885out_fail_nl80211:
@@ -848,5 +901,6 @@ static void cfg80211_exit(void)
848 wiphy_sysfs_exit(); 901 wiphy_sysfs_exit();
849 regulatory_exit(); 902 regulatory_exit();
850 unregister_pernet_device(&cfg80211_pernet_ops); 903 unregister_pernet_device(&cfg80211_pernet_ops);
904 destroy_workqueue(cfg80211_wq);
851} 905}
852module_exit(cfg80211_exit); 906module_exit(cfg80211_exit);