summary refs log tree commit diff
path: root/net/wireless/chan.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2012-07-12 13:44:50 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-07-12 13:44:50 -0400
commit38a00840638b4932152bca48098dbfa069d942a2 (patch)
treedd12897854f6df8aac237d5fd46551c74be8153a /net/wireless/chan.c
parent391e5c22f5f4e55817f8ba18a08ea717ed2d4a1f (diff)
parent2f8684ce7a47c91da7e0ccba2686277c103d02b6 (diff)
downloadlinux-38a00840638b4932152bca48098dbfa069d942a2.tar.gz
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'net/wireless/chan.c')
-rw-r--r--net/wireless/chan.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index c1999e45a07c..434c56b92c3c 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -82,13 +82,73 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
 				 int freq, enum nl80211_channel_type chantype)
 {
 	struct ieee80211_channel *chan;
+	int err;
 
 	if (!rdev->ops->set_monitor_channel)
 		return -EOPNOTSUPP;
+	if (!cfg80211_has_monitors_only(rdev))
+		return -EBUSY;
 
 	chan = rdev_freq_to_chan(rdev, freq, chantype);
 	if (!chan)
 		return -EINVAL;
 
-	return rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);
+	err = rdev->ops->set_monitor_channel(&rdev->wiphy, chan, chantype);
+	if (!err) {
+		rdev->monitor_channel = chan;
+		rdev->monitor_channel_type = chantype;
+	}
+
+	return err;
+}
+
+void
+cfg80211_get_chan_state(struct cfg80211_registered_device *rdev,
+		        struct wireless_dev *wdev,
+		        struct ieee80211_channel **chan,
+		        enum cfg80211_chan_mode *chanmode)
+{
+	*chan = NULL;
+	*chanmode = CHAN_MODE_UNDEFINED;
+
+	ASSERT_RDEV_LOCK(rdev);
+	ASSERT_WDEV_LOCK(wdev);
+
+	if (!netif_running(wdev->netdev))
+		return;
+
+	switch (wdev->iftype) {
+	case NL80211_IFTYPE_ADHOC:
+		if (wdev->current_bss) {
+			*chan = wdev->current_bss->pub.channel;
+			*chanmode = wdev->ibss_fixed
+				  ? CHAN_MODE_SHARED
+				  : CHAN_MODE_EXCLUSIVE;
+			return;
+		}
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_P2P_CLIENT:
+		if (wdev->current_bss) {
+			*chan = wdev->current_bss->pub.channel;
+			*chanmode = CHAN_MODE_SHARED;
+			return;
+		}
+		break;
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_P2P_GO:
+	case NL80211_IFTYPE_MESH_POINT:
+		*chan = wdev->channel;
+		*chanmode = CHAN_MODE_SHARED;
+		return;
+	case NL80211_IFTYPE_MONITOR:
+	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_WDS:
+		/* these interface types don't really have a channel */
+		return;
+	case NL80211_IFTYPE_UNSPECIFIED:
+	case NUM_NL80211_IFTYPES:
+		WARN_ON(1);
+	}
+
+	return;
 }