|
@@ -21,6 +21,8 @@
|
|
|
#include "regd.h"
|
|
|
#include "regd_common.h"
|
|
|
|
|
|
+static int __ath_regd_init(struct ath_regulatory *reg);
|
|
|
+
|
|
|
/*
|
|
|
* This is a set of common rules used by our world regulatory domains.
|
|
|
* We have 12 world regulatory domains. To save space we consolidate
|
|
@@ -347,10 +349,26 @@ static void ath_reg_apply_world_flags(struct wiphy *wiphy,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static u16 ath_regd_find_country_by_name(char *alpha2)
|
|
|
+{
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(allCountries); i++) {
|
|
|
+ if (!memcmp(allCountries[i].isoName, alpha2, 2))
|
|
|
+ return allCountries[i].countryCode;
|
|
|
+ }
|
|
|
+
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
int ath_reg_notifier_apply(struct wiphy *wiphy,
|
|
|
struct regulatory_request *request,
|
|
|
struct ath_regulatory *reg)
|
|
|
{
|
|
|
+ struct ath_common *common = container_of(reg, struct ath_common,
|
|
|
+ regulatory);
|
|
|
+ u16 country_code;
|
|
|
+
|
|
|
/* We always apply this */
|
|
|
ath_reg_apply_radar_flags(wiphy);
|
|
|
|
|
@@ -363,14 +381,37 @@ int ath_reg_notifier_apply(struct wiphy *wiphy,
|
|
|
return 0;
|
|
|
|
|
|
switch (request->initiator) {
|
|
|
- case NL80211_REGDOM_SET_BY_DRIVER:
|
|
|
case NL80211_REGDOM_SET_BY_CORE:
|
|
|
+ /*
|
|
|
+ * If common->reg_world_copy is world roaming it means we *were*
|
|
|
+ * world roaming... so we now have to restore that data.
|
|
|
+ */
|
|
|
+ if (!ath_is_world_regd(&common->reg_world_copy))
|
|
|
+ break;
|
|
|
+
|
|
|
+ memcpy(reg, &common->reg_world_copy,
|
|
|
+ sizeof(struct ath_regulatory));
|
|
|
+ break;
|
|
|
+ case NL80211_REGDOM_SET_BY_DRIVER:
|
|
|
case NL80211_REGDOM_SET_BY_USER:
|
|
|
break;
|
|
|
case NL80211_REGDOM_SET_BY_COUNTRY_IE:
|
|
|
- if (ath_is_world_regd(reg))
|
|
|
- ath_reg_apply_world_flags(wiphy, request->initiator,
|
|
|
- reg);
|
|
|
+ if (!ath_is_world_regd(reg))
|
|
|
+ break;
|
|
|
+
|
|
|
+ country_code = ath_regd_find_country_by_name(request->alpha2);
|
|
|
+ if (country_code == (u16) -1)
|
|
|
+ break;
|
|
|
+
|
|
|
+ reg->current_rd = COUNTRY_ERD_FLAG;
|
|
|
+ reg->current_rd |= country_code;
|
|
|
+
|
|
|
+ printk(KERN_DEBUG "ath: regdomain 0x%0x updated by CountryIE\n",
|
|
|
+ reg->current_rd);
|
|
|
+ __ath_regd_init(reg);
|
|
|
+
|
|
|
+ ath_reg_apply_world_flags(wiphy, request->initiator, reg);
|
|
|
+
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -588,12 +629,18 @@ ath_regd_init(struct ath_regulatory *reg,
|
|
|
int (*reg_notifier)(struct wiphy *wiphy,
|
|
|
struct regulatory_request *request))
|
|
|
{
|
|
|
+ struct ath_common *common = container_of(reg, struct ath_common,
|
|
|
+ regulatory);
|
|
|
int r;
|
|
|
|
|
|
r = __ath_regd_init(reg);
|
|
|
if (r)
|
|
|
return r;
|
|
|
|
|
|
+ if (ath_is_world_regd(reg))
|
|
|
+ memcpy(&common->reg_world_copy, reg,
|
|
|
+ sizeof(struct ath_regulatory));
|
|
|
+
|
|
|
ath_regd_init_wiphy(reg, wiphy, reg_notifier);
|
|
|
|
|
|
return 0;
|