Commit 2763bba6 authored by Haim Dreyfuss's avatar Haim Dreyfuss Committed by Luca Coelho

iwlwifi: Don't ignore the cap field upon mcc update

When receiving a new MCC driver get all the data about the new country
code and its regulatory information.
Mistakenly, we ignored the cap field, which includes global regulatory
information which should be applies to every channel.
Fix it.
Signed-off-by: default avatarHaim Dreyfuss <haim.dreyfuss@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent ed780545
...@@ -224,6 +224,34 @@ enum iwl_nvm_channel_flags { ...@@ -224,6 +224,34 @@ enum iwl_nvm_channel_flags {
NVM_CHANNEL_DC_HIGH = BIT(12), NVM_CHANNEL_DC_HIGH = BIT(12),
}; };
/**
* enum iwl_reg_capa_flags - global flags applied for the whole regulatory
* domain.
* @REG_CAPA_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the
* 2.4Ghz band is allowed.
* @REG_CAPA_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the
* 5Ghz band is allowed.
* @REG_CAPA_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
* @REG_CAPA_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
* for this regulatory domain (valid only in 5Ghz).
* @REG_CAPA_MCS_8_ALLOWED: 11ac with MCS 8 is allowed.
* @REG_CAPA_MCS_9_ALLOWED: 11ac with MCS 9 is allowed.
* @REG_CAPA_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden
* for this regulatory domain (valid only in 5Ghz).
* @REG_CAPA_DC_HIGH_ENABLED: DC HIGH allowed.
*/
enum iwl_reg_capa_flags {
REG_CAPA_BF_CCD_LOW_BAND = BIT(0),
REG_CAPA_BF_CCD_HIGH_BAND = BIT(1),
REG_CAPA_160MHZ_ALLOWED = BIT(2),
REG_CAPA_80MHZ_ALLOWED = BIT(3),
REG_CAPA_MCS_8_ALLOWED = BIT(4),
REG_CAPA_MCS_9_ALLOWED = BIT(5),
REG_CAPA_40MHZ_FORBIDDEN = BIT(7),
REG_CAPA_DC_HIGH_ENABLED = BIT(9),
};
static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
int chan, u32 flags) int chan, u32 flags)
{ {
...@@ -1038,6 +1066,7 @@ IWL_EXPORT_SYMBOL(iwl_parse_nvm_data); ...@@ -1038,6 +1066,7 @@ IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
int ch_idx, u16 nvm_flags, int ch_idx, u16 nvm_flags,
u16 cap_flags,
const struct iwl_cfg *cfg) const struct iwl_cfg *cfg)
{ {
u32 flags = NL80211_RRF_NO_HT40; u32 flags = NL80211_RRF_NO_HT40;
...@@ -1076,13 +1105,27 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan, ...@@ -1076,13 +1105,27 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
(flags & NL80211_RRF_NO_IR)) (flags & NL80211_RRF_NO_IR))
flags |= NL80211_RRF_GO_CONCURRENT; flags |= NL80211_RRF_GO_CONCURRENT;
/*
* cap_flags is per regulatory domain so apply it for every channel
*/
if (ch_idx >= NUM_2GHZ_CHANNELS) {
if (cap_flags & REG_CAPA_40MHZ_FORBIDDEN)
flags |= NL80211_RRF_NO_HT40;
if (!(cap_flags & REG_CAPA_80MHZ_ALLOWED))
flags |= NL80211_RRF_NO_80MHZ;
if (!(cap_flags & REG_CAPA_160MHZ_ALLOWED))
flags |= NL80211_RRF_NO_160MHZ;
}
return flags; return flags;
} }
struct ieee80211_regdomain * struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc, int num_of_ch, __le32 *channels, u16 fw_mcc,
u16 geo_info) u16 geo_info, u16 cap)
{ {
int ch_idx; int ch_idx;
u16 ch_flags; u16 ch_flags;
...@@ -1140,7 +1183,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, ...@@ -1140,7 +1183,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
} }
reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx, reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx,
ch_flags, cfg); ch_flags, cap,
cfg);
/* we can't continue the same rule */ /* we can't continue the same rule */
if (ch_idx == 0 || prev_reg_rule_flags != reg_rule_flags || if (ch_idx == 0 || prev_reg_rule_flags != reg_rule_flags ||
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* Copyright(c) 2008 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* *
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
...@@ -103,7 +103,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -103,7 +103,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
struct ieee80211_regdomain * struct ieee80211_regdomain *
iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int num_of_ch, __le32 *channels, u16 fw_mcc, int num_of_ch, __le32 *channels, u16 fw_mcc,
u16 geo_info); u16 geo_info, u16 cap);
/** /**
* struct iwl_nvm_section - describes an NVM section in memory. * struct iwl_nvm_section - describes an NVM section in memory.
......
...@@ -256,7 +256,8 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, ...@@ -256,7 +256,8 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,
__le32_to_cpu(resp->n_channels), __le32_to_cpu(resp->n_channels),
resp->channels, resp->channels,
__le16_to_cpu(resp->mcc), __le16_to_cpu(resp->mcc),
__le16_to_cpu(resp->geo_info)); __le16_to_cpu(resp->geo_info),
__le16_to_cpu(resp->cap));
/* Store the return source id */ /* Store the return source id */
src_id = resp->source_id; src_id = resp->source_id;
kfree(resp); kfree(resp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment