aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-01-19 14:43:42 -0500
committerDavid S. Miller <davem@davemloft.net>2010-01-19 14:43:42 -0500
commit6373464288cab09bc641be301d8d30fc9f64ba71 (patch)
treec1bc92dc630aa15da2e12bc0d09c92169817a702 /net/wireless
parent6d955180b2f9ccff444df06265160868cabb289a (diff)
parent730dd70549e0ec755dd55615ba5cfc38a482a947 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: drivers/net/wireless/iwlwifi/iwl-core.h
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c1
-rw-r--r--net/wireless/core.h3
-rw-r--r--net/wireless/nl80211.c130
-rw-r--r--net/wireless/reg.c319
-rw-r--r--net/wireless/reg.h11
-rw-r--r--net/wireless/scan.c120
-rw-r--r--net/wireless/sme.c1
-rw-r--r--net/wireless/wext-compat.c34
8 files changed, 556 insertions, 63 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index c2a2c563d21..0a545bb6ed0 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -402,6 +402,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
402 rdev->wiphy.retry_long = 4; 402 rdev->wiphy.retry_long = 4;
403 rdev->wiphy.frag_threshold = (u32) -1; 403 rdev->wiphy.frag_threshold = (u32) -1;
404 rdev->wiphy.rts_threshold = (u32) -1; 404 rdev->wiphy.rts_threshold = (u32) -1;
405 rdev->wiphy.coverage_class = 0;
405 406
406 return &rdev->wiphy; 407 return &rdev->wiphy;
407} 408}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 30ec95f05b5..2d6a6b9c0c4 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -111,7 +111,8 @@ struct cfg80211_internal_bss {
111 unsigned long ts; 111 unsigned long ts;
112 struct kref ref; 112 struct kref ref;
113 atomic_t hold; 113 atomic_t hold;
114 bool ies_allocated; 114 bool beacon_ies_allocated;
115 bool proberesp_ies_allocated;
115 116
116 /* must be last because of priv member */ 117 /* must be last because of priv member */
117 struct cfg80211_bss pub; 118 struct cfg80211_bss pub;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e3bee3cecdf..4af7991a9ec 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -69,6 +69,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
69 [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 }, 69 [NL80211_ATTR_WIPHY_RETRY_LONG] = { .type = NLA_U8 },
70 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, 70 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
71 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 }, 71 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
72 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
72 73
73 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 74 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
74 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 75 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
@@ -143,6 +144,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
143 .len = WLAN_PMKID_LEN }, 144 .len = WLAN_PMKID_LEN },
144 [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, 145 [NL80211_ATTR_DURATION] = { .type = NLA_U32 },
145 [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, 146 [NL80211_ATTR_COOKIE] = { .type = NLA_U64 },
147 [NL80211_ATTR_TX_RATES] = { .type = NLA_NESTED },
146}; 148};
147 149
148/* policy for the attributes */ 150/* policy for the attributes */
@@ -444,6 +446,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
444 dev->wiphy.frag_threshold); 446 dev->wiphy.frag_threshold);
445 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, 447 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD,
446 dev->wiphy.rts_threshold); 448 dev->wiphy.rts_threshold);
449 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS,
450 dev->wiphy.coverage_class);
447 451
448 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, 452 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
449 dev->wiphy.max_scan_ssids); 453 dev->wiphy.max_scan_ssids);
@@ -572,6 +576,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
572 CMD(del_pmksa, DEL_PMKSA); 576 CMD(del_pmksa, DEL_PMKSA);
573 CMD(flush_pmksa, FLUSH_PMKSA); 577 CMD(flush_pmksa, FLUSH_PMKSA);
574 CMD(remain_on_channel, REMAIN_ON_CHANNEL); 578 CMD(remain_on_channel, REMAIN_ON_CHANNEL);
579 CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
575 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { 580 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
576 i++; 581 i++;
577 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); 582 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
@@ -684,6 +689,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
684 u32 changed; 689 u32 changed;
685 u8 retry_short = 0, retry_long = 0; 690 u8 retry_short = 0, retry_long = 0;
686 u32 frag_threshold = 0, rts_threshold = 0; 691 u32 frag_threshold = 0, rts_threshold = 0;
692 u8 coverage_class = 0;
687 693
688 rtnl_lock(); 694 rtnl_lock();
689 695
@@ -806,9 +812,16 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
806 changed |= WIPHY_PARAM_RTS_THRESHOLD; 812 changed |= WIPHY_PARAM_RTS_THRESHOLD;
807 } 813 }
808 814
815 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
816 coverage_class = nla_get_u8(
817 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
818 changed |= WIPHY_PARAM_COVERAGE_CLASS;
819 }
820
809 if (changed) { 821 if (changed) {
810 u8 old_retry_short, old_retry_long; 822 u8 old_retry_short, old_retry_long;
811 u32 old_frag_threshold, old_rts_threshold; 823 u32 old_frag_threshold, old_rts_threshold;
824 u8 old_coverage_class;
812 825
813 if (!rdev->ops->set_wiphy_params) { 826 if (!rdev->ops->set_wiphy_params) {
814 result = -EOPNOTSUPP; 827 result = -EOPNOTSUPP;
@@ -819,6 +832,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
819 old_retry_long = rdev->wiphy.retry_long; 832 old_retry_long = rdev->wiphy.retry_long;
820 old_frag_threshold = rdev->wiphy.frag_threshold; 833 old_frag_threshold = rdev->wiphy.frag_threshold;
821 old_rts_threshold = rdev->wiphy.rts_threshold; 834 old_rts_threshold = rdev->wiphy.rts_threshold;
835 old_coverage_class = rdev->wiphy.coverage_class;
822 836
823 if (changed & WIPHY_PARAM_RETRY_SHORT) 837 if (changed & WIPHY_PARAM_RETRY_SHORT)
824 rdev->wiphy.retry_short = retry_short; 838 rdev->wiphy.retry_short = retry_short;
@@ -828,6 +842,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
828 rdev->wiphy.frag_threshold = frag_threshold; 842 rdev->wiphy.frag_threshold = frag_threshold;
829 if (changed & WIPHY_PARAM_RTS_THRESHOLD) 843 if (changed & WIPHY_PARAM_RTS_THRESHOLD)
830 rdev->wiphy.rts_threshold = rts_threshold; 844 rdev->wiphy.rts_threshold = rts_threshold;
845 if (changed & WIPHY_PARAM_COVERAGE_CLASS)
846 rdev->wiphy.coverage_class = coverage_class;
831 847
832 result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed); 848 result = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
833 if (result) { 849 if (result) {
@@ -835,6 +851,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
835 rdev->wiphy.retry_long = old_retry_long; 851 rdev->wiphy.retry_long = old_retry_long;
836 rdev->wiphy.frag_threshold = old_frag_threshold; 852 rdev->wiphy.frag_threshold = old_frag_threshold;
837 rdev->wiphy.rts_threshold = old_rts_threshold; 853 rdev->wiphy.rts_threshold = old_rts_threshold;
854 rdev->wiphy.coverage_class = old_coverage_class;
838 } 855 }
839 } 856 }
840 857
@@ -3146,6 +3163,10 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
3146 NLA_PUT(msg, NL80211_BSS_INFORMATION_ELEMENTS, 3163 NLA_PUT(msg, NL80211_BSS_INFORMATION_ELEMENTS,
3147 res->len_information_elements, 3164 res->len_information_elements,
3148 res->information_elements); 3165 res->information_elements);
3166 if (res->beacon_ies && res->len_beacon_ies &&
3167 res->beacon_ies != res->information_elements)
3168 NLA_PUT(msg, NL80211_BSS_BEACON_IES,
3169 res->len_beacon_ies, res->beacon_ies);
3149 if (res->tsf) 3170 if (res->tsf)
3150 NLA_PUT_U64(msg, NL80211_BSS_TSF, res->tsf); 3171 NLA_PUT_U64(msg, NL80211_BSS_TSF, res->tsf);
3151 if (res->beacon_interval) 3172 if (res->beacon_interval)
@@ -4423,6 +4444,109 @@ static int nl80211_cancel_remain_on_channel(struct sk_buff *skb,
4423 return err; 4444 return err;
4424} 4445}
4425 4446
4447static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
4448 u8 *rates, u8 rates_len)
4449{
4450 u8 i;
4451 u32 mask = 0;
4452
4453 for (i = 0; i < rates_len; i++) {
4454 int rate = (rates[i] & 0x7f) * 5;
4455 int ridx;
4456 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
4457 struct ieee80211_rate *srate =
4458 &sband->bitrates[ridx];
4459 if (rate == srate->bitrate) {
4460 mask |= 1 << ridx;
4461 break;
4462 }
4463 }
4464 if (ridx == sband->n_bitrates)
4465 return 0; /* rate not found */
4466 }
4467
4468 return mask;
4469}
4470
4471static struct nla_policy
4472nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] __read_mostly = {
4473 [NL80211_TXRATE_LEGACY] = { .type = NLA_BINARY,
4474 .len = NL80211_MAX_SUPP_RATES },
4475};
4476
4477static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
4478 struct genl_info *info)
4479{
4480 struct nlattr *tb[NL80211_TXRATE_MAX + 1];
4481 struct cfg80211_registered_device *rdev;
4482 struct cfg80211_bitrate_mask mask;
4483 int err, rem, i;
4484 struct net_device *dev;
4485 struct nlattr *tx_rates;
4486 struct ieee80211_supported_band *sband;
4487
4488 if (info->attrs[NL80211_ATTR_TX_RATES] == NULL)
4489 return -EINVAL;
4490
4491 rtnl_lock();
4492
4493 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4494 if (err)
4495 goto unlock_rtnl;
4496
4497 if (!rdev->ops->set_bitrate_mask) {
4498 err = -EOPNOTSUPP;
4499 goto unlock;
4500 }
4501
4502 memset(&mask, 0, sizeof(mask));
4503 /* Default to all rates enabled */
4504 for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
4505 sband = rdev->wiphy.bands[i];
4506 mask.control[i].legacy =
4507 sband ? (1 << sband->n_bitrates) - 1 : 0;
4508 }
4509
4510 /*
4511 * The nested attribute uses enum nl80211_band as the index. This maps
4512 * directly to the enum ieee80211_band values used in cfg80211.
4513 */
4514 nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem)
4515 {
4516 enum ieee80211_band band = nla_type(tx_rates);
4517 if (band < 0 || band >= IEEE80211_NUM_BANDS) {
4518 err = -EINVAL;
4519 goto unlock;
4520 }
4521 sband = rdev->wiphy.bands[band];
4522 if (sband == NULL) {
4523 err = -EINVAL;
4524 goto unlock;
4525 }
4526 nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates),
4527 nla_len(tx_rates), nl80211_txattr_policy);
4528 if (tb[NL80211_TXRATE_LEGACY]) {
4529 mask.control[band].legacy = rateset_to_mask(
4530 sband,
4531 nla_data(tb[NL80211_TXRATE_LEGACY]),
4532 nla_len(tb[NL80211_TXRATE_LEGACY]));
4533 if (mask.control[band].legacy == 0) {
4534 err = -EINVAL;
4535 goto unlock;
4536 }
4537 }
4538 }
4539
4540 err = rdev->ops->set_bitrate_mask(&rdev->wiphy, dev, NULL, &mask);
4541
4542 unlock:
4543 dev_put(dev);
4544 cfg80211_unlock_rdev(rdev);
4545 unlock_rtnl:
4546 rtnl_unlock();
4547 return err;
4548}
4549
4426static struct genl_ops nl80211_ops[] = { 4550static struct genl_ops nl80211_ops[] = {
4427 { 4551 {
4428 .cmd = NL80211_CMD_GET_WIPHY, 4552 .cmd = NL80211_CMD_GET_WIPHY,
@@ -4697,6 +4821,12 @@ static struct genl_ops nl80211_ops[] = {
4697 .policy = nl80211_policy, 4821 .policy = nl80211_policy,
4698 .flags = GENL_ADMIN_PERM, 4822 .flags = GENL_ADMIN_PERM,
4699 }, 4823 },
4824 {
4825 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
4826 .doit = nl80211_set_tx_bitrate_mask,
4827 .policy = nl80211_policy,
4828 .flags = GENL_ADMIN_PERM,
4829 },
4700}; 4830};
4701 4831
4702static struct genl_multicast_group nl80211_mlme_mcgrp = { 4832static struct genl_multicast_group nl80211_mlme_mcgrp = {
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 87ea60d84c3..5f8071de795 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -43,6 +43,15 @@
43#include "regdb.h" 43#include "regdb.h"
44#include "nl80211.h" 44#include "nl80211.h"
45 45
46#ifdef CONFIG_CFG80211_REG_DEBUG
47#define REG_DBG_PRINT(format, args...) \
48 do { \
49 printk(KERN_DEBUG format , ## args); \
50 } while (0)
51#else
52#define REG_DBG_PRINT(args...)
53#endif
54
46/* Receipt of information from last regulatory request */ 55/* Receipt of information from last regulatory request */
47static struct regulatory_request *last_request; 56static struct regulatory_request *last_request;
48 57
@@ -476,12 +485,212 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
476} 485}
477 486
478/* 487/*
488 * This is a work around for sanity checking ieee80211_channel_to_frequency()'s
489 * work. ieee80211_channel_to_frequency() can for example currently provide a
490 * 2 GHz channel when in fact a 5 GHz channel was desired. An example would be
491 * an AP providing channel 8 on a country IE triplet when it sent this on the
492 * 5 GHz band, that channel is designed to be channel 8 on 5 GHz, not a 2 GHz
493 * channel.
494 *
495 * This can be removed once ieee80211_channel_to_frequency() takes in a band.
496 */
497static bool chan_in_band(int chan, enum ieee80211_band band)
498{
499 int center_freq = ieee80211_channel_to_frequency(chan);
500
501 switch (band) {
502 case IEEE80211_BAND_2GHZ:
503 if (center_freq <= 2484)
504 return true;
505 return false;
506 case IEEE80211_BAND_5GHZ:
507 if (center_freq >= 5005)
508 return true;
509 return false;
510 default:
511 return false;
512 }
513}
514
515/*
516 * Some APs may send a country IE triplet for each channel they
517 * support and while this is completely overkill and silly we still
518 * need to support it. We avoid making a single rule for each channel
519 * though and to help us with this we use this helper to find the
520 * actual subband end channel. These type of country IE triplet
521 * scenerios are handled then, all yielding two regulaotry rules from
522 * parsing a country IE:
523 *
524 * [1]
525 * [2]
526 * [36]
527 * [40]
528 *
529 * [1]
530 * [2-4]
531 * [5-12]
532 * [36]
533 * [40-44]
534 *
535 * [1-4]
536 * [5-7]
537 * [36-44]
538 * [48-64]
539 *
540 * [36-36]
541 * [40-40]
542 * [44-44]
543 * [48-48]
544 * [52-52]
545 * [56-56]
546 * [60-60]
547 * [64-64]
548 * [100-100]
549 * [104-104]
550 * [108-108]
551 * [112-112]
552 * [116-116]
553 * [120-120]
554 * [124-124]
555 * [128-128]
556 * [132-132]
557 * [136-136]
558 * [140-140]
559 *
560 * Returns 0 if the IE has been found to be invalid in the middle
561 * somewhere.
562 */
563static int max_subband_chan(enum ieee80211_band band,
564 int orig_cur_chan,
565 int orig_end_channel,
566 s8 orig_max_power,
567 u8 **country_ie,
568 u8 *country_ie_len)
569{
570 u8 *triplets_start = *country_ie;
571 u8 len_at_triplet = *country_ie_len;
572 int end_subband_chan = orig_end_channel;
573
574 /*
575 * We'll deal with padding for the caller unless
576 * its not immediate and we don't process any channels
577 */
578 if (*country_ie_len == 1) {
579 *country_ie += 1;
580 *country_ie_len -= 1;
581 return orig_end_channel;
582 }
583
584 /* Move to the next triplet and then start search */
585 *country_ie += 3;
586 *country_ie_len -= 3;
587
588 if (!chan_in_band(orig_cur_chan, band))
589 return 0;
590
591 while (*country_ie_len >= 3) {
592 int end_channel = 0;
593 struct ieee80211_country_ie_triplet *triplet =
594 (struct ieee80211_country_ie_triplet *) *country_ie;
595 int cur_channel = 0, next_expected_chan;
596
597 /* means last triplet is completely unrelated to this one */
598 if (triplet->ext.reg_extension_id >=
599 IEEE80211_COUNTRY_EXTENSION_ID) {
600 *country_ie -= 3;
601 *country_ie_len += 3;
602 break;
603 }
604
605 if (triplet->chans.first_channel == 0) {
606 *country_ie += 1;
607 *country_ie_len -= 1;
608 if (*country_ie_len != 0)
609 return 0;
610 break;
611 }
612
613 if (triplet->chans.num_channels == 0)
614 return 0;
615
616 /* Monitonically increasing channel order */
617 if (triplet->chans.first_channel <= end_subband_chan)
618 return 0;
619
620 if (!chan_in_band(triplet->chans.first_channel, band))
621 return 0;
622
623 /* 2 GHz */
624 if (triplet->chans.first_channel <= 14) {
625 end_channel = triplet->chans.first_channel +
626 triplet->chans.num_channels - 1;
627 }
628 else {
629 end_channel = triplet->chans.first_channel +
630 (4 * (triplet->chans.num_channels - 1));
631 }
632
633 if (!chan_in_band(end_channel, band))
634 return 0;
635
636 if (orig_max_power != triplet->chans.max_power) {
637 *country_ie -= 3;
638 *country_ie_len += 3;
639 break;
640 }
641
642 cur_channel = triplet->chans.first_channel;
643
644 /* The key is finding the right next expected channel */
645 if (band == IEEE80211_BAND_2GHZ)
646 next_expected_chan = end_subband_chan + 1;
647 else
648 next_expected_chan = end_subband_chan + 4;
649
650 if (cur_channel != next_expected_chan) {
651 *country_ie -= 3;
652 *country_ie_len += 3;
653 break;
654 }
655
656 end_subband_chan = end_channel;
657
658 /* Move to the next one */
659 *country_ie += 3;
660 *country_ie_len -= 3;
661
662 /*
663 * Padding needs to be dealt with if we processed
664 * some channels.
665 */
666 if (*country_ie_len == 1) {
667 *country_ie += 1;
668 *country_ie_len -= 1;
669 break;
670 }
671
672 /* If seen, the IE is invalid */
673 if (*country_ie_len == 2)
674 return 0;
675 }
676
677 if (end_subband_chan == orig_end_channel) {
678 *country_ie = triplets_start;
679 *country_ie_len = len_at_triplet;
680 return orig_end_channel;
681 }
682
683 return end_subband_chan;
684}
685
686/*
479 * Converts a country IE to a regulatory domain. A regulatory domain 687 * Converts a country IE to a regulatory domain. A regulatory domain
480 * structure has a lot of information which the IE doesn't yet have, 688 * structure has a lot of information which the IE doesn't yet have,
481 * so for the other values we use upper max values as we will intersect 689 * so for the other values we use upper max values as we will intersect
482 * with our userspace regulatory agent to get lower bounds. 690 * with our userspace regulatory agent to get lower bounds.
483 */ 691 */
484static struct ieee80211_regdomain *country_ie_2_rd( 692static struct ieee80211_regdomain *country_ie_2_rd(
693 enum ieee80211_band band,
485 u8 *country_ie, 694 u8 *country_ie,
486 u8 country_ie_len, 695 u8 country_ie_len,
487 u32 *checksum) 696 u32 *checksum)
@@ -543,10 +752,29 @@ static struct ieee80211_regdomain *country_ie_2_rd(
543 continue; 752 continue;
544 } 753 }
545 754
755 /*
756 * APs can add padding to make length divisible
757 * by two, required by the spec.
758 */
759 if (triplet->chans.first_channel == 0) {
760 country_ie++;
761 country_ie_len--;
762 /* This is expected to be at the very end only */
763 if (country_ie_len != 0)
764 return NULL;
765 break;
766 }
767
768 if (triplet->chans.num_channels == 0)
769 return NULL;
770
771 if (!chan_in_band(triplet->chans.first_channel, band))
772 return NULL;
773
546 /* 2 GHz */ 774 /* 2 GHz */
547 if (triplet->chans.first_channel <= 14) 775 if (band == IEEE80211_BAND_2GHZ)
548 end_channel = triplet->chans.first_channel + 776 end_channel = triplet->chans.first_channel +
549 triplet->chans.num_channels; 777 triplet->chans.num_channels - 1;
550 else 778 else
551 /* 779 /*
552 * 5 GHz -- For example in country IEs if the first 780 * 5 GHz -- For example in country IEs if the first
@@ -561,6 +789,24 @@ static struct ieee80211_regdomain *country_ie_2_rd(
561 (4 * (triplet->chans.num_channels - 1)); 789 (4 * (triplet->chans.num_channels - 1));
562 790
563 cur_channel = triplet->chans.first_channel; 791 cur_channel = triplet->chans.first_channel;
792
793 /*
794 * Enhancement for APs that send a triplet for every channel
795 * or for whatever reason sends triplets with multiple channels
796 * separated when in fact they should be together.
797 */
798 end_channel = max_subband_chan(band,
799 cur_channel,
800 end_channel,
801 triplet->chans.max_power,
802 &country_ie,
803 &country_ie_len);
804 if (!end_channel)
805 return NULL;
806
807 if (!chan_in_band(end_channel, band))
808 return NULL;
809
564 cur_sub_max_channel = end_channel; 810 cur_sub_max_channel = end_channel;
565 811
566 /* Basic sanity check */ 812 /* Basic sanity check */
@@ -591,10 +837,13 @@ static struct ieee80211_regdomain *country_ie_2_rd(
591 837
592 last_sub_max_channel = cur_sub_max_channel; 838 last_sub_max_channel = cur_sub_max_channel;
593 839
594 country_ie += 3;
595 country_ie_len -= 3;
596 num_rules++; 840 num_rules++;
597 841
842 if (country_ie_len >= 3) {
843 country_ie += 3;
844 country_ie_len -= 3;
845 }
846
598 /* 847 /*
599 * Note: this is not a IEEE requirement but 848 * Note: this is not a IEEE requirement but
600 * simply a memory requirement 849 * simply a memory requirement
@@ -637,6 +886,12 @@ static struct ieee80211_regdomain *country_ie_2_rd(
637 continue; 886 continue;
638 } 887 }
639 888
889 if (triplet->chans.first_channel == 0) {
890 country_ie++;
891 country_ie_len--;
892 break;
893 }
894
640 reg_rule = &rd->reg_rules[i]; 895 reg_rule = &rd->reg_rules[i];
641 freq_range = &reg_rule->freq_range; 896 freq_range = &reg_rule->freq_range;
642 power_rule = &reg_rule->power_rule; 897 power_rule = &reg_rule->power_rule;
@@ -644,13 +899,20 @@ static struct ieee80211_regdomain *country_ie_2_rd(
644 reg_rule->flags = flags; 899 reg_rule->flags = flags;
645 900
646 /* 2 GHz */ 901 /* 2 GHz */
647 if (triplet->chans.first_channel <= 14) 902 if (band == IEEE80211_BAND_2GHZ)
648 end_channel = triplet->chans.first_channel + 903 end_channel = triplet->chans.first_channel +
649 triplet->chans.num_channels; 904 triplet->chans.num_channels -1;
650 else 905 else
651 end_channel = triplet->chans.first_channel + 906 end_channel = triplet->chans.first_channel +
652 (4 * (triplet->chans.num_channels - 1)); 907 (4 * (triplet->chans.num_channels - 1));
653 908
909 end_channel = max_subband_chan(band,
910 triplet->chans.first_channel,
911 end_channel,
912 triplet->chans.max_power,
913 &country_ie,
914 &country_ie_len);
915
654 /* 916 /*
655 * The +10 is since the regulatory domain expects 917 * The +10 is since the regulatory domain expects
656 * the actual band edge, not the center of freq for 918 * the actual band edge, not the center of freq for
@@ -671,12 +933,15 @@ static struct ieee80211_regdomain *country_ie_2_rd(
671 */ 933 */
672 freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40); 934 freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40);
673 power_rule->max_antenna_gain = DBI_TO_MBI(100); 935 power_rule->max_antenna_gain = DBI_TO_MBI(100);
674 power_rule->max_eirp = DBM_TO_MBM(100); 936 power_rule->max_eirp = DBM_TO_MBM(triplet->chans.max_power);
675 937
676 country_ie += 3;
677 country_ie_len -= 3;
678 i++; 938 i++;
679 939
940 if (country_ie_len >= 3) {
941 country_ie += 3;
942 country_ie_len -= 3;
943 }
944
680 BUG_ON(i > NL80211_MAX_SUPP_REG_RULES); 945 BUG_ON(i > NL80211_MAX_SUPP_REG_RULES);
681 } 946 }
682 947
@@ -972,25 +1237,21 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
972 if (r == -ERANGE && 1237 if (r == -ERANGE &&
973 last_request->initiator == 1238 last_request->initiator ==
974 NL80211_REGDOM_SET_BY_COUNTRY_IE) { 1239 NL80211_REGDOM_SET_BY_COUNTRY_IE) {
975#ifdef CONFIG_CFG80211_REG_DEBUG 1240 REG_DBG_PRINT("cfg80211: Leaving channel %d MHz "
976 printk(KERN_DEBUG "cfg80211: Leaving channel %d MHz "
977 "intact on %s - no rule found in band on " 1241 "intact on %s - no rule found in band on "
978 "Country IE\n", 1242 "Country IE\n",
979 chan->center_freq, wiphy_name(wiphy)); 1243 chan->center_freq, wiphy_name(wiphy));
980#endif
981 } else { 1244 } else {
982 /* 1245 /*
983 * In this case we know the country IE has at least one reg rule 1246 * In this case we know the country IE has at least one reg rule
984 * for the band so we respect its band definitions 1247 * for the band so we respect its band definitions
985 */ 1248 */
986#ifdef CONFIG_CFG80211_REG_DEBUG
987 if (last_request->initiator == 1249 if (last_request->initiator ==
988 NL80211_REGDOM_SET_BY_COUNTRY_IE) 1250 NL80211_REGDOM_SET_BY_COUNTRY_IE)
989 printk(KERN_DEBUG "cfg80211: Disabling " 1251 REG_DBG_PRINT("cfg80211: Disabling "
990 "channel %d MHz on %s due to " 1252 "channel %d MHz on %s due to "
991 "Country IE\n", 1253 "Country IE\n",
992 chan->center_freq, wiphy_name(wiphy)); 1254 chan->center_freq, wiphy_name(wiphy));
993#endif
994 flags |= IEEE80211_CHAN_DISABLED; 1255 flags |= IEEE80211_CHAN_DISABLED;
995 chan->flags = flags; 1256 chan->flags = flags;
996 } 1257 }
@@ -1685,7 +1946,7 @@ int regulatory_hint_user(const char *alpha2)
1685 request->wiphy_idx = WIPHY_IDX_STALE; 1946 request->wiphy_idx = WIPHY_IDX_STALE;
1686 request->alpha2[0] = alpha2[0]; 1947 request->alpha2[0] = alpha2[0];
1687 request->alpha2[1] = alpha2[1]; 1948 request->alpha2[1] = alpha2[1];
1688 request->initiator = NL80211_REGDOM_SET_BY_USER, 1949 request->initiator = NL80211_REGDOM_SET_BY_USER;
1689 1950
1690 queue_regulatory_request(request); 1951 queue_regulatory_request(request);
1691 1952
@@ -1753,8 +2014,9 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy,
1753 * therefore cannot iterate over the rdev list here. 2014 * therefore cannot iterate over the rdev list here.
1754 */ 2015 */
1755void regulatory_hint_11d(struct wiphy *wiphy, 2016void regulatory_hint_11d(struct wiphy *wiphy,
1756 u8 *country_ie, 2017 enum ieee80211_band band,
1757 u8 country_ie_len) 2018 u8 *country_ie,
2019 u8 country_ie_len)
1758{ 2020{
1759 struct ieee80211_regdomain *rd = NULL; 2021 struct ieee80211_regdomain *rd = NULL;
1760 char alpha2[2]; 2022 char alpha2[2];
@@ -1800,9 +2062,11 @@ void regulatory_hint_11d(struct wiphy *wiphy,
1800 wiphy_idx_valid(last_request->wiphy_idx))) 2062 wiphy_idx_valid(last_request->wiphy_idx)))
1801 goto out; 2063 goto out;
1802 2064
1803 rd = country_ie_2_rd(country_ie, country_ie_len, &checksum); 2065 rd = country_ie_2_rd(band, country_ie, country_ie_len, &checksum);
1804 if (!rd) 2066 if (!rd) {
2067 REG_DBG_PRINT("cfg80211: Ignoring bogus country IE\n");
1805 goto out; 2068 goto out;
2069 }
1806 2070
1807 /* 2071 /*
1808 * This will not happen right now but we leave it here for the 2072 * This will not happen right now but we leave it here for the
@@ -1870,13 +2134,12 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
1870 if (!reg_beacon) 2134 if (!reg_beacon)
1871 return -ENOMEM; 2135 return -ENOMEM;
1872 2136
1873#ifdef CONFIG_CFG80211_REG_DEBUG 2137 REG_DBG_PRINT("cfg80211: Found new beacon on "
1874 printk(KERN_DEBUG "cfg80211: Found new beacon on " 2138 "frequency: %d MHz (Ch %d) on %s\n",
1875 "frequency: %d MHz (Ch %d) on %s\n", 2139 beacon_chan->center_freq,
1876 beacon_chan->center_freq, 2140 ieee80211_frequency_to_channel(beacon_chan->center_freq),
1877 ieee80211_frequency_to_channel(beacon_chan->center_freq), 2141 wiphy_name(wiphy));
1878 wiphy_name(wiphy)); 2142
1879#endif
1880 memcpy(&reg_beacon->chan, beacon_chan, 2143 memcpy(&reg_beacon->chan, beacon_chan,
1881 sizeof(struct ieee80211_channel)); 2144 sizeof(struct ieee80211_channel));
1882 2145
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 3362c7c069b..3018508226a 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -41,14 +41,25 @@ int regulatory_hint_found_beacon(struct wiphy *wiphy,
41 * regulatory_hint_11d - hints a country IE as a regulatory domain 41 * regulatory_hint_11d - hints a country IE as a regulatory domain
42 * @wiphy: the wireless device giving the hint (used only for reporting 42 * @wiphy: the wireless device giving the hint (used only for reporting
43 * conflicts) 43 * conflicts)
44 * @band: the band on which the country IE was received on. This determines
45 * the band we'll process the country IE channel triplets for.
44 * @country_ie: pointer to the country IE 46 * @country_ie: pointer to the country IE
45 * @country_ie_len: length of the country IE 47 * @country_ie_len: length of the country IE
46 * 48 *
47 * We will intersect the rd with the what CRDA tells us should apply 49 * We will intersect the rd with the what CRDA tells us should apply
48 * for the alpha2 this country IE belongs to, this prevents APs from 50 * for the alpha2 this country IE belongs to, this prevents APs from
49 * sending us incorrect or outdated information against a country. 51 * sending us incorrect or outdated information against a country.
52 *
53 * The AP is expected to provide Country IE channel triplets for the
54 * band it is on. It is technically possible for APs to send channel
55 * country IE triplets even for channels outside of the band they are
56 * in but for that they would have to use the regulatory extension
57 * in combination with a triplet but this behaviour is currently
58 * not observed. For this reason if a triplet is seen with channel
59 * information for a band the BSS is not present in it will be ignored.
50 */ 60 */
51void regulatory_hint_11d(struct wiphy *wiphy, 61void regulatory_hint_11d(struct wiphy *wiphy,
62 enum ieee80211_band band,
52 u8 *country_ie, 63 u8 *country_ie,
53 u8 country_ie_len); 64 u8 country_ie_len);
54 65
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 0c2cbbebca9..06b0231ee5e 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -100,8 +100,10 @@ static void bss_release(struct kref *ref)
100 if (bss->pub.free_priv) 100 if (bss->pub.free_priv)
101 bss->pub.free_priv(&bss->pub); 101 bss->pub.free_priv(&bss->pub);
102 102
103 if (bss->ies_allocated) 103 if (bss->beacon_ies_allocated)
104 kfree(bss->pub.information_elements); 104 kfree(bss->pub.beacon_ies);
105 if (bss->proberesp_ies_allocated)
106 kfree(bss->pub.proberesp_ies);
105 107
106 BUG_ON(atomic_read(&bss->hold)); 108 BUG_ON(atomic_read(&bss->hold));
107 109
@@ -375,8 +377,7 @@ rb_find_bss(struct cfg80211_registered_device *dev,
375 377
376static struct cfg80211_internal_bss * 378static struct cfg80211_internal_bss *
377cfg80211_bss_update(struct cfg80211_registered_device *dev, 379cfg80211_bss_update(struct cfg80211_registered_device *dev,
378 struct cfg80211_internal_bss *res, 380 struct cfg80211_internal_bss *res)
379 bool overwrite)
380{ 381{
381 struct cfg80211_internal_bss *found = NULL; 382 struct cfg80211_internal_bss *found = NULL;
382 const u8 *meshid, *meshcfg; 383 const u8 *meshid, *meshcfg;
@@ -418,28 +419,64 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
418 found->pub.capability = res->pub.capability; 419 found->pub.capability = res->pub.capability;
419 found->ts = res->ts; 420 found->ts = res->ts;
420 421
421 /* overwrite IEs */ 422 /* Update IEs */
422 if (overwrite) { 423 if (res->pub.proberesp_ies) {
423 size_t used = dev->wiphy.bss_priv_size + sizeof(*res); 424 size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
424 size_t ielen = res->pub.len_information_elements; 425 size_t ielen = res->pub.len_proberesp_ies;
426
427 if (found->pub.proberesp_ies &&
428 !found->proberesp_ies_allocated &&
429 ksize(found) >= used + ielen) {
430 memcpy(found->pub.proberesp_ies,
431 res->pub.proberesp_ies, ielen);
432 found->pub.len_proberesp_ies = ielen;
433 } else {
434 u8 *ies = found->pub.proberesp_ies;
435
436 if (found->proberesp_ies_allocated)
437 ies = krealloc(ies, ielen, GFP_ATOMIC);
438 else
439 ies = kmalloc(ielen, GFP_ATOMIC);
440
441 if (ies) {
442 memcpy(ies, res->pub.proberesp_ies,
443 ielen);
444 found->proberesp_ies_allocated = true;
445 found->pub.proberesp_ies = ies;
446 found->pub.len_proberesp_ies = ielen;
447 }
448 }
425 449
426 if (!found->ies_allocated && ksize(found) >= used + ielen) { 450 /* Override possible earlier Beacon frame IEs */
427 memcpy(found->pub.information_elements, 451 found->pub.information_elements =
428 res->pub.information_elements, ielen); 452 found->pub.proberesp_ies;
429 found->pub.len_information_elements = ielen; 453 found->pub.len_information_elements =
454 found->pub.len_proberesp_ies;
455 }
456 if (res->pub.beacon_ies) {
457 size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
458 size_t ielen = res->pub.len_beacon_ies;
459
460 if (found->pub.beacon_ies &&
461 !found->beacon_ies_allocated &&
462 ksize(found) >= used + ielen) {
463 memcpy(found->pub.beacon_ies,
464 res->pub.beacon_ies, ielen);
465 found->pub.len_beacon_ies = ielen;
430 } else { 466 } else {
431 u8 *ies = found->pub.information_elements; 467 u8 *ies = found->pub.beacon_ies;
432 468
433 if (found->ies_allocated) 469 if (found->beacon_ies_allocated)
434 ies = krealloc(ies, ielen, GFP_ATOMIC); 470 ies = krealloc(ies, ielen, GFP_ATOMIC);
435 else 471 else
436 ies = kmalloc(ielen, GFP_ATOMIC); 472 ies = kmalloc(ielen, GFP_ATOMIC);
437 473
438 if (ies) { 474 if (ies) {
439 memcpy(ies, res->pub.information_elements, ielen); 475 memcpy(ies, res->pub.beacon_ies,
440 found->ies_allocated = true; 476 ielen);
441 found->pub.information_elements = ies; 477 found->beacon_ies_allocated = true;
442 found->pub.len_information_elements = ielen; 478 found->pub.beacon_ies = ies;
479 found->pub.len_beacon_ies = ielen;
443 } 480 }
444 } 481 }
445 } 482 }
@@ -489,14 +526,26 @@ cfg80211_inform_bss(struct wiphy *wiphy,
489 res->pub.tsf = timestamp; 526 res->pub.tsf = timestamp;
490 res->pub.beacon_interval = beacon_interval; 527 res->pub.beacon_interval = beacon_interval;
491 res->pub.capability = capability; 528 res->pub.capability = capability;
492 /* point to after the private area */ 529 /*
493 res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz; 530 * Since we do not know here whether the IEs are from a Beacon or Probe
494 memcpy(res->pub.information_elements, ie, ielen); 531 * Response frame, we need to pick one of the options and only use it
495 res->pub.len_information_elements = ielen; 532 * with the driver that does not provide the full Beacon/Probe Response
533 * frame. Use Beacon frame pointer to avoid indicating that this should
534 * override the information_elements pointer should we have received an
535 * earlier indication of Probe Response data.
536 *
537 * The initial buffer for the IEs is allocated with the BSS entry and
538 * is located after the private area.
539 */
540 res->pub.beacon_ies = (u8 *)res + sizeof(*res) + privsz;
541 memcpy(res->pub.beacon_ies, ie, ielen);
542 res->pub.len_beacon_ies = ielen;
543 res->pub.information_elements = res->pub.beacon_ies;
544 res->pub.len_information_elements = res->pub.len_beacon_ies;
496 545
497 kref_init(&res->ref); 546 kref_init(&res->ref);
498 547
499 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, 0); 548 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
500 if (!res) 549 if (!res)
501 return NULL; 550 return NULL;
502 551
@@ -517,7 +566,6 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
517 struct cfg80211_internal_bss *res; 566 struct cfg80211_internal_bss *res;
518 size_t ielen = len - offsetof(struct ieee80211_mgmt, 567 size_t ielen = len - offsetof(struct ieee80211_mgmt,
519 u.probe_resp.variable); 568 u.probe_resp.variable);
520 bool overwrite;
521 size_t privsz = wiphy->bss_priv_size; 569 size_t privsz = wiphy->bss_priv_size;
522 570
523 if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC && 571 if (WARN_ON(wiphy->signal_type == NL80211_BSS_SIGNAL_UNSPEC &&
@@ -538,16 +586,28 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
538 res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); 586 res->pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
539 res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); 587 res->pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
540 res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); 588 res->pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
541 /* point to after the private area */ 589 /*
542 res->pub.information_elements = (u8 *)res + sizeof(*res) + privsz; 590 * The initial buffer for the IEs is allocated with the BSS entry and
543 memcpy(res->pub.information_elements, mgmt->u.probe_resp.variable, ielen); 591 * is located after the private area.
544 res->pub.len_information_elements = ielen; 592 */
593 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
594 res->pub.proberesp_ies = (u8 *) res + sizeof(*res) + privsz;
595 memcpy(res->pub.proberesp_ies, mgmt->u.probe_resp.variable,
596 ielen);
597 res->pub.len_proberesp_ies = ielen;
598 res->pub.information_elements = res->pub.proberesp_ies;
599 res->pub.len_information_elements = res->pub.len_proberesp_ies;
600 } else {
601 res->pub.beacon_ies = (u8 *) res + sizeof(*res) + privsz;
602 memcpy(res->pub.beacon_ies, mgmt->u.beacon.variable, ielen);
603 res->pub.len_beacon_ies = ielen;
604 res->pub.information_elements = res->pub.beacon_ies;
605 res->pub.len_information_elements = res->pub.len_beacon_ies;
606 }
545 607
546 kref_init(&res->ref); 608 kref_init(&res->ref);
547 609
548 overwrite = ieee80211_is_probe_resp(mgmt->frame_control); 610 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
549
550 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res, overwrite);
551 if (!res) 611 if (!res)
552 return NULL; 612 return NULL;
553 613
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 2333d78187e..2ce5e1609a3 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -454,6 +454,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
454 * - and country_ie[1] which is the IE length 454 * - and country_ie[1] which is the IE length
455 */ 455 */
456 regulatory_hint_11d(wdev->wiphy, 456 regulatory_hint_11d(wdev->wiphy,
457 bss->channel->band,
457 country_ie + 2, 458 country_ie + 2,
458 country_ie[1]); 459 country_ie[1]);
459} 460}
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 4198243a3df..966d2f01bea 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -1204,21 +1204,47 @@ int cfg80211_wext_siwrate(struct net_device *dev,
1204 struct wireless_dev *wdev = dev->ieee80211_ptr; 1204 struct wireless_dev *wdev = dev->ieee80211_ptr;
1205 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 1205 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1206 struct cfg80211_bitrate_mask mask; 1206 struct cfg80211_bitrate_mask mask;
1207 u32 fixed, maxrate;
1208 struct ieee80211_supported_band *sband;
1209 int band, ridx;
1210 bool match = false;
1207 1211
1208 if (!rdev->ops->set_bitrate_mask) 1212 if (!rdev->ops->set_bitrate_mask)
1209 return -EOPNOTSUPP; 1213 return -EOPNOTSUPP;
1210 1214
1211 mask.fixed = 0; 1215 memset(&mask, 0, sizeof(mask));
1212 mask.maxrate = 0; 1216 fixed = 0;
1217 maxrate = 0;
1213 1218
1214 if (rate->value < 0) { 1219 if (rate->value < 0) {
1215 /* nothing */ 1220 /* nothing */
1216 } else if (rate->fixed) { 1221 } else if (rate->fixed) {
1217 mask.fixed = rate->value / 1000; /* kbps */ 1222 fixed = rate->value / 100000;
1218 } else { 1223 } else {
1219 mask.maxrate = rate->value / 1000; /* kbps */ 1224 maxrate = rate->value / 100000;
1225 }
1226
1227 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1228 sband = wdev->wiphy->bands[band];
1229 if (sband == NULL)
1230 continue;
1231 for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
1232 struct ieee80211_rate *srate = &sband->bitrates[ridx];
1233 if (fixed == srate->bitrate) {
1234 mask.control[band].legacy = 1 << ridx;
1235 match = true;
1236 break;
1237 }
1238 if (srate->bitrate <= maxrate) {
1239 mask.control[band].legacy |= 1 << ridx;
1240 match = true;
1241 }
1242 }
1220 } 1243 }
1221 1244
1245 if (!match)
1246 return -EINVAL;
1247
1222 return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask); 1248 return rdev->ops->set_bitrate_mask(wdev->wiphy, dev, NULL, &mask);
1223} 1249}
1224EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate); 1250EXPORT_SYMBOL_GPL(cfg80211_wext_siwrate);