* [PATCH 03/16] iwlwifi: add support for 6-7 GHz channels
From: Luca Coelho @ 2019-03-15 16:36 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Shaul Triebitz, Luca Coelho
In-Reply-To: <20190315163634.17315-1-luca@coelho.fi>
From: Shaul Triebitz <shaul.triebitz@intel.com>
Add UHB (ultra high band) channels and use 16 bit variables
to fit the new channels.
Signed-off-by: Shaul Triebitz <shaul.triebitz@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
.../net/wireless/intel/iwlwifi/cfg/22000.c | 2 +
.../net/wireless/intel/iwlwifi/iwl-config.h | 4 +-
.../wireless/intel/iwlwifi/iwl-nvm-parse.c | 74 +++++++++++--------
3 files changed, 49 insertions(+), 31 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
index fdc56f821b5a..dd781232c8a8 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -427,12 +427,14 @@ const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = {
const struct iwl_cfg iwlax210_2ax_cfg_so_gf_a0 = {
.name = "Intel(R) Wi-Fi 7 AX211 160MHz",
.fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE,
+ .uhb_supported = true,
IWL_DEVICE_AX210,
};
const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
.name = "Intel(R) Wi-Fi 7 AX210 160MHz",
.fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE,
+ .uhb_supported = true,
IWL_DEVICE_AX210,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index f5f87773667b..a68481d16f1f 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -383,6 +383,7 @@ struct iwl_csr_params {
* @bisr_workaround: BISR hardware workaround (for 22260 series devices)
* @min_txq_size: minimum number of slots required in a TX queue
* @umac_prph_offset: offset to add to UMAC periphery address
+ * @uhb_supported: ultra high band channels supported
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
@@ -433,7 +434,8 @@ struct iwl_cfg {
gen2:1,
cdb:1,
dbgc_supported:1,
- bisr_workaround:1;
+ bisr_workaround:1,
+ uhb_supported:1;
u8 valid_tx_ant;
u8 valid_rx_ant;
u8 non_shared_ant;
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
index 87d6de7efdd2..a20ac68f4ba3 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -130,7 +130,7 @@ enum nvm_sku_bits {
/*
* These are the channel numbers in the order that they are stored in the NVM
*/
-static const u8 iwl_nvm_channels[] = {
+static const u16 iwl_nvm_channels[] = {
/* 2.4 GHz */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 GHz */
@@ -139,7 +139,7 @@ static const u8 iwl_nvm_channels[] = {
149, 153, 157, 161, 165
};
-static const u8 iwl_ext_nvm_channels[] = {
+static const u16 iwl_ext_nvm_channels[] = {
/* 2.4 GHz */
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 GHz */
@@ -148,14 +148,27 @@ static const u8 iwl_ext_nvm_channels[] = {
149, 153, 157, 161, 165, 169, 173, 177, 181
};
+static const u16 iwl_uhb_nvm_channels[] = {
+ /* 2.4 GHz */
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ /* 5 GHz */
+ 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
+ 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
+ 149, 153, 157, 161, 165, 169, 173, 177, 181,
+ /* 6-7 GHz */
+ 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241,
+ 245, 249, 253, 257, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297,
+ 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353,
+ 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397, 401, 405, 409,
+ 413, 417, 421
+};
+
#define IWL_NVM_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
#define IWL_NVM_NUM_CHANNELS_EXT ARRAY_SIZE(iwl_ext_nvm_channels)
+#define IWL_NVM_NUM_CHANNELS_UHB ARRAY_SIZE(iwl_uhb_nvm_channels)
#define NUM_2GHZ_CHANNELS 14
-#define NUM_2GHZ_CHANNELS_EXT 14
#define FIRST_2GHZ_HT_MINUS 5
#define LAST_2GHZ_HT_PLUS 9
-#define LAST_5GHZ_HT 165
-#define LAST_5GHZ_HT_FAMILY_8000 181
#define N_HW_ADDR_MASK 0xF
/* rate data (static) */
@@ -247,17 +260,13 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz,
u16 nvm_flags, const struct iwl_cfg *cfg)
{
u32 flags = IEEE80211_CHAN_NO_HT40;
- u32 last_5ghz_ht = LAST_5GHZ_HT;
-
- if (cfg->nvm_type == IWL_NVM_EXT)
- last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) {
if (ch_num <= LAST_2GHZ_HT_PLUS)
flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
if (ch_num >= FIRST_2GHZ_HT_MINUS)
flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
- } else if (ch_num <= last_5ghz_ht && (nvm_flags & NVM_CHANNEL_40MHZ)) {
+ } else if (nvm_flags & NVM_CHANNEL_40MHZ) {
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
else
@@ -299,17 +308,18 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg,
int n_channels = 0;
struct ieee80211_channel *channel;
u16 ch_flags;
- int num_of_ch, num_2ghz_channels;
- const u8 *nvm_chan;
+ int num_of_ch, num_2ghz_channels = NUM_2GHZ_CHANNELS;
+ const u16 *nvm_chan;
- if (cfg->nvm_type != IWL_NVM_EXT) {
- num_of_ch = IWL_NVM_NUM_CHANNELS;
- nvm_chan = &iwl_nvm_channels[0];
- num_2ghz_channels = NUM_2GHZ_CHANNELS;
- } else {
+ if (cfg->uhb_supported) {
+ num_of_ch = IWL_NVM_NUM_CHANNELS_UHB;
+ nvm_chan = iwl_uhb_nvm_channels;
+ } else if (cfg->nvm_type == IWL_NVM_EXT) {
num_of_ch = IWL_NVM_NUM_CHANNELS_EXT;
- nvm_chan = &iwl_ext_nvm_channels[0];
- num_2ghz_channels = NUM_2GHZ_CHANNELS_EXT;
+ nvm_chan = iwl_ext_nvm_channels;
+ } else {
+ num_of_ch = IWL_NVM_NUM_CHANNELS;
+ nvm_chan = iwl_nvm_channels;
}
for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) {
@@ -1013,15 +1023,11 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
}
IWL_EXPORT_SYMBOL(iwl_parse_nvm_data);
-static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan,
+static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
int ch_idx, u16 nvm_flags,
const struct iwl_cfg *cfg)
{
u32 flags = NL80211_RRF_NO_HT40;
- u32 last_5ghz_ht = LAST_5GHZ_HT;
-
- if (cfg->nvm_type == IWL_NVM_EXT)
- last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000;
if (ch_idx < NUM_2GHZ_CHANNELS &&
(nvm_flags & NVM_CHANNEL_40MHZ)) {
@@ -1029,8 +1035,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan,
flags &= ~NL80211_RRF_NO_HT40PLUS;
if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS)
flags &= ~NL80211_RRF_NO_HT40MINUS;
- } else if (nvm_chan[ch_idx] <= last_5ghz_ht &&
- (nvm_flags & NVM_CHANNEL_40MHZ)) {
+ } else if (nvm_flags & NVM_CHANNEL_40MHZ) {
if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0)
flags &= ~NL80211_RRF_NO_HT40PLUS;
else
@@ -1074,8 +1079,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int ch_idx;
u16 ch_flags;
u32 reg_rule_flags, prev_reg_rule_flags = 0;
- const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ?
- iwl_ext_nvm_channels : iwl_nvm_channels;
+ const u16 *nvm_chan;
struct ieee80211_regdomain *regd, *copy_rd;
int size_of_regd, regd_to_copy;
struct ieee80211_reg_rule *rule;
@@ -1084,8 +1088,18 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
int center_freq, prev_center_freq = 0;
int valid_rules = 0;
bool new_rule;
- int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ?
- IWL_NVM_NUM_CHANNELS_EXT : IWL_NVM_NUM_CHANNELS;
+ int max_num_ch;
+
+ if (cfg->uhb_supported) {
+ max_num_ch = IWL_NVM_NUM_CHANNELS_UHB;
+ nvm_chan = iwl_uhb_nvm_channels;
+ } else if (cfg->nvm_type == IWL_NVM_EXT) {
+ max_num_ch = IWL_NVM_NUM_CHANNELS_EXT;
+ nvm_chan = iwl_ext_nvm_channels;
+ } else {
+ max_num_ch = IWL_NVM_NUM_CHANNELS;
+ nvm_chan = iwl_nvm_channels;
+ }
if (WARN_ON(num_of_ch > max_num_ch))
num_of_ch = max_num_ch;
--
2.20.1
^ permalink raw reply related
* [PATCH 02/16] iwlwifi: mvm: be more forgiving if num of channels is too big
From: Luca Coelho @ 2019-03-15 16:36 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Shaul Triebitz, Luca Coelho
In-Reply-To: <20190315163634.17315-1-luca@coelho.fi>
From: Shaul Triebitz <shaul.triebitz@intel.com>
If number of channels in the driver is greater than
number of scan channels given by firmware TLV, do not
fail scan config, but adjust to firmware's number of channels.
This is helpful for supporting in driver new channels before
it being supported by firmware scan.
Signed-off-by: Shaul Triebitz <shaul.triebitz@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 25 +++++++++++--------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 78694bc38e76..d9ddf9ff6428 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -1082,21 +1082,23 @@ static void iwl_mvm_fill_scan_dwell(struct iwl_mvm *mvm,
dwell->extended = IWL_SCAN_DWELL_EXTENDED;
}
-static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels)
+static void iwl_mvm_fill_channels(struct iwl_mvm *mvm, u8 *channels,
+ u32 max_channels)
{
struct ieee80211_supported_band *band;
int i, j = 0;
band = &mvm->nvm_data->bands[NL80211_BAND_2GHZ];
- for (i = 0; i < band->n_channels; i++, j++)
+ for (i = 0; i < band->n_channels && j < max_channels; i++, j++)
channels[j] = band->channels[i].hw_value;
band = &mvm->nvm_data->bands[NL80211_BAND_5GHZ];
- for (i = 0; i < band->n_channels; i++, j++)
+ for (i = 0; i < band->n_channels && j < max_channels; i++, j++)
channels[j] = band->channels[i].hw_value;
}
static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
- u32 flags, u8 channel_flags)
+ u32 flags, u8 channel_flags,
+ u32 max_channels)
{
enum iwl_mvm_scan_type type = iwl_mvm_get_scan_type(mvm, NULL);
struct iwl_scan_config_v1 *cfg = config;
@@ -1115,11 +1117,12 @@ static void iwl_mvm_fill_scan_config_v1(struct iwl_mvm *mvm, void *config,
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags;
- iwl_mvm_fill_channels(mvm, cfg->channel_array);
+ iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);
}
static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
- u32 flags, u8 channel_flags)
+ u32 flags, u8 channel_flags,
+ u32 max_channels)
{
struct iwl_scan_config *cfg = config;
@@ -1162,7 +1165,7 @@ static void iwl_mvm_fill_scan_config(struct iwl_mvm *mvm, void *config,
cfg->bcast_sta_id = mvm->aux_sta.sta_id;
cfg->channel_flags = channel_flags;
- iwl_mvm_fill_channels(mvm, cfg->channel_array);
+ iwl_mvm_fill_channels(mvm, cfg->channel_array, max_channels);
}
int iwl_mvm_config_scan(struct iwl_mvm *mvm)
@@ -1181,7 +1184,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
u8 channel_flags;
if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))
- return -ENOBUFS;
+ num_channels = mvm->fw->ucode_capa.n_scan_channels;
if (iwl_mvm_is_cdb_supported(mvm)) {
type = iwl_mvm_get_scan_type_band(mvm, NULL,
@@ -1234,9 +1237,11 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
flags |= (iwl_mvm_is_scan_fragmented(hb_type)) ?
SCAN_CONFIG_FLAG_SET_LMAC2_FRAGMENTED :
SCAN_CONFIG_FLAG_CLEAR_LMAC2_FRAGMENTED;
- iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags);
+ iwl_mvm_fill_scan_config(mvm, cfg, flags, channel_flags,
+ num_channels);
} else {
- iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags);
+ iwl_mvm_fill_scan_config_v1(mvm, cfg, flags, channel_flags,
+ num_channels);
}
cmd.data[0] = cfg;
--
2.20.1
^ permalink raw reply related
* [PATCH 01/16] iwlwifi: mvm: enable HT/VHT IBSS
From: Luca Coelho @ 2019-03-15 16:36 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Johannes Berg, Luca Coelho
In-Reply-To: <20190315163634.17315-1-luca@coelho.fi>
From: Johannes Berg <johannes.berg@intel.com>
For some reason we never enabled it, but it appears to work fine.
Enable it now.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index fd989c43df2a..dc4bff74c89c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -598,6 +598,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
BIT(NL80211_IFTYPE_ADHOC);
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
+ wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
+ hw->wiphy->features |= NL80211_FEATURE_HT_IBSS;
+
hw->wiphy->regulatory_flags |= REGULATORY_ENABLE_RELAX_NO_IR;
if (iwl_mvm_is_lar_supported(mvm))
hw->wiphy->regulatory_flags |= REGULATORY_WIPHY_SELF_MANAGED;
--
2.20.1
^ permalink raw reply related
* [PATCH 00/16] iwlwifi: updates intended for v5.1 2019-03-15
From: Luca Coelho @ 2019-03-15 16:36 UTC (permalink / raw)
To: kvalo; +Cc: linux-wireless, Luca Coelho
From: Luca Coelho <luciano.coelho@intel.com>
Hi,
Here's the second set of patches intended for v5.2. It's the usual
development, new features, cleanups and bugfixes.
The changes are:
* Continued work and bugfixes for the new debugging infra;
* Support for some new FW API versions;
* Some work to support new hardware;
* General bugfixes;
* Other cleanups;
As usual, I'm pushing this to a pending branch, for kbuild bot, and
will send a pull-request later.
Please review.
Cheers,
Luca.
Ilan Peer (1):
iwlwifi: mvm: Support new format of SCAN_OFFLOAD_PROFILES_QUERY_RSP
Johannes Berg (2):
iwlwifi: mvm: enable HT/VHT IBSS
iwlwifi: pcie: switch to correct RBD/CD layout for 22560
Luca Coelho (2):
mac80211_hwsim: make copying of ciphers safer by checking the length
iwlwifi: remove unnecessary goto out in iwl_parse_nvm_mcc_info()
Mordechay Goodstein (1):
iwlwifi: mvm: set max amsdu for TLC offload
Shahar S Matityahu (5):
iwlwifi: dbg: use dump mask for tx command dumping length
iwlwifi: mvm: use dump worker during restart instead of sync dump
iwlwifi: dbg: add DRAM monitor support for AX210 device family
iwlwifi: dbg_ini: separate between ini and legacy dump flows
iwlwifi: dbg_ini: align to FW api version 1
Shaul Triebitz (4):
iwlwifi: mvm: be more forgiving if num of channels is too big
iwlwifi: add support for 6-7 GHz channels
iwlwifi: support new NVM response API
iwlwifi: for AX210 device support radio GF4
YueHaibing (1):
iwlwifi: Use struct_size() in kzalloc
.../net/wireless/intel/iwlwifi/cfg/22000.c | 9 +
.../wireless/intel/iwlwifi/fw/api/dbg-tlv.h | 177 ++++++++++------
.../wireless/intel/iwlwifi/fw/api/nvm-reg.h | 39 +++-
.../net/wireless/intel/iwlwifi/fw/api/rx.h | 67 +------
.../net/wireless/intel/iwlwifi/fw/api/scan.h | 54 ++++-
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 189 ++++++++++--------
drivers/net/wireless/intel/iwlwifi/fw/dbg.h | 17 +-
.../wireless/intel/iwlwifi/fw/error-dump.h | 6 +-
drivers/net/wireless/intel/iwlwifi/fw/file.h | 7 +
.../net/wireless/intel/iwlwifi/fw/runtime.h | 1 +
.../net/wireless/intel/iwlwifi/iwl-config.h | 5 +-
drivers/net/wireless/intel/iwlwifi/iwl-csr.h | 5 +-
.../net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 10 +-
.../wireless/intel/iwlwifi/iwl-nvm-parse.c | 139 +++++++------
drivers/net/wireless/intel/iwlwifi/iwl-prph.h | 6 +
.../net/wireless/intel/iwlwifi/iwl-trans.h | 1 -
drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 90 +++++++--
.../net/wireless/intel/iwlwifi/mvm/debugfs.c | 2 +-
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 12 +-
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 13 --
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 2 +
.../net/wireless/intel/iwlwifi/mvm/rs-fw.c | 44 +++-
drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 25 ++-
.../wireless/intel/iwlwifi/pcie/internal.h | 30 +--
drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 13 +-
.../net/wireless/intel/iwlwifi/pcie/trans.c | 38 +++-
drivers/net/wireless/mac80211_hwsim.c | 12 +-
27 files changed, 628 insertions(+), 385 deletions(-)
--
2.20.1
^ permalink raw reply
* [PATCH 11/11] ieee80211: update HE IEs to D4.0 spec
From: Luca Coelho @ 2019-03-15 15:39 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Liad Kaufman, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Liad Kaufman <liad.kaufman@intel.com>
Update the out-dated comments as well, and have them point to
the correct sections in the D4.0 spec.
Signed-off-by: Liad Kaufman <liad.kaufman@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
include/linux/ieee80211.h | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 522881f31938..61f0a316c6ac 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1557,7 +1557,7 @@ struct ieee80211_vht_operation {
* struct ieee80211_he_cap_elem - HE capabilities element
*
* This structure is the "HE capabilities element" fixed fields as
- * described in P802.11ax_D3.0 section 9.4.2.237.2 and 9.4.2.237.3
+ * described in P802.11ax_D4.0 section 9.4.2.242.2 and 9.4.2.242.3
*/
struct ieee80211_he_cap_elem {
u8 mac_cap_info[6];
@@ -1619,12 +1619,12 @@ struct ieee80211_he_mcs_nss_supp {
* struct ieee80211_he_operation - HE capabilities element
*
* This structure is the "HE operation element" fields as
- * described in P802.11ax_D3.0 section 9.4.2.238
+ * described in P802.11ax_D4.0 section 9.4.2.243
*/
struct ieee80211_he_operation {
__le32 he_oper_params;
__le16 he_mcs_nss_set;
- /* Optional 0,1,3 or 4 bytes: depends on @he_oper_params */
+ /* Optional 0,1,3,4,5,7 or 8 bytes: depends on @he_oper_params */
u8 optional[0];
} __packed;
@@ -1632,7 +1632,7 @@ struct ieee80211_he_operation {
* struct ieee80211_he_mu_edca_param_ac_rec - MU AC Parameter Record field
*
* This structure is the "MU AC Parameter Record" fields as
- * described in P802.11ax_D2.0 section 9.4.2.240
+ * described in P802.11ax_D4.0 section 9.4.2.245
*/
struct ieee80211_he_mu_edca_param_ac_rec {
u8 aifsn;
@@ -1644,7 +1644,7 @@ struct ieee80211_he_mu_edca_param_ac_rec {
* struct ieee80211_mu_edca_param_set - MU EDCA Parameter Set element
*
* This structure is the "MU EDCA Parameter Set element" fields as
- * described in P802.11ax_D2.0 section 9.4.2.240
+ * described in P802.11ax_D4.0 section 9.4.2.245
*/
struct ieee80211_mu_edca_param_set {
u8 mu_qos_info;
@@ -2026,6 +2026,7 @@ ieee80211_he_ppe_size(u8 ppe_thres_hdr, const u8 *phy_cap_info)
#define IEEE80211_HE_OPERATION_VHT_OPER_INFO 0x00004000
#define IEEE80211_HE_OPERATION_CO_HOSTED_BSS 0x00008000
#define IEEE80211_HE_OPERATION_ER_SU_DISABLE 0x00010000
+#define IEEE80211_HE_OPERATION_6GHZ_OP_INFO 0x00020000
#define IEEE80211_HE_OPERATION_BSS_COLOR_MASK 0x3f000000
#define IEEE80211_HE_OPERATION_BSS_COLOR_OFFSET 24
#define IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR 0x40000000
@@ -2056,6 +2057,8 @@ ieee80211_he_oper_size(const u8 *he_oper_ie)
oper_len += 3;
if (he_oper_params & IEEE80211_HE_OPERATION_CO_HOSTED_BSS)
oper_len++;
+ if (he_oper_params & IEEE80211_HE_OPERATION_6GHZ_OP_INFO)
+ oper_len += 4;
/* Add the first byte (extension ID) to the total length */
oper_len++;
--
2.20.1
^ permalink raw reply related
* [PATCH 10/11] mac80211: support profile split between elements
From: Luca Coelho @ 2019-03-15 15:39 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sara Sharon, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Sara Sharon <sara.sharon@intel.com>
Since an element is limited to 255 octets, a profile may be split
split to several elements. Support the split as defined in the 11ax
draft 3.
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
net/mac80211/ieee80211_i.h | 1 -
net/mac80211/util.c | 56 +++++++++++++++++++++++++-------------
2 files changed, 37 insertions(+), 20 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index e170f986d226..c5708f8a7401 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1505,7 +1505,6 @@ struct ieee802_11_elems {
const struct ieee80211_bss_max_idle_period_ie *max_idle_period_ie;
const struct ieee80211_multiple_bssid_configuration *mbssid_config_ie;
const struct ieee80211_bssid_index *bssid_index;
- const u8 *nontransmitted_bssid_profile;
u8 max_bssid_indicator;
u8 dtim_count;
u8 dtim_period;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 08197afdb7b3..99dd58454592 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1254,15 +1254,18 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
return crc;
}
-static void ieee802_11_find_bssid_profile(const u8 *start, size_t len,
- struct ieee802_11_elems *elems,
- u8 *transmitter_bssid,
- u8 *bss_bssid)
+static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len,
+ struct ieee802_11_elems *elems,
+ u8 *transmitter_bssid,
+ u8 *bss_bssid,
+ u8 **nontransmitted_profile)
{
const struct element *elem, *sub;
+ size_t profile_len = 0;
+ bool found = false;
if (!bss_bssid || !transmitter_bssid)
- return;
+ return profile_len;
for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) {
if (elem->datalen < 2)
@@ -1287,9 +1290,17 @@ static void ieee802_11_find_bssid_profile(const u8 *start, size_t len,
continue;
}
+ memset(*nontransmitted_profile, 0, len);
+ profile_len = cfg80211_merge_profile(start, len,
+ elem,
+ sub,
+ nontransmitted_profile,
+ len);
+
/* found a Nontransmitted BSSID Profile */
index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
- sub->data, sub->datalen);
+ *nontransmitted_profile,
+ profile_len);
if (!index || index[1] < 1 || index[2] == 0) {
/* Invalid MBSSID Index element */
continue;
@@ -1300,14 +1311,15 @@ static void ieee802_11_find_bssid_profile(const u8 *start, size_t len,
index[2],
new_bssid);
if (ether_addr_equal(new_bssid, bss_bssid)) {
- elems->nontransmitted_bssid_profile =
- elem->data;
+ found = true;
elems->bssid_index_len = index[1];
elems->bssid_index = (void *)&index[2];
break;
}
}
}
+
+ return found ? profile_len : 0;
}
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
@@ -1316,30 +1328,34 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
u8 *bss_bssid)
{
const struct element *non_inherit = NULL;
+ u8 *nontransmitted_profile;
+ int nontransmitted_profile_len = 0;
memset(elems, 0, sizeof(*elems));
elems->ie_start = start;
elems->total_len = len;
- ieee802_11_find_bssid_profile(start, len, elems, transmitter_bssid,
- bss_bssid);
-
- if (elems->nontransmitted_bssid_profile)
+ nontransmitted_profile = kmalloc(len, GFP_ATOMIC);
+ if (nontransmitted_profile) {
+ nontransmitted_profile_len =
+ ieee802_11_find_bssid_profile(start, len, elems,
+ transmitter_bssid,
+ bss_bssid,
+ &nontransmitted_profile);
non_inherit =
cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
- &elems->nontransmitted_bssid_profile[2],
- elems->nontransmitted_bssid_profile[1]);
+ nontransmitted_profile,
+ nontransmitted_profile_len);
+ }
crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter,
crc, non_inherit);
/* Override with nontransmitted profile, if found */
- if (transmitter_bssid && elems->nontransmitted_bssid_profile) {
- const u8 *profile = elems->nontransmitted_bssid_profile;
-
- _ieee802_11_parse_elems_crc(&profile[2], profile[1],
+ if (nontransmitted_profile_len)
+ _ieee802_11_parse_elems_crc(nontransmitted_profile,
+ nontransmitted_profile_len,
action, elems, 0, 0, NULL);
- }
if (elems->tim && !elems->parse_error) {
const struct ieee80211_tim_ie *tim_ie = elems->tim;
@@ -1359,6 +1375,8 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
offsetofend(struct ieee80211_bssid_index, dtim_count))
elems->dtim_count = elems->bssid_index->dtim_count;
+ kfree(nontransmitted_profile);
+
return crc;
}
--
2.20.1
^ permalink raw reply related
* [PATCH 08/11] mac80211: support non-inheritance element
From: Luca Coelho @ 2019-03-15 15:39 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sara Sharon, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Sara Sharon <sara.sharon@intel.com>
Subelement profile may specify element IDs it doesn't inherit
from the management frame. Support it.
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
net/mac80211/util.c | 134 +++++++++++++++++++++++++-------------------
1 file changed, 77 insertions(+), 57 deletions(-)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 4c1655972565..08197afdb7b3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -894,10 +894,10 @@ EXPORT_SYMBOL(ieee80211_queue_delayed_work);
static u32
_ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems,
- u64 filter, u32 crc, u8 *transmitter_bssid,
- u8 *bss_bssid)
+ u64 filter, u32 crc,
+ const struct element *check_inherit)
{
- const struct element *elem, *sub;
+ const struct element *elem;
bool calc_crc = filter != 0;
DECLARE_BITMAP(seen_elems, 256);
const u8 *ie;
@@ -910,6 +910,11 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
u8 elen = elem->datalen;
const u8 *pos = elem->data;
+ if (check_inherit &&
+ !cfg80211_is_element_inherited(elem,
+ check_inherit))
+ continue;
+
switch (id) {
case WLAN_EID_SSID:
case WLAN_EID_SUPP_RATES:
@@ -1208,57 +1213,6 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
if (elen >= sizeof(*elems->max_idle_period_ie))
elems->max_idle_period_ie = (void *)pos;
break;
- case WLAN_EID_MULTIPLE_BSSID:
- if (!bss_bssid || !transmitter_bssid || elen < 4)
- break;
-
- elems->max_bssid_indicator = pos[0];
-
- for_each_element(sub, pos + 1, elen - 1) {
- u8 sub_len = sub->datalen;
- u8 new_bssid[ETH_ALEN];
- const u8 *index;
-
- /*
- * we only expect the "non-transmitted BSSID
- * profile" subelement (subelement id 0)
- */
- if (sub->id != 0 || sub->datalen < 4) {
- /* not a valid BSS profile */
- continue;
- }
-
- if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
- sub->data[1] != 2) {
- /* The first element of the
- * Nontransmitted BSSID Profile is not
- * the Nontransmitted BSSID Capability
- * element.
- */
- continue;
- }
-
- /* found a Nontransmitted BSSID Profile */
- index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
- sub->data, sub_len);
- if (!index || index[1] < 1 || index[2] == 0) {
- /* Invalid MBSSID Index element */
- continue;
- }
-
- cfg80211_gen_new_bssid(transmitter_bssid,
- pos[0],
- index[2],
- new_bssid);
- if (ether_addr_equal(new_bssid, bss_bssid)) {
- elems->nontransmitted_bssid_profile =
- (void *)sub;
- elems->bssid_index_len = index[1];
- elems->bssid_index = (void *)&index[2];
- break;
- }
- }
- break;
case WLAN_EID_EXTENSION:
if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
@@ -1300,25 +1254,91 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
return crc;
}
+static void ieee802_11_find_bssid_profile(const u8 *start, size_t len,
+ struct ieee802_11_elems *elems,
+ u8 *transmitter_bssid,
+ u8 *bss_bssid)
+{
+ const struct element *elem, *sub;
+
+ if (!bss_bssid || !transmitter_bssid)
+ return;
+
+ for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) {
+ if (elem->datalen < 2)
+ continue;
+
+ for_each_element(sub, elem->data + 1, elem->datalen - 1) {
+ u8 new_bssid[ETH_ALEN];
+ const u8 *index;
+
+ if (sub->id != 0 || sub->datalen < 4) {
+ /* not a valid BSS profile */
+ continue;
+ }
+
+ if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
+ sub->data[1] != 2) {
+ /* The first element of the
+ * Nontransmitted BSSID Profile is not
+ * the Nontransmitted BSSID Capability
+ * element.
+ */
+ continue;
+ }
+
+ /* found a Nontransmitted BSSID Profile */
+ index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
+ sub->data, sub->datalen);
+ if (!index || index[1] < 1 || index[2] == 0) {
+ /* Invalid MBSSID Index element */
+ continue;
+ }
+
+ cfg80211_gen_new_bssid(transmitter_bssid,
+ elem->data[0],
+ index[2],
+ new_bssid);
+ if (ether_addr_equal(new_bssid, bss_bssid)) {
+ elems->nontransmitted_bssid_profile =
+ elem->data;
+ elems->bssid_index_len = index[1];
+ elems->bssid_index = (void *)&index[2];
+ break;
+ }
+ }
+ }
+}
+
u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
struct ieee802_11_elems *elems,
u64 filter, u32 crc, u8 *transmitter_bssid,
u8 *bss_bssid)
{
+ const struct element *non_inherit = NULL;
+
memset(elems, 0, sizeof(*elems));
elems->ie_start = start;
elems->total_len = len;
+ ieee802_11_find_bssid_profile(start, len, elems, transmitter_bssid,
+ bss_bssid);
+
+ if (elems->nontransmitted_bssid_profile)
+ non_inherit =
+ cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
+ &elems->nontransmitted_bssid_profile[2],
+ elems->nontransmitted_bssid_profile[1]);
+
crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter,
- crc, transmitter_bssid, bss_bssid);
+ crc, non_inherit);
/* Override with nontransmitted profile, if found */
if (transmitter_bssid && elems->nontransmitted_bssid_profile) {
const u8 *profile = elems->nontransmitted_bssid_profile;
_ieee802_11_parse_elems_crc(&profile[2], profile[1],
- action, elems, 0, 0,
- transmitter_bssid, bss_bssid);
+ action, elems, 0, 0, NULL);
}
if (elems->tim && !elems->parse_error) {
--
2.20.1
^ permalink raw reply related
* [PATCH 09/11] cfg80211: support profile split between elements
From: Luca Coelho @ 2019-03-15 15:39 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sara Sharon, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Sara Sharon <sara.sharon@intel.com>
Since an element is limited to 255 octets, a profile may be split
split to several elements. Support the split as defined in the 11ax
draft 3. Detect legacy split and print a net-rate limited warning,
since there is no ROI in supporting this probably non-existent
split.
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
include/net/cfg80211.h | 14 ++++++
net/wireless/scan.c | 109 ++++++++++++++++++++++++++++++++++++++---
2 files changed, 117 insertions(+), 6 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index cd47b7085f59..f192c65fe9b4 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5499,6 +5499,20 @@ static inline void cfg80211_gen_new_bssid(const u8 *bssid, u8 max_bssid,
bool cfg80211_is_element_inherited(const struct element *element,
const struct element *non_inherit_element);
+/**
+ * cfg80211_merge_profile - merges a MBSSID profile if it is split between IEs
+ * @ie: ies
+ * @ielen: length of IEs
+ * @mbssid_elem: current MBSSID element
+ * @sub_elem: current MBSSID subelement (profile)
+ * @merged_ie: location of the merged profile
+ * @max_copy_len: max merged profile length
+ */
+size_t cfg80211_merge_profile(const u8 *ie, size_t ielen,
+ const struct element *mbssid_elem,
+ const struct element *sub_elem,
+ u8 **merged_ie, size_t max_copy_len);
+
/**
* enum cfg80211_bss_frame_type - frame type that the BSS data came from
* @CFG80211_BSS_FTYPE_UNKNOWN: driver doesn't know whether the data is
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index bda9114ded77..878c867f3f7d 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1456,6 +1456,78 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy,
return &res->pub;
}
+static const struct element
+*cfg80211_get_profile_continuation(const u8 *ie, size_t ielen,
+ const struct element *mbssid_elem,
+ const struct element *sub_elem)
+{
+ const u8 *mbssid_end = mbssid_elem->data + mbssid_elem->datalen;
+ const struct element *next_mbssid;
+ const struct element *next_sub;
+
+ next_mbssid = cfg80211_find_elem(WLAN_EID_MULTIPLE_BSSID,
+ mbssid_end,
+ ielen - (mbssid_end - ie));
+
+ /*
+ * If is is not the last subelement in current MBSSID IE or there isn't
+ * a next MBSSID IE - profile is complete.
+ */
+ if ((sub_elem->data + sub_elem->datalen < mbssid_end - 1) ||
+ !next_mbssid)
+ return NULL;
+
+ /* For any length error, just return NULL */
+
+ if (next_mbssid->datalen < 4)
+ return NULL;
+
+ next_sub = (void *)&next_mbssid->data[1];
+
+ if (next_mbssid->data + next_mbssid->datalen <
+ next_sub->data + next_sub->datalen)
+ return NULL;
+
+ if (next_sub->id != 0 || next_sub->datalen < 2)
+ return NULL;
+
+ /*
+ * Check if the first element in the next sub element is a start
+ * of a new profile
+ */
+ return next_sub->data[0] == WLAN_EID_NON_TX_BSSID_CAP ?
+ NULL : next_mbssid;
+}
+
+size_t cfg80211_merge_profile(const u8 *ie, size_t ielen,
+ const struct element *mbssid_elem,
+ const struct element *sub_elem,
+ u8 **merged_ie, size_t max_copy_len)
+{
+ size_t copied_len = sub_elem->datalen;
+ const struct element *next_mbssid;
+
+ if (sub_elem->datalen > max_copy_len)
+ return 0;
+
+ memcpy(*merged_ie, sub_elem->data, sub_elem->datalen);
+
+ while ((next_mbssid = cfg80211_get_profile_continuation(ie, ielen,
+ mbssid_elem,
+ sub_elem))) {
+ const struct element *next_sub = (void *)&next_mbssid->data[1];
+
+ if (copied_len + next_sub->datalen > max_copy_len)
+ break;
+ memcpy(*merged_ie + copied_len, next_sub->data,
+ next_sub->datalen);
+ copied_len += next_sub->datalen;
+ }
+
+ return copied_len;
+}
+EXPORT_SYMBOL(cfg80211_merge_profile);
+
static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
struct cfg80211_inform_bss *data,
enum cfg80211_bss_frame_type ftype,
@@ -1469,7 +1541,8 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
const struct element *elem, *sub;
size_t new_ie_len;
u8 new_bssid[ETH_ALEN];
- u8 *new_ie;
+ u8 *new_ie, *profile;
+ u64 seen_indices = 0;
u16 capability;
struct cfg80211_bss *bss;
@@ -1487,10 +1560,16 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
if (!new_ie)
return;
+ profile = kmalloc(ielen, gfp);
+ if (!profile)
+ goto out;
+
for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ie, ielen) {
if (elem->datalen < 4)
continue;
for_each_element(sub, elem->data + 1, elem->datalen - 1) {
+ u8 profile_len;
+
if (sub->id != 0 || sub->datalen < 4) {
/* not a valid BSS profile */
continue;
@@ -1505,16 +1584,31 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
continue;
}
+ memset(profile, 0, ielen);
+ profile_len = cfg80211_merge_profile(ie, ielen,
+ elem,
+ sub,
+ &profile,
+ ielen);
+
/* found a Nontransmitted BSSID Profile */
mbssid_index_ie = cfg80211_find_ie
(WLAN_EID_MULTI_BSSID_IDX,
- sub->data, sub->datalen);
+ profile, profile_len);
if (!mbssid_index_ie || mbssid_index_ie[1] < 1 ||
- mbssid_index_ie[2] == 0) {
+ mbssid_index_ie[2] == 0 ||
+ mbssid_index_ie[2] > 46) {
/* No valid Multiple BSSID-Index element */
continue;
}
+ if (seen_indices & BIT(mbssid_index_ie[2]))
+ /* We don't support legacy split of a profile */
+ net_dbg_ratelimited("Partial info for BSSID index %d\n",
+ mbssid_index_ie[2]);
+
+ seen_indices |= BIT(mbssid_index_ie[2]);
+
non_tx_data->bssid_index = mbssid_index_ie[2];
non_tx_data->max_bssid_indicator = elem->data[0];
@@ -1523,13 +1617,14 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
non_tx_data->bssid_index,
new_bssid);
memset(new_ie, 0, IEEE80211_MAX_DATA_LEN);
- new_ie_len = cfg80211_gen_new_ie(ie, ielen, sub->data,
- sub->datalen, new_ie,
+ new_ie_len = cfg80211_gen_new_ie(ie, ielen,
+ profile,
+ profile_len, new_ie,
gfp);
if (!new_ie_len)
continue;
- capability = get_unaligned_le16(sub->data + 2);
+ capability = get_unaligned_le16(profile + 2);
bss = cfg80211_inform_single_bss_data(wiphy, data,
ftype,
new_bssid, tsf,
@@ -1545,7 +1640,9 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy,
}
}
+out:
kfree(new_ie);
+ kfree(profile);
}
struct cfg80211_bss *
--
2.20.1
^ permalink raw reply related
* [PATCH 07/11] cfg80211: support non-inheritance element
From: Luca Coelho @ 2019-03-15 15:39 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sara Sharon, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Sara Sharon <sara.sharon@intel.com>
Subelement profile may specify element IDs it doesn't inherit
from the management frame. Support it.
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
include/linux/ieee80211.h | 1 +
include/net/cfg80211.h | 8 +++++
net/wireless/scan.c | 61 ++++++++++++++++++++++++++++++++++++++-
3 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 48703ec60d06..522881f31938 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2487,6 +2487,7 @@ enum ieee80211_eid_ext {
WLAN_EID_EXT_HE_MU_EDCA = 38,
WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME = 52,
WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION = 55,
+ WLAN_EID_EXT_NON_INHERITANCE = 56,
};
/* Action category code */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bb307a11ee63..cd47b7085f59 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5491,6 +5491,14 @@ static inline void cfg80211_gen_new_bssid(const u8 *bssid, u8 max_bssid,
u64_to_ether_addr(new_bssid_u64, new_bssid);
}
+/**
+ * cfg80211_is_element_inherited - returns if element ID should be inherited
+ * @element: element to check
+ * @non_inherit_element: non inheritance element
+ */
+bool cfg80211_is_element_inherited(const struct element *element,
+ const struct element *non_inherit_element);
+
/**
* enum cfg80211_bss_frame_type - frame type that the BSS data came from
* @CFG80211_BSS_FTYPE_UNKNOWN: driver doesn't know whether the data is
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 49f700a1460b..bda9114ded77 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -179,12 +179,63 @@ static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *rdev,
return true;
}
+bool cfg80211_is_element_inherited(const struct element *elem,
+ const struct element *non_inherit_elem)
+{
+ u8 id_len, ext_id_len, i, loop_len, id;
+ const u8 *list;
+
+ if (elem->id == WLAN_EID_MULTIPLE_BSSID)
+ return false;
+
+ if (!non_inherit_elem || non_inherit_elem->datalen < 2)
+ return true;
+
+ /*
+ * non inheritance element format is:
+ * ext ID (56) | IDs list len | list | extension IDs list len | list
+ * Both lists are optional. Both lengths are mandatory.
+ * This means valid length is:
+ * elem_len = 1 (extension ID) + 2 (list len fields) + list lengths
+ */
+ id_len = non_inherit_elem->data[1];
+ if (non_inherit_elem->datalen < 3 + id_len)
+ return true;
+
+ ext_id_len = non_inherit_elem->data[2 + id_len];
+ if (non_inherit_elem->datalen < 3 + id_len + ext_id_len)
+ return true;
+
+ if (elem->id == WLAN_EID_EXTENSION) {
+ if (!ext_id_len)
+ return true;
+ loop_len = ext_id_len;
+ list = &non_inherit_elem->data[3 + id_len];
+ id = elem->data[0];
+ } else {
+ if (!id_len)
+ return true;
+ loop_len = id_len;
+ list = &non_inherit_elem->data[2];
+ id = elem->id;
+ }
+
+ for (i = 0; i < loop_len; i++) {
+ if (list[i] == id)
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(cfg80211_is_element_inherited);
+
static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
const u8 *subelement, size_t subie_len,
u8 *new_ie, gfp_t gfp)
{
u8 *pos, *tmp;
const u8 *tmp_old, *tmp_new;
+ const struct element *non_inherit_elem;
u8 *sub_copy;
/* copy subelement as we need to change its content to
@@ -204,6 +255,11 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
pos += (tmp_new[1] + 2);
}
+ /* get non inheritance list if exists */
+ non_inherit_elem =
+ cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
+ sub_copy, subie_len);
+
/* go through IEs in ie (skip SSID) and subelement,
* merge them into new_ie
*/
@@ -224,8 +280,11 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
subie_len);
if (!tmp) {
+ const struct element *old_elem = (void *)tmp_old;
+
/* ie in old ie but not in subelement */
- if (tmp_old[0] != WLAN_EID_MULTIPLE_BSSID) {
+ if (cfg80211_is_element_inherited(old_elem,
+ non_inherit_elem)) {
memcpy(pos, tmp_old, tmp_old[1] + 2);
pos += tmp_old[1] + 2;
}
--
2.20.1
^ permalink raw reply related
* [PATCH 06/11] cfg80211: don't skip multi-bssid index element
From: Luca Coelho @ 2019-03-15 15:39 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Sara Sharon, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Sara Sharon <sara.sharon@intel.com>
When creating the IEs for the nontransmitted BSS, the index
element is skipped. However, we need to get DTIM values from
it, so don't skip it.
Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
net/wireless/scan.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 287518c6caa4..49f700a1460b 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -269,8 +269,7 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen,
tmp_new = sub_copy;
while (tmp_new + tmp_new[1] + 2 - sub_copy <= subie_len) {
if (!(tmp_new[0] == WLAN_EID_NON_TX_BSSID_CAP ||
- tmp_new[0] == WLAN_EID_SSID ||
- tmp_new[0] == WLAN_EID_MULTI_BSSID_IDX)) {
+ tmp_new[0] == WLAN_EID_SSID)) {
memcpy(pos, tmp_new, tmp_new[1] + 2);
pos += tmp_new[1] + 2;
}
--
2.20.1
^ permalink raw reply related
* [PATCH 05/11] mac80211_hwsim: set p2p device interface support indication
From: Luca Coelho @ 2019-03-15 15:39 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Avraham Stern, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Avraham Stern <avraham.stern@intel.com>
P2P device interface type was not indicated in the supported
interface types even when hwsim was configured with p2p device
support. Fix it.
Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
drivers/net/wireless/mac80211_hwsim.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 0838af04d681..d79f3ee2a741 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -3894,6 +3894,8 @@ static int __init init_mac80211_hwsim(void)
param.p2p_device = support_p2p_device;
param.use_chanctx = channels > 1;
param.iftypes = HWSIM_IFTYPE_SUPPORT_MASK;
+ if (param.p2p_device)
+ param.iftypes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
err = mac80211_hwsim_new_radio(NULL, ¶m);
if (err < 0)
--
2.20.1
^ permalink raw reply related
* [PATCH 01/11] mac80211: Increase MAX_MSG_LEN
From: Luca Coelho @ 2019-03-15 15:38 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Andrei Otcheretianski, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Looks that 100 chars isn't enough for messages, as we keep getting
warnings popping from different places due to message shortening.
Instead of trying to shorten the prints, just increase the buffer size.
Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
net/mac80211/trace_msg.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/trace_msg.h b/net/mac80211/trace_msg.h
index 366b9e6f043e..40141df09f25 100644
--- a/net/mac80211/trace_msg.h
+++ b/net/mac80211/trace_msg.h
@@ -1,4 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Portions of this file
+ * Copyright (C) 2019 Intel Corporation
+ */
+
#ifdef CONFIG_MAC80211_MESSAGE_TRACING
#if !defined(__MAC80211_MSG_DRIVER_TRACE) || defined(TRACE_HEADER_MULTI_READ)
@@ -11,7 +16,7 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mac80211_msg
-#define MAX_MSG_LEN 100
+#define MAX_MSG_LEN 120
DECLARE_EVENT_CLASS(mac80211_msg_event,
TP_PROTO(struct va_format *vaf),
--
2.20.1
^ permalink raw reply related
* [PATCH 02/11] nl80211: increase NL80211_MAX_SUPP_REG_RULES
From: Luca Coelho @ 2019-03-15 15:38 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Shaul Triebitz, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Shaul Triebitz <shaul.triebitz@intel.com>
The iwlwifi driver creates one rule per channel, thus it needs more
rules than normal. To solve this, increase NL80211_MAX_SUPP_REG_RULES
so iwlwifi can also fit UHB (ultra high band) channels.
Signed-off-by: Shaul Triebitz <shaul.triebitz@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
include/uapi/linux/nl80211.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index dd4f86ee286e..f04f407b14c5 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -11,7 +11,7 @@
* Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
* Copyright 2008 Colin McCabe <colin@cozybit.com>
* Copyright 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -2802,7 +2802,7 @@ enum nl80211_attrs {
#define NL80211_MAX_SUPP_RATES 32
#define NL80211_MAX_SUPP_HT_RATES 77
-#define NL80211_MAX_SUPP_REG_RULES 64
+#define NL80211_MAX_SUPP_REG_RULES 128
#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0
#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16
#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24
--
2.20.1
^ permalink raw reply related
* [PATCH 04/11] cfg80211: Handle WMM rules in regulatory domain intersection
From: Luca Coelho @ 2019-03-15 15:39 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Ilan Peer, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Ilan Peer <ilan.peer@intel.com>
The support added for regulatory WMM rules did not handle
the case of regulatory domain intersections. Fix it.
Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Fixes: 230ebaa189af ("cfg80211: read wmm rules from regulatory database")
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
net/wireless/reg.c | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2f1bf91eb226..0ba778f371cb 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1309,6 +1309,16 @@ reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1,
return dfs_region1;
}
+static void reg_wmm_rules_intersect(const struct ieee80211_wmm_ac *wmm_ac1,
+ const struct ieee80211_wmm_ac *wmm_ac2,
+ struct ieee80211_wmm_ac *intersect)
+{
+ intersect->cw_min = max_t(u16, wmm_ac1->cw_min, wmm_ac2->cw_min);
+ intersect->cw_max = max_t(u16, wmm_ac1->cw_max, wmm_ac2->cw_max);
+ intersect->cot = min_t(u16, wmm_ac1->cot, wmm_ac2->cot);
+ intersect->aifsn = max_t(u8, wmm_ac1->aifsn, wmm_ac2->aifsn);
+}
+
/*
* Helper for regdom_intersect(), this does the real
* mathematical intersection fun
@@ -1323,6 +1333,8 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
struct ieee80211_freq_range *freq_range;
const struct ieee80211_power_rule *power_rule1, *power_rule2;
struct ieee80211_power_rule *power_rule;
+ const struct ieee80211_wmm_rule *wmm_rule1, *wmm_rule2;
+ struct ieee80211_wmm_rule *wmm_rule;
u32 freq_diff, max_bandwidth1, max_bandwidth2;
freq_range1 = &rule1->freq_range;
@@ -1333,6 +1345,10 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
power_rule2 = &rule2->power_rule;
power_rule = &intersected_rule->power_rule;
+ wmm_rule1 = &rule1->wmm_rule;
+ wmm_rule2 = &rule2->wmm_rule;
+ wmm_rule = &intersected_rule->wmm_rule;
+
freq_range->start_freq_khz = max(freq_range1->start_freq_khz,
freq_range2->start_freq_khz);
freq_range->end_freq_khz = min(freq_range1->end_freq_khz,
@@ -1376,6 +1392,29 @@ static int reg_rules_intersect(const struct ieee80211_regdomain *rd1,
intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms,
rule2->dfs_cac_ms);
+ if (rule1->has_wmm && rule2->has_wmm) {
+ u8 ac;
+
+ for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+ reg_wmm_rules_intersect(&wmm_rule1->client[ac],
+ &wmm_rule2->client[ac],
+ &wmm_rule->client[ac]);
+ reg_wmm_rules_intersect(&wmm_rule1->ap[ac],
+ &wmm_rule2->ap[ac],
+ &wmm_rule->ap[ac]);
+ }
+
+ intersected_rule->has_wmm = true;
+ } else if (rule1->has_wmm) {
+ *wmm_rule = *wmm_rule1;
+ intersected_rule->has_wmm = true;
+ } else if (rule2->has_wmm) {
+ *wmm_rule = *wmm_rule2;
+ intersected_rule->has_wmm = true;
+ } else {
+ intersected_rule->has_wmm = false;
+ }
+
if (!is_valid_reg_rule(intersected_rule))
return -EINVAL;
--
2.20.1
^ permalink raw reply related
* [PATCH 00/11] cfg80211/mac80211 patches from our internal tree 2019-03-15
From: Luca Coelho @ 2019-03-15 15:38 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Luca Coelho
From: Luca Coelho <luciano.coelho@intel.com>
Hi,
Some patches with mac80211 and cfg80211 changes from our internal
tree.
Please review, though you have already reviewed most if not all of
them ;)
Cheers,
Luca.
Andrei Otcheretianski (1):
mac80211: Increase MAX_MSG_LEN
Avraham Stern (1):
mac80211_hwsim: set p2p device interface support indication
Ilan Peer (1):
cfg80211: Handle WMM rules in regulatory domain intersection
Liad Kaufman (1):
ieee80211: update HE IEs to D4.0 spec
Luca Coelho (1):
nl80211: copy the length of dst of src in
nl80211_notify_radar_detection()
Sara Sharon (5):
cfg80211: don't skip multi-bssid index element
cfg80211: support non-inheritance element
mac80211: support non-inheritance element
cfg80211: support profile split between elements
mac80211: support profile split between elements
Shaul Triebitz (1):
nl80211: increase NL80211_MAX_SUPP_REG_RULES
drivers/net/wireless/mac80211_hwsim.c | 2 +
include/linux/ieee80211.h | 14 ++-
include/net/cfg80211.h | 22 ++++
include/uapi/linux/nl80211.h | 4 +-
net/mac80211/ieee80211_i.h | 1 -
net/mac80211/trace_msg.h | 7 +-
net/mac80211/util.c | 162 +++++++++++++++---------
net/wireless/nl80211.c | 2 +-
net/wireless/reg.c | 39 ++++++
net/wireless/scan.c | 173 ++++++++++++++++++++++++--
10 files changed, 345 insertions(+), 81 deletions(-)
--
2.20.1
^ permalink raw reply
* [PATCH 03/11] nl80211: copy the length of dst of src in nl80211_notify_radar_detection()
From: Luca Coelho @ 2019-03-15 15:38 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Luca Coelho
In-Reply-To: <20190315153907.16192-1-luca@coelho.fi>
From: Luca Coelho <luciano.coelho@intel.com>
It is generally safer to copy the length of the destination instead of
the length of the source, because if the sizes don't match, it's
usually better to leak some data from the source than to write data
out of bounds in the destination.
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
---
net/wireless/nl80211.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 25a9e3b5c154..239be0e2f9e1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -8061,7 +8061,7 @@ static int nl80211_notify_radar_detection(struct sk_buff *skb,
cfg80211_sched_dfs_chan_update(rdev);
- memcpy(&rdev->radar_chandef, &chandef, sizeof(chandef));
+ memcpy(&rdev->radar_chandef, &chandef, sizeof(rdev->radar_chandef));
/* Propagate this notification to other radios as well */
queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk);
--
2.20.1
^ permalink raw reply related
* Re: wireless workshop coming soon :-)
From: Toke Høiland-Jørgensen @ 2019-03-15 13:06 UTC (permalink / raw)
To: Johannes Berg, Kevin Hayes, Kirtika Ruchandani; +Cc: linux-wireless
In-Reply-To: <1d87a40795765be3ce9a485381c2867b143f26e1.camel@sipsolutions.net>
Johannes Berg <johannes@sipsolutions.net> writes:
> On Sun, 2019-03-10 at 20:21 -0700, Kevin Hayes wrote:
>> [resending after html mode got nacked..]
>>
>> Hi Johannes/Toke,
>> It would be fine with Kan and me to push the airtime fairness
>> discussion to later, to accomodate Toke.
>> Workshop fairness in action. :)
>
> :)
> Yes, I know we need to do that. Unfortunately I haven't had a chance to
> really build up a time-based agenda.
>
> Let's see. We have track 4 all day on Wednesday, overlaps are:
>
> | track 1 | track 2 | track 3
> 8:30 - 10:30 | TCP | XDP tut | IoT / U-LPWA
> 10:50 - 11:50 | TCP | Kubrnts | FRR
> 11:50 - 12:20 | netlink | QUIC | FRR dataplane
> 13:20 - 14:20 | netlink | QUIC | -
> 14:40 - 16:10 | TC | NF | -
> 16:30 - 18:00 | hw offl | preempt | -
>
> So the overlaps I know about are the XDP Tutorial (Toke) and netlink
> (partially at least, myself).
>
> Any others?
>
> Clearly Toke needs to be at the full XDP Tutorial, I think I can live
> with just doing the first part of the netlink workshop, according to
> their (tentative) agenda.
>
> As far as I'm concerned, we need Toke for the eBPF/XDP wifi topic, and
> clearly for all the topics related to TXQs, which includes at least part
> of HE/11ax. Toke, is there anything else you have a strong interest in?
>
>
> So tentatively, I'd say you can do w/o me for the FQ/airtime fairness
> stuff (right Toke, Kalle?) and talk about that at 11:50?
>
>
>
> Just randomly dropping the other stuff, I get:
>
> (T = no Toke, J = no Johannes)
>
> 8:30 - 9:00 T intro / CRDA deprecation / other regulatory topics?
> 9:00 - 9:30 T CSI reporting / vendor command/event handling updates
> 9:30 - 10:00 T nl80211 APIs - non-public features, NAN deprecation
> 10:00 - 10:30 T nl80211 APIs cont'd - Android
> 10:50 - 11:20 eBPF integration / XDP support for wifi
> 11:20 - 11:50 (buffer)
> 11:50 - 12:20 J rtw88 / grill Kalle (be)fore lunch ;-)
> 13:20 - 13:50 Kevin/Kan chromiumOS fairness review, bufferbloat plans
> 13:50 - 14:20 fq_codel / airtime fairness stack integration
> 14:40 - 15:10 HE/11ax status, timeline, testing, future work
> 15:10 - 15:40 HE/11ax TXQ AP-side (is anyone doing something here?)
> 15:40 - 16:10 release discussions (iw, wpa_s, ...)
> 16:30 - 17:00 security issue handling w/ backports
> 17:00 - 17:30 (buffer)
> 17:30 - 18:00
>
> WDYT?
SGTM :)
-Toke
^ permalink raw reply
* Re: [PATCH] mac80211: rework locking for txq scheduling / airtime fairness
From: Toke Høiland-Jørgensen @ 2019-03-15 13:04 UTC (permalink / raw)
To: Felix Fietkau, linux-wireless; +Cc: johannes
In-Reply-To: <20190315100335.91445-1-nbd@nbd.name>
Felix Fietkau <nbd@nbd.name> writes:
> Holding the lock around the entire duration of tx scheduling can create
> some nasty lock contention, especially when processing airtime information
> from the tx status or the rx path.
> Improve locking by only holding the active_txq_lock for lookups / scheduling
> list modifications.
>
> Signed-off-by: Felix Fietkau <nbd@nbd.name>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
> include/net/mac80211.h | 49 ++++++++++++++++--------------------------
> net/mac80211/tx.c | 44 ++++++++++++++-----------------------
> 2 files changed, 35 insertions(+), 58 deletions(-)
>
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index 3771625b7a9d..0de0aba580eb 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
[ ... ]
> -void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
> - __acquires(txq_lock);
> +void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac);
> +
> +/* (deprecated) */
> +static inline void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
> +{
> +}
I figure I'll post a cleanup of this as part of my reworked schedule
change patch; since I'll be messing around with these bits anyway...
-Toke
^ permalink raw reply
* [PATCH] mac80211: rework locking for txq scheduling / airtime fairness
From: Felix Fietkau @ 2019-03-15 10:03 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, Toke Høiland-Jørgensen
Holding the lock around the entire duration of tx scheduling can create
some nasty lock contention, especially when processing airtime information
from the tx status or the rx path.
Improve locking by only holding the active_txq_lock for lookups / scheduling
list modifications.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
include/net/mac80211.h | 49 ++++++++++++++++--------------------------
net/mac80211/tx.c | 44 ++++++++++++++-----------------------
2 files changed, 35 insertions(+), 58 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 3771625b7a9d..0de0aba580eb 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -6269,8 +6269,6 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
* @hw: pointer as obtained from ieee80211_alloc_hw()
* @ac: AC number to return packets from.
*
- * Should only be called between calls to ieee80211_txq_schedule_start()
- * and ieee80211_txq_schedule_end().
* Returns the next txq if successful, %NULL if no queue is eligible. If a txq
* is returned, it should be returned with ieee80211_return_txq() after the
* driver has finished scheduling it.
@@ -6278,51 +6276,42 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac);
/**
- * ieee80211_return_txq - return a TXQ previously acquired by ieee80211_next_txq()
- *
- * @hw: pointer as obtained from ieee80211_alloc_hw()
- * @txq: pointer obtained from station or virtual interface
- *
- * Should only be called between calls to ieee80211_txq_schedule_start()
- * and ieee80211_txq_schedule_end().
- */
-void ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
-
-/**
- * ieee80211_txq_schedule_start - acquire locks for safe scheduling of an AC
+ * ieee80211_txq_schedule_start - start new scheduling round for TXQs
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
* @ac: AC number to acquire locks for
*
- * Acquire locks needed to schedule TXQs from the given AC. Should be called
- * before ieee80211_next_txq() or ieee80211_return_txq().
+ * Should be called before ieee80211_next_txq() or ieee80211_return_txq().
+ * The driver must not call multiple TXQ scheduling rounds concurrently.
*/
-void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
- __acquires(txq_lock);
+void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac);
+
+/* (deprecated) */
+static inline void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
+{
+}
/**
- * ieee80211_txq_schedule_end - release locks for safe scheduling of an AC
+ * ieee80211_schedule_txq - schedule a TXQ for transmission
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
- * @ac: AC number to acquire locks for
+ * @txq: pointer obtained from station or virtual interface
*
- * Release locks previously acquired by ieee80211_txq_schedule_end().
+ * Schedules a TXQ for transmission if it is not already scheduled.
*/
-void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
- __releases(txq_lock);
+void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq);
/**
- * ieee80211_schedule_txq - schedule a TXQ for transmission
+ * ieee80211_return_txq - return a TXQ previously acquired by ieee80211_next_txq()
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
* @txq: pointer obtained from station or virtual interface
- *
- * Schedules a TXQ for transmission if it is not already scheduled. Takes a
- * lock, which means it must *not* be called between
- * ieee80211_txq_schedule_start() and ieee80211_txq_schedule_end()
*/
-void ieee80211_schedule_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
- __acquires(txq_lock) __releases(txq_lock);
+static inline void
+ieee80211_return_txq(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
+{
+ ieee80211_schedule_txq(hw, txq);
+}
/**
* ieee80211_txq_may_transmit - check whether TXQ is allowed to transmit
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ca23abbf5c0b..51cc37802439 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3653,16 +3653,17 @@ EXPORT_SYMBOL(ieee80211_tx_dequeue);
struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
{
struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_txq *ret = NULL;
struct txq_info *txqi = NULL;
- lockdep_assert_held(&local->active_txq_lock[ac]);
+ spin_lock_bh(&local->active_txq_lock[ac]);
begin:
txqi = list_first_entry_or_null(&local->active_txqs[ac],
struct txq_info,
schedule_order);
if (!txqi)
- return NULL;
+ goto out;
if (txqi->txq.sta) {
struct sta_info *sta = container_of(txqi->txq.sta,
@@ -3679,21 +3680,25 @@ struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
if (txqi->schedule_round == local->schedule_round[ac])
- return NULL;
+ goto out;
list_del_init(&txqi->schedule_order);
txqi->schedule_round = local->schedule_round[ac];
- return &txqi->txq;
+ ret = &txqi->txq;
+
+out:
+ spin_unlock_bh(&local->active_txq_lock[ac]);
+ return ret;
}
EXPORT_SYMBOL(ieee80211_next_txq);
-void ieee80211_return_txq(struct ieee80211_hw *hw,
- struct ieee80211_txq *txq)
+void ieee80211_schedule_txq(struct ieee80211_hw *hw,
+ struct ieee80211_txq *txq)
{
struct ieee80211_local *local = hw_to_local(hw);
struct txq_info *txqi = to_txq_info(txq);
- lockdep_assert_held(&local->active_txq_lock[txq->ac]);
+ spin_lock_bh(&local->active_txq_lock[txq->ac]);
if (list_empty(&txqi->schedule_order) &&
(!skb_queue_empty(&txqi->frags) || txqi->tin.backlog_packets)) {
@@ -3713,17 +3718,7 @@ void ieee80211_return_txq(struct ieee80211_hw *hw,
list_add_tail(&txqi->schedule_order,
&local->active_txqs[txq->ac]);
}
-}
-EXPORT_SYMBOL(ieee80211_return_txq);
-void ieee80211_schedule_txq(struct ieee80211_hw *hw,
- struct ieee80211_txq *txq)
- __acquires(txq_lock) __releases(txq_lock)
-{
- struct ieee80211_local *local = hw_to_local(hw);
-
- spin_lock_bh(&local->active_txq_lock[txq->ac]);
- ieee80211_return_txq(hw, txq);
spin_unlock_bh(&local->active_txq_lock[txq->ac]);
}
EXPORT_SYMBOL(ieee80211_schedule_txq);
@@ -3736,7 +3731,7 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
struct sta_info *sta;
u8 ac = txq->ac;
- lockdep_assert_held(&local->active_txq_lock[ac]);
+ spin_lock_bh(&local->active_txq_lock[ac]);
if (!txqi->txq.sta)
goto out;
@@ -3766,34 +3761,27 @@ bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
sta->airtime[ac].deficit += sta->airtime_weight;
list_move_tail(&txqi->schedule_order, &local->active_txqs[ac]);
+ spin_unlock_bh(&local->active_txq_lock[ac]);
return false;
out:
if (!list_empty(&txqi->schedule_order))
list_del_init(&txqi->schedule_order);
+ spin_unlock_bh(&local->active_txq_lock[ac]);
return true;
}
EXPORT_SYMBOL(ieee80211_txq_may_transmit);
void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
- __acquires(txq_lock)
{
struct ieee80211_local *local = hw_to_local(hw);
spin_lock_bh(&local->active_txq_lock[ac]);
local->schedule_round[ac]++;
-}
-EXPORT_SYMBOL(ieee80211_txq_schedule_start);
-
-void ieee80211_txq_schedule_end(struct ieee80211_hw *hw, u8 ac)
- __releases(txq_lock)
-{
- struct ieee80211_local *local = hw_to_local(hw);
-
spin_unlock_bh(&local->active_txq_lock[ac]);
}
-EXPORT_SYMBOL(ieee80211_txq_schedule_end);
+EXPORT_SYMBOL(ieee80211_txq_schedule_start);
void __ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev,
--
2.17.0
^ permalink raw reply related
* Re: [PATCH v2] net: brcm80211: fix missing checks for kmemdup
From: Arend Van Spriel @ 2019-03-15 9:50 UTC (permalink / raw)
To: Kangjie Lu
Cc: pakki001, Franky Lin, Hante Meuleman, Chi-Hsien Lin, Wright Feng,
Kalle Valo, David S. Miller, Rafał Miłecki,
Stefan Wahren, Chung-Hsien Hsu, linux-wireless,
brcm80211-dev-list.pdl, brcm80211-dev-list, netdev, linux-kernel
In-Reply-To: <20190312043929.727-1-kjlu@umn.edu>
On 3/12/2019 5:39 AM, Kangjie Lu wrote:
> In case kmemdup fails, the fix sets conn_info->req_ie_len to zero
> to avoid buffer overflows.
Hi Kangjie,
See comment below. Also for v3 change prefix 'net:brcm80211:' to
'brcmfmac:' instead.
> Signed-off-by: Kangjie Lu <kjlu@umn.edu>
> ---
> drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
> index e92f6351bd22..5d9a3c35fef5 100644
> --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
> +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
> @@ -5464,6 +5464,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
> conn_info->req_ie =
> kmemdup(cfg->extra_buf, conn_info->req_ie_len,
> GFP_KERNEL);
> + if (!conn_info->req_ie)
> + conn_info->req_ie_len = 0;
good.
> } else {
> conn_info->req_ie_len = 0;
> conn_info->req_ie = NULL;
> @@ -5480,6 +5482,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
> conn_info->resp_ie =
> kmemdup(cfg->extra_buf, conn_info->resp_ie_len,
> GFP_KERNEL);
> + if (!conn_info->resp_ie)
> + conn_info->req_ie_len = 0;
bad! I think you took my comment too literal. Here it should set
conn_info->resp_ie_len to zero.
Regards,
Arend
> } else {
> conn_info->resp_ie_len = 0;
> conn_info->resp_ie = NULL;
>
^ permalink raw reply
* Re: preparing for 802.11ah channels
From: Johannes Berg @ 2019-03-15 9:47 UTC (permalink / raw)
To: thomas pedersen, linux-wireless
In-Reply-To: <CABWD38man7mGiConmvmK0V=35P9zV7uvhVoY-8eSQQeO9W2+Qw@mail.gmail.com>
On Sat, 2019-02-16 at 15:45 -0800, thomas pedersen wrote:
> Hello,
>
> I'm working on defining new channels for S1G PHYs in mac80211. These
> are in the 900MHz range and center frequency for the 1MHz channels are
> on a half MHz, while the existing channel definitions are in units of
> MHz.
Yay... :)
> In order to support the new channels we could change the internal
> center frequency units to KHz and extend the nl80211 API so
> NL80211_FREQUENCY_ATTR_FREQ and NL80211_ATTR_WIPHY_FREQ get _KHZ
> variants while renaming the original attributes to _MHZ to reflect the
> units.
The nl80211 API seems straightforward, yeah.
> From looking at the code it looks like this should be fairly
> straightforward, if involving a lot of changes since the driver
> declarations would have to change too. Am I missing something
> obviously wrong, or does this sound reasonable?
I'm not sure I agree about all the driver changes being straightforward.
In theory yes, but ... ;-)
I guess you'd define a new band (NL80211_BAND_S1G or something?), so
perhaps there's a way we can get away with doing it only on that band?
OTOH, I guess if you change center_freq1 to center_freq1_khz or
something then you compile-fail everywhere ...
johanne
^ permalink raw reply
* Re: [PATCH v2] fq: fix fq_tin tx bytes overflow
From: Johannes Berg @ 2019-03-15 9:38 UTC (permalink / raw)
To: Yibo Zhao, ath10k; +Cc: linux-wireless, Toke Høiland-Jørgensen
In-Reply-To: <1552446505-15444-1-git-send-email-yiboz@codeaurora.org>
On Wed, 2019-03-13 at 11:08 +0800, Yibo Zhao wrote:
> Currently, we are using u32 for tx_bytes in fq_tin.
> If the throughput stays more than 1.2Gbps, tx_bytes
> statistics overflow in about 1 min.
>
> In order to allow us to trace the tx_bytes statistics
> for longer time in high throughput, change its type
> from u32 to u64.
Hmm. 64-bit values are kinda expensive on 32-bit architectures. How
badly do you need this? I mean ... worst case you just have to capture
every 30 seconds or so if you're doing really high throughput with HE or
something?
johannes
^ permalink raw reply
* Re: wireless workshop coming soon :-)
From: Johannes Berg @ 2019-03-15 9:21 UTC (permalink / raw)
To: Kevin Hayes, Toke Høiland-Jørgensen, Kirtika Ruchandani
Cc: linux-wireless
In-Reply-To: <1d87a40795765be3ce9a485381c2867b143f26e1.camel@sipsolutions.net>
On Fri, 2019-03-15 at 10:20 +0100, Johannes Berg wrote:
> On Sun, 2019-03-10 at 20:21 -0700, Kevin Hayes wrote:
> > [resending after html mode got nacked..]
> >
> > Hi Johannes/Toke,
> > It would be fine with Kan and me to push the airtime fairness
> > discussion to later, to accomodate Toke.
> > Workshop fairness in action. :)
>
> :)
> Yes, I know we need to do that. Unfortunately I haven't had a chance to
> really build up a time-based agenda.
>
> Let's see. We have track 4 all day on Wednesday, overlaps are:
>
> | track 1 | track 2 | track 3
> 8:30 - 10:30 | TCP | XDP tut | IoT / U-LPWA
> 10:50 - 11:50 | TCP | Kubrnts | FRR
> 11:50 - 12:20 | netlink | QUIC | FRR dataplane
> 13:20 - 14:20 | netlink | QUIC | -
> 14:40 - 16:10 | TC | NF | -
> 16:30 - 18:00 | hw offl | preempt | -
>
> So the overlaps I know about are the XDP Tutorial (Toke) and netlink
> (partially at least, myself).
>
> Any others?
>
> Clearly Toke needs to be at the full XDP Tutorial, I think I can live
> with just doing the first part of the netlink workshop, according to
> their (tentative) agenda.
>
> As far as I'm concerned, we need Toke for the eBPF/XDP wifi topic, and
> clearly for all the topics related to TXQs, which includes at least part
> of HE/11ax. Toke, is there anything else you have a strong interest in?
>
>
> So tentatively, I'd say you can do w/o me for the FQ/airtime fairness
> stuff (right Toke, Kalle?) and talk about that at 11:50?
>
>
>
> Just randomly dropping the other stuff, I get:
>
> (T = no Toke, J = no Johannes)
>
> 8:30 - 9:00 T intro / CRDA deprecation / other regulatory topics?
> 9:00 - 9:30 T CSI reporting / vendor command/event handling updates
> 9:30 - 10:00 T nl80211 APIs - non-public features, NAN deprecation
> 10:00 - 10:30 T nl80211 APIs cont'd - Android
> 10:50 - 11:20 eBPF integration / XDP support for wifi
> 11:20 - 11:50 (buffer)
> 11:50 - 12:20 J rtw88 / grill Kalle (be)fore lunch ;-)
> 13:20 - 13:50 Kevin/Kan chromiumOS fairness review, bufferbloat plans
> 13:50 - 14:20 fq_codel / airtime fairness stack integration
> 14:40 - 15:10 HE/11ax status, timeline, testing, future work
> 15:10 - 15:40 HE/11ax TXQ AP-side (is anyone doing something here?)
> 15:40 - 16:10 release discussions (iw, wpa_s, ...)
> 16:30 - 17:00 security issue handling w/ backports
> 17:00 - 17:30 (buffer)
> 17:30 - 18:00
Oh, I have another idea - radiotap TLV format discussion, if anyone
cares?
johannes
^ permalink raw reply
* Re: wireless workshop coming soon :-)
From: Johannes Berg @ 2019-03-15 9:20 UTC (permalink / raw)
To: Kevin Hayes, Toke Høiland-Jørgensen, Kirtika Ruchandani
Cc: linux-wireless
In-Reply-To: <CAPJUEh3s-Bs6dKrDG54Q1Wu2+1+kwMvTDxJxxEAVBanLA0=FYA@mail.gmail.com>
On Sun, 2019-03-10 at 20:21 -0700, Kevin Hayes wrote:
> [resending after html mode got nacked..]
>
> Hi Johannes/Toke,
> It would be fine with Kan and me to push the airtime fairness
> discussion to later, to accomodate Toke.
> Workshop fairness in action. :)
:)
Yes, I know we need to do that. Unfortunately I haven't had a chance to
really build up a time-based agenda.
Let's see. We have track 4 all day on Wednesday, overlaps are:
| track 1 | track 2 | track 3
8:30 - 10:30 | TCP | XDP tut | IoT / U-LPWA
10:50 - 11:50 | TCP | Kubrnts | FRR
11:50 - 12:20 | netlink | QUIC | FRR dataplane
13:20 - 14:20 | netlink | QUIC | -
14:40 - 16:10 | TC | NF | -
16:30 - 18:00 | hw offl | preempt | -
So the overlaps I know about are the XDP Tutorial (Toke) and netlink
(partially at least, myself).
Any others?
Clearly Toke needs to be at the full XDP Tutorial, I think I can live
with just doing the first part of the netlink workshop, according to
their (tentative) agenda.
As far as I'm concerned, we need Toke for the eBPF/XDP wifi topic, and
clearly for all the topics related to TXQs, which includes at least part
of HE/11ax. Toke, is there anything else you have a strong interest in?
So tentatively, I'd say you can do w/o me for the FQ/airtime fairness
stuff (right Toke, Kalle?) and talk about that at 11:50?
Just randomly dropping the other stuff, I get:
(T = no Toke, J = no Johannes)
8:30 - 9:00 T intro / CRDA deprecation / other regulatory topics?
9:00 - 9:30 T CSI reporting / vendor command/event handling updates
9:30 - 10:00 T nl80211 APIs - non-public features, NAN deprecation
10:00 - 10:30 T nl80211 APIs cont'd - Android
10:50 - 11:20 eBPF integration / XDP support for wifi
11:20 - 11:50 (buffer)
11:50 - 12:20 J rtw88 / grill Kalle (be)fore lunch ;-)
13:20 - 13:50 Kevin/Kan chromiumOS fairness review, bufferbloat plans
13:50 - 14:20 fq_codel / airtime fairness stack integration
14:40 - 15:10 HE/11ax status, timeline, testing, future work
15:10 - 15:40 HE/11ax TXQ AP-side (is anyone doing something here?)
15:40 - 16:10 release discussions (iw, wpa_s, ...)
16:30 - 17:00 security issue handling w/ backports
17:00 - 17:30 (buffer)
17:30 - 18:00
WDYT?
johannes
^ permalink raw reply
* Re: [PATCH v8 01/14] rtw88: main files
From: Johannes Berg @ 2019-03-15 8:28 UTC (permalink / raw)
To: yhchuang, kvalo
Cc: linux-wireless, gregkh, sgruszka, pkshih, tehuang, briannorris,
Larry.Finger
In-Reply-To: <1552450443-351-2-git-send-email-yhchuang@realtek.com>
On Wed, 2019-03-13 at 12:13 +0800, yhchuang@realtek.com wrote:
>
> +static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)
> +{
> + struct rtw_dev *rtwdev = hw->priv;
> + int ret = 0;
> +
> + mutex_lock(&rtwdev->mutex);
> +
> + if (changed & IEEE80211_CONF_CHANGE_IDLE) {
> + if (hw->conf.flags & IEEE80211_CONF_IDLE) {
> + rtw_enter_ips(rtwdev);
> + } else {
> + ret = rtw_leave_ips(rtwdev);
> + if (ret) {
> + rtw_err(rtwdev, "failed to leave idle state\n");
> + goto out;
> + }
> + }
> + }
> +
> + if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
> + rtw_set_channel(rtwdev);
It's clearly your decision, but you're probably better off supporting
the modern channel context APIs, even if (at this time) you only support
a single channel.
The settings and methods here that apply to the "whole hardware" are
mostly obsolete as far as mac80211 is concerned.
Now, I also don't recommend you change that now, and it's clearly not a
requirement for an in-tree driver, but something to think about.
> +static int rtw_ops_add_interface(struct ieee80211_hw *hw,
> + struct ieee80211_vif *vif)
> +{
> + struct rtw_dev *rtwdev = hw->priv;
> + struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
> + enum rtw_net_type net_type;
> + u32 config = 0;
> + u8 port = 0;
> +
> + rtwvif->port = port;
> + rtwvif->vif = vif;
> + rtwvif->stats.tx_unicast = 0;
> + rtwvif->stats.rx_unicast = 0;
> + rtwvif->stats.tx_cnt = 0;
> + rtwvif->stats.rx_cnt = 0;
> + rtwvif->in_lps = false;
> + rtwvif->conf = &rtw_vif_port[port];
That's a bit weird, port is always 0. But I guess it's some kind of
preparation for future multi-interface changes (and then you probably
want the channel contexts too?)
> + rtw_info(rtwdev, "start vif %pM on port %d\n", vif->addr, rtwvif->port);
I'm not convinced that warrants an "info" level trace, but YMMV.
> + rtw_info(rtwdev, "stop vif %pM on port %d\n", vif->addr, rtwvif->port);
dito
> +static int rtw_ops_sta_add(struct ieee80211_hw *hw,
> + struct ieee80211_vif *vif,
> + struct ieee80211_sta *sta)
Also, here, I'd consider using sta-state API, it tells you more. Here
it's even less important though since from mac80211's POV it's exactly
the same (it only ever calls sta_state) but the driver with
sta_add/sta_remove gets a filtered view thereof.
> +{
> + struct rtw_dev *rtwdev = hw->priv;
> + struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
> + int ret = 0;
> +
> + mutex_lock(&rtwdev->mutex);
> +
> + si->mac_id = rtw_acquire_macid(rtwdev);
I note you don't handle any kinds of firmware restart scenarios here. I
guess eventually you'd want to?
> +static void rtw_watch_dog_work(struct work_struct *work)
Hm, is that really a "watchdog" in the usual sense?
It seems more like some sort of "periodic work" like the LPS stuff
below, or whatever the PHY dynamic thing is - but not a "watchdog" in
the sense of checking that things are still OK?
Anyway, just a nit about semantics.
(I was looking for FW restart handling here or so)
> + /* power on MAC before firmware downloaded */
> + ret = rtw_mac_power_on(rtwdev);
> + if (ret) {
> + rtw_err(rtwdev, "failed to power on mac\n");
> + goto err;
> + }
> +
> + wait_for_completion(&fw->completion);
Maybe I'm misreading the code, but does this every do anything? It
looked like you only get here after the callback.
> + ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work,
> + RTW_WATCH_DOG_DELAY_TIME);
Consider using at least round_jiffies_relative() - this is expensive
from a power consumption POV already and doesn't look like it needs
perfect timing.
> +static int rtw_chip_efuse_enable(struct rtw_dev *rtwdev)
> +{
> + struct rtw_fw_state *fw = &rtwdev->fw;
> + int ret;
> +
> + ret = rtw_hci_setup(rtwdev);
> + if (ret) {
> + rtw_err(rtwdev, "failed to setup hci\n");
> + goto err;
> + }
> +
> + ret = rtw_mac_power_on(rtwdev);
> + if (ret) {
> + rtw_err(rtwdev, "failed to power on mac\n");
> + goto err;
> + }
> +
> + rtw_write8(rtwdev, REG_C2HEVT, C2H_HW_FEATURE_DUMP);
> +
> + wait_for_completion(&fw->completion);
same here?
It sort of looked like you don't even need the completion, but I may not
be understanding the full flow.
Typically the flow would be
probe -> load firmware -> firmware callback -> continue work
but I haven't checked in detail if it's different here. If it is though,
why should it be? You can't really do anything without firmware?
> +++ b/drivers/net/wireless/realtek/rtw88/main.h
This file is a bit confusing. On the one hand, you have things like:
> +#define RTW_WATCH_DOG_DELAY_TIME round_jiffies_relative(HZ * 2)
(ohh. you did use round_jiffies_relative!)
> +extern unsigned int rtw_debug_mask;
> +extern const struct ieee80211_ops rtw_ops;
> +extern struct rtw_chip_info rtw8822b_hw_spec;
> +extern struct rtw_chip_info rtw8822c_hw_spec;
This which are very clearly driver specific.
On the other hand you have:
> +enum rtw_bandwidth {
> + RTW_CHANNEL_WIDTH_20 = 0,
> + RTW_CHANNEL_WIDTH_40 = 1,
> + RTW_CHANNEL_WIDTH_80 = 2,
> + RTW_CHANNEL_WIDTH_160 = 3,
> + RTW_CHANNEL_WIDTH_80_80 = 4,
> + RTW_CHANNEL_WIDTH_5 = 5,
> + RTW_CHANNEL_WIDTH_10 = 6,
> +};
> +
> +enum rtw_net_type {
> + RTW_NET_NO_LINK = 0,
> + RTW_NET_AD_HOC = 1,
> + RTW_NET_MGD_LINKED = 2,
> + RTW_NET_AP_MODE = 3,
> +};
> +
> +enum rtw_rf_type {
> + RF_1T1R = 0,
> + RF_1T2R = 1,
> + RF_2T2R = 2,
> + RF_2T3R = 3,
> + RF_2T4R = 4,
> + RF_3T3R = 5,
> + RF_3T4R = 6,
> + RF_4T4R = 7,
> + RF_TYPE_MAX,
> +};
And lots of other things like that which look like some kind of device
API (firmware, hardware, OTP, ...)
IMHO it'd be cleaner to separate that into different files.
Again, for example:
> +enum rtw_regulatory_domains {
> + RTW_REGD_FCC = 0,
> + RTW_REGD_MKK = 1,
> + RTW_REGD_ETSI = 2,
> + RTW_REGD_WW = 3,
> +
> + RTW_REGD_MAX
> +};
Must be hardware API otherwise you wouldn't really care about the exact
values, I guess?
> +enum rtw_flags {
> + RTW_FLAG_RUNNING,
> + RTW_FLAG_FW_RUNNING,
> + RTW_FLAG_SCANNING,
> + RTW_FLAG_INACTIVE_PS,
> + RTW_FLAG_LEISURE_PS,
> + RTW_FLAG_DIG_DISABLE,
> +
> + NUM_OF_RTW_FLAGS,
> +};
Where this is clearly pure driver but everything is completely
intermingled.
It's not a huge problem, but ...
> +/* the power index is represented by differences, which cck-1s & ht40-1s are
> + * the base values, so for 1s's differences, there are only ht20 & ofdm
> + */
> +struct rtw_2g_1s_pwr_idx_diff {
> +#ifdef __LITTLE_ENDIAN
> + s8 ofdm:4;
> + s8 bw20:4;
> +#else
> + s8 bw20:4;
> + s8 ofdm:4;
> +#endif
> +} __packed;
Again, clearly something with the device, otherwise you wouldn't go to
the effort of doing correct-endian-bitfields :-)
(Which I wouldn't really recommend anyway ... but that's another story)
> +#define rtw_iterate_vifs(rtwdev, iterator, data) \
> + ieee80211_iterate_active_interfaces(rtwdev->hw, \
> + IEEE80211_IFACE_ITER_NORMAL, iterator, data)
> +#define rtw_iterate_vifs_atomic(rtwdev, iterator, data) \
> + ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, \
> + IEEE80211_IFACE_ITER_NORMAL, iterator, data)
> +#define rtw_iterate_stas_atomic(rtwdev, iterator, data) \
> + ieee80211_iterate_stations_atomic(rtwdev->hw, iterator, data)
Why not make those inlines?
> +static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr)
> +{
> + __le16 fc = hdr->frame_control;
> + u8 *bssid;
> +
> + if (ieee80211_has_tods(fc))
> + bssid = hdr->addr1;
> + else if (ieee80211_has_fromds(fc))
> + bssid = hdr->addr2;
> + else
> + bssid = hdr->addr3;
> +
> + return bssid;
> +}
This is kinda incomplete, perhaps we should export ieee80211_get_bssid()
instead?
Anyway, none of that really seems like blocking issues.
joahnnes
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox