aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-05-16 17:50:18 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-05 15:32:16 -0400
commitaa430da41019c1694f6a8e3b8bef1d12ed52b0ad (patch)
tree086b60a5c6253cad2c78f5a976d0608f375f2b03 /net/wireless/nl80211.c
parentd58e7e37aac0465b08527adadc8016421bd4060e (diff)
cfg80211: provide channel to start_ap function
Instead of setting the channel first and then starting the AP, let cfg80211 store the channel and provide it as one of the AP settings. This means that now you have to set the channel before you can start an AP interface, but since hostapd/wpa_supplicant always do that we're OK with this change. Alternatively, it's now possible to give the channel as an attribute to the start-ap nl80211 command, overriding any preset channel. Cc: Kalle Valo <kvalo@qca.qualcomm.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 206465dc0cab..74f4a8f93935 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -921,7 +921,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
921 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS)) 921 if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
922 goto nla_put_failure; 922 goto nla_put_failure;
923 } 923 }
924 CMD(set_channel, SET_CHANNEL); 924 if (dev->ops->set_channel || dev->ops->start_ap) {
925 i++;
926 if (nla_put_u32(msg, i, NL80211_CMD_SET_CHANNEL))
927 goto nla_put_failure;
928 }
925 CMD(set_wds_peer, SET_WDS_PEER); 929 CMD(set_wds_peer, SET_WDS_PEER);
926 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { 930 if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) {
927 CMD(tdls_mgmt, TDLS_MGMT); 931 CMD(tdls_mgmt, TDLS_MGMT);
@@ -1170,6 +1174,9 @@ static bool nl80211_can_set_dev_channel(struct wireless_dev *wdev)
1170 * Monitors are special as they are normally slaved to 1174 * Monitors are special as they are normally slaved to
1171 * whatever else is going on, so they behave as though 1175 * whatever else is going on, so they behave as though
1172 * you tried setting the wiphy channel itself. 1176 * you tried setting the wiphy channel itself.
1177 *
1178 * For AP/GO modes, it's only for compatibility, you can
1179 * also give the channel to the start-AP command.
1173 */ 1180 */
1174 return !wdev || 1181 return !wdev ||
1175 wdev->iftype == NL80211_IFTYPE_AP || 1182 wdev->iftype == NL80211_IFTYPE_AP ||
@@ -1204,6 +1211,7 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
1204 struct wireless_dev *wdev, 1211 struct wireless_dev *wdev,
1205 struct genl_info *info) 1212 struct genl_info *info)
1206{ 1213{
1214 struct ieee80211_channel *channel;
1207 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 1215 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
1208 u32 freq; 1216 u32 freq;
1209 int result; 1217 int result;
@@ -1221,7 +1229,25 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
1221 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); 1229 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
1222 1230
1223 mutex_lock(&rdev->devlist_mtx); 1231 mutex_lock(&rdev->devlist_mtx);
1224 if (wdev) { 1232 if (wdev) switch (wdev->iftype) {
1233 case NL80211_IFTYPE_AP:
1234 case NL80211_IFTYPE_P2P_GO:
1235 if (wdev->beacon_interval) {
1236 result = -EBUSY;
1237 break;
1238 }
1239 channel = rdev_freq_to_chan(rdev, freq, channel_type);
1240 if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
1241 channel,
1242 channel_type)) {
1243 result = -EINVAL;
1244 break;
1245 }
1246 wdev->preset_chan = channel;
1247 wdev->preset_chantype = channel_type;
1248 result = 0;
1249 break;
1250 default:
1225 wdev_lock(wdev); 1251 wdev_lock(wdev);
1226 result = cfg80211_set_freq(rdev, wdev, freq, channel_type); 1252 result = cfg80211_set_freq(rdev, wdev, freq, channel_type);
1227 wdev_unlock(wdev); 1253 wdev_unlock(wdev);
@@ -2299,6 +2325,29 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
2299 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); 2325 info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
2300 } 2326 }
2301 2327
2328 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
2329 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
2330
2331 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE] &&
2332 !nl80211_valid_channel_type(info, &channel_type))
2333 return -EINVAL;
2334
2335 params.channel = rdev_freq_to_chan(rdev,
2336 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
2337 channel_type);
2338 if (!params.channel)
2339 return -EINVAL;
2340 params.channel_type = channel_type;
2341 } else if (wdev->preset_chan) {
2342 params.channel = wdev->preset_chan;
2343 params.channel_type = wdev->preset_chantype;
2344 } else
2345 return -EINVAL;
2346
2347 if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel,
2348 params.channel_type))
2349 return -EINVAL;
2350
2302 err = rdev->ops->start_ap(&rdev->wiphy, dev, &params); 2351 err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
2303 if (!err) 2352 if (!err)
2304 wdev->beacon_interval = params.beacon_interval; 2353 wdev->beacon_interval = params.beacon_interval;