aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-12-08 06:39:04 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-12-12 13:48:25 -0500
commit306d6112f9b396ed237305036f8e889f8aa964b5 (patch)
treee84748fb374e84bd16d943c2615480a08c96be3d /net/wireless/nl80211.c
parent7ba1c04ed727a70df2dc63464232c0ec906ad67d (diff)
cfg80211: fix nl80211 frequency handling
Fix two small bugs with HT frequency setting: * HT is accepted even when the driver is incapable * HT40 is accepted when the driver cannot do 40 MHz (both on the selected band) Also simplify the code a little. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9caee6022e3f..4335f76be71f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -365,6 +365,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
365 enum nl80211_sec_chan_offset sec_chan_offset = 365 enum nl80211_sec_chan_offset sec_chan_offset =
366 NL80211_SEC_CHAN_NO_HT; 366 NL80211_SEC_CHAN_NO_HT;
367 struct ieee80211_channel *chan; 367 struct ieee80211_channel *chan;
368 struct ieee80211_sta_ht_cap *ht_cap;
368 u32 freq, sec_freq; 369 u32 freq, sec_freq;
369 370
370 if (!rdev->ops->set_channel) { 371 if (!rdev->ops->set_channel) {
@@ -372,26 +373,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
372 goto bad_res; 373 goto bad_res;
373 } 374 }
374 375
376 result = -EINVAL;
377
375 if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) { 378 if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) {
376 sec_chan_offset = nla_get_u32( 379 sec_chan_offset = nla_get_u32(info->attrs[
377 info->attrs[
378 NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]); 380 NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]);
379 if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && 381 if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT &&
380 sec_chan_offset != NL80211_SEC_CHAN_DISABLED && 382 sec_chan_offset != NL80211_SEC_CHAN_DISABLED &&
381 sec_chan_offset != NL80211_SEC_CHAN_BELOW && 383 sec_chan_offset != NL80211_SEC_CHAN_BELOW &&
382 sec_chan_offset != NL80211_SEC_CHAN_ABOVE) { 384 sec_chan_offset != NL80211_SEC_CHAN_ABOVE)
383 result = -EINVAL;
384 goto bad_res; 385 goto bad_res;
385 }
386 } 386 }
387 387
388 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); 388 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
389 chan = ieee80211_get_channel(&rdev->wiphy, freq); 389 chan = ieee80211_get_channel(&rdev->wiphy, freq);
390 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) { 390
391 /* Primary channel not allowed */ 391 /* Primary channel not allowed */
392 result = -EINVAL; 392 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
393 goto bad_res; 393 goto bad_res;
394 } 394
395 if (sec_chan_offset == NL80211_SEC_CHAN_BELOW) 395 if (sec_chan_offset == NL80211_SEC_CHAN_BELOW)
396 sec_freq = freq - 20; 396 sec_freq = freq - 20;
397 else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE) 397 else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE)
@@ -399,14 +399,26 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
399 else 399 else
400 sec_freq = 0; 400 sec_freq = 0;
401 401
402 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
403
404 /* no HT capabilities */
405 if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT &&
406 !ht_cap->ht_supported)
407 goto bad_res;
408
402 if (sec_freq) { 409 if (sec_freq) {
403 struct ieee80211_channel *schan; 410 struct ieee80211_channel *schan;
411
412 /* no 40 MHz capabilities */
413 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
414 (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
415 goto bad_res;
416
404 schan = ieee80211_get_channel(&rdev->wiphy, sec_freq); 417 schan = ieee80211_get_channel(&rdev->wiphy, sec_freq);
405 if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) { 418
406 /* Secondary channel not allowed */ 419 /* Secondary channel not allowed */
407 result = -EINVAL; 420 if (!schan || schan->flags & IEEE80211_CHAN_DISABLED)
408 goto bad_res; 421 goto bad_res;
409 }
410 } 422 }
411 423
412 result = rdev->ops->set_channel(&rdev->wiphy, chan, 424 result = rdev->ops->set_channel(&rdev->wiphy, chan,
@@ -416,7 +428,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
416 } 428 }
417 429
418 430
419bad_res: 431 bad_res:
420 cfg80211_put_dev(rdev); 432 cfg80211_put_dev(rdev);
421 return result; 433 return result;
422} 434}