|
@@ -847,22 +847,36 @@ static bool valid_regdb(const u8 *data, unsigned int size)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-static void set_wmm_rule(struct ieee80211_reg_rule *rrule,
|
|
|
- struct fwdb_wmm_rule *wmm)
|
|
|
-{
|
|
|
- struct ieee80211_wmm_rule *rule = &rrule->wmm_rule;
|
|
|
- unsigned int i;
|
|
|
+static void set_wmm_rule(const struct fwdb_header *db,
|
|
|
+ const struct fwdb_country *country,
|
|
|
+ const struct fwdb_rule *rule,
|
|
|
+ struct ieee80211_reg_rule *rrule)
|
|
|
+{
|
|
|
+ struct ieee80211_wmm_rule *wmm_rule = &rrule->wmm_rule;
|
|
|
+ struct fwdb_wmm_rule *wmm;
|
|
|
+ unsigned int i, wmm_ptr;
|
|
|
+
|
|
|
+ wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2;
|
|
|
+ wmm = (void *)((u8 *)db + wmm_ptr);
|
|
|
+
|
|
|
+ if (!valid_wmm(wmm)) {
|
|
|
+ pr_err("Invalid regulatory WMM rule %u-%u in domain %c%c\n",
|
|
|
+ be32_to_cpu(rule->start), be32_to_cpu(rule->end),
|
|
|
+ country->alpha2[0], country->alpha2[1]);
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
|
|
- rule->client[i].cw_min =
|
|
|
+ wmm_rule->client[i].cw_min =
|
|
|
ecw2cw((wmm->client[i].ecw & 0xf0) >> 4);
|
|
|
- rule->client[i].cw_max = ecw2cw(wmm->client[i].ecw & 0x0f);
|
|
|
- rule->client[i].aifsn = wmm->client[i].aifsn;
|
|
|
- rule->client[i].cot = 1000 * be16_to_cpu(wmm->client[i].cot);
|
|
|
- rule->ap[i].cw_min = ecw2cw((wmm->ap[i].ecw & 0xf0) >> 4);
|
|
|
- rule->ap[i].cw_max = ecw2cw(wmm->ap[i].ecw & 0x0f);
|
|
|
- rule->ap[i].aifsn = wmm->ap[i].aifsn;
|
|
|
- rule->ap[i].cot = 1000 * be16_to_cpu(wmm->ap[i].cot);
|
|
|
+ wmm_rule->client[i].cw_max = ecw2cw(wmm->client[i].ecw & 0x0f);
|
|
|
+ wmm_rule->client[i].aifsn = wmm->client[i].aifsn;
|
|
|
+ wmm_rule->client[i].cot =
|
|
|
+ 1000 * be16_to_cpu(wmm->client[i].cot);
|
|
|
+ wmm_rule->ap[i].cw_min = ecw2cw((wmm->ap[i].ecw & 0xf0) >> 4);
|
|
|
+ wmm_rule->ap[i].cw_max = ecw2cw(wmm->ap[i].ecw & 0x0f);
|
|
|
+ wmm_rule->ap[i].aifsn = wmm->ap[i].aifsn;
|
|
|
+ wmm_rule->ap[i].cot = 1000 * be16_to_cpu(wmm->ap[i].cot);
|
|
|
}
|
|
|
|
|
|
rrule->has_wmm = true;
|
|
@@ -870,7 +884,7 @@ static void set_wmm_rule(struct ieee80211_reg_rule *rrule,
|
|
|
|
|
|
static int __regdb_query_wmm(const struct fwdb_header *db,
|
|
|
const struct fwdb_country *country, int freq,
|
|
|
- struct ieee80211_reg_rule *rule)
|
|
|
+ struct ieee80211_reg_rule *rrule)
|
|
|
{
|
|
|
unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
|
|
|
struct fwdb_collection *coll = (void *)((u8 *)db + ptr);
|
|
@@ -879,18 +893,14 @@ static int __regdb_query_wmm(const struct fwdb_header *db,
|
|
|
for (i = 0; i < coll->n_rules; i++) {
|
|
|
__be16 *rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2));
|
|
|
unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2;
|
|
|
- struct fwdb_rule *rrule = (void *)((u8 *)db + rule_ptr);
|
|
|
- struct fwdb_wmm_rule *wmm;
|
|
|
- unsigned int wmm_ptr;
|
|
|
+ struct fwdb_rule *rule = (void *)((u8 *)db + rule_ptr);
|
|
|
|
|
|
- if (rrule->len < offsetofend(struct fwdb_rule, wmm_ptr))
|
|
|
+ if (rule->len < offsetofend(struct fwdb_rule, wmm_ptr))
|
|
|
continue;
|
|
|
|
|
|
- if (freq >= KHZ_TO_MHZ(be32_to_cpu(rrule->start)) &&
|
|
|
- freq <= KHZ_TO_MHZ(be32_to_cpu(rrule->end))) {
|
|
|
- wmm_ptr = be16_to_cpu(rrule->wmm_ptr) << 2;
|
|
|
- wmm = (void *)((u8 *)db + wmm_ptr);
|
|
|
- set_wmm_rule(rule, wmm);
|
|
|
+ if (freq >= KHZ_TO_MHZ(be32_to_cpu(rule->start)) &&
|
|
|
+ freq <= KHZ_TO_MHZ(be32_to_cpu(rule->end))) {
|
|
|
+ set_wmm_rule(db, country, rule, rrule);
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
@@ -972,12 +982,8 @@ static int regdb_query_country(const struct fwdb_header *db,
|
|
|
if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout))
|
|
|
rrule->dfs_cac_ms =
|
|
|
1000 * be16_to_cpu(rule->cac_timeout);
|
|
|
- if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr)) {
|
|
|
- u32 wmm_ptr = be16_to_cpu(rule->wmm_ptr) << 2;
|
|
|
- struct fwdb_wmm_rule *wmm = (void *)((u8 *)db + wmm_ptr);
|
|
|
-
|
|
|
- set_wmm_rule(rrule, wmm);
|
|
|
- }
|
|
|
+ if (rule->len >= offsetofend(struct fwdb_rule, wmm_ptr))
|
|
|
+ set_wmm_rule(db, country, rule, rrule);
|
|
|
}
|
|
|
|
|
|
return reg_schedule_apply(regdom);
|