OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2002-2005, Instant802 Networks, Inc. | 2 * Copyright 2002-2005, Instant802 Networks, Inc. |
3 * Copyright 2005-2006, Devicescape Software, Inc. | 3 * Copyright 2005-2006, Devicescape Software, Inc. |
4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> | 4 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> |
5 * Copyright 2008 Luis R. Rodriguez <lrodriguz@atheros.com> | 5 * Copyright 2008 Luis R. Rodriguez <lrodriguz@atheros.com> |
6 * | 6 * |
7 * This program is free software; you can redistribute it and/or modify | 7 * This program is free software; you can redistribute it and/or modify |
8 * it under the terms of the GNU General Public License version 2 as | 8 * it under the terms of the GNU General Public License version 2 as |
9 * published by the Free Software Foundation. | 9 * published by the Free Software Foundation. |
10 */ | 10 */ |
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 | 716 |
717 /* | 717 /* |
718 * Note that right now we assume the desired channel bandwidth | 718 * Note that right now we assume the desired channel bandwidth |
719 * is always 20 MHz for each individual channel (HT40 uses 20 MHz | 719 * is always 20 MHz for each individual channel (HT40 uses 20 MHz |
720 * per channel, the primary and the extension channel). To support | 720 * per channel, the primary and the extension channel). To support |
721 * smaller custom bandwidths such as 5 MHz or 10 MHz we'll need a | 721 * smaller custom bandwidths such as 5 MHz or 10 MHz we'll need a |
722 * new ieee80211_channel.target_bw and re run the regulatory check | 722 * new ieee80211_channel.target_bw and re run the regulatory check |
723 * on the wiphy with the target_bw specified. Then we can simply use | 723 * on the wiphy with the target_bw specified. Then we can simply use |
724 * that below for the desired_bw_khz below. | 724 * that below for the desired_bw_khz below. |
725 */ | 725 */ |
726 static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | 726 static void handle_channel(struct wiphy *wiphy, |
| 727 » » » enum nl80211_reg_initiator initiator, |
| 728 » » » enum ieee80211_band band, |
727 unsigned int chan_idx) | 729 unsigned int chan_idx) |
728 { | 730 { |
729 int r; | 731 int r; |
730 u32 flags, bw_flags = 0; | 732 u32 flags, bw_flags = 0; |
731 u32 desired_bw_khz = MHZ_TO_KHZ(20); | 733 u32 desired_bw_khz = MHZ_TO_KHZ(20); |
732 const struct ieee80211_reg_rule *reg_rule = NULL; | 734 const struct ieee80211_reg_rule *reg_rule = NULL; |
733 const struct ieee80211_power_rule *power_rule = NULL; | 735 const struct ieee80211_power_rule *power_rule = NULL; |
734 const struct ieee80211_freq_range *freq_range = NULL; | 736 const struct ieee80211_freq_range *freq_range = NULL; |
735 struct ieee80211_supported_band *sband; | 737 struct ieee80211_supported_band *sband; |
736 struct ieee80211_channel *chan; | 738 struct ieee80211_channel *chan; |
737 struct wiphy *request_wiphy = NULL; | 739 struct wiphy *request_wiphy = NULL; |
738 | 740 |
739 assert_cfg80211_lock(); | 741 assert_cfg80211_lock(); |
740 | 742 |
741 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); | 743 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); |
742 | 744 |
743 sband = wiphy->bands[band]; | 745 sband = wiphy->bands[band]; |
744 BUG_ON(chan_idx >= sband->n_channels); | 746 BUG_ON(chan_idx >= sband->n_channels); |
745 chan = &sband->channels[chan_idx]; | 747 chan = &sband->channels[chan_idx]; |
746 | 748 |
747 flags = chan->orig_flags; | 749 flags = chan->orig_flags; |
748 | 750 |
749 r = freq_reg_info(wiphy, | 751 r = freq_reg_info(wiphy, |
750 MHZ_TO_KHZ(chan->center_freq), | 752 MHZ_TO_KHZ(chan->center_freq), |
751 desired_bw_khz, | 753 desired_bw_khz, |
752 ®_rule); | 754 ®_rule); |
753 | 755 |
754 » if (r) | 756 » if (r) { |
| 757 » » /* |
| 758 » » * We will disable all channels that do not match our |
| 759 » » * recieved regulatory rule unless the hint is coming |
| 760 » » * from a Country IE and the Country IE had no information |
| 761 » » * about a band. The IEEE 802.11 spec allows for an AP |
| 762 » » * to send only a subset of the regulatory rules allowed, |
| 763 » » * so an AP in the US that only supports 2.4 GHz may only send |
| 764 » » * a country IE with information for the 2.4 GHz band |
| 765 » » * while 5 GHz is still supported. |
| 766 » » */ |
| 767 » » if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && |
| 768 » » r == -ERANGE) |
| 769 » » » return; |
| 770 |
| 771 » » REG_DBG_PRINT("cfg80211: Disabling freq %d MHz\n", |
| 772 » » » chan->center_freq); |
| 773 » » chan->flags = IEEE80211_CHAN_DISABLED; |
755 return; | 774 return; |
| 775 } |
756 | 776 |
757 power_rule = ®_rule->power_rule; | 777 power_rule = ®_rule->power_rule; |
758 freq_range = ®_rule->freq_range; | 778 freq_range = ®_rule->freq_range; |
759 | 779 |
760 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) | 780 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) |
761 bw_flags = IEEE80211_CHAN_NO_HT40; | 781 bw_flags = IEEE80211_CHAN_NO_HT40; |
762 | 782 |
763 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && | 783 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
764 request_wiphy && request_wiphy == wiphy && | 784 request_wiphy && request_wiphy == wiphy && |
765 request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { | 785 request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { |
(...skipping 14 matching lines...) Expand all Loading... |
780 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); | 800 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); |
781 chan->max_antenna_gain = min(chan->orig_mag, | 801 chan->max_antenna_gain = min(chan->orig_mag, |
782 (int) MBI_TO_DBI(power_rule->max_antenna_gain)); | 802 (int) MBI_TO_DBI(power_rule->max_antenna_gain)); |
783 if (chan->orig_mpwr) | 803 if (chan->orig_mpwr) |
784 chan->max_power = min(chan->orig_mpwr, | 804 chan->max_power = min(chan->orig_mpwr, |
785 (int) MBM_TO_DBM(power_rule->max_eirp)); | 805 (int) MBM_TO_DBM(power_rule->max_eirp)); |
786 else | 806 else |
787 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 807 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); |
788 } | 808 } |
789 | 809 |
790 static void handle_band(struct wiphy *wiphy, enum ieee80211_band band) | 810 static void handle_band(struct wiphy *wiphy, |
| 811 » » » enum ieee80211_band band, |
| 812 » » » enum nl80211_reg_initiator initiator) |
791 { | 813 { |
792 unsigned int i; | 814 unsigned int i; |
793 struct ieee80211_supported_band *sband; | 815 struct ieee80211_supported_band *sband; |
794 | 816 |
795 BUG_ON(!wiphy->bands[band]); | 817 BUG_ON(!wiphy->bands[band]); |
796 sband = wiphy->bands[band]; | 818 sband = wiphy->bands[band]; |
797 | 819 |
798 for (i = 0; i < sband->n_channels; i++) | 820 for (i = 0; i < sband->n_channels; i++) |
799 » » handle_channel(wiphy, band, i); | 821 » » handle_channel(wiphy, initiator, band, i); |
800 } | 822 } |
801 | 823 |
802 static bool ignore_reg_update(struct wiphy *wiphy, | 824 static bool ignore_reg_update(struct wiphy *wiphy, |
803 enum nl80211_reg_initiator initiator) | 825 enum nl80211_reg_initiator initiator) |
804 { | 826 { |
805 if (!last_request) | 827 if (!last_request) |
806 return true; | 828 return true; |
807 if (initiator == NL80211_REGDOM_SET_BY_CORE && | 829 if (initiator == NL80211_REGDOM_SET_BY_CORE && |
808 wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) | 830 wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) |
809 return true; | 831 return true; |
810 /* | 832 /* |
811 * wiphy->regd will be set once the device has its own | 833 * wiphy->regd will be set once the device has its own |
812 * desired regulatory domain set | 834 * desired regulatory domain set |
813 */ | 835 */ |
814 if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && | 836 if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && |
| 837 initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
815 !is_world_regdom(last_request->alpha2)) | 838 !is_world_regdom(last_request->alpha2)) |
816 return true; | 839 return true; |
817 return false; | 840 return false; |
818 } | 841 } |
819 | 842 |
820 static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) | 843 static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator) |
821 { | 844 { |
822 struct cfg80211_registered_device *rdev; | 845 struct cfg80211_registered_device *rdev; |
823 | 846 |
824 list_for_each_entry(rdev, &cfg80211_rdev_list, list) | 847 list_for_each_entry(rdev, &cfg80211_rdev_list, list) |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 | 1049 |
1027 void wiphy_update_regulatory(struct wiphy *wiphy, | 1050 void wiphy_update_regulatory(struct wiphy *wiphy, |
1028 enum nl80211_reg_initiator initiator) | 1051 enum nl80211_reg_initiator initiator) |
1029 { | 1052 { |
1030 enum ieee80211_band band; | 1053 enum ieee80211_band band; |
1031 | 1054 |
1032 if (ignore_reg_update(wiphy, initiator)) | 1055 if (ignore_reg_update(wiphy, initiator)) |
1033 goto out; | 1056 goto out; |
1034 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1057 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
1035 if (wiphy->bands[band]) | 1058 if (wiphy->bands[band]) |
1036 » » » handle_band(wiphy, band); | 1059 » » » handle_band(wiphy, band, initiator); |
1037 } | 1060 } |
1038 out: | 1061 out: |
1039 reg_process_beacons(wiphy); | 1062 reg_process_beacons(wiphy); |
1040 reg_process_ht_flags(wiphy); | 1063 reg_process_ht_flags(wiphy); |
1041 if (wiphy->reg_notifier) | 1064 if (wiphy->reg_notifier) |
1042 wiphy->reg_notifier(wiphy, last_request); | 1065 wiphy->reg_notifier(wiphy, last_request); |
1043 } | 1066 } |
1044 | 1067 |
1045 static void handle_channel_custom(struct wiphy *wiphy, | 1068 static void handle_channel_custom(struct wiphy *wiphy, |
1046 enum ieee80211_band band, | 1069 enum ieee80211_band band, |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1163 return -EALREADY; | 1186 return -EALREADY; |
1164 } | 1187 } |
1165 /* | 1188 /* |
1166 * Two consecutive Country IE hints on the same wiphy. | 1189 * Two consecutive Country IE hints on the same wiphy. |
1167 * This should be picked up early by the driver/stack | 1190 * This should be picked up early by the driver/stack |
1168 */ | 1191 */ |
1169 if (WARN_ON(regdom_changes(pending_request->alpha2))) | 1192 if (WARN_ON(regdom_changes(pending_request->alpha2))) |
1170 return 0; | 1193 return 0; |
1171 return -EALREADY; | 1194 return -EALREADY; |
1172 } | 1195 } |
1173 » » return REG_INTERSECT; | 1196 » » return 0; |
1174 case NL80211_REGDOM_SET_BY_DRIVER: | 1197 case NL80211_REGDOM_SET_BY_DRIVER: |
1175 if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { | 1198 if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { |
1176 if (regdom_changes(pending_request->alpha2)) | 1199 if (regdom_changes(pending_request->alpha2)) |
1177 return 0; | 1200 return 0; |
1178 return -EALREADY; | 1201 return -EALREADY; |
1179 } | 1202 } |
1180 | 1203 |
1181 /* | 1204 /* |
1182 * This would happen if you unplug and plug your card | 1205 * This would happen if you unplug and plug your card |
1183 * back in or if you add a new device for which the previously | 1206 * back in or if you add a new device for which the previously |
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2071 ®_requests_list, list) { | 2094 ®_requests_list, list) { |
2072 list_del(®_request->list); | 2095 list_del(®_request->list); |
2073 kfree(reg_request); | 2096 kfree(reg_request); |
2074 } | 2097 } |
2075 } | 2098 } |
2076 spin_unlock(®_requests_lock); | 2099 spin_unlock(®_requests_lock); |
2077 | 2100 |
2078 mutex_unlock(®_mutex); | 2101 mutex_unlock(®_mutex); |
2079 mutex_unlock(&cfg80211_mutex); | 2102 mutex_unlock(&cfg80211_mutex); |
2080 } | 2103 } |
OLD | NEW |