aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2012-06-18 20:50:57 -0400
committerJohannes Berg <johannes.berg@intel.com>2012-06-20 05:10:43 -0400
commit46c1dd0c7fac54d3739d62b6362024d9b568c6de (patch)
tree79f89f85ca9f6aff2efa1f7f1aed319ae3c1a51f /net/wireless/nl80211.c
parent2bd7e35da011f51d4fdb3b71f888c3a50194bfcd (diff)
cfg80211: fix regression in multi-vif AP start
Commit "cfg80211: provide channel to start_ap function" assumes that the channel is always passed to the NL80211_CMD_START_AP command, however in case of multi-BSSID, hostapd only passes the channel for the first vif. This makes starting beaconing on secondary vifs fail with -EINVAL. Fix this by storing the channel provided to .start_ap in wdev->preset_chan and picking the first AP vif's channel for secondary vifs if not provided. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 06623d064606..888fadc4d63e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2335,6 +2335,33 @@ static int nl80211_parse_beacon(struct genl_info *info,
2335 return 0; 2335 return 0;
2336} 2336}
2337 2337
2338static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
2339 struct cfg80211_ap_settings *params)
2340{
2341 struct wireless_dev *wdev;
2342 bool ret = false;
2343
2344 mutex_lock(&rdev->devlist_mtx);
2345
2346 list_for_each_entry(wdev, &rdev->netdev_list, list) {
2347 if (wdev->iftype != NL80211_IFTYPE_AP &&
2348 wdev->iftype != NL80211_IFTYPE_P2P_GO)
2349 continue;
2350
2351 if (!wdev->preset_chan)
2352 continue;
2353
2354 params->channel = wdev->preset_chan;
2355 params->channel_type = wdev->preset_chantype;
2356 ret = true;
2357 break;
2358 }
2359
2360 mutex_unlock(&rdev->devlist_mtx);
2361
2362 return ret;
2363}
2364
2338static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) 2365static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
2339{ 2366{
2340 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 2367 struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -2437,7 +2464,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
2437 } else if (wdev->preset_chan) { 2464 } else if (wdev->preset_chan) {
2438 params.channel = wdev->preset_chan; 2465 params.channel = wdev->preset_chan;
2439 params.channel_type = wdev->preset_chantype; 2466 params.channel_type = wdev->preset_chantype;
2440 } else 2467 } else if (!nl80211_get_ap_channel(rdev, &params))
2441 return -EINVAL; 2468 return -EINVAL;
2442 2469
2443 if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel, 2470 if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, params.channel,
@@ -2445,8 +2472,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
2445 return -EINVAL; 2472 return -EINVAL;
2446 2473
2447 err = rdev->ops->start_ap(&rdev->wiphy, dev, &params); 2474 err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
2448 if (!err) 2475 if (!err) {
2476 wdev->preset_chan = params.channel;
2477 wdev->preset_chantype = params.channel_type;
2449 wdev->beacon_interval = params.beacon_interval; 2478 wdev->beacon_interval = params.beacon_interval;
2479 }
2450 return err; 2480 return err;
2451} 2481}
2452 2482