diff mbox

[RFC,10/15] nl80211: add channel support to the periodic scan

Message ID 1288612336-2830-11-git-send-email-luciano.coelho@nokia.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Luciano Coelho Nov. 1, 2010, 11:52 a.m. UTC
None
diff mbox

Patch

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e1d7ab2..d5b9047 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3004,7 +3004,11 @@  static int nl80211_start_periodic(struct sk_buff *skb,
 	struct cfg80211_periodic_request *request;
 	struct cfg80211_registered_device *rdev;
 	struct net_device *dev;
-	int err;
+	struct ieee80211_channel *channel;
+	struct nlattr *attr;
+	struct wiphy *wiphy;
+	int err, tmp, n_channels, i;
+	enum ieee80211_band band;
 
 	printk("nl80211_start_periodic\n");
 
@@ -3029,7 +3033,24 @@  static int nl80211_start_periodic(struct sk_buff *skb,
 		goto out;
 	}
 
-	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	wiphy = &rdev->wiphy;
+
+	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
+		n_channels = validate_scan_freqs(
+				info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
+		if (!n_channels)
+			return -EINVAL;
+	} else {
+		n_channels = 0;
+
+		for (band = 0; band < IEEE80211_NUM_BANDS; band++)
+			if (wiphy->bands[band])
+				n_channels += wiphy->bands[band]->n_channels;
+	}
+
+	request = kzalloc(sizeof(*request)
+			  + sizeof(channel) * n_channels,
+			  GFP_KERNEL);
 	if (!request) {
 		err = -ENOMEM;
 		goto out;
@@ -3040,8 +3061,56 @@  static int nl80211_start_periodic(struct sk_buff *skb,
 
 	rdev->periodic_req = request;
 
+	i = 0;
+	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
+		/* user specified, bail out if channel not found */
+		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
+			struct ieee80211_channel *chan;
+
+			chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
+
+			if (!chan) {
+				err = -EINVAL;
+				goto out_free;
+			}
+
+			/* ignore disabled channels */
+			if (chan->flags & IEEE80211_CHAN_DISABLED)
+				continue;
+
+			request->channels[i] = chan;
+			i++;
+		}
+	} else {
+		/* all channels */
+		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+			int j;
+			if (!wiphy->bands[band])
+				continue;
+			for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
+				struct ieee80211_channel *chan;
+
+				chan = &wiphy->bands[band]->channels[j];
+
+				if (chan->flags & IEEE80211_CHAN_DISABLED)
+					continue;
+
+				request->channels[i] = chan;
+				i++;
+			}
+		}
+	}
+
+	if (!i) {
+		err = -EINVAL;
+		goto out_free;
+	}
+
+	request->n_channels = i;
+
 	err = rdev->ops->periodic_start(&rdev->wiphy, dev, request);
 	if (err) {
+out_free:
 		kfree(request);
 		rdev->periodic_req = NULL;
 		goto out;