aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2012-06-29 06:47:01 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-06-29 07:39:16 -0400
commitdbbae26afa81320b3315fb4ad755b20f1ff256b4 (patch)
tree5b8b56bc68ca4f8d176f340d81a21a75263b7500 /net
parent26ab9a0c589db9ba2710f042c4959da25fd3297b (diff)
cfg80211: track monitor interfaces count
Implements .set_monitor_enabled(wiphy, enabled). Notifies driver upon change of interface layout. If only monitor interfaces become present it is called with 2nd argument being true. If non-monitor interface appears then 2nd argument is false. Driver is notified only upon change. This makes it more obvious about the fact that cfg80211 supports single monitor channel. Once we implement multi-channel we don't want to allow setting monitor channel while other interface types are running. Otherwise it would be ambiguous once we start considering num_different_channels. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/wireless/core.c24
-rw-r--r--net/wireless/core.h14
-rw-r--r--net/wireless/util.c5
3 files changed, 43 insertions, 0 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index c65f59c952c9..8412da7d0f25 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -717,6 +717,24 @@ static struct device_type wiphy_type = {
717 .name = "wlan", 717 .name = "wlan",
718}; 718};
719 719
720void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
721 enum nl80211_iftype iftype, int num)
722{
723 bool has_monitors_only_old = cfg80211_has_monitors_only(rdev);
724 bool has_monitors_only_new;
725
726 ASSERT_RDEV_LOCK(rdev);
727
728 rdev->num_running_ifaces += num;
729 if (iftype == NL80211_IFTYPE_MONITOR)
730 rdev->num_running_monitor_ifaces += num;
731
732 has_monitors_only_new = cfg80211_has_monitors_only(rdev);
733 if (has_monitors_only_new != has_monitors_only_old)
734 rdev->ops->set_monitor_enabled(&rdev->wiphy,
735 has_monitors_only_new);
736}
737
720static int cfg80211_netdev_notifier_call(struct notifier_block *nb, 738static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
721 unsigned long state, 739 unsigned long state,
722 void *ndev) 740 void *ndev)
@@ -820,6 +838,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
820 break; 838 break;
821 case NETDEV_DOWN: 839 case NETDEV_DOWN:
822 dev_hold(dev); 840 dev_hold(dev);
841 cfg80211_lock_rdev(rdev);
842 cfg80211_update_iface_num(rdev, wdev->iftype, -1);
843 cfg80211_unlock_rdev(rdev);
823 queue_work(cfg80211_wq, &wdev->cleanup_work); 844 queue_work(cfg80211_wq, &wdev->cleanup_work);
824 break; 845 break;
825 case NETDEV_UP: 846 case NETDEV_UP:
@@ -927,6 +948,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
927 ret = cfg80211_can_add_interface(rdev, wdev->iftype); 948 ret = cfg80211_can_add_interface(rdev, wdev->iftype);
928 if (ret) 949 if (ret)
929 return notifier_from_errno(ret); 950 return notifier_from_errno(ret);
951 cfg80211_lock_rdev(rdev);
952 cfg80211_update_iface_num(rdev, wdev->iftype, 1);
953 cfg80211_unlock_rdev(rdev);
930 break; 954 break;
931 } 955 }
932 956
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 56f18c2eb919..99acd51343b1 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -56,6 +56,9 @@ struct cfg80211_registered_device {
56 56
57 u32 ap_beacons_nlpid; 57 u32 ap_beacons_nlpid;
58 58
59 int num_running_ifaces;
60 int num_running_monitor_ifaces;
61
59 /* BSSes/scanning */ 62 /* BSSes/scanning */
60 spinlock_t bss_lock; 63 spinlock_t bss_lock;
61 struct list_head bss_list; 64 struct list_head bss_list;
@@ -197,6 +200,14 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
197#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx) 200#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)
198#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) 201#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
199 202
203static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
204{
205 ASSERT_RDEV_LOCK(rdev);
206
207 return rdev->num_running_ifaces == rdev->num_running_monitor_ifaces &&
208 rdev->num_running_ifaces > 0;
209}
210
200enum cfg80211_event_type { 211enum cfg80211_event_type {
201 EVENT_CONNECT_RESULT, 212 EVENT_CONNECT_RESULT,
202 EVENT_ROAMED, 213 EVENT_ROAMED,
@@ -444,6 +455,9 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
444int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, 455int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
445 u32 beacon_int); 456 u32 beacon_int);
446 457
458void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
459 enum nl80211_iftype iftype, int num);
460
447#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS 461#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
448#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) 462#define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond)
449#else 463#else
diff --git a/net/wireless/util.c b/net/wireless/util.c
index fc948d0a53f3..9b92ec57d07b 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -871,6 +871,11 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
871 } 871 }
872 } 872 }
873 873
874 if (!err && ntype != otype && netif_running(dev)) {
875 cfg80211_update_iface_num(rdev, ntype, 1);
876 cfg80211_update_iface_num(rdev, otype, -1);
877 }
878
874 return err; 879 return err;
875} 880}
876 881