diff options
-rw-r--r-- | include/net/wireless.h | 10 | ||||
-rw-r--r-- | net/wireless/reg.c | 28 |
2 files changed, 37 insertions, 1 deletions
diff --git a/include/net/wireless.h b/include/net/wireless.h index 9c19764a4849..a42c1562d52b 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h | |||
@@ -186,6 +186,15 @@ struct ieee80211_supported_band { | |||
186 | * ISO / IEC 3166 alpha2 it belongs to. When this is enabled | 186 | * ISO / IEC 3166 alpha2 it belongs to. When this is enabled |
187 | * we will disregard the first regulatory hint (when the | 187 | * we will disregard the first regulatory hint (when the |
188 | * initiator is %REGDOM_SET_BY_CORE). | 188 | * initiator is %REGDOM_SET_BY_CORE). |
189 | * @strict_regulatory: tells us the driver for this device will ignore | ||
190 | * regulatory domain settings until it gets its own regulatory domain | ||
191 | * via its regulatory_hint(). After its gets its own regulatory domain | ||
192 | * it will only allow further regulatory domain settings to further | ||
193 | * enhance compliance. For example if channel 13 and 14 are disabled | ||
194 | * by this regulatory domain no user regulatory domain can enable these | ||
195 | * channels at a later time. This can be used for devices which do not | ||
196 | * have calibration information gauranteed for frequencies or settings | ||
197 | * outside of its regulatory domain. | ||
189 | * @reg_notifier: the driver's regulatory notification callback | 198 | * @reg_notifier: the driver's regulatory notification callback |
190 | * @regd: the driver's regulatory domain, if one was requested via | 199 | * @regd: the driver's regulatory domain, if one was requested via |
191 | * the regulatory_hint() API. This can be used by the driver | 200 | * the regulatory_hint() API. This can be used by the driver |
@@ -202,6 +211,7 @@ struct wiphy { | |||
202 | u16 interface_modes; | 211 | u16 interface_modes; |
203 | 212 | ||
204 | bool custom_regulatory; | 213 | bool custom_regulatory; |
214 | bool strict_regulatory; | ||
205 | 215 | ||
206 | /* If multiple wiphys are registered and you're handed e.g. | 216 | /* If multiple wiphys are registered and you're handed e.g. |
207 | * a regular netdev with assigned ieee80211_ptr, you won't | 217 | * a regular netdev with assigned ieee80211_ptr, you won't |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index cad4daadba0d..89e0d8b3cf1e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -867,6 +867,22 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
867 | 867 | ||
868 | power_rule = ®_rule->power_rule; | 868 | power_rule = ®_rule->power_rule; |
869 | 869 | ||
870 | if (last_request->initiator == REGDOM_SET_BY_DRIVER && | ||
871 | last_request->wiphy && last_request->wiphy == wiphy && | ||
872 | last_request->wiphy->strict_regulatory) { | ||
873 | /* This gaurantees the driver's requested regulatory domain | ||
874 | * will always be used as a base for further regulatory | ||
875 | * settings */ | ||
876 | chan->flags = chan->orig_flags = | ||
877 | map_regdom_flags(reg_rule->flags); | ||
878 | chan->max_antenna_gain = chan->orig_mag = | ||
879 | (int) MBI_TO_DBI(power_rule->max_antenna_gain); | ||
880 | chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); | ||
881 | chan->max_power = chan->orig_mpwr = | ||
882 | (int) MBM_TO_DBM(power_rule->max_eirp); | ||
883 | return; | ||
884 | } | ||
885 | |||
870 | chan->flags = flags | map_regdom_flags(reg_rule->flags); | 886 | chan->flags = flags | map_regdom_flags(reg_rule->flags); |
871 | chan->max_antenna_gain = min(chan->orig_mag, | 887 | chan->max_antenna_gain = min(chan->orig_mag, |
872 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); | 888 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); |
@@ -897,6 +913,11 @@ static bool ignore_reg_update(struct wiphy *wiphy, enum reg_set_by setby) | |||
897 | if (setby == REGDOM_SET_BY_CORE && | 913 | if (setby == REGDOM_SET_BY_CORE && |
898 | wiphy->custom_regulatory) | 914 | wiphy->custom_regulatory) |
899 | return true; | 915 | return true; |
916 | /* wiphy->regd will be set once the device has its own | ||
917 | * desired regulatory domain set */ | ||
918 | if (wiphy->strict_regulatory && !wiphy->regd && | ||
919 | !is_world_regdom(last_request->alpha2)) | ||
920 | return true; | ||
900 | return false; | 921 | return false; |
901 | } | 922 | } |
902 | 923 | ||
@@ -1155,10 +1176,15 @@ new_request: | |||
1155 | 1176 | ||
1156 | void regulatory_hint(struct wiphy *wiphy, const char *alpha2) | 1177 | void regulatory_hint(struct wiphy *wiphy, const char *alpha2) |
1157 | { | 1178 | { |
1179 | int r; | ||
1158 | BUG_ON(!alpha2); | 1180 | BUG_ON(!alpha2); |
1159 | 1181 | ||
1160 | mutex_lock(&cfg80211_drv_mutex); | 1182 | mutex_lock(&cfg80211_drv_mutex); |
1161 | __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, alpha2, 0, ENVIRON_ANY); | 1183 | r = __regulatory_hint(wiphy, REGDOM_SET_BY_DRIVER, |
1184 | alpha2, 0, ENVIRON_ANY); | ||
1185 | /* This is required so that the orig_* parameters are saved */ | ||
1186 | if (r == -EALREADY && wiphy->strict_regulatory) | ||
1187 | wiphy_update_regulatory(wiphy, REGDOM_SET_BY_DRIVER); | ||
1162 | mutex_unlock(&cfg80211_drv_mutex); | 1188 | mutex_unlock(&cfg80211_drv_mutex); |
1163 | } | 1189 | } |
1164 | EXPORT_SYMBOL(regulatory_hint); | 1190 | EXPORT_SYMBOL(regulatory_hint); |