diff options
author | Luis R. Rodriguez <lrodriguez@atheros.com> | 2009-01-22 18:05:44 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-01-29 16:01:14 -0500 |
commit | 1fa25e413659f943dfec65da2abe713d566c7fdf (patch) | |
tree | 7de278f35b33c2bf35f4964e0b5381a6f029dff5 /net/wireless/reg.c | |
parent | 078e1e60dd6c6b0d4bc8d58ccb80c008e8efc9ff (diff) |
cfg80211: add wiphy_apply_custom_regulatory()
This adds wiphy_apply_custom_regulatory() to be used by drivers
prior to wiphy registration to apply a custom regulatory domain.
This can be used by drivers that do not have a direct 1-1 mapping
between a regulatory domain and a country.
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r-- | net/wireless/reg.c | 115 |
1 files changed, 91 insertions, 24 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index b34fd84b3e2f..0d6059502b40 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -782,36 +782,18 @@ static u32 map_regdom_flags(u32 rd_flags) | |||
782 | return channel_flags; | 782 | return channel_flags; |
783 | } | 783 | } |
784 | 784 | ||
785 | /** | 785 | static int freq_reg_info_regd(struct wiphy *wiphy, |
786 | * freq_reg_info - get regulatory information for the given frequency | 786 | u32 center_freq, |
787 | * @wiphy: the wiphy for which we want to process this rule for | 787 | u32 *bandwidth, |
788 | * @center_freq: Frequency in KHz for which we want regulatory information for | 788 | const struct ieee80211_reg_rule **reg_rule, |
789 | * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one | 789 | const struct ieee80211_regdomain *custom_regd) |
790 | * you can set this to 0. If this frequency is allowed we then set | ||
791 | * this value to the maximum allowed bandwidth. | ||
792 | * @reg_rule: the regulatory rule which we have for this frequency | ||
793 | * | ||
794 | * Use this function to get the regulatory rule for a specific frequency on | ||
795 | * a given wireless device. If the device has a specific regulatory domain | ||
796 | * it wants to follow we respect that unless a country IE has been received | ||
797 | * and processed already. | ||
798 | * | ||
799 | * Returns 0 if it was able to find a valid regulatory rule which does | ||
800 | * apply to the given center_freq otherwise it returns non-zero. It will | ||
801 | * also return -ERANGE if we determine the given center_freq does not even have | ||
802 | * a regulatory rule for a frequency range in the center_freq's band. See | ||
803 | * freq_in_rule_band() for our current definition of a band -- this is purely | ||
804 | * subjective and right now its 802.11 specific. | ||
805 | */ | ||
806 | static int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, | ||
807 | const struct ieee80211_reg_rule **reg_rule) | ||
808 | { | 790 | { |
809 | int i; | 791 | int i; |
810 | bool band_rule_found = false; | 792 | bool band_rule_found = false; |
811 | const struct ieee80211_regdomain *regd; | 793 | const struct ieee80211_regdomain *regd; |
812 | u32 max_bandwidth = 0; | 794 | u32 max_bandwidth = 0; |
813 | 795 | ||
814 | regd = cfg80211_regdomain; | 796 | regd = custom_regd ? custom_regd : cfg80211_regdomain; |
815 | 797 | ||
816 | /* Follow the driver's regulatory domain, if present, unless a country | 798 | /* Follow the driver's regulatory domain, if present, unless a country |
817 | * IE has been processed */ | 799 | * IE has been processed */ |
@@ -852,6 +834,34 @@ static int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, | |||
852 | return !max_bandwidth; | 834 | return !max_bandwidth; |
853 | } | 835 | } |
854 | 836 | ||
837 | /** | ||
838 | * freq_reg_info - get regulatory information for the given frequency | ||
839 | * @wiphy: the wiphy for which we want to process this rule for | ||
840 | * @center_freq: Frequency in KHz for which we want regulatory information for | ||
841 | * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one | ||
842 | * you can set this to 0. If this frequency is allowed we then set | ||
843 | * this value to the maximum allowed bandwidth. | ||
844 | * @reg_rule: the regulatory rule which we have for this frequency | ||
845 | * | ||
846 | * Use this function to get the regulatory rule for a specific frequency on | ||
847 | * a given wireless device. If the device has a specific regulatory domain | ||
848 | * it wants to follow we respect that unless a country IE has been received | ||
849 | * and processed already. | ||
850 | * | ||
851 | * Returns 0 if it was able to find a valid regulatory rule which does | ||
852 | * apply to the given center_freq otherwise it returns non-zero. It will | ||
853 | * also return -ERANGE if we determine the given center_freq does not even have | ||
854 | * a regulatory rule for a frequency range in the center_freq's band. See | ||
855 | * freq_in_rule_band() for our current definition of a band -- this is purely | ||
856 | * subjective and right now its 802.11 specific. | ||
857 | */ | ||
858 | static int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, | ||
859 | const struct ieee80211_reg_rule **reg_rule) | ||
860 | { | ||
861 | return freq_reg_info_regd(wiphy, center_freq, | ||
862 | bandwidth, reg_rule, NULL); | ||
863 | } | ||
864 | |||
855 | static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | 865 | static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, |
856 | unsigned int chan_idx) | 866 | unsigned int chan_idx) |
857 | { | 867 | { |
@@ -962,6 +972,63 @@ void wiphy_update_regulatory(struct wiphy *wiphy, enum reg_set_by setby) | |||
962 | wiphy->reg_notifier(wiphy, setby); | 972 | wiphy->reg_notifier(wiphy, setby); |
963 | } | 973 | } |
964 | 974 | ||
975 | static void handle_channel_custom(struct wiphy *wiphy, | ||
976 | enum ieee80211_band band, | ||
977 | unsigned int chan_idx, | ||
978 | const struct ieee80211_regdomain *regd) | ||
979 | { | ||
980 | int r; | ||
981 | u32 max_bandwidth = 0; | ||
982 | const struct ieee80211_reg_rule *reg_rule = NULL; | ||
983 | const struct ieee80211_power_rule *power_rule = NULL; | ||
984 | struct ieee80211_supported_band *sband; | ||
985 | struct ieee80211_channel *chan; | ||
986 | |||
987 | sband = wiphy->bands[band]; | ||
988 | BUG_ON(chan_idx >= sband->n_channels); | ||
989 | chan = &sband->channels[chan_idx]; | ||
990 | |||
991 | r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), | ||
992 | &max_bandwidth, ®_rule, regd); | ||
993 | |||
994 | if (r) { | ||
995 | chan->flags = IEEE80211_CHAN_DISABLED; | ||
996 | return; | ||
997 | } | ||
998 | |||
999 | power_rule = ®_rule->power_rule; | ||
1000 | |||
1001 | chan->flags |= map_regdom_flags(reg_rule->flags); | ||
1002 | chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); | ||
1003 | chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); | ||
1004 | chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); | ||
1005 | } | ||
1006 | |||
1007 | static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, | ||
1008 | const struct ieee80211_regdomain *regd) | ||
1009 | { | ||
1010 | unsigned int i; | ||
1011 | struct ieee80211_supported_band *sband; | ||
1012 | |||
1013 | BUG_ON(!wiphy->bands[band]); | ||
1014 | sband = wiphy->bands[band]; | ||
1015 | |||
1016 | for (i = 0; i < sband->n_channels; i++) | ||
1017 | handle_channel_custom(wiphy, band, i, regd); | ||
1018 | } | ||
1019 | |||
1020 | /* Used by drivers prior to wiphy registration */ | ||
1021 | void wiphy_apply_custom_regulatory(struct wiphy *wiphy, | ||
1022 | const struct ieee80211_regdomain *regd) | ||
1023 | { | ||
1024 | enum ieee80211_band band; | ||
1025 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
1026 | if (wiphy->bands[band]) | ||
1027 | handle_band_custom(wiphy, band, regd); | ||
1028 | } | ||
1029 | } | ||
1030 | EXPORT_SYMBOL(wiphy_apply_custom_regulatory); | ||
1031 | |||
965 | static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, | 1032 | static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd, |
966 | const struct ieee80211_regdomain *src_regd) | 1033 | const struct ieee80211_regdomain *src_regd) |
967 | { | 1034 | { |