[iwlwifi] Update to latest driver.
Updates the driver to the latest one from ToT. Also contains
the necessary changed to make it compile against the latest
build of partner sdk.
Change-Id: I7ae01c41c3f35563984e60dcad738f427c077e95
Reviewed-on: https://fuchsia-review.googlesource.com/c/drivers/wlan/intel/iwlwifi/+/640827
Fuchsia-Auto-Submit: Sakthi Vignesh Radhakrishnan <rsakthi@google.com>
Reviewed-by: Sean Cuff <seancuff@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
diff --git a/third_party/iwlwifi/BUILD.bazel b/third_party/iwlwifi/BUILD.bazel
index 3d258ba..94b2781 100644
--- a/third_party/iwlwifi/BUILD.bazel
+++ b/third_party/iwlwifi/BUILD.bazel
@@ -1,3 +1,7 @@
+# Copyright 2021 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
package(default_visibility = ["//visibility:public"])
cc_library(
@@ -8,41 +12,33 @@
"iwl-io.c",
"iwl-nvm-parse.c",
"iwl-phy-db.c",
- "iwl-trans.c",
+ "iwl-trans.c",
],
hdrs = [
- "iwl-agn-hw.h",
- "iwl-config.h",
+ "iwl-agn-hw.h",
+ "iwl-config.h",
"iwl-constants.h",
- "iwl-csr.h",
+ "iwl-csr.h",
"iwl-dbg-tlv.h",
"iwl-debug.h",
"iwl-drv.h",
"iwl-eeprom-parse.h",
"iwl-eeprom-read.h",
"iwl-fh.h",
- "iwl-io.h",
- "iwl-modparams.h",
- "iwl-nvm-parse.h",
- "iwl-op-mode.h",
- "iwl-phy-db.h",
- "iwl-prph.h",
- "iwl-scd.h",
- "iwl-trans.h",
- "iwl-vendor-cmd.h",
- "iwl-context-info-gen3.h",
- "iwl-context-info.h",
+ "iwl-io.h",
+ "iwl-modparams.h",
+ "iwl-nvm-parse.h",
+ "iwl-op-mode.h",
+ "iwl-phy-db.h",
+ "iwl-prph.h",
+ "iwl-scd.h",
+ "iwl-trans.h",
+ "iwl-vendor-cmd.h",
+ "iwl-context-info-gen3.h",
+ "iwl-context-info.h",
],
deps = [
"//third_party/iwlwifi/fw:api",
-# "//third_party/iwlwifi/platform:platform",
-# "@fuchsia_sdk//pkg/ddk",
-# "//zircon/system/public",
-# "//zircon/system/ulib/sync",
-# "//zircon/system/ulib/zircon-internal",
-
-# "//sdk/banjo/ddk.hw.wlan.wlaninfo:ddk.hw.wlan.wlaninfo_banjo_c",
-# "//zircon/system/public",
+ "//third_party/iwlwifi/platform:platform",
],
)
-
diff --git a/third_party/iwlwifi/BUILD.gn b/third_party/iwlwifi/BUILD.gn
index 9ec51cf..588d580 100644
--- a/third_party/iwlwifi/BUILD.gn
+++ b/third_party/iwlwifi/BUILD.gn
@@ -5,7 +5,7 @@
import("//build/components.gni")
import("//build/drivers.gni")
-visibility = [ "//src/iwlwifi/*" ]
+visibility = [ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/*" ]
# Common configuration for builds on Fuchsia.
config("fuchsia_config") {
@@ -47,15 +47,14 @@
"iwl-vendor-cmd.h",
]
deps = [
- "//src/iwlwifi/fw:api",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/fw:api",
"//src/lib/ddk",
"//zircon/system/public",
"//zircon/system/ulib/sync",
- "//zircon/system/ulib/zircon-internal",
]
public_deps = [
- "//sdk/banjo/ddk.hw.wlan.wlaninfo:ddk.hw.wlan.wlaninfo_banjo_c",
- "//src/iwlwifi/platform",
+ "//sdk/banjo/fuchsia.hardware.wlan.phyinfo:fuchsia.hardware.wlan.phyinfo_banjo_c",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform",
"//zircon/system/public",
]
@@ -65,10 +64,11 @@
fuchsia_driver("iwlwifi_driver-driver") {
output_name = "iwlwifi"
- deps = [ "//src/iwlwifi/platform:fuchsia_device" ]
+ deps = [ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform:fuchsia_device" ]
}
fuchsia_driver_component("iwlwifi_driver") {
+ info = "iwlwifi_driver-info.json"
component_name = "iwlwifi"
deps = [ ":iwlwifi_driver-driver" ]
visibility = []
@@ -102,8 +102,8 @@
group("tests") {
testonly = true
deps = [
- "//src/iwlwifi/platform:fuchsia_bind_test",
- "//src/iwlwifi/test:iwlwifi_test",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform:fuchsia_bind_test",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test:iwlwifi_test",
]
visibility = []
visibility = [ "*" ]
diff --git a/third_party/iwlwifi/README.md b/third_party/iwlwifi/README.md
index f1d3ea2..5b7d0eb 100644
--- a/third_party/iwlwifi/README.md
+++ b/third_party/iwlwifi/README.md
@@ -45,7 +45,7 @@
```
MLME
|
- --------------- wlanphy_impl_protocol_ops_t / wlanmac_protocol_ops_t
+ --------------- wlanphy_impl_protocol_ops_t / wlan_softmac_protocol_ops_t
|
^ |
| +-------------+ +--------------+
diff --git a/third_party/iwlwifi/cfg/7000.c b/third_party/iwlwifi/cfg/7000.c
index 36da06f..b054c7f 100644
--- a/third_party/iwlwifi/cfg/7000.c
+++ b/third_party/iwlwifi/cfg/7000.c
@@ -115,7 +115,7 @@
static const struct iwl_ht_params iwl7000_ht_params = {
.stbc = true,
- .ht40_bands = BIT(WLAN_INFO_BAND_2GHZ) | BIT(WLAN_INFO_BAND_5GHZ),
+ .ht40_bands = BIT(WLAN_INFO_BAND_TWO_GHZ) | BIT(WLAN_INFO_BAND_FIVE_GHZ),
};
#define IWL_DEVICE_7000_COMMON \
@@ -226,7 +226,7 @@
static const struct iwl_ht_params iwl7265_ht_params = {
.stbc = true,
.ldpc = true,
- .ht40_bands = BIT(WLAN_INFO_BAND_2GHZ) | BIT(WLAN_INFO_BAND_5GHZ),
+ .ht40_bands = BIT(WLAN_INFO_BAND_TWO_GHZ) | BIT(WLAN_INFO_BAND_FIVE_GHZ),
};
const struct iwl_cfg iwl3165_2ac_cfg = {
diff --git a/third_party/iwlwifi/cfg/8000.c b/third_party/iwlwifi/cfg/8000.c
index ca344d8..110a0e1 100644
--- a/third_party/iwlwifi/cfg/8000.c
+++ b/third_party/iwlwifi/cfg/8000.c
@@ -77,7 +77,7 @@
static const struct iwl_ht_params iwl8000_ht_params = {
.stbc = true,
.ldpc = true,
- .ht40_bands = BIT(WLAN_INFO_BAND_2GHZ) | BIT(WLAN_INFO_BAND_5GHZ),
+ .ht40_bands = BIT(WLAN_INFO_BAND_TWO_GHZ) | BIT(WLAN_INFO_BAND_FIVE_GHZ),
};
static const struct iwl_tt_params iwl8000_tt_params = {
diff --git a/third_party/iwlwifi/cfg/9000.c b/third_party/iwlwifi/cfg/9000.c
index ae96844..85fbf5d 100644
--- a/third_party/iwlwifi/cfg/9000.c
+++ b/third_party/iwlwifi/cfg/9000.c
@@ -72,7 +72,7 @@
static const struct iwl_ht_params iwl9000_ht_params = {
.stbc = true,
.ldpc = true,
- .ht40_bands = BIT(WLAN_INFO_BAND_2GHZ) | BIT(WLAN_INFO_BAND_5GHZ),
+ .ht40_bands = BIT(WLAN_INFO_BAND_TWO_GHZ) | BIT(WLAN_INFO_BAND_FIVE_GHZ),
};
static const struct iwl_tt_params iwl9000_tt_params = {
diff --git a/third_party/iwlwifi/cfg/BUILD.gn b/third_party/iwlwifi/cfg/BUILD.gn
index 10ad30a..6d98072 100644
--- a/third_party/iwlwifi/cfg/BUILD.gn
+++ b/third_party/iwlwifi/cfg/BUILD.gn
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-visibility = [ "//src/iwlwifi/*" ]
+visibility = [ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/*" ]
source_set("cfg") {
sources = [
@@ -11,7 +11,7 @@
"9000.c",
]
deps = [
- "//src/iwlwifi:core",
- "//src/iwlwifi/fw:api",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/fw:api",
]
}
diff --git a/third_party/iwlwifi/fw/BUILD.bazel b/third_party/iwlwifi/fw/BUILD.bazel
index 9b8975c..7a841ef 100644
--- a/third_party/iwlwifi/fw/BUILD.bazel
+++ b/third_party/iwlwifi/fw/BUILD.bazel
@@ -75,7 +75,5 @@
":api",
"//third_party/iwlwifi:core",
"//third_party/iwlwifi/platform:platform",
-# "//zircon/system/public",
-# "//zircon/system/ulib/sync",
],
)
diff --git a/third_party/iwlwifi/fw/BUILD.gn b/third_party/iwlwifi/fw/BUILD.gn
index f7035c9..7ccedcb 100644
--- a/third_party/iwlwifi/fw/BUILD.gn
+++ b/third_party/iwlwifi/fw/BUILD.gn
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-visibility = [ "//src/iwlwifi/*" ]
+visibility = [ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/*" ]
# These are the headers for the firmware API. To avoid circular dependencies, these do not depend
# on anything in iwlwifi other than platform/.
@@ -50,7 +50,7 @@
]
public_deps = [
"//sdk/fidl/fuchsia.wlan.ieee80211:fuchsia.wlan.ieee80211_c",
- "//src/iwlwifi/platform",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform",
"//src/lib/ddk",
]
}
@@ -70,8 +70,8 @@
]
public_deps = [
":api",
- "//src/iwlwifi:core",
- "//src/iwlwifi/platform",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform",
"//zircon/system/public",
"//zircon/system/ulib/sync",
]
diff --git a/third_party/iwlwifi/fw/api/fmac.h b/third_party/iwlwifi/fw/api/fmac.h
index 7d84de6..5f97d66 100644
--- a/third_party/iwlwifi/fw/api/fmac.h
+++ b/third_party/iwlwifi/fw/api/fmac.h
@@ -35,7 +35,7 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_FW_API_FMAC_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_FW_API_FMAC_H_
-#include <fuchsia/wlan/ieee80211/c/fidl.h>
+#include <fuchsia/wlan/ieee80211/c/banjo.h>
#define FMAC_GROUP 0x10
diff --git a/third_party/iwlwifi/fw/dbg.c b/third_party/iwlwifi/fw/dbg.c
index ab7359e..167258d 100644
--- a/third_party/iwlwifi/fw/dbg.c
+++ b/third_party/iwlwifi/fw/dbg.c
@@ -1417,7 +1417,7 @@
}
iwl_write_prph(trans, DBGC_IN_SAMPLE, 0);
- zx_nanosleep(ZX_USEC(100));
+ zx_nanosleep(zx_deadline_after(ZX_USEC(100)));
iwl_write_prph(trans, DBGC_OUT_CTRL, 0);
#ifdef CPTCFG_IWLWIFI_DEBUGFS
trans->dbg_rec_on = false;
@@ -1445,7 +1445,7 @@
iwl_set_bits_prph(trans, MON_BUFF_SAMPLE_CTL, 0x1);
} else {
iwl_write_prph(trans, DBGC_IN_SAMPLE, params->in_sample);
- zx_nanosleep(ZX_USEC(100));
+ zx_nanosleep(zx_deadline_after(ZX_USEC(100)));
iwl_write_prph(trans, DBGC_OUT_CTRL, params->out_ctrl);
}
}
@@ -1494,7 +1494,7 @@
/* start recording again if the firmware is not crashed */
if (!test_bit(STATUS_FW_ERROR, &fwrt->trans->status) && fwrt->fw->dbg.dest_tlv) {
/* wait before we collect the data till the DBGC stop */
- zx_nanosleep(ZX_USEC(500));
+ zx_nanosleep(zx_deadline_after(ZX_USEC(500)));
iwl_fw_dbg_restart_recording(fwrt, ¶ms);
}
}
diff --git a/third_party/iwlwifi/iwl-dbg-cfg.c b/third_party/iwlwifi/iwl-dbg-cfg.c
index 28a45e0..94591d0 100644
--- a/third_party/iwlwifi/iwl-dbg-cfg.c
+++ b/third_party/iwlwifi/iwl-dbg-cfg.c
@@ -32,9 +32,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
-// TODO(rsakthi) - how to get this from bazel?
-#define CPTCFG_IWLMVM 1
-
#include "iwl-dbg-cfg.h"
#include <linux/export.h>
diff --git a/third_party/iwlwifi/iwl-dbg-cfg.h b/third_party/iwlwifi/iwl-dbg-cfg.h
index 1159aed..9c45136 100644
--- a/third_party/iwlwifi/iwl-dbg-cfg.h
+++ b/third_party/iwlwifi/iwl-dbg-cfg.h
@@ -35,9 +35,6 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_IWL_DBG_CFG_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_IWL_DBG_CFG_H_
-// TODO(rsakthi) - how to get this from bazel?
-#define CPTCFG_IWLMVM 1
-
/*
* with DBG_CFG_REINCLUDE set this file should contain nothing
* but IWL_DBG_CFG() macro invocations so it can be used in
diff --git a/third_party/iwlwifi/iwl-drv.c b/third_party/iwlwifi/iwl-drv.c
index 3efb4d0..32b13ad 100644
--- a/third_party/iwlwifi/iwl-drv.c
+++ b/third_party/iwlwifi/iwl-drv.c
@@ -33,7 +33,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
-#include "iwl-drv.h"
+#include "third_party/iwlwifi/iwl-drv.h"
#include <lib/ddk/debug.h>
#include <lib/ddk/driver.h>
@@ -43,7 +43,6 @@
#include <zircon/listnode.h>
#include <zircon/status.h>
-#include "third_party/iwlwifi/platform/align.h"
#include "third_party/iwlwifi/fw/img.h"
#include "third_party/iwlwifi/iwl-agn-hw.h"
#include "third_party/iwlwifi/iwl-config.h"
@@ -53,13 +52,14 @@
#include "third_party/iwlwifi/iwl-modparams.h"
#include "third_party/iwlwifi/iwl-op-mode.h"
#include "third_party/iwlwifi/iwl-trans.h"
+#include "third_party/iwlwifi/platform/align.h"
#include "third_party/iwlwifi/platform/device.h"
#include "third_party/iwlwifi/platform/module.h"
#ifdef CPTCFG_IWLWIFI_SUPPORT_DEBUG_OVERRIDES
-#include "iwl-dbg-cfg.h"
+#include "third_party/iwlwifi/iwl-dbg-cfg.h"
#endif
#ifdef CPTCFG_IWLWIFI_DEVICE_TESTMODE
-#include "iwl-tm-gnl.h"
+#include "third_party/iwlwifi/iwl-tm-gnl.h"
#endif
#define FIRMWARE_DIR "iwlwifi"
diff --git a/third_party/iwlwifi/iwl-eeprom-parse.c b/third_party/iwlwifi/iwl-eeprom-parse.c
index 7cf77e4..049f94e 100644
--- a/third_party/iwlwifi/iwl-eeprom-parse.c
+++ b/third_party/iwlwifi/iwl-eeprom-parse.c
@@ -682,12 +682,11 @@
return n;
}
-#if 0 // NEEDS_PORTING
#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
void iwl_init_ht_hw_capab(const struct iwl_cfg* cfg, struct iwl_nvm_data* data,
- struct ieee80211_sta_ht_cap* ht_info, enum nl80211_band band,
+ struct ieee80211_sta_ht_cap* ht_info, wlan_info_band_t band,
uint8_t tx_chains, uint8_t rx_chains) {
int max_bit_rate = 0;
@@ -754,8 +753,8 @@
/* Highest supported Rx data rate */
max_bit_rate *= rx_chains;
- WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
- ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
+ ZX_ASSERT(~(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK));
+ ht_info->mcs.rx_highest_le = cpu_to_le16(max_bit_rate);
/* Tx MCS capabilities */
ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
@@ -765,6 +764,8 @@
}
}
+#if 0 // NEEDS_PORTING
+
static void iwl_init_sbands(struct device* dev, const struct iwl_cfg* cfg,
struct iwl_nvm_data* data, const uint8_t* eeprom, size_t eeprom_size) {
int n_channels = iwl_init_channel_map(dev, cfg, data, eeprom, eeprom_size);
@@ -881,4 +882,4 @@
return NULL;
}
IWL_EXPORT_SYMBOL(iwl_parse_eeprom_data);
-#endif // NEEDS_PORTING
+#endif // NEEDS_PORTING
diff --git a/third_party/iwlwifi/iwl-eeprom-parse.h b/third_party/iwlwifi/iwl-eeprom-parse.h
index d8041c3..62d8b6a 100644
--- a/third_party/iwlwifi/iwl-eeprom-parse.h
+++ b/third_party/iwlwifi/iwl-eeprom-parse.h
@@ -34,7 +34,7 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_IWL_EEPROM_PARSE_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_IWL_EEPROM_PARSE_H_
-#include <fuchsia/hardware/wlanphyinfo/c/banjo.h>
+#include <fuchsia/hardware/wlan/phyinfo/c/banjo.h>
#include "third_party/iwlwifi/iwl-trans.h"
#include "third_party/iwlwifi/platform/compiler.h"
diff --git a/third_party/iwlwifi/iwl-nvm-parse.c b/third_party/iwlwifi/iwl-nvm-parse.c
index e4b9e88..9a19eaa 100644
--- a/third_party/iwlwifi/iwl-nvm-parse.c
+++ b/third_party/iwlwifi/iwl-nvm-parse.c
@@ -46,7 +46,7 @@
#include "third_party/iwlwifi/iwl-io.h"
#include "third_party/iwlwifi/iwl-modparams.h"
#include "third_party/iwlwifi/iwl-prph.h"
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
/* NVM offsets (in words) definitions */
enum nvm_offsets {
@@ -327,7 +327,7 @@
n_channels++;
channel->ch_num = nvm_chan[ch_idx];
- channel->band = is_5ghz ? WLAN_INFO_BAND_5GHZ : WLAN_INFO_BAND_2GHZ;
+ channel->band = is_5ghz ? WLAN_INFO_BAND_FIVE_GHZ : WLAN_INFO_BAND_TWO_GHZ;
channel->center_freq = ieee80211_get_center_freq((uint8_t)channel->ch_num);
/* Initialize regulatory-based run-time data */
@@ -739,32 +739,36 @@
struct ieee80211_supported_band* sband;
n_channels = iwl_init_channel_map(dev, cfg, data, nvm_ch_flags, sbands_flags);
- sband = &data->bands[WLAN_INFO_BAND_2GHZ];
- sband->band = WLAN_INFO_BAND_2GHZ;
+ sband = &data->bands[WLAN_INFO_BAND_TWO_GHZ];
+ sband->band = WLAN_INFO_BAND_TWO_GHZ;
sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS];
sband->n_bitrates = N_RATES_24;
- n_used += iwl_init_sband_channels(data, sband, n_channels, WLAN_INFO_BAND_2GHZ);
-#if 0 // NEEDS_PORTING
- // TODO(36683): HT support.
- iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_2GHZ, tx_chains, rx_chains);
+ n_used += iwl_init_sband_channels(data, sband, n_channels, WLAN_INFO_BAND_TWO_GHZ);
+ iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, WLAN_INFO_BAND_TWO_GHZ, tx_chains, rx_chains);
+
+#if 0 // NEEDS_PORTING
+ // TODO(84773): HE support.
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax) {
iwl_init_he_hw_capab(sband, tx_chains, rx_chains);
}
#endif // NEEDS_PORTING
- sband = &data->bands[WLAN_INFO_BAND_5GHZ];
- sband->band = WLAN_INFO_BAND_5GHZ;
+ sband = &data->bands[WLAN_INFO_BAND_FIVE_GHZ];
+ sband->band = WLAN_INFO_BAND_FIVE_GHZ;
sband->bitrates = &iwl_cfg80211_rates[RATES_52_OFFS];
sband->n_bitrates = N_RATES_52;
- n_used += iwl_init_sband_channels(data, sband, n_channels, WLAN_INFO_BAND_5GHZ);
+ n_used += iwl_init_sband_channels(data, sband, n_channels, WLAN_INFO_BAND_FIVE_GHZ);
+
+ iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, WLAN_INFO_BAND_FIVE_GHZ, tx_chains, rx_chains);
+
#if 0 // NEEDS_PORTING
- // TODO(36683): HT support.
- iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, NL80211_BAND_5GHZ, tx_chains, rx_chains);
+ // TODO(36684): Supports VHT (802.11ac)
if (data->sku_cap_11ac_enable && !iwlwifi_mod_params.disable_11ac) {
iwl_init_vht_hw_capab(trans, data, &sband->vht_cap, tx_chains, rx_chains);
}
+ // TODO(84773): HE support.
if (data->sku_cap_11ax_enable && !iwlwifi_mod_params.disable_11ax) {
iwl_init_he_hw_capab(sband, tx_chains, rx_chains);
}
@@ -1058,8 +1062,8 @@
}
#ifdef CPTCFG_IWLWIFI_SUPPORT_DEBUG_OVERRIDES
- iwl_init_he_override(trans, &data->bands[WLAN_INFO_BAND_2GHZ]);
- iwl_init_he_override(trans, &data->bands[WLAN_INFO_BAND_5GHZ]);
+ iwl_init_he_override(trans, &data->bands[WLAN_INFO_BAND_TWO_GHZ]);
+ iwl_init_he_override(trans, &data->bands[WLAN_INFO_BAND_FIVE_GHZ]);
#endif
if (lar_fw_supported && lar_enabled) {
sbands_flags |= IWL_NVM_SBANDS_FLAGS_LAR;
diff --git a/third_party/iwlwifi/iwl-trans.c b/third_party/iwlwifi/iwl-trans.c
index caeadc0..c1a78d1 100644
--- a/third_party/iwlwifi/iwl-trans.c
+++ b/third_party/iwlwifi/iwl-trans.c
@@ -87,7 +87,8 @@
ret = trans->ops->send_cmd(trans, cmd);
- if (WARN_ON((cmd->flags & CMD_WANT_SKB) && !ret && !cmd->resp_pkt)) {
+ if ((cmd->flags & CMD_WANT_SKB) && !ret && !cmd->resp_pkt) {
+ IWL_ERR(trans, "%s(): WANT_SKB required but no resp pkt attached.\n", __func__);
return ZX_ERR_IO;
}
diff --git a/third_party/iwlwifi/iwl-trans.h b/third_party/iwlwifi/iwl-trans.h
index 774cf62..88ef902 100644
--- a/third_party/iwlwifi/iwl-trans.h
+++ b/third_party/iwlwifi/iwl-trans.h
@@ -36,6 +36,10 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_IWL_TRANS_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_IWL_TRANS_H_
+// ToDo(rsakthi): war sinde defines isnt working in bazel.
+#define CPTCFG_IWLMVM 1
+#define CPTCFG_IWL_TIMEOUT_FACTOR 1
+
#include "third_party/iwlwifi/fw/img.h"
#include "third_party/iwlwifi/iwl-config.h"
#include "third_party/iwlwifi/iwl-debug.h"
diff --git a/third_party/iwlwifi/iwlwifi_driver-info.json b/third_party/iwlwifi/iwlwifi_driver-info.json
new file mode 100644
index 0000000..a80c124
--- /dev/null
+++ b/third_party/iwlwifi/iwlwifi_driver-info.json
@@ -0,0 +1,16 @@
+{
+ "short_description": "Intel WLAN SoftMAC driver",
+ "manufacturer": "Intel",
+ "families": [
+ "iwlwifi"
+ ],
+ "models": [
+ "7265",
+ "8265",
+ "9260"
+ ],
+ "areas": [
+ "Connectivity",
+ "Wlan"
+ ]
+}
diff --git a/third_party/iwlwifi/mvm/API_rates.h b/third_party/iwlwifi/mvm/API_rates.h
index 7edd932..c8884dc 100644
--- a/third_party/iwlwifi/mvm/API_rates.h
+++ b/third_party/iwlwifi/mvm/API_rates.h
@@ -408,14 +408,14 @@
// bit-13 0==>normal guard interval 1==>short guard interval
#define RATE_MCS_SGI_POS 13
#define RATE_MCS_SGI_MSK (1 << RATE_MCS_SGI_POS)
-// bit-14 0==>chain A incative 1==>chain A active
+// bit-14 0==>chain A inactive 1==>chain A active
#define RATE_MCS_ANT_A_POS 14
-// bit-15 0==>chain B incative 1==>chain B active
+// bit-15 0==>chain B inactive 1==>chain B active
#define RATE_MCS_ANT_B_POS 15
// new flags in shiloh (ext_flags)
-// bit-16 0==>chain B incative 1==>chain B active
+// bit-16 0==>chain B inactive 1==>chain B active
#define RATE_MCS_ANT_C_POS 16
// bit-15:14 mask for both ant.
#define RATE_MCS_ANT_AB_MSK (RATE_MCS_ANT_A_MSK | RATE_MCS_ANT_B_MSK)
@@ -904,10 +904,10 @@
#define GET_HT_VHT_HE_RATE_CODE_API_M(c_rate) GET_HT_VHT_RATE_CODE_API_M_VER_1(c_rate)
// vht supported
-#define GET_MIMO_INDEX_API_M_VER_3(c_rate) \
- (IS_RATE_OFDM_HT_API_M_VER_2(c_rate) \
- ? GET_HT_MIMO_INDEX_API_M_VER_1(c_rate) \
- : IS_RATE_OFDM_VHT_HE_API_M(c_rate) ? GET_VHT_MIMO_INDX_API_M_VER_1(c_rate) : SISO_INDX)
+#define GET_MIMO_INDEX_API_M_VER_3(c_rate) \
+ (IS_RATE_OFDM_HT_API_M_VER_2(c_rate) ? GET_HT_MIMO_INDEX_API_M_VER_1(c_rate) \
+ : IS_RATE_OFDM_VHT_HE_API_M(c_rate) ? GET_VHT_MIMO_INDX_API_M_VER_1(c_rate) \
+ : SISO_INDX)
/**@} GroupRates */
diff --git a/third_party/iwlwifi/mvm/BUILD.bazel b/third_party/iwlwifi/mvm/BUILD.bazel
index 2e98f2d..8a9a5dc 100644
--- a/third_party/iwlwifi/mvm/BUILD.bazel
+++ b/third_party/iwlwifi/mvm/BUILD.bazel
@@ -16,6 +16,8 @@
"ops.c",
"phy-ctxt.c",
"power.c",
+ "rateScaleMng.c",
+ "rs-ng.c",
"rx.c",
"rxmq.c",
"scan.c",
@@ -41,17 +43,14 @@
"tof.h",
],
deps = [
- # "//zircon/system/ulib/zircon-internal",
- # "//garnet/lib/wlan/protocol:protocol",
- "@fuchsia_sdk//fidl/fuchsia_hardware_wlanphyinfo:fuchsia_hardware_wlanphyinfo_banjo_cc",
- "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_info:fuchsia_hardware_wlan_info_banjo_cc",
+ "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_phyinfo:fuchsia_hardware_wlan_phyinfo_banjo_cc",
+ "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_associnfo:fuchsia_hardware_wlan_associnfo_banjo_cc",
+ "@fuchsia_sdk//fidl/fuchsia_hardware_wlanphyimpl:fuchsia_hardware_wlanphyimpl_banjo_cc",
"@fuchsia_sdk//fidl/fuchsia_wlan_ieee80211:fuchsia_wlan_ieee80211_llcpp_cc",
"//third_party/iwlwifi:core",
"//third_party/iwlwifi/fw:fw",
"//third_party/iwlwifi/fw:api",
- "//third_party/iwlwifi/platform:platform",
+ "//third_party/iwlwifi/platform:platform",
"@fuchsia_sdk//pkg/ddk",
-# "//zircon/system/public",
-# "//zircon/system/ulib/async",
],
)
diff --git a/third_party/iwlwifi/mvm/BUILD.gn b/third_party/iwlwifi/mvm/BUILD.gn
index cf10c18..b11247f 100644
--- a/third_party/iwlwifi/mvm/BUILD.gn
+++ b/third_party/iwlwifi/mvm/BUILD.gn
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-visibility = [ "//src/iwlwifi/*" ]
+visibility = [ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/*" ]
source_set("mvm") {
sources = [
@@ -15,6 +15,8 @@
"ops.c",
"phy-ctxt.c",
"power.c",
+ "rateScaleMng.c",
+ "rs-ng.c",
"rx.c",
"rxmq.c",
"scan.c",
@@ -39,16 +41,14 @@
"time-event.h",
"tof.h",
]
- deps = [ "//zircon/system/ulib/zircon-internal" ]
public_deps = [
- "//garnet/lib/wlan/protocol:protocol",
- "//sdk/banjo/ddk.hw.wlan.wlaninfo:ddk.hw.wlan.wlaninfo_banjo_c",
- "//sdk/banjo/fuchsia.hardware.wlan.info:fuchsia.hardware.wlan.info_banjo_c",
+ "//sdk/banjo/fuchsia.hardware.wlan.associnfo:fuchsia.hardware.wlan.associnfo_banjo_c",
+ "//sdk/banjo/fuchsia.hardware.wlan.phyinfo:fuchsia.hardware.wlan.phyinfo_banjo_c",
"//sdk/fidl/fuchsia.wlan.ieee80211:fuchsia.wlan.ieee80211_c",
- "//src/iwlwifi:core",
- "//src/iwlwifi/fw",
- "//src/iwlwifi/fw:api",
- "//src/iwlwifi/platform",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/fw",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/fw:api",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform",
"//src/lib/ddk",
"//zircon/system/public",
"//zircon/system/ulib/async",
diff --git a/third_party/iwlwifi/mvm/_rateScaleMng.h b/third_party/iwlwifi/mvm/_rateScaleMng.h
index a4214f4..3ebaefe 100644
--- a/third_party/iwlwifi/mvm/_rateScaleMng.h
+++ b/third_party/iwlwifi/mvm/_rateScaleMng.h
@@ -36,8 +36,12 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_MVM__RATESCALEMNG_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_MVM__RATESCALEMNG_H_
+#include "third_party/iwlwifi/iwl-config.h"
+#include "third_party/iwlwifi/mvm/API_rates.h"
#include "third_party/iwlwifi/mvm/apiGroupDatapath.h"
#include "third_party/iwlwifi/mvm/apiVersion.h"
+#include "third_party/iwlwifi/platform/compiler.h"
+#include "third_party/iwlwifi/platform/debug.h"
#define RS_MNG_INVALID_VAL ((U32)-1)
#define RS_MNG_RATE_MIN_FAILURE_TH 3
@@ -135,11 +139,11 @@
};
typedef struct _RS_MNG_STA_LIMITS_S {
- U32 successFramesLimit; // successfull frames threshold for starting a search cycle.
- U32 failedFramesLimit; // failed frames threshold for starting a search cycle.
- U32 statsFlushTimeLimit; // time thrshold for starting a search cycle, in usec.
- U32 clearTblWindowsLimit; // txed frames threshold for clearing table windows during
- // stay-in-col.
+ uint32_t successFramesLimit; // successfull frames threshold for starting a search cycle.
+ uint32_t failedFramesLimit; // failed frames threshold for starting a search cycle.
+ uint32_t statsFlushTimeLimit; // time thrshold for starting a search cycle, in usec.
+ uint32_t clearTblWindowsLimit; // txed frames threshold for clearing table windows during
+ // stay-in-col.
} RS_MNG_STA_LIMITS_S;
// TX AMSDU size
@@ -217,7 +221,7 @@
RS_MCS_NUM,
} RS_MCS_E;
-#define RS_MNG_MAX_RATES_NUM MAX((U08)RS_NON_HT_RATE_NUM, (U08)RS_MCS_NUM)
+#define RS_MNG_MAX_RATES_NUM MAX((uint8_t)RS_NON_HT_RATE_NUM, (uint8_t)RS_MCS_NUM)
typedef enum _RS_MNG_STATE_E {
RS_MNG_STATE_SEARCH_CYCLE_STARTED,
@@ -255,7 +259,7 @@
} RS_MNG_COLUMN_DESC_E;
/***********************************/
-typedef U16 TPT_BY_RATE_ARR[RS_MNG_MAX_RATES_NUM];
+typedef uint16_t TPT_BY_RATE_ARR[RS_MNG_MAX_RATES_NUM];
/**************************************************/
@@ -329,14 +333,14 @@
U08 ignoreNextTlcNotif; // The next notification recieved from lmac is irrelevant.
// Could happen if aggregations are opened in the middle of a
// search cycle.
- U08 tryingRateUpscale; // TRUE if now trying to upscale the rate.
- U32 lastRateUpscaleTimeJiffies; // system time of last rate upscale attempt.
- U32 totalFramesFailed; // total failed frames, any/all rates //total_failed
+ U08 tryingRateUpscale; // TRUE if now trying to upscale the rate.
+ zx_time_t lastRateUpscaleTimestamp; // system time of last rate upscale attempt.
+ U32 totalFramesFailed; // total failed frames, any/all rates //total_failed
U32 totalFramesSuccess;
U16 framesSinceLastRun; // number of frames sent since the last time rateScalePerform
// ran.
- U32 lastSearchCycleEndTimeJiffies; // time since end of last search cycle
- U32 txedFrames; // number of txed frames while stay in column, before clearing
+ zx_time_t lastSearchCycleEndTimestamp; // time since end of last search cycle
+ U32 txedFrames; // number of txed frames while stay in column, before clearing
// the all the stat windows in the current table.
U32 visitedColumns; // bitmask of TX columns that were tested during this search cycle
U32 searchBw; // holds a new bandwidth to try before ending a search cycle,
@@ -352,11 +356,11 @@
RS_MNG_TX_AMSDU_SIZE_E amsduEnabledSize;
U32 trafficLoad;
U08 amsduBlacklist;
- U32 lastTrafficLoadStatJiffies;
+ zx_time_t lastTrafficLoadStatTimestamp;
U32 failSafeCounter;
bool isUpscaleSearchCycle; // TRUE if last search cycle started because of passing success
// frame limit.
- U32 lastEnableJiffies; // timestamp of the last TX AMSDU enablement
+ zx_time_t lastEnableTimestamp; // timestamp of the last TX AMSDU enablement
RATE_MCS_API_U lastNotifiedRate;
@@ -385,12 +389,14 @@
ALLOW_COL_FUNC_F checks[MAX_COLUMN_CHECKS];
};
+uint64_t nonht_rate_to_bit(uint8_t rate_value);
+
static INLINE U08 rsMngGetDualAntMsk(void) { return TLC_MNG_CHAIN_A_MSK | TLC_MNG_CHAIN_B_MSK; }
static INLINE U08 _rsMngGetSingleAntMsk(U08 chainsEnabled, uint8_t non_shared_ant,
uint8_t valid_tx_ant) {
- BUILD_BUG_ON(TLC_MNG_CHAIN_A_MSK != ANT_A);
- BUILD_BUG_ON(TLC_MNG_CHAIN_B_MSK != ANT_B);
+ ZX_ASSERT(TLC_MNG_CHAIN_A_MSK == ANT_A);
+ ZX_ASSERT(TLC_MNG_CHAIN_B_MSK == ANT_B);
// Since TLC offload only supports 2 chains, if the non-shared antenna isn't enabled,
// chainsEnabled must have exactly one chain enabled.
return (U08)(valid_tx_ant != rsMngGetDualAntMsk()
@@ -398,6 +404,10 @@
: (non_shared_ant & chainsEnabled ? non_shared_ant : chainsEnabled));
}
+void cmdHandlerTlcMngConfig(struct iwl_mvm* mvm, struct iwl_mvm_sta* mvmsta,
+ RS_MNG_STA_INFO_S* staInfo, TLC_MNG_CONFIG_PARAMS_CMD_API_S* config,
+ bool reconfigure);
+
#define rsMngGetSingleAntMsk(chainsEnabled) \
(_rsMngGetSingleAntMsk((chainsEnabled), staInfo->mvm->cfg->non_shared_ant, \
iwl_mvm_get_valid_tx_ant(staInfo->mvm)))
diff --git a/third_party/iwlwifi/mvm/apiGroupDatapath.h b/third_party/iwlwifi/mvm/apiGroupDatapath.h
index 9ff3e5b..1ffe9d4 100644
--- a/third_party/iwlwifi/mvm/apiGroupDatapath.h
+++ b/third_party/iwlwifi/mvm/apiGroupDatapath.h
@@ -44,7 +44,7 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_MVM_APIGROUPDATAPATH_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_MVM_APIGROUPDATAPATH_H_
-#include <fuchsia/hardware/wlanphyinfo/c/banjo.h>
+#include <fuchsia/hardware/wlan/phyinfo/c/banjo.h>
/* ***************************************************************************
* 0x0F - GRP_DATAPATH_TLC_MNG_CONFIG_CMD
@@ -140,13 +140,13 @@
#define TLC_AMSDU_SUPPORTED 1
typedef struct _TLC_MNG_CONFIG_PARAMS_CMD_API_S_VER_2 {
- U08 maxChWidth; // one of TLC_MNG_CH_WIDTH_E
- U08 bestSuppMode; // best mode supported - as defined above in TLC_MNG_MODE_E
- U08 chainsEnabled; // bitmask of TLC_MNG_CHAIN_[A/B]_MSK
- U08 amsduSupported; // TX AMSDU transmission is supported
+ uint8_t maxChWidth; // one of TLC_MNG_CH_WIDTH_E
+ uint8_t bestSuppMode; // best mode supported - as defined above in TLC_MNG_MODE_E
+ uint8_t chainsEnabled; // bitmask of TLC_MNG_CHAIN_[A/B]_MSK
+ uint8_t amsduSupported; // TX AMSDU transmission is supported
// Use TLC_AMSDU_[NOT_]SUPPORTED
- U16 configFlags; // bitmask of TLC_MNG_CONFIG_FLAGS_*
- U16 nonHt; // bitmap of supported non-HT CCK and OFDM rates
+ uint16_t configFlags; // bitmask of TLC_MNG_CONFIG_FLAGS_*
+ uint16_t nonHt; // bitmap of supported non-HT CCK and OFDM rates
/* bit | rate
-------|--------
0 | R_1M CCK
@@ -162,16 +162,16 @@
10 | R_48M OFDM
11 | R_54M OFDM
*/
- U16 mcs[TLC_MNG_NSS_MAX][2]; // supported HT/VHT/HE rates per nss. [0] for 80mhz width
+ uint16_t mcs[TLC_MNG_NSS_MAX][2]; // supported HT/VHT/HE rates per nss. [0] for 80mhz width
// and lower, [1] for 160mhz.
// This is done in order to conform with HE capabilites.
- U16 maxMpduLen; // Max length of MPDU, in bytes.
+ uint16_t maxMpduLen; // Max length of MPDU, in bytes.
// Used to calculate allowed A-MSDU sizes.
- U08 sgiChWidthSupport; // bitmap of SGI support per channel width.
+ uint8_t sgiChWidthSupport; // bitmap of SGI support per channel width.
// use 1 << BIT(TLC_MNG_CH_WIDTH_*) to indicate sgi support
// for that channel width.
// unused for HE.
- U08 reserved1[1];
+ uint8_t reserved1[1];
wlan_info_band_t band;
} TLC_MNG_CONFIG_PARAMS_CMD_API_S_VER_2;
diff --git a/third_party/iwlwifi/mvm/binding.c b/third_party/iwlwifi/mvm/binding.c
index b68ac79..16eda6e 100644
--- a/third_party/iwlwifi/mvm/binding.c
+++ b/third_party/iwlwifi/mvm/binding.c
@@ -59,7 +59,7 @@
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT)) {
size = sizeof(cmd);
- if (iwl_mvm_get_channel_band(phyctxt->chandef.primary) == WLAN_INFO_BAND_2GHZ ||
+ if (iwl_mvm_get_channel_band(phyctxt->chandef.primary) == WLAN_INFO_BAND_TWO_GHZ ||
!iwl_mvm_is_cdb_supported(mvm)) {
cmd.lmac_id = cpu_to_le32(IWL_LMAC_24G_INDEX);
} else {
diff --git a/third_party/iwlwifi/mvm/fw.c b/third_party/iwlwifi/mvm/fw.c
index 3888e8f..ccd395f 100644
--- a/third_party/iwlwifi/mvm/fw.c
+++ b/third_party/iwlwifi/mvm/fw.c
@@ -1235,17 +1235,16 @@
goto error;
}
-#if 0 // NEEDS_PORTING
- /*
- * RTNL is not taken during Ct-kill, but we don't need to scan/Tx
- * anyway, so don't init MCC.
- */
- // TODO(42213): port this function.
- if (!test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status)) {
- ret = iwl_mvm_init_mcc(mvm);
- if (ret) { goto error; }
+ /*
+ * RTNL is not taken during Ct-kill, but we don't need to scan/Tx
+ * anyway, so don't init MCC.
+ */
+ if (!test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status)) {
+ ret = iwl_mvm_init_mcc(mvm);
+ if (ret != ZX_OK) {
+ goto error;
}
-#endif // NEEDS_PORTING
+ }
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
mvm->scan_type = IWL_SCAN_TYPE_NOT_SET;
diff --git a/third_party/iwlwifi/mvm/mac-ctxt.c b/third_party/iwlwifi/mvm/mac-ctxt.c
index b0be0e1..528bcfd 100644
--- a/third_party/iwlwifi/mvm/mac-ctxt.c
+++ b/third_party/iwlwifi/mvm/mac-ctxt.c
@@ -39,6 +39,7 @@
#include "third_party/iwlwifi/mvm/fw-api.h"
#include "third_party/iwlwifi/mvm/mvm.h"
#include "third_party/iwlwifi/mvm/time-event.h"
+#include "third_party/iwlwifi/platform/rcu.h"
const uint8_t iwl_mvm_ac_to_tx_fifo[] = {
IWL_MVM_TX_FIFO_VO,
@@ -511,10 +512,10 @@
cmd->action = cpu_to_le32(action);
switch (mvmvif->mac_role) {
- case WLAN_INFO_MAC_ROLE_CLIENT:
+ case WLAN_MAC_ROLE_CLIENT:
cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_BSS_STA);
break;
- case WLAN_INFO_MAC_ROLE_AP:
+ case WLAN_MAC_ROLE_AP:
cmd->mac_type = cpu_to_le32(FW_MAC_TYPE_GO);
break;
#if 0 // NEEDS_PORTING
@@ -542,9 +543,9 @@
eth_broadcast_addr(cmd->bssid_addr);
}
- rcu_read_lock();
+ iwl_rcu_read_lock(mvm->dev);
iwl_mvm_ack_rates(mvmvif, band, &cck_ack_rates, &ofdm_ack_rates);
- rcu_read_unlock();
+ iwl_rcu_read_unlock(mvm->dev);
cmd->cck_rates = cpu_to_le32((uint32_t)cck_ack_rates);
cmd->ofdm_rates = cpu_to_le32((uint32_t)ofdm_ack_rates);
@@ -597,10 +598,10 @@
struct iwl_mac_ctx_cmd cmd = {};
struct iwl_mac_data_sta* ctxt_sta;
- WARN_ON(mvmvif->mac_role != WLAN_INFO_MAC_ROLE_CLIENT);
+ WARN_ON(mvmvif->mac_role != WLAN_MAC_ROLE_CLIENT);
/* Fill the common data for all mac context types */
- iwl_mvm_mac_ctxt_cmd_common(mvmvif, WLAN_INFO_BAND_2GHZ, // Use default value.
+ iwl_mvm_mac_ctxt_cmd_common(mvmvif, WLAN_INFO_BAND_TWO_GHZ, // Use default value.
mvmvif->ht_enabled, &cmd, bssid_override, action);
#if 1 // NEEDS_PORTING
@@ -1122,7 +1123,7 @@
static zx_status_t iwl_mvm_mac_ctx_send(struct iwl_mvm_vif* mvmvif, uint32_t action,
bool force_assoc_off, const uint8_t* bssid_override) {
switch (mvmvif->mac_role) {
- case WLAN_INFO_MAC_ROLE_CLIENT:
+ case WLAN_MAC_ROLE_CLIENT:
return iwl_mvm_mac_ctxt_cmd_sta(mvmvif, action, force_assoc_off, bssid_override);
break;
#if 0 // NEEDS_PORTING
diff --git a/third_party/iwlwifi/mvm/mac80211.c b/third_party/iwlwifi/mvm/mac80211.c
index 1dd56ea..a398583 100644
--- a/third_party/iwlwifi/mvm/mac80211.c
+++ b/third_party/iwlwifi/mvm/mac80211.c
@@ -34,7 +34,7 @@
*
*****************************************************************************/
-#include <fuchsia/hardware/wlan/info/c/banjo.h>
+#include <fuchsia/hardware/wlan/associnfo/c/banjo.h>
#include <string.h>
#include <zircon/status.h>
@@ -53,7 +53,8 @@
#include "third_party/iwlwifi/mvm/sta.h"
#include "third_party/iwlwifi/mvm/time-event.h"
#include "third_party/iwlwifi/mvm/tof.h"
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
+#include "third_party/iwlwifi/platform/rcu.h"
#ifdef CPTCFG_IWLWIFI_DEVICE_TESTMODE
#include "third_party/iwlwifi/iwl-dnt-cfg.h"
#include "third_party/iwlwifi/iwl-dnt-dispatch.h"
@@ -284,50 +285,60 @@
}
}
-#if 0 // NEEDS_PORTING
-struct ieee80211_regdomain* iwl_mvm_get_regdomain(struct wiphy* wiphy, const char* alpha2,
- enum iwl_mcc_source src_id, bool* changed) {
- struct ieee80211_regdomain* regd = NULL;
- struct ieee80211_hw* hw = wiphy_to_ieee80211_hw(wiphy);
- struct iwl_mvm* mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mcc_update_resp* resp;
+zx_status_t iwl_mvm_get_regdomain(struct iwl_mvm* mvm, const char* alpha2,
+ enum iwl_mcc_source src_id, bool* changed,
+ wlanphy_country_t* out_country) {
+ wlanphy_country_t country = {};
+ wlanphy_country_t* regd = &country;
+ struct iwl_mcc_update_resp* resp;
- IWL_DEBUG_LAR(mvm, "Getting regdomain data for %s from FW\n", alpha2);
+ ZX_ASSERT(out_country);
- iwl_assert_lock_held(&mvm->mutex);
+ IWL_DEBUG_LAR(mvm, "Getting regdomain data for %s from FW\n", alpha2);
- resp = iwl_mvm_update_mcc(mvm, alpha2, src_id);
- if (IS_ERR_OR_NULL(resp)) {
- IWL_DEBUG_LAR(mvm, "Could not get update from FW %d\n", PTR_ERR_OR_ZERO(resp));
- goto out;
- }
+ iwl_assert_lock_held(&mvm->mutex);
- if (changed) {
- uint32_t status = le32_to_cpu(resp->status);
+ zx_status_t ret = iwl_mvm_update_mcc(mvm, alpha2, src_id, &resp);
+ if (ret != ZX_OK) {
+ IWL_DEBUG_LAR(mvm, "Could not get update from FW %s\n", zx_status_get_string(ret));
+ goto out;
+ }
- *changed = (status == MCC_RESP_NEW_CHAN_PROFILE || status == MCC_RESP_ILLEGAL);
- }
+ if (changed) {
+ uint32_t status = le32_to_cpu(resp->status);
- regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg, __le32_to_cpu(resp->n_channels),
- resp->channels, __le16_to_cpu(resp->mcc),
- __le16_to_cpu(resp->geo_info));
- /* Store the return source id */
- src_id = resp->source_id;
- kfree(resp);
- if (IS_ERR_OR_NULL(regd)) {
- IWL_DEBUG_LAR(mvm, "Could not get parse update from FW %d\n", PTR_ERR_OR_ZERO(regd));
- goto out;
- }
+ *changed = (status == MCC_RESP_NEW_CHAN_PROFILE || status == MCC_RESP_ILLEGAL);
+ }
- IWL_DEBUG_LAR(mvm, "setting alpha2 from FW to %s (0x%x, 0x%x) src=%d\n", regd->alpha2,
- regd->alpha2[0], regd->alpha2[1], src_id);
- mvm->lar_regdom_set = true;
- mvm->mcc_src = src_id;
+#if 1 // NEEDS_PORTING
+ country.alpha2[0] = le16_to_cpu(resp->mcc) >> 8;
+ country.alpha2[1] = le16_to_cpu(resp->mcc) & 0xff;
+ *out_country = *regd;
+#else // NEEDS_PORTING
+ // TODO(fxbug.dev/87321): port iwl_parse_nvm_mcc_info()
+ struct ieee80211_regdomain* regd = iwl_parse_nvm_mcc_info(
+ mvm->trans->dev, mvm->cfg, __le32_to_cpu(resp->n_channels), resp->channels,
+ __le16_to_cpu(resp->mcc), __le16_to_cpu(resp->geo_info));
+#endif // NEEDS_PORTING
+
+ /* Store the return source id */
+ src_id = resp->source_id;
+ free(resp);
+ if (ret != ZX_OK) {
+ IWL_DEBUG_LAR(mvm, "Could not get parse update from FW: %s\n", zx_status_get_string(ret));
+ goto out;
+ }
+
+ IWL_DEBUG_LAR(mvm, "setting alpha2 from FW to %c%c (0x%x, 0x%x) src=%d\n", regd->alpha2[0],
+ regd->alpha2[1], regd->alpha2[0], regd->alpha2[1], src_id);
+ mvm->lar_regdom_set = true;
+ mvm->mcc_src = src_id;
out:
- return regd;
+ return ret;
}
+#if 0 // NEEDS_PORTING
void iwl_mvm_update_changed_regdom(struct iwl_mvm* mvm) {
bool changed;
struct ieee80211_regdomain* regd;
@@ -342,13 +353,16 @@
kfree(regd);
}
}
+#endif // NEEDS_PORTING
-struct ieee80211_regdomain* iwl_mvm_get_current_regdomain(struct iwl_mvm* mvm, bool* changed) {
- return iwl_mvm_get_regdomain(
- mvm->hw->wiphy, "ZZ",
- iwl_mvm_is_wifi_mcc_supported(mvm) ? MCC_SOURCE_GET_CURRENT : MCC_SOURCE_OLD_FW, changed);
+zx_status_t iwl_mvm_get_current_regdomain(struct iwl_mvm* mvm, bool* changed,
+ wlanphy_country_t* out_country) {
+ return iwl_mvm_get_regdomain(
+ mvm, "ZZ", iwl_mvm_is_wifi_mcc_supported(mvm) ? MCC_SOURCE_GET_CURRENT : MCC_SOURCE_OLD_FW,
+ changed, out_country);
}
+#if 0 // NEEDS_PORTING
int iwl_mvm_init_fw_regd(struct iwl_mvm* mvm) {
enum iwl_mcc_source used_src;
struct ieee80211_regdomain* regd;
@@ -573,20 +587,15 @@
}
#endif // NEEDS_PORTING
-zx_status_t iwl_mvm_mac_tx(struct iwl_mvm_vif* mvmvif, struct ieee80211_mac_packet* pkt) {
+zx_status_t iwl_mvm_mac_tx(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvmsta,
+ struct ieee80211_mac_packet* pkt) {
iwl_assert_lock_held(&mvmvif->mvm->mutex);
- if (mvmvif->mac_role != WLAN_INFO_MAC_ROLE_CLIENT) {
+ if (mvmvif->mac_role != WLAN_MAC_ROLE_CLIENT) {
IWL_ERR(mvmvif, "%s(): not supported MAC role %d yet\n", __func__, mvmvif->mac_role);
return ZX_ERR_INVALID_ARGS;
}
- struct iwl_mvm_sta* mvmsta = mvmvif->mvm->fw_id_to_mac_id[mvmvif->ap_sta_id];
- if (!mvmsta) {
- IWL_ERR(mvmvif, "%s(): mvmsta is NULL. mvmvif->ap_sta_id=%d\n", __func__, mvmvif->ap_sta_id);
- return ZX_ERR_INTERNAL;
- }
-
return iwl_mvm_tx_skb(mvmvif->mvm, pkt, mvmsta);
#if 0 // NEEDS_PORTING
@@ -1451,6 +1460,7 @@
zx_status_t iwl_mvm_mac_remove_interface(struct iwl_mvm_vif* mvmvif) {
struct iwl_mvm* mvm = mvmvif->mvm;
+ struct iwl_probe_resp_data* probe_data;
#if 0 // NEEDS_PORTING
iwl_mvm_prepare_mac_removal(mvm, vif);
@@ -1470,8 +1480,10 @@
mtx_lock(&mvm->mutex);
- free(mvmvif->probe_resp_data);
- mvmvif->probe_resp_data = NULL;
+ probe_data = iwl_rcu_exchange(mvmvif->probe_resp_data, NULL);
+ if (probe_data) {
+ iwl_rcu_free_sync(mvm->dev, probe_data);
+ }
#if 0 // NEEDS_PORTING
if (mvm->bf_allowed_vif == mvmvif) {
@@ -1579,12 +1591,10 @@
return;
}
- // Only associated client interface can continue. Other interfaces will be ignored.
- if (mvmvif->mac_role != WLAN_INFO_MAC_ROLE_CLIENT ||
- mvmvif->mvm->fw_id_to_mac_id[0]->sta_state != IWL_STA_AUTHORIZED) {
- IWL_ERR(mvmvif, "unexpected state while setting mcast filter. role: %d!=%d or state: %d!=%d\n",
- mvmvif->mac_role, WLAN_INFO_MAC_ROLE_CLIENT, mvmvif->mvm->fw_id_to_mac_id[0]->sta_state,
- IWL_STA_AUTHORIZED);
+ // Only client interface can continue. Other interfaces will be ignored.
+ if (mvmvif->mac_role != WLAN_MAC_ROLE_CLIENT || !mvmvif->bss_conf.assoc) {
+ IWL_ERR(mvmvif, "unexpected state while setting mcast filter. role: %d!=%d or assoc: %d!=%d\n",
+ mvmvif->mac_role, WLAN_MAC_ROLE_CLIENT, mvmvif->bss_conf.assoc, true);
return;
}
@@ -2502,22 +2512,30 @@
}
#endif // NEEDS_PORTING
-zx_status_t iwl_mvm_mac_hw_scan(struct iwl_mvm_vif* mvmvif,
- const wlan_hw_scan_config_t* scan_config) {
+// Modified from original iwl_mvm_mac_hw_scan() to split call path for active and passive.
+zx_status_t iwl_mvm_mac_hw_scan_passive(struct iwl_mvm_vif* mvmvif,
+ const wlan_softmac_passive_scan_args_t* passive_scan_args,
+ uint64_t* out_scan_id) {
struct iwl_mvm* mvm = mvmvif->mvm;
zx_status_t ret;
- if (scan_config->num_channels == 0 ||
- scan_config->num_channels > mvm->fw->ucode_capa.n_scan_channels) {
- IWL_WARN(mvmvif, "Cannot scan: invalid #channel (%d). FW's cap (%d)\n",
- scan_config->num_channels, mvm->fw->ucode_capa.n_scan_channels);
+ if (passive_scan_args->channels_count == 0 ||
+ passive_scan_args->channels_count > mvm->fw->ucode_capa.n_scan_channels) {
+ IWL_WARN(mvmvif, "Cannot scan: invalid #channel (%zu). FW's cap (%d)\n",
+ passive_scan_args->channels_count, mvm->fw->ucode_capa.n_scan_channels);
return ZX_ERR_INVALID_ARGS;
}
mtx_lock(&mvm->mutex);
- ret = iwl_mvm_reg_scan_start(mvmvif, scan_config);
+ ret = iwl_mvm_reg_scan_start_passive(mvmvif, passive_scan_args);
mtx_unlock(&mvm->mutex);
+ if (ret != ZX_OK) {
+ return ret;
+ }
+
+ // TODO(fxbug.dev/88934): scan_id is always 0
+ *out_scan_id = 0;
return ret;
}
@@ -2788,7 +2806,7 @@
* attempts to connect to this AP, and eventually wpa_s will
* blacklist the AP...
*/
- if (mvmvif->mac_role == WLAN_INFO_MAC_ROLE_CLIENT && mvmvif->bss_conf.beacon_int < 16) {
+ if (mvmvif->mac_role == WLAN_MAC_ROLE_CLIENT && mvmvif->bss_conf.beacon_int < 16) {
IWL_ERR(mvm, "AP %pM beacon interval is %d, refusing due to firmware bug!\n", mvm_sta->addr,
mvmvif->bss_conf.beacon_int);
ret = ZX_ERR_INVALID_ARGS;
@@ -2826,9 +2844,9 @@
ret = ZX_OK;
} else if (old_state == IWL_STA_AUTH && new_state == IWL_STA_ASSOC) {
-#if 0 // NEEDS_PORTING
- // TODO(36677): Supports AP role
- if (mvmvif->mac_role == WLAN_INFO_MAC_ROLE_AP) {
+#if 0 // NEEDS_PORTING
+ // TODO(36677): Supports AP role
+ if (mvmvif->mac_role == WLAN_MAC_ROLE_AP) {
mvmvif->ap_assoc_sta_count++;
iwl_mvm_mac_ctxt_changed(mvmvif, false, NULL);
if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) {
@@ -2836,8 +2854,8 @@
}
}
- iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, false);
#endif // NEEDS_PORTING
+ iwl_mvm_rs_rate_init(mvm, mvm_sta, false);
ret = iwl_mvm_update_sta(mvm, mvm_sta);
@@ -2862,7 +2880,7 @@
// TODO(36677): Supports AP role
/* if wep is used, need to set the key for the station now */
- if (mvmvif->mac_role == WLAN_INFO_MAC_ROLE_AP && mvmvif->ap_wep_key) {
+ if (mvmvif->mac_role == WLAN_MAC_ROLE_AP && mvmvif->ap_wep_key) {
ret = iwl_mvm_set_sta_key(mvm, vif, sta, mvmvif->ap_wep_key, STA_KEY_IDX_INVALID);
} else {
ret = ZX_OK;
@@ -2877,7 +2895,7 @@
} else if (old_state == IWL_STA_ASSOC && new_state == IWL_STA_AUTH) {
#if 0 // NEEDS_PORTING
// TODO(36677): Supports AP role
- if (mvmvif->mac_role == WLAN_INFO_MAC_ROLE_AP) {
+ if (mvmvif->mac_role == WLAN_MAC_ROLE_AP) {
mvmvif->ap_assoc_sta_count--;
iwl_mvm_mac_ctxt_changed(mvmvif, false, NULL);
}
@@ -2886,17 +2904,6 @@
} else if (old_state == IWL_STA_AUTH && new_state == IWL_STA_NONE) {
ret = ZX_OK;
} else if (old_state == IWL_STA_NONE && new_state == IWL_STA_NOTEXIST) {
- // Delete all set keys
- // TODO(fxbug.dev/86728): remove the WPA2 key workaround
- for (int i = 0; i < STA_KEY_MAX_NUM; i++) {
- if (mvm->active_key_list[i].keylen) {
- // delete the key if present
- if (iwl_mvm_remove_sta_key(mvmvif, mvm_sta, &mvm->active_key_list[i]) != ZX_OK) {
- IWL_ERR(mvm, "Unable to delete key at offset %d", i);
- }
- memset(&mvm->active_key_list[i], 0, sizeof(struct iwl_mvm_sta_key_conf));
- }
- }
ret = iwl_mvm_rm_sta(mvmvif, mvm_sta);
#if 0 // NEEDS_PORTING
if (sta->tdls) {
@@ -3041,58 +3048,146 @@
return ret;
}
+
+static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
+ enum set_key_cmd cmd,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_mvm_sta *mvmsta;
+ struct iwl_mvm_key_pn *ptk_pn;
+ int keyidx = key->keyidx;
+ int ret;
+ u8 key_offset;
+
+ if (iwlwifi_mod_params.swcrypto) {
+ IWL_DEBUG_MAC80211(mvm, "leave - hwcrypto disabled\n");
+ return -EOPNOTSUPP;
+ }
+
+ switch (key->cipher) {
+ case WLAN_CIPHER_SUITE_TKIP:
+ if (!mvm->trans->cfg->gen2) {
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
+ } else if (vif->type == NL80211_IFTYPE_STATION) {
+ key->flags |= IEEE80211_KEY_FLAG_PUT_MIC_SPACE;
+ } else {
+ IWL_DEBUG_MAC80211(mvm, "Use SW encryption for TKIP\n");
+ return -EOPNOTSUPP;
+ }
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ case WLAN_CIPHER_SUITE_GCMP:
+ case WLAN_CIPHER_SUITE_GCMP_256:
+ if (!iwl_mvm_has_new_tx_api(mvm))
+ key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
+ break;
+ case WLAN_CIPHER_SUITE_AES_CMAC:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+ case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+ WARN_ON_ONCE(!ieee80211_hw_check(hw, MFP_CAPABLE));
+ break;
+ case WLAN_CIPHER_SUITE_WEP40:
+ case WLAN_CIPHER_SUITE_WEP104:
+ if (vif->type == NL80211_IFTYPE_AP) {
+ struct iwl_mvm_vif *mvmvif =
+ iwl_mvm_vif_from_mac80211(vif);
+
+ mvmvif->ap_wep_key = kmemdup(key,
+ sizeof(*key) + key->keylen,
+ GFP_KERNEL);
+ if (!mvmvif->ap_wep_key)
+ return -ENOMEM;
+ }
+
+ if (vif->type != NL80211_IFTYPE_STATION)
+ return 0;
+ break;
+ default:
+ /* currently FW supports only one optional cipher scheme */
+ if (hw->n_cipher_schemes &&
+ hw->cipher_schemes->cipher == key->cipher)
+ key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
+ else
+ return -EOPNOTSUPP;
+ }
+
+ switch (cmd) {
+ case SET_KEY:
+ ret = iwl_mvm_mac_add_key(vif, sta, key);
+ case DISABLE_KEY:
+ ret = iwl_mvm_mac_remove_key(vif, sta, key);
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
#endif // NEEDS_PORTING
-zx_status_t iwl_mvm_mac_set_key(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvmsta,
- const struct iwl_mvm_sta_key_conf* key) {
+zx_status_t iwl_mvm_mac_add_key(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvmsta,
+ struct ieee80211_key_conf* key) {
zx_status_t ret = ZX_OK;
struct iwl_mvm* mvm = mvmvif->mvm;
- struct iwl_mvm_key_pn* ptk_pn;
+ struct iwl_mvm_key_pn* ptk_pn = NULL;
uint8_t key_offset = 0;
- if (iwlwifi_mod_params.swcrypto) {
- IWL_DEBUG_MAC80211(mvm, "leave - hwcrypto disabled\n");
- return ZX_ERR_NOT_SUPPORTED;
- }
-
- switch (key->cipher_type) {
+ // Fuchsia only supports a limited selection of cipher types for now.
+ switch (key->cipher) {
case CIPHER_SUITE_TYPE_CCMP_128:
+ // Note: the Linux iwlwifi driver requests IEEE80211_KEY_FLAG_PUT_IV_SPACE from the mac80211
+ // stack. We will apply equivalent functionality manually to Incoming packets from Fuchsia.
if (iwl_mvm_has_new_tx_api(mvm)) {
return ZX_ERR_NOT_SUPPORTED;
}
break;
+ case CIPHER_SUITE_TYPE_BIP_CMAC_128:
+ break;
default:
return ZX_ERR_NOT_SUPPORTED;
}
mtx_lock(&mvm->mutex);
- // Porting note: the following is the equivalent of just the SET_KEY path, as Fuchsia does not
- // have the equivalent to a DELETE_KEY call.
-
- if ((mvmvif->mac_role == WLAN_INFO_MAC_ROLE_MESH || mvmvif->mac_role == WLAN_INFO_MAC_ROLE_AP) &&
- !mvmsta) {
+ if ((mvmvif->mac_role == WLAN_MAC_ROLE_MESH || mvmvif->mac_role == WLAN_MAC_ROLE_AP) && !mvmsta) {
/*
* GTK on AP interface is a TX-only key, return 0;
* on IBSS they're per-station and because we're lazy
* we don't support them for RX, so do the same.
* CMAC/GMAC in AP/IBSS modes must be done in software.
*/
- if (key->cipher_type == CIPHER_SUITE_TYPE_BIP_CMAC_128 ||
- key->cipher_type == CIPHER_SUITE_TYPE_BIP_GMAC_128 ||
- key->cipher_type == CIPHER_SUITE_TYPE_BIP_GMAC_256) {
+ if (key->cipher == CIPHER_SUITE_TYPE_BIP_CMAC_128 ||
+ key->cipher == CIPHER_SUITE_TYPE_BIP_GMAC_128 ||
+ key->cipher == CIPHER_SUITE_TYPE_BIP_GMAC_256) {
ret = ZX_ERR_NOT_SUPPORTED;
} else {
ret = ZX_OK;
}
+
+ if (key->cipher != CIPHER_SUITE_TYPE_GCMP_128 && key->cipher != CIPHER_SUITE_TYPE_GCMP_256 &&
+ !iwl_mvm_has_new_tx_api(mvm)) {
+ key->hw_key_idx = STA_KEY_IDX_INVALID;
+ goto out;
+ }
+ }
+
+ /* During FW restart, in order to restore the state as it was,
+ * don't try to reprogram keys we previously failed for.
+ */
+ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
+ key->hw_key_idx == STA_KEY_IDX_INVALID) {
+ IWL_DEBUG_MAC80211(mvm, "skip invalid idx key programming during restart\n");
+ ret = ZX_OK;
+ goto out;
}
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && mvmsta &&
iwl_mvm_has_new_rx_api(mvm) && key->key_type == WLAN_KEY_TYPE_PAIRWISE &&
- (key->cipher_type == CIPHER_SUITE_TYPE_CCMP_128 ||
-
- key->cipher_type == CIPHER_SUITE_TYPE_GCMP_128 ||
- key->cipher_type == CIPHER_SUITE_TYPE_GCMP_256)) {
+ (key->cipher == CIPHER_SUITE_TYPE_CCMP_128 || key->cipher == CIPHER_SUITE_TYPE_GCMP_128 ||
+ key->cipher == CIPHER_SUITE_TYPE_GCMP_256)) {
int tid, q;
ptk_pn = calloc(1, sizeof(*ptk_pn) + sizeof(ptk_pn->q->pn) * mvm->trans->num_rx_queues);
@@ -3103,19 +3198,15 @@
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
for (q = 0; q < mvm->trans->num_rx_queues; q++) {
- memset(ptk_pn->q[q].pn[tid], 0, IEEE80211_CCMP_PN_LEN);
+ /* The packet number in packet byte order is little-endian */
+ uint64_t pn_le = cpu_to_le64(key->rx_seq);
+ memcpy(ptk_pn->q[q].pn[tid], &pn_le, IEEE80211_CCMP_PN_LEN);
}
}
- struct iwl_mvm_key_pn* old_ptk_pn = NULL;
-
- mtx_lock(&mvmsta->ptk_pn_mutex);
- old_ptk_pn = mvmsta->ptk_pn[key->keyidx];
- mvmsta->ptk_pn[key->keyidx] = ptk_pn;
- mtx_unlock(&mvmsta->ptk_pn_mutex);
-
+ struct iwl_mvm_key_pn* old_ptk_pn = iwl_rcu_exchange(mvmsta->ptk_pn[key->keyidx], ptk_pn);
if (old_ptk_pn) {
- free(old_ptk_pn);
+ iwl_rcu_free_sync(mvm->dev, old_ptk_pn);
}
}
@@ -3143,6 +3234,35 @@
return ret;
}
+zx_status_t iwl_mvm_mac_remove_key(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvmsta,
+ const struct ieee80211_key_conf* key) {
+ zx_status_t ret = ZX_OK;
+ struct iwl_mvm* mvm = mvmvif->mvm;
+ struct iwl_mvm_key_pn* ptk_pn = NULL;
+
+ mtx_lock(&mvm->mutex);
+
+ if (key->hw_key_idx == STA_KEY_IDX_INVALID) {
+ ret = 0;
+ goto out;
+ }
+
+ if (mvmsta && iwl_mvm_has_new_rx_api(mvm) && key->key_type == WLAN_KEY_TYPE_PAIRWISE &&
+ (key->cipher == CIPHER_SUITE_TYPE_CCMP_128 || key->cipher == CIPHER_SUITE_TYPE_GCMP_128 ||
+ key->cipher == CIPHER_SUITE_TYPE_GCMP_256)) {
+ ptk_pn = iwl_rcu_exchange(mvmsta->ptk_pn[key->keyidx], NULL);
+ if (ptk_pn)
+ iwl_rcu_free_sync(mvm->dev, ptk_pn);
+ }
+
+ IWL_DEBUG_MAC80211(mvm, "disable hwcrypto key\n");
+ ret = iwl_mvm_remove_sta_key(mvm, mvmvif, mvmsta, key);
+
+out:
+ mtx_unlock(&mvm->mutex);
+ return ret;
+}
+
#if 0 // NEEDS_PORTING
static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw* hw, struct ieee80211_vif* vif,
struct ieee80211_key_conf* keyconf,
@@ -3553,7 +3673,7 @@
ret = 0;
goto out;
#endif // NEEDS_PORTING
- case WLAN_INFO_MAC_ROLE_CLIENT:
+ case WLAN_MAC_ROLE_CLIENT:
mvmvif->csa_bcn_pending = false;
break;
#if 0 // NEEDS_PORTING
@@ -3605,7 +3725,7 @@
}
#endif // NEEDS_PORTING
- if (switching_chanctx && mvmvif->mac_role == WLAN_INFO_MAC_ROLE_CLIENT) {
+ if (switching_chanctx && mvmvif->mac_role == WLAN_MAC_ROLE_CLIENT) {
uint32_t duration = 3 * mvmvif->bss_conf.beacon_int;
/* iwl_mvm_protect_session() reads directly from the
@@ -3687,7 +3807,7 @@
mvmvif->ap_ibss_active = false;
break;
#endif // NEEDS_PORTING
- case WLAN_INFO_MAC_ROLE_CLIENT:
+ case WLAN_MAC_ROLE_CLIENT:
if (!switching_chanctx) {
break;
}
diff --git a/third_party/iwlwifi/mvm/mvm.h b/third_party/iwlwifi/mvm/mvm.h
index 21d34dd..5d7f71f 100644
--- a/third_party/iwlwifi/mvm/mvm.h
+++ b/third_party/iwlwifi/mvm/mvm.h
@@ -37,13 +37,11 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_MVM_MVM_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_MVM_MVM_H_
+#include <fuchsia/hardware/wlanphyimpl/c/banjo.h>
#include <threads.h>
#include <zircon/listnode.h>
#include <zircon/time.h>
-#include <fuchsia/hardware/wlanphyinfo/c/banjo.h>
-//#include <wlan/protocol/mac.h>
-
#include "third_party/iwlwifi/fw/acpi.h"
#include "third_party/iwlwifi/fw/dbg.h"
#include "third_party/iwlwifi/fw/file.h"
@@ -139,6 +137,7 @@
uint32_t ref;
wlan_channel_t chandef;
+ wlan_info_band_t band;
#ifdef CPTCFG_IWLWIFI_FRQ_MGR
/* Frequency Manager tx power limit*/
@@ -473,9 +472,9 @@
/* Zircon objects */
struct zx_device* zxdev;
- wlan_info_mac_role_t mac_role;
+ wlan_mac_role_t mac_role;
zx_handle_t mlme_channel; // Channel passed from devmgr. Will be passed to MLME at mac_start().
- wlanmac_ifc_protocol_t ifc;
+ wlan_softmac_ifc_protocol_t ifc;
// Merged from 'struct ieee80211_vif'
bool ht_enabled;
@@ -1026,8 +1025,6 @@
*/
unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
uint8_t fw_key_deleted[STA_KEY_MAX_NUM];
- // TODO(fxbug.dev/86728): remove the WPA2 key workaround
- struct iwl_mvm_sta_key_conf active_key_list[STA_KEY_MAX_NUM];
/* references taken by the driver and spinlock protecting them */
mtx_t refs_lock;
@@ -1587,7 +1584,8 @@
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm* mvm, struct sk_buff* skb);
void iwl_mvm_set_tx_cmd(struct iwl_mvm* mvm, struct ieee80211_mac_packet* pkt,
struct iwl_tx_cmd* tx_cmd, uint8_t sta_id);
-void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm* mvm, struct iwl_tx_cmd* tx_cmd);
+void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm* mvm, struct iwl_tx_cmd* tx_cmd,
+ const struct ieee80211_frame_header* hdr);
void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw* hw, struct ieee80211_txq* txq);
unsigned int iwl_mvm_max_amsdu_size(struct iwl_mvm* mvm, struct ieee80211_sta* sta,
unsigned int tid);
@@ -1604,7 +1602,7 @@
void iwl_mvm_async_handlers_purge(struct iwl_mvm* mvm);
-static inline void iwl_mvm_set_tx_cmd_ccmp(struct iwl_mvm_sta_key_conf* keyconf,
+static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_key_conf* keyconf,
struct iwl_tx_cmd* tx_cmd) {
tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
@@ -1767,8 +1765,10 @@
#endif
/* Scanning */
-zx_status_t iwl_mvm_reg_scan_start(struct iwl_mvm_vif* mvmvif,
- const wlan_hw_scan_config_t* scan_config);
+zx_status_t iwl_mvm_reg_scan_start_passive(
+ struct iwl_mvm_vif* mvmvif, const wlan_softmac_passive_scan_args_t* passive_scan_args);
+zx_status_t iwl_mvm_reg_scan_start(struct iwl_mvm_vif* mvmvif, const uint8_t* channel_list_buffer,
+ size_t channel_list_size);
int iwl_mvm_scan_size(struct iwl_mvm* mvm);
int iwl_mvm_scan_stop(struct iwl_mvm* mvm, int type, bool notify);
int iwl_mvm_max_scan_ie_len(struct iwl_mvm* mvm);
@@ -1946,7 +1946,7 @@
* command queue, which can't be flushed.
*/
static inline uint32_t iwl_mvm_flushable_queues(struct iwl_mvm* mvm) {
- return ((BIT(mvm->cfg->base_params->num_of_queues) - 1) & ~BIT(IWL_MVM_DQA_CMD_QUEUE));
+ return ((uint32_t)(BIT(mvm->cfg->base_params->num_of_queues) - 1) & ~BIT(IWL_MVM_DQA_CMD_QUEUE));
}
static inline void iwl_mvm_stop_device(struct iwl_mvm* mvm) {
@@ -2005,14 +2005,27 @@
int iwl_mvm_fm_unregister(struct iwl_mvm* mvm);
#endif
-/* Location Aware Regulatory */
-struct iwl_mcc_update_resp* iwl_mvm_update_mcc(struct iwl_mvm* mvm, const char* alpha2,
- enum iwl_mcc_source src_id);
-int iwl_mvm_init_mcc(struct iwl_mvm* mvm);
+//------------------------------------------------------------------------------------------------
+// Location Aware Regulatory
+
+// Send the 2-byte country code to the firmware.
+//
+// When this function returns ZX_OK, the 'out_resp_cp' will be pointed to a
+// 'struct iwl_mcc_update_resp' object (variable-sized). It is the caller's responsibility
+// to release the memory.
+zx_status_t iwl_mvm_update_mcc(struct iwl_mvm* mvm, const char* alpha2, enum iwl_mcc_source src_id,
+ struct iwl_mcc_update_resp** out_resp_cp);
+
+zx_status_t iwl_mvm_init_mcc(struct iwl_mvm* mvm);
void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm* mvm, struct iwl_rx_cmd_buffer* rxb);
-struct ieee80211_regdomain* iwl_mvm_get_regdomain(struct wiphy* wiphy, const char* alpha2,
- enum iwl_mcc_source src_id, bool* changed);
-struct ieee80211_regdomain* iwl_mvm_get_current_regdomain(struct iwl_mvm* mvm, bool* changed);
+
+zx_status_t iwl_mvm_get_regdomain(struct iwl_mvm* mvm, const char* alpha2,
+ enum iwl_mcc_source src_id, bool* changed,
+ wlanphy_country_t* out_country);
+
+zx_status_t iwl_mvm_get_current_regdomain(struct iwl_mvm* mvm, bool* changed,
+ wlanphy_country_t* out_country);
+
int iwl_mvm_init_fw_regd(struct iwl_mvm* mvm);
void iwl_mvm_update_changed_regdom(struct iwl_mvm* mvm);
@@ -2134,7 +2147,8 @@
//
// Interfaces for mac80211.c
//
-zx_status_t iwl_mvm_mac_tx(struct iwl_mvm_vif* mvmvif, struct ieee80211_mac_packet* pkt);
+zx_status_t iwl_mvm_mac_tx(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvmsta,
+ struct ieee80211_mac_packet* pkt);
zx_status_t iwl_mvm_find_free_mvmvif_slot(struct iwl_mvm* mvm, int* ret_idx);
zx_status_t iwl_mvm_bind_mvmvif(struct iwl_mvm* mvm, int idx, struct iwl_mvm_vif* mvmvif);
@@ -2144,8 +2158,9 @@
void iwl_mvm_configure_filter(struct iwl_mvm* mvm);
-zx_status_t iwl_mvm_mac_hw_scan(struct iwl_mvm_vif* mvmvif,
- const wlan_hw_scan_config_t* scan_config);
+zx_status_t iwl_mvm_mac_hw_scan_passive(struct iwl_mvm_vif* mvmvif,
+ const wlan_softmac_passive_scan_args_t* passive_scan_args,
+ uint64_t* out_scan_id);
zx_status_t iwl_mvm_mac_sta_state(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvm_sta,
enum iwl_sta_state old_state, enum iwl_sta_state new_state);
@@ -2153,8 +2168,10 @@
void iwl_mvm_mac_mgd_prepare_tx(struct iwl_mvm* mvm, struct iwl_mvm_vif* mvmvif,
uint16_t req_duration);
-zx_status_t iwl_mvm_mac_set_key(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvmsta,
- const struct iwl_mvm_sta_key_conf* key);
+zx_status_t iwl_mvm_mac_add_key(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvmsta,
+ struct ieee80211_key_conf* key);
+zx_status_t iwl_mvm_mac_remove_key(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvmsta,
+ const struct ieee80211_key_conf* key);
zx_status_t iwl_mvm_add_chanctx(struct iwl_mvm* mvm, const wlan_channel_t* channeldef,
uint16_t* phy_ctxt_id);
diff --git a/third_party/iwlwifi/mvm/nvm.c b/third_party/iwlwifi/mvm/nvm.c
index 76979e3..e40aafa 100644
--- a/third_party/iwlwifi/mvm/nvm.c
+++ b/third_party/iwlwifi/mvm/nvm.c
@@ -34,6 +34,8 @@
*
*****************************************************************************/
+#include <zircon/status.h>
+
#include "third_party/iwlwifi/fw/acpi.h"
#include "third_party/iwlwifi/iwl-csr.h"
#include "third_party/iwlwifi/iwl-eeprom-parse.h"
@@ -42,6 +44,7 @@
#include "third_party/iwlwifi/iwl-prph.h"
#include "third_party/iwlwifi/iwl-trans.h"
#include "third_party/iwlwifi/mvm/mvm.h"
+#include "third_party/iwlwifi/platform/compiler.h"
#if 0 // NEEDS_PORTING
/*
@@ -430,14 +433,13 @@
return ret;
}
-#if 0 // NEEDS_PORTING
-struct iwl_mcc_update_resp* iwl_mvm_update_mcc(struct iwl_mvm* mvm, const char* alpha2,
- enum iwl_mcc_source src_id) {
+zx_status_t iwl_mvm_update_mcc(struct iwl_mvm* mvm, const char* alpha2, enum iwl_mcc_source src_id,
+ struct iwl_mcc_update_resp** out_resp_cp) {
struct iwl_mcc_update_cmd mcc_update_cmd = {
.mcc = cpu_to_le16(alpha2[0] << 8 | alpha2[1]),
.source_id = (uint8_t)src_id,
};
- struct iwl_mcc_update_resp* resp_cp;
+ struct iwl_mcc_update_resp* resp_cp = NULL;
struct iwl_rx_packet* pkt;
struct iwl_host_cmd cmd = {
.id = MCC_UPDATE_CMD,
@@ -445,22 +447,26 @@
.data = {&mcc_update_cmd},
};
- int ret;
+ zx_status_t ret;
uint32_t status;
int resp_len, n_channels;
uint16_t mcc;
- if (WARN_ON_ONCE(!iwl_mvm_is_lar_supported(mvm))) {
- return ERR_PTR(-EOPNOTSUPP);
+ if (!iwl_mvm_is_lar_supported(mvm)) {
+ IWL_WARN(mvm, "LAR is not supported. Ignore update MCC.\n");
+ return ZX_ERR_NOT_SUPPORTED;
}
+ ZX_ASSERT(out_resp_cp);
+
cmd.len[0] = sizeof(struct iwl_mcc_update_cmd);
IWL_DEBUG_LAR(mvm, "send MCC update to FW with '%c%c' src = %d\n", alpha2[0], alpha2[1], src_id);
ret = iwl_mvm_send_cmd(mvm, &cmd);
- if (ret) {
- return ERR_PTR(ret);
+ if (ret != ZX_OK) {
+ IWL_ERR(mvm, "MCC update command failed: %s\n", zx_status_get_string(ret));
+ return ret;
}
pkt = cmd.resp_pkt;
@@ -469,21 +475,22 @@
if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_MCC_UPDATE_11AX_SUPPORT)) {
struct iwl_mcc_update_resp* mcc_resp = (void*)pkt->data;
- n_channels = __le32_to_cpu(mcc_resp->n_channels);
+ n_channels = le32_to_cpu(mcc_resp->n_channels);
resp_len = sizeof(struct iwl_mcc_update_resp) + n_channels * sizeof(__le32);
- resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL);
+ resp_cp = calloc(1, resp_len);
if (!resp_cp) {
- resp_cp = ERR_PTR(-ENOMEM);
+ ret = ZX_ERR_NO_MEMORY;
goto exit;
}
+ memcpy(resp_cp, mcc_resp, resp_len);
} else {
struct iwl_mcc_update_resp_v3* mcc_resp_v3 = (void*)pkt->data;
- n_channels = __le32_to_cpu(mcc_resp_v3->n_channels);
+ n_channels = le32_to_cpu(mcc_resp_v3->n_channels);
resp_len = sizeof(struct iwl_mcc_update_resp) + n_channels * sizeof(__le32);
- resp_cp = kzalloc(resp_len, GFP_KERNEL);
+ resp_cp = calloc(1, resp_len);
if (!resp_cp) {
- resp_cp = ERR_PTR(-ENOMEM);
+ ret = ZX_ERR_NO_MEMORY;
goto exit;
}
@@ -507,19 +514,21 @@
resp_cp->mcc = cpu_to_le16(mcc);
}
+ *out_resp_cp = resp_cp;
+
IWL_DEBUG_LAR(mvm, "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') n_chans: %d\n", status, mcc,
mcc >> 8, mcc & 0xff, n_channels);
exit:
iwl_free_resp(&cmd);
- return resp_cp;
+ return ret;
}
-int iwl_mvm_init_mcc(struct iwl_mvm* mvm) {
+zx_status_t iwl_mvm_init_mcc(struct iwl_mvm* mvm) {
bool tlv_lar;
bool nvm_lar;
- int retval;
- struct ieee80211_regdomain* regd;
+ zx_status_t retval;
+ wlanphy_country_t country;
char mcc[3];
if (mvm->cfg->nvm_type == IWL_NVM_EXT) {
@@ -531,17 +540,19 @@
}
if (!iwl_mvm_is_lar_supported(mvm)) {
- return 0;
+ return ZX_OK;
}
+#if 0 // NEEDS_PORTING
/*
* try to replay the last set MCC to FW. If it doesn't exist,
* queue an update to cfg80211 to retrieve the default alpha2 from FW.
*/
retval = iwl_mvm_init_fw_regd(mvm);
- if (retval != -ENOENT) {
+ if (retval != ZX_ERR_NO_RESOURCES) {
return retval;
}
+#endif // NEEDS_PORTING
/*
* Driver regulatory hint for initial update, this also informs the
@@ -551,24 +562,27 @@
*/
mvm->lar_regdom_set = false;
- regd = iwl_mvm_get_current_regdomain(mvm, NULL);
- if (IS_ERR_OR_NULL(regd)) {
- return -EIO;
+ retval = iwl_mvm_get_current_regdomain(mvm, NULL, &country);
+ if (retval != ZX_OK) {
+ return ZX_ERR_BAD_STATE;
}
if (iwl_mvm_is_wifi_mcc_supported(mvm) && !iwl_acpi_get_mcc(mvm->dev, mcc)) {
- kfree(regd);
- regd = iwl_mvm_get_regdomain(mvm->hw->wiphy, mcc, MCC_SOURCE_BIOS, NULL);
- if (IS_ERR_OR_NULL(regd)) {
- return -EIO;
+ retval = iwl_mvm_get_regdomain(mvm, mcc, MCC_SOURCE_BIOS, NULL, &country);
+ if (retval != ZX_OK) {
+ return ZX_ERR_BAD_STATE;
}
}
+#if 0 // NEEDS_PORTING
retval = regulatory_set_wiphy_regd_sync_rtnl(mvm->hw->wiphy, regd);
kfree(regd);
+#endif // NEEDS_PORTING
+
return retval;
}
+#if 0 // NEEDS_PORTING
void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm* mvm, struct iwl_rx_cmd_buffer* rxb) {
struct iwl_rx_packet* pkt = rxb_addr(rxb);
struct iwl_mcc_chub_notif* notif = (void*)pkt->data;
diff --git a/third_party/iwlwifi/mvm/ops.c b/third_party/iwlwifi/mvm/ops.c
index ff6843c..a14b2a3 100644
--- a/third_party/iwlwifi/mvm/ops.c
+++ b/third_party/iwlwifi/mvm/ops.c
@@ -36,8 +36,8 @@
#include <stdbool.h>
#include <threads.h>
-#include <zircon/syscalls.h>
#include <zircon/compiler.h>
+#include <zircon/syscalls.h>
#include <ddk/hw/wlan/ieee80211/c/banjo.h>
@@ -63,6 +63,7 @@
#include "third_party/iwlwifi/mvm/mvm.h"
#include "third_party/iwlwifi/mvm/rs.h"
#include "third_party/iwlwifi/mvm/time-event.h"
+#include "third_party/iwlwifi/platform/rcu.h"
#ifdef CPTCFG_IWLWIFI_DEVICE_TESTMODE
#include "third_party/iwlwifi/iwl-dnt-cfg.h"
@@ -260,8 +261,11 @@
RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, RX_HANDLER_ASYNC_LOCKED),
RX_HANDLER(BA_WINDOW_STATUS_NOTIFICATION_ID, iwl_mvm_window_status_notif, RX_HANDLER_SYNC),
+#endif // NEEDS_PORTING
RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, RX_HANDLER_SYNC),
+
+#if 0 // NEEDS_PORTING
RX_HANDLER(MCC_CHUB_UPDATE_CMD, iwl_mvm_rx_chub_update_mcc, RX_HANDLER_ASYNC_LOCKED),
RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, RX_HANDLER_SYNC),
@@ -606,8 +610,7 @@
}
#endif
-// TODO(rsakthi) - Reintroduce TA_NO_THREAD_SAFETY_ANALYSIS
-static int iwl_mvm_fwrt_dump_start(void* ctx) { //TA_NO_THREAD_SAFETY_ANALYSIS {
+static int iwl_mvm_fwrt_dump_start(void* ctx) __TA_NO_THREAD_SAFETY_ANALYSIS {
struct iwl_mvm* mvm = ctx;
int ret;
@@ -621,7 +624,7 @@
return 0;
}
-static void iwl_mvm_fwrt_dump_end(void* ctx) { //TA_NO_THREAD_SAFETY_ANALYSIS {
+static void iwl_mvm_fwrt_dump_end(void* ctx) __TA_NO_THREAD_SAFETY_ANALYSIS {
struct iwl_mvm* mvm = ctx;
mtx_unlock(&mvm->mutex);
@@ -1304,9 +1307,9 @@
return;
}
- rcu_read_lock();
+ iwl_rcu_read_lock(mvm->dev);
- mvmsta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
+ mvmsta = iwl_rcu_load(mvm->fw_id_to_mac_id[sta_id]);
if (IS_ERR_OR_NULL(mvmsta)) {
goto out;
}
@@ -1339,7 +1342,7 @@
}
out:
- rcu_read_unlock();
+ iwl_rcu_read_unlock(mvm->dev);
}
static void iwl_mvm_stop_sw_queue(struct iwl_op_mode* op_mode, int hw_queue) {
@@ -1624,9 +1627,9 @@
return;
}
- rcu_read_lock();
+ iwl_rcu_read_lock(mvm->dev);
- ap_sta = rcu_dereference(mvm->fw_id_to_mac_id[iter_data->ap_sta_id]);
+ ap_sta = iwl_rcu_load(mvm->fw_id_to_mac_id[iter_data->ap_sta_id]);
if (IS_ERR_OR_NULL(ap_sta)) {
goto out;
}
@@ -1642,7 +1645,7 @@
*/
iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, cmd);
out:
- rcu_read_unlock();
+ iwl_rcu_read_unlock(mvm->dev);
}
int iwl_mvm_enter_d0i3(struct iwl_op_mode* op_mode) {
diff --git a/third_party/iwlwifi/mvm/phy-ctxt.c b/third_party/iwlwifi/mvm/phy-ctxt.c
index 72e1b1d..581d82e 100644
--- a/third_party/iwlwifi/mvm/phy-ctxt.c
+++ b/third_party/iwlwifi/mvm/phy-ctxt.c
@@ -33,9 +33,8 @@
*
*****************************************************************************/
-#include <fuchsia/hardware/wlan/info/c/banjo.h>
-
-#include <fuchsia/hardware/wlanphyinfo/c/banjo.h>
+#include <fuchsia/hardware/wlan/associnfo/c/banjo.h>
+#include <fuchsia/hardware/wlan/phyinfo/c/banjo.h>
#include "third_party/iwlwifi/mvm/fw-api.h"
#include "third_party/iwlwifi/mvm/mvm.h"
@@ -56,7 +55,7 @@
// Returns:
// the band ID.
wlan_info_band_t iwl_mvm_get_channel_band(uint8_t chan_num) {
- return chan_num < 14 ? WLAN_INFO_BAND_2GHZ : WLAN_INFO_BAND_5GHZ;
+ return chan_num < 14 ? WLAN_INFO_BAND_TWO_GHZ : WLAN_INFO_BAND_FIVE_GHZ;
}
/* Maps the driver specific channel width definition to the fw values */
@@ -226,8 +225,8 @@
uint8_t active_cnt, idle_cnt;
/* Set the channel info data */
- cmd->ci.band =
- iwl_mvm_get_channel_band(chandef->primary) == WLAN_INFO_BAND_2GHZ ? PHY_BAND_24 : PHY_BAND_5;
+ cmd->ci.band = iwl_mvm_get_channel_band(chandef->primary) == WLAN_INFO_BAND_TWO_GHZ ? PHY_BAND_24
+ : PHY_BAND_5;
cmd->ci.channel = chandef->primary;
cmd->ci.width = iwl_mvm_get_channel_width(chandef);
diff --git a/third_party/iwlwifi/mvm/power.c b/third_party/iwlwifi/mvm/power.c
index 7f2bc7d..8be67d8 100644
--- a/third_party/iwlwifi/mvm/power.c
+++ b/third_party/iwlwifi/mvm/power.c
@@ -53,7 +53,7 @@
#include <zircon/status.h>
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
#include "third_party/iwlwifi/iwl-debug.h"
#include "third_party/iwlwifi/iwl-modparams.h"
@@ -576,7 +576,7 @@
break;
#endif // NEEDS_PORTING
- case WLAN_INFO_MAC_ROLE_CLIENT:
+ case WLAN_MAC_ROLE_CLIENT:
power_iterator->bss_vif = mvmvif;
if (active) {
power_iterator->bss_active = true;
@@ -776,7 +776,7 @@
struct iwl_mvm* mvm = mvmvif->mvm;
if (mvmvif != mvm->bf_allowed_vif || !mvmvif->bss_conf.dtim_period ||
- mvmvif->mac_role != WLAN_INFO_MAC_ROLE_CLIENT || mvmvif->p2p) {
+ mvmvif->mac_role != WLAN_MAC_ROLE_CLIENT || mvmvif->p2p) {
return ZX_OK;
}
@@ -809,7 +809,7 @@
bool d0i3) {
struct iwl_beacon_filter_cmd cmd = {};
- if (mvmvif->mac_role != WLAN_INFO_MAC_ROLE_CLIENT || mvmvif->p2p) {
+ if (mvmvif->mac_role != WLAN_MAC_ROLE_CLIENT || mvmvif->p2p) {
return ZX_OK;
}
diff --git a/third_party/iwlwifi/mvm/rateScaleMng.c b/third_party/iwlwifi/mvm/rateScaleMng.c
index 19e7ed9..9485dd6 100644
--- a/third_party/iwlwifi/mvm/rateScaleMng.c
+++ b/third_party/iwlwifi/mvm/rateScaleMng.c
@@ -33,9 +33,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
-#include "_rateScaleMng.h"
-#define BOOLEAN bool
+#include <zircon/syscalls.h>
+
+#include "_rateScaleMng.h"
+#include "mvm.h"
#define SHIFT_AND_MASK(val, mask, pos) (((val) >> (pos)) & ((mask) >> (pos)))
#define SEC_TO_USEC(x) ((x)*USEC_PER_SEC)
@@ -49,9 +51,58 @@
#define MSB2ORD msb2ord
#define LSB2ORD lsb2ord
-static inline unsigned long msb2ord(unsigned long x) { return find_last_bit(&x, BITS_PER_LONG); }
+static inline unsigned long msb2ord(unsigned long x) {
+ return find_last_bit((unsigned int*)&x, BITS_PER_LONG);
+}
-static inline unsigned long lsb2ord(unsigned long x) { return find_first_bit(&x, BITS_PER_LONG); }
+static inline unsigned long lsb2ord(unsigned long x) {
+ return find_first_bit((unsigned int*)&x, BITS_PER_LONG);
+}
+
+uint64_t nonht_rate_to_bit(uint8_t rate_value) {
+ uint64_t rate_bit = 0;
+ switch (rate_value) {
+ case 1:
+ rate_bit = BIT(RS_NON_HT_RATE_CCK_1M);
+ break;
+ case 2:
+ rate_bit = BIT(RS_NON_HT_RATE_CCK_2M);
+ break;
+ case 11:
+ rate_bit = BIT(RS_NON_HT_RATE_CCK_5_5M);
+ break;
+ case 22:
+ rate_bit = BIT(RS_NON_HT_RATE_CCK_11M);
+ break;
+ case 6:
+ rate_bit = BIT(RS_NON_HT_RATE_OFDM_6M);
+ break;
+ case 9:
+ rate_bit = BIT(RS_NON_HT_RATE_OFDM_9M);
+ break;
+ case 12:
+ rate_bit = BIT(RS_NON_HT_RATE_OFDM_12M);
+ break;
+ case 18:
+ rate_bit = BIT(RS_NON_HT_RATE_OFDM_18M);
+ break;
+ case 24:
+ rate_bit = BIT(RS_NON_HT_RATE_OFDM_24M);
+ break;
+ case 36:
+ rate_bit = BIT(RS_NON_HT_RATE_OFDM_36M);
+ break;
+ case 48:
+ rate_bit = BIT(RS_NON_HT_RATE_OFDM_48M);
+ break;
+ case 54:
+ rate_bit = BIT(RS_NON_HT_RATE_OFDM_54M);
+ break;
+ default:
+ IWL_WARN(NULL, "Not non-HT rate: %u", rate_value);
+ }
+ return rate_bit;
+}
// TODO - move to coex.c
static bool btCoexManagerIsAntAvailable(struct iwl_mvm* mvm, uint8_t ant) {
@@ -97,6 +148,8 @@
[RS_NON_HT_RATE_OFDM_48M] = R_48M, [RS_NON_HT_RATE_OFDM_54M] = R_54M,
};
+#if 0 // NEEDS_PORTING
+// TODO(fxbug.dev/36684): Supports VHT (802.11ac)
// This array converts VHT rate configuration to phy rate
// See ieee80211-2016 spec, section 21.4 tabled for reference values
// Note the values are in bps, instead of mbps (i.e. multiplied by 2^20)
@@ -111,6 +164,7 @@
[CHANNEL_WIDTH160] = {61341696, 122683392, 184025088, 245366784, 368050176, 490733568,
552075264, 613416960, 736100352, 817889280},
};
+#endif // NEEDS_PORTING
// The array cell index is the MCS. e.g. - cell 0 - MCS0 6M. etc.
static const U08 downColMcsToLegacy[] = {
@@ -144,6 +198,7 @@
RS_MNG_DYN_BW_STAY_MCS(20, 0, 1, 0, 1), RS_MNG_DYN_BW_STAY_MCS(40, 2, 2, 2, 2),
RS_MNG_DYN_BW_STAY_MCS(80, 5, 8, 4, 7), RS_MNG_DYN_BW_STAY_MCS(160, 7, 9, 6, 9)};
+#if 0 // NEEDS_PORTING
/***********************************************************************/
/*
* The following tables contain the expected throughput metrics for all rates
@@ -690,6 +745,7 @@
},
},
};
+#endif // NEEDS_PORTING
/*******************************************************************************/
@@ -700,6 +756,7 @@
// info about the relevant fields can be found for LINK_QUAL_AGG_PARAMS_API_S
#define RS_MNG_AGG_DISABLE_START_TH 3
+#if 0 // TODO(fxbug.dev/36684): Supports VHT (802.11ac)
/*******************************************************************************/
static const RS_MNG_STA_LIMITS_S g_rsMngStaModLimits[] = {
{
@@ -716,21 +773,21 @@
.statsFlushTimeLimit = RS_MNG_STATS_FLUSH_TIME_LIMIT,
.clearTblWindowsLimit = RS_MNG_LEGACY_MOD_COUNTER_LIMIT,
}};
+#endif // NEEDS_PORTING
-static BOOLEAN _allowColAnt(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol);
-static BOOLEAN _allowColMimo(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol);
-static BOOLEAN _allowColSiso(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol);
-static BOOLEAN _allowColSgi(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol);
-static BOOLEAN _alloCol2xLTF(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol);
-static BOOLEAN _allowColHe(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+static bool _allowColAnt(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol);
+static bool _allowColMimo(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol);
+static bool _allowColSiso(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol);
+static bool _allowColSgi(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol);
+static bool _alloCol2xLTF(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol);
+static bool _allowColHe(const RS_MNG_STA_INFO_S* staInfo, U32 bw, const RS_MNG_COL_ELEM_S* nextCol);
+static bool _allowColHtVht(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
const RS_MNG_COL_ELEM_S* nextCol);
-static BOOLEAN _allowColHtVht(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol);
static const RS_MNG_COL_ELEM_S rsMngColumns[] = {
[RS_MNG_COL_NON_HT_ANT_A] =
@@ -1059,18 +1116,20 @@
rsMngRate->unset &= ~RS_MNG_RATE_GI;
}
-static void _rsMngRateSetLdpc(RS_MNG_RATE_S* rsMngRate, BOOLEAN ldpc) {
+static void _rsMngRateSetLdpc(RS_MNG_RATE_S* rsMngRate, bool ldpc) {
rsMngRate->rate.rate_n_flags &= ~RATE_MCS_LDPC_MSK;
rsMngRate->rate.rate_n_flags |= (!!ldpc) << RATE_MCS_LDPC_POS;
rsMngRate->unset &= ~RS_MNG_RATE_LDPC;
}
+#if 0 // NEEDS_PORTING
static BOOLEAN _rsMngRateGetStbc(const RS_MNG_RATE_S* rsMngRate) {
_rsMngRateCheckSet(rsMngRate, RS_MNG_RATE_STBC);
return !!(rsMngRate->rate.rate_n_flags & RATE_MCS_STBC_MSK);
}
+#endif // NEEDS_PORTING
-static void _rsMngRateSetStbc(RS_MNG_RATE_S* rsMngRate, BOOLEAN stbc) {
+static void _rsMngRateSetStbc(RS_MNG_RATE_S* rsMngRate, bool stbc) {
WARN_ON(!(!stbc || !(rsMngRate->rate.rate_n_flags & RATE_MCS_HE_DCM_MSK)));
rsMngRate->rate.rate_n_flags &= ~RATE_MCS_STBC_MSK;
@@ -1079,7 +1138,7 @@
rsMngRate->unset |= RS_MNG_RATE_ANT;
}
-static void _rsMngRateSetBfer(RS_MNG_RATE_S* rsMngRate, BOOLEAN bfer) {
+static void _rsMngRateSetBfer(RS_MNG_RATE_S* rsMngRate, bool bfer) {
rsMngRate->rate.rate_n_flags &= ~RATE_MCS_BF_MSK;
rsMngRate->rate.rate_n_flags |= (!!bfer) << RATE_MCS_BF_POS;
rsMngRate->unset &= ~RS_MNG_RATE_BFER;
@@ -1161,7 +1220,7 @@
static U16 _rsMngGetSupportedRatesByModeAndBw(const RS_MNG_STA_INFO_S* staInfo,
RS_MNG_MODULATION_E modulation,
TLC_MNG_CH_WIDTH_E bw) {
- BOOLEAN isBw160;
+ bool isBw160;
U32 supportedRates;
if (modulation == RS_MNG_MODUL_LEGACY) {
@@ -1190,11 +1249,13 @@
return (TLC_MNG_CH_WIDTH_E)staInfo->config.maxChWidth;
}
+#if 0 // NEEDS_PORTING
static BOOLEAN _rsMngAreAggsSupported(TLC_MNG_MODE_E bestSuppMode) {
return bestSuppMode > TLC_MNG_MODE_LEGACY;
}
+#endif // NEEDS_PORTING
-static BOOLEAN _rsMngIsDcmSupported(const RS_MNG_STA_INFO_S* staInfo, BOOLEAN isMimo) {
+static bool _rsMngIsDcmSupported(const RS_MNG_STA_INFO_S* staInfo, bool isMimo) {
if (isMimo) {
return !!(staInfo->config.configFlags & TLC_MNG_CONFIG_FLAGS_HE_DCM_NSS_2_MSK);
}
@@ -1202,6 +1263,7 @@
return !!(staInfo->config.configFlags & TLC_MNG_CONFIG_FLAGS_HE_DCM_NSS_1_MSK);
}
+#if 0 // NEEDS_PORTING
static BOOLEAN _rsMngRateIsOptimal(const RS_MNG_STA_INFO_S* staInfo,
const RS_MNG_RATE_S* rsMngRate) {
U32 bw = _rsMngRateGetBw(rsMngRate);
@@ -1231,6 +1293,7 @@
return TRUE;
}
+#endif // NEEDS_PORTING
static U08 _rsMngGetHigherRateIdx(U08 initRateIdx, U32 supportedRatesMsk) {
U32 tmpRateMsk;
@@ -1279,34 +1342,34 @@
}
// TODO - check. what if bt doesn't allow?
-static BOOLEAN _rsMngIsStbcSupported(const RS_MNG_STA_INFO_S* staInfo) {
+static bool _rsMngIsStbcSupported(const RS_MNG_STA_INFO_S* staInfo) {
return !!(staInfo->config.configFlags & TLC_MNG_CONFIG_FLAGS_STBC_MSK);
}
-static BOOLEAN _rsMngIsStbcAllowed(const RS_MNG_STA_INFO_S* staInfo, const RS_MNG_RATE_S* rate) {
+static bool _rsMngIsStbcAllowed(const RS_MNG_STA_INFO_S* staInfo, const RS_MNG_RATE_S* rate) {
if ((iwl_mvm_get_valid_tx_ant(staInfo->mvm) & rsMngGetDualAntMsk()) != rsMngGetDualAntMsk()) {
- return FALSE;
+ return false;
}
return _rsMngIsStbcSupported(staInfo) && !(rate->rate.rate_n_flags & RATE_MCS_HE_DCM_MSK);
}
-static BOOLEAN _rsMngCoexIsLongAggAllowed(const RS_MNG_STA_INFO_S* staInfo) {
- if (staInfo->config.band != NL80211_BAND_2GHZ) {
- return TRUE;
+static bool _rsMngCoexIsLongAggAllowed(const RS_MNG_STA_INFO_S* staInfo) {
+ if (staInfo->config.band != WLAN_INFO_BAND_TWO_GHZ) {
+ return true;
}
if (btCoexManagerBtOwnsAnt(staInfo->mvm)) {
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-static BOOLEAN _rsMngIsLdpcAllowed(const RS_MNG_STA_INFO_S* staInfo) {
+static bool _rsMngIsLdpcAllowed(const RS_MNG_STA_INFO_S* staInfo) {
return !!(staInfo->config.configFlags & TLC_MNG_CONFIG_FLAGS_LDPC_MSK);
}
-static BOOLEAN _rsMngIsAntSupported(const RS_MNG_STA_INFO_S* staInfo, U08 ant) {
+static bool _rsMngIsAntSupported(const RS_MNG_STA_INFO_S* staInfo, U08 ant) {
return (ant & staInfo->config.chainsEnabled) == ant &&
(iwl_mvm_get_valid_tx_ant(staInfo->mvm) & ant) == ant;
}
@@ -1316,28 +1379,28 @@
/* allowColFuncs */
/************************************************************************************/
-static BOOLEAN _allowColAnt(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol) {
+static bool _allowColAnt(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol) {
if (!_rsMngIsAntSupported(staInfo, nextCol->ant)) {
- return FALSE;
+ return false;
}
if (!_rsMngIsAntSupported(staInfo, (U08)(nextCol->ant ^ rsMngGetDualAntMsk()))) {
// If the other antenna is disabled for some reason, this antenna is the only one allowed so
// we must ignore possible BT-Coex restrictions. Also note that this function is only called
// for siso columns, so nextCol->ant always has just one bit set so the xor makes sense.
- return TRUE;
+ return true;
}
- if (staInfo->config.band != NL80211_BAND_2GHZ) {
- return TRUE;
+ if (staInfo->config.band != WLAN_INFO_BAND_TWO_GHZ) {
+ return true;
}
if (btCoexManagerIsAntAvailable(staInfo->mvm, nextCol->ant)) {
- return TRUE;
+ return true;
}
- return FALSE;
+ return false;
}
static U16 _rsMngGetAggTimeLimit(RS_MNG_STA_INFO_S* staInfo) {
@@ -1347,74 +1410,74 @@
}
if (_rsMngCoexIsLongAggAllowed(staInfo)) {
- staInfo->longAggEnabled = TRUE;
+ staInfo->longAggEnabled = true;
return RS_MNG_AGG_DURATION_LIMIT;
}
- staInfo->longAggEnabled = FALSE;
+ staInfo->longAggEnabled = false;
return RS_MNG_AGG_DURATION_LIMIT_SHORT;
}
-static BOOLEAN _allowColMimo(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol) {
- BOOLEAN isBw160 = (bw == TLC_MNG_CH_WIDTH_160MHZ);
+static bool _allowColMimo(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol) {
+ bool isBw160 = (bw == TLC_MNG_CH_WIDTH_160MHZ);
// TODO - check if ht/vht supported? redundent
// if no mimo rate is supported
if (!(staInfo->config.mcs[TLC_MNG_NSS_2][isBw160])) {
- return FALSE;
+ return false;
}
if (staInfo->config.chainsEnabled != rsMngGetDualAntMsk()) {
- return FALSE;
+ return false;
}
if (iwl_mvm_get_valid_tx_ant(staInfo->mvm) != rsMngGetDualAntMsk()) {
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
-static BOOLEAN _allowColSiso(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol) {
- BOOLEAN isBw160 = (bw == TLC_MNG_CH_WIDTH_160MHZ);
+static bool _allowColSiso(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol) {
+ bool isBw160 = (bw == TLC_MNG_CH_WIDTH_160MHZ);
// if there are supported SISO rates - return true. else - return false
return (!!(staInfo->config.mcs[TLC_MNG_NSS_1][isBw160]));
}
-static BOOLEAN _allowColHe(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol) {
+static bool _allowColHe(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol) {
return !!(staInfo->config.bestSuppMode == TLC_MNG_MODE_HE);
}
-static BOOLEAN _allowColHtVht(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol) {
+static bool _allowColHtVht(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol) {
return !!(staInfo->config.bestSuppMode == TLC_MNG_MODE_HT ||
staInfo->config.bestSuppMode == TLC_MNG_MODE_VHT);
}
-static BOOLEAN _allowColSgi(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol) {
+static bool _allowColSgi(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol) {
U08 sgiChWidthSupport = staInfo->config.sgiChWidthSupport;
return !!(sgiChWidthSupport & BIT(bw));
}
-static BOOLEAN _alloCol2xLTF(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
- const RS_MNG_COL_ELEM_S* nextCol) {
+static bool _alloCol2xLTF(const RS_MNG_STA_INFO_S* staInfo, U32 bw,
+ const RS_MNG_COL_ELEM_S* nextCol) {
return !(staInfo->config.configFlags & TLC_MNG_CONFIG_FLAGS_HE_BLOCK_2X_LTF_MSK);
}
/***************************************************************/
-static BOOLEAN _rsMngTpcIsActive(const RS_MNG_STA_INFO_S* staInfo) {
+static bool _rsMngTpcIsActive(const RS_MNG_STA_INFO_S* staInfo) {
// There are 2 values for currStep that mean tpc isn't working currently - RS_MNG_TPC_INACTIVE
// and RS_MNG_TPC_DISABLED.
return staInfo->tpcTable.currStep < RS_MNG_TPC_NUM_STEPS;
}
-static BOOLEAN _rsMngIsTestWindow(const RS_MNG_STA_INFO_S* staInfo) {
+static bool _rsMngIsTestWindow(const RS_MNG_STA_INFO_S* staInfo) {
return staInfo->tryingRateUpscale || staInfo->searchBetterTbl || staInfo->tpcTable.testing;
}
@@ -1422,9 +1485,14 @@
lqCmd->agg_time_limit = cpu_to_le16(_rsMngGetAggTimeLimit(staInfo));
lqCmd->agg_disable_start_th = RS_MNG_AGG_DISABLE_START_TH;
+#if 0 // NEEDS_PORTING
+ // TODO(fxbug.dev/79993): AMPDU Support
// W/A for a HW bug that causes it to not prepare a second burst if the first one uses
// all frames in the Fifo. W/A this by making sure there's always at least one frame left.
lqCmd->agg_frame_cnt_limit = (U08)(staInfo->staBuffSize - 1);
+#else // NEEDS_PORTING
+ lqCmd->agg_frame_cnt_limit = 1;
+#endif
}
// Get the next supported lower rate in the current column.
@@ -1442,6 +1510,8 @@
return lowerSuppRateIdx;
}
+#if 0 // NNEDS_PORTING
+// TODO(fxbug.dev/51295): Supports A-MSDU
static void tlcMngNotifyAmsdu(const RS_MNG_STA_INFO_S* staInfo, U16 amsduSize, U16 tidBitmap) {
int i;
@@ -1462,11 +1532,12 @@
}
}
}
+#endif // NEEDS_PORTING
static void _rsMngFillNonHtRates(const RS_MNG_STA_INFO_S* staInfo, struct iwl_lq_cmd* lqCmd, U08 i,
RS_MNG_RATE_S* rsMngRate) {
- BOOLEAN togglingPossible = _rsMngIsAntSupported(staInfo, rsMngGetDualAntMsk()) &&
- btCoexManagerIsAntAvailable(staInfo->mvm, BT_COEX_SHARED_ANT_ID);
+ bool togglingPossible = _rsMngIsAntSupported(staInfo, rsMngGetDualAntMsk()) &&
+ btCoexManagerIsAntAvailable(staInfo->mvm, BT_COEX_SHARED_ANT_ID);
if (_rsMngRateGetMode(rsMngRate) != TLC_MNG_MODE_LEGACY) {
U08 currIdx = _rsMngRateGetIdx(rsMngRate);
@@ -1474,8 +1545,8 @@
_rsMngRateSetMode(rsMngRate, TLC_MNG_MODE_LEGACY);
_rsMngRateSetModulation(rsMngRate, RS_MNG_MODUL_LEGACY);
_rsMngRateSetBw(rsMngRate, CHANNEL_WIDTH20);
- _rsMngRateSetLdpc(rsMngRate, FALSE);
- _rsMngRateSetStbc(rsMngRate, FALSE);
+ _rsMngRateSetLdpc(rsMngRate, false);
+ _rsMngRateSetStbc(rsMngRate, false);
// Always start with the non-shared antenna if it's available. If there's toggling, it
// doesn't make much difference, and if there's no toggling due to bt-coex it promises we'll
@@ -1547,8 +1618,9 @@
_rsMngFillNonHtRates(staInfo, lqCmd, i, &rsMngRate);
}
-static void _rsMngFillLQCmd(RS_MNG_STA_INFO_S* staInfo, struct iwl_lq_cmd* lqCmd) {
+static void _rsMngFillLQCmd(RS_MNG_STA_INFO_S* staInfo) {
int i;
+ struct iwl_lq_cmd* lqCmd = &staInfo->mvmsta->lq_sta.rs_drv.lq;
memset(lqCmd, 0, sizeof(*lqCmd));
lqCmd->sta_id = staInfo->mvmsta->sta_id;
@@ -1588,12 +1660,23 @@
lqCmd->rs_table[i] |= cpu_to_le32(RATE_MCS_RTS_REQUIRED_MSK);
}
}
+
+ DBG_PRINTF(
+ UT, TLC_OFFLOAD_DBG, INFO,
+ "---------\nLQ cmd data\nsta_id: %02x\ntpc: %02x\nflags: %02x\nmimo_delim: %02x\nssam: "
+ "%02x\ndsam: %02x\ninit_rate_idx: %02x %02x %02x %02x\nagg_time_limit: %04x\nadsh: "
+ "%02x\nafcl: %02x\nreserved2: %08x\nrs_table first: %08x\nss_params: "
+ "%08x\n-----------",
+ lqCmd->sta_id, lqCmd->reduced_tpc, lqCmd->flags, lqCmd->mimo_delim,
+ lqCmd->single_stream_ant_msk, lqCmd->dual_stream_ant_msk, lqCmd->initial_rate_index[0],
+ lqCmd->initial_rate_index[1], lqCmd->initial_rate_index[2], lqCmd->initial_rate_index[3],
+ lqCmd->agg_time_limit, lqCmd->agg_disable_start_th, lqCmd->agg_frame_cnt_limit,
+ lqCmd->reserved2, cpu_to_le32(lqCmd->rs_table[0]), lqCmd->ss_params);
}
// rs_update_rate_tbl
-static void _rsMngUpdateRateTbl(RS_MNG_STA_INFO_S* staInfo, BOOLEAN notifyHost) {
- _rsMngFillLQCmd(staInfo, &staInfo->mvmsta->lq_sta.rs_drv.lq);
-
+static void _rsMngUpdateRateTbl(RS_MNG_STA_INFO_S* staInfo) {
+ _rsMngFillLQCmd(staInfo);
iwl_mvm_send_lq_cmd(staInfo->mvm, &staInfo->mvmsta->lq_sta.rs_drv.lq, !staInfo->enabled);
}
@@ -1623,9 +1706,8 @@
BUILD_BUG_ON(!((RS_MNG_COL_HE_1_6_SISO_ANT_A ^ RS_MNG_COL_HE_1_6_SISO_ANT_B) == 1));
BUILD_BUG_ON(!((RS_MNG_COL_HE_0_8_SISO_ANT_A ^ RS_MNG_COL_HE_0_8_SISO_ANT_B) == 1));
- DBG_PRINTF(UT, TLC_OFFLOAD_DBG, INFO,
- "_rsMngSetVisitedColumn: colId %d, stbc allowed %d, visited columns 0x%x", colId,
- _rsMngIsStbcSupported(staInfo), staInfo->visitedColumns);
+ IWL_DEBUG_RATE(NULL, "_rsMngSetVisitedColumn: colId %d, stbc allowed %d, visited columns 0x%x",
+ colId, _rsMngIsStbcSupported(staInfo), staInfo->visitedColumns);
staInfo->visitedColumns |= BIT(colId);
if (rsMngColumns[colId].mode == RS_MNG_MODUL_SISO && _rsMngIsStbcSupported(staInfo)) {
@@ -1636,6 +1718,7 @@
staInfo->visitedColumns);
}
+#if 0 // NEEDS_PORTING
static U32 _rsMngVhtRateToPhyRate(U32 bw, RS_MCS_E mcs, RS_MNG_GI_E gi, RS_MNG_MODULATION_E nss) {
U32 bitrate;
@@ -1731,6 +1814,7 @@
return 0;
}
+
static RS_MNG_TX_AMSDU_SIZE_E _rsMngAmsduSize(const RS_MNG_STA_INFO_S* staInfo, TLC_MNG_MODE_E mode,
U32 bw, RS_MCS_E mcs, RS_MNG_GI_E gi,
RS_MNG_MODULATION_E nss) {
@@ -2022,7 +2106,7 @@
}
// return: TRUE if there is a better start rate, so need to send LQ command
-// newIdx: valid only if the return value is true
+// newIdx: valid only if the return value is TRUE
// RS_MNG_INVALID_RATE_IDX - if need to keep using the current index
// new index to use - if there is another rate that will provide better tpt / tpc
static RS_MNG_ACTION_E _rsMngSearchBetterStartRate(const RS_MNG_STA_INFO_S* staInfo,
@@ -2373,6 +2457,7 @@
// isUpscaleSearchCycle here is referring to the type of the previous search cycle.
// This is here to prevent two consecutive upscale search cycles (i.e. started because of
// passing the successFramesLimit threshold) within too short a time.
+ zx_time_t cur_time = zx::clock::get_monotonic().get();
return staInfo->totalFramesSuccess > staLimits->successFramesLimit &&
(!staInfo->isUpscaleSearchCycle ||
time_after(jiffies,
@@ -2405,10 +2490,11 @@
return FALSE;
}
+#endif // NEEDS_PORTING
static void _rsMngPrepareForBwChangeAttempt(RS_MNG_STA_INFO_S* staInfo,
const RS_MNG_RATE_S* rsMngRate) {
- BOOLEAN isNonHt = _rsMngRateGetMode(rsMngRate) == TLC_MNG_MODE_LEGACY;
+ bool isNonHt = _rsMngRateGetMode(rsMngRate) == TLC_MNG_MODE_LEGACY;
RS_MCS_E mcs;
U32 bw;
U32 isMimo;
@@ -2437,6 +2523,7 @@
}
}
+#if 0 // NEEDS_PORTING
static void _rsMngSetStayInCol(RS_MNG_STA_INFO_S* staInfo) {
staInfo->rsMngState = RS_MNG_STATE_STAY_IN_COLUMN;
staInfo->stableColumn = staInfo->rateTblInfo.column;
@@ -2606,7 +2693,6 @@
"_rsMngTpcAllowed: TPC disallowed because amsdu is not yet active");
return RS_MNG_TPC_DISALLOWED_AMSDU_INACTIVE;
}
-
if (time_before(jiffies,
staInfo->lastEnableJiffies + usecs_to_jiffies(RS_MNG_TPC_AMSDU_ENABLE))) {
DBG_PRINTF(UT, TLC_OFFLOAD_DBG, INFO,
@@ -2646,7 +2732,7 @@
}
if (!tpcInactive) {
- // if testing is true, then we are now operating on results from a tpc_action_increase test
+ // if testing is TRUE, then we are now operating on results from a tpc_action_increase test
// window. In this case we don't want to completely disable tpc even if the current SR is
// relatively bad. Instead we will just decrease back to the last good step.
if (currStepSR <= RS_MNG_TPC_SR_DISABLE && !tpcTbl->testing) {
@@ -2854,7 +2940,7 @@
updateLmac |= _rsMngStartSearchCycle(staInfo, currWin->averageTpt, &updateHost);
} else {
// Note that if the rate didn't really change the host-update function will not send
- // a notification to host regadless of the value of this boolean.
+ // a notification to host regadless of the value of this BOOLEAN.
updateHost = TRUE;
}
}
@@ -3272,9 +3358,10 @@
return FALSE;
}
+// TODO(fxbug.dev/84605): Rate Selection
static void tlcStatUpdateHandler(RS_MNG_STA_INFO_S* staInfo, TLC_STAT_COMMON_API_S* stats,
struct iwl_mvm* mvm, struct ieee80211_sta* sta, int tid,
- bool is_ndp) {
+ BOOLEAN is_ndp) {
BOOLEAN forceLmacUpdate = FALSE;
int i;
@@ -3336,6 +3423,8 @@
}
}
+#endif // NEEDS_PORTING
+
/*********************************************************************/
/* External Functions + funcs used by them */
/*********************************************************************/
@@ -3418,7 +3507,7 @@
_rsMngRateSetMode(rsMngRate, mode);
if (mode == TLC_MNG_MODE_LEGACY) {
_rsMngRateSetModulation(rsMngRate, RS_MNG_MODUL_LEGACY);
- _rsMngRateSetLdpc(rsMngRate, FALSE);
+ _rsMngRateSetLdpc(rsMngRate, false);
} else {
_rsMngRateSetModulation(rsMngRate, RS_MNG_MODUL_SISO);
_rsMngRateSetLdpc(rsMngRate, _rsMngIsLdpcAllowed(staInfo));
@@ -3431,20 +3520,19 @@
} else {
_rsMngRateSetGi(rsMngRate, HT_VHT_NGI);
}
- _rsMngRateSetBfer(rsMngRate, FALSE);
+ _rsMngRateSetBfer(rsMngRate, false);
if (mode > TLC_MNG_MODE_LEGACY && _rsMngIsStbcAllowed(staInfo, rsMngRate)) {
- _rsMngRateSetStbc(rsMngRate, TRUE);
+ _rsMngRateSetStbc(rsMngRate, true);
_rsMngRateSetAnt(rsMngRate, rsMngGetDualAntMsk());
} else {
- _rsMngRateSetStbc(rsMngRate, FALSE);
+ _rsMngRateSetStbc(rsMngRate, false);
_rsMngRateSetAnt(rsMngRate, rsMngGetSingleAntMsk(staInfo->config.chainsEnabled));
}
if (mode > TLC_MNG_MODE_LEGACY) {
U08 idx =
(U08)(_rsMngGetSuppRatesSameMode(staInfo, rsMngRate) & BIT(RS_MCS_3) ? RS_MCS_3 : RS_MCS_0);
-
_rsMngRateSetIdx(rsMngRate, idx);
} else {
if (LSB2ORD(nonHtRates) > RS_NON_HT_RATE_CCK_LAST) {
@@ -3472,25 +3560,25 @@
tblInfo->column = _rsMngGetColByRate(&(tblInfo->rsMngRate));
staInfo->stableColumn = tblInfo->column;
- _rsMngUpdateRateTbl(staInfo, TRUE);
+ _rsMngUpdateRateTbl(staInfo);
}
-static void rsMngResetStaInfo(struct iwl_mvm* mvm, struct ieee80211_sta* sta,
- struct iwl_mvm_sta* mvmsta, RS_MNG_STA_INFO_S* staInfo,
- BOOLEAN reconfigure) {
+static void rsMngResetStaInfo(struct iwl_mvm* mvm, struct iwl_mvm_sta* mvmsta,
+ RS_MNG_STA_INFO_S* staInfo, bool reconfigure) {
U32 fixedRate = staInfo->fixedRate;
U16 aggDurationLimit = staInfo->aggDurationLimit;
U08 amsduInAmpdu = staInfo->amsduInAmpdu;
- BOOLEAN longAggEnabled = staInfo->longAggEnabled;
+ bool longAggEnabled = staInfo->longAggEnabled;
_memclr(staInfo, sizeof(*staInfo));
+ zx_time_t cur_time = zx_clock_get_monotonic();
staInfo->mvm = mvm;
- staInfo->sta = sta;
+ // staInfo->sta = sta;
staInfo->mvmsta = mvmsta;
- staInfo->lastSearchCycleEndTimeJiffies = jiffies;
- staInfo->lastRateUpscaleTimeJiffies = jiffies;
- staInfo->lastEnableJiffies = jiffies;
+ staInfo->lastSearchCycleEndTimestamp = cur_time;
+ staInfo->lastRateUpscaleTimestamp = cur_time;
+ staInfo->lastEnableTimestamp = cur_time;
if (reconfigure) {
staInfo->fixedRate = fixedRate;
@@ -3511,7 +3599,7 @@
staInfo->tpcTable.currStep = RS_MNG_TPC_DISABLED;
staInfo->staBuffSize = RS_MNG_AGG_FRAME_CNT_LIMIT;
staInfo->amsduEnabledSize = RS_MNG_AMSDU_INVALID;
- staInfo->amsduSupport = FALSE;
+ staInfo->amsduSupport = false;
staInfo->failSafeCounter = 0;
staInfo->amsduBlacklist = 0;
}
@@ -3614,9 +3702,9 @@
/* Cmd Handlers */
/**********************************************************************/
-static void cmdHandlerTlcMngConfig(struct iwl_mvm* mvm, struct ieee80211_sta* sta,
- struct iwl_mvm_sta* mvmsta, RS_MNG_STA_INFO_S* staInfo,
- TLC_MNG_CONFIG_PARAMS_CMD_API_S* config, BOOLEAN reconfigure) {
+void cmdHandlerTlcMngConfig(struct iwl_mvm* mvm, struct iwl_mvm_sta* mvmsta,
+ RS_MNG_STA_INFO_S* staInfo, TLC_MNG_CONFIG_PARAMS_CMD_API_S* config,
+ bool reconfigure) {
if (!_tlcMngConfigValid(config)) {
return;
}
@@ -3634,14 +3722,15 @@
}
}
- rsMngResetStaInfo(mvm, sta, mvmsta, staInfo, staInfo->enabled && reconfigure);
+ rsMngResetStaInfo(mvm, mvmsta, staInfo, staInfo->enabled && reconfigure);
BUILD_BUG_ON(sizeof(staInfo->config) != sizeof(*config));
memcpy(&staInfo->config, config, sizeof(staInfo->config));
- rsMngInitAmsdu(staInfo);
+ // TODO(fxbug.dev/51295): Supports A-MSDU
+ // rsMngInitAmsdu(staInfo);
// send LQ command with basic rates table
_rsMngTlcInit(staInfo);
- staInfo->enabled = TRUE;
+ staInfo->enabled = true;
}
diff --git a/third_party/iwlwifi/mvm/rs-ng.c b/third_party/iwlwifi/mvm/rs-ng.c
index a643be6..b43c446 100644
--- a/third_party/iwlwifi/mvm/rs-ng.c
+++ b/third_party/iwlwifi/mvm/rs-ng.c
@@ -33,9 +33,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
+#include "_rateScaleMng.h"
#include "mvm.h"
#include "rs.h"
+#if 0 // NEEDS_PORTING
+
static void iwl_start_agg(struct iwl_mvm* mvm, struct ieee80211_sta* sta, int tid) {
struct iwl_mvm_sta* mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_tid_data* tid_data;
@@ -52,16 +55,17 @@
}
}
}
+#endif // NEEDS_PORTING
-static uint8_t rs_fw_bw_from_sta_bw(struct ieee80211_sta* sta) {
- switch (sta->bandwidth) {
- case IEEE80211_STA_RX_BW_160:
+static uint8_t rs_fw_bw_from_sta_bw(struct iwl_mvm_sta* mvm_sta) {
+ switch (mvm_sta->bw) {
+ case CHANNEL_BANDWIDTH_CBW160:
return IWL_TLC_MNG_CH_WIDTH_160MHZ;
- case IEEE80211_STA_RX_BW_80:
+ case CHANNEL_BANDWIDTH_CBW80:
return IWL_TLC_MNG_CH_WIDTH_80MHZ;
- case IEEE80211_STA_RX_BW_40:
+ case CHANNEL_BANDWIDTH_CBW40:
return IWL_TLC_MNG_CH_WIDTH_40MHZ;
- case IEEE80211_STA_RX_BW_20:
+ case CHANNEL_BANDWIDTH_CBW20:
default:
return IWL_TLC_MNG_CH_WIDTH_20MHZ;
}
@@ -83,38 +87,57 @@
return fw_chains;
}
-static uint8_t rs_fw_sgi_cw_support(struct ieee80211_sta* sta) {
- struct ieee80211_sta_ht_cap* ht_cap = &sta->ht_cap;
- struct ieee80211_sta_vht_cap* vht_cap = &sta->vht_cap;
- struct ieee80211_sta_he_cap* he_cap = &sta->he_cap;
+static uint8_t rs_fw_sgi_cw_support(struct iwl_mvm_sta* mvm_sta) {
+ struct ieee80211_ht_capabilities* ht_cap = &mvm_sta->ht_cap;
uint8_t supp = 0;
+#if 0 // TODO(fxbug.dev/84773): Support HE (802.11ax)
+ struct ieee80211_sta_he_cap* he_cap = &sta->he_cap;
+
if (he_cap && he_cap->has_he) {
return 0;
}
+#endif
- if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20) {
+ if (ht_cap->ht_capability_info & IEEE80211_HT_CAP_SGI_20) {
supp |= BIT(IWL_TLC_MNG_CH_WIDTH_20MHZ);
}
- if (ht_cap->cap & IEEE80211_HT_CAP_SGI_40) {
+ if (ht_cap->ht_capability_info & IEEE80211_HT_CAP_SGI_40) {
supp |= BIT(IWL_TLC_MNG_CH_WIDTH_40MHZ);
}
+
+#if 0 // TODO(fxbug.dev/36684): Support VHT (802.11ac)
+ struct ieee80211_sta_vht_cap* vht_cap = &mvm_sta->vht_cap;
+
if (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_80) {
supp |= BIT(IWL_TLC_MNG_CH_WIDTH_80MHZ);
}
if (vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_160) {
supp |= BIT(IWL_TLC_MNG_CH_WIDTH_160MHZ);
}
+#endif
return supp;
}
-static uint16_t rs_fw_set_config_flags(struct iwl_mvm* mvm, struct ieee80211_sta* sta) {
- struct ieee80211_sta_ht_cap* ht_cap = &sta->ht_cap;
+static uint16_t rs_fw_set_config_flags(struct iwl_mvm* mvm, struct iwl_mvm_sta* sta) {
+ struct ieee80211_ht_capabilities* ht_cap = &sta->ht_cap;
+
+ uint16_t flags = 0;
+
+ if (mvm->cfg->ht_params->stbc && (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1)) {
+ if ((ht_cap && (ht_cap->ht_capability_info & IEEE80211_HT_CAP_RX_STBC))) {
+ flags |= IWL_TLC_MNG_CFG_FLAGS_STBC_MSK;
+ }
+ }
+
+#if 0 // NEEDS_PORTING
+ // The following code needs porting when VHT and HE are supported.
+ // TODO(fxbug.dev/84773): Support HE (802.11ax)
+ // TODO(fxbug.dev/36684): Support VHT (802.11ac)
struct ieee80211_sta_vht_cap* vht_cap = &sta->vht_cap;
struct ieee80211_sta_he_cap* he_cap = &sta->he_cap;
bool vht_ena = vht_cap && vht_cap->vht_supported;
- uint16_t flags = 0;
if (mvm->cfg->ht_params->stbc && (num_of_ant(iwl_mvm_get_valid_tx_ant(mvm)) > 1)) {
if (he_cap && he_cap->has_he) {
@@ -140,10 +163,13 @@
(he_cap->he_cap_elem.phy_cap_info[3] & IEEE80211_HE_PHY_CAP3_DCM_MAX_CONST_RX_MASK)) {
flags |= IWL_TLC_MNG_CFG_FLAGS_HE_DCM_NSS_1_MSK;
}
+#endif
return flags;
}
+#if 0 // NEEDS_PORTING
+// TODO(fxbug.dev/36684): Support VHT (802.11ac)
static int rs_fw_vht_highest_rx_mcs_index(const struct ieee80211_sta_vht_cap* vht_cap, int nss) {
uint16_t rx_mcs = le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map) & (0x3 << (2 * (nss - 1)));
rx_mcs >>= (2 * (nss - 1));
@@ -223,77 +249,95 @@
}
}
-static void rs_fw_set_supp_rates(struct ieee80211_sta* sta, struct ieee80211_supported_band* sband,
+#endif // NEEDS_PORTING
+
+static void rs_fw_set_supp_rates(struct iwl_mvm_sta* mvm_sta,
TLC_MNG_CONFIG_PARAMS_CMD_API_S* cmd) {
- int i;
- unsigned long tmp;
- unsigned long supp;
- const struct ieee80211_sta_ht_cap* ht_cap = &sta->ht_cap;
- const struct ieee80211_sta_vht_cap* vht_cap = &sta->vht_cap;
- const struct ieee80211_sta_he_cap* he_cap = &sta->he_cap;
+ uint16_t i;
+ uint64_t nonht_rates = 0;
+ uint8_t* supported_rates = mvm_sta->supp_rates;
+ const struct ieee80211_ht_capabilities* ht_cap = &mvm_sta->ht_cap;
+
+#if 0 // NEEDS_PORTING
+ // TODO(fxbug.dev/84773): Support HE (802.11ax)
+ const struct ieee80211_he_capabilities* he_cap = &sta->he_cap;
+#endif // NEEDS_PORTING
/* non HT rates */
- supp = 0;
- tmp = sta->supp_rates[sband->band];
- for_each_set_bit(i, &tmp, BITS_PER_LONG) supp |= BIT(sband->bitrates[i].hw_value);
+ // We got the supported rates from MLME, and filt out the non-HT rates here.
+ for (i = 0; i < WLAN_MAC_MAX_RATES; i++) {
+ if (supported_rates[i] <= 54 && supported_rates[i] != 0)
+ nonht_rates |= nonht_rate_to_bit(supported_rates[i]);
+ }
- cmd->nonHt = supp;
+ cmd->nonHt = nonht_rates;
cmd->bestSuppMode = IWL_TLC_MNG_MODE_NON_HT;
/* HT/VHT rates */
+#if 0 // NEEDS_PORTING
+ // TODO(fxbug.dev/84773): Support HE (802.11ax)
if (he_cap && he_cap->has_he) {
cmd->bestSuppMode = IWL_TLC_MNG_MODE_HE;
rs_fw_he_set_enabled_rates(sta, he_cap, cmd);
- } else if (vht_cap && vht_cap->vht_supported) {
+ } else
+
+ // TODO(fxbug.dev/36684): Support VHT (802.11ac)
+ const struct ieee80211_vht_capabilities* vht_cap = &sta->vht_cap;
+
+ if (vht_cap) {
cmd->bestSuppMode = IWL_TLC_MNG_MODE_VHT;
rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd);
- } else if (ht_cap && ht_cap->ht_supported) {
+ } else
+#endif // NEEDS_PORTING
+ if (ht_cap) {
cmd->bestSuppMode = IWL_TLC_MNG_MODE_HT;
- cmd->mcs[0][0] = (ht_cap->mcs.rx_mask[0]);
- cmd->mcs[1][0] = (ht_cap->mcs.rx_mask[1]);
+ cmd->mcs[0][0] = (ht_cap->supported_mcs_set.bytes[0]);
+ cmd->mcs[1][0] = (ht_cap->supported_mcs_set.bytes[1]);
}
}
-/// TODO: merge file?
-#include "rateScaleMng.c"
+static void rs_drv_rate_init(struct iwl_mvm* mvm, struct iwl_mvm_sta* mvm_sta, bool update) {
+ struct iwl_lq_sta* lq_sta = &mvm_sta->lq_sta.rs_drv;
+ struct iwl_mvm_vif* mvm_vif = mvm_sta->mvmvif;
-static void rs_drv_rate_init(struct iwl_mvm* mvm, struct ieee80211_sta* sta, enum nl80211_band band,
- bool update) {
- struct ieee80211_hw* hw = mvm->hw;
- struct iwl_mvm_sta* mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct iwl_lq_sta* lq_sta = &mvmsta->lq_sta.rs_drv;
- struct ieee80211_supported_band* sband;
RS_MNG_STA_INFO_S* staInfo = &lq_sta->pers;
TLC_MNG_CONFIG_PARAMS_CMD_API_S config = {};
#ifdef CPTCFG_IWLWIFI_DEBUGFS
iwl_mvm_reset_frame_stats(mvm);
#endif
- sband = hw->wiphy->bands[band];
- mvmsta->amsdu_enabled = 0;
- mvmsta->max_amsdu_len = sta->max_amsdu_len;
-
- config.maxChWidth = update ? rs_fw_bw_from_sta_bw(sta) : IWL_TLC_MNG_CH_WIDTH_20MHZ;
- config.configFlags = rs_fw_set_config_flags(mvm, sta);
+ config.maxChWidth = rs_fw_bw_from_sta_bw(mvm_sta);
+ config.configFlags = rs_fw_set_config_flags(mvm, mvm_sta);
config.chainsEnabled = rs_fw_set_active_chains(iwl_mvm_get_valid_tx_ant(mvm));
- config.maxMpduLen = sta->max_amsdu_len;
- config.sgiChWidthSupport = rs_fw_sgi_cw_support(sta);
+
+ config.sgiChWidthSupport = rs_fw_sgi_cw_support(mvm_sta);
config.amsduSupported = iwl_mvm_is_csum_supported(mvm);
- config.band = sband->band;
- rs_fw_set_supp_rates(sta, sband, &config);
- cmdHandlerTlcMngConfig(mvm, sta, mvmsta, staInfo, &config, update);
+ mvm_sta->amsdu_enabled = 0;
+#if 0 // TODO(fxbug.dev/49528): Support Aggregation
+ mvm_sta->max_amsdu_len = sta->max_amsdu_len;
+ config.maxMpduLen = sta->max_amsdu_len;
+#endif
+
+ config.band = mvm_vif->phy_ctxt->band;
+ rs_fw_set_supp_rates(mvm_sta, &config);
+
+ cmdHandlerTlcMngConfig(mvm, mvm_sta, staInfo, &config, update);
}
-void iwl_mvm_rs_rate_init(struct iwl_mvm* mvm, struct ieee80211_sta* sta, enum nl80211_band band,
- bool update) {
+void iwl_mvm_rs_rate_init(struct iwl_mvm* mvm, struct iwl_mvm_sta* mvm_sta, bool update) {
+#if 0 // NEEDS PORTING
if (iwl_mvm_has_tlc_offload(mvm)) {
- rs_fw_rate_init(mvm, sta, band, update);
+ rs_fw_rate_init(mvm, mvm_sta, band, update);
} else {
- rs_drv_rate_init(mvm, sta, band, update);
+ rs_drv_rate_init(mvm, mvm_sta, band, update);
}
+#endif
+ // Only use driver rate initialization before supporting tlc offload for new firmwares.
+ rs_drv_rate_init(mvm, mvm_sta, update);
}
+#if 0 // NEEDS_PORTING
void iwl_mvm_rs_tx_status(struct iwl_mvm* mvm, struct ieee80211_sta* sta, int tid,
struct ieee80211_tx_info* info, bool is_ndp) {
@@ -477,3 +521,5 @@
void rs_update_last_rssi(struct iwl_mvm* mvm, struct iwl_mvm_sta* mvmsta,
struct ieee80211_rx_status* rx_status) {}
+
+#endif // NEEDS_PORTING
diff --git a/third_party/iwlwifi/mvm/rs-ng.h b/third_party/iwlwifi/mvm/rs-ng.h
index 4afe94b..4d49c34 100644
--- a/third_party/iwlwifi/mvm/rs-ng.h
+++ b/third_party/iwlwifi/mvm/rs-ng.h
@@ -36,21 +36,14 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_MVM_RS_NG_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_MVM_RS_NG_H_
-#include <fuchsia/hardware/wlanphyinfo/c/banjo.h>
+#include <fuchsia/hardware/wlan/phyinfo/c/banjo.h>
#include "third_party/iwlwifi/iwl-trans.h"
-#include "third_party/iwlwifi/mvm/fw-api.h"
-
-#define U08 uint8_t
-#define U16 uint16_t
-#define U32 uint32_t
-#define U64 uint64_t
-#define INLINE inline
-
#include "third_party/iwlwifi/mvm/API_rates.h"
#include "third_party/iwlwifi/mvm/_rateScaleMng.h"
#include "third_party/iwlwifi/mvm/apiGroupDatapath.h"
#include "third_party/iwlwifi/mvm/apiVersion.h"
+#include "third_party/iwlwifi/mvm/fw-api.h"
#include "third_party/iwlwifi/platform/kernel.h"
#define RS_NAME "iwlwifi-rs"
@@ -92,8 +85,7 @@
int iwl_mvm_rate_control_register(void);
void iwl_mvm_rate_control_unregister(void);
int iwl_mvm_tx_protection(struct iwl_mvm* mvm, struct iwl_mvm_sta* mvmsta, bool enable);
-void iwl_mvm_rs_rate_init(struct iwl_mvm* mvm, struct ieee80211_sta* sta, wlan_info_band_t band,
- bool update);
+void iwl_mvm_rs_rate_init(struct iwl_mvm* mvm, struct iwl_mvm_sta* mvm_sta, bool update);
void iwl_mvm_rs_tx_status(struct iwl_mvm* mvm, struct ieee80211_sta* sta, int tid,
struct ieee80211_tx_info* info, bool is_ndp);
#ifdef CPTCFG_IWLWIFI_DEBUGFS
@@ -101,7 +93,7 @@
#endif
void iwl_mvm_tlc_update_notif(struct iwl_mvm* mvm, struct iwl_rx_cmd_buffer* rxb);
-void rs_fw_rate_init(struct iwl_mvm* mvm, struct ieee80211_sta* sta, wlan_info_band_t band,
+void rs_fw_rate_init(struct iwl_mvm* mvm, struct iwl_mvm_sta* sta, wlan_info_band_t band,
bool update);
void iwl_mvm_rs_add_sta(struct iwl_mvm* mvm, struct iwl_mvm_sta* mvmsta);
int rs_fw_tx_protection(struct iwl_mvm* mvm, struct iwl_mvm_sta* mvmsta, bool enable);
diff --git a/third_party/iwlwifi/mvm/rx.c b/third_party/iwlwifi/mvm/rx.c
index 013a772..4ebe0e0 100644
--- a/third_party/iwlwifi/mvm/rx.c
+++ b/third_party/iwlwifi/mvm/rx.c
@@ -38,7 +38,7 @@
#include "third_party/iwlwifi/iwl-trans.h"
#include "third_party/iwlwifi/mvm/fw-api.h"
#include "third_party/iwlwifi/mvm/mvm.h"
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
/*
* iwl_mvm_rx_rx_phy_cmd - REPLY_RX_PHY_CMD handler
*
@@ -274,7 +274,7 @@
}
wlan_info_band_t band =
- phy_flags & RX_RES_PHY_FLAGS_BAND_24 ? WLAN_INFO_BAND_2GHZ : WLAN_INFO_BAND_5GHZ;
+ phy_flags & RX_RES_PHY_FLAGS_BAND_24 ? WLAN_INFO_BAND_TWO_GHZ : WLAN_INFO_BAND_FIVE_GHZ;
rx_info.channel.primary = le16_to_cpu(phy_info->channel);
#if 0 // NEEDS_PORTING
@@ -433,7 +433,7 @@
#endif // NEEDS_PORTING
} else {
rx_info.phy =
- phy_flags & RX_RES_PHY_FLAGS_MOD_CCK ? WLAN_INFO_PHY_TYPE_CCK : WLAN_INFO_PHY_TYPE_OFDM;
+ phy_flags & RX_RES_PHY_FLAGS_MOD_CCK ? WLAN_INFO_PHY_TYPE_HR : WLAN_INFO_PHY_TYPE_OFDM;
int mac80211_idx;
zx_status_t status = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags, band, &mac80211_idx);
@@ -488,7 +488,7 @@
.mac_frame_size = res_len,
.info = rx_info,
};
- wlanmac_ifc_recv(&mvm->mvmvif[0]->ifc, &rx_packet);
+ wlan_softmac_ifc_recv(&mvm->mvmvif[0]->ifc, &rx_packet);
#if 0 // NEEDS_PORTING
if (take_ref) {
diff --git a/third_party/iwlwifi/mvm/rxmq.c b/third_party/iwlwifi/mvm/rxmq.c
index 2cccb58..512e7a5 100644
--- a/third_party/iwlwifi/mvm/rxmq.c
+++ b/third_party/iwlwifi/mvm/rxmq.c
@@ -36,7 +36,8 @@
#include "third_party/iwlwifi/iwl-trans.h"
#include "third_party/iwlwifi/mvm/fw-api.h"
#include "third_party/iwlwifi/mvm/mvm.h"
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
+#include "third_party/iwlwifi/platform/rcu.h"
static bool is_multicast_ether_addr(uint8_t addr[6]) { return (addr[0] & 0x1) != 0; }
@@ -77,10 +78,8 @@
keyidx = stats->extiv[3] >> 6;
- mtx_lock(&mvmsta->ptk_pn_mutex);
- ptk_pn = rcu_dereference(mvmsta->ptk_pn[keyidx]);
+ ptk_pn = iwl_rcu_load(mvmsta->ptk_pn[keyidx]);
if (!ptk_pn) {
- mtx_unlock(&mvmsta->ptk_pn_mutex);
return ZX_ERR_BAD_STATE;
}
@@ -92,30 +91,26 @@
/* we don't use HCCA/802.11 QoS TSPECs, so drop such frames */
if (tid >= IWL_MAX_TID_COUNT) {
- mtx_unlock(&mvmsta->ptk_pn_mutex);
return ZX_ERR_NOT_SUPPORTED;
}
/* load pn */
- pn[0] = stats->extiv[7];
- pn[1] = stats->extiv[6];
- pn[2] = stats->extiv[5];
- pn[3] = stats->extiv[4];
- pn[4] = stats->extiv[1];
- pn[5] = stats->extiv[0];
+ pn[0] = stats->extiv[0];
+ pn[1] = stats->extiv[1];
+ pn[2] = stats->extiv[4];
+ pn[3] = stats->extiv[5];
+ pn[4] = stats->extiv[6];
+ pn[5] = stats->extiv[7];
res = memcmp(pn, ptk_pn->q[queue].pn[tid], IEEE80211_CCMP_PN_LEN);
if (res < 0) {
- mtx_unlock(&mvmsta->ptk_pn_mutex);
return ZX_ERR_INVALID_ARGS;
}
if (!res && !(stats->flag & RX_FLAG_ALLOW_SAME_PN)) {
- mtx_unlock(&mvmsta->ptk_pn_mutex);
return ZX_ERR_INVALID_ARGS;
}
memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN);
- mtx_unlock(&mvmsta->ptk_pn_mutex);
stats->flag |= RX_FLAG_PN_VALIDATED;
@@ -218,12 +213,12 @@
// Send to MLME
// TODO(fxbug.dev/43218) Need to revisit to handle multiple IFs
- wlan_rx_packet_t rx_packet = {
+ wlan_rx_packet_t rx_packet = {
.mac_frame_buffer = (uint8_t*)frame,
.mac_frame_size = frame_len,
.info = rx_status->rx_info,
};
- wlanmac_ifc_recv(&mvm->mvmvif[0]->ifc, &rx_packet);
+ wlan_softmac_ifc_recv(&mvm->mvmvif[0]->ifc, &rx_packet);
}
static int iwl_mvm_get_signal_strength(struct iwl_mvm* mvm, int energy_a, int energy_b) {
@@ -320,8 +315,10 @@
return 0;
#endif // NEEDS_PORTING
default:
- /* Expected in monitor (not having the keys) */
- if (!mvm->monitor_on) { IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status); }
+ /* Expected in monitor (not having the keys) */
+ if (!mvm->monitor_on) {
+ IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status);
+ }
}
return 0;
@@ -1384,22 +1381,20 @@
}
}
- rcu_read_lock();
+ iwl_rcu_read_lock(mvm->dev);
if (desc->status & cpu_to_le16(IWL_RX_MPDU_STATUS_SRC_STA_FOUND)) {
uint8_t id = desc->sta_id_flags & IWL_RX_MPDU_SIF_STA_ID_MASK;
if (!WARN_ON_ONCE(id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))) {
- sta = rcu_dereference(mvm->fw_id_to_mac_id[id]);
+ sta = iwl_rcu_load(mvm->fw_id_to_mac_id[id]);
}
} else if (!is_multicast_ether_addr(hdr->addr2)) {
/*
* This is fine since we prevent two stations with the same
* address from being added.
*/
- mtx_lock(&mvm->mutex);
sta = iwl_mvm_find_sta_by_addr(mvm, hdr->addr2);
- mtx_unlock(&mvm->mutex);
}
#if 0 // NEEDS_PORTING
@@ -1535,7 +1530,7 @@
}
// rx_status->rate_idx = rate;
rx_status.rx_info.phy =
- phy_info & RX_RES_PHY_FLAGS_MOD_CCK ? WLAN_INFO_PHY_TYPE_CCK : WLAN_INFO_PHY_TYPE_OFDM;
+ phy_info & RX_RES_PHY_FLAGS_MOD_CCK ? WLAN_INFO_PHY_TYPE_HR : WLAN_INFO_PHY_TYPE_OFDM;
}
rx_status.rx_info.valid_fields |= WLAN_RX_INFO_VALID_DATA_RATE;
@@ -1560,7 +1555,7 @@
iwl_mvm_pass_packet_to_mac80211(mvm, hdr, len, &rx_status, queue, sta);
}
out:
- rcu_read_unlock();
+ iwl_rcu_read_unlock(mvm->dev);
}
void iwl_mvm_rx_monitor_ndp(struct iwl_mvm* mvm, struct napi_struct* napi,
diff --git a/third_party/iwlwifi/mvm/scan.c b/third_party/iwlwifi/mvm/scan.c
index 532d78d..9723afc 100644
--- a/third_party/iwlwifi/mvm/scan.c
+++ b/third_party/iwlwifi/mvm/scan.c
@@ -154,7 +154,7 @@
}
static inline __le32 iwl_mvm_scan_rxon_flags(wlan_info_band_t band) {
- if (band == WLAN_INFO_BAND_2GHZ) {
+ if (band == WLAN_INFO_BAND_TWO_GHZ) {
return cpu_to_le32(PHY_BAND_24);
} else {
return cpu_to_le32(PHY_BAND_5);
@@ -168,7 +168,7 @@
iwl_mvm_toggle_tx_ant(mvm, &mvm->scan_last_antenna_idx);
tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;
- if (band == WLAN_INFO_BAND_2GHZ && !no_cck) {
+ if (band == WLAN_INFO_BAND_TWO_GHZ && !no_cck) {
return cpu_to_le32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK | tx_ant);
} else {
return cpu_to_le32(IWL_RATE_6M_PLCP | tx_ant);
@@ -371,11 +371,9 @@
}
}
-static void notify_mlme_scan_completion(struct iwl_mvm_vif* mvmvif, bool successful) {
- wlan_hw_scan_result_t scan_result = {
- .code = successful ? WLAN_HW_SCAN_SUCCESS : WLAN_HW_SCAN_ABORTED,
- };
- wlanmac_ifc_hw_scan_complete(&mvmvif->ifc, &scan_result);
+static void notify_mlme_scan_completion(struct iwl_mvm_vif* mvmvif, zx_status_t status) {
+ // TODO(fxbug.dev/88934): scan_id is always 0
+ wlan_softmac_ifc_scan_complete(&mvmvif->ifc, status, 0);
}
void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm* mvm, struct iwl_rx_cmd_buffer* rxb) {
@@ -454,7 +452,7 @@
mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
if (mvm->scan_vif) {
- notify_mlme_scan_completion(mvm->scan_vif, !aborted);
+ notify_mlme_scan_completion(mvm->scan_vif, aborted ? ZX_ERR_CANCELED : ZX_OK);
} else {
IWL_WARN(mvm, "mvm->scan_vif is not registered, but got a SCAN completion\n");
}
@@ -629,11 +627,11 @@
static void iwl_mvm_scan_fill_tx_cmd(struct iwl_mvm* mvm, struct iwl_scan_req_tx_cmd* tx_cmd,
bool no_cck) {
tx_cmd[0].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_BT_DIS);
- tx_cmd[0].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm, WLAN_INFO_BAND_2GHZ, no_cck);
+ tx_cmd[0].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm, WLAN_INFO_BAND_TWO_GHZ, no_cck);
tx_cmd[0].sta_id = mvm->aux_sta.sta_id;
tx_cmd[1].tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_BT_DIS);
- tx_cmd[1].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm, WLAN_INFO_BAND_5GHZ, no_cck);
+ tx_cmd[1].rate_n_flags = iwl_mvm_scan_rate_n_flags(mvm, WLAN_INFO_BAND_FIVE_GHZ, no_cck);
tx_cmd[1].sta_id = mvm->aux_sta.sta_id;
}
@@ -886,8 +884,8 @@
cmd->scan_flags = cpu_to_le32(iwl_mvm_scan_lmac_flags(mvm, params));
- cmd->flags = iwl_mvm_scan_rxon_flags(params->channels[0] <= 14 ? WLAN_INFO_BAND_2GHZ
- : WLAN_INFO_BAND_5GHZ);
+ cmd->flags = iwl_mvm_scan_rxon_flags(params->channels[0] <= 14 ? WLAN_INFO_BAND_TWO_GHZ
+ : WLAN_INFO_BAND_FIVE_GHZ);
cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP | MAC_FILTER_IN_BEACON);
iwl_mvm_scan_fill_tx_cmd(mvm, cmd->tx_cmd, params->no_cck);
#if 0 // NEEDS_PORTING
@@ -959,11 +957,11 @@
uint16_t rates = 0;
int i;
- band = &mvm->nvm_data->bands[WLAN_INFO_BAND_2GHZ];
+ band = &mvm->nvm_data->bands[WLAN_INFO_BAND_TWO_GHZ];
for (i = 0; i < band->n_bitrates; i++) {
rates |= rate_to_scan_rate_flag(iwl_get_rate_index(band->bitrates[i]));
}
- band = &mvm->nvm_data->bands[WLAN_INFO_BAND_5GHZ];
+ band = &mvm->nvm_data->bands[WLAN_INFO_BAND_FIVE_GHZ];
for (i = 0; i < band->n_bitrates; i++) {
rates |= rate_to_scan_rate_flag(iwl_get_rate_index(band->bitrates[i]));
}
@@ -985,11 +983,11 @@
struct ieee80211_supported_band* band;
int i, j = 0;
- band = &mvm->nvm_data->bands[WLAN_INFO_BAND_2GHZ];
+ band = &mvm->nvm_data->bands[WLAN_INFO_BAND_TWO_GHZ];
for (i = 0; i < band->n_channels; i++, j++) {
channels[j] = band->channels[i].ch_num;
}
- band = &mvm->nvm_data->bands[WLAN_INFO_BAND_5GHZ];
+ band = &mvm->nvm_data->bands[WLAN_INFO_BAND_FIVE_GHZ];
for (i = 0; i < band->n_channels; i++, j++) {
channels[j] = band->channels[i].ch_num;
}
@@ -1029,8 +1027,8 @@
if (iwl_mvm_is_cdb_supported(mvm)) {
enum iwl_mvm_scan_type lb_type, hb_type;
- lb_type = iwl_mvm_get_scan_type_band(mvm, WLAN_INFO_BAND_2GHZ);
- hb_type = iwl_mvm_get_scan_type_band(mvm, WLAN_INFO_BAND_5GHZ);
+ lb_type = iwl_mvm_get_scan_type_band(mvm, WLAN_INFO_BAND_TWO_GHZ);
+ hb_type = iwl_mvm_get_scan_type_band(mvm, WLAN_INFO_BAND_FIVE_GHZ);
cfg->out_of_channel_time[SCAN_LB_LMAC_IDX] = cpu_to_le32(scan_timing[lb_type].max_out_time);
cfg->suspend_time[SCAN_LB_LMAC_IDX] = cpu_to_le32(scan_timing[lb_type].suspend_time);
@@ -1063,8 +1061,8 @@
};
enum iwl_mvm_scan_type type = IWL_SCAN_TYPE_NOT_SET;
enum iwl_mvm_scan_type hb_type = IWL_SCAN_TYPE_NOT_SET;
- uint32_t num_channels = mvm->nvm_data->bands[WLAN_INFO_BAND_2GHZ].n_channels +
- mvm->nvm_data->bands[WLAN_INFO_BAND_5GHZ].n_channels;
+ uint32_t num_channels = mvm->nvm_data->bands[WLAN_INFO_BAND_TWO_GHZ].n_channels +
+ mvm->nvm_data->bands[WLAN_INFO_BAND_FIVE_GHZ].n_channels;
uint32_t flags;
uint8_t channel_flags;
@@ -1073,8 +1071,8 @@
}
if (iwl_mvm_is_cdb_supported(mvm)) {
- type = iwl_mvm_get_scan_type_band(mvm, WLAN_INFO_BAND_2GHZ);
- hb_type = iwl_mvm_get_scan_type_band(mvm, WLAN_INFO_BAND_5GHZ);
+ type = iwl_mvm_get_scan_type_band(mvm, WLAN_INFO_BAND_TWO_GHZ);
+ hb_type = iwl_mvm_get_scan_type_band(mvm, WLAN_INFO_BAND_FIVE_GHZ);
if (type == mvm->scan_type && hb_type == mvm->hb_scan_type) {
return ZX_OK;
}
@@ -1455,7 +1453,7 @@
return ZX_OK;
}
-#if 0 // NEEDS_PORTING
+#if 0 // NEEDS_PORTING
static int iwl_mvm_num_scans(struct iwl_mvm* mvm) {
return hweight32(mvm->scan_status & IWL_MVM_SCAN_MASK);
}
@@ -1541,7 +1539,7 @@
mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
if (mvm->scan_vif) {
- notify_mlme_scan_completion(mvm->scan_vif, false);
+ notify_mlme_scan_completion(mvm->scan_vif, ZX_ERR_TIMED_OUT);
} else {
IWL_ERR(mvm, "mvm->scan_vif is not registered, but got a SCAN timeout\n");
}
@@ -1561,8 +1559,17 @@
}
#endif // NEEDS_PORTING
-zx_status_t iwl_mvm_reg_scan_start(struct iwl_mvm_vif* mvmvif,
- const wlan_hw_scan_config_t* scan_config) {
+// TODO(fxbug.dev/89682): Fuchsia-specific wlan_softmac_passive_scan_args_t should be moved out
+// of these function arguments or this function should be moved to platform/mvm-mlme.cc.
+zx_status_t iwl_mvm_reg_scan_start_passive(
+ struct iwl_mvm_vif* mvmvif, const wlan_softmac_passive_scan_args_t* passive_scan_args) {
+ // TODO(fxbug.dev/89693): iwlwifi only uses the channels field.
+ return iwl_mvm_reg_scan_start(mvmvif, passive_scan_args->channels_list,
+ passive_scan_args->channels_count);
+}
+
+zx_status_t iwl_mvm_reg_scan_start(struct iwl_mvm_vif* mvmvif, const uint8_t* channels_list,
+ size_t channels_count) {
struct iwl_mvm* mvm = mvmvif->mvm;
struct iwl_host_cmd hcmd = {
.len =
@@ -1607,6 +1614,8 @@
return ZX_ERR_SHOULD_WAIT;
}
+// TODO(fxbug.dev/89683): The number of SSIDs and channels is not actually limitless
+// and should be checked.
#if 0 // NEEDS_PORTING
if (!iwl_mvm_scan_fits(mvm, req->n_ssids, ies, req->n_channels)) { return ZX_ERR_BUFFER_TOO_SMALL; }
#endif // NEEDS_PORTING
@@ -1619,9 +1628,9 @@
.delay = 0,
};
- params.n_channels = scan_config->num_channels;
+ params.n_channels = channels_count;
for (uint32_t i = 0; i < params.n_channels; ++i) {
- params.channels[i] = scan_config->channels[i];
+ params.channels[i] = channels_list[i];
}
#if 0 // NEEDS_PORTING
@@ -1817,7 +1826,7 @@
}
if (mvm->scan_vif != NULL) {
- notify_mlme_scan_completion(mvm->scan_vif, !aborted);
+ notify_mlme_scan_completion(mvm->scan_vif, aborted ? ZX_ERR_CANCELED : ZX_OK);
}
mvm->scan_vif = NULL;
diff --git a/third_party/iwlwifi/mvm/sta.c b/third_party/iwlwifi/mvm/sta.c
index 5075699..602de19 100644
--- a/third_party/iwlwifi/mvm/sta.c
+++ b/third_party/iwlwifi/mvm/sta.c
@@ -39,12 +39,13 @@
#include "third_party/iwlwifi/mvm/mvm.h"
#include "third_party/iwlwifi/mvm/rs.h"
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
+#include "third_party/iwlwifi/platform/rcu.h"
static zx_status_t iwl_mvm_set_fw_key_idx(struct iwl_mvm* mvm);
static zx_status_t iwl_mvm_send_sta_key(struct iwl_mvm* mvm, uint32_t sta_id,
- const struct iwl_mvm_sta_key_conf* keyconf, bool mcast,
+ const struct ieee80211_key_conf* keyconf, bool mcast,
uint32_t tkip_iv32, uint16_t* tkip_p1k, uint32_t cmd_flags,
uint8_t key_offset, bool mfp);
@@ -66,7 +67,7 @@
// Note that in order to avoid race condition, the mvm->mutex must be hold before calling this
// function, and cannot be released before adding new STA to mvm->fw_id_to_mac_id[].
//
-static int iwl_mvm_find_free_sta_id(struct iwl_mvm* mvm, wlan_info_mac_role_t mac_role) {
+static int iwl_mvm_find_free_sta_id(struct iwl_mvm* mvm, wlan_mac_role_t mac_role) {
uint32_t reserved_ids = 0;
BUILD_BUG_ON(IWL_MVM_STATION_COUNT > 32);
@@ -75,17 +76,17 @@
iwl_assert_lock_held(&mvm->mutex);
/* d0i3/d3 assumes the AP's sta_id (of sta vif) is 0. reserve it. */
- if (mac_role != WLAN_INFO_MAC_ROLE_CLIENT) {
+ if (mac_role != WLAN_MAC_ROLE_CLIENT) {
reserved_ids = BIT(0);
}
- // find an empty slot in mvm->fw_id_to_mac_id array.
+ /* Don't take rcu_read_lock() since we are protected by mvm->mutex */
for (size_t sta_id = 0; sta_id < ARRAY_SIZE(mvm->fw_id_to_mac_id); sta_id++) {
if (BIT(sta_id) & reserved_ids) {
continue;
}
- if (!mvm->fw_id_to_mac_id[sta_id]) {
+ if (!iwl_rcu_load(mvm->fw_id_to_mac_id[sta_id])) {
return sta_id;
}
}
@@ -124,29 +125,13 @@
}
}
-#if 1 // NEEDS_PORTING
- add_sta_cmd.station_flags |=
- cpu_to_le32(STA_FLG_MIMO_EN_SISO) | cpu_to_le32(STA_FLG_FAT_EN_20MHZ);
-#else
+#if 0 // NEEDS_PORTING
+// TODO(fxbug.dev/51295): Supports A-MSDU
+ mpdu_dens = sta->ht_cap.ampdu_density;
uint32_t agg_size = 0, mpdu_dens = 0;
- switch (sta->bandwidth) {
- case IEEE80211_STA_RX_BW_160:
- add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_160MHZ);
- /* fall through */
- case IEEE80211_STA_RX_BW_80:
- add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_80MHZ);
- /* fall through */
- case IEEE80211_STA_RX_BW_40:
- add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_40MHZ);
- /* fall through */
- case IEEE80211_STA_RX_BW_20:
- if (sta->ht_cap.ht_supported) {
- add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_20MHZ);
- }
- break;
- }
- switch (sta->rx_nss) {
+ //TODO(fxbug.dev/91457): Use real NSS data for filling the flag.
+ switch (mvm_sta->rx_nss) {
case 1:
add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
break;
@@ -175,14 +160,8 @@
/* nothing */
break;
}
-
- if (sta->ht_cap.ht_supported) {
- add_sta_cmd.station_flags_msk |=
- cpu_to_le32(STA_FLG_MAX_AGG_SIZE_MSK | STA_FLG_AGG_MPDU_DENS_MSK);
-
- mpdu_dens = sta->ht_cap.ampdu_density;
- }
-
+
+ // TODO(fxbug.dev/36684): Support VHT (802.11ac)
if (sta->vht_cap.vht_supported) {
agg_size = sta->vht_cap.cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
agg_size >>= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
@@ -214,6 +193,34 @@
add_sta_cmd.uapsd_acs |= add_sta_cmd.uapsd_acs << 4;
add_sta_cmd.sp_length = sta->max_sp ? sta->max_sp * 2 : 128;
}
+
+#else
+ add_sta_cmd.station_flags |=
+ cpu_to_le32(STA_FLG_MIMO_EN_SISO) | cpu_to_le32(STA_FLG_FAT_EN_20MHZ);
+
+ add_sta_cmd.station_flags_msk |=
+ cpu_to_le32(STA_FLG_MAX_AGG_SIZE_MSK | STA_FLG_AGG_MPDU_DENS_MSK);
+
+ switch (mvm_sta->bw) {
+ add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_160MHZ);
+ __attribute__((fallthrough));
+ case CHANNEL_BANDWIDTH_CBW80:
+ add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_80MHZ);
+ __attribute__((fallthrough));
+ case CHANNEL_BANDWIDTH_CBW40:
+ add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_40MHZ);
+ __attribute__((fallthrough));
+ case CHANNEL_BANDWIDTH_CBW20:
+ if (mvm_sta->support_ht) {
+ add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_20MHZ);
+ }
+ break;
+ default:
+ IWL_WARN(NULL, "No bandwidth from station is indicated, hardcode it to 40mhz.");
+ add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_40MHZ);
+ }
+ add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO2);
+
#endif // NEEDS_PORTING
status = ADD_STA_SUCCESS;
@@ -1668,7 +1675,7 @@
goto err;
}
- if (mvmvif->mac_role == WLAN_INFO_MAC_ROLE_CLIENT) {
+ if (mvmvif->mac_role == WLAN_MAC_ROLE_CLIENT) {
if (!mvm_sta->tdls) {
if (mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
IWL_WARN(mvmvif, "mvmvif->ap_sta_id is invalid\n");
@@ -1681,7 +1688,7 @@
}
}
- mvmvif->mvm->fw_id_to_mac_id[sta_id] = mvm_sta;
+ iwl_rcu_store(mvmvif->mvm->fw_id_to_mac_id[sta_id], mvm_sta);
ret = ZX_OK;
err:
@@ -1690,10 +1697,9 @@
struct iwl_mvm_sta* iwl_mvm_find_sta_by_addr(struct iwl_mvm* mvm, uint8_t addr[ETH_ALEN]) {
struct iwl_mvm_sta* sta = NULL;
- iwl_assert_lock_held(&mvm->mutex);
for (size_t sta_id = 0; sta_id < ARRAY_SIZE(mvm->fw_id_to_mac_id); sta_id++) {
- sta = mvm->fw_id_to_mac_id[sta_id];
+ sta = iwl_rcu_load(mvm->fw_id_to_mac_id[sta_id]);
if (sta == NULL) {
continue;
}
@@ -1750,7 +1756,7 @@
iwl_assert_lock_held(&mvm->mutex);
- struct iwl_mvm_sta* mvm_sta = mvm->fw_id_to_mac_id[sta_id];
+ struct iwl_mvm_sta* mvm_sta = iwl_rcu_load(mvm->fw_id_to_mac_id[sta_id]);
/* Note: internal stations are marked as error values */
if (!mvm_sta) {
@@ -1870,7 +1876,7 @@
*status = IWL_MVM_QUEUE_FREE;
}
- if (mvmvif->mac_role == WLAN_INFO_MAC_ROLE_CLIENT && mvmvif->ap_sta_id == sta_id) {
+ if (mvmvif->mac_role == WLAN_MAC_ROLE_CLIENT && mvmvif->ap_sta_id == sta_id) {
/* if associated - we can't remove the AP STA now */
if (mvmvif->bss_conf.assoc) {
IWL_WARN(mvmvif, "Ignore the AP station removal since it is still associated\n");
@@ -1905,6 +1911,7 @@
#endif // NEEDS_PORTING
ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
+ iwl_rcu_store(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
return ret;
}
@@ -3057,7 +3064,7 @@
#endif // NEEDS_PORTING
static zx_status_t iwl_mvm_send_sta_key(struct iwl_mvm* mvm, uint32_t sta_id,
- const struct iwl_mvm_sta_key_conf* key, bool mcast,
+ const struct ieee80211_key_conf* key, bool mcast,
uint32_t tkip_iv32, uint16_t* tkip_p1k, uint32_t cmd_flags,
uint8_t key_offset, bool mfp) {
union {
@@ -3082,7 +3089,7 @@
key_flags = cpu_to_le16(keyidx);
key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_KEY_MAP);
- switch (key->cipher_type) {
+ switch (key->cipher) {
case CIPHER_SUITE_TYPE_CCMP_128:
key_flags |= cpu_to_le16(STA_KEY_FLG_CCM);
memcpy(u.cmd.common.key, key->key, key->keylen);
@@ -3124,21 +3131,20 @@
return ret;
}
-static int iwl_mvm_send_sta_igtk(struct iwl_mvm* mvm, const struct iwl_mvm_sta_key_conf* keyconf,
+static int iwl_mvm_send_sta_igtk(struct iwl_mvm* mvm, const struct ieee80211_key_conf* keyconf,
uint8_t sta_id, bool remove_key) {
struct iwl_mvm_mgmt_mcast_key_cmd igtk_cmd = {};
/* verify the key details match the required command's expectations */
if (WARN_ON((keyconf->key_type == WLAN_KEY_TYPE_PAIRWISE) ||
(keyconf->keyidx != 4 && keyconf->keyidx != 5) ||
- (keyconf->cipher_type != CIPHER_SUITE_TYPE_BIP_CMAC_128 &&
- keyconf->cipher_type != CIPHER_SUITE_TYPE_BIP_GMAC_128 &&
- keyconf->cipher_type != CIPHER_SUITE_TYPE_BIP_GMAC_256))) {
+ (keyconf->cipher != CIPHER_SUITE_TYPE_BIP_CMAC_128 &&
+ keyconf->cipher != CIPHER_SUITE_TYPE_BIP_GMAC_128 &&
+ keyconf->cipher != CIPHER_SUITE_TYPE_BIP_GMAC_256))) {
return ZX_ERR_INVALID_ARGS;
}
- if (WARN_ON(!iwl_mvm_has_new_rx_api(mvm) &&
- keyconf->cipher_type != CIPHER_SUITE_TYPE_BIP_CMAC_128)) {
+ if (WARN_ON(!iwl_mvm_has_new_rx_api(mvm) && keyconf->cipher != CIPHER_SUITE_TYPE_BIP_CMAC_128)) {
return ZX_ERR_INVALID_ARGS;
}
@@ -3148,7 +3154,7 @@
if (remove_key) {
igtk_cmd.ctrl_flags |= cpu_to_le32(STA_KEY_NOT_VALID);
} else {
- switch (keyconf->cipher_type) {
+ switch (keyconf->cipher) {
case CIPHER_SUITE_TYPE_BIP_CMAC_128:
igtk_cmd.ctrl_flags |= cpu_to_le32(STA_KEY_FLG_CCM);
break;
@@ -3161,7 +3167,7 @@
}
memcpy(igtk_cmd.igtk, keyconf->key, keyconf->keylen);
- if (keyconf->cipher_type == CIPHER_SUITE_TYPE_BIP_GMAC_256) {
+ if (keyconf->cipher == CIPHER_SUITE_TYPE_BIP_GMAC_256) {
igtk_cmd.ctrl_flags |= cpu_to_le32(STA_KEY_FLG_KEY_32BYTES);
}
igtk_cmd.receive_seq_cnt = cpu_to_le64(keyconf->rx_seq);
@@ -3204,7 +3210,7 @@
static zx_status_t __iwl_mvm_set_sta_key(struct iwl_mvm* mvm, struct iwl_mvm_vif* mvmvif,
struct iwl_mvm_sta* mvmsta,
- const struct iwl_mvm_sta_key_conf* keyconf,
+ const struct ieee80211_key_conf* keyconf,
uint8_t key_offset, bool mcast) {
zx_status_t ret = ZX_OK;
uint32_t sta_id;
@@ -3214,15 +3220,15 @@
if (mvmsta) {
sta_id = mvmsta->sta_id;
- } else if (mvmvif->mac_role == WLAN_INFO_MAC_ROLE_AP &&
- keyconf->key_type != WLAN_KEY_TYPE_PAIRWISE) {
+ mfp = (keyconf->key_type == WLAN_KEY_TYPE_IGTK);
+ } else if (mvmvif->mac_role == WLAN_MAC_ROLE_AP && keyconf->key_type != WLAN_KEY_TYPE_PAIRWISE) {
sta_id = mvmvif->mcast_sta.sta_id;
} else {
IWL_ERR(mvm, "Failed to find station id\n");
return ZX_ERR_INVALID_ARGS;
}
- switch (keyconf->cipher_type) {
+ switch (keyconf->cipher) {
case CIPHER_SUITE_TYPE_CCMP_128:
ret = iwl_mvm_send_sta_key(mvm, sta_id, keyconf, mcast, 0, NULL, 0, key_offset, mfp);
break;
@@ -3234,8 +3240,7 @@
}
static zx_status_t __iwl_mvm_remove_sta_key(struct iwl_mvm* mvm, uint8_t sta_id,
- const struct iwl_mvm_sta_key_conf* keyconf,
- uint8_t key_offset, bool mcast) {
+ const struct ieee80211_key_conf* keyconf, bool mcast) {
union {
struct iwl_mvm_add_sta_key_cmd_v1 cmd_v1;
struct iwl_mvm_add_sta_key_cmd cmd;
@@ -3264,7 +3269,7 @@
* of the command, so we can do this union trick.
*/
u.cmd.common.key_flags = key_flags;
- u.cmd.common.key_offset = key_offset;
+ u.cmd.common.key_offset = keyconf->hw_key_idx;
u.cmd.common.sta_id = sta_id;
size = new_api ? sizeof(u.cmd) : sizeof(u.cmd_v1);
@@ -3286,37 +3291,28 @@
}
zx_status_t iwl_mvm_set_sta_key(struct iwl_mvm* mvm, struct iwl_mvm_vif* mvmvif,
- struct iwl_mvm_sta* mvmsta,
- const struct iwl_mvm_sta_key_conf* keyconf, uint8_t key_offset) {
- bool mcast = keyconf->key_type != WLAN_KEY_TYPE_PAIRWISE;
+ struct iwl_mvm_sta* mvmsta, struct ieee80211_key_conf* keyconf,
+ uint8_t key_offset) {
+ bool mcast = keyconf->key_type == WLAN_KEY_TYPE_GROUP;
uint8_t sta_id = IWL_MVM_INVALID_STA;
zx_status_t ret = ZX_OK;
static const uint8_t __maybe_unused zero_addr[ETH_ALEN] = {0};
iwl_assert_lock_held(&mvm->mutex);
- if (mvmvif->mac_role != WLAN_INFO_MAC_ROLE_AP || keyconf->key_type == WLAN_KEY_TYPE_PAIRWISE) {
+ if (mvmvif->mac_role != WLAN_MAC_ROLE_AP || keyconf->key_type == WLAN_KEY_TYPE_PAIRWISE) {
sta_id = mvmsta->sta_id;
} else {
sta_id = mvmvif->mcast_sta.sta_id;
}
- if (keyconf->cipher_type == CIPHER_SUITE_TYPE_BIP_CMAC_128 ||
- keyconf->cipher_type == CIPHER_SUITE_TYPE_BIP_GMAC_128 ||
- keyconf->cipher_type == CIPHER_SUITE_TYPE_BIP_GMAC_256) {
+ if (keyconf->cipher == CIPHER_SUITE_TYPE_BIP_CMAC_128 ||
+ keyconf->cipher == CIPHER_SUITE_TYPE_BIP_GMAC_128 ||
+ keyconf->cipher == CIPHER_SUITE_TYPE_BIP_GMAC_256) {
ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, false);
goto end;
}
- // TODO(fxbug.dev/86728): remove the WPA2 key workaround
- key_offset = keyconf->keyidx;
- if (mvm->active_key_list[key_offset].keylen) {
- // delete the last key if present
- if (iwl_mvm_remove_sta_key(mvmvif, mvmsta, &mvm->active_key_list[key_offset]) != ZX_OK) {
- IWL_WARN(mvm, "Unable to delete key at offset %d", key_offset);
- }
- memset(&mvm->active_key_list[key_offset], 0, sizeof(struct iwl_mvm_sta_key_conf));
- }
/* If the key_offset is not pre-assigned, we need to find a
* new offset to use. In normal cases, the offset is not
@@ -3334,6 +3330,7 @@
if (key_offset == STA_KEY_IDX_INVALID) {
return ZX_ERR_NO_SPACE;
}
+ keyconf->hw_key_idx = key_offset;
}
ret = __iwl_mvm_set_sta_key(mvm, mvmvif, mvmsta, keyconf, key_offset, mcast);
@@ -3347,34 +3344,29 @@
* to the same key slot (offset).
* If this fails, remove the original as well.
*/
- if ((keyconf->cipher_type == CIPHER_SUITE_TYPE_WEP_40 ||
- keyconf->cipher_type == CIPHER_SUITE_TYPE_WEP_104) &&
+ if ((keyconf->cipher == CIPHER_SUITE_TYPE_WEP_40 ||
+ keyconf->cipher == CIPHER_SUITE_TYPE_WEP_104) &&
mvmsta) {
ret = __iwl_mvm_set_sta_key(mvm, mvmvif, mvmsta, keyconf, key_offset, !mcast);
if (ret != ZX_OK) {
- __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, key_offset, mcast);
+ __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
goto end;
}
}
__set_bit(key_offset, mvm->fw_key_table);
- // TODO(fxbug.dev/86728): remove the WPA2 key workaround
- // Save the keyconf in the driver key table for easier deleteion
- mvm->active_key_list[key_offset] = *keyconf;
end:
- IWL_DEBUG_WEP(mvm, "key: cipher=%x len=%zu idx=%d mvmsta=%pM ret=%d\n", keyconf->cipher_type,
+ IWL_DEBUG_WEP(mvm, "key: cipher=%x len=%zu idx=%d mvmsta=%pM ret=%d\n", keyconf->cipher,
keyconf->keylen, keyconf->keyidx, mvmsta ? mvmsta->addr : zero_addr, ret);
return ret;
}
-zx_status_t iwl_mvm_remove_sta_key(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvm_sta,
- struct iwl_mvm_sta_key_conf* keyconf) {
- struct iwl_mvm* mvm = mvmvif->mvm;
+zx_status_t iwl_mvm_remove_sta_key(struct iwl_mvm* mvm, struct iwl_mvm_vif* mvmvif,
+ struct iwl_mvm_sta* mvm_sta,
+ const struct ieee80211_key_conf* keyconf) {
bool mcast = keyconf->key_type != WLAN_KEY_TYPE_PAIRWISE;
uint8_t sta_id = IWL_MVM_INVALID_STA;
- // TODO(fxbug.dev/86728): remove the WPA2 key workaround
- int hw_key_idx = keyconf->keyidx;
int i;
zx_status_t ret;
@@ -3384,16 +3376,14 @@
IWL_INFO(mvm, "mvm remove dynamic key: idx=%d sta=%d\n", keyconf->keyidx, sta_id);
-#if 0 // NEEDS_PORTING
- if (mvm_sta && (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
- keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
- keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256)) {
+ if (mvm_sta && (keyconf->cipher == CIPHER_SUITE_TYPE_BIP_CMAC_128 ||
+ keyconf->cipher == CIPHER_SUITE_TYPE_BIP_GMAC_128 ||
+ keyconf->cipher == CIPHER_SUITE_TYPE_BIP_GMAC_256)) {
return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);
}
-#endif // NEEDS_PORTING
- if (!test_and_clear_bit(hw_key_idx, mvm->fw_key_table)) {
- IWL_ERR(mvm, "offset %d not used in fw key table.\n", hw_key_idx);
+ if (!test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) {
+ IWL_ERR(mvm, "offset %d not used in fw key table.\n", keyconf->hw_key_idx);
return ZX_ERR_BAD_HANDLE;
}
@@ -3403,22 +3393,21 @@
mvm->fw_key_deleted[i]++;
}
}
- mvm->fw_key_deleted[hw_key_idx] = 0;
+ mvm->fw_key_deleted[keyconf->hw_key_idx] = 0;
if (!mvm_sta) {
IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n");
return ZX_OK;
}
- ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, hw_key_idx, mcast);
+ ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
if (ret != ZX_OK) {
return ret;
}
/* delete WEP key twice to get rid of (now useless) offset */
- if (keyconf->cipher_type == CIPHER_SUITE_TYPE_WEP_40 ||
- keyconf->cipher_type == CIPHER_SUITE_TYPE_WEP_104) {
- ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, hw_key_idx, !mcast);
+ if (keyconf->cipher == CIPHER_SUITE_TYPE_WEP_40 || keyconf->cipher == CIPHER_SUITE_TYPE_WEP_104) {
+ ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, !mcast);
}
return ret;
diff --git a/third_party/iwlwifi/mvm/sta.h b/third_party/iwlwifi/mvm/sta.h
index a12e6b4..3780ede 100644
--- a/third_party/iwlwifi/mvm/sta.h
+++ b/third_party/iwlwifi/mvm/sta.h
@@ -37,13 +37,12 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_MVM_STA_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_MVM_STA_H_
-#include <fuchsia/hardware/wlan/info/c/banjo.h>
+#include <fuchsia/hardware/wlan/associnfo/c/banjo.h>
+#include <fuchsia/hardware/wlan/phyinfo/c/banjo.h>
#include <fuchsia/wlan/ieee80211/c/banjo.h>
#include <threads.h>
#include <zircon/types.h>
-#include <fuchsia/hardware/wlanphyinfo/c/banjo.h>
-
/* for IWL_MAX_TID_COUNT */
#include "third_party/iwlwifi/iwl-trans.h"
#include "third_party/iwlwifi/mvm/rs.h"
@@ -324,6 +323,7 @@
struct iwl_mvm_key_pn {
struct rcu_head rcu_head;
struct {
+ /* Stored in packet byte order (little-endian) */
uint8_t pn[IWL_MAX_TID_COUNT][IEEE80211_CCMP_PN_LEN];
} ____cacheline_aligned_in_smp q[];
};
@@ -359,19 +359,6 @@
};
/**
- * struct iwl_mvm_sta_key_conf - per station key configuration data
- */
-struct iwl_mvm_sta_key_conf {
- atomic64_t tx_pn;
- uint64_t rx_seq;
- cipher_suite_type_t cipher_type;
- wlan_key_type_t key_type;
- uint8_t keyidx;
- size_t keylen;
- uint8_t key[0];
-};
-
-/**
* struct iwl_mvm_sta - representation of a station in the driver
* @sta_id: the index of the station in the fw (will be replaced by id_n_color)
* @tfd_queue_msk: the tfd queues used by the station
@@ -436,8 +423,6 @@
struct iwl_lq_sta rs_drv;
} lq_sta;
struct iwl_mvm_vif* mvmvif;
- struct iwl_mvm_sta_key_conf* key_conf;
- mtx_t ptk_pn_mutex;
struct iwl_mvm_key_pn __rcu* ptk_pn[4];
struct iwl_mvm_rxq_dup_data* dup_data;
@@ -465,6 +450,14 @@
uint8_t addr[ETH_ALEN];
bool tdls; // not really used, but add here to make code compile
+
+ channel_bandwidth_t bw;
+ bool support_ht;
+ struct ieee80211_ht_capabilities ht_cap;
+ bool support_vht;
+ struct ieee80211_vht_capabilities vht_cap;
+
+ uint8_t supp_rates[WLAN_MAC_MAX_RATES];
};
uint16_t iwl_mvm_tid_queued(struct iwl_mvm* mvm, struct iwl_mvm_tid_data* tid_data);
@@ -510,10 +503,11 @@
zx_status_t iwl_mvm_rm_sta(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvm_sta);
int iwl_mvm_rm_sta_id(struct iwl_mvm* mvm, struct ieee80211_vif* vif, uint8_t sta_id);
int iwl_mvm_set_sta_key(struct iwl_mvm* mvm, struct iwl_mvm_vif* mvm_vif,
- struct iwl_mvm_sta* mvm_sta, const struct iwl_mvm_sta_key_conf* key_conf,
+ struct iwl_mvm_sta* mvm_sta, struct ieee80211_key_conf* key_conf,
uint8_t key_offset);
-zx_status_t iwl_mvm_remove_sta_key(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvmsta,
- struct iwl_mvm_sta_key_conf* keyconf);
+zx_status_t iwl_mvm_remove_sta_key(struct iwl_mvm* mvm, struct iwl_mvm_vif* mvmvif,
+ struct iwl_mvm_sta* mvmsta,
+ const struct ieee80211_key_conf* keyconf);
void iwl_mvm_update_tkip_key(struct iwl_mvm* mvm, struct ieee80211_vif* vif,
struct ieee80211_key_conf* keyconf, struct ieee80211_sta* sta,
@@ -547,7 +541,7 @@
int iwl_mvm_add_mcast_sta(struct iwl_mvm* mvm, struct ieee80211_vif* vif);
int iwl_mvm_rm_mcast_sta(struct iwl_mvm* mvm, struct ieee80211_vif* vif);
int iwl_mvm_allocate_int_sta(struct iwl_mvm* mvm, struct iwl_mvm_int_sta* sta, uint32_t qmask,
- wlan_info_mac_role_t iftype, enum iwl_sta_type type);
+ wlan_mac_role_t iftype, enum iwl_sta_type type);
void iwl_mvm_dealloc_bcast_sta(struct iwl_mvm* mvm, struct ieee80211_vif* vif);
void iwl_mvm_dealloc_int_sta(struct iwl_mvm* mvm, struct iwl_mvm_int_sta* sta);
int iwl_mvm_add_snif_sta(struct iwl_mvm* mvm, struct ieee80211_vif* vif);
diff --git a/third_party/iwlwifi/mvm/time-event.c b/third_party/iwlwifi/mvm/time-event.c
index 9b5d233..29e3233 100644
--- a/third_party/iwlwifi/mvm/time-event.c
+++ b/third_party/iwlwifi/mvm/time-event.c
@@ -163,26 +163,28 @@
out_unlock:
rcu_read_unlock();
}
+#endif // NEEDS_PORTING
-static bool iwl_mvm_te_check_disconnect(struct iwl_mvm* mvm, struct ieee80211_vif* vif,
+static bool iwl_mvm_te_check_disconnect(struct iwl_mvm* mvm, struct iwl_mvm_vif* mvmvif,
const char* errmsg) {
- struct iwl_mvm_vif* mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- if (vif->type != NL80211_IFTYPE_STATION) {
+ if (mvmvif->mac_role != WLAN_MAC_ROLE_CLIENT) {
return false;
}
- if (!mvmvif->csa_bcn_pending && vif->bss_conf.assoc && vif->bss_conf.dtim_period) {
+ if (!mvmvif->csa_bcn_pending && mvmvif->bss_conf.assoc && mvmvif->bss_conf.dtim_period) {
return false;
}
if (errmsg) {
IWL_ERR(mvm, "%s\n", errmsg);
}
+#if 0 // NEEDS_PORTING
iwl_mvm_connection_loss(mvm, vif, errmsg);
+#endif // NEEDS_PORTING
return true;
}
+#if 0 // NEEDS_PORTING
static void iwl_mvm_te_handle_notify_csa(struct iwl_mvm* mvm,
struct iwl_mvm_time_event_data* te_data,
struct iwl_time_event_notif* notif) {
@@ -247,6 +249,7 @@
break;
}
}
+#endif // NEEDS_PORTING
/*
* Handles a FW notification for an event that is known to the driver.
@@ -262,7 +265,9 @@
IWL_DEBUG_TE(mvm, "Handle time event notif - UID = 0x%x action %d\n",
le32_to_cpu(notif->unique_id), le32_to_cpu(notif->action));
+#if 0 // NEEDS_PORTING
iwl_mvm_te_check_trigger(mvm, notif, te_data);
+#endif // NEEDS_PORTING
/*
* The FW sends the start/end time event notifications even for events
@@ -283,28 +288,30 @@
IWL_DEBUG_TE(mvm, "%s\n", msg);
- if (iwl_mvm_te_check_disconnect(mvm, te_data->vif, msg)) {
+ if (iwl_mvm_te_check_disconnect(mvm, te_data->mvmvif, msg)) {
iwl_mvm_te_clear_data(mvm, te_data);
return;
}
}
if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_END) {
- IWL_DEBUG_TE(mvm, "TE ended - current time %lu, estimated end %lu\n", jiffies,
- te_data->end_jiffies);
+ IWL_DEBUG_TE(mvm, "TE ended - current time %lu, estimated end %lu\n", iwl_time_now(mvm->dev),
+ te_data->end_time);
- switch (te_data->vif->type) {
+ switch (te_data->mvmvif->mac_role) {
+#if 0 // NEEDS_PORTING
case NL80211_IFTYPE_P2P_DEVICE:
ieee80211_remain_on_channel_expired(mvm->hw);
set_bit(IWL_MVM_STATUS_NEED_FLUSH_P2P, &mvm->status);
iwl_mvm_roc_finished(mvm);
break;
- case NL80211_IFTYPE_STATION:
+#endif // NEEDS_PORTING
+ case WLAN_MAC_ROLE_CLIENT:
/*
* By now, we should have finished association
* and know the dtim period.
*/
- iwl_mvm_te_check_disconnect(mvm, te_data->vif,
+ iwl_mvm_te_check_disconnect(mvm, te_data->mvmvif,
"No beacon heard and the time event is over already...");
break;
default:
@@ -314,8 +321,9 @@
iwl_mvm_te_clear_data(mvm, te_data);
} else if (le32_to_cpu(notif->action) & TE_V2_NOTIF_HOST_EVENT_START) {
te_data->running = true;
- te_data->end_jiffies = TU_TO_EXP_TIME(te_data->duration);
+ te_data->end_time = TU_TO_DURATION(te_data->duration);
+#if 0 // NEEDS_PORTING
if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {
set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
iwl_mvm_ref(mvm, IWL_MVM_REF_ROC);
@@ -323,11 +331,13 @@
} else if (te_data->id == TE_CHANNEL_SWITCH_PERIOD) {
iwl_mvm_te_handle_notify_csa(mvm, te_data, notif);
}
+#endif // NEEDS_PORTING
} else {
IWL_WARN(mvm, "Got TE with unknown action\n");
}
}
+#if 0 // NEEDS_PORTING
/*
* Handle A Aux ROC time event
*/
@@ -374,6 +384,7 @@
return 0;
}
+#endif // NEEDS_PORTING
/*
* The Rx handler for time event notifications
@@ -386,21 +397,24 @@
IWL_DEBUG_TE(mvm, "Time event notification - UID = 0x%x action %d\n",
le32_to_cpu(notif->unique_id), le32_to_cpu(notif->action));
- spin_lock_bh(&mvm->time_event_lock);
+ mtx_lock(&mvm->time_event_lock);
+
+#if 0 // NEEDS_PORTING
/* This time event is triggered for Aux ROC request */
if (!iwl_mvm_aux_roc_te_handle_notif(mvm, notif)) {
goto unlock;
}
+#endif // NEEDS_PORTING
- list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) {
+ list_for_every_entry_safe (&mvm->time_event_list, te_data, tmp, struct iwl_mvm_time_event_data,
+ list) {
if (le32_to_cpu(notif->unique_id) == te_data->uid) {
iwl_mvm_te_handle_notif(mvm, te_data, notif);
}
}
-unlock:
- spin_unlock_bh(&mvm->time_event_lock);
+
+ mtx_unlock(&mvm->time_event_lock);
}
-#endif // NEEDS_PORTING
static bool iwl_mvm_te_notif(struct iwl_notif_wait_data* notif_wait, struct iwl_rx_packet* pkt,
void* data) {
@@ -481,6 +495,7 @@
mtx_unlock(&mvm->time_event_lock);
return ZX_ERR_BAD_STATE;
}
+ // TODO(fxbug.dev/88102): ensure pointer validation.
te_data->mvmvif = mvmvif;
te_data->duration = le32_to_cpu(te_cmd->duration);
te_data->id = le32_to_cpu(te_cmd->id);
diff --git a/third_party/iwlwifi/mvm/tx.c b/third_party/iwlwifi/mvm/tx.c
index 743a343..701ab44 100644
--- a/third_party/iwlwifi/mvm/tx.c
+++ b/third_party/iwlwifi/mvm/tx.c
@@ -38,7 +38,7 @@
#include "third_party/iwlwifi/iwl-trans.h"
#include "third_party/iwlwifi/mvm/mvm.h"
#include "third_party/iwlwifi/mvm/sta.h"
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
#include "third_party/iwlwifi/platform/kernel.h"
#if 0 // NEEDS_PORTING
@@ -270,8 +270,8 @@
}
#if 0 // NEEDS_PORTING
-static uint32_t iwl_mvm_get_tx_ant(struct iwl_mvm* mvm, struct ieee80211_tx_info* info,
- struct ieee80211_sta* sta, __le16 fc) {
+static uint32_t iwl_mvm_get_tx_ant(struct iwl_mvm* mvm) {
+ // TODO(fxbug.dev/91465): Configure the ANT bit.
if (info->band == NL80211_BAND_2GHZ && !iwl_mvm_bt_coex_is_shared_ant_avail(mvm)) {
return mvm->cfg->non_shared_ant << RATE_MCS_ANT_POS;
}
@@ -285,8 +285,7 @@
return BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
}
-static uint32_t iwl_mvm_get_tx_rate(struct iwl_mvm* mvm, struct ieee80211_tx_info* info,
- struct ieee80211_sta* sta) {
+static uint32_t iwl_mvm_get_tx_rate(struct iwl_mvm* mvm) {
int rate_idx;
uint8_t rate_plcp;
uint32_t rate_flags = 0;
@@ -327,61 +326,74 @@
struct ieee80211_sta* sta, __le16 fc) {
return iwl_mvm_get_tx_rate(mvm, info, sta) | iwl_mvm_get_tx_ant(mvm, info, sta, fc);
}
+
#endif // NEEDS_PORTING
/*
* Sets the fields in the Tx cmd that are rate related
*/
-void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm* mvm, struct iwl_tx_cmd* tx_cmd) {
+void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm* mvm, struct iwl_tx_cmd* tx_cmd,
+ const struct ieee80211_frame_header* hdr) {
/* Set retry limit on RTS packets */
tx_cmd->rts_retry_limit = IWL_RTS_DFAULT_RETRY_LIMIT;
+ /* Set retry limit on DATA packets and Probe Responses*/
+ tx_cmd->data_retry_limit = IWL_DEFAULT_TX_RETRY;
+
+#if 1 // NEEDS_PORTING
+ // Return in advance if it's a data frame(except EAPOL frame), the rate of data frame is
+ // controlled by LINK_QUALITY command.
+ if (hdr != NULL && ieee80211_is_data(hdr) &&
+ mvm->fw_id_to_mac_id[0]->sta_state >= IWL_STA_AUTHORIZED) {
+ tx_cmd->initial_rate_index = 0;
+ tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
+ return;
+ }
+
tx_cmd->rate_n_flags = iwl_mvm_mac80211_idx_to_hwrate(IWL_FIRST_OFDM_RATE) |
(BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS);
- /* Set retry limit on DATA packets and Probe Responses*/
- tx_cmd->data_retry_limit = IWL_DEFAULT_TX_RETRY;
+#else // NEEDS_PORTING
// TODO(51120): below code needs rewrite to support QoS.
-#if 0 // NEEDS_PORTING
- /* Set retry limit on DATA packets and Probe Responses*/
- if (ieee80211_is_probe_resp(fc)) {
- tx_cmd->data_retry_limit = IWL_MGMT_DFAULT_RETRY_LIMIT;
- tx_cmd->rts_retry_limit = min(tx_cmd->data_retry_limit, tx_cmd->rts_retry_limit);
- } else if (ieee80211_is_back_req(fc)) {
- tx_cmd->data_retry_limit = IWL_BAR_DFAULT_RETRY_LIMIT;
- } else {
- tx_cmd->data_retry_limit = IWL_DEFAULT_TX_RETRY;
- }
+ /* Set retry limit on DATA packets and Probe Responses*/
+ if (ieee80211_is_probe_resp(fc)) {
+ tx_cmd->data_retry_limit = IWL_MGMT_DFAULT_RETRY_LIMIT;
+ tx_cmd->rts_retry_limit = min(tx_cmd->data_retry_limit, tx_cmd->rts_retry_limit);
+ } else if (ieee80211_is_back_req(fc)) {
+ tx_cmd->data_retry_limit = IWL_BAR_DFAULT_RETRY_LIMIT;
+ } else {
+ tx_cmd->data_retry_limit = IWL_DEFAULT_TX_RETRY;
+ }
- /*
- * for data packets, rate info comes from the table inside the fw. This
- * table is controlled by LINK_QUALITY commands
- */
+ /*
+ * for data packets, rate info comes from the table inside the fw. This
+ * table is controlled by LINK_QUALITY commands
+ */
#ifndef CPTCFG_IWLWIFI_FORCE_OFDM_RATE
- if (ieee80211_is_data(fc) && sta) {
- struct iwl_mvm_sta* mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ if (ieee80211_is_data(fc) && sta) {
+ struct iwl_mvm_sta* mvmsta = iwl_mvm_sta_from_mac80211(sta);
- if (mvmsta->sta_state >= IEEE80211_STA_AUTHORIZED) {
- tx_cmd->initial_rate_index = 0;
- tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
- return;
- }
- } else if (ieee80211_is_back_req(fc)) {
- tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_ACK | TX_CMD_FLG_BAR);
+ if (mvmsta->sta_state >= IEEE80211_STA_AUTHORIZED) {
+ tx_cmd->initial_rate_index = 0;
+ tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
+ return;
}
+ } else if (ieee80211_is_back_req(fc)) {
+ tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_ACK | TX_CMD_FLG_BAR);
+ }
#else
- if (ieee80211_is_back_req(fc)) {
- tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_ACK | TX_CMD_FLG_BAR);
- }
+ if (ieee80211_is_back_req(fc)) {
+ tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_ACK | TX_CMD_FLG_BAR);
+ }
#endif
- /* Set the rate in the TX cmd */
- tx_cmd->rate_n_flags = cpu_to_le32(iwl_mvm_get_tx_rate_n_flags(mvm, info, sta, fc));
+ /* Set the rate in the TX cmd */
+ tx_cmd->rate_n_flags = cpu_to_le32(iwl_mvm_get_tx_rate_n_flags(mvm, info, sta, fc));
#endif // NEEDS_PORTING
}
-static void iwl_mvm_set_tx_cmd_pn(struct iwl_mvm_sta_key_conf* keyconf, uint8_t* ccmp_hdr) {
+static void iwl_mvm_set_tx_cmd_pn(struct ieee80211_key_conf* keyconf, uint8_t* ccmp_hdr) {
uint64_t pn = atomic64_inc_return(&keyconf->tx_pn);
ccmp_hdr[0] = pn;
ccmp_hdr[2] = 0;
@@ -396,22 +408,23 @@
/*
* Sets the fields in the Tx cmd that are crypto related
*/
-static zx_status_t iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm* mvm, struct iwl_mvm_sta_key_conf* key,
+static zx_status_t iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm* mvm, struct ieee80211_tx_info* info,
struct iwl_tx_cmd* tx_cmd,
struct ieee80211_mac_packet* pkt) {
- switch (key->cipher_type) {
+ struct ieee80211_key_conf* key_conf = info->control.hw_key;
+ switch (key_conf->cipher) {
case CIPHER_SUITE_TYPE_CCMP_128:
// Insert the CCMP header into the headroom space.
if (sizeof(pkt->headroom) - pkt->headroom_used_size < 8) {
return ZX_ERR_NO_SPACE;
}
- iwl_mvm_set_tx_cmd_ccmp(key, tx_cmd);
- iwl_mvm_set_tx_cmd_pn(key, pkt->headroom + pkt->headroom_used_size);
+ iwl_mvm_set_tx_cmd_ccmp(key_conf, tx_cmd);
+ iwl_mvm_set_tx_cmd_pn(key_conf, pkt->headroom + pkt->headroom_used_size);
tx_cmd->len += 8;
pkt->headroom_used_size += 8;
break;
default:
- tx_cmd->sec_ctl |= TX_CMD_SEC_EXT;
+ tx_cmd->sec_ctl |= TX_CMD_SEC_EXT;
}
return ZX_OK;
}
@@ -429,6 +442,7 @@
*
*/
static zx_status_t iwl_mvm_set_tx_params(struct iwl_mvm* mvm, struct ieee80211_mac_packet* pkt,
+ struct ieee80211_tx_info* info,
const struct iwl_mvm_sta* mvmsta,
struct iwl_device_cmd* dev_cmd) {
zx_status_t ret = ZX_OK;
@@ -512,13 +526,14 @@
tx_cmd = (struct iwl_tx_cmd*)dev_cmd->payload;
iwl_mvm_set_tx_cmd(mvm, pkt, tx_cmd, sta_id);
- if (mvmsta->key_conf) {
- if ((ret = iwl_mvm_set_tx_cmd_crypto(mvm, mvmsta->key_conf, tx_cmd, pkt)) != ZX_OK) {
+ if (info->control.hw_key) {
+ if ((ret = iwl_mvm_set_tx_cmd_crypto(mvm, info, tx_cmd, pkt)) != ZX_OK) {
return ret;
}
}
- iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd);
+ // Set rate ralated fields in iwl_tx_cmd
+ iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, pkt->common_header);
/* Copy MAC header from pkt into command buffer */
memcpy(tx_cmd->hdr, pkt->common_header, pkt->header_size);
@@ -950,14 +965,14 @@
return ZX_OK;
}
-zx_status_t iwl_mvm_tx_mpdu(struct iwl_mvm* mvm, struct ieee80211_mac_packet* pkt,
- struct iwl_mvm_sta* mvmsta) {
+static zx_status_t iwl_mvm_tx_mpdu(struct iwl_mvm* mvm, struct ieee80211_mac_packet* pkt,
+ struct ieee80211_tx_info* info, struct iwl_mvm_sta* mvmsta) {
zx_status_t ret = ZX_OK;
uint8_t tid = IWL_MAX_TID_COUNT; // TODO(51120): support QoS
uint16_t txq_id = mvmsta->tid_data[tid].txq_id;
struct iwl_device_cmd dev_cmd;
- if ((ret = iwl_mvm_set_tx_params(mvm, pkt, mvmsta, &dev_cmd)) != ZX_OK) {
+ if ((ret = iwl_mvm_set_tx_params(mvm, pkt, info, mvmsta, &dev_cmd)) != ZX_OK) {
return ret;
}
@@ -1072,6 +1087,7 @@
zx_status_t iwl_mvm_tx_skb(struct iwl_mvm* mvm, struct ieee80211_mac_packet* pkt,
struct iwl_mvm_sta* mvmsta) {
+ struct ieee80211_tx_info info = pkt->info;
if (!mvmsta) {
IWL_ERR(mvm, "iwl_mvm_tx_skb(): mvmsta is NULL\n");
return ZX_ERR_INVALID_ARGS;
@@ -1082,7 +1098,7 @@
return ZX_ERR_INVALID_ARGS;
}
- return iwl_mvm_tx_mpdu(mvm, pkt, mvmsta);
+ return iwl_mvm_tx_mpdu(mvm, pkt, &info, mvmsta);
#if 0 // NEEDS_PORTING
// TODO(fxbug.dev/61069): supports TSO (TCP Segment Offload)/
diff --git a/third_party/iwlwifi/mvm/utils.c b/third_party/iwlwifi/mvm/utils.c
index 0feff42..81903fd 100644
--- a/third_party/iwlwifi/mvm/utils.c
+++ b/third_party/iwlwifi/mvm/utils.c
@@ -67,7 +67,6 @@
iwl_mvm_ref(mvm, IWL_MVM_REF_SENDING_CMD);
}
}
-
ret = iwl_trans_send_cmd(mvm->trans, cmd);
if (!(cmd->flags & (CMD_ASYNC | CMD_SEND_IN_IDLE))) {
@@ -223,9 +222,9 @@
zx_status_t mac80211_idx_to_data_rate(wlan_info_band_t band, int mac_idx, uint32_t* data_rate) {
int band_offset;
- if (band == WLAN_INFO_BAND_2GHZ) {
+ if (band == WLAN_INFO_BAND_TWO_GHZ) {
band_offset = 0;
- } else if (band == WLAN_INFO_BAND_5GHZ) {
+ } else if (band == WLAN_INFO_BAND_FIVE_GHZ) {
band_offset = IWL_FIRST_OFDM_RATE;
} else {
return ZX_ERR_NOT_SUPPORTED;
@@ -284,7 +283,7 @@
#endif // NEEDS_PORTING
/* Legacy rate format, search for match in table */
- if (band == WLAN_INFO_BAND_5GHZ) {
+ if (band == WLAN_INFO_BAND_FIVE_GHZ) {
band_offset = IWL_FIRST_OFDM_RATE;
}
for (int chan_idx = band_offset; chan_idx < IWL_RATE_COUNT_LEGACY; chan_idx++) {
@@ -705,27 +704,24 @@
* progress.
*/
zx_status_t iwl_mvm_send_lq_cmd(struct iwl_mvm* mvm, struct iwl_lq_cmd* lq, bool sync) {
- return ZX_ERR_NOT_SUPPORTED;
-#if 0 // NEEDS_PORTING
- struct iwl_host_cmd cmd = {
- .id = LQ_CMD,
- .len =
- {
- sizeof(struct iwl_lq_cmd),
- },
- .flags = sync ? 0 : CMD_ASYNC,
- .data =
- {
- lq,
- },
- };
+ struct iwl_host_cmd cmd = {
+ .id = LQ_CMD,
+ .len =
+ {
+ sizeof(struct iwl_lq_cmd),
+ },
+ .flags = sync ? 0 : CMD_ASYNC,
+ .data =
+ {
+ lq,
+ },
+ };
- if (WARN_ON(lq->sta_id == IWL_MVM_INVALID_STA || iwl_mvm_has_tlc_offload(mvm))) {
- return -EINVAL;
- }
-
- return iwl_mvm_send_cmd(mvm, &cmd);
-#endif // NEEDS_PORTING
+ if (WARN_ON(lq->sta_id == IWL_MVM_INVALID_STA || iwl_mvm_has_tlc_offload(mvm))) {
+ return ZX_ERR_INTERNAL;
+ }
+ IWL_DEBUG_RATE(NULL, "Sending LQ_CMD data...");
+ return iwl_mvm_send_cmd(mvm, &cmd);
}
/**
diff --git a/third_party/iwlwifi/pcie/BUILD.bazel b/third_party/iwlwifi/pcie/BUILD.bazel
index c0fff06..96e1d9e 100644
--- a/third_party/iwlwifi/pcie/BUILD.bazel
+++ b/third_party/iwlwifi/pcie/BUILD.bazel
@@ -6,7 +6,6 @@
cc_library(
name = "pcie",
-
srcs = [
"drv.c",
"internal.h",
@@ -17,23 +16,9 @@
],
hdrs = [ "entry.h" ],
deps = [
- # "//garnet/lib/wlan/protocol:protocol",
- # "//sdk/banjo/fuchsia.hardware.pci:fuchsia.hardware.pci_banjo_c",
"//third_party/iwlwifi:core",
"//third_party/iwlwifi/fw",
- # "//third_party/devices/pci/lib/device-protocol-pci",
- # "//third_party/lib/ddk",
- # "//zircon/system/ulib/backtrace-request",
- # "//zircon/system/ulib/sync",
- # "//zircon/system/ulib/zircon-internal",
],
- # public_deps = [
- # "//third_party/iwlwifi/platform",
- # "//zircon/system/public",
- # ]
- # friend =
+ #friend =
# [ "//third_party/iwlwifi/test:*" ]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- #configs += [ "//build/config:Wno-conversion" ]
)
diff --git a/third_party/iwlwifi/pcie/BUILD.gn b/third_party/iwlwifi/pcie/BUILD.gn
index e908134..b9d59e4 100644
--- a/third_party/iwlwifi/pcie/BUILD.gn
+++ b/third_party/iwlwifi/pcie/BUILD.gn
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-visibility = [ "//src/iwlwifi/*" ]
+visibility = [ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/*" ]
source_set("pcie") {
sources = [
@@ -15,22 +15,20 @@
]
public = [ "entry.h" ]
deps = [
- "//garnet/lib/wlan/protocol:protocol",
"//sdk/banjo/fuchsia.hardware.pci:fuchsia.hardware.pci_banjo_c",
- "//src/iwlwifi:core",
- "//src/iwlwifi/fw",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/fw",
"//src/devices/pci/lib/device-protocol-pci",
"//src/lib/ddk",
"//zircon/system/ulib/backtrace-request",
"//zircon/system/ulib/sync",
- "//zircon/system/ulib/zircon-internal",
]
public_deps = [
- "//src/iwlwifi/platform",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform",
"//zircon/system/public",
]
friend =
- [ "//src/iwlwifi/test:*" ]
+ [ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test:*" ]
# TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
configs += [ "//build/config:Wno-conversion" ]
diff --git a/third_party/iwlwifi/pcie/drv.c b/third_party/iwlwifi/pcie/drv.c
index 6ac8f46..0e1cb9d 100644
--- a/third_party/iwlwifi/pcie/drv.c
+++ b/third_party/iwlwifi/pcie/drv.c
@@ -34,9 +34,6 @@
*
*****************************************************************************/
-// TODO(rsakthi) - how to get this from bazel?
-#define CPTCFG_IWLMVM 1
-
#include <stdlib.h>
#include <zircon/status.h>
diff --git a/third_party/iwlwifi/pcie/internal.h b/third_party/iwlwifi/pcie/internal.h
index fb3fd80..9e3b853 100644
--- a/third_party/iwlwifi/pcie/internal.h
+++ b/third_party/iwlwifi/pcie/internal.h
@@ -50,7 +50,7 @@
#include "third_party/iwlwifi/iwl-op-mode.h"
#include "third_party/iwlwifi/iwl-trans.h"
#include "third_party/iwlwifi/platform/compiler.h"
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
#include "third_party/iwlwifi/platform/irq.h"
#include "third_party/iwlwifi/platform/kernel.h"
#include "third_party/iwlwifi/platform/memory.h"
diff --git a/third_party/iwlwifi/pcie/rx.c b/third_party/iwlwifi/pcie/rx.c
index 8a014fc..276612e 100644
--- a/third_party/iwlwifi/pcie/rx.c
+++ b/third_party/iwlwifi/pcie/rx.c
@@ -39,13 +39,13 @@
#include <zircon/time.h>
#if 0 // NEEDS_PORTING
-#include "iwl-context-info-gen3.h"
+#include "third_party/iwlwifi/iwl-context-info-gen3.h"
#endif
-#include "third_party/iwlwifi/platform/align.h"
#include "third_party/iwlwifi/iwl-io.h"
#include "third_party/iwlwifi/iwl-op-mode.h"
#include "third_party/iwlwifi/iwl-prph.h"
#include "third_party/iwlwifi/pcie/internal.h"
+#include "third_party/iwlwifi/platform/align.h"
#include "third_party/iwlwifi/platform/irq.h"
#include "third_party/iwlwifi/platform/memory.h"
diff --git a/third_party/iwlwifi/pcie/trans.c b/third_party/iwlwifi/pcie/trans.c
index c7d1497..9a822b1 100644
--- a/third_party/iwlwifi/pcie/trans.c
+++ b/third_party/iwlwifi/pcie/trans.c
@@ -34,10 +34,6 @@
*
*****************************************************************************/
#define _ALL_SOURCE // for threads.h
-
-// TODO(rsakthi) - how to get this from bazel?
-#define CPTCFG_IWLMVM 1
-
#include <lib/async/time.h>
//#include <lib/device-protocol/pci.h>
#include <stdint.h>
@@ -3265,9 +3261,9 @@
}
#endif // NEEDS_PORTING
-// TODO(rsakthi) - unable to import device-protocol/pci.h
-// status = pci_map_bar_buffer(trans_pcie->pci, 0 /* bar_id */, ZX_CACHE_POLICY_UNCACHED_DEVICE,
-// &trans_pcie->mmio);
+ // TODO(rsakthi) - unable to import device-protocol/pci.h
+ //status = pci_map_bar_buffer(trans_pcie->pci, 0 /* bar_id */, ZX_CACHE_POLICY_UNCACHED_DEVICE,
+ // &trans_pcie->mmio);
if (status != ZX_OK) {
IWL_ERR(trans, "Failed to map resources for BAR 0: %s\n", zx_status_get_string(status));
goto out_no_pci;
diff --git a/third_party/iwlwifi/pcie/tx.c b/third_party/iwlwifi/pcie/tx.c
index 72c1dca..ff48d09 100644
--- a/third_party/iwlwifi/pcie/tx.c
+++ b/third_party/iwlwifi/pcie/tx.c
@@ -39,7 +39,7 @@
#include <zircon/status.h>
#include <zircon/types.h>
-//#include <src/iwlwifi/ieee80211.h>
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
#if 0 // NEEDS_PORTING
#include "third_party/iwlwifi/iwl-op-mode.h"
@@ -50,7 +50,7 @@
#include "third_party/iwlwifi/iwl-prph.h"
#include "third_party/iwlwifi/iwl-scd.h"
#include "third_party/iwlwifi/pcie/internal.h"
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
#define IWL_TX_CRC_SIZE 4
#define IWL_TX_DELIMITER_SIZE 4
diff --git a/third_party/iwlwifi/platform/BUILD.bazel b/third_party/iwlwifi/platform/BUILD.bazel
index bffbd52..d0bd06a 100644
--- a/third_party/iwlwifi/platform/BUILD.bazel
+++ b/third_party/iwlwifi/platform/BUILD.bazel
@@ -1,4 +1,8 @@
+# Copyright 2021 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
package(default_visibility = ["//visibility:public"])
load("@fuchsia_sdk//build_defs:driver_bind_rules.bzl", "driver_header_bind_rules", "driver_bytecode_bind_rules")
@@ -35,12 +39,14 @@
cc_library(
name = "platform",
srcs = [
+ "compiler.cc",
"debug.cc",
"device.cc",
"ieee80211.cc",
"irq.cc",
"memory.cc",
"module.cc",
+ "rcu.cc",
"task-internal.cc",
"task.cc",
"time.cc",
@@ -58,6 +64,7 @@
"memory.h",
"module.h",
"pci.h",
+ "rcu.h",
"task-internal.h",
"task.h",
"time.h",
@@ -69,30 +76,46 @@
],
deps = [
":driver_inspector",
+ ":rcu_manager",
"@fuchsia_sdk//pkg/ddk",
"@fuchsia_sdk//fidl/fuchsia_hardware_pci:fuchsia_hardware_pci_banjo_cc",
- "@fuchsia_sdk//fidl/fuchsia_hardware_wlanphyinfo:fuchsia_hardware_wlanphyinfo_banjo_cc",
- "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_mac:fuchsia_hardware_wlan_mac_banjo_cc",
+ "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_phyinfo:fuchsia_hardware_wlan_phyinfo_banjo_cc",
+ "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_softmac:fuchsia_hardware_wlan_softmac_banjo_cc",
# Needed only for library purposes (channel and ieee includes)
"@fuchsia_sdk//fidl/fuchsia_wlan_common:fuchsia_wlan_common_cc",
- "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_info:fuchsia_hardware_wlan_info_banjo_cc",
+ "@fuchsia_sdk//fidl/fuchsia_wlan_mlme:fuchsia_wlan_mlme_cc",
+ "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_associnfo:fuchsia_hardware_wlan_associnfo_banjo_cc",
],
)
+# Support for RCU synchronization.
+cc_library(
+ name = "rcu_manager",
+ srcs = [ "rcu-manager.cc" ],
+ hdrs = [ "rcu-manager.h" ],
+ deps = [
+ "@fuchsia_sdk//pkg/async",
+ "@fuchsia_sdk//pkg/async_cpp",
+ ],
+)
+
cc_library(
name = "fuchsia_device",
srcs = [
# "bind.cc",
"mvm-mlme.cc",
+ "mvm-sta.cc",
"pcie-device.cc",
- "wlanmac-device.cc",
+ "wlan-softmac-device.cc",
"wlanphy-impl-device.cc",
],
hdrs = [
"mvm-mlme.h",
+ "mvm-sta.h",
"pcie-device.h",
- "wlanmac-device.h",
+ "scoped_utils.h",
+ "wlan-softmac-device.h",
"wlanphy-impl-device.h",
"ieee80211.h",
],
@@ -100,35 +123,27 @@
":driver_inspector",
# ":fuchsia_bind",
":platform",
+ ":rcu_manager",
"@fuchsia_sdk//pkg/ddktl_experimental_driver_only",
- "@fuchsia_sdk//fidl/fuchsia_hardware_wlanphyinfo:fuchsia_hardware_wlanphyinfo_banjo_cc",
- "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_mac:fuchsia_hardware_wlan_mac_banjo_cc",
+ "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_phyinfo:fuchsia_hardware_wlan_phyinfo_banjo_cc",
+ "@fuchsia_sdk//fidl/fuchsia_hardware_wlan_softmac:fuchsia_hardware_wlan_softmac_banjo_cc",
"@fuchsia_sdk//fidl/fuchsia_hardware_wlanphyimpl:fuchsia_hardware_wlanphyimpl_banjo_cc",
"@fuchsia_sdk//fidl/fuchsia_wlan_common:fuchsia_wlan_common_banjo_cc",
"@fuchsia_sdk//fidl/fuchsia_wlan_ieee80211:fuchsia_wlan_ieee80211_cc",
"@fuchsia_sdk//fidl/fuchsia_wlan_internal:fuchsia_wlan_internal_banjo_cc",
- "//third_party/iwlwifi:core",
- # "//third_party/iwlwifi/cfg",
- "//third_party/iwlwifi/mvm:mvm",
- "//third_party/iwlwifi/pcie",
- # "//third_party/devices/lib/driver",
+ "//third_party/iwlwifi:core",
+ "//third_party/iwlwifi/mvm:mvm",
+ "//third_party/iwlwifi/pcie",
"@fuchsia_sdk//pkg/ddk",
"@fuchsia_sdk//pkg/async_loop_cpp",
"@fuchsia_sdk//pkg/async_loop_default",
- # "//third_party/lib/ddktl",
-
- # Zircon deps dont have to be mentioned I think.
- # "//zircon/system/public",
- # "//zircon/system/ulib/async-loop:async-loop-cpp",
- # "//zircon/system/ulib/async-loop:async-loop-default",
- # "//zircon/system/ulib/fbl",
],
- copts = ["-Ithird_party/iwlwifi"],
-)
-#source_set("fuchsia_device") {
-# friend =
-# [ "//third_party/iwlwifi/test:*" ]
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
-# configs += [ "//build/config:Wno-conversion" ]
-#}
+ copts = ["-Ithird_party/iwlwifi"],
+
+ # This doesn't seem to be taking effect.
+ defines = [
+ "CPTCFG_IWL_TIMEOUT_FACTOR=1",
+ "CPTCFG_IWLMVM=1",
+ ],
+)
diff --git a/third_party/iwlwifi/platform/BUILD.gn b/third_party/iwlwifi/platform/BUILD.gn
index 13e83b7..a476f4b 100644
--- a/third_party/iwlwifi/platform/BUILD.gn
+++ b/third_party/iwlwifi/platform/BUILD.gn
@@ -4,19 +4,21 @@
import("//build/bind/bind.gni")
-visibility = [ "//src/iwlwifi/*" ]
+visibility = [ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/*" ]
# This BUILD.gn defines the Fuchsia-specific platform support library for the iwlwifi driver.
# Platform-support library for the iwlwifi driver.
source_set("platform") {
sources = [
+ "compiler.cc",
"debug.cc",
"device.cc",
"ieee80211.cc",
"irq.cc",
"memory.cc",
"module.cc",
+ "rcu.cc",
"task-internal.cc",
"task.cc",
"time.cc",
@@ -31,27 +33,29 @@
"memory.h",
"module.h",
"pci.h",
+ "rcu.h",
"task-internal.h",
"task.h",
"time.h",
]
deps = [
":driver_inspector",
+ ":rcu_manager",
"//sdk/lib/stdcompat",
- "//src/connectivity/wlan/lib/common/cpp:common",
- "//zircon/system/ulib/sync",
+ "//zircon/system/ulib/async:async-cpp",
]
public_deps = [
- "//garnet/lib/wlan/protocol:protocol",
- "//sdk/banjo/ddk.hw.wlan.wlaninfo:ddk.hw.wlan.wlaninfo_banjo_c",
"//sdk/banjo/fuchsia.hardware.pci:fuchsia.hardware.pci_banjo_c",
- "//sdk/banjo/fuchsia.hardware.wlan.mac:fuchsia.hardware.wlan.mac_banjo_c",
+ "//sdk/banjo/fuchsia.hardware.wlan.phyinfo:fuchsia.hardware.wlan.phyinfo_banjo_c",
+ "//sdk/banjo/fuchsia.hardware.wlan.softmac:fuchsia.hardware.wlan.softmac_banjo_c",
+ "//sdk/fidl/fuchsia.wlan.common:fuchsia.wlan.common_banjo_c",
+ "//src/connectivity/wlan/lib/common/cpp:common",
"//src/lib/ddk",
"//zircon/system/public",
"//zircon/system/ulib/async",
]
public_configs = [
- "//src/iwlwifi:fuchsia_config",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:fuchsia_config",
]
}
@@ -66,6 +70,17 @@
]
}
+# Support for RCU synchronization.
+source_set("rcu_manager") {
+ sources = [ "rcu-manager.cc" ]
+ public = [ "rcu-manager.h" ]
+ deps = [
+ "//zircon/system/public",
+ "//zircon/system/ulib/async:async-cpp",
+ ]
+ public_deps = [ "//zircon/system/ulib/async" ]
+}
+
driver_bind_rules("fuchsia_bind") {
rules = "iwlwifi.bind"
header_output = "iwlwifi-bind.h"
@@ -79,10 +94,13 @@
"bind.cc",
"mvm-mlme.cc",
"mvm-mlme.h",
+ "mvm-sta.cc",
+ "mvm-sta.h",
"pcie-device.cc",
"pcie-device.h",
- "wlanmac-device.cc",
- "wlanmac-device.h",
+ "scoped_utils.h",
+ "wlan-softmac-device.cc",
+ "wlan-softmac-device.h",
"wlanphy-impl-device.cc",
"wlanphy-impl-device.h",
]
@@ -90,26 +108,27 @@
":driver_inspector",
":fuchsia_bind",
":platform",
- "//sdk/banjo/ddk.hw.wlan.wlaninfo:ddk.hw.wlan.wlaninfo_banjo_cpp",
- "//sdk/banjo/fuchsia.hardware.wlan.mac:fuchsia.hardware.wlan.mac_banjo_cpp",
+ ":rcu_manager",
+ "//sdk/banjo/fuchsia.hardware.wlan.phyinfo:fuchsia.hardware.wlan.phyinfo_banjo_cpp",
+ "//sdk/banjo/fuchsia.hardware.wlan.softmac:fuchsia.hardware.wlan.softmac_banjo_cpp",
"//sdk/banjo/fuchsia.hardware.wlanphyimpl:fuchsia.hardware.wlanphyimpl_banjo_cpp",
"//sdk/fidl/fuchsia.wlan.common:fuchsia.wlan.common_banjo_cpp",
"//sdk/fidl/fuchsia.wlan.ieee80211:fuchsia.wlan.ieee80211_llcpp",
"//sdk/fidl/fuchsia.wlan.internal:fuchsia.wlan.internal_banjo_cpp",
- "//src/iwlwifi:core",
- "//src/iwlwifi/cfg",
- "//src/iwlwifi/mvm",
- "//src/iwlwifi/pcie",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/cfg",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/pcie",
+ "//src/connectivity/wlan/lib/common/cpp:common",
"//src/devices/lib/driver",
"//src/lib/ddk",
"//src/lib/ddktl",
"//zircon/system/public",
"//zircon/system/ulib/async-loop:async-loop-cpp",
"//zircon/system/ulib/async-loop:async-loop-default",
- "//zircon/system/ulib/fbl",
]
friend =
- [ "//src/iwlwifi/test:*" ]
+ [ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test:*" ]
# TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
configs += [ "//build/config:Wno-conversion" ]
diff --git a/third_party/iwlwifi/platform/channel.cc b/third_party/iwlwifi/platform/channel.cc
index c9c824e..f6d3fa8 100644
--- a/third_party/iwlwifi/platform/channel.cc
+++ b/third_party/iwlwifi/platform/channel.cc
@@ -283,14 +283,28 @@
switch (phy) {
case WLAN_INFO_PHY_TYPE_DSSS:
return "802.11 DSSS";
- case WLAN_INFO_PHY_TYPE_CCK:
+ case WLAN_INFO_PHY_TYPE_HR:
return "802.11b CCK/DSSS";
- case WLAN_INFO_PHY_TYPE_OFDM: // and WLAN_INFO_PHY_TYPE_ERP
+ case WLAN_INFO_PHY_TYPE_OFDM:
return "802.11a/g OFDM";
+ case WLAN_INFO_PHY_TYPE_ERP:
+ return "802.11g ERP";
case WLAN_INFO_PHY_TYPE_HT:
return "802.11n HT";
+ case WLAN_INFO_PHY_TYPE_DMG:
+ return "802.11ad DMG";
case WLAN_INFO_PHY_TYPE_VHT:
return "802.11ac VHT";
+ case WLAN_INFO_PHY_TYPE_TVHT:
+ return "802.11af TVHT";
+ case WLAN_INFO_PHY_TYPE_S1G:
+ return "802.11ah S1G";
+ case WLAN_INFO_PHY_TYPE_CDMG:
+ return "802.11aj CDMG";
+ case WLAN_INFO_PHY_TYPE_CMMG:
+ return "802.11aj CMMG";
+ case WLAN_INFO_PHY_TYPE_HE:
+ return "802.11ax HE";
default:
return "UNKNOWN_PHY";
}
@@ -300,7 +314,7 @@
// TODO(fxbug.dev/29293): Streamline the enum values
switch (phy) {
case wlan_common::PHY::HR:
- return WLAN_INFO_PHY_TYPE_CCK;
+ return WLAN_INFO_PHY_TYPE_HR;
case wlan_common::PHY::ERP:
return WLAN_INFO_PHY_TYPE_OFDM;
case wlan_common::PHY::HT:
@@ -308,18 +322,18 @@
case wlan_common::PHY::VHT:
return WLAN_INFO_PHY_TYPE_VHT;
case wlan_common::PHY::HEW:
- return WLAN_INFO_PHY_TYPE_HEW;
+ return WLAN_INFO_PHY_TYPE_HE;
default:
//errorf("Unknown phy value: %d\n", phy);
ZX_DEBUG_ASSERT(false);
- return WLAN_INFO_PHY_TYPE_HEW;
+ return WLAN_INFO_PHY_TYPE_DSSS;
}
}
::fuchsia::wlan::common::PHY ToFidl(wlan_info_phy_type_t phy) {
// TODO(fxbug.dev/29293): Streamline the enum values
switch (phy) {
- case WLAN_INFO_PHY_TYPE_CCK:
+ case WLAN_INFO_PHY_TYPE_HR:
return wlan_common::PHY::HR;
case WLAN_INFO_PHY_TYPE_OFDM:
return wlan_common::PHY::ERP;
@@ -327,12 +341,12 @@
return wlan_common::PHY::HT;
case WLAN_INFO_PHY_TYPE_VHT:
return wlan_common::PHY::VHT;
- case WLAN_INFO_PHY_TYPE_HEW:
+ case WLAN_INFO_PHY_TYPE_HE:
return wlan_common::PHY::HEW;
default:
//errorf("Unknown phy value: %d\n", phy);
ZX_DEBUG_ASSERT(false);
- return wlan_common::PHY::HEW;
+ return wlan_common::PHY::HR;
}
}
diff --git a/third_party/iwlwifi/platform/channel.h b/third_party/iwlwifi/platform/channel.h
index 4c01703..8c3b98c 100644
--- a/third_party/iwlwifi/platform/channel.h
+++ b/third_party/iwlwifi/platform/channel.h
@@ -5,15 +5,14 @@
#ifndef SRC_CONNECTIVITY_WLAN_LIB_COMMON_CPP_INCLUDE_WLAN_COMMON_CHANNEL_H_
#define SRC_CONNECTIVITY_WLAN_LIB_COMMON_CPP_INCLUDE_WLAN_COMMON_CHANNEL_H_
-#include <fuchsia/hardware/wlan/info/c/banjo.h>
+#include <fuchsia/hardware/wlan/associnfo/c/banjo.h>
+#include <fuchsia/hardware/wlan/phyinfo/c/banjo.h>
#include <fuchsia/wlan/common/c/banjo.h>
-#include <fuchsia/wlan/common/cpp/fidl.h>
+#include <fuchsia/wlan/mlme/cpp/fidl.h>
#include <cstdint>
#include <string>
-#include <fuchsia/hardware/wlanphyinfo/c/banjo.h>
-
bool operator==(const wlan_channel_t& lhs, const wlan_channel_t& rhs);
bool operator!=(const wlan_channel_t& lhs, const wlan_channel_t& rhs);
@@ -58,11 +57,11 @@
// See IEEE Std 802.11-2016 19.3.15
};
-wlan_channel_t FromFidl(const fuchsia::wlan::common::WlanChannel& fidl_channel);
-fuchsia::wlan::common::WlanChannel ToFidl(const wlan_channel_t& channel);
+wlan_channel_t FromFidl(const ::fuchsia::wlan::common::WlanChannel& fidl_channel);
+::fuchsia::wlan::common::WlanChannel ToFidl(const wlan_channel_t& channel);
-wlan_info_phy_type_t FromFidl(fuchsia::wlan::common::PHY phy);
-fuchsia::wlan::common::PHY ToFidl(wlan_info_phy_type_t phy);
+wlan_info_phy_type_t FromFidl(::fuchsia::wlan::common::PHY phy);
+::fuchsia::wlan::common::PHY ToFidl(wlan_info_phy_type_t phy);
const char* CbwSuffix(channel_bandwidth_t cbw);
const char* CbwStr(channel_bandwidth_t cbw);
diff --git a/third_party/iwlwifi/platform/compiler.cc b/third_party/iwlwifi/platform/compiler.cc
new file mode 100644
index 0000000..63d3d26
--- /dev/null
+++ b/third_party/iwlwifi/platform/compiler.cc
@@ -0,0 +1,85 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/iwlwifi/platform/compiler.h"
+
+#define BITARR_TYPE_NUM_BITS (sizeof(uint64_t) * 8)
+
+// Find the first asserted LSB(assume the input is little-endian).
+//
+// Returns:
+// [0, num_bits): found. The index of first asserted bit (the least significant one).
+// num_bits: No asserted bit found in num_bits.
+//
+size_t find_first_bit(unsigned int* bits, const size_t num_bits) {
+ const size_t num_of_ints = DIV_ROUND_UP(num_bits, BITS_PER_INT);
+ size_t ret = num_bits;
+
+ for (size_t i = 0; i < num_of_ints; ++i) {
+ if (bits[i] == 0) {
+ continue;
+ }
+ ret = (i * BITS_PER_INT) + __builtin_ctz(bits[i]);
+ break;
+ }
+
+ return MIN(num_bits, ret);
+}
+
+// Find the last asserted MSB(assume the input is little-endian).
+//
+// Returns:
+// [0, num_bits): found. The index of last asserted bit (the most significant one).
+// num_bits: No asserted bit found in num_bits.
+//
+size_t find_last_bit(unsigned int* bits, const size_t num_bits) {
+ const size_t num_of_ints = DIV_ROUND_UP(num_bits, BITS_PER_INT);
+ const size_t size_inside_int = (num_bits - 1) % BITS_PER_INT + 1;
+ unsigned int mask =
+ size_inside_int == BITS_PER_INT ? ~0U : (unsigned int)(1 << size_inside_int) - 1;
+
+ size_t ret = num_bits;
+ for (int64_t i = (int64_t)(num_of_ints - 1); i >= 0; --i) {
+ if (bits[i] == 0) {
+ continue;
+ }
+ unsigned int val = mask & bits[i];
+
+ if (val == 0) {
+ continue;
+ }
+ ret = (i * BITS_PER_INT) + (BITS_PER_INT - 1 - __builtin_clz(val));
+ break;
+ }
+
+ return MIN(num_bits, ret);
+}
+
+// Find next bit which is set in an unsigned integer.
+//
+// Returns:
+// [0, num_bits): found. The index of next bit which is set to 1 starts from bit_offset.
+// num_bits: No asserted bit found in num_bits.
+//
+size_t find_next_bit(unsigned int* bitarr, size_t num_bits, size_t bit_offset) {
+ if (bit_offset >= num_bits) {
+ return num_bits;
+ }
+
+ size_t word_offset = bit_offset / BITARR_TYPE_NUM_BITS;
+ size_t offset_within_word = bit_offset % BITARR_TYPE_NUM_BITS;
+
+ size_t rest = bitarr[word_offset] & (~0ULL << offset_within_word);
+ if (rest != 0) {
+ int bit = __builtin_ffsll(rest) - 1;
+ return MIN(word_offset * BITARR_TYPE_NUM_BITS + bit, num_bits);
+ }
+
+ size_t skipped_bits = (word_offset + 1) * BITARR_TYPE_NUM_BITS;
+ if (skipped_bits >= num_bits) {
+ return num_bits;
+ }
+
+ return skipped_bits + find_first_bit(bitarr + word_offset + 1, num_bits - skipped_bits);
+}
diff --git a/third_party/iwlwifi/platform/compiler.h b/third_party/iwlwifi/platform/compiler.h
index 1a7a2f9..ed0a1dd 100644
--- a/third_party/iwlwifi/platform/compiler.h
+++ b/third_party/iwlwifi/platform/compiler.h
@@ -14,6 +14,8 @@
#include <string.h>
#include <zircon/compiler.h>
+#include "third_party/iwlwifi/platform/debug.h"
+
typedef uint32_t __be32;
typedef uint16_t __be16;
typedef uint64_t __le64;
@@ -22,12 +24,21 @@
typedef int8_t __s8;
typedef uint8_t __u8;
+#define U08 uint8_t
+#define U16 uint16_t
+#define U32 uint32_t
+#define U64 uint64_t
+#define INLINE inline
+
#if defined(__cplusplus)
extern "C++" {
#include <atomic>
} // extern "C++"
#define _Atomic(T) std::atomic<T>
+using std::memory_order_acq_rel;
+using std::memory_order_acquire;
using std::memory_order_relaxed;
+using std::memory_order_release;
using std::memory_order_seq_cst;
#else // defined(__cplusplus)
#include <stdatomic.h>
@@ -133,7 +144,7 @@
static inline void __set_bit(unsigned long bit, volatile unsigned long* addr) {
volatile unsigned long* p = addr + (bit / BITS_PER_LONG);
const unsigned long mask = 1ul << (bit % BITS_PER_LONG);
- *p |= mask;
+ *p = *p | mask;
}
// Atomic operations. DANGER DANGER DANGER HERE BE DRAGONS
@@ -227,25 +238,24 @@
#define max_t(type, a, b) MAX((type)(a), (type)(b))
#define min_t(type, a, b) MIN((type)(a), (type)(b))
-// Find the first asserted LSB.
-//
-// Returns:
-// [0, num_bits): found. The index of first asserted bit (the least significant one.
-// num_bits: No asserted bit found in num_bits.
-//
-static inline size_t find_first_bit(unsigned* bits, const size_t num_bits) {
- const size_t num_of_ints = DIV_ROUND_UP(num_bits, BITS_PER_INT);
- size_t ret = num_bits;
+size_t find_first_bit(unsigned int* bits, const size_t num_bits);
- for (size_t i = 0; i < num_of_ints; ++i) {
- if (bits[i] == 0) {
- continue;
- }
- ret = (i * BITS_PER_INT) + __builtin_ctz(bits[i]);
- break;
- }
+size_t find_last_bit(unsigned int* bits, const size_t num_bits);
- return MIN(num_bits, ret);
+#define BITARR_TYPE_NUM_BITS (sizeof(uint64_t) * 8)
+
+size_t find_next_bit(unsigned int* bitarr, size_t num_bits, size_t bit_offset);
+
+#define for_each_set_bit(bit, bitarr, num_bits) \
+ for ((bit) = find_first_bit((bitarr), (num_bits)); (bit) < (num_bits); \
+ (bit) = find_next_bit((bitarr), (num_bits), (bit) + 1))
+
+// This function calculates the hamming weight of an 8-bit bitmap.
+static inline uint8_t hweight8(uint8_t bitmap) {
+ uint8_t hw = bitmap - ((bitmap >> 1) & 0x55);
+ hw = (hw & 0x33) + ((hw >> 2) & 0x33);
+ hw = (hw + (hw >> 4)) & 0x0F;
+ return hw;
}
#if defined(__cplusplus)
diff --git a/third_party/iwlwifi/platform/debug.cc b/third_party/iwlwifi/platform/debug.cc
index eba96ea..ab02bae 100644
--- a/third_party/iwlwifi/platform/debug.cc
+++ b/third_party/iwlwifi/platform/debug.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "debug.h"
+#include "third_party/iwlwifi/platform/debug.h"
#include <stdint.h>
#include <stdio.h>
@@ -13,8 +13,8 @@
#include <memory>
#include <numeric>
-#include "driver-inspector.h"
-#include "kernel.h"
+#include "third_party/iwlwifi/platform/driver-inspector.h"
+#include "third_party/iwlwifi/platform/kernel.h"
// Maximum bytes to dump in hex_dump_str()
constexpr size_t kMaxDumpLenInARow = 16;
diff --git a/third_party/iwlwifi/platform/device.cc b/third_party/iwlwifi/platform/device.cc
index 54fd7d1..dca48bb 100644
--- a/third_party/iwlwifi/platform/device.cc
+++ b/third_party/iwlwifi/platform/device.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "device.h"
+#include "third_party/iwlwifi/platform/device.h"
#include <lib/ddk/driver.h>
diff --git a/third_party/iwlwifi/platform/device.h b/third_party/iwlwifi/platform/device.h
index 34914cf..98b9a71 100644
--- a/third_party/iwlwifi/platform/device.h
+++ b/third_party/iwlwifi/platform/device.h
@@ -5,7 +5,7 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_DEVICE_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_DEVICE_H_
-#include "kernel.h"
+#include "third_party/iwlwifi/platform/kernel.h"
#if defined(__cplusplus)
extern "C" {
diff --git a/third_party/iwlwifi/platform/ieee80211.cc b/third_party/iwlwifi/platform/ieee80211.cc
index b891259..0f495f9 100644
--- a/third_party/iwlwifi/platform/ieee80211.cc
+++ b/third_party/iwlwifi/platform/ieee80211.cc
@@ -4,9 +4,10 @@
// This file is in C++, as it interfaces with C++-only libraries.
-#include "ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
-#include "channel.h"
+#include "third_party/iwlwifi/platform/channel.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
size_t ieee80211_get_header_len(const struct ieee80211_frame_header* fw) {
return ieee80211_hdrlen(fw);
diff --git a/third_party/iwlwifi/platform/ieee80211.h b/third_party/iwlwifi/platform/ieee80211.h
index 73aad70..fefd20a 100644
--- a/third_party/iwlwifi/platform/ieee80211.h
+++ b/third_party/iwlwifi/platform/ieee80211.h
@@ -19,13 +19,15 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_IEEE80211_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_IEEE80211_H_
-#include <fuchsia/hardware/wlan/mac/c/banjo.h>
+#include <fuchsia/hardware/wlan/phyinfo/c/banjo.h>
+#include <fuchsia/hardware/wlan/softmac/c/banjo.h>
#include <netinet/if_ether.h>
#include <stddef.h>
#include <stdint.h>
-#include <fuchsia/hardware/wlanphyinfo/c/banjo.h>
-#include "ieee80211_include.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
+
+#include "third_party/iwlwifi/platform/compiler.h"
#if defined(__cplusplus)
extern "C" {
@@ -45,6 +47,34 @@
#define IEEE80211_SCTL_SEQ_OFFSET 4
#define IEEE80211_SEQ_TO_SN(seq) (((seq) >> IEEE80211_SCTL_SEQ_OFFSET) & IEEE80211_SCTL_SEQ_MASK)
+/* 802.11n HT capabilities masks (for cap_info) */
+#define IEEE80211_HT_CAP_LDPC_CODING 0x0001
+#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002
+#define IEEE80211_HT_CAP_SM_PS 0x000C
+#define IEEE80211_HT_CAP_SM_PS_SHIFT 2
+#define IEEE80211_HT_CAP_GRN_FLD 0x0010
+#define IEEE80211_HT_CAP_SGI_20 0x0020
+#define IEEE80211_HT_CAP_SGI_40 0x0040
+#define IEEE80211_HT_CAP_TX_STBC 0x0080
+#define IEEE80211_HT_CAP_RX_STBC 0x0300
+#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8
+#define IEEE80211_HT_CAP_DELAY_BA 0x0400
+#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800
+#define IEEE80211_HT_CAP_DSSSCCK40 0x1000
+#define IEEE80211_HT_CAP_RESERVED 0x2000
+#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000
+#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000
+
+/* 802.11n HT capability MSC set */
+#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff
+#define IEEE80211_HT_MCS_TX_DEFINED 0x01
+#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02
+
+#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C
+#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2
+#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4
+#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10
+
// The order of access categories is not clearly specified in 802.11-2016 Std.
// Therefore it cannot be moved into ieee80211 banjo file.
enum ieee80211_ac_numbers {
@@ -68,6 +98,18 @@
IEEE80211_HT_MAX_AMPDU_64K = 3
};
+/* Minimum MPDU start spacing */
+enum ieee80211_min_mpdu_spacing {
+ IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */
+ IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */
+ IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */
+ IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */
+ IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */
+ IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */
+ IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */
+ IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */
+};
+
enum ieee80211_roc_type {
IEEE80211_ROC_TYPE_NORMAL = 0,
IEEE80211_ROC_TYPE_MGMT_TX,
@@ -127,12 +169,28 @@
int max_power;
};
+struct ieee80211_mcs_info {
+ uint8_t rx_mask[IEEE80211_HT_MCS_MASK_LEN];
+ __le16 rx_highest_le;
+ uint8_t tx_params;
+ uint8_t reserved[3];
+} __packed;
+
+struct ieee80211_sta_ht_cap {
+ uint16_t cap; /* use IEEE80211_HT_CAP_ */
+ bool ht_supported;
+ uint8_t ampdu_factor;
+ uint8_t ampdu_density;
+ struct ieee80211_mcs_info mcs;
+};
+
struct ieee80211_supported_band {
wlan_info_band_t band;
struct ieee80211_channel* channels;
int n_channels;
uint16_t* bitrates;
int n_bitrates;
+ struct ieee80211_sta_ht_cap ht_cap;
};
struct ieee80211_tx_queue_params {
@@ -152,10 +210,6 @@
struct ieee80211_txq* txq[IEEE80211_TIDS_MAX + 1];
};
-struct ieee80211_tx_info {
- void* driver_data[8];
-};
-
struct ieee80211_txq {
void* drv_priv;
};
@@ -165,6 +219,28 @@
uint8_t dummy;
};
+/**
+ * struct ieee80211_key_conf - HW key configuration data
+ * @tx_pn - TX packet number, in host byte order
+ * @rx_seq - RX sequence number, in host byte order
+ */
+struct ieee80211_key_conf {
+ atomic64_t tx_pn;
+ uint64_t rx_seq;
+ uint32_t cipher;
+ uint8_t hw_key_idx;
+ uint8_t keyidx;
+ uint8_t key_type;
+ size_t keylen;
+ uint8_t key[0];
+};
+
+struct ieee80211_tx_info {
+ struct {
+ struct ieee80211_key_conf* hw_key;
+ } control;
+};
+
// Struct for transferring an IEEE 802.11 MAC-framed packet around the driver.
struct ieee80211_mac_packet {
// The common portion of the MAC header.
@@ -185,6 +261,9 @@
// MAC frame body size.
size_t body_size;
+
+ // Control information for this packet.
+ struct ieee80211_tx_info info;
};
// Flags for the ieee80211_rx_status.flag
diff --git a/third_party/iwlwifi/platform/irq.cc b/third_party/iwlwifi/platform/irq.cc
index eba421e..236df2f 100644
--- a/third_party/iwlwifi/platform/irq.cc
+++ b/third_party/iwlwifi/platform/irq.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "irq.h"
+#include "third_party/iwlwifi/platform/irq.h"
#include <lib/async/dispatcher.h>
#include <memory>
-#include "task-internal.h"
+#include "third_party/iwlwifi/platform/task-internal.h"
// Internally, the IRQ timers are just tasks, dispatched on the IRQ dispatcher.
struct iwl_irq_timer : public wlan::iwlwifi::TaskInternal {
diff --git a/third_party/iwlwifi/platform/kernel.h b/third_party/iwlwifi/platform/kernel.h
index 70a8bf0..f869368 100644
--- a/third_party/iwlwifi/platform/kernel.h
+++ b/third_party/iwlwifi/platform/kernel.h
@@ -9,6 +9,8 @@
// routines that are typically provided by the Linux kernel API.
#include <fuchsia/hardware/pci/c/banjo.h>
+#include <fuchsia/hardware/wlan/phyinfo/c/banjo.h>
+#include <fuchsia/wlan/common/c/banjo.h>
#include <limits.h>
#include <netinet/if_ether.h>
#include <stdint.h>
@@ -17,8 +19,6 @@
#include <zircon/assert.h>
#include <zircon/listnode.h>
-#include <fuchsia/hardware/wlanphyinfo/c/banjo.h>
-
#if defined(__cplusplus)
extern "C" {
#endif // defined(__cplusplus)
@@ -35,21 +35,9 @@
#define iwl_assert_lock_held(x) ZX_DEBUG_ASSERT(mtx_trylock(x) == thrd_busy)
-// NEEDS_TYPES: need protection while accessing the variable.
-#define rcu_dereference(p) (p)
-#define rcu_dereference_protected(p, c) (p)
-
// NEEDS_TYPES: how to guarantee this?
#define READ_ONCE(x) (x)
-// NEEDS_TYPES: implement this
-#define rcu_read_lock() \
- do { \
- } while (0);
-#define rcu_read_unlock() \
- do { \
- } while (0);
-
#define DMA_BIT_MASK(n) (((n) >= 64) ? ~0ULL : ((1ULL << (n)) - 1))
// Converts a WiFi time unit (1024 us) to zx_duration_t.
@@ -62,6 +50,7 @@
struct zx_device;
struct async_dispatcher;
struct driver_inspector;
+struct rcu_manager;
// This struct is analogous to the Linux device struct, and contains all the Fuchsia-specific data
// fields relevant to generic device functionality.
@@ -83,6 +72,9 @@
// we will maintain a dedicated IRQ dispatcher here.
struct async_dispatcher* irq_dispatcher;
+ // The RCU manager instance used to manage RCU-based synchronization.
+ struct rcu_manager* rcu_manager;
+
// The inspector used to publish the component inspection tree from the driver.
struct driver_inspector* inspector;
};
@@ -160,7 +152,7 @@
};
struct wireless_dev {
- wlan_info_mac_role_t iftype;
+ wlan_mac_role_t iftype;
};
////
diff --git a/third_party/iwlwifi/platform/memory.cc b/third_party/iwlwifi/platform/memory.cc
index 3bb4d73..49840e8 100644
--- a/third_party/iwlwifi/platform/memory.cc
+++ b/third_party/iwlwifi/platform/memory.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "memory.h"
+#include "third_party/iwlwifi/platform/memory.h"
#include <lib/ddk/io-buffer.h>
diff --git a/third_party/iwlwifi/platform/memory.h b/third_party/iwlwifi/platform/memory.h
index 08ec6aa..3a9ee97 100644
--- a/third_party/iwlwifi/platform/memory.h
+++ b/third_party/iwlwifi/platform/memory.h
@@ -10,7 +10,7 @@
#include <stdint.h>
#include <zircon/types.h>
-#include "kernel.h"
+#include "third_party/iwlwifi/platform/kernel.h"
#if defined(__cplusplus)
extern "C" {
diff --git a/third_party/iwlwifi/platform/module.cc b/third_party/iwlwifi/platform/module.cc
index aca91a7..9171fc2 100644
--- a/third_party/iwlwifi/platform/module.cc
+++ b/third_party/iwlwifi/platform/module.cc
@@ -2,13 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// TODO(rsakthi) - how to get this from bazel?
-#define CPTCFG_IWLMVM 1
-
-#include "module.h"
+#include "third_party/iwlwifi/platform/module.h"
#include <lib/ddk/driver.h>
-#include <lib/sync/completion.h>
#include <stdarg.h>
#include <stdio.h>
#include <zircon/process.h>
@@ -18,7 +14,7 @@
#include <string>
-#include "device.h"
+#include "third_party/iwlwifi/platform/device.h"
static const size_t kModuleNameMax = 256;
diff --git a/third_party/iwlwifi/platform/mvm-mlme.cc b/third_party/iwlwifi/platform/mvm-mlme.cc
index 8a102e5..b795cab 100644
--- a/third_party/iwlwifi/platform/mvm-mlme.cc
+++ b/third_party/iwlwifi/platform/mvm-mlme.cc
@@ -46,11 +46,10 @@
// + Now, both sides of channel (SME and MLME) can talk now.
//
-#include "mvm-mlme.h"
+#include "third_party/iwlwifi/platform/mvm-mlme.h"
-//#include <fidl/fuchsia.wlan.ieee80211/cpp/wire.h>
-#include <fuchsia/hardware/wlan/mac/c/banjo.h>
-#include <fuchsia/wlan/ieee80211/c/banjo.h>
+#include <fidl/fuchsia.wlan.ieee80211/cpp/wire.h>
+#include <fuchsia/hardware/wlan/softmac/c/banjo.h>
#include <fuchsia/wlan/internal/c/banjo.h>
#include <lib/ddk/device.h>
#include <lib/ddk/driver.h>
@@ -59,23 +58,20 @@
#include <zircon/status.h>
#include <algorithm>
+#include <iterator>
-#include "ieee80211_include.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
extern "C" {
#include "third_party/iwlwifi/iwl-debug.h"
#include "third_party/iwlwifi/mvm/mvm.h"
+#include "third_party/iwlwifi/mvm/sta.h"
#include "third_party/iwlwifi/mvm/time-event.h"
} // extern "C"
-#include "ieee80211.h"
-
-namespace {
-
-// IEEE 802.11-2016 3.2 (c.f. "vendor organizationally unique identifier")
-constexpr uint8_t kIeeeOui[] = {0x00, 0x0F, 0xAC};
-
-} // namespace
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
+#include "third_party/iwlwifi/platform/rcu.h"
+#include "third_party/iwlwifi/platform/scoped_utils.h"
//////////////////////////////////// Helper Functions ////////////////////////////////////////////
@@ -91,10 +87,10 @@
size_t bands_count = 0;
if (nvm_data->sku_cap_band_24ghz_enable) {
- bands[bands_count++] = WLAN_INFO_BAND_2GHZ;
+ bands[bands_count++] = WLAN_INFO_BAND_TWO_GHZ;
}
if (nvm_data->sku_cap_band_52ghz_enable) {
- bands[bands_count++] = WLAN_INFO_BAND_5GHZ;
+ bands[bands_count++] = WLAN_INFO_BAND_FIVE_GHZ;
}
ZX_ASSERT(bands_count <= WLAN_INFO_BAND_COUNT);
@@ -109,7 +105,7 @@
//
void fill_band_infos(const struct iwl_nvm_data* nvm_data, const wlan_info_band_t* bands,
size_t bands_count, wlan_info_band_info_t* band_infos) {
- ZX_ASSERT(bands_count <= ARRAY_SIZE(nvm_data->bands));
+ ZX_ASSERT(bands_count <= std::size(nvm_data->bands));
for (size_t band_idx = 0; band_idx < bands_count; ++band_idx) {
wlan_info_band_t band_id = bands[band_idx];
@@ -117,16 +113,16 @@
wlan_info_band_info_t* band_info = &band_infos[band_idx]; // destination
band_info->band = band_id;
- band_info->ht_supported = nvm_data->sku_cap_11n_enable;
- // TODO(43517): Better handling of driver features bits/flags
- band_info->ht_caps.ht_capability_info =
- IEEE80211_HT_CAPS_CHAN_WIDTH | IEEE80211_HT_CAPS_SMPS_DYNAMIC;
- band_info->ht_caps.ampdu_params = (3 << IEEE80211_AMPDU_RX_LEN_SHIFT) | // (64K - 1) bytes
- (6 << IEEE80211_AMPDU_DENSITY_SHIFT); // 8 us
- // TODO(36683): band_info->ht_caps->supported_mcs_set =
+ band_info->ht_supported = sband->ht_cap.ht_supported;
+ band_info->ht_caps.ht_capability_info = sband->ht_cap.cap;
+ band_info->ht_caps.ampdu_params =
+ (sband->ht_cap.ampdu_factor << IEEE80211_AMPDU_RX_LEN_SHIFT) | // (64K - 1) bytes
+ (sband->ht_cap.ampdu_density << IEEE80211_AMPDU_DENSITY_SHIFT); // 8 us
+ memcpy(&band_info->ht_caps.supported_mcs_set, &sband->ht_cap.mcs,
+ sizeof(struct ieee80211_mcs_info));
// TODO(36684): band_info->vht_caps =
- ZX_ASSERT(sband->n_bitrates <= (int)ARRAY_SIZE(band_info->rates));
+ ZX_ASSERT(sband->n_bitrates <= static_cast<int>(std::size(band_info->rates)));
for (int rate_idx = 0; rate_idx < sband->n_bitrates; ++rate_idx) {
band_info->rates[rate_idx] = cfg_rates_to_80211(sband->bitrates[rate_idx]);
}
@@ -134,62 +130,26 @@
// Fill the channel list of this band.
wlan_info_channel_list_t* ch_list = &band_info->supported_channels;
switch (band_info->band) {
- case WLAN_INFO_BAND_2GHZ:
+ case WLAN_INFO_BAND_TWO_GHZ:
ch_list->base_freq = 2407;
break;
- case WLAN_INFO_BAND_5GHZ:
+ case WLAN_INFO_BAND_FIVE_GHZ:
ch_list->base_freq = 5000;
break;
default:
ZX_ASSERT(0); // Unknown band ID.
break;
}
- ZX_ASSERT(sband->n_channels <= (int)ARRAY_SIZE(ch_list->channels));
+ ZX_ASSERT(sband->n_channels <= static_cast<int>(std::size(ch_list->channels)));
for (int ch_idx = 0; ch_idx < sband->n_channels; ++ch_idx) {
ch_list->channels[ch_idx] = sband->channels[ch_idx].ch_num;
}
}
}
-static struct iwl_mvm_sta* alloc_ap_mvm_sta(const uint8_t bssid[]) {
- auto mvm_sta = reinterpret_cast<struct iwl_mvm_sta*>(calloc(1, sizeof(struct iwl_mvm_sta)));
- if (!mvm_sta) {
- return NULL;
- }
-
- for (size_t i = 0; i < ARRAY_SIZE(mvm_sta->txq); i++) {
- mvm_sta->txq[i] = reinterpret_cast<struct iwl_mvm_txq*>(calloc(1, sizeof(struct iwl_mvm_txq)));
- }
- memcpy(mvm_sta->addr, bssid, ETH_ALEN);
- mtx_init(&mvm_sta->lock, mtx_plain);
-
- return mvm_sta;
-}
-
-static void free_ap_mvm_sta(struct iwl_mvm_sta* mvm_sta) {
- if (!mvm_sta) {
- return;
- }
-
- for (size_t i = 0; i < ARRAY_SIZE(mvm_sta->txq); i++) {
- free(mvm_sta->txq[i]);
- }
- if (mvm_sta->key_conf) {
- free(mvm_sta->key_conf);
- }
- free(mvm_sta);
-}
-
-static void reset_sta_mapping(struct iwl_mvm_vif* mvmvif) {
- if (mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
- mvmvif->mvm->fw_id_to_mac_id[mvmvif->ap_sta_id] = NULL;
- mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
- }
-}
-
///////////////////////////////////// MAC //////////////////////////////////////////////
-zx_status_t mac_query(void* ctx, uint32_t options, wlanmac_info_t* info) {
+zx_status_t mac_query(void* ctx, uint32_t options, wlan_softmac_info_t* info) {
const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
if (!ctx || !info) {
@@ -204,9 +164,9 @@
memcpy(info->sta_addr, nvm_data->hw_addr, sizeof(info->sta_addr));
info->mac_role = mvmvif->mac_role;
// TODO(43517): Better handling of driver features bits/flags
- info->driver_features = WLAN_INFO_DRIVER_FEATURE_SCAN_OFFLOAD;
- info->supported_phys = WLAN_INFO_PHY_TYPE_DSSS | WLAN_INFO_PHY_TYPE_CCK |
- WLAN_INFO_PHY_TYPE_OFDM | WLAN_INFO_PHY_TYPE_HT;
+ info->driver_features = WLAN_INFO_DRIVER_FEATURE_SCAN_OFFLOAD | WLAN_INFO_DRIVER_FEATURE_MFP;
+ info->supported_phys = WLAN_INFO_PHY_TYPE_DSSS | WLAN_INFO_PHY_TYPE_HR | WLAN_INFO_PHY_TYPE_OFDM |
+ WLAN_INFO_PHY_TYPE_HT;
info->caps = WLAN_INFO_HARDWARE_CAPABILITY_SHORT_PREAMBLE |
WLAN_INFO_HARDWARE_CAPABILITY_SPECTRUM_MGMT |
WLAN_INFO_HARDWARE_CAPABILITY_SHORT_SLOT_TIME;
@@ -220,7 +180,8 @@
return ZX_OK;
}
-zx_status_t mac_start(void* ctx, const wlanmac_ifc_protocol_t* ifc, zx_handle_t* out_mlme_channel) {
+zx_status_t mac_start(void* ctx, const wlan_softmac_ifc_protocol_t* ifc,
+ zx_handle_t* out_mlme_channel) {
const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
if (!ctx || !ifc || !out_mlme_channel) {
@@ -252,39 +213,14 @@
return ret;
}
-void mac_stop(void* ctx) {
- const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
- zx_status_t ret;
-
- // Change the sta state linking to the AP.
- if (mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
- struct iwl_mvm_sta* mvm_sta = mvmvif->mvm->fw_id_to_mac_id[mvmvif->ap_sta_id];
- if (!mvm_sta) {
- IWL_ERR(mvmvif, "sta info is not set before stop.\n");
- } else {
- ret = iwl_mvm_mac_sta_state(mvmvif, mvm_sta, IWL_STA_NONE, IWL_STA_NOTEXIST);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "Cannot set station state to NOT EXIST: %s\n", zx_status_get_string(ret));
- }
- }
- }
+void mac_stop(struct iwl_mvm_vif* mvmvif) {
+ zx_status_t ret = ZX_OK;
if (mvmvif->phy_ctxt) {
ret = iwl_mvm_remove_chanctx(mvmvif->mvm, mvmvif->phy_ctxt->id);
if (ret != ZX_OK) {
IWL_WARN(mvmvif, "Cannot remove chanctx: %s\n", zx_status_get_string(ret));
}
- } else {
- IWL_WARN(mvmvif, "PHY context is NULL in %s()\n", __func__);
- }
-
- // Clean up other sta info.
- for (size_t i = 0; i < ARRAY_SIZE(mvmvif->mvm->fw_id_to_mac_id); i++) {
- struct iwl_mvm_sta* mvm_sta = mvmvif->mvm->fw_id_to_mac_id[i];
- if (mvm_sta) {
- free_ap_mvm_sta(mvm_sta);
- mvmvif->mvm->fw_id_to_mac_id[i] = NULL;
- }
}
ret = iwl_mvm_mac_remove_interface(mvmvif);
@@ -293,35 +229,6 @@
}
}
-zx_status_t mac_queue_tx(void* ctx, uint32_t options, const wlan_tx_packet_t* tx_packet) {
- const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
-
- if (tx_packet->mac_frame_size > WLAN_MSDU_MAX_LEN) {
- IWL_ERR(mvmvif, "Frame size is to large (%lu). expect less than %lu.\n",
- tx_packet->mac_frame_size, WLAN_MSDU_MAX_LEN);
- return ZX_ERR_INVALID_ARGS;
- }
-
- ieee80211_mac_packet packet = {};
- packet.common_header =
- reinterpret_cast<const ieee80211_frame_header*>(tx_packet->mac_frame_buffer);
- packet.header_size = ieee80211_get_header_len(packet.common_header);
- if (packet.header_size > tx_packet->mac_frame_size) {
- IWL_ERR(mvmvif, "TX packet header size %zu too large for data size %zu\n", packet.header_size,
- tx_packet->mac_frame_size);
- return ZX_ERR_INVALID_ARGS;
- }
-
- packet.body = tx_packet->mac_frame_buffer + packet.header_size;
- packet.body_size = tx_packet->mac_frame_size - packet.header_size;
-
- mtx_lock(&mvmvif->mvm->mutex);
- zx_status_t ret = iwl_mvm_mac_tx(mvmvif, &packet);
- mtx_unlock(&mvmvif->mvm->mutex);
-
- return ret;
-}
-
// This function will ensure the mvmvif->phy_ctxt is valid (either get a free one from pool
// or use the assigned one).
//
@@ -340,12 +247,39 @@
return ZX_OK;
}
-static zx_status_t mac_unconfigure_bss(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvm_sta);
+static zx_status_t remove_chanctx(struct iwl_mvm_vif* mvmvif) {
+ zx_status_t ret;
+
+ // mvmvif->phy_ctxt will be cleared up in iwl_mvm_unassign_vif_chanctx(). So back up the phy
+ // context ID and the chandef pointer for later use.
+ auto phy_ctxt_id = mvmvif->phy_ctxt->id;
+ auto chandef = &mvmvif->phy_ctxt->chandef;
+
+ // Unbinding MAC and PHY contexts.
+ ret = iwl_mvm_unassign_vif_chanctx(mvmvif);
+ if (ret != ZX_OK) {
+ IWL_ERR(mvmvif, "cannot unassign VIF channel context: %s\n", zx_status_get_string(ret));
+ goto out;
+ }
+
+ ret = iwl_mvm_remove_chanctx(mvmvif->mvm, phy_ctxt_id);
+ if (ret != ZX_OK) {
+ IWL_ERR(mvmvif, "Cannot remove channel context: %s\n", zx_status_get_string(ret));
+ goto out;
+ }
+
+ // Clear the chandef in mvm->phy_ctxts[] (was pointed by mvmvif->phy_ctxt->chandef) to indicate
+ // this phy_ctxt is unused.
+ memset(chandef, 0, sizeof(*chandef));
+
+out:
+ return ret;
+}
// This is called right after SSID scan. The MLME tells this function the channel to tune in.
// This function configures the PHY context and binds the MAC to that PHY context.
-zx_status_t mac_set_channel(void* ctx, uint32_t options, const wlan_channel_t* channel) {
- const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
+zx_status_t mac_set_channel(struct iwl_mvm_vif* mvmvif, uint32_t options,
+ const wlan_channel_t* channel) {
zx_status_t ret;
IWL_INFO(mvmvif, "mac_set_channel(primary:%d, bandwidth:'%s', secondary:%d)\n", channel->primary,
@@ -358,31 +292,14 @@
: "unknown",
channel->secondary80);
- if (mvmvif->phy_ctxt && mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
- // We already have PHY context set. It probably was left from the last association attempt
- // (which was rejected by the AP). Remove it first.
- IWL_INFO(mvmvif, "We already have PHY context set (ap_sta_id=%d). Removing it.\n",
- mvmvif->ap_sta_id);
-
- // In the normal case, the time event is added in the mac_configure_bss() and removed in the
- // mac_configure_assoc(). So in the abnormal cases (assoc failed), we need to remove it before
- // configure_bss().
- mtx_lock(&mvmvif->mvm->mutex);
- ret = iwl_mvm_remove_time_event(mvmvif, &mvmvif->time_event_data);
- mtx_unlock(&mvmvif->mvm->mutex);
+ if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->chandef.primary != 0) {
+ // The PHY context is set (the RF is on a particular channel). Remove it first. Below code
+ // will allocate a new one.
+ ret = remove_chanctx(mvmvif);
if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot remove time event: %s\n", zx_status_get_string(ret));
+ IWL_ERR(mvmvif, "Cannot reset PHY context: %s\n", zx_status_get_string(ret));
return ret;
}
-
- auto mvm_sta = mvmvif->mvm->fw_id_to_mac_id[mvmvif->ap_sta_id];
- if (mvm_sta) {
- ret = mac_unconfigure_bss(mvmvif, mvm_sta);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "Cannot unconfigure bss: %s\n", zx_status_get_string(ret));
- return ret;
- }
- }
}
// Before we do anything, ensure the PHY context had been assigned to the mvmvif.
@@ -411,8 +328,8 @@
}
// This is called after mac_set_channel(). The MAC (mvmvif) will be configured as a CLIENT role.
-zx_status_t mac_configure_bss(void* ctx, uint32_t options, const bss_config_t* config) {
- const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
+zx_status_t mac_configure_bss(struct iwl_mvm_vif* mvmvif, uint32_t options,
+ const bss_config_t* config) {
zx_status_t ret = ZX_OK;
IWL_INFO(mvmvif, "mac_configure_bss(bssid=%02x:%02x:%02x:%02x:%02x:%02x, type=%d, remote=%d)\n",
@@ -424,61 +341,45 @@
return ZX_ERR_INVALID_ARGS;
}
- if (mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) {
- IWL_ERR(mvmvif, "The AP sta ID has been set already. ap_sta_id=%d\n", mvmvif->ap_sta_id);
- return ZX_ERR_ALREADY_EXISTS;
- }
- // Note that 'ap_sta_id' is unset and later will be set in iwl_mvm_add_sta().
+ {
+ // Copy the BSSID info.
+ auto lock = std::lock_guard(mvmvif->mvm->mutex);
+ memcpy(mvmvif->bss_conf.bssid, config->bssid, ETH_ALEN);
+ memcpy(mvmvif->bssid, config->bssid, ETH_ALEN);
- // Copy the BSSID info.
- mtx_lock(&mvmvif->mvm->mutex);
- memcpy(mvmvif->bss_conf.bssid, config->bssid, ETH_ALEN);
- memcpy(mvmvif->bssid, config->bssid, ETH_ALEN);
-
- // Simulates the behavior of iwl_mvm_bss_info_changed_station().
- ret = iwl_mvm_mac_ctxt_changed(mvmvif, false, mvmvif->bssid);
- mtx_unlock(&mvmvif->mvm->mutex);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot set BSSID: %s\n", zx_status_get_string(ret));
- return ret;
- }
-
- // Add AP into the STA table in the firmware.
- struct iwl_mvm_sta* mvm_sta = alloc_ap_mvm_sta(config->bssid);
- if (!mvm_sta) {
- IWL_ERR(mvmvif, "cannot allocate MVM STA for AP.\n");
- return ZX_ERR_NO_RESOURCES;
- }
-
- // mvm_sta ownership will be transfered to mvm->fw_id_to_mac_id[] in iwl_mvm_add_sta(). It will be
- // freed at mac_clear_assoc().
- // Below is to how the iwl_mvm_mac_sta_state() is called.
- ret = iwl_mvm_mac_sta_state(mvmvif, mvm_sta, IWL_STA_NOTEXIST, IWL_STA_NONE);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot set MVM STA state: %s\n", zx_status_get_string(ret));
- goto exit;
+ // Simulates the behavior of iwl_mvm_bss_info_changed_station().
+ ret = iwl_mvm_mac_ctxt_changed(mvmvif, false, mvmvif->bssid);
+ if (ret != ZX_OK) {
+ IWL_ERR(mvmvif, "cannot set BSSID: %s\n", zx_status_get_string(ret));
+ return ret;
+ }
}
// Ask the firmware to pay attention for beacon.
// Note that this would add TIME_EVENT as well.
iwl_mvm_mac_mgd_prepare_tx(mvmvif->mvm, mvmvif, IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS);
- // Allocate a Tx queue for this station.
- mtx_lock(&mvmvif->mvm->mutex);
- ret = iwl_mvm_sta_alloc_queue(mvmvif->mvm, mvm_sta, IEEE80211_AC_BE, IWL_MAX_TID_COUNT);
- mtx_unlock(&mvmvif->mvm->mutex);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot allocate queue for STA: %s\n", zx_status_get_string(ret));
- goto exit;
+ return ZX_OK;
+}
+
+// This function is to revert what mac_configure_bss() does.
+zx_status_t mac_unconfigure_bss(struct iwl_mvm_vif* mvmvif) {
+ zx_status_t ret = ZX_OK;
+
+ {
+ // To simulate the behavior that iwl_mvm_bss_info_changed_station() would do for disassocitaion.
+ auto lock = std::lock_guard(mvmvif->mvm->mutex);
+ memset(mvmvif->bss_conf.bssid, 0, ETH_ALEN);
+ memset(mvmvif->bssid, 0, ETH_ALEN);
+ // This will take the cleared BSSID from bss_conf and update the firmware.
+ ret = iwl_mvm_mac_ctxt_changed(mvmvif, false, NULL);
+ if (ret != ZX_OK) {
+ IWL_ERR(mvm, "failed to update MAC (clear after unassoc)\n");
+ return ret;
+ }
}
-exit:
- // If it is successful, the ownership has been transferred. If not, free the resource.
- if (ret != ZX_OK) {
- free_ap_mvm_sta(mvm_sta);
- reset_sta_mapping(mvmvif);
- }
- return ret;
+ return ZX_OK;
}
zx_status_t mac_enable_beaconing(void* ctx, uint32_t options, const wlan_bcn_config_t* bcn_cfg) {
@@ -486,259 +387,127 @@
return ZX_ERR_NOT_SUPPORTED;
}
-zx_status_t mac_configure_beacon(void* ctx, uint32_t options, const wlan_tx_packet_t* pkt) {
+zx_status_t mac_configure_beacon(void* ctx, uint32_t options,
+ const wlan_tx_packet_t* packet_template) {
IWL_ERR(ctx, "%s() needs porting ... see fxbug.dev/36742\n", __func__);
return ZX_ERR_NOT_SUPPORTED;
}
-zx_status_t mac_set_key(void* ctx, uint32_t options, const wlan_key_config_t* key_config) {
- zx_status_t status = ZX_OK;
- const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
- iwl_mvm* mvm = mvmvif->mvm;
-
- if (mvm->trans->cfg->gen2 || iwl_mvm_has_new_tx_api(mvm)) {
- // The new firmwares (for starting with the 22000 series) have different packet generation
- // requirements than mentioned below.
- return ZX_ERR_NOT_SUPPORTED;
- }
-
- if (!std::equal(key_config->cipher_oui,
- key_config->cipher_oui + std::size(key_config->cipher_oui), kIeeeOui,
- kIeeeOui + std::size(kIeeeOui))) {
- // IEEE 802.11-2016 9.4.2.25.2
- // The standard ciphers all live in the IEEE space.
- return ZX_ERR_NOT_SUPPORTED;
- }
-
- switch (key_config->cipher_type) {
- case CIPHER_SUITE_TYPE_CCMP_128:
- // Note: the Linux iwlwifi driver requests IEEE80211_KEY_FLAG_PUT_IV_SPACE from the mac80211
- // stack. We will apply equivalent functionality manually to Incoming packets from Fuchsia.
- break;
- default:
- // Additional porting required for other types.
- return ZX_ERR_NOT_SUPPORTED;
- }
-
- auto key_conf = reinterpret_cast<iwl_mvm_sta_key_conf*>(
- malloc(sizeof(iwl_mvm_sta_key_conf) + key_config->key_len));
- memset(key_conf, 0, sizeof(*key_conf) + key_config->key_len);
- key_conf->cipher_type = key_config->cipher_type;
- key_conf->key_type = key_config->key_type;
- key_conf->keyidx = key_config->key_idx;
- key_conf->keylen = key_config->key_len;
- key_conf->rx_seq = key_config->rsc;
- memcpy(key_conf->key, key_config->key, key_conf->keylen);
-
- struct iwl_mvm_sta* mvm_sta = mvmvif->mvm->fw_id_to_mac_id[mvmvif->ap_sta_id];
- if ((status = iwl_mvm_mac_set_key(mvmvif, mvm_sta, key_conf)) != ZX_OK) {
- free(key_conf);
- IWL_ERR(mvmvif, "iwl_mvm_mac_set_key() failed: %s\n", zx_status_get_string(status));
- return status;
- }
-
- if (key_conf->key_type == WLAN_KEY_TYPE_PAIRWISE) {
- // Save the pairwise key, for use in the TX path. Group keys are receive-only and do not need
- // to be saved.
- free(mvm_sta->key_conf);
- mvm_sta->key_conf = key_conf;
- } else {
- free(key_conf);
- }
-
- return ZX_OK;
-}
-
// Set the association result to the firmware.
//
// The current mac context is set by mac_configure_bss() with default values.
-// TODO(fxbug.dev/36683): supports HT (802.11n)
// TODO(fxbug.dev/36684): supports VHT (802.11ac)
//
-zx_status_t mac_configure_assoc(void* ctx, uint32_t options, const wlan_assoc_ctx_t* assoc_ctx) {
- const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
+zx_status_t mac_configure_assoc(struct iwl_mvm_vif* mvmvif, uint32_t options,
+ const wlan_assoc_ctx_t* assoc_ctx) {
zx_status_t ret = ZX_OK;
-
IWL_INFO(ctx, "Associating ...\n");
+ // TODO(fxbug.dev/86715): this RCU-unprotected access is safe as deletions from the map are
+ // RCU-synchronized from API calls to mac_stop() in this same thread.
struct iwl_mvm_sta* mvm_sta = mvmvif->mvm->fw_id_to_mac_id[mvmvif->ap_sta_id];
if (!mvm_sta) {
IWL_ERR(mvmvif, "sta info is not set before association.\n");
ret = ZX_ERR_BAD_STATE;
- goto out;
+ return ret;
+ }
+
+ // Save band info into interface struct for future usage.
+ mvmvif->phy_ctxt->band = iwl_mvm_get_channel_band(assoc_ctx->channel.primary);
+
+ mvm_sta->bw = assoc_ctx->channel.cbw;
+ // Record the intersection of AP and station supported rate to mvm_sta.
+ ZX_ASSERT(assoc_ctx->rates_cnt <= sizeof(mvm_sta->supp_rates));
+ memcpy(mvm_sta->supp_rates, assoc_ctx->rates, assoc_ctx->rates_cnt);
+
+ // Copy HT related fields from wlan_assoc_ctx_t.
+ mvm_sta->support_ht = assoc_ctx->has_ht_cap;
+ if (assoc_ctx->has_ht_cap) {
+ memcpy(&mvm_sta->ht_cap, &assoc_ctx->ht_cap, sizeof(struct ieee80211_ht_capabilities));
}
// Change the station states step by step.
-
ret = iwl_mvm_mac_sta_state(mvmvif, mvm_sta, IWL_STA_NONE, IWL_STA_AUTH);
if (ret != ZX_OK) {
IWL_ERR(mvmvif, "cannot set state from NONE to AUTH: %s\n", zx_status_get_string(ret));
- goto out;
+ return ret;
}
ret = iwl_mvm_mac_sta_state(mvmvif, mvm_sta, IWL_STA_AUTH, IWL_STA_ASSOC);
if (ret != ZX_OK) {
IWL_ERR(mvmvif, "cannot set state from AUTH to ASSOC: %s\n", zx_status_get_string(ret));
- goto out;
+ return ret;
}
ret = iwl_mvm_mac_sta_state(mvmvif, mvm_sta, IWL_STA_ASSOC, IWL_STA_AUTHORIZED);
if (ret != ZX_OK) {
IWL_ERR(mvmvif, "cannot set state from ASSOC to AUTHORIZED: %s\n", zx_status_get_string(ret));
- goto out;
+ return ret;
}
// Tell firmware to pass multicast packets to driver.
iwl_mvm_configure_filter(mvmvif->mvm);
- mtx_lock(&mvmvif->mvm->mutex);
+ {
+ auto lock = std::lock_guard(mvmvif->mvm->mutex);
- // Update the MAC context in the firmware.
- mvmvif->bss_conf.assoc = true;
- mvmvif->bss_conf.listen_interval = assoc_ctx->listen_interval;
- ret = iwl_mvm_mac_ctxt_changed(mvmvif, false, NULL);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot update MAC context in the firmware: %s\n", zx_status_get_string(ret));
- goto unlock;
+ // Update the MAC context in the firmware.
+ mvmvif->bss_conf.assoc = true;
+ mvmvif->bss_conf.listen_interval = assoc_ctx->listen_interval;
+ ret = iwl_mvm_mac_ctxt_changed(mvmvif, false, NULL);
+ if (ret != ZX_OK) {
+ IWL_ERR(mvmvif, "cannot update MAC context in the firmware: %s\n", zx_status_get_string(ret));
+ return ret;
+ }
+
+ ret = iwl_mvm_remove_time_event(mvmvif, &mvmvif->time_event_data);
+ if (ret != ZX_OK) {
+ IWL_ERR(mvmvif, "cannot remove time event: %s\n", zx_status_get_string(ret));
+ return ret;
+ }
}
- ret = iwl_mvm_remove_time_event(mvmvif, &mvmvif->time_event_data);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot remove time event: %s\n", zx_status_get_string(ret));
- goto unlock;
- }
+ // Tell firmware to pass multicast packets to driver.
+ iwl_mvm_configure_filter(mvmvif->mvm);
// TODO(43218): support multiple interfaces. Need to port iwl_mvm_update_quotas() in mvm/quota.c.
// TODO(56093): support low latency in struct iwl_time_quota_data.
-
-unlock:
- mtx_unlock(&mvmvif->mvm->mutex);
-out:
- return ret;
+ return ZX_OK;
}
-zx_status_t mac_clear_assoc(void* ctx, uint32_t options,
- const uint8_t peer_addr[fuchsia_wlan_ieee80211_MAC_ADDR_LEN]) {
+zx_status_t mac_clear_assoc(struct iwl_mvm_vif* mvmvif, uint32_t options,
+ const uint8_t peer_addr[fuchsia_wlan_ieee80211::wire::kMacAddrLen]) {
IWL_INFO(ctx, "Disassociating ...\n");
- const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
zx_status_t ret = ZX_OK;
- if (mvmvif->ap_sta_id == IWL_MVM_INVALID_STA) {
- IWL_ERR(mvmif, "sta id has not been set yet");
- return ZX_ERR_BAD_STATE;
- }
- // iwl_mvm_rm_sta() will reset the ap_sta_id value so that we have to keep it.
- uint8_t ap_sta_id = mvmvif->ap_sta_id;
-
- struct iwl_mvm_sta* mvm_sta = mvmvif->mvm->fw_id_to_mac_id[ap_sta_id];
- if (!mvm_sta) {
- IWL_ERR(mvmvif, "sta info is not set before disassociation.\n");
- return ZX_ERR_BAD_STATE;
+ {
+ auto lock = std::lock_guard(mvmvif->mvm->mutex);
+ // Remove Time event (in case assoc failed)
+ ret = iwl_mvm_remove_time_event(mvmvif, &mvmvif->time_event_data);
+ if (ret != ZX_OK) {
+ IWL_ERR(mvmvif, "cannot remove time event: %s\n", zx_status_get_string(ret));
+ }
}
- // Mark the station is no longer associated. This must be set before iwl_mvm_mac_sta_state().
- mvmvif->bss_conf.assoc = false;
-
- // Below are to simulate the behavior of iwl_mvm_bss_info_changed_station().
- ret = iwl_mvm_mac_sta_state(mvmvif, mvm_sta, IWL_STA_AUTHORIZED, IWL_STA_ASSOC);
+ ret = mac_unconfigure_bss(mvmvif);
if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot set state from AUTHORIZED to ASSOC: %s\n", zx_status_get_string(ret));
- goto out;
- }
- ret = iwl_mvm_mac_sta_state(mvmvif, mvm_sta, IWL_STA_ASSOC, IWL_STA_AUTH);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot set state from ASSOC to AUTH: %s\n", zx_status_get_string(ret));
- goto out;
- }
- ret = iwl_mvm_mac_sta_state(mvmvif, mvm_sta, IWL_STA_AUTH, IWL_STA_NONE);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot set state from AUTH to NONE: %s\n", zx_status_get_string(ret));
- goto out;
+ return ret;
}
- // Tell firmware to flush all packets in the Tx queue. This must be done before we remove the STA
- // (in the NONE->NOTEXIST transition).
- // TODO(79799): understand why we need this.
- mtx_lock(&mvmvif->mvm->mutex);
- // Remove Time event (in case assoc failed)
- ret = iwl_mvm_remove_time_event(mvmvif, &mvmvif->time_event_data);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot remove time event: %s\n", zx_status_get_string(ret));
- }
- iwl_mvm_flush_sta(mvmvif->mvm, mvm_sta, false, 0);
-
- // Update the MAC context in the firmware.
- mvmvif->bss_conf.assoc = false;
- ret = iwl_mvm_mac_ctxt_changed(mvmvif, false, NULL);
- mtx_unlock(&mvmvif->mvm->mutex);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot update MAC context in the firmware: %s\n", zx_status_get_string(ret));
- goto out;
- }
-
- ret = mac_unconfigure_bss(mvmvif, mvm_sta);
-
-out:
- return ret;
+ return remove_chanctx(mvmvif);
}
-// This function is to revert what mac_configure_bss() does.
-zx_status_t mac_unconfigure_bss(struct iwl_mvm_vif* mvmvif, struct iwl_mvm_sta* mvm_sta) {
- // mvmvif->phy_ctxt will be cleared up in iwl_mvm_unassign_vif_chanctx(). So backup the phy
- // context ID for removing.
- auto phy_ctxt_id = mvmvif->phy_ctxt->id;
-
- // The 'ap_sta_id' will be reset in iwl_mvm_rm_sta() (via NONE --> NOTEXIST), back it up.
- auto ap_sta_id = mvmvif->ap_sta_id;
-
- // REMOVE_STA will be issued to remove the station entry in the firmware.
- zx_status_t ret = iwl_mvm_mac_sta_state(mvmvif, mvm_sta, IWL_STA_NONE, IWL_STA_NOTEXIST);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot set state from NONE to NOTEXIST: %s\n", zx_status_get_string(ret));
- goto out;
- }
-
- // To simulate the behavior that iwl_mvm_bss_info_changed_station() would do for disassocitaion.
- mtx_lock(&mvmvif->mvm->mutex);
- memset(mvmvif->bss_conf.bssid, 0, ETH_ALEN);
- memset(mvmvif->bssid, 0, ETH_ALEN);
- // This will take the cleared BSSID from bss_conf and update the firmware.
- ret = iwl_mvm_mac_ctxt_changed(mvmvif, false, NULL);
- mtx_unlock(&mvmvif->mvm->mutex);
- if (ret != ZX_OK) {
- IWL_ERR(mvm, "failed to update MAC (clear after unassoc)\n");
- goto out;
- }
-
- // Unbinding MAC and PHY contexts.
- ret = iwl_mvm_unassign_vif_chanctx(mvmvif);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "cannot unassign VIF channel context: %s\n", zx_status_get_string(ret));
- goto out;
- }
-
- ret = iwl_mvm_remove_chanctx(mvmvif->mvm, phy_ctxt_id);
- if (ret != ZX_OK) {
- IWL_ERR(mvmvif, "Cannot remove channel context: %s\n", zx_status_get_string(ret));
- goto out;
- }
-
-out:
- free_ap_mvm_sta(mvm_sta);
- mvmvif->mvm->fw_id_to_mac_id[ap_sta_id] = NULL;
-
- return ret;
-}
-
-zx_status_t mac_start_hw_scan(void* ctx, const wlan_hw_scan_config_t* scan_config) {
+zx_status_t mac_start_passive_scan(void* ctx,
+ const wlan_softmac_passive_scan_args_t* passive_scan_args,
+ uint64_t* out_scan_id) {
const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
+ return iwl_mvm_mac_hw_scan_passive(mvmvif, passive_scan_args, out_scan_id);
+}
- if (scan_config->scan_type != WLAN_HW_SCAN_TYPE_PASSIVE) {
- IWL_ERR(ctx, "Unsupported scan type: %s\n", wlan_hw_scan_type_to_str(scan_config->scan_type));
- return ZX_ERR_NOT_SUPPORTED;
- }
-
- return iwl_mvm_mac_hw_scan(mvmvif, scan_config);
+zx_status_t mac_start_active_scan(void* ctx,
+ const wlan_softmac_active_scan_args_t* active_scan_args,
+ uint64_t* out_scan_id) {
+ return ZX_ERR_NOT_SUPPORTED;
}
zx_status_t mac_init(void* ctx, struct iwl_trans* drvdata, zx_device_t* zxdev, uint16_t idx) {
@@ -750,22 +519,6 @@
return status;
}
-// TODO (fxbug.dev/63618) - to be removed.
-wlanmac_protocol_ops_t wlanmac_ops = {
- .query = mac_query,
- .start = mac_start,
- .stop = mac_stop,
- .queue_tx = mac_queue_tx,
- .set_channel = mac_set_channel,
- .configure_bss = mac_configure_bss,
- .enable_beaconing = mac_enable_beaconing,
- .configure_beacon = mac_configure_beacon,
- .set_key = mac_set_key,
- .configure_assoc = mac_configure_assoc,
- .clear_assoc = mac_clear_assoc,
- .start_hw_scan = mac_start_hw_scan,
-};
-
void mac_unbind(void* ctx) {
const auto mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(ctx);
@@ -789,30 +542,25 @@
free(mvmvif);
}
-// //TODO (fxbug.dev/63618) - to be removed.
-zx_protocol_device_t device_mac_ops = {
- .version = DEVICE_OPS_VERSION,
- .unbind = mac_unbind,
- .release = mac_release,
-};
-
///////////////////////////////////// PHY //////////////////////////////////////////////
-zx_status_t phy_query(void* ctx, wlanphy_impl_info_t* info) {
+zx_status_t phy_get_supported_mac_roles(
+ void* ctx,
+ wlan_mac_role_t out_supported_mac_roles_list[fuchsia_wlan_common_MAX_SUPPORTED_MAC_ROLES],
+ uint8_t* out_supported_mac_roles_count) {
const auto iwl_trans = reinterpret_cast<struct iwl_trans*>(ctx);
struct iwl_mvm* mvm = iwl_trans_get_mvm(iwl_trans);
- if (!mvm || !info) {
+ if (nullptr == mvm || nullptr == out_supported_mac_roles_list ||
+ nullptr == out_supported_mac_roles_count) {
return ZX_ERR_INVALID_ARGS;
}
struct iwl_nvm_data* nvm_data = mvm->nvm_data;
ZX_ASSERT(nvm_data);
- memset(info, 0, sizeof(*info));
-
// TODO(fxbug.dev/36677): supports AP role
- info->supported_mac_roles = WLAN_INFO_MAC_ROLE_CLIENT;
-
+ out_supported_mac_roles_list[0] = WLAN_MAC_ROLE_CLIENT;
+ *out_supported_mac_roles_count = 1;
return ZX_OK;
}
@@ -844,14 +592,14 @@
return ZX_ERR_INVALID_ARGS;
}
- mtx_lock(&mvm->mutex);
+ auto lock = std::lock_guard(mvm->mutex);
// Find the first empty mvmvif slot.
int idx;
ret = iwl_mvm_find_free_mvmvif_slot(mvm, &idx);
if (ret != ZX_OK) {
IWL_ERR(mvm, "cannot find an empty slot for new MAC interface\n");
- goto unlock;
+ return ret;
}
// Allocate a MAC context. This will be initialized once iwl_mvm_mac_add_interface() is called.
@@ -860,7 +608,7 @@
mvmvif = reinterpret_cast<struct iwl_mvm_vif*>(calloc(1, sizeof(struct iwl_mvm_vif)));
if (!mvmvif) {
ret = ZX_ERR_NO_MEMORY;
- goto unlock;
+ return ret;
}
// Set default values into the mvmvif
@@ -874,13 +622,11 @@
if (ret != ZX_OK) {
IWL_ERR(ctx, "Cannot assign the new mvmvif to MVM: %s\n", zx_status_get_string(ret));
// The allocated mvmvif instance will be freed at mac_release().
- goto unlock;
+ return ret;
}
- *out_iface_id = idx;
-unlock:
- mtx_unlock(&mvm->mutex);
- return ret;
+ *out_iface_id = idx;
+ return ZX_OK;
}
// If there are failures post phy_create_iface() and before phy_start_iface()
@@ -888,11 +634,13 @@
void phy_create_iface_undo(struct iwl_trans* iwl_trans, uint16_t idx) {
struct iwl_mvm* mvm = iwl_trans_get_mvm(iwl_trans);
- // Unbind and free the mvmvif interface.
- mtx_lock(&mvm->mutex);
- struct iwl_mvm_vif* mvmvif = mvm->mvmvif[idx];
- iwl_mvm_unbind_mvmvif(mvm, idx);
- mtx_unlock(&mvm->mutex);
+ struct iwl_mvm_vif* mvmvif = nullptr;
+ {
+ // Unbind and free the mvmvif interface.
+ auto lock = std::lock_guard(mvm->mutex);
+ mvmvif = mvm->mvmvif[idx];
+ iwl_mvm_unbind_mvmvif(mvm, idx);
+ }
free(mvmvif);
}
@@ -902,7 +650,12 @@
struct iwl_mvm* mvm = iwl_trans_get_mvm(iwl_trans);
zx_status_t ret = ZX_OK;
- mtx_lock(&mvm->mutex);
+ if (idx >= MAX_NUM_MVMVIF) {
+ IWL_ERR(mvm, "Interface index is too large (%d). expect less than %d\n", idx, MAX_NUM_MVMVIF);
+ return ZX_ERR_INVALID_ARGS;
+ }
+
+ auto lock = std::lock_guard(mvm->mutex);
struct iwl_mvm_vif* mvmvif = mvm->mvmvif[idx];
mvmvif->zxdev = zxdev;
@@ -918,7 +671,7 @@
// TODO: It does not look clean to have unbind happen here.
iwl_mvm_unbind_mvmvif(mvm, idx);
- goto unlock;
+ return ret;
}
// Once MVM is started, copy the MAC address to mvmvif.
@@ -926,9 +679,7 @@
memcpy(mvmvif->addr, nvm_data->hw_addr, ETH_ALEN);
}
-unlock:
- mtx_unlock(&mvm->mutex);
- return ret;
+ return ZX_OK;
}
// This function is working with a PHY context ('ctx') to delete a MAC interface ('id').
@@ -937,43 +688,39 @@
const auto iwl_trans = reinterpret_cast<struct iwl_trans*>(ctx);
struct iwl_mvm* mvm = iwl_trans_get_mvm(iwl_trans);
struct iwl_mvm_vif* mvmvif = nullptr;
- zx_status_t ret = ZX_OK;
if (!mvm) {
IWL_ERR(mvm, "cannot obtain MVM from ctx=%p while destroying interface (%d)\n", ctx, id);
return ZX_ERR_INVALID_ARGS;
}
- mtx_lock(&mvm->mutex);
+ {
+ auto lock = std::lock_guard(mvm->mutex);
- if (id >= MAX_NUM_MVMVIF) {
- IWL_ERR(mvm, "the interface id (%d) is invalid\n", id);
- ret = ZX_ERR_INVALID_ARGS;
- goto unlock;
- }
+ if (id >= MAX_NUM_MVMVIF) {
+ IWL_ERR(mvm, "the interface id (%d) is invalid\n", id);
+ return ZX_ERR_INVALID_ARGS;
+ }
- mvmvif = mvm->mvmvif[id];
- if (!mvmvif) {
- IWL_ERR(mvm, "the interface id (%d) has no MAC context\n", id);
- ret = ZX_ERR_NOT_FOUND;
- goto unlock;
- }
+ mvmvif = mvm->mvmvif[id];
+ if (!mvmvif) {
+ IWL_ERR(mvm, "the interface id (%d) has no MAC context\n", id);
+ return ZX_ERR_NOT_FOUND;
+ }
- // Unlink the 'mvmvif' from the 'mvm'. The zxdev will be removed in mac_unbind(),
- // and the memory of 'mvmvif' will be freed in mac_release().
- iwl_mvm_unbind_mvmvif(mvm, id);
+ // Unlink the 'mvmvif' from the 'mvm'. The zxdev will be removed in mac_unbind(),
+ // and the memory of 'mvmvif' will be freed in mac_release().
+ iwl_mvm_unbind_mvmvif(mvm, id);
- // the last MAC interface. stop the MVM to save power. 'vif_count' had been decreased in
- // iwl_mvm_mac_remove_interface().
- if (mvm->vif_count == 0) {
- __iwl_mvm_mac_stop(mvm);
+ // the last MAC interface. stop the MVM to save power. 'vif_count' had been decreased in
+ // iwl_mvm_mac_remove_interface().
+ if (mvm->vif_count == 0) {
+ __iwl_mvm_mac_stop(mvm);
+ }
}
device_async_remove(mvmvif->zxdev);
-
-unlock:
- mtx_unlock(&mvm->mutex);
- return ret;
+ return ZX_OK;
}
zx_status_t phy_set_country(void* ctx, const wlanphy_country_t* country) {
diff --git a/third_party/iwlwifi/platform/mvm-mlme.h b/third_party/iwlwifi/platform/mvm-mlme.h
index 98649cd..90bfc57 100644
--- a/third_party/iwlwifi/platform/mvm-mlme.h
+++ b/third_party/iwlwifi/platform/mvm-mlme.h
@@ -7,15 +7,14 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_MVM_MLME_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_MVM_MLME_H_
-#include <fuchsia/hardware/wlan/mac/cpp/banjo.h>
+#include <fuchsia/hardware/wlan/phyinfo/cpp/banjo.h>
+#include <fuchsia/hardware/wlan/softmac/cpp/banjo.h>
#include <fuchsia/hardware/wlanphyimpl/cpp/banjo.h>
#include <fuchsia/wlan/common/cpp/banjo.h>
#include <fuchsia/wlan/ieee80211/c/banjo.h>
#include <fuchsia/wlan/internal/cpp/banjo.h>
#include <lib/ddk/device.h>
-#include <fuchsia/hardware/wlanphyinfo/cpp/banjo.h>
-
#if defined(__cplusplus)
extern "C" {
#endif // defined(__cplusplus)
@@ -23,8 +22,8 @@
// IEEE Std 802.11-2016, Table 9-19
#define WLAN_MSDU_MAX_LEN 2304UL
-extern wlanmac_protocol_ops_t wlanmac_ops;
-extern zx_protocol_device_t device_mac_ops; // for testing only
+struct iwl_mvm_vif;
+struct iwl_mvm_sta;
// for testing
size_t compose_band_list(const struct iwl_nvm_data* nvm_data,
@@ -33,7 +32,10 @@
size_t bands_count, wlan_info_band_info_t* band_infos);
// Phy protocol helpers
-zx_status_t phy_query(void* ctx, wlanphy_impl_info_t* info);
+zx_status_t phy_get_supported_mac_roles(
+ void* ctx,
+ wlan_mac_role_t out_supported_mac_roles_list[fuchsia_wlan_common_MAX_SUPPORTED_MAC_ROLES],
+ uint8_t* out_supported_mac_roles_count);
zx_status_t phy_create_iface(void* ctx, const wlanphy_impl_create_iface_req_t* req,
uint16_t* out_iface_id);
zx_status_t phy_start_iface(void* ctx, zx_device_t* zxdev, uint16_t idx);
@@ -44,19 +46,28 @@
void phy_create_iface_undo(struct iwl_trans* iwl_trans, uint16_t idx);
// Mac protocol helpers
-zx_status_t mac_query(void* ctx, uint32_t options, wlanmac_info_t* info);
-zx_status_t mac_start(void* ctx, const wlanmac_ifc_protocol_t* ifc, zx_handle_t* out_mlme_channel);
-void mac_stop(void* ctx);
-zx_status_t mac_queue_tx(void* ctx, uint32_t options, const wlan_tx_packet_t* pkt);
-zx_status_t mac_set_channel(void* ctx, uint32_t options, const wlan_channel_t* channel);
-zx_status_t mac_configure_bss(void* ctx, uint32_t options, const bss_config_t* config);
+zx_status_t mac_query(void* ctx, uint32_t options, wlan_softmac_info_t* info);
+zx_status_t mac_start(void* ctx, const wlan_softmac_ifc_protocol_t* ifc,
+ zx_handle_t* out_mlme_channel);
+void mac_stop(struct iwl_mvm_vif* mvmvif);
+zx_status_t mac_set_channel(struct iwl_mvm_vif* mvmvif, uint32_t options,
+ const wlan_channel_t* channel);
+zx_status_t mac_configure_bss(struct iwl_mvm_vif* mvmvif, uint32_t options,
+ const bss_config_t* config);
+zx_status_t mac_unconfigure_bss(struct iwl_mvm_vif* mvmvif);
zx_status_t mac_enable_beaconing(void* ctx, uint32_t options, const wlan_bcn_config_t* bcn_cfg);
-zx_status_t mac_configure_beacon(void* ctx, uint32_t options, const wlan_tx_packet_t* pkt);
-zx_status_t mac_set_key(void* ctx, uint32_t options, const wlan_key_config_t* key_config);
-zx_status_t mac_configure_assoc(void* ctx, uint32_t options, const wlan_assoc_ctx_t* assoc_ctx);
-zx_status_t mac_clear_assoc(void* ctx, uint32_t options,
+zx_status_t mac_configure_beacon(void* ctx, uint32_t options,
+ const wlan_tx_packet_t* packet_template);
+zx_status_t mac_configure_assoc(struct iwl_mvm_vif* mvmvif, uint32_t options,
+ const wlan_assoc_ctx_t* assoc_ctx);
+zx_status_t mac_clear_assoc(struct iwl_mvm_vif* mvmvif, uint32_t options,
const uint8_t peer_addr[fuchsia_wlan_ieee80211_MAC_ADDR_LEN]);
-zx_status_t mac_start_hw_scan(void* ctx, const wlan_hw_scan_config_t* scan_config);
+zx_status_t mac_start_passive_scan(void* ctx,
+ const wlan_softmac_passive_scan_args_t* passive_scan_args,
+ uint64_t* out_scan_id);
+zx_status_t mac_start_active_scan(void* ctx,
+ const wlan_softmac_active_scan_args_t* active_scan_args,
+ uint64_t* out_scan_id);
zx_status_t mac_init(void* ctx, struct iwl_trans* drvdata, zx_device_t* zxdev, uint16_t idx);
void mac_unbind(void* ctx);
void mac_release(void* ctx);
diff --git a/third_party/iwlwifi/platform/mvm-sta.cc b/third_party/iwlwifi/platform/mvm-sta.cc
new file mode 100644
index 0000000..2cdf130
--- /dev/null
+++ b/third_party/iwlwifi/platform/mvm-sta.cc
@@ -0,0 +1,276 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/iwlwifi/platform/mvm-sta.h"
+
+#include <fidl/fuchsia.wlan.ieee80211/cpp/wire.h>
+#include <threads.h>
+#include <zircon/errors.h>
+#include <zircon/status.h>
+
+#include <algorithm>
+#include <cstring>
+
+extern "C" {
+#include "third_party/iwlwifi/mvm/sta.h"
+} // extern "C"
+
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
+#include "third_party/iwlwifi/platform/mvm-mlme.h"
+#include "third_party/iwlwifi/platform/rcu.h"
+
+namespace wlan::iwlwifi {
+namespace {
+
+// IEEE 802.11-2016 3.2 (c.f. "vendor organizationally unique identifier")
+constexpr uint8_t kIeeeOui[] = {0x00, 0x0F, 0xAC};
+
+} // namespace
+
+MvmSta::MvmSta(struct iwl_mvm_vif* iwl_mvm_vif, std::unique_ptr<struct iwl_mvm_sta> iwl_mvm_sta)
+ : iwl_mvm_vif_(iwl_mvm_vif), iwl_mvm_sta_(std::move(iwl_mvm_sta)) {}
+
+MvmSta::~MvmSta() {
+ if (iwl_mvm_sta_ != nullptr) {
+ zx_status_t status = ZX_OK;
+
+ for (auto& key_conf : ieee80211_key_confs_) {
+ if (key_conf == nullptr) {
+ continue;
+ }
+ if ((status = iwl_mvm_mac_remove_key(iwl_mvm_sta_->mvmvif, iwl_mvm_sta_.get(),
+ key_conf.get())) != ZX_OK) {
+ IWL_ERR(iwl_mvm_vif_, "iwl_mvm_mac_remove_key() failed for keyidx %d: %s\n",
+ key_conf->keyidx, zx_status_get_string(status));
+ }
+ key_conf.reset();
+ }
+
+ if ((status = ChangeState(iwl_sta_state::IWL_STA_NOTEXIST)) != ZX_OK) {
+ IWL_ERR(iwl_mvm_vif_, "ChangeState() failed: %s\n", zx_status_get_string(status));
+ }
+
+ iwl_rcu_call_sync(
+ iwl_mvm_vif_->mvm->dev,
+ [](void* data) {
+ auto mvm_sta = reinterpret_cast<struct iwl_mvm_sta*>(data);
+ for (auto txq : mvm_sta->txq) {
+ delete txq;
+ }
+ delete mvm_sta;
+ },
+ iwl_mvm_sta_.release());
+ }
+}
+
+// static
+zx_status_t MvmSta::Create(struct iwl_mvm_vif* iwl_mvm_vif, const uint8_t bssid[ETH_ALEN],
+ std::unique_ptr<MvmSta>* mvm_sta_out) {
+ zx_status_t status = ZX_OK;
+
+ // Initialize the iwl_mvm_sta instance.
+ auto iwl_mvm_sta = std::make_unique<struct iwl_mvm_sta>();
+ for (auto& txq_ref : iwl_mvm_sta->txq) {
+ txq_ref = new struct iwl_mvm_txq();
+ }
+ static_assert(sizeof(iwl_mvm_sta->addr) == sizeof(*bssid) * ETH_ALEN);
+ std::memcpy(iwl_mvm_sta->addr, bssid, sizeof(iwl_mvm_sta->addr));
+ mtx_init(&iwl_mvm_sta->lock, mtx_plain);
+
+ auto mvm_sta = std::unique_ptr<MvmSta>(new MvmSta(iwl_mvm_vif, std::move(iwl_mvm_sta)));
+
+ if ((status = mvm_sta->ChangeState(iwl_sta_state::IWL_STA_NONE)) != ZX_OK) {
+ return status;
+ }
+
+ {
+ // Allocate a TX queue for this station.
+ auto iwl_mvm = mvm_sta->iwl_mvm_vif_->mvm;
+ auto lock = std::lock_guard(iwl_mvm->mutex);
+ if ((status = iwl_mvm_sta_alloc_queue(iwl_mvm, mvm_sta->iwl_mvm_sta_.get(), IEEE80211_AC_BE,
+ IWL_MAX_TID_COUNT)) != ZX_OK) {
+ mtx_unlock(&iwl_mvm->mutex);
+ IWL_ERR(iwl_mvm, "iwl_mvm_sta_alloc_queue() failed: %s\n", zx_status_get_string(status));
+ return status;
+ }
+ }
+
+ *mvm_sta_out = std::move(mvm_sta);
+ return status;
+}
+
+zx_status_t MvmSta::SetKey(const struct wlan_key_config* key_config) {
+ zx_status_t status = ZX_OK;
+ struct iwl_mvm* const mvm = iwl_mvm_sta_->mvmvif->mvm;
+
+ if (mvm->trans->cfg->gen2 || iwl_mvm_has_new_tx_api(mvm)) {
+ // The new firmwares (for starting with the 22000 series) have different packet generation
+ // requirements than mentioned below.
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+
+ if (!std::equal(key_config->cipher_oui,
+ key_config->cipher_oui + std::size(key_config->cipher_oui), kIeeeOui,
+ kIeeeOui + std::size(kIeeeOui))) {
+ // IEEE 802.11-2016 9.4.2.25.2
+ // The standard ciphers all live in the IEEE space.
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+
+ if (key_config->key_type < 0 || key_config->key_type >= ieee80211_key_confs_.size()) {
+ return ZX_ERR_INVALID_ARGS;
+ }
+
+ // Remove any existing key in this slot.
+ if (ieee80211_key_confs_[key_config->key_type] != nullptr) {
+ if ((status = iwl_mvm_mac_remove_key(iwl_mvm_sta_->mvmvif, iwl_mvm_sta_.get(),
+ ieee80211_key_confs_[key_config->key_type].get())) !=
+ ZX_OK) {
+ IWL_ERR(mvmvif, "iwl_mvm_mac_remove_key() failed: %s\n", zx_status_get_string(status));
+ return status;
+ }
+ ieee80211_key_confs_[key_config->key_type].reset();
+ }
+
+ unique_free_ptr<struct ieee80211_key_conf> key_conf(reinterpret_cast<struct ieee80211_key_conf*>(
+ malloc(sizeof(ieee80211_key_conf) + key_config->key_len)));
+ memset(key_conf.get(), 0, sizeof(*key_conf) + key_config->key_len);
+ key_conf->cipher = key_config->cipher_type;
+ key_conf->keyidx = key_config->key_idx;
+ key_conf->keylen = key_config->key_len;
+ key_conf->rx_seq = key_config->rsc;
+ memcpy(key_conf->key, key_config->key, key_conf->keylen);
+
+ if ((status = iwl_mvm_mac_add_key(iwl_mvm_sta_->mvmvif, iwl_mvm_sta_.get(), key_conf.get())) !=
+ ZX_OK) {
+ IWL_ERR(mvmvif, "iwl_mvm_mac_add_key(key_type %d, cipher_type %d, key_idx %d) failed: %s\n",
+ key_config->key_type, key_config->cipher_type, key_config->key_idx,
+ zx_status_get_string(status));
+ return status;
+ }
+
+ ieee80211_key_confs_[key_config->key_type] = std::move(key_conf);
+ return ZX_OK;
+}
+
+struct ieee80211_key_conf* MvmSta::GetKey(wlan_key_type_t key_type) {
+ if (key_type < 0 || key_type > ieee80211_key_confs_.size()) {
+ return nullptr;
+ }
+ return ieee80211_key_confs_[key_type].get();
+}
+
+const struct ieee80211_key_conf* MvmSta::GetKey(wlan_key_type_t key_type) const {
+ if (key_type < 0 || key_type > ieee80211_key_confs_.size()) {
+ return nullptr;
+ }
+ return ieee80211_key_confs_[key_type].get();
+}
+
+enum iwl_sta_state MvmSta::GetState() const { return sta_state_; }
+
+zx_status_t MvmSta::ChangeState(enum iwl_sta_state state) {
+ zx_status_t status = ZX_OK;
+ while (state > sta_state_) {
+ if ((status = ChangeStateUp()) != ZX_OK) {
+ return status;
+ }
+ }
+ while (state < sta_state_) {
+ if ((status = ChangeStateDown()) != ZX_OK) {
+ return status;
+ }
+ }
+ return ZX_OK;
+}
+
+struct iwl_mvm_sta* MvmSta::iwl_mvm_sta() {
+ return iwl_mvm_sta_.get();
+}
+
+const struct iwl_mvm_sta* MvmSta::iwl_mvm_sta() const { return iwl_mvm_sta_.get(); }
+
+zx_status_t MvmSta::ChangeStateUp() {
+ zx_status_t status = ZX_OK;
+ iwl_sta_state new_state = iwl_sta_state::IWL_STA_NOTEXIST;
+ switch (sta_state_) {
+ case iwl_sta_state::IWL_STA_NOTEXIST: {
+ new_state = iwl_sta_state::IWL_STA_NONE;
+ break;
+ }
+ case iwl_sta_state::IWL_STA_NONE: {
+ new_state = iwl_sta_state::IWL_STA_AUTH;
+ break;
+ }
+ case iwl_sta_state::IWL_STA_AUTH: {
+ new_state = iwl_sta_state::IWL_STA_ASSOC;
+ break;
+ }
+ case iwl_sta_state::IWL_STA_ASSOC: {
+ new_state = iwl_sta_state::IWL_STA_AUTHORIZED;
+ break;
+ }
+ default: {
+ IWL_ERR(iwl_mvm_vif_, "ChangeStateUp() in invalid state %d\n", sta_state_);
+ return ZX_ERR_BAD_STATE;
+ }
+ }
+
+ if ((status = iwl_mvm_mac_sta_state(iwl_mvm_vif_, iwl_mvm_sta_.get(), sta_state_, new_state)) !=
+ ZX_OK) {
+ IWL_ERR(iwl_mvm_vif_, "iwl_mvm_mac_sta_state() failed for %d -> %d: %s\n", sta_state_,
+ new_state, zx_status_get_string(status));
+ return status;
+ }
+
+ sta_state_ = new_state;
+ return ZX_OK;
+}
+
+zx_status_t MvmSta::ChangeStateDown() {
+ zx_status_t status = ZX_OK;
+ iwl_sta_state new_state = iwl_sta_state::IWL_STA_NOTEXIST;
+ switch (sta_state_) {
+ case iwl_sta_state::IWL_STA_AUTHORIZED: {
+ new_state = iwl_sta_state::IWL_STA_ASSOC;
+ break;
+ }
+ case iwl_sta_state::IWL_STA_ASSOC: {
+ new_state = iwl_sta_state::IWL_STA_AUTH;
+ break;
+ }
+ case iwl_sta_state::IWL_STA_AUTH: {
+ new_state = iwl_sta_state::IWL_STA_NONE;
+ break;
+ }
+ case iwl_sta_state::IWL_STA_NONE: {
+ {
+ // Tell firmware to flush all packets in the Tx queue. This must be done before we remove
+ // the STA (in the NONE->NOTEXIST transition).
+ // TODO(79799): understand why we need this.
+ auto lock = std::lock_guard(iwl_mvm_vif_->mvm->mutex);
+ iwl_mvm_flush_sta(iwl_mvm_vif_->mvm, iwl_mvm_sta_.get(), false, 0);
+ }
+
+ new_state = iwl_sta_state::IWL_STA_NOTEXIST;
+ break;
+ }
+ default: {
+ IWL_ERR(iwl_mvm_vif_, "ChangeStateDown() in invalid state %d\n", sta_state_);
+ return ZX_ERR_BAD_STATE;
+ }
+ }
+
+ if ((status = iwl_mvm_mac_sta_state(iwl_mvm_vif_, iwl_mvm_sta_.get(), sta_state_, new_state)) !=
+ ZX_OK) {
+ IWL_ERR(iwl_mvm_vif_, "iwl_mvm_mac_sta_state() failed for %d -> %d: %s\n", sta_state_,
+ new_state, zx_status_get_string(status));
+ return status;
+ }
+
+ sta_state_ = new_state;
+ return ZX_OK;
+}
+
+} // namespace wlan::iwlwifi
diff --git a/third_party/iwlwifi/platform/mvm-sta.h b/third_party/iwlwifi/platform/mvm-sta.h
new file mode 100644
index 0000000..6d9445a
--- /dev/null
+++ b/third_party/iwlwifi/platform/mvm-sta.h
@@ -0,0 +1,72 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_MVM_STA_H_
+#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_MVM_STA_H_
+
+#include <fuchsia/hardware/wlan/associnfo/cpp/banjo.h>
+#include <fuchsia/hardware/wlan/softmac/cpp/banjo.h>
+#include <netinet/if_ether.h>
+#include <zircon/types.h>
+
+#include <array>
+#include <cstdlib>
+#include <memory>
+#include <type_traits>
+
+extern "C" {
+#include "third_party/iwlwifi/mvm/mvm.h"
+} // extern "C"
+
+#include "third_party/iwlwifi/platform/scoped_utils.h"
+
+struct ieee80211_key_conf;
+struct iwl_mvm_sta;
+
+namespace wlan::iwlwifi {
+
+// This class manages the lifetime of one instance of a iwl_mvm_sta, including associated state such
+// as encryption keys.
+class MvmSta {
+ public:
+ // Factory function for MvmSta instances.
+ static zx_status_t Create(struct iwl_mvm_vif* iwl_mvm_vif, const uint8_t bssid[ETH_ALEN],
+ std::unique_ptr<MvmSta>* mvm_sta_out);
+ ~MvmSta();
+
+ // Set one of the keys for this station, which may be the pairwise, group, etc. key.
+ zx_status_t SetKey(const struct wlan_key_config* key_config);
+
+ // Get a key for this station, which may be used for TX.
+ struct ieee80211_key_conf* GetKey(wlan_key_type_t key_type);
+ const struct ieee80211_key_conf* GetKey(wlan_key_type_t key_type) const;
+
+ // Get the current station state.
+ enum iwl_sta_state GetState() const;
+
+ // Effect a change to the given station state.
+ zx_status_t ChangeState(enum iwl_sta_state state);
+
+ // Accessors.
+ struct iwl_mvm_sta* iwl_mvm_sta();
+ const struct iwl_mvm_sta* iwl_mvm_sta() const;
+
+ private:
+ explicit MvmSta(struct iwl_mvm_vif* iwl_mvm_vif, std::unique_ptr<struct iwl_mvm_sta> iwl_mvm_sta);
+
+ // Change the station state in each direction:
+ // * Up is from NOTEXIST -> AUTHORIZED
+ // * Down is from AUTHORIZED -> NOTEXIST
+ zx_status_t ChangeStateUp();
+ zx_status_t ChangeStateDown();
+
+ struct iwl_mvm_vif* iwl_mvm_vif_ = nullptr;
+ std::unique_ptr<struct iwl_mvm_sta> iwl_mvm_sta_;
+ std::array<unique_free_ptr<struct ieee80211_key_conf>, 5> ieee80211_key_confs_;
+ enum iwl_sta_state sta_state_ = iwl_sta_state::IWL_STA_NOTEXIST;
+};
+
+} // namespace wlan::iwlwifi
+
+#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_MVM_STA_H_
diff --git a/third_party/iwlwifi/platform/pci.h b/third_party/iwlwifi/platform/pci.h
index 78c0038..5485bd3 100644
--- a/third_party/iwlwifi/platform/pci.h
+++ b/third_party/iwlwifi/platform/pci.h
@@ -8,7 +8,7 @@
// This file contains PCI bus code that operates as a compatibility layer between the Linux and
// Fuchsia PCI bus driver models.
-#include "kernel.h"
+#include "third_party/iwlwifi/platform/kernel.h"
#if defined(__cplusplus)
extern "C" {
diff --git a/third_party/iwlwifi/platform/pcie-device.cc b/third_party/iwlwifi/platform/pcie-device.cc
index 80605cf..be5e98d 100644
--- a/third_party/iwlwifi/platform/pcie-device.cc
+++ b/third_party/iwlwifi/platform/pcie-device.cc
@@ -2,13 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// TODO(rsakthi) - how to get this from bazel?
-#define CPTCFG_IWLMVM 1
-
#include "third_party/iwlwifi/platform/pcie-device.h"
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
+#include <lib/async/cpp/task.h>
#include <zircon/assert.h>
#include <zircon/status.h>
@@ -21,6 +19,7 @@
}
#include "third_party/iwlwifi/platform/driver-inspector.h"
+#include "third_party/iwlwifi/platform/rcu-manager.h"
#if !CPTCFG_IWLMVM
#error "PcieDevice requires support for MVM firmwares."
@@ -72,11 +71,16 @@
zx_status_get_string(status));
return status;
}
+ rcu_manager_ = std::make_unique<RcuManager>(task_loop_->dispatcher());
+ rcu_manager_->InitForThread();
+ ::async::PostTask(task_loop_->dispatcher(), [this]() { rcu_manager_->InitForThread(); });
+ ::async::PostTask(irq_loop_->dispatcher(), [this]() { rcu_manager_->InitForThread(); });
// Fill in the relevant Fuchsia-specific fields in our driver interface struct.
pci_dev_.dev.zxdev = zxdev();
pci_dev_.dev.task_dispatcher = task_loop_->dispatcher();
pci_dev_.dev.irq_dispatcher = irq_loop_->dispatcher();
+ pci_dev_.dev.rcu_manager = static_cast<struct rcu_manager*>(rcu_manager_.get());
pci_dev_.dev.inspector = static_cast<struct driver_inspector*>(driver_inspector_.get());
if ((status = device_get_fragment_protocol(parent(), "pci", ZX_PROTOCOL_PCI,
diff --git a/third_party/iwlwifi/platform/pcie-device.h b/third_party/iwlwifi/platform/pcie-device.h
index 2f08f40..80f16c6 100644
--- a/third_party/iwlwifi/platform/pcie-device.h
+++ b/third_party/iwlwifi/platform/pcie-device.h
@@ -19,6 +19,7 @@
namespace wlan::iwlwifi {
class DriverInspector;
+class RcuManager;
// This class contains the Fuchsia-specific PCIE bus initialization logic, using the DDKTL classes
// to manage the lifetime of a iwlwifi driver instance.
@@ -44,6 +45,7 @@
std::unique_ptr<DriverInspector> driver_inspector_;
std::unique_ptr<::async::Loop> task_loop_;
std::unique_ptr<::async::Loop> irq_loop_;
+ std::unique_ptr<RcuManager> rcu_manager_;
iwl_pci_dev pci_dev_;
};
diff --git a/third_party/iwlwifi/platform/rcu-manager.cc b/third_party/iwlwifi/platform/rcu-manager.cc
new file mode 100644
index 0000000..8ca9bd5
--- /dev/null
+++ b/third_party/iwlwifi/platform/rcu-manager.cc
@@ -0,0 +1,76 @@
+#include "third_party/iwlwifi/platform/rcu-manager.h"
+
+#include <lib/async/cpp/task.h>
+#include <lib/stdcompat/atomic.h>
+#include <zircon/assert.h>
+
+#include <limits>
+
+namespace wlan::iwlwifi {
+
+// static
+thread_local int RcuManager::read_lock_count_ = 0;
+
+RcuManager::RcuManager(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher) {}
+
+RcuManager::~RcuManager() {
+ zx_status_t status = ZX_OK;
+
+ // Wait for all existing calls to complete.
+ cpp20::atomic_ref<zx_futex_t> call_count_ref(call_count_);
+ zx_futex_t count = call_count_ref.load(std::memory_order_acquire);
+ while (count > 0) {
+ if ((status = zx_futex_wait(&call_count_, count, ZX_HANDLE_INVALID, ZX_TIME_INFINITE)) !=
+ ZX_OK) {
+ if (status != ZX_ERR_BAD_STATE) {
+ break;
+ }
+ }
+ count = call_count_ref.load(std::memory_order_acquire);
+ }
+}
+
+void RcuManager::InitForThread() { read_lock_count_ = 0; }
+
+void RcuManager::ReadLock() {
+ if (++read_lock_count_ == 1) {
+ rwlock_.lock_shared();
+ }
+}
+
+void RcuManager::ReadUnlock() {
+ ZX_DEBUG_ASSERT(read_lock_count_ > 0);
+ if (--read_lock_count_ == 0) {
+ rwlock_.unlock_shared();
+ }
+}
+
+void RcuManager::Sync() {
+ // Sync only has to ensure that there are no more outstanding reader locks.
+ rwlock_.lock();
+ rwlock_.unlock();
+}
+
+void RcuManager::CallSync(void (*func)(void*), void* data) {
+ // Post the task to the worker dispatcher. This has the advantages of:
+ // * Not immediately blocking the current thread.
+ // * The worker dispatcher is often another thread that uses RCUs. By posting the task to this
+ // thread, we ensure that it cannot also be locking for RCU at the same time, thus reducing
+ // contention.
+ cpp20::atomic_ref<zx_futex_t> call_count_ref(call_count_);
+ call_count_ref.fetch_add(1, std::memory_order_release);
+ ::async::PostTask(dispatcher_, [this, func, data]() {
+ Sync();
+ func(data);
+
+ // Signal waiters that may be waiting for all calls to complete.
+ cpp20::atomic_ref<zx_futex_t> call_count_ref(call_count_);
+ if (call_count_ref.fetch_sub(1, std::memory_order_release) == 1) {
+ zx_futex_wake(&call_count_, std::numeric_limits<uint32_t>::max());
+ }
+ });
+}
+
+void RcuManager::FreeSync(void* alloc) { CallSync(&free, alloc); }
+
+} // namespace wlan::iwlwifi
diff --git a/third_party/iwlwifi/platform/rcu-manager.h b/third_party/iwlwifi/platform/rcu-manager.h
new file mode 100644
index 0000000..1a71268
--- /dev/null
+++ b/third_party/iwlwifi/platform/rcu-manager.h
@@ -0,0 +1,53 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_RCU_MANAGER_H_
+#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_RCU_MANAGER_H_
+
+#include <lib/async/dispatcher.h>
+#include <zircon/types.h>
+
+#include <shared_mutex>
+
+namespace wlan::iwlwifi {
+
+// This class manages RCU-based synchronization for a set of threads.
+class RcuManager {
+ public:
+ explicit RcuManager(async_dispatcher_t* dispatcher);
+ ~RcuManager();
+
+ // Initialize the RCU manager for the current thread. This must be run on every thread that will
+ // be using RCU.
+ void InitForThread();
+
+ // Enter a RCU read-side lock.
+ void ReadLock();
+
+ // Exit a RCU read-side lock.
+ void ReadUnlock();
+
+ // Wait for all existing read-side locks to unlock.
+ void Sync();
+
+ // Helper: call a function after synchronizing.
+ void CallSync(void (*func)(void*), void* data);
+
+ // Helper: free() an allocation after synchronizing.
+ void FreeSync(void* alloc);
+
+ private:
+ async_dispatcher_t* dispatcher_ = nullptr;
+ std::shared_mutex rwlock_;
+ static thread_local int read_lock_count_;
+ zx_futex_t call_count_ = 0;
+};
+
+} // namespace wlan::iwlwifi
+
+// This subclass-as-an-alias exists purely to be compatible with C code that uses the
+// `rcu_manager` type as a struct pointer.
+struct rcu_manager final : public wlan::iwlwifi::RcuManager {};
+
+#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_RCU_MANAGER_H_
diff --git a/third_party/iwlwifi/platform/rcu.cc b/third_party/iwlwifi/platform/rcu.cc
new file mode 100644
index 0000000..4affa0f
--- /dev/null
+++ b/third_party/iwlwifi/platform/rcu.cc
@@ -0,0 +1,20 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/iwlwifi/platform/rcu.h"
+
+#include "third_party/iwlwifi/platform/kernel.h"
+#include "third_party/iwlwifi/platform/rcu-manager.h"
+
+void iwl_rcu_read_lock(struct device* dev) { dev->rcu_manager->ReadLock(); }
+
+void iwl_rcu_read_unlock(struct device* dev) { dev->rcu_manager->ReadUnlock(); }
+
+void iwl_rcu_sync(struct device* dev) { dev->rcu_manager->Sync(); }
+
+void iwl_rcu_call_sync(struct device* dev, iwl_rcu_call_func func, void* data) {
+ dev->rcu_manager->CallSync(func, data);
+}
+
+void iwl_rcu_free_sync(struct device* dev, void* alloc) { dev->rcu_manager->FreeSync(alloc); }
diff --git a/third_party/iwlwifi/platform/rcu.h b/third_party/iwlwifi/platform/rcu.h
new file mode 100644
index 0000000..1c6ea77
--- /dev/null
+++ b/third_party/iwlwifi/platform/rcu.h
@@ -0,0 +1,43 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_RCU_H_
+#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_RCU_H_
+
+#include "third_party/iwlwifi/platform/compiler.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif // defined(__cplusplus)
+
+struct device;
+
+typedef void (*iwl_rcu_call_func)(void*);
+
+// Enter a RCU read-side lock. May be nested.
+void iwl_rcu_read_lock(struct device* dev);
+
+// Exit a RCU read-side lock. May be nested.
+void iwl_rcu_read_unlock(struct device* dev);
+
+// Wait for all existing read-side locks to unlock.
+void iwl_rcu_sync(struct device* dev);
+
+// Call a function after synchronizing with existing read-side locks.
+void iwl_rcu_call_sync(struct device* dev, iwl_rcu_call_func func, void* data);
+
+// Free an allocation after synchronizing with existing read-side locks.
+void iwl_rcu_free_sync(struct device* dev, void* alloc);
+
+#define iwl_rcu_load(p) (atomic_load_explicit((_Atomic(__typeof(p))*)&p, memory_order_acquire))
+#define iwl_rcu_store(p, v) \
+ (atomic_store_explicit((_Atomic(__typeof(p))*)&p, v, memory_order_release))
+#define iwl_rcu_exchange(p, v) \
+ (atomic_exchange_explicit((_Atomic(__typeof(p))*)&p, v, memory_order_acq_rel))
+
+#if defined(__cplusplus)
+} // extern "C"
+#endif // defined(__cplusplus)
+
+#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_RCU_H_
diff --git a/third_party/iwlwifi/platform/scoped_utils.h b/third_party/iwlwifi/platform/scoped_utils.h
new file mode 100644
index 0000000..7603e9a
--- /dev/null
+++ b/third_party/iwlwifi/platform/scoped_utils.h
@@ -0,0 +1,45 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_SCOPED_UTILS_H_
+#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_SCOPED_UTILS_H_
+
+// This file contains a collection of utilities for owning a resource for the duration of a scope.
+
+#include <threads.h>
+#include <zircon/compiler.h>
+
+#include <cstdlib>
+#include <memory>
+#include <mutex>
+#include <type_traits>
+
+namespace std {
+
+// A specialization for std::lock_guard<> for use with mtx_t types.
+template <>
+class __TA_SCOPED_CAPABILITY lock_guard<mtx_t> {
+ public:
+ using mutex_type = mtx_t;
+ __WARN_UNUSED_CONSTRUCTOR explicit lock_guard(mtx_t& m) __TA_ACQUIRE(m) : m(m) { mtx_lock(&m); }
+ __WARN_UNUSED_CONSTRUCTOR lock_guard(mtx_t& m, std::adopt_lock_t t) __TA_REQUIRES(m) : m(m) {}
+ ~lock_guard() __TA_RELEASE() { mtx_unlock(&m); }
+ lock_guard(const lock_guard&) = delete;
+ lock_guard& operator=(const lock_guard&) = delete;
+
+ private:
+ mutex_type& m;
+};
+
+} // namespace std
+
+namespace wlan::iwlwifi {
+
+// unique_free_ptr is like std::unique_ptr<>, but uses free() to destroy the held object.
+template <typename T>
+using unique_free_ptr = std::unique_ptr<T, std::integral_constant<decltype(std::free)*, std::free>>;
+
+} // namespace wlan::iwlwifi
+
+#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_SCOPED_UTILS_H_
diff --git a/third_party/iwlwifi/platform/task-internal.cc b/third_party/iwlwifi/platform/task-internal.cc
index 64b2862..7272f0c 100644
--- a/third_party/iwlwifi/platform/task-internal.cc
+++ b/third_party/iwlwifi/platform/task-internal.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "task-internal.h"
+#include "third_party/iwlwifi/platform/task-internal.h"
#include <lib/async/time.h>
#include <lib/stdcompat/atomic.h>
diff --git a/third_party/iwlwifi/platform/task.cc b/third_party/iwlwifi/platform/task.cc
index bcbcf62..5c9aee0 100644
--- a/third_party/iwlwifi/platform/task.cc
+++ b/third_party/iwlwifi/platform/task.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "task.h"
+#include "third_party/iwlwifi/platform/task.h"
#include <lib/async/dispatcher.h>
#include <memory>
-#include "task-internal.h"
+#include "third_party/iwlwifi/platform/task-internal.h"
struct iwl_task : public wlan::iwlwifi::TaskInternal {
public:
diff --git a/third_party/iwlwifi/platform/task.h b/third_party/iwlwifi/platform/task.h
index 48c6c53..da0e9ae 100644
--- a/third_party/iwlwifi/platform/task.h
+++ b/third_party/iwlwifi/platform/task.h
@@ -11,7 +11,7 @@
#include <zircon/types.h>
-#include "kernel.h"
+#include "third_party/iwlwifi/platform/kernel.h"
#if defined(__cplusplus)
extern "C" {
diff --git a/third_party/iwlwifi/platform/time.cc b/third_party/iwlwifi/platform/time.cc
index 2fe34a2..2970c3a 100644
--- a/third_party/iwlwifi/platform/time.cc
+++ b/third_party/iwlwifi/platform/time.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "time.h"
+#include "third_party/iwlwifi/platform/time.h"
#include <lib/async/time.h>
diff --git a/third_party/iwlwifi/platform/time.h b/third_party/iwlwifi/platform/time.h
index 5332f3d..97d074d 100644
--- a/third_party/iwlwifi/platform/time.h
+++ b/third_party/iwlwifi/platform/time.h
@@ -7,7 +7,7 @@
#include <zircon/types.h>
-#include "kernel.h"
+#include "third_party/iwlwifi/platform/kernel.h"
#if defined(__cplusplus)
extern "C" {
diff --git a/third_party/iwlwifi/platform/wlan-softmac-device.cc b/third_party/iwlwifi/platform/wlan-softmac-device.cc
new file mode 100644
index 0000000..b65684f
--- /dev/null
+++ b/third_party/iwlwifi/platform/wlan-softmac-device.cc
@@ -0,0 +1,205 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/iwlwifi/platform/wlan-softmac-device.h"
+
+#include <zircon/assert.h>
+#include <zircon/status.h>
+
+#include <memory>
+
+extern "C" {
+#include "third_party/iwlwifi/mvm/mvm.h"
+} // extern "C"
+
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
+#include "third_party/iwlwifi/platform/mvm-mlme.h"
+#include "third_party/iwlwifi/platform/mvm-sta.h"
+#include "third_party/iwlwifi/platform/scoped_utils.h"
+
+namespace wlan::iwlwifi {
+
+WlanSoftmacDevice::WlanSoftmacDevice(zx_device* parent, iwl_trans* drvdata, uint16_t iface_id,
+ struct iwl_mvm_vif* mvmvif)
+ : ddk::Device<WlanSoftmacDevice, ddk::Initializable, ddk::Unbindable>(parent),
+ mvmvif_(mvmvif),
+ drvdata_(drvdata),
+ iface_id_(iface_id) {}
+
+WlanSoftmacDevice::~WlanSoftmacDevice() = default;
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacQuery(uint32_t options, wlan_softmac_info_t* out_info) {
+ return mac_query(mvmvif_, options, out_info);
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacStart(const wlan_softmac_ifc_protocol_t* ifc,
+ zx::channel* out_mlme_channel) {
+ return mac_start(mvmvif_, ifc, (zx_handle_t*)out_mlme_channel);
+}
+
+void WlanSoftmacDevice::WlanSoftmacStop() {
+ ap_mvm_sta_.reset();
+ mac_stop(mvmvif_);
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacQueueTx(uint32_t options,
+ const wlan_tx_packet_t* packet) {
+ if (ap_mvm_sta_ == nullptr) {
+ return ZX_ERR_BAD_STATE;
+ }
+
+ if (packet->mac_frame_size > WLAN_MSDU_MAX_LEN) {
+ IWL_ERR(mvmvif_, "Frame size is to large (%lu). expect less than %lu.\n",
+ packet->mac_frame_size, WLAN_MSDU_MAX_LEN);
+ return ZX_ERR_INVALID_ARGS;
+ }
+
+ ieee80211_mac_packet mac_packet = {};
+ mac_packet.common_header =
+ reinterpret_cast<const ieee80211_frame_header*>(packet->mac_frame_buffer);
+ mac_packet.header_size = ieee80211_get_header_len(mac_packet.common_header);
+ if (mac_packet.header_size > packet->mac_frame_size) {
+ IWL_ERR(mvmvif_, "TX packet header size %zu too large for data size %zu\n",
+ mac_packet.header_size, packet->mac_frame_size);
+ return ZX_ERR_INVALID_ARGS;
+ }
+
+ mac_packet.body = packet->mac_frame_buffer + mac_packet.header_size;
+ mac_packet.body_size = packet->mac_frame_size - mac_packet.header_size;
+ if (ieee80211_pkt_is_protected(mac_packet.common_header)) {
+ switch (ieee80211_get_frame_type(mac_packet.common_header)) {
+ case ieee80211_frame_type::IEEE80211_FRAME_TYPE_MGMT:
+ mac_packet.info.control.hw_key = ap_mvm_sta_->GetKey(WLAN_KEY_TYPE_IGTK);
+ break;
+ case ieee80211_frame_type::IEEE80211_FRAME_TYPE_DATA:
+ mac_packet.info.control.hw_key = ap_mvm_sta_->GetKey(WLAN_KEY_TYPE_PAIRWISE);
+ break;
+ default:
+ break;
+ }
+ }
+
+ auto lock = std::lock_guard(mvmvif_->mvm->mutex);
+ return iwl_mvm_mac_tx(mvmvif_, ap_mvm_sta_->iwl_mvm_sta(), &mac_packet);
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacSetChannel(uint32_t options,
+ const wlan_channel_t* channel) {
+ zx_status_t status = ZX_OK;
+
+ // If the AP sta already exists, it probably was left from the previous association attempt.
+ // Remove it first.
+ if (ap_mvm_sta_ != nullptr) {
+ if ((status = mac_unconfigure_bss(mvmvif_)) != ZX_OK) {
+ return status;
+ }
+ ap_mvm_sta_.reset();
+ }
+ return mac_set_channel(mvmvif_, options, channel);
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacConfigureBss(uint32_t options,
+ const bss_config_t* config) {
+ zx_status_t status = ZX_OK;
+ if (ap_mvm_sta_ != nullptr) {
+ return ZX_ERR_ALREADY_BOUND;
+ }
+ if ((status = mac_configure_bss(mvmvif_, options, config)) != ZX_OK) {
+ return status;
+ }
+
+ ZX_DEBUG_ASSERT(mvmvif_->mac_role == WLAN_MAC_ROLE_CLIENT);
+ std::unique_ptr<MvmSta> ap_mvm_sta;
+ if ((status = MvmSta::Create(mvmvif_, config->bssid, &ap_mvm_sta)) != ZX_OK) {
+ return status;
+ }
+
+ ap_mvm_sta_ = std::move(ap_mvm_sta);
+ return ZX_OK;
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacEnableBeaconing(uint32_t options,
+ const wlan_bcn_config_t* bcn_cfg) {
+ return mac_enable_beaconing(mvmvif_, options, bcn_cfg);
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacConfigureBeacon(uint32_t options,
+ const wlan_tx_packet_t* pkt) {
+ return mac_configure_beacon(mvmvif_, options, pkt);
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacSetKey(uint32_t options,
+ const wlan_key_config_t* key_config) {
+ if (ap_mvm_sta_ == nullptr) {
+ return ZX_ERR_BAD_STATE;
+ }
+ return ap_mvm_sta_->SetKey(key_config);
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacConfigureAssoc(uint32_t options,
+ const wlan_assoc_ctx_t* assoc_ctx) {
+ zx_status_t status = ZX_OK;
+ if (ap_mvm_sta_ == nullptr) {
+ return ZX_ERR_BAD_STATE;
+ }
+ if ((status = ap_mvm_sta_->ChangeState(iwl_sta_state::IWL_STA_AUTHORIZED)) != ZX_OK) {
+ return status;
+ }
+ return mac_configure_assoc(mvmvif_, options, assoc_ctx);
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacClearAssoc(
+ uint32_t options, const uint8_t peer_addr_list[fuchsia_wlan_ieee80211_MAC_ADDR_LEN]) {
+ zx_status_t status = ZX_OK;
+
+ if (ap_mvm_sta_ == nullptr) {
+ return ZX_ERR_BAD_STATE;
+ }
+
+ // Mark the station is no longer associated. This must be set before we start operating on the STA
+ // instance.
+ mvmvif_->bss_conf.assoc = false;
+ ap_mvm_sta_.reset();
+
+ if ((status = mac_clear_assoc(mvmvif_, options, peer_addr_list)) != ZX_OK) {
+ return status;
+ }
+
+ return ZX_OK;
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacStartPassiveScan(
+ const wlan_softmac_passive_scan_args_t* passive_scan_args, uint64_t* out_scan_id) {
+ return mac_start_passive_scan(mvmvif_, passive_scan_args, out_scan_id);
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacStartActiveScan(
+ const wlan_softmac_active_scan_args_t* active_scan_args, uint64_t* out_scan_id) {
+ return mac_start_active_scan(mvmvif_, active_scan_args, out_scan_id);
+}
+
+zx_status_t WlanSoftmacDevice::WlanSoftmacUpdateWmmParams(wlan_ac_t ac,
+ const wlan_wmm_params_t* params) {
+ IWL_ERR(this, "%s() needs porting\n", __func__);
+ return ZX_ERR_NOT_SUPPORTED;
+}
+
+void WlanSoftmacDevice::DdkInit(ddk::InitTxn txn) {
+ txn.Reply(mac_init(mvmvif_, drvdata_, zxdev(), iface_id_));
+}
+
+void WlanSoftmacDevice::DdkRelease() {
+ IWL_DEBUG_INFO(this, "Releasing iwlwifi mac-device\n");
+ mac_release(mvmvif_);
+
+ delete this;
+}
+
+void WlanSoftmacDevice::DdkUnbind(ddk::UnbindTxn txn) {
+ IWL_DEBUG_INFO(this, "Unbinding iwlwifi mac-device\n");
+ mac_unbind(mvmvif_);
+ txn.Reply();
+}
+
+} // namespace wlan::iwlwifi
diff --git a/third_party/iwlwifi/platform/wlan-softmac-device.h b/third_party/iwlwifi/platform/wlan-softmac-device.h
new file mode 100644
index 0000000..5e9eeab
--- /dev/null
+++ b/third_party/iwlwifi/platform/wlan-softmac-device.h
@@ -0,0 +1,71 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_WLAN_SOFTMAC_DEVICE_H_
+#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_WLAN_SOFTMAC_DEVICE_H_
+
+#include <fuchsia/hardware/wlan/softmac/cpp/banjo.h>
+#include <fuchsia/wlan/ieee80211/c/banjo.h>
+#include <fuchsia/wlan/internal/cpp/banjo.h>
+#include <lib/ddk/device.h>
+
+#include <memory>
+
+#include <ddktl/device.h>
+
+struct iwl_mvm_vif;
+struct iwl_trans;
+
+namespace wlan::iwlwifi {
+
+class MvmSta;
+class WlanSoftmacDevice;
+
+class WlanSoftmacDevice
+ : public ddk::Device<WlanSoftmacDevice, ddk::Initializable, ddk::Unbindable>,
+ public ::ddk::WlanSoftmacProtocol<WlanSoftmacDevice, ::ddk::base_protocol> {
+ public:
+ WlanSoftmacDevice(zx_device* parent, iwl_trans* drvdata, uint16_t iface_id,
+ struct iwl_mvm_vif* mvmvif);
+ ~WlanSoftmacDevice();
+
+ void DdkInit(ddk::InitTxn txn);
+ void DdkRelease();
+ void DdkUnbind(ddk::UnbindTxn txn);
+
+ // WlanSoftmac interface implementation.
+ zx_status_t WlanSoftmacQuery(uint32_t options, wlan_softmac_info_t* out_info);
+ zx_status_t WlanSoftmacStart(const wlan_softmac_ifc_protocol_t* ifc,
+ zx::channel* out_mlme_channel);
+ void WlanSoftmacStop();
+ zx_status_t WlanSoftmacQueueTx(uint32_t options, const wlan_tx_packet_t* packet);
+ zx_status_t WlanSoftmacSetChannel(uint32_t options, const wlan_channel_t* channel);
+ zx_status_t WlanSoftmacConfigureBss(uint32_t options, const bss_config_t* config);
+ zx_status_t WlanSoftmacEnableBeaconing(uint32_t options, const wlan_bcn_config_t* bcn_cfg);
+ zx_status_t WlanSoftmacConfigureBeacon(uint32_t options, const wlan_tx_packet_t* pkt);
+ zx_status_t WlanSoftmacSetKey(uint32_t options, const wlan_key_config_t* key_config);
+ zx_status_t WlanSoftmacConfigureAssoc(uint32_t options, const wlan_assoc_ctx_t* assoc_ctx);
+ zx_status_t WlanSoftmacClearAssoc(
+ uint32_t options, const uint8_t peer_addr_list[fuchsia_wlan_ieee80211_MAC_ADDR_LEN]);
+ zx_status_t WlanSoftmacStartPassiveScan(const wlan_softmac_passive_scan_args_t* passive_scan_args,
+ uint64_t* out_scan_id);
+ zx_status_t WlanSoftmacStartActiveScan(const wlan_softmac_active_scan_args_t* active_scan_args,
+ uint64_t* out_scan_id);
+ zx_status_t WlanSoftmacUpdateWmmParams(wlan_ac_t ac, const wlan_wmm_params_t* params);
+
+ protected:
+ struct iwl_mvm_vif* mvmvif_;
+
+ private:
+ iwl_trans* drvdata_;
+ uint16_t iface_id_;
+
+ // Each peer on this interface will require a MvmSta instance. For now, as we only support client
+ // mode, we have only one peer (the AP), which simplifies things.
+ std::unique_ptr<MvmSta> ap_mvm_sta_;
+};
+
+} // namespace wlan::iwlwifi
+
+#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_WLAN_SOFTMAC_DEVICE_H_
diff --git a/third_party/iwlwifi/platform/wlanmac-device.cc b/third_party/iwlwifi/platform/wlanmac-device.cc
deleted file mode 100644
index f035e23..0000000
--- a/third_party/iwlwifi/platform/wlanmac-device.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2021 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/iwlwifi/platform/wlanmac-device.h"
-
-#include <zircon/status.h>
-
-#include <memory>
-
-extern "C" {
-#include "third_party/iwlwifi/mvm/mvm.h"
-} // extern "C"
-
-#include "third_party/iwlwifi/platform/mvm-mlme.h"
-
-namespace wlan::iwlwifi {
-
-zx_status_t WlanmacDevice::WlanmacQuery(uint32_t options, wlanmac_info_t* out_info) {
- return mac_query(mvmvif_, options, out_info);
-}
-
-zx_status_t WlanmacDevice::WlanmacStart(const wlanmac_ifc_protocol_t* ifc,
- zx::channel* out_mlme_channel) {
- return mac_start(mvmvif_, ifc, (zx_handle_t*)out_mlme_channel);
-}
-
-void WlanmacDevice::WlanmacStop() { mac_stop(mvmvif_); }
-
-zx_status_t WlanmacDevice::WlanmacQueueTx(uint32_t options, const wlan_tx_packet_t* packet) {
- return mac_queue_tx(mvmvif_, options, packet);
-}
-
-zx_status_t WlanmacDevice::WlanmacSetChannel(uint32_t options, const wlan_channel_t* channel) {
- return mac_set_channel(mvmvif_, options, channel);
-}
-
-zx_status_t WlanmacDevice::WlanmacConfigureBss(uint32_t options, const bss_config_t* config) {
- return mac_configure_bss(mvmvif_, options, config);
-}
-
-zx_status_t WlanmacDevice::WlanmacEnableBeaconing(uint32_t options,
- const wlan_bcn_config_t* bcn_cfg) {
- return mac_enable_beaconing(mvmvif_, options, bcn_cfg);
-}
-
-zx_status_t WlanmacDevice::WlanmacConfigureBeacon(uint32_t options, const wlan_tx_packet_t* pkt) {
- return mac_configure_beacon(mvmvif_, options, pkt);
-}
-
-zx_status_t WlanmacDevice::WlanmacSetKey(uint32_t options, const wlan_key_config_t* key_config) {
- return mac_set_key(mvmvif_, options, key_config);
-}
-
-zx_status_t WlanmacDevice::WlanmacConfigureAssoc(uint32_t options,
- const wlan_assoc_ctx_t* assoc_ctx) {
- return mac_configure_assoc(mvmvif_, options, assoc_ctx);
-}
-
-zx_status_t WlanmacDevice::WlanmacClearAssoc(
- uint32_t options, const uint8_t peer_addr_list[fuchsia_wlan_ieee80211_MAC_ADDR_LEN]) {
- return mac_clear_assoc(mvmvif_, options, peer_addr_list);
-}
-
-zx_status_t WlanmacDevice::WlanmacStartHwScan(const wlan_hw_scan_config_t* scan_config) {
- return mac_start_hw_scan(mvmvif_, scan_config);
-}
-
-zx_status_t WlanmacDevice::WlanmacUpdateWmmParams(wlan_ac_t ac, const wlan_wmm_params_t* params) {
- IWL_ERR(this, "%s() needs porting\n", __func__);
- return ZX_ERR_NOT_SUPPORTED;
-}
-
-void WlanmacDevice::DdkInit(ddk::InitTxn txn) {
- txn.Reply(mac_init(mvmvif_, drvdata_, zxdev(), iface_id_));
-}
-
-void WlanmacDevice::DdkRelease() {
- IWL_DEBUG_INFO(this, "Releasing iwlwifi mac-device\n");
- mac_release(mvmvif_);
-
- delete this;
-}
-
-void WlanmacDevice::DdkUnbind(ddk::UnbindTxn txn) {
- IWL_DEBUG_INFO(this, "Unbinding iwlwifi mac-device\n");
- mac_unbind(mvmvif_);
- txn.Reply();
-}
-
-} // namespace wlan::iwlwifi
diff --git a/third_party/iwlwifi/platform/wlanmac-device.h b/third_party/iwlwifi/platform/wlanmac-device.h
deleted file mode 100644
index 498228e..0000000
--- a/third_party/iwlwifi/platform/wlanmac-device.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2021 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <fuchsia/hardware/wlan/mac/cpp/banjo.h>
-#include <fuchsia/wlan/ieee80211/c/banjo.h>
-#include <fuchsia/wlan/internal/cpp/banjo.h>
-#include <lib/ddk/device.h>
-
-#include <ddktl/device.h>
-
-#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_WLANMAC_DEVICE_H_
-#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_WLANMAC_DEVICE_H_
-
-struct iwl_mvm_vif;
-struct iwl_trans;
-
-namespace wlan::iwlwifi {
-
-class WlanmacDevice;
-using WlanmacDeviceType = ddk::Device<WlanmacDevice, ddk::Initializable, ddk::Unbindable>;
-
-class WlanmacDevice : public WlanmacDeviceType,
- public ::ddk::WlanmacProtocol<WlanmacDevice, ::ddk::base_protocol> {
- public:
- WlanmacDevice(zx_device* parent, iwl_trans* drvdata, uint16_t iface_id,
- struct iwl_mvm_vif* mvmvif)
- : WlanmacDeviceType(parent), mvmvif_(mvmvif), drvdata_(drvdata), iface_id_(iface_id){}
- ~WlanmacDevice() = default;
-
- void DdkInit(ddk::InitTxn txn);
- void DdkRelease();
- void DdkUnbind(ddk::UnbindTxn txn);
-
- // Wlanmac interface implementation.
- zx_status_t WlanmacQuery(uint32_t options, wlanmac_info_t* out_info);
- zx_status_t WlanmacStart(const wlanmac_ifc_protocol_t* ifc, zx::channel* out_mlme_channel);
- void WlanmacStop();
- zx_status_t WlanmacQueueTx(uint32_t options, const wlan_tx_packet_t* packet);
- zx_status_t WlanmacSetChannel(uint32_t options, const wlan_channel_t* channel);
- zx_status_t WlanmacConfigureBss(uint32_t options, const bss_config_t* config);
- zx_status_t WlanmacEnableBeaconing(uint32_t options, const wlan_bcn_config_t* bcn_cfg);
- zx_status_t WlanmacConfigureBeacon(uint32_t options, const wlan_tx_packet_t* pkt);
- zx_status_t WlanmacSetKey(uint32_t options, const wlan_key_config_t* key_config);
- zx_status_t WlanmacConfigureAssoc(uint32_t options, const wlan_assoc_ctx_t* assoc_ctx);
- zx_status_t WlanmacClearAssoc(uint32_t options,
- const uint8_t peer_addr_list[fuchsia_wlan_ieee80211_MAC_ADDR_LEN]);
- zx_status_t WlanmacStartHwScan(const wlan_hw_scan_config_t* scan_config);
- zx_status_t WlanmacUpdateWmmParams(wlan_ac_t ac, const wlan_wmm_params_t* params);
-
- protected:
- struct iwl_mvm_vif* mvmvif_;
-
- private:
- iwl_trans* drvdata_;
- uint16_t iface_id_;
-};
-
-} // namespace wlan::iwlwifi
-
-#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_PLATFORM_WLANMAC_DEVICE_H_
diff --git a/third_party/iwlwifi/platform/wlanphy-impl-device.cc b/third_party/iwlwifi/platform/wlanphy-impl-device.cc
index d23adaa..51d575f 100644
--- a/third_party/iwlwifi/platform/wlanphy-impl-device.cc
+++ b/third_party/iwlwifi/platform/wlanphy-impl-device.cc
@@ -13,7 +13,7 @@
} // extern "C"
#include "third_party/iwlwifi/platform/mvm-mlme.h"
-#include "third_party/iwlwifi/platform/wlanmac-device.h"
+#include "third_party/iwlwifi/platform/wlan-softmac-device.h"
namespace wlan::iwlwifi {
@@ -24,8 +24,11 @@
void WlanphyImplDevice::DdkRelease() { delete this; }
-zx_status_t WlanphyImplDevice::WlanphyImplQuery(wlanphy_impl_info_t* out_info) {
- return phy_query(drvdata(), out_info);
+zx_status_t WlanphyImplDevice::WlanphyImplGetSupportedMacRoles(
+ wlan_mac_role_t out_supported_mac_roles_list[fuchsia_wlan_common_MAX_SUPPORTED_MAC_ROLES],
+ uint8_t* out_supported_mac_roles_count) {
+ return phy_get_supported_mac_roles(drvdata(), out_supported_mac_roles_list,
+ out_supported_mac_roles_count);
}
zx_status_t WlanphyImplDevice::WlanphyImplCreateIface(const wlanphy_impl_create_iface_req_t* req,
@@ -45,15 +48,15 @@
struct iwl_mvm* mvm = iwl_trans_get_mvm(drvdata());
struct iwl_mvm_vif* mvmvif = mvm->mvmvif[*out_iface_id];
- auto wlanmac_device =
- std::make_unique<WlanmacDevice>(zxdev(), drvdata(), *out_iface_id, mvmvif);
+ auto wlan_softmac_device =
+ std::make_unique<WlanSoftmacDevice>(parent(), drvdata(), *out_iface_id, mvmvif);
- if ((status = wlanmac_device->DdkAdd("iwlwifi-wlanmac")) != ZX_OK) {
+ if ((status = wlan_softmac_device->DdkAdd("iwlwifi-wlan-softmac")) != ZX_OK) {
IWL_ERR(this, "%s() failed mac device add: %s\n", __func__, zx_status_get_string(status));
phy_create_iface_undo(drvdata(), *out_iface_id);
return status;
}
- wlanmac_device.release();
+ wlan_softmac_device.release();
return ZX_OK;
}
diff --git a/third_party/iwlwifi/platform/wlanphy-impl-device.h b/third_party/iwlwifi/platform/wlanphy-impl-device.h
index ce390e6..fe4c8be 100644
--- a/third_party/iwlwifi/platform/wlanphy-impl-device.h
+++ b/third_party/iwlwifi/platform/wlanphy-impl-device.h
@@ -34,7 +34,9 @@
virtual const iwl_trans* drvdata() const = 0;
// WlanphyImpl interface implementation.
- zx_status_t WlanphyImplQuery(wlanphy_impl_info_t* out_info);
+ zx_status_t WlanphyImplGetSupportedMacRoles(
+ wlan_mac_role_t out_supported_mac_roles_list[fuchsia_wlan_common_MAX_SUPPORTED_MAC_ROLES],
+ uint8_t* out_supported_mac_roles_count);
zx_status_t WlanphyImplCreateIface(const wlanphy_impl_create_iface_req_t* req,
uint16_t* out_iface_id);
zx_status_t WlanphyImplDestroyIface(uint16_t iface_id);
diff --git a/third_party/iwlwifi/test/BUILD.gn b/third_party/iwlwifi/test/BUILD.gn
index 09adbe7..5758c53 100644
--- a/third_party/iwlwifi/test/BUILD.gn
+++ b/third_party/iwlwifi/test/BUILD.gn
@@ -13,12 +13,14 @@
source_set("sim_library") {
testonly = true
sources = [
- "fake-ucode-capa-test.cc",
+ "fake-ucode-test.cc",
"inspect-host-cmd.cc",
"inspect-host-cmd.h",
+ "sim-mcc-update.cc",
"sim-mvm.cc",
"sim-nvm-data.inc",
"sim-nvm.cc",
+ "sim-time-event.cc",
"sim-trans.cc",
"single-ap-test.cc",
"tlv-fw-builder.cc",
@@ -26,43 +28,40 @@
"wlan-pkt-builder.cc",
]
public = [
- "fake-ucode-capa-test.h",
+ "fake-ucode-test.h",
"mock-trans.h",
+ "sim-mcc-update.h",
"sim-mvm.h",
"sim-nvm.h",
+ "sim-time-event.h",
"sim-trans.h",
"sim.h",
"single-ap-test.h",
"wlan-pkt-builder.h",
]
deps = [
- "//sdk/banjo/fuchsia.hardware.wlan.mac:fuchsia.hardware.wlan.mac_banjo_cpp",
+ "//sdk/banjo/fuchsia.hardware.wlan.softmac:fuchsia.hardware.wlan.softmac_banjo_cpp",
"//sdk/banjo/fuchsia.hardware.wlanphyimpl:fuchsia.hardware.wlanphyimpl_banjo_cpp",
"//sdk/fidl/fuchsia.wlan.common:fuchsia.wlan.common_banjo_cpp",
- "//src/iwlwifi:core",
- "//src/iwlwifi/fw:api",
- "//src/iwlwifi/mvm",
- "//src/iwlwifi/platform:fuchsia_device",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/fw:api",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform:fuchsia_device",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform:rcu_manager",
"//src/devices/testing/fake-bti",
"//zircon/system/ulib/async-loop:async-loop-cpp",
"//zircon/system/ulib/async-loop:async-loop-default",
- "//zircon/system/ulib/fbl",
]
public_deps = [
- "//src/connectivity/wlan/drivers/testing/lib/sim-device",
- "//src/connectivity/wlan/drivers/testing/lib/sim-env",
- "//src/connectivity/wlan/drivers/testing/lib/sim-fake-ap",
- "//src/iwlwifi:core",
- "//src/iwlwifi/platform",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform",
+ "//src/connectivity/wlan/lib/common/cpp:common",
"//src/devices/pci/testing:pci-protocol-fake",
"//src/devices/testing/mock-ddk",
"//zircon/system/public",
"//zircon/system/ulib/zxtest",
]
public_configs = [ ":test_config" ]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
# Stub entrypoints for MVM.
@@ -71,7 +70,7 @@
sources = [ "stub-mvm.cc" ]
deps = [ "//zircon/system/public" ]
public_configs = [
- "//src/iwlwifi:fuchsia_config",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:fuchsia_config",
]
}
@@ -81,7 +80,7 @@
testonly = true
sources = [ "driver-inspector-test.cc" ]
deps = [
- "//src/iwlwifi/platform:driver_inspector",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform:driver_inspector",
"//zircon/system/ulib/inspect",
"//zircon/system/ulib/zxtest",
]
@@ -96,9 +95,6 @@
":sim_library",
"//zircon/system/ulib/zxtest",
]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
executable("fw_test") {
@@ -107,13 +103,10 @@
sources = [ "fw-test.cc" ]
deps = [
":sim_library",
- "//src/iwlwifi:core",
- "//src/iwlwifi/mvm",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
"//zircon/system/ulib/zxtest",
]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
executable("fw_dbg_test") {
@@ -122,14 +115,11 @@
sources = [ "fw-dbg-test.cc" ]
deps = [
":sim_library",
- "//src/iwlwifi/fw",
- "//src/iwlwifi/platform:driver_inspector",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/fw",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform:driver_inspector",
"//zircon/system/ulib/inspect",
"//zircon/system/ulib/zxtest",
]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
executable("iwl_phy_db_test") {
@@ -138,7 +128,7 @@
sources = [ "iwl-phy-db-test.cc" ]
deps = [
":stub_mvm",
- "//src/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
"//src/devices/testing/no_ddk",
"//zircon/system/ulib/zxtest",
]
@@ -150,14 +140,10 @@
sources = [ "mac80211-test.cc" ]
deps = [
":sim_library",
- "//src/iwlwifi/mvm",
- "//zircon/system/ulib/fbl",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
"//zircon/system/ulib/mock-function",
"//zircon/system/ulib/zxtest",
]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
executable("mac_ctxt_test") {
@@ -166,32 +152,9 @@
sources = [ "mac-ctxt-test.cc" ]
deps = [
":sim_library",
- "//src/iwlwifi/mvm",
- "//zircon/system/ulib/zircon-internal",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
"//zircon/system/ulib/zxtest",
]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
-}
-
-executable("mvm_mlme_test") {
- output_name = "mvm_mlme_test"
- testonly = true
- sources = [ "mvm-mlme-test.cc" ]
- deps = [
- ":sim_library",
- "//sdk/fidl/fuchsia.wlan.common:fuchsia.wlan.common_banjo_cpp",
- "//sdk/fidl/fuchsia.wlan.internal:fuchsia.wlan.internal_banjo_cpp",
- "//src/iwlwifi/mvm",
- "//src/iwlwifi/platform:fuchsia_device",
- "//zircon/system/public",
- "//zircon/system/ulib/mock-function",
- "//zircon/system/ulib/zxtest",
- ]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
# Test code for MVM features.
@@ -201,15 +164,11 @@
sources = [ "mvm-test.cc" ]
deps = [
":sim_library",
- "//src/iwlwifi/mvm",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
"//src/devices/testing/fake-bti",
"//zircon/system/ulib/mock-function",
- "//zircon/system/ulib/zircon-internal",
"//zircon/system/ulib/zxtest",
]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
executable("notif_wait_test") {
@@ -218,7 +177,7 @@
sources = [ "notif-wait-test.cc" ]
deps = [
":stub_mvm",
- "//src/iwlwifi/fw",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/fw",
"//src/devices/testing/no_ddk",
"//zircon/system/ulib/zxtest",
]
@@ -230,13 +189,10 @@
sources = [ "nvm-test.cc" ]
deps = [
":sim_library",
- "//src/iwlwifi:core",
- "//src/iwlwifi/mvm",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
"//zircon/system/ulib/zxtest",
]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
executable("pcie_test") {
@@ -245,10 +201,10 @@
sources = [ "pcie-test.cc" ]
deps = [
":sim_library",
- "//src/iwlwifi:core",
- "//src/iwlwifi/fw:api",
- "//src/iwlwifi/pcie",
- "//src/iwlwifi/platform:fuchsia_device",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/fw:api",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/pcie",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform:fuchsia_device",
"//src/devices/pci/testing:pci-protocol-fake",
"//src/devices/testing/fake-bti",
"//src/devices/testing/mock-ddk",
@@ -257,13 +213,9 @@
"//zircon/system/ulib/async-loop:async-loop-default",
"//zircon/system/ulib/mock-function",
"//zircon/system/ulib/sync",
- "//zircon/system/ulib/zircon-internal",
"//zircon/system/ulib/zx",
"//zircon/system/ulib/zxtest",
]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
executable("phy_ctxt_test") {
@@ -272,13 +224,9 @@
sources = [ "phy-ctxt-test.cc" ]
deps = [
":sim_library",
- "//src/iwlwifi/mvm",
- "//zircon/system/ulib/zircon-internal",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
"//zircon/system/ulib/zxtest",
]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
executable("platform_test") {
@@ -287,25 +235,34 @@
sources = [ "platform-test.cc" ]
deps = [
":stub_mvm",
- "//src/iwlwifi/platform",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform",
"//src/devices/testing/no_ddk",
"//zircon/system/ulib/zxtest",
]
}
+executable("rcu_manager_test") {
+ output_name = "rcu_manager_test"
+ testonly = true
+ sources = [ "rcu-manager-test.cc" ]
+ deps = [
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform:rcu_manager",
+ "//zircon/system/ulib/async-testing",
+ "//zircon/system/ulib/sync",
+ "//zircon/system/ulib/zxtest",
+ ]
+}
+
executable("sta_test") {
output_name = "sta_test"
testonly = true
sources = [ "sta-test.cc" ]
deps = [
":sim_library",
- "//src/iwlwifi/mvm",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
"//zircon/system/ulib/mock-function",
"//zircon/system/ulib/zxtest",
]
-
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
}
executable("task_test") {
@@ -314,7 +271,7 @@
sources = [ "task-test.cc" ]
deps = [
":stub_mvm",
- "//src/iwlwifi/platform",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform",
"//src/devices/testing/no_ddk",
"//zircon/system/public",
"//zircon/system/ulib/async-testing",
@@ -327,13 +284,45 @@
testonly = true
sources = [ "utils-test.cc" ]
deps = [
- "//src/iwlwifi/mvm",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
"//src/devices/testing/no_ddk",
"//zircon/system/ulib/zxtest",
]
+}
- # TODO(https://fxbug.dev/58162): delete the below and fix compiler warnings
- configs += [ "//build/config:Wno-conversion" ]
+executable("wlan_softmac_device_test") {
+ output_name = "wlan_softmac_device_test"
+ testonly = true
+ sources = [ "wlan-softmac-device-test.cc" ]
+ deps = [
+ ":sim_library",
+ "//sdk/banjo/fuchsia.hardware.wlan.associnfo:fuchsia.hardware.wlan.associnfo_banjo_cpp",
+ "//sdk/banjo/fuchsia.hardware.wlan.softmac:fuchsia.hardware.wlan.softmac_banjo_cpp",
+ "//sdk/fidl/fuchsia.wlan.ieee80211:fuchsia.wlan.ieee80211_llcpp",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform:fuchsia_device",
+ "//zircon/system/public",
+ "//zircon/system/ulib/mock-function",
+ "//zircon/system/ulib/mock-function",
+ "//zircon/system/ulib/zx",
+ "//zircon/system/ulib/zxtest",
+ ]
+}
+
+executable("wlanphy_impl_device_test") {
+ output_name = "wlanphy_impl_device_test"
+ testonly = true
+ sources = [ "wlanphy-impl-device-test.cc" ]
+ deps = [
+ ":sim_library",
+ "//sdk/fidl/fuchsia.wlan.common:fuchsia.wlan.common_banjo_cpp",
+ "//sdk/fidl/fuchsia.wlan.internal:fuchsia.wlan.internal_banjo_cpp",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/mvm",
+ "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi/platform:fuchsia_device",
+ "//zircon/system/public",
+ "//zircon/system/ulib/zxtest",
+ ]
}
_tests = [
@@ -344,16 +333,18 @@
"iwl_phy_db_test",
"mac80211_test",
"mac_ctxt_test",
- "mvm_mlme_test",
"mvm_test",
"notif_wait_test",
"nvm_test",
"pcie_test",
"phy_ctxt_test",
"platform_test",
+ "rcu_manager_test",
"sta_test",
"task_test",
"utils_test",
+ "wlan_softmac_device_test",
+ "wlanphy_impl_device_test",
]
foreach(test_name, _tests) {
diff --git a/third_party/iwlwifi/test/fake-ucode-capa-test.h b/third_party/iwlwifi/test/fake-ucode-capa-test.h
deleted file mode 100644
index 9468785..0000000
--- a/third_party/iwlwifi/test/fake-ucode-capa-test.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2021 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_FAKE_UCODE_CAPA_TEST_H_
-#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_FAKE_UCODE_CAPA_TEST_H_
-
-#include <memory>
-
-#include <zxtest/zxtest.h>
-
-#include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h"
-#include "third_party/iwlwifi/test/sim-trans.h"
-#include "src/devices/testing/mock-ddk/mock-device.h"
-
-namespace wlan::testing {
-
-// Helper class for unit test code to inherit in order to create an fake firmware with
-// customized ucode capability.
-//
-// Note that the contructor will call the init function of transportation layer,
-// and assert it is successful. The test case doesn't need to init again.
-//
-class FakeUcodeCapaTest : public ::zxtest::Test {
- public:
- // The constructor takes two parameters, they will be assigned to the two fields struct
- // iwl_ucode_capa, api_index indicates the offset of api_capa in iwl_ucode_capabilities._capa, the
- // value of api_index is usually 0 for 8265. api_capa is the 4-byte flag indicates the supported
- // ucode capabilities of this firmware.
- //
- // For how iwlwifi driver is parsing the ucode capabilities from firmware tlv binary, please refer
- // to iwl_set_ucode_capabilities() in iwlwifi/iwl-drv.c. For the value options of api_capa flags,
- // please refer to enum iwl_ucode_tlv_capa in iwlwifi/fw/file.h.
- FakeUcodeCapaTest(uint32_t api_index, uint32_t api_capa);
- ~FakeUcodeCapaTest() = default;
-
- protected:
- ::wlan::simulation::Environment dummy_env_;
- std::shared_ptr<MockDevice> fake_parent_;
- SimTransport sim_trans_;
-};
-
-} // namespace wlan::testing
-
-#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_FAKE_UCODE_CAPA_TEST_H_
diff --git a/third_party/iwlwifi/test/fake-ucode-capa-test.cc b/third_party/iwlwifi/test/fake-ucode-test.cc
similarity index 74%
rename from third_party/iwlwifi/test/fake-ucode-capa-test.cc
rename to third_party/iwlwifi/test/fake-ucode-test.cc
index 77af2e2..ede2857 100644
--- a/third_party/iwlwifi/test/fake-ucode-capa-test.cc
+++ b/third_party/iwlwifi/test/fake-ucode-test.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/iwlwifi/test/fake-ucode-capa-test.h"
+#include "third_party/iwlwifi/test/fake-ucode-test.h"
#include <zircon/assert.h>
#include <zircon/status.h>
@@ -15,8 +15,9 @@
namespace wlan::testing {
-FakeUcodeCapaTest::FakeUcodeCapaTest(uint32_t api_index, uint32_t api_capa)
- : fake_parent_(MockDevice::FakeRootParent()), sim_trans_(&dummy_env_, fake_parent_.get()) {
+FakeUcodeTest::FakeUcodeTest(uint32_t capa_index, uint32_t capa_val, uint32_t api_index,
+ uint32_t api_val)
+ : fake_parent_(MockDevice::FakeRootParent()), sim_trans_(fake_parent_.get()) {
// Add a default MVM firmware to the fake DDK.
TlvFwBuilder fw_builder;
@@ -27,10 +28,14 @@
fw_builder.AddValue(IWL_UCODE_TLV_INIT, &dummy_ucode, sizeof(dummy_ucode));
fw_builder.AddValue(IWL_UCODE_TLV_INIT_DATA, &dummy_ucode, sizeof(dummy_ucode));
- const struct iwl_ucode_capa ucode_capa = {.api_index = cpu_to_le32(api_index),
- .api_capa = cpu_to_le32(api_capa)};
+ const struct iwl_ucode_capa ucode_capa = {.api_index = cpu_to_le32(capa_index),
+ .api_capa = cpu_to_le32(capa_val)};
fw_builder.AddValue(IWL_UCODE_TLV_ENABLED_CAPABILITIES, &ucode_capa, sizeof(ucode_capa));
+ const struct iwl_ucode_api ucode_api = {.api_index = cpu_to_le32(api_index),
+ .api_flags = cpu_to_le32(api_val)};
+ fw_builder.AddValue(IWL_UCODE_TLV_API_CHANGES_SET, &ucode_api, sizeof(ucode_api));
+
const uint32_t ucode_phy_sku =
cpu_to_le32((3 << FW_PHY_CFG_TX_CHAIN_POS) | // Tx antenna 1 and 0.
(6 << FW_PHY_CFG_RX_CHAIN_POS)); // Rx antenna 2 and 1.
diff --git a/third_party/iwlwifi/test/fake-ucode-test.h b/third_party/iwlwifi/test/fake-ucode-test.h
new file mode 100644
index 0000000..73dbda7
--- /dev/null
+++ b/third_party/iwlwifi/test/fake-ucode-test.h
@@ -0,0 +1,45 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_FAKE_UCODE_TEST_H_
+#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_FAKE_UCODE_TEST_H_
+
+#include <memory>
+
+#include <zxtest/zxtest.h>
+
+#include "third_party/iwlwifi/test/sim-trans.h"
+#include "src/devices/testing/mock-ddk/mock-device.h"
+
+namespace wlan::testing {
+
+// Helper class for unit test code to inherit in order to create an fake firmware with
+// customized ucode capability.
+//
+// Note that the contructor will call the init function of transportation layer,
+// and assert it is successful. The test case doesn't need to init again.
+//
+class FakeUcodeTest : public ::zxtest::Test {
+ public:
+ // The constructor takes four parameters. They will be assigned to the API flags and capabilities.
+ // The *_index are the array index in iwl_ucode_capabilities._api[] and ._capa[]. The *_value are
+ // limited from 0 to 31. These 2 fields are used to present all values of IWL_UCODE_TLV_API_* and
+ // IWL_UCODE_TLV_CAPA_*.
+ //
+ // TODO(fxbug.dev/92106): support multiple bits.
+ //
+ // For how iwlwifi driver is parsing the ucode capabilities from firmware tlv binary, please refer
+ // to iwl_set_ucode_capabilities() in iwlwifi/iwl-drv.c. For the value options, please refer to
+ // enum iwl_ucode_tlv_capa and enum iwl_ucode_tlv_api in iwlwifi/fw/file.h.
+ FakeUcodeTest(uint32_t capa_index, uint32_t capa_val, uint32_t api_index, uint32_t api_val);
+ ~FakeUcodeTest() = default;
+
+ protected:
+ std::shared_ptr<MockDevice> fake_parent_;
+ SimTransport sim_trans_;
+};
+
+} // namespace wlan::testing
+
+#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_FAKE_UCODE_TEST_H_
diff --git a/third_party/iwlwifi/test/fw-test.cc b/third_party/iwlwifi/test/fw-test.cc
index 4cb7e11..044ae11 100644
--- a/third_party/iwlwifi/test/fw-test.cc
+++ b/third_party/iwlwifi/test/fw-test.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <iterator>
+
#include <zxtest/zxtest.h>
extern "C" {
@@ -41,7 +43,7 @@
FW_PAGING_SIZE * (NUM_OF_PAGE_PER_GROUP * (NUM_OF_PAGE_BLK - 1) + NUM_OF_PAGES_IN_LAST_BLK);
uint8_t arbitrary_data[PAGING_MEM_SIZE] = {};
for (size_t i = 0; i < sizeof(arbitrary_data); i++) {
- arbitrary_data[i] = i; // fill with arbitrary data for testing.
+ arbitrary_data[i] = static_cast<uint8_t>(i); // fill with arbitrary data for testing.
}
// About the sections, see iwl_fill_paging_mem().
@@ -84,7 +86,7 @@
// IWL_UCODE_INIT
{
.sec = sec,
- .num_sec = ARRAY_SIZE(sec),
+ .num_sec = std::size(sec),
.paging_mem_size = PAGING_MEM_SIZE,
},
diff --git a/third_party/iwlwifi/test/inspect-host-cmd.cc b/third_party/iwlwifi/test/inspect-host-cmd.cc
index 661a92b..6eee771 100644
--- a/third_party/iwlwifi/test/inspect-host-cmd.cc
+++ b/third_party/iwlwifi/test/inspect-host-cmd.cc
@@ -10,11 +10,11 @@
#include <stdio.h>
#include <zircon/syscalls.h>
+#include <cstdio>
+#include <iterator>
#include <sstream>
#include <string>
-#include <fbl/string_printf.h>
-
#define INSPECT_BUFSIZ 512
// Given a 'bitmap_value' and an array of bit definition, this function returns a joined string
@@ -50,19 +50,18 @@
"dup",
};
- std::string out(
- fbl::StringPrintf("host_cmd id[0x%02x] flags[0x%x:%s]\n", cmd->id, cmd->flags,
- join_bitmap_string(flags_defs, ARRAY_SIZE(flags_defs), cmd->flags).c_str())
- .c_str());
+ constexpr size_t kMaxStrBufSize = 1024;
+ char strbuf[kMaxStrBufSize];
+ std::snprintf(strbuf, kMaxStrBufSize, "host_cmd id[0x%02x] flags[0x%x:%s]\n", cmd->id, cmd->flags,
+ join_bitmap_string(flags_defs, std::size(flags_defs), cmd->flags).c_str());
+ std::string out(strbuf);
- for (size_t i = 0; i < ARRAY_SIZE(cmd->len); i++) {
- out +=
- std::string(fbl::StringPrintf(" [%zu] dataflags[0x%x:%s] len[%d]\n", i, cmd->dataflags[i],
- join_bitmap_string(dataflags_defs, ARRAY_SIZE(dataflags_defs),
- cmd->dataflags[i])
- .c_str(),
- cmd->len[i])
- .c_str());
+ for (size_t i = 0; i < std::size(cmd->len); i++) {
+ std::snprintf(
+ strbuf, kMaxStrBufSize, " [%zu] dataflags[0x%x:%s] len[%d]\n", i, cmd->dataflags[i],
+ join_bitmap_string(dataflags_defs, std::size(dataflags_defs), cmd->dataflags[i]).c_str(),
+ cmd->len[i]);
+ out += std::string(strbuf);
}
return out;
diff --git a/third_party/iwlwifi/test/mac-ctxt-test.cc b/third_party/iwlwifi/test/mac-ctxt-test.cc
index 279eb23..d5ae86a 100644
--- a/third_party/iwlwifi/test/mac-ctxt-test.cc
+++ b/third_party/iwlwifi/test/mac-ctxt-test.cc
@@ -4,7 +4,7 @@
// Used to test mvm/mac-ctxt.c
-#include <lib/zircon-internal/thread_annotations.h>
+#include <zircon/compiler.h>
#include <zxtest/zxtest.h>
@@ -19,11 +19,11 @@
class MacContextTest : public SingleApTest {
public:
- MacContextTest() TA_NO_THREAD_SAFETY_ANALYSIS {
+ MacContextTest() __TA_NO_THREAD_SAFETY_ANALYSIS {
mvm_ = iwl_trans_get_mvm(sim_trans_.iwl_trans());
mtx_lock(&mvm_->mutex);
}
- ~MacContextTest() TA_NO_THREAD_SAFETY_ANALYSIS { mtx_unlock(&mvm_->mutex); }
+ ~MacContextTest() __TA_NO_THREAD_SAFETY_ANALYSIS { mtx_unlock(&mvm_->mutex); }
protected:
struct iwl_mvm* mvm_;
@@ -32,7 +32,7 @@
TEST_F(MacContextTest, Init) {
struct iwl_mvm_vif mvmvif = {
.mvm = mvm_,
- .mac_role = WLAN_INFO_MAC_ROLE_CLIENT,
+ .mac_role = WLAN_MAC_ROLE_CLIENT,
};
ASSERT_OK(iwl_mvm_mac_ctxt_init(&mvmvif));
@@ -41,7 +41,7 @@
TEST_F(MacContextTest, AddModifyRemove) {
struct iwl_mvm_vif mvmvif = {
.mvm = mvm_,
- .mac_role = WLAN_INFO_MAC_ROLE_CLIENT,
+ .mac_role = WLAN_MAC_ROLE_CLIENT,
};
ASSERT_OK(iwl_mvm_mac_ctxt_init(&mvmvif));
diff --git a/third_party/iwlwifi/test/mac80211-test.cc b/third_party/iwlwifi/test/mac80211-test.cc
index d0e5b58..9145b6a 100644
--- a/third_party/iwlwifi/test/mac80211-test.cc
+++ b/third_party/iwlwifi/test/mac80211-test.cc
@@ -5,6 +5,9 @@
// Used to test mvm/mac80211.c
#include <lib/mock-function/mock-function.h>
+#include <zircon/compiler.h>
+
+#include <iterator>
#include <zxtest/zxtest.h>
@@ -12,25 +15,19 @@
#include "third_party/iwlwifi/mvm/mvm.h"
}
+#include "third_party/iwlwifi/test/fake-ucode-test.h"
#include "third_party/iwlwifi/test/mock-trans.h"
#include "third_party/iwlwifi/test/single-ap-test.h"
-#include "zircon/system/ulib/fbl/include/fbl/auto_lock.h"
namespace wlan::testing {
namespace {
-class Mac80211Test : public SingleApTest {
+class ClientInterfaceHelper {
public:
- Mac80211Test() { mvm_ = iwl_trans_get_mvm(sim_trans_.iwl_trans()); }
- ~Mac80211Test() {
- mtx_lock(&mvm_->mutex);
- iwl_mvm_unbind_mvmvif(mvm_, mvmvif_idx_);
- mtx_unlock(&mvm_->mutex);
- }
+ ClientInterfaceHelper(SimTransport* sim_trans) : mvmvif_{}, ap_sta_{}, txqs_ {}
+ {
+ mvm_ = iwl_trans_get_mvm(sim_trans->iwl_trans());
- protected:
- // A helper function to create a client interface to be used in the test case.
- void ClientInterfaceHelper() {
// First find a free slot for the interface.
mtx_lock(&mvm_->mutex);
EXPECT_EQ(ZX_OK, iwl_mvm_find_free_mvmvif_slot(mvm_, &mvmvif_idx_));
@@ -39,7 +36,7 @@
// Initialize the interface data and add it to the mvm.
mvmvif_.mvm = mvm_;
- mvmvif_.mac_role = WLAN_INFO_MAC_ROLE_CLIENT;
+ mvmvif_.mac_role = WLAN_MAC_ROLE_CLIENT;
mvmvif_.bss_conf.beacon_int = 16;
iwl_mvm_mac_add_interface(&mvmvif_);
@@ -53,16 +50,30 @@
mvmvif_.phy_ctxt = &mvm_->phy_ctxts[phy_ctxt_id];
// Assign the AP sta info.
- ASSERT_EQ(IEEE80211_TIDS_MAX + 1, ARRAY_SIZE(ap_sta_.txq));
- for (size_t i = 0; i < ARRAY_SIZE(ap_sta_.txq); i++) {
+ ASSERT_EQ(IEEE80211_TIDS_MAX + 1, std::size(ap_sta_.txq));
+ for (size_t i = 0; i < std::size(ap_sta_.txq); i++) {
ap_sta_.txq[i] = &txqs_[i];
}
ASSERT_EQ(ZX_OK, iwl_mvm_mac_sta_state(&mvmvif_, &ap_sta_, IWL_STA_NOTEXIST, IWL_STA_NONE));
// Set it to associated.
- mvm_->fw_id_to_mac_id[0]->sta_state = IWL_STA_AUTHORIZED;
+ mvmvif_.bss_conf.assoc = true;
}
+ ~ClientInterfaceHelper() {
+ mtx_lock(&mvm_->mutex);
+ iwl_mvm_unbind_mvmvif(mvm_, mvmvif_idx_);
+ mtx_unlock(&mvm_->mutex);
+ }
+
+ struct iwl_mvm* mvm() {
+ return mvm_;
+ }
+ struct iwl_mvm_vif* mvmvif() {
+ return &mvmvif_;
+ }
+
+ private:
struct iwl_mvm* mvm_;
// for ClientInterfaceHelper().
struct iwl_mvm_vif mvmvif_;
@@ -71,11 +82,32 @@
struct iwl_mvm_txq txqs_[IEEE80211_TIDS_MAX + 1];
};
+class Mac80211Test : public SingleApTest {
+ public:
+ Mac80211Test() : mvm_(iwl_trans_get_mvm(sim_trans_.iwl_trans())) {}
+ ~Mac80211Test() {}
+
+ protected:
+ struct iwl_mvm* mvm_;
+};
+
+class Mac80211UcodeTest : public FakeUcodeTest {
+ public:
+ Mac80211UcodeTest()
+ : FakeUcodeTest(0, BIT(IWL_UCODE_TLV_CAPA_LAR_SUPPORT), 0,
+ BIT(IWL_UCODE_TLV_API_WIFI_MCC_UPDATE)),
+ mvm_(iwl_trans_get_mvm(sim_trans_.iwl_trans())) {}
+ ~Mac80211UcodeTest() {}
+
+ protected:
+ struct iwl_mvm* mvm_;
+};
+
// Normal case: add an interface, then delete it.
TEST_F(Mac80211Test, AddThenRemove) {
struct iwl_mvm_vif mvmvif = {
.mvm = mvm_,
- .mac_role = WLAN_INFO_MAC_ROLE_CLIENT,
+ .mac_role = WLAN_MAC_ROLE_CLIENT,
};
ASSERT_OK(iwl_mvm_mac_add_interface(&mvmvif));
@@ -100,19 +132,19 @@
struct iwl_mvm_vif mvmvif[] = {
{
.mvm = mvm_,
- .mac_role = WLAN_INFO_MAC_ROLE_CLIENT,
+ .mac_role = WLAN_MAC_ROLE_CLIENT,
},
{
.mvm = mvm_,
- .mac_role = WLAN_INFO_MAC_ROLE_CLIENT,
+ .mac_role = WLAN_MAC_ROLE_CLIENT,
},
{
.mvm = mvm_,
- .mac_role = WLAN_INFO_MAC_ROLE_CLIENT,
+ .mac_role = WLAN_MAC_ROLE_CLIENT,
},
};
- size_t mvmvif_count = ARRAY_SIZE(mvmvif);
+ size_t mvmvif_count = std::size(mvmvif);
for (size_t i = 0; i < mvmvif_count; ++i) {
ASSERT_OK(iwl_mvm_mac_add_interface(&mvmvif[i]));
@@ -178,13 +210,13 @@
// Test the normal usage.
//
-TEST_F(Mac80211Test, MvmSlotNormalCase) {
- fbl::AutoLock auto_lock(&mvm_->mutex);
+TEST_F(Mac80211Test, MvmSlotNormalCase) __TA_NO_THREAD_SAFETY_ANALYSIS {
int index;
struct iwl_mvm_vif mvmvif = {}; // an instance to bind
zx_status_t ret;
// Fill up all mvmvif slots and expect okay
+ mtx_lock(&mvm_->mutex);
for (size_t i = 0; i < MAX_NUM_MVMVIF; i++) {
ret = iwl_mvm_find_free_mvmvif_slot(mvm_, &index);
ASSERT_EQ(ret, ZX_OK);
@@ -202,12 +234,12 @@
// One more is not accepted.
ret = iwl_mvm_find_free_mvmvif_slot(mvm_, &index);
ASSERT_EQ(ret, ZX_ERR_NO_RESOURCES);
+ mtx_unlock(&mvm_->mutex);
}
// Bind / unbind test.
//
-TEST_F(Mac80211Test, MvmSlotBindUnbind) {
- fbl::AutoLock auto_lock(&mvm_->mutex);
+TEST_F(Mac80211Test, MvmSlotBindUnbind) __TA_NO_THREAD_SAFETY_ANALYSIS {
int index;
struct iwl_mvm_vif mvmvif = {}; // an instance to bind
zx_status_t ret;
@@ -216,6 +248,7 @@
ASSERT_EQ(MAX_NUM_MVMVIF, 4);
// First occupy the index 0, 1, 3.
+ mtx_lock(&mvm_->mutex);
ret = iwl_mvm_bind_mvmvif(mvm_, 0, &mvmvif);
ASSERT_EQ(ret, ZX_OK);
ret = iwl_mvm_bind_mvmvif(mvm_, 1, &mvmvif);
@@ -241,12 +274,15 @@
ret = iwl_mvm_find_free_mvmvif_slot(mvm_, &index);
ASSERT_EQ(ret, ZX_OK);
ASSERT_EQ(index, 1);
+ mtx_unlock(&mvm_->mutex);
}
-class McastFilterTest : public Mac80211Test, public MockTrans {
+class McastFilterTestWithoutIface : public Mac80211Test, public MockTrans {
public:
- McastFilterTest() { BIND_TEST(mvm_->trans); }
- ~McastFilterTest() { mock_send_cmd_.VerifyAndClear(); }
+ McastFilterTestWithoutIface() : mvm_(iwl_trans_get_mvm(sim_trans_.iwl_trans())) {
+ BIND_TEST(mvm_->trans);
+ }
+ ~McastFilterTestWithoutIface() { mock_send_cmd_.VerifyAndClear(); }
// The values we expect. We only test few arbitrary bytes in 'addr_list' .
//
@@ -264,17 +300,27 @@
static zx_status_t send_cmd_wrapper(struct iwl_trans* trans, struct iwl_host_cmd* hcmd) {
auto mcast_cmd = reinterpret_cast<const struct iwl_mcast_filter_cmd*>(hcmd->data[0]);
- auto test = GET_TEST(McastFilterTest, trans);
+ auto test = GET_TEST(McastFilterTestWithoutIface, trans);
return test->mock_send_cmd_.Call(hcmd->id, mcast_cmd->port_id, mcast_cmd->count,
mcast_cmd->bssid[0], mcast_cmd->addr_list[0 * ETH_ALEN + 0],
mcast_cmd->addr_list[1 * ETH_ALEN + 5],
mcast_cmd->addr_list[2 * ETH_ALEN + 2]);
}
+
+ protected:
+ struct iwl_mvm* mvm_;
+};
+
+class McastFilterTest : public McastFilterTestWithoutIface {
+ public:
+ McastFilterTest() : helper_(ClientInterfaceHelper(&sim_trans_)) {}
+ ~McastFilterTest() {}
+
+ protected:
+ ClientInterfaceHelper helper_;
};
TEST_F(McastFilterTest, McastFilterNormal) {
- ClientInterfaceHelper();
-
// mock function after the testing environment had been set.
bindSendCmd(send_cmd_wrapper);
@@ -294,7 +340,7 @@
unbindSendCmd();
}
-TEST_F(McastFilterTest, McastFilterNoActiveInterface) {
+TEST_F(McastFilterTestWithoutIface, McastFilterNoActiveInterface) {
// mock function after the testing environment had been set.
bindSendCmd(send_cmd_wrapper);
@@ -306,8 +352,7 @@
}
TEST_F(McastFilterTest, McastFilterAp) {
- ClientInterfaceHelper();
- mvmvif_.mac_role = WLAN_INFO_MAC_ROLE_AP; // overwrite to AP.
+ helper_.mvmvif()->mac_role = WLAN_MAC_ROLE_AP; // overwrite to AP.
// mock function after the testing environment had been set.
bindSendCmd(send_cmd_wrapper);
@@ -318,5 +363,42 @@
unbindSendCmd();
}
+class RegulatoryTest : public Mac80211UcodeTest {
+ public:
+ RegulatoryTest() {}
+ ~RegulatoryTest() {}
+};
+
+TEST_F(RegulatoryTest, RegulatoryTestNormal) {
+ ClientInterfaceHelper helper = ClientInterfaceHelper(&sim_trans_);
+
+ bool changed;
+ wlanphy_country_t country;
+ mtx_lock(&mvm_->mutex);
+ EXPECT_EQ(ZX_OK, iwl_mvm_get_regdomain(mvm_, "TW", MCC_SOURCE_WIFI, &changed, &country));
+ mtx_unlock(&mvm_->mutex);
+
+ EXPECT_EQ(true, changed);
+ EXPECT_EQ(0x54, country.alpha2[0]);
+ EXPECT_EQ(0x57, country.alpha2[1]);
+ EXPECT_EQ(true, mvm_->lar_regdom_set);
+ EXPECT_EQ(MCC_SOURCE_WIFI, mvm_->mcc_src);
+}
+
+TEST_F(RegulatoryTest, TestGetCurrentRegDomain) {
+ ClientInterfaceHelper helper = ClientInterfaceHelper(&sim_trans_);
+
+ bool changed;
+ wlanphy_country_t country = {};
+ mtx_lock(&mvm_->mutex);
+ EXPECT_EQ(ZX_OK, iwl_mvm_get_current_regdomain(mvm_, &changed, &country));
+ mtx_unlock(&mvm_->mutex);
+
+ EXPECT_EQ(true, changed);
+ EXPECT_EQ(0x5a, country.alpha2[0]); // Becomes 'ZZ' now.
+ EXPECT_EQ(0x5a, country.alpha2[1]);
+ EXPECT_EQ(MCC_SOURCE_GET_CURRENT, mvm_->mcc_src);
+}
+
} // namespace
} // namespace wlan::testing
diff --git a/third_party/iwlwifi/test/mvm-mlme-test.cc b/third_party/iwlwifi/test/mvm-mlme-test.cc
deleted file mode 100644
index 3f6f250..0000000
--- a/third_party/iwlwifi/test/mvm-mlme-test.cc
+++ /dev/null
@@ -1,894 +0,0 @@
-// Copyright 2021 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// To test PHY and MAC device callback functions.
-
-#include <fuchsia/wlan/common/cpp/banjo.h>
-#include <fuchsia/wlan/ieee80211/c/banjo.h>
-#include <fuchsia/wlan/internal/cpp/banjo.h>
-#include <lib/mock-function/mock-function.h>
-#include <zircon/listnode.h>
-#include <zircon/syscalls.h>
-
-#include <list>
-
-#include <zxtest/zxtest.h>
-
-extern "C" {
-#include "third_party/iwlwifi/mvm/mvm.h"
-}
-
-#include "third_party/iwlwifi/platform/ieee80211.h"
-#include "third_party/iwlwifi/platform/mvm-mlme.h"
-#include "third_party/iwlwifi/platform/wlanphy-impl-device.h"
-#include "third_party/iwlwifi/test/mock-trans.h"
-#include "third_party/iwlwifi/test/single-ap-test.h"
-#include "third_party/iwlwifi/test/wlan-pkt-builder.h"
-
-namespace wlan::testing {
-namespace {
-
-static constexpr size_t kListenInterval = 100;
-
-typedef mock_function::MockFunction<void, void*, uint32_t, const void*, size_t,
- const wlan_rx_info_t*>
- recv_cb_t;
-
-// The wrapper used by wlanmac_ifc_t.recv() to call mock-up.
-void recv_wrapper(void* cookie, uint32_t flags, const uint8_t* data, size_t length,
- const wlan_rx_info_t* info) {
- auto recv = reinterpret_cast<recv_cb_t*>(cookie);
- recv->Call(cookie, flags, data, length, info);
-}
-
-class WlanDeviceTest : public SingleApTest {
- public:
- WlanDeviceTest()
- : mvmvif_sta_{
- .mvm = iwl_trans_get_mvm(sim_trans_.iwl_trans()),
- .mac_role = WLAN_INFO_MAC_ROLE_CLIENT,
- .bss_conf =
- {
- .beacon_int = kListenInterval,
- },
- } {
- device_ = sim_trans_.sim_device();
- }
- ~WlanDeviceTest() {}
-
- protected:
- static constexpr zx_handle_t mlme_channel_ =
- 73939133; // An arbitrary value not ZX_HANDLE_INVALID
- static constexpr uint8_t kInvalidBandIdFillByte = 0xa5;
- static constexpr wlan_info_band_t kInvalidBandId = 0xa5a5a5a5;
- struct iwl_mvm_vif mvmvif_sta_; // The mvm_vif settings for station role.
- wlan::iwlwifi::WlanphyImplDevice* device_;
-};
-
-//////////////////////////////////// Helper Functions /////////////////////////////////////////////
-TEST_F(WlanDeviceTest, ComposeBandList) {
- struct iwl_nvm_data nvm_data;
- wlan_info_band_t bands[WLAN_INFO_BAND_COUNT];
-
- // nothing enabled
- memset(&nvm_data, 0, sizeof(nvm_data));
- memset(bands, kInvalidBandIdFillByte, sizeof(bands));
- EXPECT_EQ(0, compose_band_list(&nvm_data, bands));
- EXPECT_EQ(kInvalidBandId, bands[0]);
- EXPECT_EQ(kInvalidBandId, bands[1]);
-
- // 2.4GHz only
- memset(&nvm_data, 0, sizeof(nvm_data));
- memset(bands, kInvalidBandIdFillByte, sizeof(bands));
- nvm_data.sku_cap_band_24ghz_enable = true;
- EXPECT_EQ(1, compose_band_list(&nvm_data, bands));
- EXPECT_EQ(WLAN_INFO_BAND_2GHZ, bands[0]);
- EXPECT_EQ(kInvalidBandId, bands[1]);
-
- // 5GHz only
- memset(&nvm_data, 0, sizeof(nvm_data));
- memset(bands, kInvalidBandIdFillByte, sizeof(bands));
- nvm_data.sku_cap_band_52ghz_enable = true;
- EXPECT_EQ(1, compose_band_list(&nvm_data, bands));
- EXPECT_EQ(WLAN_INFO_BAND_5GHZ, bands[0]);
- EXPECT_EQ(kInvalidBandId, bands[1]);
-
- // both bands enabled
- memset(&nvm_data, 0, sizeof(nvm_data));
- memset(bands, kInvalidBandIdFillByte, sizeof(bands));
- nvm_data.sku_cap_band_24ghz_enable = true;
- nvm_data.sku_cap_band_52ghz_enable = true;
- EXPECT_EQ(2, compose_band_list(&nvm_data, bands));
- EXPECT_EQ(WLAN_INFO_BAND_2GHZ, bands[0]);
- EXPECT_EQ(WLAN_INFO_BAND_5GHZ, bands[1]);
-}
-
-// Short-cut to access the iwl_cfg80211_rates[] structure and convert it to 802.11 rate.
-//
-// Args:
-// index: the index of iwl_cfg80211_rates[].
-//
-// Returns:
-// the 802.11 rate.
-//
-static unsigned expected_rate(size_t index) {
- return cfg_rates_to_80211(iwl_cfg80211_rates[index]);
-}
-
-TEST_F(WlanDeviceTest, FillBandInfos) {
- // The default 'nvm_data' is loaded from test/sim-default-nvm.cc.
-
- wlan_info_band_t bands[WLAN_INFO_BAND_COUNT] = {
- WLAN_INFO_BAND_2GHZ,
- WLAN_INFO_BAND_5GHZ,
- };
- wlan_info_band_info_t band_infos[WLAN_INFO_BAND_COUNT] = {};
-
- fill_band_infos(iwl_trans_get_mvm(sim_trans_.iwl_trans())->nvm_data, bands, ARRAY_SIZE(bands),
- band_infos);
- // 2.4Ghz
- wlan_info_band_info_t* exp_band_info = &band_infos[0];
- EXPECT_EQ(WLAN_INFO_BAND_2GHZ, exp_band_info->band);
- EXPECT_EQ(true, exp_band_info->ht_supported);
- EXPECT_EQ(expected_rate(0), exp_band_info->rates[0]); // 1Mbps
- EXPECT_EQ(expected_rate(11), exp_band_info->rates[11]); // 54Mbps
- EXPECT_EQ(2407, exp_band_info->supported_channels.base_freq);
- EXPECT_EQ(1, exp_band_info->supported_channels.channels[0]);
- EXPECT_EQ(13, exp_band_info->supported_channels.channels[12]);
- // 5GHz
- exp_band_info = &band_infos[1];
- EXPECT_EQ(WLAN_INFO_BAND_5GHZ, exp_band_info->band);
- EXPECT_EQ(true, exp_band_info->ht_supported);
- EXPECT_EQ(expected_rate(4), exp_band_info->rates[0]); // 6Mbps
- EXPECT_EQ(expected_rate(11), exp_band_info->rates[7]); // 54Mbps
- EXPECT_EQ(5000, exp_band_info->supported_channels.base_freq);
- EXPECT_EQ(36, exp_band_info->supported_channels.channels[0]);
- EXPECT_EQ(165, exp_band_info->supported_channels.channels[24]);
-}
-
-TEST_F(WlanDeviceTest, FillBandInfosOnly5GHz) {
- // The default 'nvm_data' is loaded from test/sim-default-nvm.cc.
-
- wlan_info_band_t bands[WLAN_INFO_BAND_COUNT] = {
- WLAN_INFO_BAND_5GHZ,
- 0,
- };
- wlan_info_band_info_t band_infos[WLAN_INFO_BAND_COUNT] = {};
-
- fill_band_infos(iwl_trans_get_mvm(sim_trans_.iwl_trans())->nvm_data, bands, 1, band_infos);
- // 5GHz
- wlan_info_band_info_t* exp_band_info = &band_infos[0];
- EXPECT_EQ(WLAN_INFO_BAND_5GHZ, exp_band_info->band);
- EXPECT_EQ(true, exp_band_info->ht_supported);
- EXPECT_EQ(expected_rate(4), exp_band_info->rates[0]); // 6Mbps
- EXPECT_EQ(expected_rate(11), exp_band_info->rates[7]); // 54Mbps
- EXPECT_EQ(5000, exp_band_info->supported_channels.base_freq);
- EXPECT_EQ(36, exp_band_info->supported_channels.channels[0]);
- EXPECT_EQ(165, exp_band_info->supported_channels.channels[24]);
- // index 1 should be empty.
- exp_band_info = &band_infos[1];
- EXPECT_EQ(false, exp_band_info->ht_supported);
- EXPECT_EQ(0x00, exp_band_info->rates[0]);
- EXPECT_EQ(0x00, exp_band_info->rates[7]);
- EXPECT_EQ(0, exp_band_info->supported_channels.channels[0]);
-}
-
-///////////////////////////////////// MAC //////////////////////////////////////////////
-
-TEST_F(WlanDeviceTest, MacQuery) {
- // Test input null pointers
- uint32_t options = 0;
- void* whatever = &options;
- ASSERT_EQ(ZX_ERR_INVALID_ARGS, wlanmac_ops.query(nullptr, options, nullptr));
- ASSERT_EQ(ZX_ERR_INVALID_ARGS, wlanmac_ops.query(whatever, options, nullptr));
- ASSERT_EQ(ZX_ERR_INVALID_ARGS,
- wlanmac_ops.query(nullptr, options, reinterpret_cast<wlanmac_info*>(whatever)));
-
- wlanmac_info_t info = {};
- ASSERT_EQ(ZX_OK, wlanmac_ops.query(&mvmvif_sta_, options, &info));
- EXPECT_EQ(WLAN_INFO_MAC_ROLE_CLIENT, info.mac_role);
-
- //
- // The below code assumes the test/sim-default-nvm.cc contains 2 bands.
- //
- // .bands[0]: WLAN_INFO_BAND_2GHZ
- // .bands[1]: WLAN_INFO_BAND_5GHZ
- //
- ASSERT_EQ(2, info.bands_count);
- EXPECT_EQ(expected_rate(0), info.bands[0].rates[0]); // 1 Mbps
- EXPECT_EQ(expected_rate(7), info.bands[0].rates[7]); // 18 Mbps
- EXPECT_EQ(expected_rate(11), info.bands[0].rates[11]); // 54 Mbps
- EXPECT_EQ(expected_rate(4), info.bands[1].rates[0]); // 6 Mbps
- EXPECT_EQ(165, info.bands[1].supported_channels.channels[24]);
-}
-
-TEST_F(WlanDeviceTest, MacStart) {
- // Test input null pointers
- wlanmac_ifc_protocol_ops_t proto_ops = {
- .recv = recv_wrapper,
- };
- wlanmac_ifc_protocol_t ifc = {.ops = &proto_ops};
- zx_handle_t mlme_channel;
- ASSERT_EQ(wlanmac_ops.start(nullptr, &ifc, &mlme_channel), ZX_ERR_INVALID_ARGS);
- ASSERT_EQ(wlanmac_ops.start(&mvmvif_sta_, nullptr, &mlme_channel), ZX_ERR_INVALID_ARGS);
- ASSERT_EQ(wlanmac_ops.start(&mvmvif_sta_, &ifc, nullptr), ZX_ERR_INVALID_ARGS);
-
- // Test callback function
- recv_cb_t mock_recv; // To mock up the wlanmac_ifc_t.recv().
- mvmvif_sta_.mlme_channel = mlme_channel_;
- ASSERT_EQ(wlanmac_ops.start(&mvmvif_sta_, &ifc, &mlme_channel), ZX_OK);
- // Expect the above line would copy the 'ifc'. Then set expectation below and fire test.
- mock_recv.ExpectCall(&mock_recv, 0, nullptr, 0, nullptr);
- mvmvif_sta_.ifc.ops->recv(&mock_recv, 0, nullptr, 0, nullptr);
- mock_recv.VerifyAndClear();
-}
-
-TEST_F(WlanDeviceTest, MacStartSmeChannel) {
- // The normal case. A channel will be transferred to MLME.
- constexpr zx_handle_t from_devmgr = mlme_channel_;
- mvmvif_sta_.mlme_channel = from_devmgr;
- wlanmac_ifc_protocol_ops_t proto_ops = {
- .recv = recv_wrapper,
- };
- wlanmac_ifc_protocol_t ifc = {.ops = &proto_ops};
- zx_handle_t mlme_channel;
- ASSERT_EQ(wlanmac_ops.start(&mvmvif_sta_, &ifc, &mlme_channel), ZX_OK);
- ASSERT_EQ(mlme_channel, from_devmgr); // The channel handle is returned.
- ASSERT_EQ(mvmvif_sta_.mlme_channel, ZX_HANDLE_INVALID); // Driver no longer holds the ownership.
-
- // Since the driver no longer owns the handle, the start should fail.
- ASSERT_EQ(wlanmac_ops.start(&mvmvif_sta_, &ifc, &mlme_channel), ZX_ERR_ALREADY_BOUND);
-}
-
-TEST_F(WlanDeviceTest, MacRelease) {
- // Allocate an instance so that we can free that in mac_release().
- struct iwl_mvm_vif* mvmvif =
- reinterpret_cast<struct iwl_mvm_vif*>(calloc(1, sizeof(struct iwl_mvm_vif)));
-
- // Create a channel. Let this test case holds one end while driver holds the other end.
- char dummy[1];
- zx_handle_t case_end;
- ASSERT_EQ(zx_channel_create(0 /* option */, &case_end, &mvmvif->mlme_channel), ZX_OK);
- ASSERT_EQ(zx_channel_write(case_end, 0 /* option */, dummy, sizeof(dummy), nullptr, 0), ZX_OK);
-
- // Call release and the sme channel should be closed so that we will get a peer-close error while
- // trying to write any data to it.
- device_mac_ops.release(mvmvif);
- ASSERT_EQ(zx_channel_write(case_end, 0 /* option */, dummy, sizeof(dummy), nullptr, 0),
- ZX_ERR_PEER_CLOSED);
-}
-
-///////////////////////////////////// PHY //////////////////////////////////////////////
-
-TEST_F(WlanDeviceTest, PhyQuery) {
- wlanphy_impl_info_t info = {};
-
- // Test input null pointers
- ASSERT_EQ(ZX_ERR_INVALID_ARGS, device_->WlanphyImplQuery(nullptr));
- ASSERT_EQ(ZX_OK, device_->WlanphyImplQuery(&info));
-
- // Normal case
- ASSERT_EQ(ZX_OK, device_->WlanphyImplQuery(&info));
- EXPECT_EQ(WLAN_INFO_MAC_ROLE_CLIENT, info.supported_mac_roles);
-}
-
-TEST_F(WlanDeviceTest, PhyPartialCreateCleanup) {
- wlanphy_impl_create_iface_req_t req = {
- .role = WLAN_INFO_MAC_ROLE_CLIENT,
- .mlme_channel = mlme_channel_,
- };
- uint16_t iface_id;
- struct iwl_trans* iwl_trans = sim_trans_.iwl_trans();
-
- // Test input null pointers
- ASSERT_OK(phy_create_iface(iwl_trans, &req, &iface_id));
-
- // Ensure mvmvif got created and indexed.
- struct iwl_mvm* mvm = iwl_trans_get_mvm(iwl_trans);
- ASSERT_NOT_NULL(mvm->mvmvif[iface_id]);
-
- // Ensure partial create failure removes it from the index.
- phy_create_iface_undo(iwl_trans, iface_id);
- ASSERT_NULL(mvm->mvmvif[iface_id]);
-}
-
-TEST_F(WlanDeviceTest, PhyCreateDestroySingleInterface) {
- wlanphy_impl_create_iface_req_t req = {
- .role = WLAN_INFO_MAC_ROLE_CLIENT,
- .mlme_channel = mlme_channel_,
- };
- uint16_t iface_id;
-
- // Test input null pointers
- ASSERT_EQ(device_->WlanphyImplCreateIface(nullptr, &iface_id), ZX_ERR_INVALID_ARGS);
- ASSERT_EQ(device_->WlanphyImplCreateIface(&req, nullptr), ZX_ERR_INVALID_ARGS);
- ASSERT_EQ(device_->WlanphyImplCreateIface(nullptr, nullptr), ZX_ERR_INVALID_ARGS);
-
- // Test invalid inputs
- ASSERT_EQ(device_->WlanphyImplDestroyIface(MAX_NUM_MVMVIF), ZX_ERR_INVALID_ARGS);
- ASSERT_EQ(device_->WlanphyImplDestroyIface(0), ZX_ERR_NOT_FOUND); // hasn't been added yet.
-
- // To verify the internal state of MVM driver.
- struct iwl_mvm* mvm = iwl_trans_get_mvm(sim_trans_.iwl_trans());
-
- // Add interface
- ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
- ASSERT_EQ(iface_id, 0); // the first interface should have id 0.
- struct iwl_mvm_vif* mvmvif = mvm->mvmvif[iface_id];
- ASSERT_NE(mvmvif, nullptr);
- ASSERT_EQ(mvmvif->mac_role, WLAN_INFO_MAC_ROLE_CLIENT);
- // Count includes phy device in addition to the newly created mac device.
- ASSERT_EQ(fake_parent_->descendant_count(), 2);
- device_->zxdev()->GetLatestChild()->InitOp();
-
- // Remove interface
- ASSERT_EQ(device_->WlanphyImplDestroyIface(0), ZX_OK);
- mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
- ASSERT_EQ(mvm->mvmvif[iface_id], nullptr);
- ASSERT_EQ(fake_parent_->descendant_count(), 1);
-}
-
-TEST_F(WlanDeviceTest, PhyCreateDestroyMultipleInterfaces) {
- wlanphy_impl_create_iface_req_t req = {
- .role = WLAN_INFO_MAC_ROLE_CLIENT,
- .mlme_channel = mlme_channel_,
- };
- uint16_t iface_id;
- struct iwl_trans* iwl_trans = sim_trans_.iwl_trans();
- struct iwl_mvm* mvm = iwl_trans_get_mvm(iwl_trans); // To verify the internal state of MVM driver
-
- // Add 1st interface
- ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
- ASSERT_EQ(iface_id, 0);
- ASSERT_EQ(mvm->mvmvif[iface_id]->mac_role, WLAN_INFO_MAC_ROLE_CLIENT);
- ASSERT_EQ(fake_parent_->descendant_count(), 2);
- device_->zxdev()->GetLatestChild()->InitOp();
-
- // Add 2nd interface
- ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
- ASSERT_EQ(iface_id, 1);
- ASSERT_NE(mvm->mvmvif[iface_id], nullptr);
- ASSERT_EQ(mvm->mvmvif[iface_id]->mac_role, WLAN_INFO_MAC_ROLE_CLIENT);
- ASSERT_EQ(fake_parent_->descendant_count(), 3);
- device_->zxdev()->GetLatestChild()->InitOp();
-
- // Add 3rd interface
- ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
- ASSERT_EQ(iface_id, 2);
- ASSERT_NE(mvm->mvmvif[iface_id], nullptr);
- ASSERT_EQ(mvm->mvmvif[iface_id]->mac_role, WLAN_INFO_MAC_ROLE_CLIENT);
- ASSERT_EQ(fake_parent_->descendant_count(), 4);
- device_->zxdev()->GetLatestChild()->InitOp();
-
- // Remove the 2nd interface
- ASSERT_EQ(device_->WlanphyImplDestroyIface(1), ZX_OK);
- mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
- ASSERT_EQ(mvm->mvmvif[1], nullptr);
- ASSERT_EQ(fake_parent_->descendant_count(), 3);
-
- // Add a new interface and it should be the 2nd one.
- ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
- ASSERT_EQ(iface_id, 1);
- ASSERT_NE(mvm->mvmvif[iface_id], nullptr);
- ASSERT_EQ(mvm->mvmvif[iface_id]->mac_role, WLAN_INFO_MAC_ROLE_CLIENT);
- ASSERT_EQ(fake_parent_->descendant_count(), 4);
- device_->zxdev()->GetLatestChild()->InitOp();
-
- // Add 4th interface
- ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
- ASSERT_EQ(iface_id, 3);
- ASSERT_NE(mvm->mvmvif[iface_id], nullptr);
- ASSERT_EQ(mvm->mvmvif[iface_id]->mac_role, WLAN_INFO_MAC_ROLE_CLIENT);
- ASSERT_EQ(fake_parent_->descendant_count(), 5);
- device_->zxdev()->GetLatestChild()->InitOp();
-
- // Add 5th interface and it should fail
- ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_ERR_NO_RESOURCES);
- ASSERT_EQ(fake_parent_->descendant_count(), 5);
-
- // Remove the 2nd interface
- ASSERT_EQ(device_->WlanphyImplDestroyIface(1), ZX_OK);
- mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
- ASSERT_EQ(mvm->mvmvif[1], nullptr);
- ASSERT_EQ(fake_parent_->descendant_count(), 4);
-
- // Remove the 3rd interface
- ASSERT_EQ(device_->WlanphyImplDestroyIface(2), ZX_OK);
- mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
- ASSERT_EQ(mvm->mvmvif[2], nullptr);
- ASSERT_EQ(fake_parent_->descendant_count(), 3);
-
- // Remove the 4th interface
- ASSERT_EQ(device_->WlanphyImplDestroyIface(3), ZX_OK);
- mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
- ASSERT_EQ(mvm->mvmvif[3], nullptr);
- ASSERT_EQ(fake_parent_->descendant_count(), 2);
-
- // Remove the 1st interface
- ASSERT_EQ(device_->WlanphyImplDestroyIface(0), ZX_OK);
- mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
- ASSERT_EQ(mvm->mvmvif[0], nullptr);
- ASSERT_EQ(fake_parent_->descendant_count(), 1);
-
- // Remove the 1st interface again and it should fail.
- ASSERT_EQ(device_->WlanphyImplDestroyIface(0), ZX_ERR_NOT_FOUND);
- ASSERT_EQ(fake_parent_->descendant_count(), 1);
-}
-
-// The class for WLAN device MAC testing.
-//
-class MacInterfaceTest : public WlanDeviceTest, public MockTrans {
- public:
- MacInterfaceTest() : ifc_{ .ops = &proto_ops_, } , proto_ops_{ .recv = recv_wrapper, } {
- mvmvif_sta_.mlme_channel = mlme_channel_;
- zx_handle_t mlme_channel;
- ASSERT_EQ(wlanmac_ops.start(&mvmvif_sta_, &ifc_, &mlme_channel), ZX_OK);
-
- // Add the interface to MVM instance.
- mvmvif_sta_.mvm->mvmvif[0] = &mvmvif_sta_;
- }
-
- ~MacInterfaceTest() {
- VerifyExpectation(); // Ensure all expectations had been met.
-
- // Restore the original callback for other test cases not using the mock.
- if (original_send_cmd) {
- sim_trans_.iwl_trans()->ops->send_cmd = original_send_cmd;
- }
-
- // Stop the MAC to free resources we allocated.
- // This must be called after we verify the expected commands and restore the mock command
- // callback so that the stop command doesn't mess up the test case expectation.
- wlanmac_ops.stop(&mvmvif_sta_);
- VerifyStaHasBeenRemoved();
- }
-
- // Used in MockCommand constructor to indicate if the command needs to be either
- //
- // - returned immediately (with a status code), or
- // - passed to the sim_mvm.c.
- //
- enum SimMvmBehavior {
- kSimMvmReturnWithStatus,
- kSimMvmBypassToSimMvm,
- };
-
- // A flexible mock-up of firmware command for testing code. Testing code can decide to either call
- // the simulated firmware or return the status code immediately.
- //
- // cmd_id: the command ID. Sometimes composed with WIDE_ID() macro.
- // behavior: determine what this mockup command is to do.
- // status: the status code to return when behavior is 'kSimMvmReturnWithStatus'.
- //
- class MockCommand {
- public:
- MockCommand(uint32_t cmd_id, SimMvmBehavior behavior, zx_status_t status)
- : cmd_id_(cmd_id), behavior_(behavior), status_(status) {}
- MockCommand(uint32_t cmd_id) : MockCommand(cmd_id, kSimMvmBypassToSimMvm, ZX_OK) {}
-
- ~MockCommand() {}
-
- uint32_t cmd_id_;
- SimMvmBehavior behavior_;
- zx_status_t status_;
- };
- typedef std::list<MockCommand> expected_cmd_id_list;
- typedef zx_status_t (*fp_send_cmd)(struct iwl_trans* trans, struct iwl_host_cmd* cmd);
-
- // Public for MockSendCmd().
- expected_cmd_id_list expected_cmd_ids;
- fp_send_cmd original_send_cmd;
-
- protected:
- zx_status_t SetChannel(const wlan_channel_t* channel) {
- uint32_t option = 0;
- return wlanmac_ops.set_channel(&mvmvif_sta_, option, channel);
- }
-
- zx_status_t ConfigureBss(const bss_config_t* config) {
- uint32_t option = 0;
- return wlanmac_ops.configure_bss(&mvmvif_sta_, option, config);
- }
-
- zx_status_t ConfigureAssoc(const wlan_assoc_ctx_t* config) {
- uint32_t option = 0;
- return wlanmac_ops.configure_assoc(&mvmvif_sta_, option, config);
- }
-
- zx_status_t ClearAssoc() {
- uint32_t option = 0;
- uint8_t peer_addr[fuchsia_wlan_ieee80211_MAC_ADDR_LEN]; // Not used since all info were
- // saved in mvmvif_sta_ already.
- return wlanmac_ops.clear_assoc(&mvmvif_sta_, option, peer_addr);
- }
-
- zx_status_t SetKey(const wlan_key_config_t* key_config) {
- uint32_t option = 0;
- IWL_INFO(nullptr, "Calling set_key");
- return wlanmac_ops.set_key(&mvmvif_sta_, option, key_config);
- }
- // The following functions are for mocking up the firmware commands.
- //
- // The mock function will return the special error ZX_ERR_INTERNAL when the expectation
- // is not expected.
-
- // Set the expected commands sending to the firmware.
- //
- // Args:
- // cmd_ids: list of expected commands. Will be matched in order.
- //
- void ExpectSendCmd(const expected_cmd_id_list& cmd_ids) {
- expected_cmd_ids = cmd_ids;
-
- // Re-define the 'dev' field in the 'struct iwl_trans' to a test instance of this class.
- sim_trans_.iwl_trans()->dev = reinterpret_cast<struct device*>(this);
-
- // Setup the mock function for send command.
- original_send_cmd = sim_trans_.iwl_trans()->ops->send_cmd;
- sim_trans_.iwl_trans()->ops->send_cmd = MockSendCmd;
- }
-
- static zx_status_t MockSendCmd(struct iwl_trans* trans, struct iwl_host_cmd* cmd) {
- MacInterfaceTest* this_ = reinterpret_cast<MacInterfaceTest*>(trans->dev);
-
- // remove the first one and match.
- expected_cmd_id_list& expected = this_->expected_cmd_ids;
- ZX_ASSERT_MSG(!expected.empty(),
- "A command (0x%04x) is going to send, but no command is expected.\n", cmd->id);
-
- // check the command ID.
- auto exp = expected.front();
- ZX_ASSERT_MSG(exp.cmd_id_ == cmd->id,
- "The command doesn't match! Expect: 0x%04x, actual: 0x%04x.\n", exp.cmd_id_,
- cmd->id);
- expected.pop_front();
-
- if (exp.behavior_ == kSimMvmBypassToSimMvm) {
- return this_->original_send_cmd(trans, cmd);
- } else {
- return exp.status_;
- }
- }
-
- void VerifyExpectation() {
- for (expected_cmd_id_list::iterator it = expected_cmd_ids.begin(); it != expected_cmd_ids.end();
- it++) {
- printf(" ==> 0x%04x\n", it->cmd_id_);
- }
- ASSERT_TRUE(expected_cmd_ids.empty(), "The expected command set is not empty.");
-
- mock_tx_.VerifyAndClear();
- }
-
- void VerifyStaHasBeenRemoved() {
- auto mvm = mvmvif_sta_.mvm;
-
- for (size_t i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) {
- struct iwl_mvm_sta* mvm_sta = mvm->fw_id_to_mac_id[i];
- ASSERT_EQ(nullptr, mvm_sta);
- }
- ASSERT_EQ(0, mvm->vif_count);
- }
-
- // Mock function for Tx.
- mock_function::MockFunction<zx_status_t, // return value
- size_t, // packet size
- uint16_t, // cmd + group_id
- int // txq_id
- >
- mock_tx_;
-
- static zx_status_t tx_wrapper(struct iwl_trans* trans, struct ieee80211_mac_packet* pkt,
- const struct iwl_device_cmd* dev_cmd, int txq_id) {
- auto test = GET_TEST(MacInterfaceTest, trans);
- return test->mock_tx_.Call(pkt->header_size + pkt->headroom_used_size + pkt->body_size,
- WIDE_ID(dev_cmd->hdr.group_id, dev_cmd->hdr.cmd), txq_id);
- }
-
- wlanmac_ifc_protocol_t ifc_;
- wlanmac_ifc_protocol_ops_t proto_ops_;
- static constexpr bss_config_t kBssConfig = {
- .bssid = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
- .bss_type = BSS_TYPE_INFRASTRUCTURE,
- .remote = true,
- };
- static constexpr wlan_assoc_ctx_t kAssocCtx = {
- .listen_interval = kListenInterval,
- };
-};
-
-// Test the set_channel().
-//
-TEST_F(MacInterfaceTest, TestSetChannel) {
- ExpectSendCmd(expected_cmd_id_list({
- MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for add_chanctx
- MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for change_chanctx
- MockCommand(WIDE_ID(LONG_GROUP, BINDING_CONTEXT_CMD)),
- MockCommand(WIDE_ID(LONG_GROUP, MAC_PM_POWER_TABLE)),
- }));
-
- mvmvif_sta_.csa_bcn_pending = true; // Expect to be clear because this is client role.
- ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
- EXPECT_EQ(false, mvmvif_sta_.csa_bcn_pending);
-}
-
-// Test the unsupported MAC role.
-//
-TEST_F(MacInterfaceTest, TestSetChannelWithUnsupportedRole) {
- ExpectSendCmd(expected_cmd_id_list({
- MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for add_chanctx
- MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for change_chanctx
- }));
-
- mvmvif_sta_.mac_role = WLAN_INFO_MAC_ROLE_AP;
- ASSERT_EQ(ZX_ERR_NOT_SUPPORTED, SetChannel(&kChannel));
-}
-
-// Tests calling SetChannel()/ConfigureBss() again without ConfigureAssoc()/ClearAssoc()
-TEST_F(MacInterfaceTest, DuplicateSetChannel) {
- ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
- ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
- struct iwl_mvm_sta* mvm_sta = mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id];
- struct iwl_mvm_phy_ctxt* phy_ctxt = mvmvif_sta_.phy_ctxt;
- ASSERT_NE(nullptr, phy_ctxt);
- ASSERT_EQ(IWL_STA_NONE, mvm_sta->sta_state);
- // Call SetChannel() again. This should return the same phy context but ConfigureBss()
- // should setup a new STA.
- ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
- struct iwl_mvm_phy_ctxt* new_phy_ctxt = mvmvif_sta_.phy_ctxt;
- ASSERT_NE(nullptr, new_phy_ctxt);
- ASSERT_EQ(phy_ctxt, new_phy_ctxt);
- ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
- struct iwl_mvm_sta* new_mvm_sta = mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id];
- // Now Associate and disassociate - this should release and reset the phy ctxt.
- ASSERT_EQ(ZX_OK, ConfigureAssoc(&kAssocCtx));
- ASSERT_EQ(IWL_STA_AUTHORIZED, new_mvm_sta->sta_state);
- ASSERT_EQ(true, mvmvif_sta_.bss_conf.assoc);
- ASSERT_EQ(kListenInterval, mvmvif_sta_.bss_conf.listen_interval);
-
- ASSERT_EQ(ZX_OK, ClearAssoc());
- ASSERT_EQ(nullptr, mvmvif_sta_.phy_ctxt);
- ASSERT_EQ(IWL_MVM_INVALID_STA, mvmvif_sta_.ap_sta_id);
-}
-
-// Test ConfigureBss()
-//
-TEST_F(MacInterfaceTest, TestConfigureBss) {
- ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
-
- ExpectSendCmd(expected_cmd_id_list({
- MockCommand(WIDE_ID(LONG_GROUP, MAC_CONTEXT_CMD)),
- MockCommand(WIDE_ID(LONG_GROUP, ADD_STA)),
- MockCommand(WIDE_ID(LONG_GROUP, TIME_EVENT_CMD)),
- MockCommand(WIDE_ID(LONG_GROUP, SCD_QUEUE_CFG)),
- MockCommand(WIDE_ID(LONG_GROUP, ADD_STA)),
- }));
-
- ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
- // Ensure the BSSID was copied into mvmvif
- ASSERT_EQ(memcmp(mvmvif_sta_.bss_conf.bssid, kBssConfig.bssid, ETH_ALEN), 0);
- ASSERT_EQ(memcmp(mvmvif_sta_.bssid, kBssConfig.bssid, ETH_ALEN), 0);
-}
-
-// Test duplicate BSS config.
-//
-TEST_F(MacInterfaceTest, DuplicateConfigureBss) {
- ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
- ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
- ASSERT_EQ(ZX_ERR_ALREADY_EXISTS, ConfigureBss(&kBssConfig));
-}
-
-// Test unsupported bss_type.
-//
-TEST_F(MacInterfaceTest, UnsupportedBssType) {
- static constexpr bss_config_t kUnsupportedBssConfig = {
- .bssid = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
- .bss_type = BSS_TYPE_INDEPENDENT,
- .remote = true,
- };
- ASSERT_EQ(ZX_ERR_INVALID_ARGS, ConfigureBss(&kUnsupportedBssConfig));
-}
-
-// Test failed ADD_STA command.
-//
-TEST_F(MacInterfaceTest, TestFailedAddSta) {
- ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
-
- ExpectSendCmd(expected_cmd_id_list({
- MockCommand(WIDE_ID(LONG_GROUP, MAC_CONTEXT_CMD), kSimMvmReturnWithStatus,
- ZX_ERR_BUFFER_TOO_SMALL /* an arbitrary error */),
- }));
-
- ASSERT_EQ(ZX_ERR_BUFFER_TOO_SMALL, ConfigureBss(&kBssConfig));
-}
-
-// Test exception handling in driver.
-//
-TEST_F(MacInterfaceTest, TestExceptionHandling) {
- ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
-
- // Test the beacon interval checking.
- mvmvif_sta_.bss_conf.beacon_int = 0;
- EXPECT_EQ(ZX_ERR_INVALID_ARGS, ConfigureBss(&kBssConfig));
- mvmvif_sta_.bss_conf.beacon_int = 16; // which just passes the check.
-
- // Test the phy_ctxt checking.
- auto backup_phy_ctxt = mvmvif_sta_.phy_ctxt;
- mvmvif_sta_.phy_ctxt = nullptr;
- EXPECT_EQ(ZX_ERR_BAD_STATE, ConfigureBss(&kBssConfig));
- mvmvif_sta_.phy_ctxt = backup_phy_ctxt;
-
- // Test the case we run out of slots for STA.
- //
- // In the constructor of the test, mvmvif_sta_ had been added once. So we would expect the
- // following (IWL_MVM_STATION_COUNT - 1) adding would be successful as well.
- //
- for (size_t i = 0; i < IWL_MVM_STATION_COUNT - 1; i++) {
- // Pretent the STA is not assigned so that we can add it again.
- mvmvif_sta_.ap_sta_id = IWL_MVM_INVALID_STA;
- ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
- }
- // However, the last one should fail because we run out of all slots in fw_id_to_mac_id[].
- mvmvif_sta_.ap_sta_id = IWL_MVM_INVALID_STA;
- ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
-}
-
-// The test is used to test the typical procedure to connect to an open network.
-//
-TEST_F(MacInterfaceTest, AssociateToOpenNetwork) {
- ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
- ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
- struct iwl_mvm_sta* mvm_sta = mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id];
- ASSERT_EQ(IWL_STA_NONE, mvm_sta->sta_state);
- struct iwl_mvm* mvm = mvmvif_sta_.mvm;
- ASSERT_GT(list_length(&mvm->time_event_list), 0);
-
- ASSERT_EQ(ZX_OK, ConfigureAssoc(&kAssocCtx));
- ASSERT_EQ(IWL_STA_AUTHORIZED, mvm_sta->sta_state);
- ASSERT_EQ(true, mvmvif_sta_.bss_conf.assoc);
- ASSERT_EQ(kListenInterval, mvmvif_sta_.bss_conf.listen_interval);
-
- ASSERT_EQ(ZX_OK, ClearAssoc());
- ASSERT_EQ(nullptr, mvmvif_sta_.phy_ctxt);
- ASSERT_EQ(IWL_MVM_INVALID_STA, mvmvif_sta_.ap_sta_id);
- ASSERT_EQ(list_length(&mvm->time_event_list), 0);
-}
-
-// Back to back calls of ClearAssoc().
-TEST_F(MacInterfaceTest, ClearAssocAfterClearAssoc) {
- ASSERT_NE(ZX_OK, ClearAssoc());
- ASSERT_NE(ZX_OK, ClearAssoc());
-}
-
-// ClearAssoc() should cleanup when called without Assoc
-TEST_F(MacInterfaceTest, ClearAssocAfterNoAssoc) {
- ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
- ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
- struct iwl_mvm_sta* mvm_sta = mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id];
- ASSERT_EQ(IWL_STA_NONE, mvm_sta->sta_state);
- struct iwl_mvm* mvm = mvmvif_sta_.mvm;
- ASSERT_GT(list_length(&mvm->time_event_list), 0);
-
- ASSERT_EQ(ZX_OK, ClearAssoc());
- ASSERT_EQ(nullptr, mvmvif_sta_.phy_ctxt);
- ASSERT_EQ(IWL_MVM_INVALID_STA, mvmvif_sta_.ap_sta_id);
- ASSERT_EQ(list_length(&mvm->time_event_list), 0);
- // Call ClearAssoc() again to check if it is handled correctly.
- ASSERT_NE(ZX_OK, ClearAssoc());
-}
-
-TEST_F(MacInterfaceTest, AssociateToOpenNetworkNullStation) {
- SetChannel(&kChannel);
- ConfigureBss(&kBssConfig);
-
- // Replace the STA pointer with NULL and expect the association will fail.
- auto org = mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id];
- mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id] = nullptr;
-
- ASSERT_EQ(ZX_ERR_BAD_STATE, ConfigureAssoc(&kAssocCtx));
-
- // Expect error while disassociating a non-existing association.
- ASSERT_EQ(ZX_ERR_BAD_STATE, ClearAssoc());
-
- // We have to recover the pointer so that the MAC stop function can recycle the memory.
- mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id] = org;
-}
-
-TEST_F(MacInterfaceTest, ClearAssocAfterFailedAssoc) {
- SetChannel(&kChannel);
- ConfigureBss(&kBssConfig);
-
- struct iwl_mvm* mvm = mvmvif_sta_.mvm;
- ASSERT_GT(list_length(&mvm->time_event_list), 0);
- // Replace the STA pointer with NULL and expect the association will fail.
- auto org = mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id];
- mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id] = nullptr;
-
- ASSERT_EQ(ZX_ERR_BAD_STATE, ConfigureAssoc(&kAssocCtx));
- // Now put back the original STA pointer so ClearAssoc runs and also
- // to recycle allocated memory
- mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id] = org;
- ASSERT_GT(list_length(&mvm->time_event_list), 0);
-
- // Expect error while disassociating a non-existing association.
- ASSERT_EQ(ZX_OK, ClearAssoc());
- ASSERT_EQ(nullptr, mvmvif_sta_.phy_ctxt);
- ASSERT_EQ(IWL_MVM_INVALID_STA, mvmvif_sta_.ap_sta_id);
- ASSERT_EQ(list_length(&mvm->time_event_list), 0);
- // Call ClearAssoc() again to check if it is handled correctly.
- ASSERT_NE(ZX_OK, ClearAssoc());
-}
-
-// Check to ensure keys are set during assoc and deleted after disassoc
-// for now use open network
-TEST_F(MacInterfaceTest, SetKeysTest) {
- constexpr uint8_t kIeeeOui[] = {0x00, 0x0F, 0xAC};
- ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
- ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
- struct iwl_mvm_sta* mvm_sta = mvmvif_sta_.mvm->fw_id_to_mac_id[mvmvif_sta_.ap_sta_id];
- ASSERT_EQ(IWL_STA_NONE, mvm_sta->sta_state);
- struct iwl_mvm* mvm = mvmvif_sta_.mvm;
- ASSERT_GT(list_length(&mvm->time_event_list), 0);
-
- ASSERT_EQ(ZX_OK, ConfigureAssoc(&kAssocCtx));
- ASSERT_EQ(IWL_STA_AUTHORIZED, mvm_sta->sta_state);
- ASSERT_EQ(true, mvmvif_sta_.bss_conf.assoc);
- ASSERT_EQ(kListenInterval, mvmvif_sta_.bss_conf.listen_interval);
-
- char keybuf[sizeof(wlan_key_config_t) + 16];
- wlan_key_config_t* key_config = (wlan_key_config_t*)keybuf;
- // PAIRWISE KEY
- key_config->cipher_type = 4;
- key_config->key_type = 1;
- key_config->key_idx = 0;
- key_config->key_len = 16;
- memcpy(key_config->cipher_oui, kIeeeOui, 3);
- ASSERT_EQ(ZX_OK, SetKey((const wlan_key_config_t*)key_config));
- // Expect bit 0 to be set.
- ASSERT_EQ(*mvm->fw_key_table, 0x1);
- // GROUP KEY
- key_config->key_type = 2;
- key_config->key_idx = 1;
- ASSERT_EQ(ZX_OK, SetKey((const wlan_key_config_t*)key_config));
- // Expect bit 1 to be set as well.
- ASSERT_EQ(*mvm->fw_key_table, 0x3);
- ASSERT_EQ(ZX_OK, ClearAssoc());
- ASSERT_EQ(nullptr, mvmvif_sta_.phy_ctxt);
- ASSERT_EQ(IWL_MVM_INVALID_STA, mvmvif_sta_.ap_sta_id);
- ASSERT_EQ(list_length(&mvm->time_event_list), 0);
- // Both the keys should have been deleted.
- ASSERT_EQ(*mvm->fw_key_table, 0x0);
-}
-
-TEST_F(MacInterfaceTest, TxPktNotSupportedRole) {
- SetChannel(&kChannel);
- ConfigureBss(&kBssConfig);
- BIND_TEST(sim_trans_.iwl_trans());
-
- // Set to an unsupported role.
- mvmvif_sta_.mac_role = WLAN_INFO_MAC_ROLE_AP;
-
- bindTx(tx_wrapper);
- WlanPktBuilder builder;
- std::shared_ptr<WlanPktBuilder::WlanPkt> wlan_pkt = builder.build();
- ASSERT_EQ(ZX_ERR_INVALID_ARGS, wlanmac_ops.queue_tx(&mvmvif_sta_, 0, wlan_pkt->wlan_pkt()));
- unbindTx();
-}
-
-// To test if a packet can be sent out.
-TEST_F(MacInterfaceTest, TxPkt) {
- SetChannel(&kChannel);
- ConfigureBss(&kBssConfig);
- BIND_TEST(sim_trans_.iwl_trans());
-
- bindTx(tx_wrapper);
- WlanPktBuilder builder;
- std::shared_ptr<WlanPktBuilder::WlanPkt> wlan_pkt = builder.build();
- mock_tx_.ExpectCall(ZX_OK, wlan_pkt->len(), WIDE_ID(0, TX_CMD), IWL_MVM_DQA_MIN_MGMT_QUEUE);
- ASSERT_EQ(ZX_OK, wlanmac_ops.queue_tx(&mvmvif_sta_, 0, wlan_pkt->wlan_pkt()));
- unbindTx();
-}
-
-} // namespace
-} // namespace wlan::testing
diff --git a/third_party/iwlwifi/test/mvm-test.cc b/third_party/iwlwifi/test/mvm-test.cc
index 3c455e3..b83fd8b 100644
--- a/third_party/iwlwifi/test/mvm-test.cc
+++ b/third_party/iwlwifi/test/mvm-test.cc
@@ -3,8 +3,9 @@
// found in the LICENSE file.
#include <lib/mock-function/mock-function.h>
-#include <lib/zircon-internal/thread_annotations.h>
+#include <zircon/compiler.h>
+#include <iterator>
#include <memory>
#include <zxtest/zxtest.h>
@@ -14,10 +15,11 @@
#include "third_party/iwlwifi/mvm/time-event.h"
}
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
#include "third_party/iwlwifi/platform/memory.h"
-#include "third_party/iwlwifi/test/fake-ucode-capa-test.h"
+#include "third_party/iwlwifi/test/fake-ucode-test.h"
#include "third_party/iwlwifi/test/mock-trans.h"
+#include "third_party/iwlwifi/test/sim-time-event.h"
#include "third_party/iwlwifi/test/single-ap-test.h"
#include "third_party/iwlwifi/test/wlan-pkt-builder.h"
@@ -27,7 +29,7 @@
// Helper function to create a PHY context for the interface.
//
-static void setup_phy_ctxt(struct iwl_mvm_vif* mvmvif) TA_NO_THREAD_SAFETY_ANALYSIS {
+static void setup_phy_ctxt(struct iwl_mvm_vif* mvmvif) __TA_NO_THREAD_SAFETY_ANALYSIS {
// Create a PHY context and assign it to mvmvif.
wlan_channel_t chandef = {
// any arbitrary values
@@ -70,38 +72,38 @@
class MvmTest : public SingleApTest {
public:
- MvmTest() TA_NO_THREAD_SAFETY_ANALYSIS {
+ MvmTest() __TA_NO_THREAD_SAFETY_ANALYSIS {
mvm_ = iwl_trans_get_mvm(sim_trans_.iwl_trans());
mvmvif_ = reinterpret_cast<struct iwl_mvm_vif*>(calloc(1, sizeof(struct iwl_mvm_vif)));
mvmvif_->mvm = mvm_;
- mvmvif_->mac_role = WLAN_INFO_MAC_ROLE_CLIENT;
- mvmvif_->ifc.ops = reinterpret_cast<wlanmac_ifc_protocol_ops_t*>(
- calloc(1, sizeof(wlanmac_ifc_protocol_ops_t)));
+ mvmvif_->mac_role = WLAN_MAC_ROLE_CLIENT;
+ mvmvif_->ifc.ops = reinterpret_cast<wlan_softmac_ifc_protocol_ops_t*>(
+ calloc(1, sizeof(wlan_softmac_ifc_protocol_ops_t)));
mvm_->mvmvif[0] = mvmvif_;
mvm_->vif_count++;
mtx_lock(&mvm_->mutex);
}
- ~MvmTest() TA_NO_THREAD_SAFETY_ANALYSIS {
+ ~MvmTest() __TA_NO_THREAD_SAFETY_ANALYSIS {
free(mvmvif_->ifc.ops);
free(mvmvif_);
mtx_unlock(&mvm_->mutex);
}
protected:
- // This function is kind of dirty. It hijacks the wlanmac_ifc_protocol_t.recv() so that we can
- // save the rx_info passed to MLME. See TearDown() for cleanup logic related to this function.
+ // This function is kind of dirty. It hijacks the wlan_softmac_ifc_protocol_t.recv() so that we
+ // can save the rx_info passed to MLME. See TearDown() for cleanup logic related to this
+ // function.
void MockRecv(TestCtx* ctx) {
// TODO(fxbug.dev/43218): replace rxq->napi with interface instance so that we can map to
// mvmvif.
- mvmvif_->ifc.ctx = ctx; // 'ctx' was used as 'wlanmac_ifc_protocol_t*', but we override it
+ mvmvif_->ifc.ctx = ctx; // 'ctx' was used as 'wlan_softmac_ifc_protocol_t*', but we override it
// with 'TestCtx*'.
- mvmvif_->ifc.ops->recv = [](void* ctx, uint32_t flags, const uint8_t* data_buffer,
- size_t data_size, const wlan_rx_info_t* info) {
+ mvmvif_->ifc.ops->recv = [](void* ctx, const wlan_rx_packet_t* packet) {
TestCtx* test_ctx = reinterpret_cast<TestCtx*>(ctx);
- test_ctx->rx_info = *info;
- test_ctx->frame_len = data_size;
+ test_ctx->rx_info = packet->info;
+ test_ctx->frame_len = packet->mac_frame_size;
};
}
@@ -350,33 +352,36 @@
///////////////////////////////////////////////////////////////////////////////
// Scan Test
//
-class ScanTest : public MvmTest {
+class PassiveScanTest : public MvmTest {
public:
- ScanTest() {
+ PassiveScanTest() {
// Fake callback registered to capture scan completion responses.
- ops.hw_scan_complete = [](void* ctx, const wlan_hw_scan_result_t* result) {
+ ops.scan_complete = [](void* ctx, zx_status_t status, uint64_t scan_id) {
+ // TODO(fxbug.dev/88934): scan_id is always 0
+ EXPECT_EQ(scan_id, 0);
struct ScanResult* sr = (struct ScanResult*)ctx;
sr->sme_notified = true;
- sr->success = (result->code == WLAN_HW_SCAN_SUCCESS ? true : false);
+ sr->success = (status == ZX_OK ? true : false);
};
mvmvif_sta.mvm = iwl_trans_get_mvm(sim_trans_.iwl_trans());
- mvmvif_sta.mac_role = WLAN_INFO_MAC_ROLE_CLIENT;
+ mvmvif_sta.mac_role = WLAN_MAC_ROLE_CLIENT;
mvmvif_sta.ifc.ops = &ops;
mvmvif_sta.ifc.ctx = &scan_result;
- // This can be moved out or overridden when we add other scan types.
- scan_config.scan_type = WLAN_HW_SCAN_TYPE_PASSIVE;
-
trans_ = sim_trans_.iwl_trans();
}
- ~ScanTest() {}
+ ~PassiveScanTest() {}
struct iwl_trans* trans_;
- wlanmac_ifc_protocol_ops_t ops;
+ wlan_softmac_ifc_protocol_ops_t ops;
struct iwl_mvm_vif mvmvif_sta;
- wlan_hw_scan_config_t scan_config{.num_channels = 4, .channels = {7, 1, 40, 136}};
+ uint8_t channels_to_scan_[4] = {7, 1, 40, 136};
+ wlan_softmac_passive_scan_args_t passive_scan_args_{
+ .channels_list = channels_to_scan_, .channels_count = 4,
+ // TODO(fxbug.dev/88943): Fill in other fields once support determined.
+ };
// Structure to capture scan results.
struct ScanResult {
@@ -385,49 +390,52 @@
} scan_result;
};
-class UmacScanTest : public FakeUcodeCapaTest {
+class PassiveUmacScanTest : public FakeUcodeTest {
public:
- UmacScanTest() TA_NO_THREAD_SAFETY_ANALYSIS
- : FakeUcodeCapaTest(0, BIT(IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
+ PassiveUmacScanTest() __TA_NO_THREAD_SAFETY_ANALYSIS
+ : FakeUcodeTest(0, BIT(IWL_UCODE_TLV_CAPA_UMAC_SCAN), 0, 0) {
mvm_ = iwl_trans_get_mvm(sim_trans_.iwl_trans());
mvmvif_ = reinterpret_cast<struct iwl_mvm_vif*>(calloc(1, sizeof(struct iwl_mvm_vif)));
mvmvif_->mvm = mvm_;
- mvmvif_->mac_role = WLAN_INFO_MAC_ROLE_CLIENT;
- mvmvif_->ifc.ops = reinterpret_cast<wlanmac_ifc_protocol_ops_t*>(
- calloc(1, sizeof(wlanmac_ifc_protocol_ops_t)));
+ mvmvif_->mac_role = WLAN_MAC_ROLE_CLIENT;
+ mvmvif_->ifc.ops = reinterpret_cast<wlan_softmac_ifc_protocol_ops_t*>(
+ calloc(1, sizeof(wlan_softmac_ifc_protocol_ops_t)));
mvm_->mvmvif[0] = mvmvif_;
mvm_->vif_count++;
mtx_lock(&mvm_->mutex);
// Fake callback registered to capture scan completion responses.
- ops_.hw_scan_complete = [](void* ctx, const wlan_hw_scan_result_t* result) {
+ ops_.scan_complete = [](void* ctx, zx_status_t status, uint64_t scan_id) {
+ // TODO(fxbug.dev/88934): scan_id is always 0
+ EXPECT_EQ(scan_id, 0);
struct ScanResult* sr = (struct ScanResult*)ctx;
sr->sme_notified = true;
- sr->success = (result->code == WLAN_HW_SCAN_SUCCESS ? true : false);
+ sr->success = (status == ZX_OK ? true : false);
};
mvmvif_sta_.mvm = iwl_trans_get_mvm(sim_trans_.iwl_trans());
- mvmvif_sta_.mac_role = WLAN_INFO_MAC_ROLE_CLIENT;
+ mvmvif_sta_.mac_role = WLAN_MAC_ROLE_CLIENT;
mvmvif_sta_.ifc.ops = &ops_;
mvmvif_sta_.ifc.ctx = &scan_result_;
- // This can be moved out or overridden when we add other scan types.
- scan_config_.scan_type = WLAN_HW_SCAN_TYPE_PASSIVE;
-
trans_ = sim_trans_.iwl_trans();
}
- ~UmacScanTest() TA_NO_THREAD_SAFETY_ANALYSIS {
+ ~PassiveUmacScanTest() __TA_NO_THREAD_SAFETY_ANALYSIS {
free(mvmvif_->ifc.ops);
free(mvmvif_);
mtx_unlock(&mvm_->mutex);
}
struct iwl_trans* trans_;
- wlanmac_ifc_protocol_ops_t ops_;
+ wlan_softmac_ifc_protocol_ops_t ops_;
struct iwl_mvm_vif mvmvif_sta_;
- wlan_hw_scan_config_t scan_config_{.num_channels = 4, .channels = {7, 1, 40, 136}};
+ uint8_t channels_to_scan_[4] = {7, 1, 40, 136};
+ wlan_softmac_passive_scan_args_t passive_scan_args_{
+ .channels_list = channels_to_scan_, .channels_count = 4,
+ // TODO(fxbug.dev/89693): iwlwifi ignores all other fields.
+ };
// Structure to capture scan results.
struct ScanResult {
@@ -442,13 +450,13 @@
/* Tests for LMAC scan */
// Tests scenario for a successful scan completion.
-TEST_F(ScanTest, RegPassiveLmacScanSuccess) TA_NO_THREAD_SAFETY_ANALYSIS {
+TEST_F(PassiveScanTest, RegPassiveLmacScanSuccess) __TA_NO_THREAD_SAFETY_ANALYSIS {
ASSERT_EQ(0, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
ASSERT_EQ(nullptr, mvm_->scan_vif);
ASSERT_EQ(false, scan_result.sme_notified);
ASSERT_EQ(false, scan_result.success);
- ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start(&mvmvif_sta, &scan_config));
+ ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start_passive(&mvmvif_sta, &passive_scan_args_));
EXPECT_EQ(IWL_MVM_SCAN_REGULAR, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
EXPECT_EQ(&mvmvif_sta, mvm_->scan_vif);
@@ -468,13 +476,13 @@
}
// Tests scenario where the scan request aborted / failed.
-TEST_F(ScanTest, RegPassiveLmacScanAborted) TA_NO_THREAD_SAFETY_ANALYSIS {
+TEST_F(PassiveScanTest, RegPassiveLmacScanAborted) __TA_NO_THREAD_SAFETY_ANALYSIS {
ASSERT_EQ(0, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
ASSERT_EQ(nullptr, mvm_->scan_vif);
ASSERT_EQ(false, scan_result.sme_notified);
ASSERT_EQ(false, scan_result.success);
- ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start(&mvmvif_sta, &scan_config));
+ ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start_passive(&mvmvif_sta, &passive_scan_args_));
EXPECT_EQ(IWL_MVM_SCAN_REGULAR, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
EXPECT_EQ(&mvmvif_sta, mvm_->scan_vif);
@@ -496,13 +504,12 @@
/* Tests for UMAC scan */
// Tests scenario for a successful scan completion.
-TEST_F(UmacScanTest, RegPassiveUmacScanSuccess) TA_NO_THREAD_SAFETY_ANALYSIS {
+TEST_F(PassiveUmacScanTest, RegPassiveUmacScanSuccess) __TA_NO_THREAD_SAFETY_ANALYSIS {
ASSERT_EQ(0, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
ASSERT_EQ(nullptr, mvm_->scan_vif);
ASSERT_EQ(false, scan_result_.sme_notified);
ASSERT_EQ(false, scan_result_.success);
-
- ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start(&mvmvif_sta_, &scan_config_));
+ ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start_passive(&mvmvif_sta_, &passive_scan_args_));
EXPECT_EQ(IWL_MVM_SCAN_REGULAR, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
EXPECT_EQ(&mvmvif_sta_, mvm_->scan_vif);
@@ -522,13 +529,13 @@
}
// Tests scenario where the scan request aborted / failed.
-TEST_F(UmacScanTest, RegPassiveUmacScanAborted) TA_NO_THREAD_SAFETY_ANALYSIS {
+TEST_F(PassiveUmacScanTest, RegPassiveUmacScanAborted) __TA_NO_THREAD_SAFETY_ANALYSIS {
ASSERT_EQ(0, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
ASSERT_EQ(nullptr, mvm_->scan_vif);
ASSERT_EQ(false, scan_result_.sme_notified);
ASSERT_EQ(false, scan_result_.success);
- ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start(&mvmvif_sta_, &scan_config_));
+ ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start_passive(&mvmvif_sta_, &passive_scan_args_));
EXPECT_EQ(IWL_MVM_SCAN_REGULAR, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
EXPECT_EQ(&mvmvif_sta_, mvm_->scan_vif);
@@ -550,13 +557,13 @@
/* Tests for both LMAC and UMAC scans */
// Tests condition where scan completion timeouts out due to no response from FW.
-TEST_F(ScanTest, RegPassiveScanTimeout) TA_NO_THREAD_SAFETY_ANALYSIS {
+TEST_F(PassiveScanTest, RegPassiveScanTimeout) __TA_NO_THREAD_SAFETY_ANALYSIS {
ASSERT_EQ(0, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
ASSERT_EQ(nullptr, mvm_->scan_vif);
ASSERT_EQ(false, scan_result.sme_notified);
ASSERT_EQ(false, scan_result.success);
- ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start(&mvmvif_sta, &scan_config));
+ ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start_passive(&mvmvif_sta, &passive_scan_args_));
EXPECT_EQ(IWL_MVM_SCAN_REGULAR, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
EXPECT_EQ(&mvmvif_sta, mvm_->scan_vif);
@@ -571,13 +578,13 @@
}
// Tests condition where timer is shutdown and there is no response from FW.
-TEST_F(ScanTest, RegPassiveScanTimerShutdown) TA_NO_THREAD_SAFETY_ANALYSIS {
+TEST_F(PassiveScanTest, RegPassiveScanTimerShutdown) __TA_NO_THREAD_SAFETY_ANALYSIS {
ASSERT_EQ(0, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
ASSERT_EQ(nullptr, mvm_->scan_vif);
ASSERT_EQ(false, scan_result.sme_notified);
ASSERT_EQ(false, scan_result.success);
- ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start(&mvmvif_sta, &scan_config));
+ ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start_passive(&mvmvif_sta, &passive_scan_args_));
EXPECT_EQ(IWL_MVM_SCAN_REGULAR, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
EXPECT_EQ(&mvmvif_sta, mvm_->scan_vif);
@@ -591,11 +598,11 @@
}
// Tests condition where iwl_mvm_mac_stop() is invoked while timer is pending.
-TEST_F(ScanTest, RegPassiveScanTimerMvmStop) TA_NO_THREAD_SAFETY_ANALYSIS {
+TEST_F(PassiveScanTest, RegPassiveScanTimerMvmStop) __TA_NO_THREAD_SAFETY_ANALYSIS {
ASSERT_EQ(0, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
ASSERT_EQ(nullptr, mvm_->scan_vif);
- ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start(&mvmvif_sta, &scan_config));
+ ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start_passive(&mvmvif_sta, &passive_scan_args_));
EXPECT_EQ(IWL_MVM_SCAN_REGULAR, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
EXPECT_EQ(&mvmvif_sta, mvm_->scan_vif);
@@ -605,11 +612,11 @@
}
// Tests condition where multiple calls to the scan API returns appropriate error.
-TEST_F(ScanTest, RegPassiveScanParallel) TA_NO_THREAD_SAFETY_ANALYSIS {
+TEST_F(PassiveScanTest, RegPassiveScanParallel) __TA_NO_THREAD_SAFETY_ANALYSIS {
ASSERT_EQ(0, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
- ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start(&mvmvif_sta, &scan_config));
+ ASSERT_EQ(ZX_OK, iwl_mvm_reg_scan_start_passive(&mvmvif_sta, &passive_scan_args_));
EXPECT_EQ(IWL_MVM_SCAN_REGULAR, mvm_->scan_status & IWL_MVM_SCAN_REGULAR);
- EXPECT_EQ(ZX_ERR_SHOULD_WAIT, iwl_mvm_reg_scan_start(&mvmvif_sta, &scan_config));
+ EXPECT_EQ(ZX_ERR_SHOULD_WAIT, iwl_mvm_reg_scan_start_passive(&mvmvif_sta, &passive_scan_args_));
}
///////////////////////////////////////////////////////////////////////////////
@@ -625,12 +632,53 @@
TEST_F(TimeEventTest, NormalCase) {
// wait_for_notif is true.
+ ASSERT_EQ(0, list_length(&mvm_->time_event_list));
ASSERT_EQ(ZX_OK, iwl_mvm_protect_session(mvm_, mvmvif_, 1, 2, 3, true));
+ ASSERT_EQ(1, list_length(&mvm_->time_event_list));
ASSERT_EQ(ZX_OK, iwl_mvm_stop_session_protection(mvmvif_));
+ ASSERT_EQ(0, list_length(&mvm_->time_event_list));
// wait_for_notif is false.
+ ASSERT_EQ(0, list_length(&mvm_->time_event_list));
ASSERT_EQ(ZX_OK, iwl_mvm_protect_session(mvm_, mvmvif_, 1, 2, 3, false));
+ ASSERT_EQ(1, list_length(&mvm_->time_event_list));
ASSERT_EQ(ZX_OK, iwl_mvm_stop_session_protection(mvmvif_));
+ ASSERT_EQ(0, list_length(&mvm_->time_event_list));
+}
+
+TEST_F(TimeEventTest, Notification) {
+ // Set wait_for_notif to false so that we don't wait for TIME_EVENT_NOTIFICATION.
+ ASSERT_EQ(ZX_OK, iwl_mvm_protect_session(mvm_, mvmvif_, 1, 2, 3, false));
+
+ // On the real device, 'te_data->uid' is populated by response of TIME_EVENT_CMD. However, the
+ // iwl_mvm_time_event_send_add() uses iwl_wait_notification() to get the value instead of reading
+ // from the cmd->resp_pkt (see the comment in iwl_mvm_time_event_send_add()).
+ //
+ // However, the current test/sim-mvm.cc is hard to implement the wait notification yet (which
+ // requires multi-threading model). So, the hack is inserting the 'te_data->uid' in the test code.
+ //
+ // TODO(fxbug.dev/87974): remove this hack once the wait notification model is supported in the
+ // testing code.
+ //
+ ASSERT_EQ(1, list_length(&mvm_->time_event_list));
+ auto* te_data = list_peek_head_type(&mvm_->time_event_list, struct iwl_mvm_time_event_data, list);
+ te_data->uid = kFakeUniqueId;
+
+ // Generate a fake TIME_EVENT_NOTIFICATION from the firmware. Note that this notification is
+ // differnt from the above code, which is the notification for TIME_EVENT_CMD.
+ //
+ // We expect the driver will remove the waiting notification from the `time_event_list`.
+ //
+ // TODO(fxbug.dev/51671): remove this hack once the test/sim-mvm.cc can support filing another
+ // notification from one host command.
+ //
+ struct iwl_time_event_notif notif = {
+ .unique_id = kFakeUniqueId,
+ .action = TE_V2_NOTIF_HOST_EVENT_END,
+ };
+ TestRxcb time_event_rxcb(sim_trans_.iwl_trans()->dev, ¬if, sizeof(notif));
+ iwl_mvm_rx_time_event_notif(mvm_, &time_event_rxcb);
+ ASSERT_EQ(0, list_length(&mvm_->time_event_list));
}
///////////////////////////////////////////////////////////////////////////////
@@ -721,14 +769,15 @@
} {
BIND_TEST(mvm_->trans);
- for (size_t i = 0; i < ARRAY_SIZE(sta_.txq); ++i) {
+ mvm_->fw_id_to_mac_id[0] = &sta_;
+ for (size_t i = 0; i < std::size(sta_.txq); ++i) {
sta_.txq[i] = reinterpret_cast<struct iwl_mvm_txq*>(calloc(1, sizeof(struct iwl_mvm_txq)));
ASSERT_NE(nullptr, sta_.txq[i]);
}
}
~TxqTest() {
- for (size_t i = 0; i < ARRAY_SIZE(sta_.txq); ++i) {
+ for (size_t i = 0; i < std::size(sta_.txq); ++i) {
free(sta_.txq[i]);
}
}
@@ -805,7 +854,7 @@
iwl_tx_cmd tx_cmd = {
.tx_flags = TX_CMD_FLG_TSF, // arbitary value to ensure the function would keep it.
};
- iwl_mvm_set_tx_cmd(mvmvif_->mvm, &pkt, &tx_cmd, sta_.sta_id);
+ iwl_mvm_set_tx_cmd(mvmvif_->mvm, &pkt, &tx_cmd, static_cast<uint8_t>(sta_.sta_id));
// Currently the function doesn't consider the QoS so that those values are just fixed value.
EXPECT_EQ(TX_CMD_FLG_TSF | TX_CMD_FLG_SEQ_CTL | TX_CMD_FLG_BT_DIS | TX_CMD_FLG_ACK,
@@ -820,15 +869,40 @@
TEST_F(TxqTest, DataTxCmdRate) {
iwl_tx_cmd tx_cmd = {};
- iwl_mvm_set_tx_cmd_rate(mvmvif_->mvm, &tx_cmd);
+ struct ieee80211_frame_header frame_hdr;
+ // construct a data frame, and check the rate.
+ frame_hdr.frame_ctrl |= IEEE80211_FRAME_TYPE_DATA;
+ sta_.sta_state = IWL_STA_AUTHORIZED;
+
+ iwl_mvm_set_tx_cmd_rate(mvmvif_->mvm, &tx_cmd, &frame_hdr);
+
+ // Verify tx_cmd rate fields when frame type is data frame when station is authorized, the rate
+ // should not be set.
+ EXPECT_EQ(0, tx_cmd.initial_rate_index);
+ EXPECT_GT(tx_cmd.tx_flags & cpu_to_le32(TX_CMD_FLG_STA_RATE), 0);
+ EXPECT_EQ(0, tx_cmd.rate_n_flags);
EXPECT_EQ(IWL_RTS_DFAULT_RETRY_LIMIT, tx_cmd.rts_retry_limit);
- EXPECT_EQ(IWL_RATE_6M_PLCP | BIT(mvm_->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS,
- tx_cmd.rate_n_flags);
EXPECT_EQ(IWL_DEFAULT_TX_RETRY, tx_cmd.data_retry_limit);
}
-TEST_F(TxqTest, TxpktInvalidInput) {
+TEST_F(TxqTest, MgmtTxCmdRate) {
+ iwl_tx_cmd tx_cmd = {};
+ struct ieee80211_frame_header frame_hdr;
+
+ // construct a non-data frame, and check the rate.
+ frame_hdr.frame_ctrl |= IEEE80211_FRAME_TYPE_MGMT;
+
+ iwl_mvm_set_tx_cmd_rate(mvmvif_->mvm, &tx_cmd, &frame_hdr);
+
+ // Because the rate which is set to non-data frame in our code is a temporary value, so this line
+ // might be changed in the future.
+ EXPECT_EQ(iwl_mvm_mac80211_idx_to_hwrate(IWL_FIRST_OFDM_RATE) |
+ (BIT(mvm_->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS),
+ tx_cmd.rate_n_flags);
+}
+
+TEST_F(TxqTest, TxPktInvalidInput) {
WlanPktBuilder builder;
std::shared_ptr<WlanPktBuilder::WlanPkt> wlan_pkt(builder.build());
@@ -865,6 +939,33 @@
unbindTx();
}
+// Check to see Tx params are set correctly based on frame control
+TEST_F(TxqTest, TxPktProtected) {
+ // Send a protected data frame and see that the crypt header is being added
+ WlanPktBuilder builder;
+ std::shared_ptr<WlanPktBuilder::WlanPkt> wlan_pkt(builder.build(0x4188));
+
+ EXPECT_EQ(wlan_pkt->mac_pkt()->headroom_used_size, 0);
+ // Setup a key conf to pretend that this is a secure connection
+ auto key_conf = reinterpret_cast<ieee80211_key_conf*>(malloc(sizeof(ieee80211_key_conf) + 16));
+ memset(key_conf, 0, sizeof(*key_conf) + 16);
+ key_conf->cipher = 4;
+ key_conf->key_type = 1;
+ key_conf->keyidx = 0;
+ key_conf->keylen = 16;
+ key_conf->rx_seq = 0;
+ wlan_pkt->mac_pkt()->info.control.hw_key = key_conf;
+
+ bindTx(tx_wrapper);
+ // Expect the packet length to be 8 bytes longer
+ mock_tx_.ExpectCall(ZX_OK, wlan_pkt->len() + 8, WIDE_ID(0, TX_CMD), 0);
+ EXPECT_EQ(ZX_OK, iwl_mvm_tx_skb(mvmvif_->mvm, wlan_pkt->mac_pkt(), &sta_));
+ unbindTx();
+ // Expect that the headroom size is set to 8
+ EXPECT_EQ(wlan_pkt->mac_pkt()->headroom_used_size, 8);
+ free(key_conf);
+}
+
} // namespace
} // namespace testing
} // namespace wlan
diff --git a/third_party/iwlwifi/test/notif-wait-test.cc b/third_party/iwlwifi/test/notif-wait-test.cc
index 9405610..448d089 100644
--- a/third_party/iwlwifi/test/notif-wait-test.cc
+++ b/third_party/iwlwifi/test/notif-wait-test.cc
@@ -8,6 +8,8 @@
// IRQ) and the user (the driver code waiting for the notification from firmware). In this file,
// we will act as those 2 parties in a test case.
+#include <iterator>
+
#include <zxtest/zxtest.h>
extern "C" {
@@ -49,7 +51,7 @@
static void helper_create_fake_cmd(struct iwl_notif_wait_data* wait_data,
struct iwl_notification_wait* wait_entry, uint16_t fake_cmd) {
uint16_t cmds[] = {fake_cmd};
- iwl_init_notification_wait(wait_data, wait_entry, cmds, countof(cmds), nullptr, nullptr);
+ iwl_init_notification_wait(wait_data, wait_entry, cmds, std::size(cmds), nullptr, nullptr);
}
// Helper function for test case init. This would create a wait_entry for fake cmd 1.
@@ -220,7 +222,7 @@
iwl_notification_wait_init(wait_data);
uint16_t cmds[] = {FAKE_CMD_1};
- iwl_init_notification_wait(wait_data, wait_entry, cmds, countof(cmds), fn, fn_data);
+ iwl_init_notification_wait(wait_data, wait_entry, cmds, std::size(cmds), fn, fn_data);
}
TEST_F(NotifWaitTest, FnReturnsTrue) {
diff --git a/third_party/iwlwifi/test/nvm-test.cc b/third_party/iwlwifi/test/nvm-test.cc
index deca6e9..f04437a 100644
--- a/third_party/iwlwifi/test/nvm-test.cc
+++ b/third_party/iwlwifi/test/nvm-test.cc
@@ -11,14 +11,14 @@
}
#include "third_party/iwlwifi/iwl-drv.h"
-#include "third_party/iwlwifi/test/single-ap-test.h"
+#include "third_party/iwlwifi/test/fake-ucode-test.h"
namespace wlan::testing {
namespace {
-class NvmTest : public SingleApTest {
+class NvmTest : public FakeUcodeTest {
public:
- NvmTest() {}
+ NvmTest() : FakeUcodeTest(0, BIT(IWL_UCODE_TLV_CAPA_LAR_SUPPORT), 0, 0) {}
~NvmTest() {}
};
@@ -48,18 +48,40 @@
// Band and channel info
// - 2G band
- EXPECT_EQ(data->bands[WLAN_INFO_BAND_2GHZ].band, WLAN_INFO_BAND_2GHZ);
- EXPECT_EQ(data->bands[WLAN_INFO_BAND_2GHZ].n_channels, 13);
- EXPECT_EQ(data->bands[WLAN_INFO_BAND_2GHZ].channels[0].ch_num, 1);
+ EXPECT_EQ(data->bands[WLAN_INFO_BAND_TWO_GHZ].band, WLAN_INFO_BAND_TWO_GHZ);
+ EXPECT_EQ(data->bands[WLAN_INFO_BAND_TWO_GHZ].n_channels, 14);
+ EXPECT_EQ(data->bands[WLAN_INFO_BAND_TWO_GHZ].channels[0].ch_num, 1);
// - 5G band
- EXPECT_EQ(data->bands[WLAN_INFO_BAND_5GHZ].band, WLAN_INFO_BAND_5GHZ);
- EXPECT_EQ(data->bands[WLAN_INFO_BAND_5GHZ].n_channels, 25);
- EXPECT_EQ(data->bands[WLAN_INFO_BAND_5GHZ].channels[0].ch_num, 36);
+ EXPECT_EQ(data->bands[WLAN_INFO_BAND_FIVE_GHZ].band, WLAN_INFO_BAND_FIVE_GHZ);
+ EXPECT_EQ(data->bands[WLAN_INFO_BAND_FIVE_GHZ].n_channels, 25);
+ EXPECT_EQ(data->bands[WLAN_INFO_BAND_FIVE_GHZ].channels[0].ch_num, 36);
}
TEST_F(NvmTest, CfgRatesTo80211) {
EXPECT_EQ(2, cfg_rates_to_80211(1 * 10)); // 1 Mbps
}
+TEST_F(NvmTest, UpdateMcc) {
+ auto mvm = iwl_trans_get_mvm(sim_trans_.iwl_trans());
+ struct iwl_mcc_update_resp *resp;
+
+ mtx_lock(&mvm->mutex);
+ EXPECT_EQ(ZX_OK, iwl_mvm_update_mcc(mvm, "US", MCC_SOURCE_WIFI, &resp));
+ mtx_unlock(&mvm->mutex);
+
+ EXPECT_EQ(resp->mcc, 0x5553); // "US"
+
+ free(resp);
+}
+
+TEST_F(NvmTest, InitMcc) {
+ auto mvm = iwl_trans_get_mvm(sim_trans_.iwl_trans());
+
+ mtx_lock(&mvm->mutex);
+ EXPECT_EQ(ZX_OK, iwl_mvm_init_mcc(mvm));
+ mtx_unlock(&mvm->mutex);
+ EXPECT_EQ(true, mvm->lar_regdom_set);
+}
+
} // namespace
} // namespace wlan::testing
diff --git a/third_party/iwlwifi/test/pcie-test.cc b/third_party/iwlwifi/test/pcie-test.cc
index dd8c396..c2a5b35 100644
--- a/third_party/iwlwifi/test/pcie-test.cc
+++ b/third_party/iwlwifi/test/pcie-test.cc
@@ -31,18 +31,18 @@
#include "src/devices/testing/mock-ddk/mock-device.h"
extern "C" {
-#include "fw/api/commands.h"
-#include "iwl-csr.h"
-#include "pcie/internal.h"
+#include "third_party/iwlwifi/fw/api/commands.h"
+#include "third_party/iwlwifi/iwl-csr.h"
+#include "third_party/iwlwifi/pcie/internal.h"
}
-#include "align.h"
-#include "platform/ieee80211.h"
-#include "platform/irq.h"
-#include "platform/kernel.h"
-#include "platform/memory.h"
-#include "platform/pcie-device.h"
-#include "test/wlan-pkt-builder.h"
+#include "third_party/iwlwifi/platform/align.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
+#include "third_party/iwlwifi/platform/irq.h"
+#include "third_party/iwlwifi/platform/kernel.h"
+#include "third_party/iwlwifi/platform/memory.h"
+#include "third_party/iwlwifi/platform/pcie-device.h"
+#include "third_party/iwlwifi/test/wlan-pkt-builder.h"
#include "src/devices/pci/testing/pci_protocol_fake.h"
namespace {
@@ -333,7 +333,7 @@
for (uint32_t i = from; i <= to; ++i) {
struct iwl_rx_mem_buffer* rxb = rxq->queue[i];
for (size_t offset = 0; offset < iwl_iobuf_size(rxb->io_buf);
- offset += ZX_ALIGN(1, FH_RSCSR_FRAME_ALIGN)) { // move to next packet
+ offset += IWL_ALIGN(1, FH_RSCSR_FRAME_ALIGN)) { // move to next packet
struct iwl_rx_cmd_buffer rxcb = {
._iobuf = rxb->io_buf,
._offset = static_cast<int>(offset),
@@ -479,7 +479,7 @@
EXPECT_EQ(trans_pcie_->ict_index, 4);
// This should match ICT_COUNT defined in pcie/rx.c.
- size_t ict_count = iwl_iobuf_size(trans_pcie_->ict_tbl) / sizeof(uint32_t);
+ int ict_count = static_cast<int>(iwl_iobuf_size(trans_pcie_->ict_tbl) / sizeof(uint32_t));
// Guarantee that we have enough room in the table for the tests.
ASSERT_GT(ict_count, 42);
diff --git a/third_party/iwlwifi/test/phy-ctxt-test.cc b/third_party/iwlwifi/test/phy-ctxt-test.cc
index adf93a4..4cb8c32 100644
--- a/third_party/iwlwifi/test/phy-ctxt-test.cc
+++ b/third_party/iwlwifi/test/phy-ctxt-test.cc
@@ -4,7 +4,7 @@
// Used to test mvm/phy-ctxt.c
-#include <lib/zircon-internal/thread_annotations.h>
+#include <zircon/compiler.h>
#include <zxtest/zxtest.h>
@@ -20,11 +20,11 @@
class PhyContextTest : public SingleApTest {
public:
- PhyContextTest() TA_NO_THREAD_SAFETY_ANALYSIS {
+ PhyContextTest() __TA_NO_THREAD_SAFETY_ANALYSIS {
mvm_ = iwl_trans_get_mvm(sim_trans_.iwl_trans());
mtx_lock(&mvm_->mutex);
}
- ~PhyContextTest() TA_NO_THREAD_SAFETY_ANALYSIS { mtx_unlock(&mvm_->mutex); }
+ ~PhyContextTest() __TA_NO_THREAD_SAFETY_ANALYSIS { mtx_unlock(&mvm_->mutex); }
protected:
struct iwl_mvm* mvm_;
diff --git a/third_party/iwlwifi/test/platform-test.cc b/third_party/iwlwifi/test/platform-test.cc
index 6435a23..311693c 100644
--- a/third_party/iwlwifi/test/platform-test.cc
+++ b/third_party/iwlwifi/test/platform-test.cc
@@ -129,6 +129,49 @@
EXPECT_EQ(32, find_first_bit(test2, 64));
}
+TEST_F(PlatformTest, find_last_bit) {
+ unsigned test0[] = {
+ 0x00000000,
+ 0x00000000,
+ };
+ EXPECT_EQ(1, find_last_bit(test0, 1)); // Not found
+ EXPECT_EQ(31, find_last_bit(test0, 31)); // Not found
+ EXPECT_EQ(32, find_last_bit(test0, 32)); // Not found
+ EXPECT_EQ(64, find_last_bit(test0, 64)); // Not found
+
+ unsigned test1[] = {
+ 0x40000000,
+ 0x00010001,
+ };
+ ASSERT_EQ(sizeof(*test1), 4);
+ EXPECT_EQ(1, find_last_bit(test1, 1)); // Not found
+ EXPECT_EQ(30, find_last_bit(test1, 31));
+ EXPECT_EQ(30, find_last_bit(test1, 32));
+ EXPECT_EQ(32, find_last_bit(test1, 33));
+ EXPECT_EQ(32, find_last_bit(test1, 48));
+ EXPECT_EQ(48, find_last_bit(test1, 64));
+
+ unsigned test2[] = {
+ 0x00000000,
+ 0x80000000,
+ };
+ EXPECT_EQ(31, find_last_bit(test2, 31)); // Not found
+ EXPECT_EQ(32, find_last_bit(test2, 32)); // Not found
+ EXPECT_EQ(33, find_last_bit(test2, 33)); // Not found
+ EXPECT_EQ(63, find_last_bit(test2, 64));
+}
+
+TEST_F(PlatformTest, find_next_bit) {
+ unsigned test[] = {
+ 0x00001000,
+ 0x00000000,
+ };
+
+ EXPECT_EQ(32, find_next_bit(test, 32, 16)); // Not found
+ EXPECT_EQ(12, find_next_bit(test, 32, 0));
+ EXPECT_EQ(12, find_next_bit(test, 64, 0));
+}
+
TEST_F(PlatformTest, HexDumpErrorHandling) {
char buf[HEX_DUMP_BUF_SIZE - 1];
uint8_t data[] = {};
diff --git a/third_party/iwlwifi/test/rcu-manager-test.cc b/third_party/iwlwifi/test/rcu-manager-test.cc
new file mode 100644
index 0000000..aeb2f82
--- /dev/null
+++ b/third_party/iwlwifi/test/rcu-manager-test.cc
@@ -0,0 +1,115 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/iwlwifi/platform/rcu-manager.h"
+
+#include <lib/async-testing/test_loop.h>
+#include <lib/sync/completion.h>
+#include <zircon/time.h>
+
+#include <memory>
+#include <thread>
+
+#include <zxtest/zxtest.h>
+
+namespace wlan::testing {
+namespace {
+
+TEST(RcuManagerTest, NestedReadLock) {
+ auto test_loop = std::make_unique<::async::TestLoop>();
+ auto manager = std::make_unique<::wlan::iwlwifi::RcuManager>(test_loop->dispatcher());
+
+ manager->InitForThread();
+ manager->ReadLock();
+
+ // Call RcuManager::Sync() on another thread.
+ bool synced = false;
+ std::thread sync_thread([&]() {
+ manager->InitForThread();
+ manager->Sync();
+ synced = true;
+ });
+ EXPECT_FALSE(synced);
+
+ // Nesting a lock and then unlocking it (without unlocking the outer lock) should not cause the
+ // Sync() call to complete yet.
+ manager->ReadLock();
+ EXPECT_FALSE(synced);
+ manager->ReadUnlock();
+ EXPECT_FALSE(synced);
+
+ // Unlocking the lock a final time should allow the Sync() call to finish.
+ manager->ReadUnlock();
+ sync_thread.join();
+ EXPECT_TRUE(synced);
+}
+
+TEST(RcuManagerTest, ThreadedReadLock) {
+ auto test_loop = std::make_unique<::async::TestLoop>();
+ auto manager = std::make_unique<::wlan::iwlwifi::RcuManager>(test_loop->dispatcher());
+
+ manager->InitForThread();
+ manager->ReadLock();
+
+ // Perform a read-side lock on another thread.
+ sync_completion_t thread_started = {};
+ sync_completion_t thread_continue = {};
+ std::thread lock_thread([&]() {
+ manager->InitForThread();
+ manager->ReadLock();
+ sync_completion_signal(&thread_started);
+ sync_completion_wait(&thread_continue, ZX_TIME_INFINITE);
+ manager->ReadUnlock();
+ });
+
+ // Wait for the other thread to read-side lock.
+ sync_completion_wait(&thread_started, ZX_TIME_INFINITE);
+
+ // Start a thread that waits for a sync.
+ bool synced = false;
+ std::thread sync_thread([&]() {
+ manager->InitForThread();
+ manager->Sync();
+ synced = true;
+ });
+ EXPECT_FALSE(synced);
+
+ // Unlocking this thread still means another thread is holding the read-side lock.
+ manager->ReadUnlock();
+ EXPECT_FALSE(synced);
+
+ // Unlocking the other thread finally allows the Sync() to complete.
+ sync_completion_signal(&thread_continue);
+ lock_thread.join();
+ sync_thread.join();
+ EXPECT_TRUE(synced);
+}
+
+TEST(RcuManagerTest, CallSync) {
+ auto test_loop = std::make_unique<::async::TestLoop>();
+ auto manager = std::make_unique<::wlan::iwlwifi::RcuManager>(test_loop->dispatcher());
+
+ manager->InitForThread();
+ manager->ReadLock();
+
+ // Prepare a call that will execute after all read-side locks are unlocked.
+ bool called = false;
+ manager->CallSync([](void* data) { *reinterpret_cast<bool*>(data) = true; }, &called);
+ std::thread loop_thread([&]() { test_loop->RunUntilIdle(); });
+ EXPECT_FALSE(called);
+
+ // A nested lock will not cause the call to executed.
+ manager->ReadLock();
+ EXPECT_FALSE(called);
+ manager->ReadUnlock();
+ EXPECT_FALSE(called);
+
+ // Unlocking the last lock allows the call to proceed.
+ manager->ReadUnlock();
+ loop_thread.join();
+ EXPECT_TRUE(called);
+}
+
+} // namespace
+} // namespace wlan::testing
diff --git a/third_party/iwlwifi/test/sim-mcc-update.cc b/third_party/iwlwifi/test/sim-mcc-update.cc
new file mode 100644
index 0000000..0464f73
--- /dev/null
+++ b/third_party/iwlwifi/test/sim-mcc-update.cc
@@ -0,0 +1,29 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/iwlwifi/test/sim-mcc-update.h"
+
+#include <string.h>
+#include <zircon/assert.h>
+
+extern "C" {
+#include "third_party/iwlwifi/mvm/mvm.h"
+}
+
+namespace wlan::testing {
+
+zx_status_t HandleMccUpdate(struct iwl_host_cmd* cmd, SimMvmResponse* resp) {
+ auto mcc_cmd = reinterpret_cast<const struct iwl_mcc_update_cmd*>(cmd->data[0]);
+
+ resp->resize(sizeof(struct iwl_mcc_update_resp_v3));
+ auto mcc_resp = reinterpret_cast<struct iwl_mcc_update_resp_v3*>(resp->data());
+ memset(mcc_resp, 0, sizeof(*mcc_resp));
+ mcc_resp->status = le32_to_cpu(MCC_RESP_NEW_CHAN_PROFILE);
+ mcc_resp->mcc = mcc_cmd->mcc;
+ mcc_resp->source_id = mcc_cmd->source_id;
+
+ return ZX_OK;
+}
+
+} // namespace wlan::testing
diff --git a/third_party/iwlwifi/test/sim-mcc-update.h b/third_party/iwlwifi/test/sim-mcc-update.h
new file mode 100644
index 0000000..fb87ade
--- /dev/null
+++ b/third_party/iwlwifi/test/sim-mcc-update.h
@@ -0,0 +1,21 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// To simulate the TIME_EVENT_CMD in the testing code.
+
+#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_SIM_MCC_UPDATE_H_
+#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_SIM_MCC_UPDATE_H_
+
+#include <zircon/types.h>
+
+#include "third_party/iwlwifi/iwl-trans.h"
+#include "third_party/iwlwifi/test/sim.h"
+
+namespace wlan::testing {
+
+zx_status_t HandleMccUpdate(struct iwl_host_cmd* cmd, SimMvmResponse* resp);
+
+} // namespace wlan::testing
+
+#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_SIM_MCC_UPDATE_H_
diff --git a/third_party/iwlwifi/test/sim-mvm.cc b/third_party/iwlwifi/test/sim-mvm.cc
index ac79f6e..7a1cc1e 100644
--- a/third_party/iwlwifi/test/sim-mvm.cc
+++ b/third_party/iwlwifi/test/sim-mvm.cc
@@ -4,6 +4,9 @@
#include "third_party/iwlwifi/test/sim-mvm.h"
+#include "third_party/iwlwifi/test/sim-mcc-update.h"
+#include "third_party/iwlwifi/test/sim-time-event.h"
+
extern "C" {
#include "third_party/iwlwifi/fw/api/commands.h"
#include "third_party/iwlwifi/fw/api/datapath.h"
@@ -40,7 +43,8 @@
// On real hardware, this command will reply a pakcet to unblock the driver waiting.
// In the simulated code, we don't generate the packet. Instead, we unblock it directly.
case PHY_CONFIGURATION_CMD:
- // passthru
+ *notify_wait = true;
+ return ZX_OK;
// The driver code expects 2 notifications from the firmware in this command:
//
@@ -51,11 +55,11 @@
// However, the current sim-mvm code can only unblock the first wait. So added
// TODO(fxbug.dev/51671) to track this.
case TIME_EVENT_CMD:
- // passthru
-
- // The above commands require unblock the notification.
+ ret = HandleTimeEvent(cmd, &resp);
*notify_wait = true;
- __FALLTHROUGH;
+ break;
+
+ // Below commands don't require a response in the testing code to continue.
case SHARED_MEM_CFG:
case TX_ANT_CONFIGURATION_CMD:
case PHY_DB_CMD:
@@ -65,6 +69,7 @@
case BT_CONFIG:
case MAC_CONTEXT_CMD:
case TXPATH_FLUSH:
+ case LQ_CMD:
case SCAN_OFFLOAD_REQUEST_CMD:
case SCAN_CFG_CMD:
case SCAN_REQ_UMAC:
@@ -76,7 +81,7 @@
case REPLY_BEACON_FILTERING_CMD:
return ZX_OK;
- // Command would return 'status' back to driver.
+ // Commands would return 'status' back to driver.
case BINDING_CONTEXT_CMD:
build_response_with_status(&resp, 0);
ret = ZX_OK;
@@ -89,6 +94,10 @@
ret = ZX_OK;
break;
+ case MCC_UPDATE_CMD:
+ ret = HandleMccUpdate(cmd, &resp);
+ break;
+
case NVM_ACCESS_CMD:
ret = nvm_.HandleCommand(cmd, &resp);
break;
diff --git a/third_party/iwlwifi/test/sim-mvm.h b/third_party/iwlwifi/test/sim-mvm.h
index 01ed86f..eab33da 100644
--- a/third_party/iwlwifi/test/sim-mvm.h
+++ b/third_party/iwlwifi/test/sim-mvm.h
@@ -8,9 +8,6 @@
#include <memory>
#include <vector>
-#include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h"
-#include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-sta-ifc.h"
-
extern "C" {
#include "third_party/iwlwifi/iwl-trans.h"
} // extern "C"
@@ -20,16 +17,9 @@
namespace wlan::testing {
-class SimMvm : public ::wlan::simulation::StationIfc {
+class SimMvm {
public:
- explicit SimMvm(::wlan::simulation::Environment* env) : env_(env), resp_buf_(kNvmAccessCmdSize) {
- env->AddStation(this);
- }
- ~SimMvm() {
- if (env_ != nullptr) {
- env_->RemoveStation(this);
- }
- }
+ explicit SimMvm() : resp_buf_(kNvmAccessCmdSize) {}
// Execute the command.
//
@@ -39,16 +29,11 @@
//
zx_status_t SendCmd(struct iwl_host_cmd* cmd, bool* notify_wait);
- // StationIfc operations
- void Rx(std::shared_ptr<const simulation::SimFrame> frame,
- std::shared_ptr<const simulation::WlanRxInfo> info) override {}
-
private:
// The buffer size should be determined by the max response size.
// This number is for the response of NVM_ACCESS_CMD read command.
static constexpr size_t kNvmAccessCmdSize = 16 + 2048;
- ::wlan::simulation::Environment* env_;
SimNvm nvm_;
// Used by SendCmd() to store the response from the simulated firmware functions.
diff --git a/third_party/iwlwifi/test/sim-nvm-data.inc b/third_party/iwlwifi/test/sim-nvm-data.inc
index eaa3a41..fe18d0a 100644
--- a/third_party/iwlwifi/test/sim-nvm-data.inc
+++ b/third_party/iwlwifi/test/sim-nvm-data.inc
@@ -910,7 +910,7 @@
.data = {},
}};
return kDefaultNvmSections;
-};
+}
} // namespace
} // namespace wlan::testing
diff --git a/third_party/iwlwifi/test/sim-nvm.cc b/third_party/iwlwifi/test/sim-nvm.cc
index 4c8ad34..529e4d8 100644
--- a/third_party/iwlwifi/test/sim-nvm.cc
+++ b/third_party/iwlwifi/test/sim-nvm.cc
@@ -7,6 +7,7 @@
#include <string.h>
#include <zircon/assert.h>
+#include <algorithm>
#include <vector>
extern "C" {
@@ -35,17 +36,11 @@
}
// Handle the boundary cases.
- size_t size = iter.data.size();
- if (offset > size) {
- offset = size;
- }
- if (offset + length > size) {
- length = size - offset;
- }
-
+ const size_t read_offset = std::min<size_t>(offset, iter.data.size());
+ const size_t read_length = std::min<size_t>(length, iter.data.size() - read_offset);
std::vector<uint8_t> ret;
- ret.reserve(length);
- std::copy_n(iter.data.begin() + offset, length, std::back_inserter(ret));
+ ret.reserve(read_length);
+ std::copy_n(iter.data.begin() + read_offset, read_length, std::back_inserter(ret));
return ret;
}
diff --git a/third_party/iwlwifi/test/sim-time-event.cc b/third_party/iwlwifi/test/sim-time-event.cc
new file mode 100644
index 0000000..5744807
--- /dev/null
+++ b/third_party/iwlwifi/test/sim-time-event.cc
@@ -0,0 +1,29 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/iwlwifi/test/sim-time-event.h"
+
+#include <string.h>
+#include <zircon/assert.h>
+
+extern "C" {
+#include "third_party/iwlwifi/mvm/mvm.h"
+}
+
+namespace wlan::testing {
+
+zx_status_t HandleTimeEvent(struct iwl_host_cmd* cmd, SimMvmResponse* resp) {
+ auto tm_cmd = reinterpret_cast<const struct iwl_time_event_cmd*>(cmd->data[0]);
+
+ resp->resize(sizeof(struct iwl_time_event_resp));
+ auto tm_resp = reinterpret_cast<struct iwl_time_event_resp*>(resp->data());
+ memset(tm_resp, 0, sizeof(*tm_resp));
+ // Copy the 'id' field from the command and fill a fake value in 'unique_id' field.
+ tm_resp->id = le32_to_cpu(tm_cmd->id);
+ tm_resp->unique_id = le32_to_cpu(kFakeUniqueId);
+
+ return ZX_OK;
+}
+
+} // namespace wlan::testing
diff --git a/third_party/iwlwifi/test/sim-time-event.h b/third_party/iwlwifi/test/sim-time-event.h
new file mode 100644
index 0000000..70cca7b
--- /dev/null
+++ b/third_party/iwlwifi/test/sim-time-event.h
@@ -0,0 +1,25 @@
+// Copyright 2021 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// To simulate the TIME_EVENT_CMD in the testing code.
+
+#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_SIM_TIME_EVENT_H_
+#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_SIM_TIME_EVENT_H_
+
+#include <zircon/types.h>
+
+#include "third_party/iwlwifi/iwl-trans.h"
+#include "third_party/iwlwifi/test/sim.h"
+
+namespace wlan::testing {
+
+// The returned unique_id for the time event command. On the real firmware, this value is
+// generated randomly. But a fake fixed value is good enough for the testing code.
+constexpr uint16_t kFakeUniqueId = 0x5566;
+
+zx_status_t HandleTimeEvent(struct iwl_host_cmd* cmd, SimMvmResponse* resp);
+
+} // namespace wlan::testing
+
+#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_SIM_TIME_EVENT_H_
diff --git a/third_party/iwlwifi/test/sim-trans.cc b/third_party/iwlwifi/test/sim-trans.cc
index f143a9a..5ed7a22 100644
--- a/third_party/iwlwifi/test/sim-trans.cc
+++ b/third_party/iwlwifi/test/sim-trans.cc
@@ -18,7 +18,7 @@
#include "third_party/iwlwifi/test/sim-trans.h"
-#include <fuchsia/hardware/wlan/mac/c/banjo.h>
+#include <fuchsia/hardware/wlan/softmac/c/banjo.h>
#include <fuchsia/hardware/wlanphyimpl/c/banjo.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
@@ -35,6 +35,7 @@
}
#include "third_party/iwlwifi/platform/mvm-mlme.h"
+#include "third_party/iwlwifi/platform/rcu-manager.h"
#include "third_party/iwlwifi/platform/wlanphy-impl-device.h"
#include "src/devices/testing/mock-ddk/mock-device.h"
@@ -48,7 +49,7 @@
class SimTransDevice : public ::wlan::iwlwifi::WlanphyImplDevice {
public:
explicit SimTransDevice(zx_device_t* parent, iwl_trans* drvdata)
- : WlanphyImplDevice(parent), drvdata_(drvdata){};
+ : WlanphyImplDevice(parent), drvdata_(drvdata) {}
void DdkInit(::ddk::InitTxn txn) override { txn.Reply(ZX_OK); }
void DdkUnbind(::ddk::UnbindTxn txn) override {
struct iwl_trans* trans = drvdata_;
@@ -57,7 +58,7 @@
}
free(trans);
txn.Reply();
- };
+ }
iwl_trans* drvdata() override { return drvdata_; }
const iwl_trans* drvdata() const override { return drvdata_; }
@@ -310,16 +311,17 @@
namespace wlan::testing {
-SimTransport::SimTransport(::wlan::simulation::Environment* env, zx_device_t* parent)
- : SimMvm(env), device_{}, iwl_trans_(nullptr) {
+SimTransport::SimTransport(zx_device_t* parent) : device_{}, iwl_trans_(nullptr) {
task_loop_ = std::make_unique<::async::Loop>(&kAsyncLoopConfigNoAttachToCurrentThread);
task_loop_->StartThread("iwlwifi-test-task-worker", nullptr);
irq_loop_ = std::make_unique<::async::Loop>(&kAsyncLoopConfigNoAttachToCurrentThread);
irq_loop_->StartThread("iwlwifi-test-irq-worker", nullptr);
+ rcu_manager_ = std::make_unique<::wlan::iwlwifi::RcuManager>(task_loop_->dispatcher());
device_.zxdev = parent;
device_.task_dispatcher = task_loop_->dispatcher();
device_.irq_dispatcher = irq_loop_->dispatcher();
+ device_.rcu_manager = static_cast<struct rcu_manager*>(rcu_manager_.get());
fake_bti_create(&device_.bti);
}
@@ -341,8 +343,8 @@
const struct iwl_trans* SimTransport::iwl_trans() const { return iwl_trans_; }
-wlan::iwlwifi::WlanphyImplDevice* SimTransport::sim_device() { return sim_device_; }
+::wlan::iwlwifi::WlanphyImplDevice* SimTransport::sim_device() { return sim_device_; }
-const wlan::iwlwifi::WlanphyImplDevice* SimTransport::sim_device() const { return sim_device_; }
+const ::wlan::iwlwifi::WlanphyImplDevice* SimTransport::sim_device() const { return sim_device_; }
} // namespace wlan::testing
diff --git a/third_party/iwlwifi/test/sim-trans.h b/third_party/iwlwifi/test/sim-trans.h
index ce53d30..a368d67 100644
--- a/third_party/iwlwifi/test/sim-trans.h
+++ b/third_party/iwlwifi/test/sim-trans.h
@@ -15,7 +15,6 @@
#include <memory>
-#include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h"
#include "third_party/iwlwifi/platform/kernel.h"
#include "third_party/iwlwifi/test/sim-mvm.h"
@@ -28,6 +27,7 @@
namespace wlan {
namespace iwlwifi {
+class RcuManager;
class WlanphyImplDevice;
} // namespace iwlwifi
@@ -49,7 +49,7 @@
class SimTransport : public SimMvm {
public:
- explicit SimTransport(::wlan::simulation::Environment* env, zx_device_t* parent);
+ explicit SimTransport(zx_device_t* parent);
~SimTransport();
// This function must be called before starting using other functions.
@@ -58,12 +58,13 @@
// Member accessors.
struct iwl_trans* iwl_trans();
const struct iwl_trans* iwl_trans() const;
- wlan::iwlwifi::WlanphyImplDevice* sim_device();
- const wlan::iwlwifi::WlanphyImplDevice* sim_device() const;
+ ::wlan::iwlwifi::WlanphyImplDevice* sim_device();
+ const ::wlan::iwlwifi::WlanphyImplDevice* sim_device() const;
private:
std::unique_ptr<::async::Loop> task_loop_;
std::unique_ptr<::async::Loop> irq_loop_;
+ std::unique_ptr<::wlan::iwlwifi::RcuManager> rcu_manager_;
struct device device_;
struct iwl_trans* iwl_trans_;
wlan::iwlwifi::WlanphyImplDevice* sim_device_;
diff --git a/third_party/iwlwifi/test/single-ap-test.cc b/third_party/iwlwifi/test/single-ap-test.cc
index db98be1..950b47c 100644
--- a/third_party/iwlwifi/test/single-ap-test.cc
+++ b/third_party/iwlwifi/test/single-ap-test.cc
@@ -17,9 +17,7 @@
const common::MacAddr SingleApTest::default_macaddr_(kApAddr);
SingleApTest::SingleApTest()
- : fake_parent_(MockDevice::FakeRootParent()),
- ap_(&env_, default_macaddr_, kSsid, kChannel),
- sim_trans_(&env_, fake_parent_.get()) {
+ : fake_parent_(MockDevice::FakeRootParent()), sim_trans_(fake_parent_.get()) {
// Add a default MVM firmware to the fake DDK.
TlvFwBuilder fw_builder;
@@ -40,7 +38,6 @@
zx_status_t status = sim_trans_.Init();
ZX_ASSERT_MSG(ZX_OK == status, "Transportation initialization failed: %s",
zx_status_get_string(status));
- env_.AddStation(&ap_);
}
SingleApTest::~SingleApTest() = default;
diff --git a/third_party/iwlwifi/test/single-ap-test.h b/third_party/iwlwifi/test/single-ap-test.h
index 3b48dcc..25ddbea 100644
--- a/third_party/iwlwifi/test/single-ap-test.h
+++ b/third_party/iwlwifi/test/single-ap-test.h
@@ -9,10 +9,9 @@
#include <memory>
+#include <wlan/common/macaddr.h>
#include <zxtest/zxtest.h>
-#include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h"
-#include "src/connectivity/wlan/drivers/testing/lib/sim-fake-ap/sim-fake-ap.h"
#include "third_party/iwlwifi/test/sim-trans.h"
#include "src/devices/testing/mock-ddk/mock-device.h"
@@ -38,8 +37,6 @@
static const common::MacAddr default_macaddr_;
std::shared_ptr<MockDevice> fake_parent_;
- ::wlan::simulation::Environment env_;
- ::wlan::simulation::FakeAp ap_;
SimTransport sim_trans_;
};
diff --git a/third_party/iwlwifi/test/stub-mvm.cc b/third_party/iwlwifi/test/stub-mvm.cc
index 10c60c7..128aebd 100644
--- a/third_party/iwlwifi/test/stub-mvm.cc
+++ b/third_party/iwlwifi/test/stub-mvm.cc
@@ -5,9 +5,6 @@
// When MVM isn't otherwise linked into a test, we will need to provide implementations for some of
// its entry points that are not called but still linked in.
-// TODO(rsakthi) - how to get this from bazel?
-#define CPTCFG_IWLMVM 1
-
#include <zircon/errors.h>
#include <zircon/types.h>
diff --git a/third_party/iwlwifi/test/utils-test.cc b/third_party/iwlwifi/test/utils-test.cc
index c565903..6a2f84e 100644
--- a/third_party/iwlwifi/test/utils-test.cc
+++ b/third_party/iwlwifi/test/utils-test.cc
@@ -15,6 +15,8 @@
*/
// Unittest code for the functions in mvm/utils.c
+#include <iterator>
+
#include <zxtest/zxtest.h>
extern "C" {
@@ -37,7 +39,7 @@
ZX_ERR_OUT_OF_RANGE);
// Invalid pointer
- EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(0, WLAN_INFO_BAND_5GHZ, nullptr),
+ EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(0, WLAN_INFO_BAND_FIVE_GHZ, nullptr),
ZX_ERR_INVALID_ARGS);
#if 0 // NEEDS_PORTING
@@ -46,24 +48,27 @@
#endif // NEEDS_PORTING
// 2.4 GHz: data rate: 1 Mbps ~ 54 Mbps
- EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(10 /* 1 Mbpsz */, WLAN_INFO_BAND_2GHZ, &idx),
+ EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(10 /* 1 Mbpsz */, WLAN_INFO_BAND_TWO_GHZ, &idx),
ZX_OK);
EXPECT_EQ(idx, 0);
- EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(3 /* 54 Mbpsz */, WLAN_INFO_BAND_2GHZ, &idx),
+ EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(3 /* 54 Mbpsz */, WLAN_INFO_BAND_TWO_GHZ, &idx),
ZX_OK);
EXPECT_EQ(idx, 11);
// 5 GHz: data rate: 6 Mbps ~ 54 Mbps
- EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(13 /* 6 Mbps */, WLAN_INFO_BAND_5GHZ, &idx), ZX_OK);
+ EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(13 /* 6 Mbps */, WLAN_INFO_BAND_FIVE_GHZ, &idx),
+ ZX_OK);
EXPECT_EQ(idx, 0);
- EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(3 /* 54 Mbps */, WLAN_INFO_BAND_5GHZ, &idx), ZX_OK);
+ EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(3 /* 54 Mbps */, WLAN_INFO_BAND_FIVE_GHZ, &idx),
+ ZX_OK);
EXPECT_EQ(idx, 7);
- EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(10 /* 1 Mbps */, WLAN_INFO_BAND_5GHZ, &idx),
+ EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(10 /* 1 Mbps */, WLAN_INFO_BAND_FIVE_GHZ, &idx),
ZX_ERR_NOT_FOUND);
// Not in the table
- EXPECT_EQ(iwl_mvm_legacy_rate_to_mac80211_idx(0 /* random number */, WLAN_INFO_BAND_5GHZ, &idx),
- ZX_ERR_NOT_FOUND);
+ EXPECT_EQ(
+ iwl_mvm_legacy_rate_to_mac80211_idx(0 /* random number */, WLAN_INFO_BAND_FIVE_GHZ, &idx),
+ ZX_ERR_NOT_FOUND);
}
TEST_F(UtilsTest, Dot11ToHWRate) {
@@ -75,18 +80,18 @@
uint32_t data_rate;
// 2.4 GHz, idx: 0 ~ 11
- EXPECT_EQ(ZX_OK, mac80211_idx_to_data_rate(WLAN_INFO_BAND_2GHZ, 0 /* 1 Mbps */, &data_rate));
+ EXPECT_EQ(ZX_OK, mac80211_idx_to_data_rate(WLAN_INFO_BAND_TWO_GHZ, 0 /* 1 Mbps */, &data_rate));
EXPECT_EQ(data_rate, TO_HALF_MBPS(1));
- EXPECT_EQ(ZX_OK, mac80211_idx_to_data_rate(WLAN_INFO_BAND_2GHZ, 11 /* 54 Mbps */, &data_rate));
+ EXPECT_EQ(ZX_OK, mac80211_idx_to_data_rate(WLAN_INFO_BAND_TWO_GHZ, 11 /* 54 Mbps */, &data_rate));
EXPECT_EQ(data_rate, TO_HALF_MBPS(54));
- EXPECT_EQ(ZX_ERR_INVALID_ARGS, mac80211_idx_to_data_rate(WLAN_INFO_BAND_2GHZ, 12, &data_rate));
+ EXPECT_EQ(ZX_ERR_INVALID_ARGS, mac80211_idx_to_data_rate(WLAN_INFO_BAND_TWO_GHZ, 12, &data_rate));
// 5 GHz, idx: 0 ~ 7
- EXPECT_EQ(ZX_OK, mac80211_idx_to_data_rate(WLAN_INFO_BAND_5GHZ, 0 /* 6 Mbps */, &data_rate));
+ EXPECT_EQ(ZX_OK, mac80211_idx_to_data_rate(WLAN_INFO_BAND_FIVE_GHZ, 0 /* 6 Mbps */, &data_rate));
EXPECT_EQ(data_rate, TO_HALF_MBPS(6));
- EXPECT_EQ(ZX_OK, mac80211_idx_to_data_rate(WLAN_INFO_BAND_5GHZ, 7 /* 54 Mbps */, &data_rate));
+ EXPECT_EQ(ZX_OK, mac80211_idx_to_data_rate(WLAN_INFO_BAND_FIVE_GHZ, 7 /* 54 Mbps */, &data_rate));
EXPECT_EQ(data_rate, TO_HALF_MBPS(54));
- EXPECT_EQ(ZX_ERR_INVALID_ARGS, mac80211_idx_to_data_rate(WLAN_INFO_BAND_5GHZ, 8, &data_rate));
+ EXPECT_EQ(ZX_ERR_INVALID_ARGS, mac80211_idx_to_data_rate(WLAN_INFO_BAND_FIVE_GHZ, 8, &data_rate));
// For future 60 GHz
EXPECT_EQ(ZX_ERR_NOT_SUPPORTED, mac80211_idx_to_data_rate(WLAN_INFO_BAND_COUNT, 0, &data_rate));
@@ -121,7 +126,7 @@
.associated = true,
},
};
- uint8_t vif_count = ARRAY_SIZE(mvmvifs);
+ uint8_t vif_count = std::size(mvmvifs);
ZX_ASSERT(vif_count <= MAX_NUM_MVMVIF);
// Initialize the 'mvm' structure (and its 'mvmvif').
diff --git a/third_party/iwlwifi/test/wlan-pkt-builder.cc b/third_party/iwlwifi/test/wlan-pkt-builder.cc
index 3b471f2..4cae28d 100644
--- a/third_party/iwlwifi/test/wlan-pkt-builder.cc
+++ b/third_party/iwlwifi/test/wlan-pkt-builder.cc
@@ -29,8 +29,8 @@
mac_pkt_->body_size = len - mac_pkt_->header_size;
*wlan_pkt_ = {};
- wlan_pkt_->packet_head.data_buffer = &*buf_;
- wlan_pkt_->packet_head.data_size = len;
+ wlan_pkt_->mac_frame_buffer = &*buf_;
+ wlan_pkt_->mac_frame_size = len;
wlan_pkt_->info.tx_flags = 0;
wlan_pkt_->info.channel_bandwidth = CHANNEL_BANDWIDTH_CBW20;
}
@@ -51,9 +51,11 @@
WlanPktBuilder::~WlanPktBuilder() = default;
-std::shared_ptr<WlanPktBuilder::WlanPkt> WlanPktBuilder::build() {
- static constexpr uint8_t kMacPkt[] = {
- 0x08, 0x01, // frame_ctrl
+std::shared_ptr<WlanPktBuilder::WlanPkt> WlanPktBuilder::build(uint16_t fc) {
+ const uint8_t fc0 = (uint8_t)fc & 0xff;
+ const uint8_t fc1 = (uint8_t)(fc >> 8);
+ const uint8_t kMacPkt[] = {
+ fc0, fc1, // frame_ctrl
0x00, 0x00, // duration
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, // MAC1
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // MAC2
diff --git a/third_party/iwlwifi/test/wlan-pkt-builder.h b/third_party/iwlwifi/test/wlan-pkt-builder.h
index ecc7ee7..d63610e 100644
--- a/third_party/iwlwifi/test/wlan-pkt-builder.h
+++ b/third_party/iwlwifi/test/wlan-pkt-builder.h
@@ -7,14 +7,14 @@
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_WLAN_PKT_BUILDER_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_WLAN_PKT_BUILDER_H_
-#include <fuchsia/hardware/wlan/mac/c/banjo.h>
+#include <fuchsia/hardware/wlan/softmac/c/banjo.h>
#include <stdint.h>
#include <memory>
#include <zxtest/zxtest.h>
-#include "third_party/iwlwifi/platform/ieee80211.h"
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
namespace wlan::testing {
@@ -64,7 +64,7 @@
WlanPktBuilder& operator=(const WlanPktBuilder&) = delete; // copy assignment
WlanPktBuilder& operator=(WlanPktBuilder&&) = delete; // move assignment
- std::shared_ptr<WlanPkt> build();
+ std::shared_ptr<WlanPkt> build(uint16_t fc = 0x0801);
};
} // namespace wlan::testing
diff --git a/third_party/iwlwifi/test/wlan-softmac-device-test.cc b/third_party/iwlwifi/test/wlan-softmac-device-test.cc
new file mode 100644
index 0000000..9fd15fa
--- /dev/null
+++ b/third_party/iwlwifi/test/wlan-softmac-device-test.cc
@@ -0,0 +1,900 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/iwlwifi/platform/wlan-softmac-device.h"
+
+#include <fidl/fuchsia.wlan.ieee80211/cpp/wire_types.h>
+#include <fuchsia/hardware/wlan/associnfo/cpp/banjo.h>
+#include <fuchsia/hardware/wlan/softmac/cpp/banjo.h>
+#include <fuchsia/wlan/ieee80211/c/fidl.h>
+#include <lib/mock-function/mock-function.h>
+#include <lib/zx/channel.h>
+#include <stdlib.h>
+#include <zircon/errors.h>
+#include <zircon/syscalls.h>
+#include <zircon/types.h>
+
+#include <iterator>
+#include <list>
+#include <memory>
+#include <utility>
+
+#include <zxtest/zxtest.h>
+
+extern "C" {
+#include "third_party/iwlwifi/iwl-nvm-parse.h"
+#include "third_party/iwlwifi/mvm/mvm.h"
+} // extern "C"
+
+#include "third_party/iwlwifi/platform/mvm-mlme.h"
+#include "third_party/iwlwifi/platform/scoped_utils.h"
+#include "third_party/iwlwifi/test/mock-trans.h"
+#include "third_party/iwlwifi/test/single-ap-test.h"
+#include "third_party/iwlwifi/test/wlan-pkt-builder.h"
+
+namespace wlan::testing {
+namespace {
+
+constexpr size_t kListenInterval = 100;
+constexpr uint8_t kInvalidBandIdFillByte = 0xa5;
+constexpr wlan_info_band_t kInvalidBandId = 0xa5a5a5a5;
+constexpr zx_handle_t kDummyMlmeChannel = 73939133; // An arbitrary value not ZX_HANDLE_INVALID
+
+using recv_cb_t = mock_function::MockFunction<void, void*, const wlan_rx_packet_t*>;
+
+// Short-cut to access the iwl_cfg80211_rates[] structure and convert it to 802.11 rate.
+//
+// Args:
+// index: the index of iwl_cfg80211_rates[].
+//
+// Returns:
+// the 802.11 rate.
+//
+static unsigned expected_rate(size_t index) {
+ return cfg_rates_to_80211(iwl_cfg80211_rates[index]);
+}
+
+// The wrapper used by wlan_softmac_ifc_t.recv() to call mock-up.
+void recv_wrapper(void* cookie, const wlan_rx_packet_t* packet) {
+ auto recv = reinterpret_cast<recv_cb_t*>(cookie);
+ recv->Call(cookie, packet);
+}
+
+class WlanSoftmacDeviceTest : public SingleApTest {
+ public:
+ WlanSoftmacDeviceTest() {
+ mvmvif_.reset(reinterpret_cast<struct iwl_mvm_vif*>(calloc(1, sizeof(struct iwl_mvm_vif))));
+ mvmvif_->mvm = iwl_trans_get_mvm(sim_trans_.iwl_trans());
+ mvmvif_->mlme_channel = kDummyMlmeChannel;
+ mvmvif_->mac_role = WLAN_MAC_ROLE_CLIENT;
+ mvmvif_->bss_conf = {.beacon_int = kListenInterval};
+
+ device_ = std::make_unique<::wlan::iwlwifi::WlanSoftmacDevice>(nullptr, sim_trans_.iwl_trans(),
+ 0, mvmvif_.get());
+ }
+ ~WlanSoftmacDeviceTest() override {}
+
+ protected:
+ wlan::iwlwifi::unique_free_ptr<struct iwl_mvm_vif> mvmvif_;
+ std::unique_ptr<::wlan::iwlwifi::WlanSoftmacDevice> device_;
+};
+
+//////////////////////////////////// Helper Functions /////////////////////////////////////////////
+
+TEST_F(WlanSoftmacDeviceTest, ComposeBandList) {
+ struct iwl_nvm_data nvm_data;
+ wlan_info_band_t bands[WLAN_INFO_BAND_COUNT];
+
+ // nothing enabled
+ memset(&nvm_data, 0, sizeof(nvm_data));
+ memset(bands, kInvalidBandIdFillByte, sizeof(bands));
+ EXPECT_EQ(0, compose_band_list(&nvm_data, bands));
+ EXPECT_EQ(kInvalidBandId, bands[0]);
+ EXPECT_EQ(kInvalidBandId, bands[1]);
+
+ // 2.4GHz only
+ memset(&nvm_data, 0, sizeof(nvm_data));
+ memset(bands, kInvalidBandIdFillByte, sizeof(bands));
+ nvm_data.sku_cap_band_24ghz_enable = true;
+ EXPECT_EQ(1, compose_band_list(&nvm_data, bands));
+ EXPECT_EQ(WLAN_INFO_BAND_TWO_GHZ, bands[0]);
+ EXPECT_EQ(kInvalidBandId, bands[1]);
+
+ // 5GHz only
+ memset(&nvm_data, 0, sizeof(nvm_data));
+ memset(bands, kInvalidBandIdFillByte, sizeof(bands));
+ nvm_data.sku_cap_band_52ghz_enable = true;
+ EXPECT_EQ(1, compose_band_list(&nvm_data, bands));
+ EXPECT_EQ(WLAN_INFO_BAND_FIVE_GHZ, bands[0]);
+ EXPECT_EQ(kInvalidBandId, bands[1]);
+
+ // both bands enabled
+ memset(&nvm_data, 0, sizeof(nvm_data));
+ memset(bands, kInvalidBandIdFillByte, sizeof(bands));
+ nvm_data.sku_cap_band_24ghz_enable = true;
+ nvm_data.sku_cap_band_52ghz_enable = true;
+ EXPECT_EQ(2, compose_band_list(&nvm_data, bands));
+ EXPECT_EQ(WLAN_INFO_BAND_TWO_GHZ, bands[0]);
+ EXPECT_EQ(WLAN_INFO_BAND_FIVE_GHZ, bands[1]);
+}
+
+TEST_F(WlanSoftmacDeviceTest, FillBandInfos) {
+ // The default 'nvm_data' is loaded from test/sim-default-nvm.cc.
+
+ wlan_info_band_t bands[WLAN_INFO_BAND_COUNT] = {
+ WLAN_INFO_BAND_TWO_GHZ,
+ WLAN_INFO_BAND_FIVE_GHZ,
+ };
+ wlan_info_band_info_t band_infos[WLAN_INFO_BAND_COUNT] = {};
+
+ fill_band_infos(iwl_trans_get_mvm(sim_trans_.iwl_trans())->nvm_data, bands, std::size(bands),
+ band_infos);
+ // 2.4Ghz
+ wlan_info_band_info_t* exp_band_info = &band_infos[0];
+ EXPECT_EQ(WLAN_INFO_BAND_TWO_GHZ, exp_band_info->band);
+ EXPECT_EQ(true, exp_band_info->ht_supported);
+ EXPECT_EQ(expected_rate(0), exp_band_info->rates[0]); // 1Mbps
+ EXPECT_EQ(expected_rate(11), exp_band_info->rates[11]); // 54Mbps
+ EXPECT_EQ(2407, exp_band_info->supported_channels.base_freq);
+ EXPECT_EQ(1, exp_band_info->supported_channels.channels[0]);
+ EXPECT_EQ(13, exp_band_info->supported_channels.channels[12]);
+ // 5GHz
+ exp_band_info = &band_infos[1];
+ EXPECT_EQ(WLAN_INFO_BAND_FIVE_GHZ, exp_band_info->band);
+ EXPECT_EQ(true, exp_band_info->ht_supported);
+ EXPECT_EQ(expected_rate(4), exp_band_info->rates[0]); // 6Mbps
+ EXPECT_EQ(expected_rate(11), exp_band_info->rates[7]); // 54Mbps
+ EXPECT_EQ(5000, exp_band_info->supported_channels.base_freq);
+ EXPECT_EQ(36, exp_band_info->supported_channels.channels[0]);
+ EXPECT_EQ(165, exp_band_info->supported_channels.channels[24]);
+}
+
+TEST_F(WlanSoftmacDeviceTest, FillBandInfosOnly5GHz) {
+ // The default 'nvm_data' is loaded from test/sim-default-nvm.cc.
+
+ wlan_info_band_t bands[WLAN_INFO_BAND_COUNT] = {
+ WLAN_INFO_BAND_FIVE_GHZ,
+ 0,
+ };
+ wlan_info_band_info_t band_infos[WLAN_INFO_BAND_COUNT] = {};
+
+ fill_band_infos(iwl_trans_get_mvm(sim_trans_.iwl_trans())->nvm_data, bands, 1, band_infos);
+ // 5GHz
+ wlan_info_band_info_t* exp_band_info = &band_infos[0];
+ EXPECT_EQ(WLAN_INFO_BAND_FIVE_GHZ, exp_band_info->band);
+ EXPECT_EQ(true, exp_band_info->ht_supported);
+ EXPECT_EQ(expected_rate(4), exp_band_info->rates[0]); // 6Mbps
+ EXPECT_EQ(expected_rate(11), exp_band_info->rates[7]); // 54Mbps
+ EXPECT_EQ(5000, exp_band_info->supported_channels.base_freq);
+ EXPECT_EQ(36, exp_band_info->supported_channels.channels[0]);
+ EXPECT_EQ(165, exp_band_info->supported_channels.channels[24]);
+ // index 1 should be empty.
+ exp_band_info = &band_infos[1];
+ EXPECT_EQ(false, exp_band_info->ht_supported);
+ EXPECT_EQ(0x00, exp_band_info->rates[0]);
+ EXPECT_EQ(0x00, exp_band_info->rates[7]);
+ EXPECT_EQ(0, exp_band_info->supported_channels.channels[0]);
+}
+
+TEST_F(WlanSoftmacDeviceTest, Query) {
+ // Test input null pointers
+ uint32_t options = 0;
+ ASSERT_EQ(ZX_ERR_INVALID_ARGS, device_->WlanSoftmacQuery(options, nullptr));
+
+ wlan_softmac_info_t info = {};
+ ASSERT_EQ(ZX_OK, device_->WlanSoftmacQuery(options, &info));
+ EXPECT_EQ(WLAN_MAC_ROLE_CLIENT, info.mac_role);
+
+ //
+ // The below code assumes the test/sim-default-nvm.cc contains 2 bands.
+ //
+ // .bands[0]: WLAN_INFO_BAND_TWO_GHZ
+ // .bands[1]: WLAN_INFO_BAND_FIVE_GHZ
+ //
+ ASSERT_EQ(2, info.bands_count);
+ EXPECT_EQ(expected_rate(0), info.bands[0].rates[0]); // 1 Mbps
+ EXPECT_EQ(expected_rate(7), info.bands[0].rates[7]); // 18 Mbps
+ EXPECT_EQ(expected_rate(11), info.bands[0].rates[11]); // 54 Mbps
+ EXPECT_EQ(expected_rate(4), info.bands[1].rates[0]); // 6 Mbps
+ EXPECT_EQ(165, info.bands[1].supported_channels.channels[24]);
+}
+
+TEST_F(WlanSoftmacDeviceTest, MacStart) {
+ // Test input null pointers
+ wlan_softmac_ifc_protocol_ops_t proto_ops = {
+ .recv = recv_wrapper,
+ };
+ wlan_softmac_ifc_protocol_t ifc = {.ops = &proto_ops};
+ zx::channel mlme_channel;
+ ASSERT_EQ(ZX_ERR_INVALID_ARGS, device_->WlanSoftmacStart(nullptr, &mlme_channel));
+ ASSERT_EQ(ZX_ERR_INVALID_ARGS, device_->WlanSoftmacStart(&ifc, nullptr));
+
+ // Test callback function
+ recv_cb_t mock_recv; // To mock up the wlan_softmac_ifc_t.recv().
+ mlme_channel = zx::channel(static_cast<zx_handle_t>(0xF000));
+ ASSERT_EQ(ZX_OK, device_->WlanSoftmacStart(&ifc, &mlme_channel));
+ // Expect the above line would copy the 'ifc'. Then set expectation below and fire test.
+ mock_recv.ExpectCall(&mock_recv, nullptr);
+ mvmvif_->ifc.ops->recv(&mock_recv, nullptr);
+ mock_recv.VerifyAndClear();
+}
+
+TEST_F(WlanSoftmacDeviceTest, MacStartSmeChannel) {
+ // The normal case. A channel will be transferred to MLME.
+ constexpr zx_handle_t kChannelOne = static_cast<zx_handle_t>(0xF001);
+ constexpr zx_handle_t kChannelTwo = static_cast<zx_handle_t>(0xF002);
+ mvmvif_->mlme_channel = kChannelOne;
+ wlan_softmac_ifc_protocol_ops_t proto_ops = {
+ .recv = recv_wrapper,
+ };
+ wlan_softmac_ifc_protocol_t ifc = {.ops = &proto_ops};
+ zx::channel mlme_channel(kChannelTwo);
+ ASSERT_EQ(ZX_OK, device_->WlanSoftmacStart(&ifc, &mlme_channel));
+ ASSERT_EQ(mlme_channel.get(), kChannelOne); // The channel handle is returned.
+ ASSERT_EQ(mvmvif_->mlme_channel, ZX_HANDLE_INVALID); // Driver no longer holds the ownership.
+
+ // Since the driver no longer owns the handle, the start should fail.
+ ASSERT_EQ(ZX_ERR_ALREADY_BOUND, device_->WlanSoftmacStart(&ifc, &mlme_channel));
+}
+
+TEST_F(WlanSoftmacDeviceTest, Release) {
+ // Create a channel. Let this test case holds one end while driver holds the other end.
+ char dummy[1];
+ zx_handle_t case_end;
+ ASSERT_EQ(zx_channel_create(0 /* option */, &case_end, &mvmvif_->mlme_channel), ZX_OK);
+ ASSERT_EQ(zx_channel_write(case_end, 0 /* option */, dummy, sizeof(dummy), nullptr, 0), ZX_OK);
+
+ // Call release and the sme channel should be closed so that we will get a peer-close error while
+ // trying to write any data to it.
+ mvmvif_.release();
+ device_.release()->DdkRelease();
+ ASSERT_EQ(zx_channel_write(case_end, 0 /* option */, dummy, sizeof(dummy), nullptr, 0),
+ ZX_ERR_PEER_CLOSED);
+}
+
+// The class for WLAN device MAC testing.
+//
+class MacInterfaceTest : public WlanSoftmacDeviceTest, public MockTrans {
+ public:
+ MacInterfaceTest() : ifc_{ .ops = &proto_ops_, } , proto_ops_{ .recv = recv_wrapper, } {
+ zx_handle_t wlanphy_impl_channel = mvmvif_->mlme_channel;
+ zx::channel mlme_channel;
+ ASSERT_EQ(ZX_OK, device_->WlanSoftmacStart(&ifc_, &mlme_channel));
+ ASSERT_EQ(wlanphy_impl_channel, mlme_channel);
+
+ // Add the interface to MVM instance.
+ mvmvif_->mvm->mvmvif[0] = mvmvif_.get();
+ }
+
+ ~MacInterfaceTest() {
+ VerifyExpectation(); // Ensure all expectations had been met.
+
+ // Restore the original callback for other test cases not using the mock.
+ ResetSendCmdFunc();
+
+ // Stop the MAC to free resources we allocated.
+ // This must be called after we verify the expected commands and restore the mock command
+ // callback so that the stop command doesn't mess up the test case expectation.
+ device_->WlanSoftmacStop();
+ VerifyStaHasBeenRemoved();
+ }
+
+ // Used in MockCommand constructor to indicate if the command needs to be either
+ //
+ // - returned immediately (with a status code), or
+ // - passed to the sim_mvm.c.
+ //
+ enum SimMvmBehavior {
+ kSimMvmReturnWithStatus,
+ kSimMvmBypassToSimMvm,
+ };
+
+ // A flexible mock-up of firmware command for testing code. Testing code can decide to either call
+ // the simulated firmware or return the status code immediately.
+ //
+ // cmd_id: the command ID. Sometimes composed with WIDE_ID() macro.
+ // behavior: determine what this mockup command is to do.
+ // status: the status code to return when behavior is 'kSimMvmReturnWithStatus'.
+ //
+ class MockCommand {
+ public:
+ MockCommand(uint32_t cmd_id, SimMvmBehavior behavior, zx_status_t status)
+ : cmd_id_(cmd_id), behavior_(behavior), status_(status) {}
+ MockCommand(uint32_t cmd_id) : MockCommand(cmd_id, kSimMvmBypassToSimMvm, ZX_OK) {}
+
+ ~MockCommand() {}
+
+ uint32_t cmd_id_;
+ SimMvmBehavior behavior_;
+ zx_status_t status_;
+ };
+ typedef std::list<MockCommand> expected_cmd_id_list;
+ typedef zx_status_t (*fp_send_cmd)(struct iwl_trans* trans, struct iwl_host_cmd* cmd);
+
+ // Public for MockSendCmd().
+ expected_cmd_id_list expected_cmd_ids;
+ fp_send_cmd original_send_cmd;
+
+ protected:
+ zx_status_t SetChannel(const wlan_channel_t* channel) {
+ uint32_t option = 0;
+ return device_->WlanSoftmacSetChannel(option, channel);
+ }
+
+ zx_status_t ConfigureBss(const bss_config_t* config) {
+ uint32_t option = 0;
+ return device_->WlanSoftmacConfigureBss(option, config);
+ }
+
+ zx_status_t ConfigureAssoc(const wlan_assoc_ctx_t* config) {
+ uint32_t option = 0;
+ return device_->WlanSoftmacConfigureAssoc(option, config);
+ }
+
+ zx_status_t ClearAssoc() {
+ uint32_t option = 0;
+ uint8_t
+ peer_addr[::fuchsia_wlan_ieee80211::wire::kMacAddrLen]; // Not used since all info were
+ // saved in mvmvif_sta_ already.
+ return device_->WlanSoftmacClearAssoc(option, peer_addr);
+ }
+
+ zx_status_t SetKey(const wlan_key_config_t* key_config) {
+ uint32_t option = 0;
+ IWL_INFO(nullptr, "Calling set_key");
+ return device_->WlanSoftmacSetKey(option, key_config);
+ }
+ // The following functions are for mocking up the firmware commands.
+ //
+ // The mock function will return the special error ZX_ERR_INTERNAL when the expectation
+ // is not expected.
+
+ // Set the expected commands sending to the firmware.
+ //
+ // Args:
+ // cmd_ids: list of expected commands. Will be matched in order.
+ //
+ void ExpectSendCmd(const expected_cmd_id_list& cmd_ids) {
+ expected_cmd_ids = cmd_ids;
+
+ // Re-define the 'dev' field in the 'struct iwl_trans' to a test instance of this class.
+ sim_trans_.iwl_trans()->dev = reinterpret_cast<struct device*>(this);
+
+ // Setup the mock function for send command.
+ original_send_cmd = sim_trans_.iwl_trans()->ops->send_cmd;
+ sim_trans_.iwl_trans()->ops->send_cmd = MockSendCmd;
+ }
+
+ // Reset the send command function to the original one, so that the test case would stop checking
+ // commands one by one.
+ void ResetSendCmdFunc() {
+ if (original_send_cmd) {
+ IWL_INFO(nullptr, "Reseting send_cmd.");
+ sim_trans_.iwl_trans()->ops->send_cmd = original_send_cmd;
+ } else {
+ IWL_WARN(nullptr, "No original send_cmd found.");
+ }
+ }
+
+ static zx_status_t MockSendCmd(struct iwl_trans* trans, struct iwl_host_cmd* cmd) {
+ MacInterfaceTest* this_ = reinterpret_cast<MacInterfaceTest*>(trans->dev);
+
+ // remove the first one and match.
+ expected_cmd_id_list& expected = this_->expected_cmd_ids;
+ ZX_ASSERT_MSG(!expected.empty(),
+ "A command (0x%04x) is going to send, but no command is expected.\n", cmd->id);
+
+ // check the command ID.
+ auto exp = expected.front();
+ ZX_ASSERT_MSG(exp.cmd_id_ == cmd->id,
+ "The command doesn't match! Expect: 0x%04x, actual: 0x%04x.\n", exp.cmd_id_,
+ cmd->id);
+ expected.pop_front();
+
+ if (exp.behavior_ == kSimMvmBypassToSimMvm) {
+ return this_->original_send_cmd(trans, cmd);
+ } else {
+ return exp.status_;
+ }
+ }
+
+ void VerifyExpectation() {
+ for (expected_cmd_id_list::iterator it = expected_cmd_ids.begin(); it != expected_cmd_ids.end();
+ it++) {
+ printf(" ==> 0x%04x\n", it->cmd_id_);
+ }
+ ASSERT_TRUE(expected_cmd_ids.empty(), "The expected command set is not empty.");
+
+ mock_tx_.VerifyAndClear();
+ }
+
+ void VerifyStaHasBeenRemoved() {
+ auto mvm = mvmvif_->mvm;
+
+ for (size_t i = 0; i < std::size(mvm->fw_id_to_mac_id); i++) {
+ struct iwl_mvm_sta* mvm_sta = mvm->fw_id_to_mac_id[i];
+ ASSERT_EQ(nullptr, mvm_sta);
+ }
+ ASSERT_EQ(0, mvm->vif_count);
+ }
+
+ // Mock function for Tx.
+ mock_function::MockFunction<zx_status_t, // return value
+ size_t, // packet size
+ uint16_t, // cmd + group_id
+ int // txq_id
+ >
+ mock_tx_;
+
+ static zx_status_t tx_wrapper(struct iwl_trans* trans, struct ieee80211_mac_packet* pkt,
+ const struct iwl_device_cmd* dev_cmd, int txq_id) {
+ auto test = GET_TEST(MacInterfaceTest, trans);
+ return test->mock_tx_.Call(pkt->header_size + pkt->headroom_used_size + pkt->body_size,
+ WIDE_ID(dev_cmd->hdr.group_id, dev_cmd->hdr.cmd), txq_id);
+ }
+
+ wlan_softmac_ifc_protocol_t ifc_;
+ wlan_softmac_ifc_protocol_ops_t proto_ops_;
+ static constexpr bss_config_t kBssConfig = {
+ .bssid = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
+ .bss_type = BSS_TYPE_INFRASTRUCTURE,
+ .remote = true,
+ };
+ // Assoc context without HT related data.
+ static constexpr wlan_assoc_ctx_t kAssocCtx = {
+ .listen_interval = kListenInterval,
+ };
+
+ // Assoc context with HT related data. (The values below comes from real data in manual test)
+ static constexpr wlan_assoc_ctx_t kHtAssocCtx = {
+ .listen_interval = kListenInterval,
+ .channel =
+ {
+ .primary = 157,
+ .cbw = CHANNEL_BANDWIDTH_CBW80,
+ },
+ .rates_cnt = 8,
+ .rates =
+ {
+ 140,
+ 18,
+ 152,
+ 36,
+ 176,
+ 72,
+ 96,
+ 108,
+ },
+ .has_ht_cap = true,
+ .ht_cap =
+ {
+ .supported_mcs_set =
+ {
+ .bytes =
+ {
+ 255,
+ 255,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ 0,
+ },
+ },
+ },
+ };
+};
+
+// Test the set_channel().
+//
+TEST_F(MacInterfaceTest, TestSetChannel) {
+ ExpectSendCmd(expected_cmd_id_list({
+ MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for add_chanctx
+ MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for change_chanctx
+ MockCommand(WIDE_ID(LONG_GROUP, BINDING_CONTEXT_CMD)),
+ MockCommand(WIDE_ID(LONG_GROUP, MAC_PM_POWER_TABLE)),
+ }));
+
+ mvmvif_->csa_bcn_pending = true; // Expect to be clear because this is client role.
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+ EXPECT_EQ(false, mvmvif_->csa_bcn_pending);
+}
+
+// Test call set_channel() multiple times.
+//
+TEST_F(MacInterfaceTest, TestMultipleSetChannel) {
+ ExpectSendCmd(expected_cmd_id_list({
+ // for the first SetChannel()
+ MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for add_chanctx
+ MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for change_chanctx
+ MockCommand(WIDE_ID(LONG_GROUP, BINDING_CONTEXT_CMD)),
+ MockCommand(WIDE_ID(LONG_GROUP, MAC_PM_POWER_TABLE)),
+
+ // for the second SetChannel()
+ MockCommand(WIDE_ID(LONG_GROUP, BINDING_CONTEXT_CMD)), // for remove_chanctx
+ MockCommand(WIDE_ID(LONG_GROUP, MAC_PM_POWER_TABLE)),
+ MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)),
+ MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for add_chanctx
+ MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for change_chanctx
+ MockCommand(WIDE_ID(LONG_GROUP, BINDING_CONTEXT_CMD)),
+ MockCommand(WIDE_ID(LONG_GROUP, MAC_PM_POWER_TABLE)),
+ }));
+
+ for (size_t i = 0; i < 2; i++) {
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+ }
+}
+
+// Test the unsupported MAC role.
+//
+TEST_F(MacInterfaceTest, TestSetChannelWithUnsupportedRole) {
+ ExpectSendCmd(expected_cmd_id_list({
+ MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for add_chanctx
+ MockCommand(WIDE_ID(LONG_GROUP, PHY_CONTEXT_CMD)), // for change_chanctx
+ }));
+
+ mvmvif_->mac_role = WLAN_MAC_ROLE_AP;
+ ASSERT_EQ(ZX_ERR_NOT_SUPPORTED, SetChannel(&kChannel));
+}
+
+// Tests calling SetChannel()/ConfigureBss() again without ConfigureAssoc()/ClearAssoc()
+TEST_F(MacInterfaceTest, DuplicateSetChannel) {
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+ ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
+ struct iwl_mvm_sta* mvm_sta = mvmvif_->mvm->fw_id_to_mac_id[mvmvif_->ap_sta_id];
+ struct iwl_mvm_phy_ctxt* phy_ctxt = mvmvif_->phy_ctxt;
+ ASSERT_NE(nullptr, phy_ctxt);
+ ASSERT_EQ(IWL_STA_NONE, mvm_sta->sta_state);
+ // Call SetChannel() again. This should return the same phy context but ConfigureBss()
+ // should setup a new STA.
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+ struct iwl_mvm_phy_ctxt* new_phy_ctxt = mvmvif_->phy_ctxt;
+ ASSERT_NE(nullptr, new_phy_ctxt);
+ ASSERT_EQ(phy_ctxt, new_phy_ctxt);
+ ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
+ struct iwl_mvm_sta* new_mvm_sta = mvmvif_->mvm->fw_id_to_mac_id[mvmvif_->ap_sta_id];
+ // Now Associate and disassociate - this should release and reset the phy ctxt.
+ ASSERT_EQ(ZX_OK, ConfigureAssoc(&kAssocCtx));
+ ASSERT_EQ(IWL_STA_AUTHORIZED, new_mvm_sta->sta_state);
+ ASSERT_EQ(true, mvmvif_->bss_conf.assoc);
+ ASSERT_EQ(kListenInterval, mvmvif_->bss_conf.listen_interval);
+
+ ASSERT_EQ(ZX_OK, ClearAssoc());
+ ASSERT_EQ(nullptr, mvmvif_->phy_ctxt);
+ ASSERT_EQ(IWL_MVM_INVALID_STA, mvmvif_->ap_sta_id);
+}
+
+// Test ConfigureBss()
+//
+TEST_F(MacInterfaceTest, TestConfigureBss) {
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+
+ ExpectSendCmd(expected_cmd_id_list({
+ MockCommand(WIDE_ID(LONG_GROUP, MAC_CONTEXT_CMD)),
+ MockCommand(WIDE_ID(LONG_GROUP, TIME_EVENT_CMD)),
+ MockCommand(WIDE_ID(LONG_GROUP, ADD_STA)),
+ MockCommand(WIDE_ID(LONG_GROUP, SCD_QUEUE_CFG)),
+ MockCommand(WIDE_ID(LONG_GROUP, ADD_STA)),
+ }));
+
+ ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
+ // Ensure the BSSID was copied into mvmvif
+ ASSERT_EQ(memcmp(mvmvif_->bss_conf.bssid, kBssConfig.bssid, ETH_ALEN), 0);
+ ASSERT_EQ(memcmp(mvmvif_->bssid, kBssConfig.bssid, ETH_ALEN), 0);
+}
+
+// Test duplicate BSS config.
+//
+TEST_F(MacInterfaceTest, DuplicateConfigureBss) {
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+ ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
+ ASSERT_EQ(ZX_ERR_ALREADY_BOUND, ConfigureBss(&kBssConfig));
+}
+
+// Test unsupported bss_type.
+//
+TEST_F(MacInterfaceTest, UnsupportedBssType) {
+ static constexpr bss_config_t kUnsupportedBssConfig = {
+ .bssid = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
+ .bss_type = BSS_TYPE_INDEPENDENT,
+ .remote = true,
+ };
+ ASSERT_EQ(ZX_ERR_INVALID_ARGS, ConfigureBss(&kUnsupportedBssConfig));
+}
+
+// Test failed ADD_STA command.
+//
+TEST_F(MacInterfaceTest, TestFailedAddSta) {
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+
+ ExpectSendCmd(expected_cmd_id_list({
+ MockCommand(WIDE_ID(LONG_GROUP, MAC_CONTEXT_CMD), kSimMvmReturnWithStatus,
+ ZX_ERR_BUFFER_TOO_SMALL /* an arbitrary error */),
+ }));
+
+ ASSERT_EQ(ZX_ERR_BUFFER_TOO_SMALL, ConfigureBss(&kBssConfig));
+}
+
+// Test exception handling in driver.
+//
+TEST_F(MacInterfaceTest, TestExceptionHandling) {
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+
+ // Test the beacon interval checking.
+ mvmvif_->bss_conf.beacon_int = 0;
+ EXPECT_EQ(ZX_ERR_INVALID_ARGS, ConfigureBss(&kBssConfig));
+ mvmvif_->bss_conf.beacon_int = 16; // which just passes the check.
+
+ // Test the phy_ctxt checking.
+ auto backup_phy_ctxt = mvmvif_->phy_ctxt;
+ mvmvif_->phy_ctxt = nullptr;
+ EXPECT_EQ(ZX_ERR_BAD_STATE, ConfigureBss(&kBssConfig));
+ mvmvif_->phy_ctxt = backup_phy_ctxt;
+
+ // Test the case we run out of slots for STA.
+ std::list<std::unique_ptr<::wlan::iwlwifi::WlanSoftmacDevice>> devices;
+ for (size_t i = 0; i < IWL_MVM_STATION_COUNT; i++) {
+ // Pretend the STA is not assigned so that we can add it again.
+ devices.emplace_back(std::make_unique<::wlan::iwlwifi::WlanSoftmacDevice>(
+ nullptr, sim_trans_.iwl_trans(), 0, mvmvif_.get()));
+ std::swap(device_, devices.back());
+ ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
+ }
+
+ // However, the last one should fail because we run out of all slots in fw_id_to_mac_id[].
+ devices.emplace_back(std::make_unique<::wlan::iwlwifi::WlanSoftmacDevice>(
+ nullptr, sim_trans_.iwl_trans(), 0, mvmvif_.get()));
+ std::swap(device_, devices.back());
+ ASSERT_EQ(ZX_ERR_NO_RESOURCES, ConfigureBss(&kBssConfig));
+}
+
+// The test is used to test the typical procedure to connect to an open network.
+//
+TEST_F(MacInterfaceTest, AssociateToOpenNetwork) {
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+ ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
+ struct iwl_mvm_sta* mvm_sta = mvmvif_->mvm->fw_id_to_mac_id[mvmvif_->ap_sta_id];
+ ASSERT_EQ(IWL_STA_NONE, mvm_sta->sta_state);
+ struct iwl_mvm* mvm = mvmvif_->mvm;
+ ASSERT_GT(list_length(&mvm->time_event_list), 0);
+
+ ASSERT_EQ(ZX_OK, ConfigureAssoc(&kAssocCtx));
+ ASSERT_EQ(IWL_STA_AUTHORIZED, mvm_sta->sta_state);
+ ASSERT_EQ(true, mvmvif_->bss_conf.assoc);
+ ASSERT_EQ(kListenInterval, mvmvif_->bss_conf.listen_interval);
+
+ ASSERT_EQ(ZX_OK, ClearAssoc());
+ ASSERT_EQ(nullptr, mvmvif_->phy_ctxt);
+ ASSERT_EQ(IWL_MVM_INVALID_STA, mvmvif_->ap_sta_id);
+ ASSERT_EQ(list_length(&mvm->time_event_list), 0);
+}
+
+// Back to back calls of ClearAssoc().
+TEST_F(MacInterfaceTest, ClearAssocAfterClearAssoc) {
+ ASSERT_NE(ZX_OK, ClearAssoc());
+ ASSERT_NE(ZX_OK, ClearAssoc());
+}
+
+// ClearAssoc() should cleanup when called without Assoc
+TEST_F(MacInterfaceTest, ClearAssocAfterNoAssoc) {
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+ ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
+ struct iwl_mvm_sta* mvm_sta = mvmvif_->mvm->fw_id_to_mac_id[mvmvif_->ap_sta_id];
+ ASSERT_EQ(IWL_STA_NONE, mvm_sta->sta_state);
+ struct iwl_mvm* mvm = mvmvif_->mvm;
+ ASSERT_GT(list_length(&mvm->time_event_list), 0);
+
+ ASSERT_EQ(ZX_OK, ClearAssoc());
+ ASSERT_EQ(nullptr, mvmvif_->phy_ctxt);
+ ASSERT_EQ(IWL_MVM_INVALID_STA, mvmvif_->ap_sta_id);
+ ASSERT_EQ(list_length(&mvm->time_event_list), 0);
+
+ // Call ClearAssoc() again to check if it is handled correctly.
+ ASSERT_NE(ZX_OK, ClearAssoc());
+}
+
+// ClearAssoc() should cleanup when called after a failed Assoc
+TEST_F(MacInterfaceTest, ClearAssocAfterFailedAssoc) {
+ SetChannel(&kChannel);
+ ConfigureBss(&kBssConfig);
+
+ struct iwl_mvm* mvm = mvmvif_->mvm;
+ ASSERT_GT(list_length(&mvm->time_event_list), 0);
+ // Fail the association by forcing some relevant internal state.
+ auto orig = mvmvif_->uploaded;
+ mvmvif_->uploaded = false;
+ ASSERT_EQ(ZX_ERR_IO, ConfigureAssoc(&kAssocCtx));
+ mvmvif_->uploaded = orig;
+
+ // ClearAssoc will clean up the failed association.
+ ASSERT_EQ(ZX_OK, ClearAssoc());
+ ASSERT_EQ(nullptr, mvmvif_->phy_ctxt);
+ ASSERT_EQ(IWL_MVM_INVALID_STA, mvmvif_->ap_sta_id);
+ ASSERT_EQ(list_length(&mvm->time_event_list), 0);
+
+ // Call ClearAssoc() again to check if it is handled correctly.
+ ASSERT_NE(ZX_OK, ClearAssoc());
+}
+
+// This test case is to verify ConfigureAssoc() with HT wlan_assoc_ctx_t input can successfully
+// trigger LQ_CMD with correct data.
+TEST_F(MacInterfaceTest, AssocWithHtConfig) {
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+ ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
+
+ ExpectSendCmd(expected_cmd_id_list({
+ MockCommand(WIDE_ID(LONG_GROUP, ADD_STA)),
+ MockCommand(WIDE_ID(LONG_GROUP, LQ_CMD)),
+ MockCommand(WIDE_ID(LONG_GROUP, ADD_STA)),
+ MockCommand(WIDE_ID(LONG_GROUP, MAC_CONTEXT_CMD)),
+ MockCommand(WIDE_ID(LONG_GROUP, TIME_EVENT_CMD)),
+ MockCommand(WIDE_ID(LONG_GROUP, MCAST_FILTER_CMD)),
+ }));
+
+ // Extract LQ_CMD data.
+ struct iwl_mvm_sta* mvm_sta = mvmvif_->mvm->fw_id_to_mac_id[mvmvif_->ap_sta_id];
+ struct iwl_lq_cmd* lq_cmd = &mvm_sta->lq_sta.rs_drv.lq;
+
+ ASSERT_EQ(IWL_STA_NONE, mvm_sta->sta_state);
+ struct iwl_mvm* mvm = mvmvif_->mvm;
+ ASSERT_GT(list_length(&mvm->time_event_list), 0);
+
+ ASSERT_EQ(ZX_OK, ConfigureAssoc(&kHtAssocCtx));
+
+ // Verify the values in LQ_CMD API structure.
+ EXPECT_EQ(lq_cmd->sta_id, 0);
+ EXPECT_EQ(lq_cmd->reduced_tpc, 0);
+ EXPECT_EQ(lq_cmd->flags, 0);
+ EXPECT_EQ(lq_cmd->mimo_delim, 0);
+ EXPECT_EQ(lq_cmd->single_stream_ant_msk, 1);
+ EXPECT_EQ(lq_cmd->dual_stream_ant_msk, 3);
+ EXPECT_EQ(lq_cmd->initial_rate_index[0], 0);
+ EXPECT_EQ(lq_cmd->initial_rate_index[1], 0);
+ EXPECT_EQ(lq_cmd->initial_rate_index[2], 0);
+ EXPECT_EQ(lq_cmd->initial_rate_index[3], 0);
+ EXPECT_EQ(lq_cmd->agg_time_limit, 0x0fa0);
+ EXPECT_EQ(lq_cmd->agg_disable_start_th, 3);
+ EXPECT_EQ(lq_cmd->agg_frame_cnt_limit, 1);
+ EXPECT_EQ(lq_cmd->reserved2, 0);
+
+ // Verify rate_n_flags in the table.
+ EXPECT_EQ(lq_cmd->rs_table[0], 0x4103);
+ // The value of RS_MNG_RETRY_TABLE_INITIAL_RATE_NUM is 3.
+ EXPECT_EQ(lq_cmd->rs_table[3], 0x4102);
+
+ EXPECT_EQ(lq_cmd->ss_params, 0);
+
+ // Stop checking following commands one by one.
+ ResetSendCmdFunc();
+
+ // Clean up the association states.
+ ASSERT_EQ(ZX_OK, ClearAssoc());
+}
+
+// Check to ensure keys are set during assoc and deleted after disassoc
+// for now use open network
+TEST_F(MacInterfaceTest, SetKeysTest) {
+ constexpr uint8_t kIeeeOui[] = {0x00, 0x0F, 0xAC};
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+ ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
+ struct iwl_mvm_sta* mvm_sta = mvmvif_->mvm->fw_id_to_mac_id[mvmvif_->ap_sta_id];
+ ASSERT_EQ(IWL_STA_NONE, mvm_sta->sta_state);
+ struct iwl_mvm* mvm = mvmvif_->mvm;
+ ASSERT_GT(list_length(&mvm->time_event_list), 0);
+
+ ASSERT_EQ(ZX_OK, ConfigureAssoc(&kAssocCtx));
+ ASSERT_EQ(IWL_STA_AUTHORIZED, mvm_sta->sta_state);
+ ASSERT_EQ(true, mvmvif_->bss_conf.assoc);
+ ASSERT_EQ(kListenInterval, mvmvif_->bss_conf.listen_interval);
+
+ char keybuf[sizeof(wlan_key_config_t) + 16] = {};
+ wlan_key_config_t* key_config = new (keybuf) wlan_key_config_t();
+
+ // Set an arbitrary pairwise key.
+ key_config->cipher_type = 4;
+ key_config->key_type = 1;
+ key_config->key_idx = 0;
+ key_config->key_len = 16;
+ memcpy(key_config->cipher_oui, kIeeeOui, 3);
+ ASSERT_EQ(ZX_OK, SetKey(key_config));
+ // Expect bit 0 to be set.
+ ASSERT_EQ(*mvm->fw_key_table, 0x1);
+
+ // Set an arbitrary group key.
+ key_config->key_type = 2;
+ key_config->key_idx = 1;
+ ASSERT_EQ(ZX_OK, SetKey(key_config));
+ // Expect bit 1 to be set as well.
+ ASSERT_EQ(*mvm->fw_key_table, 0x3);
+ ASSERT_EQ(ZX_OK, ClearAssoc());
+ ASSERT_EQ(nullptr, mvmvif_->phy_ctxt);
+ ASSERT_EQ(IWL_MVM_INVALID_STA, mvmvif_->ap_sta_id);
+ ASSERT_EQ(list_length(&mvm->time_event_list), 0);
+ // Both the keys should have been deleted.
+ ASSERT_EQ(*mvm->fw_key_table, 0x0);
+}
+
+// Check that we can sucessfully set some key configurations required for supported functionality.
+TEST_F(MacInterfaceTest, SetKeysSupportConfigs) {
+ constexpr uint8_t kIeeeOui[] = {0x00, 0x0F, 0xAC};
+ ASSERT_EQ(ZX_OK, SetChannel(&kChannel));
+ ASSERT_EQ(ZX_OK, ConfigureBss(&kBssConfig));
+ ASSERT_EQ(ZX_OK, ConfigureAssoc(&kAssocCtx));
+ ASSERT_EQ(true, mvmvif_->bss_conf.assoc);
+
+ char keybuf[sizeof(wlan_key_config_t) + 16] = {};
+ wlan_key_config_t* key_config = new (keybuf) wlan_key_config_t();
+ key_config->key_len = 16;
+ memcpy(key_config->cipher_oui, kIeeeOui, 3);
+
+ // Default cipher configuration for WPA2/3 PTK. This is data frame protection, required for
+ // WPA2/3.
+ key_config->cipher_type = fuchsia_wlan_ieee80211_CipherSuiteType_CCMP_128;
+ key_config->key_type = WLAN_KEY_TYPE_PAIRWISE;
+ key_config->key_idx = 0;
+ ASSERT_EQ(ZX_OK, SetKey(key_config));
+
+ // Default cipher configuration for WPA2/3 IGTK. This is management frame protection, optional
+ // for WPA2 and required for WPA3.
+ key_config->cipher_type = fuchsia_wlan_ieee80211_CipherSuiteType_BIP_CMAC_128;
+ key_config->key_type = WLAN_KEY_TYPE_IGTK;
+ key_config->key_idx = 1;
+ ASSERT_EQ(ZX_OK, SetKey(key_config));
+
+ ASSERT_EQ(ZX_OK, ClearAssoc());
+}
+
+TEST_F(MacInterfaceTest, TxPktTooLong) {
+ SetChannel(&kChannel);
+ ConfigureBss(&kBssConfig);
+ BIND_TEST(sim_trans_.iwl_trans());
+
+ bindTx(tx_wrapper);
+ WlanPktBuilder builder;
+ std::shared_ptr<WlanPktBuilder::WlanPkt> wlan_pkt = builder.build();
+ wlan_pkt->wlan_pkt()->mac_frame_size = WLAN_MSDU_MAX_LEN + 1;
+ ASSERT_EQ(ZX_ERR_INVALID_ARGS, device_->WlanSoftmacQueueTx(0, wlan_pkt->wlan_pkt()));
+ unbindTx();
+}
+
+TEST_F(MacInterfaceTest, TxPktNotSupportedRole) {
+ SetChannel(&kChannel);
+ ConfigureBss(&kBssConfig);
+ BIND_TEST(sim_trans_.iwl_trans());
+
+ // Set to an unsupported role.
+ mvmvif_->mac_role = WLAN_MAC_ROLE_AP;
+
+ bindTx(tx_wrapper);
+ WlanPktBuilder builder;
+ std::shared_ptr<WlanPktBuilder::WlanPkt> wlan_pkt = builder.build();
+ ASSERT_EQ(ZX_ERR_INVALID_ARGS, device_->WlanSoftmacQueueTx(0, wlan_pkt->wlan_pkt()));
+ unbindTx();
+}
+
+// To test if a packet can be sent out.
+TEST_F(MacInterfaceTest, TxPkt) {
+ SetChannel(&kChannel);
+ ConfigureBss(&kBssConfig);
+ BIND_TEST(sim_trans_.iwl_trans());
+
+ bindTx(tx_wrapper);
+ WlanPktBuilder builder;
+ std::shared_ptr<WlanPktBuilder::WlanPkt> wlan_pkt = builder.build();
+ mock_tx_.ExpectCall(ZX_OK, wlan_pkt->len(), WIDE_ID(0, TX_CMD), IWL_MVM_DQA_MIN_MGMT_QUEUE);
+ ASSERT_EQ(ZX_OK, device_->WlanSoftmacQueueTx(0, wlan_pkt->wlan_pkt()));
+ unbindTx();
+}
+
+} // namespace
+} // namespace wlan::testing
diff --git a/third_party/iwlwifi/test/wlanphy-impl-device-test.cc b/third_party/iwlwifi/test/wlanphy-impl-device-test.cc
new file mode 100644
index 0000000..2f79271
--- /dev/null
+++ b/third_party/iwlwifi/test/wlanphy-impl-device-test.cc
@@ -0,0 +1,213 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// To test PHY device callback functions.
+
+#include <fuchsia/wlan/common/cpp/banjo.h>
+#include <fuchsia/wlan/internal/cpp/banjo.h>
+#include <zircon/listnode.h>
+#include <zircon/syscalls.h>
+
+#include <iterator>
+
+#include <zxtest/zxtest.h>
+
+extern "C" {
+#include "third_party/iwlwifi/mvm/mvm.h"
+}
+
+#include "third_party/iwlwifi/platform/ieee80211_include.h"
+#include "third_party/iwlwifi/platform/mvm-mlme.h"
+#include "third_party/iwlwifi/platform/wlanphy-impl-device.h"
+#include "third_party/iwlwifi/test/single-ap-test.h"
+
+namespace wlan::testing {
+namespace {
+
+constexpr size_t kListenInterval = 100;
+constexpr zx_handle_t kDummyMlmeChannel = 73939133; // An arbitrary value not ZX_HANDLE_INVALID
+
+class WlanphyImplDeviceTest : public SingleApTest {
+ public:
+ WlanphyImplDeviceTest()
+ : mvmvif_sta_{
+ .mvm = iwl_trans_get_mvm(sim_trans_.iwl_trans()),
+ .mac_role = WLAN_MAC_ROLE_CLIENT,
+ .bss_conf =
+ {
+ .beacon_int = kListenInterval,
+ },
+ } {
+ device_ = sim_trans_.sim_device();
+ }
+ ~WlanphyImplDeviceTest() {}
+
+ protected:
+ struct iwl_mvm_vif mvmvif_sta_; // The mvm_vif settings for station role.
+ wlan::iwlwifi::WlanphyImplDevice* device_;
+};
+
+///////////////////////////////////// PHY //////////////////////////////////////////////
+
+TEST_F(WlanphyImplDeviceTest, PhyGetSupportedMacRolesNullPtr) {
+ // Test input null pointers
+ ASSERT_EQ(ZX_ERR_INVALID_ARGS, device_->WlanphyImplGetSupportedMacRoles(nullptr, 0));
+}
+
+TEST_F(WlanphyImplDeviceTest, PhyGetSupportedMacRoles) {
+ wlan_mac_role_t supported_mac_roles_list[fuchsia_wlan_common_MAX_SUPPORTED_MAC_ROLES] = {};
+ uint8_t supported_mac_roles_count = 0;
+
+ // Normal case
+ ASSERT_EQ(ZX_OK, device_->WlanphyImplGetSupportedMacRoles(supported_mac_roles_list,
+ &supported_mac_roles_count));
+ EXPECT_EQ(supported_mac_roles_count, 1);
+ EXPECT_EQ(supported_mac_roles_list[0], WLAN_MAC_ROLE_CLIENT);
+}
+
+TEST_F(WlanphyImplDeviceTest, PhyPartialCreateCleanup) {
+ wlanphy_impl_create_iface_req_t req = {
+ .role = WLAN_MAC_ROLE_CLIENT,
+ .mlme_channel = kDummyMlmeChannel,
+ };
+ uint16_t iface_id;
+ struct iwl_trans* iwl_trans = sim_trans_.iwl_trans();
+
+ // Test input null pointers
+ ASSERT_OK(phy_create_iface(iwl_trans, &req, &iface_id));
+
+ // Ensure mvmvif got created and indexed.
+ struct iwl_mvm* mvm = iwl_trans_get_mvm(iwl_trans);
+ ASSERT_NOT_NULL(mvm->mvmvif[iface_id]);
+
+ // Ensure partial create failure removes it from the index.
+ phy_create_iface_undo(iwl_trans, iface_id);
+ ASSERT_NULL(mvm->mvmvif[iface_id]);
+}
+
+TEST_F(WlanphyImplDeviceTest, PhyCreateDestroySingleInterface) {
+ wlanphy_impl_create_iface_req_t req = {
+ .role = WLAN_MAC_ROLE_CLIENT,
+ .mlme_channel = kDummyMlmeChannel,
+ };
+ uint16_t iface_id;
+
+ // Test input null pointers
+ ASSERT_EQ(device_->WlanphyImplCreateIface(nullptr, &iface_id), ZX_ERR_INVALID_ARGS);
+ ASSERT_EQ(device_->WlanphyImplCreateIface(&req, nullptr), ZX_ERR_INVALID_ARGS);
+ ASSERT_EQ(device_->WlanphyImplCreateIface(nullptr, nullptr), ZX_ERR_INVALID_ARGS);
+
+ // Test invalid inputs
+ ASSERT_EQ(device_->WlanphyImplDestroyIface(MAX_NUM_MVMVIF), ZX_ERR_INVALID_ARGS);
+ ASSERT_EQ(device_->WlanphyImplDestroyIface(0), ZX_ERR_NOT_FOUND); // hasn't been added yet.
+
+ // To verify the internal state of MVM driver.
+ struct iwl_mvm* mvm = iwl_trans_get_mvm(sim_trans_.iwl_trans());
+
+ // Add interface
+ ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
+ ASSERT_EQ(iface_id, 0); // the first interface should have id 0.
+ struct iwl_mvm_vif* mvmvif = mvm->mvmvif[iface_id];
+ ASSERT_NE(mvmvif, nullptr);
+ ASSERT_EQ(mvmvif->mac_role, WLAN_MAC_ROLE_CLIENT);
+ // Count includes phy device in addition to the newly created mac device.
+ ASSERT_EQ(fake_parent_->descendant_count(), 2);
+ device_->parent()->GetLatestChild()->InitOp();
+
+ // Remove interface
+ ASSERT_EQ(device_->WlanphyImplDestroyIface(0), ZX_OK);
+ mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
+ ASSERT_EQ(mvm->mvmvif[iface_id], nullptr);
+ ASSERT_EQ(fake_parent_->descendant_count(), 1);
+}
+
+TEST_F(WlanphyImplDeviceTest, PhyCreateDestroyMultipleInterfaces) {
+ wlanphy_impl_create_iface_req_t req = {
+ .role = WLAN_MAC_ROLE_CLIENT,
+ .mlme_channel = kDummyMlmeChannel,
+ };
+ uint16_t iface_id;
+ struct iwl_trans* iwl_trans = sim_trans_.iwl_trans();
+ struct iwl_mvm* mvm = iwl_trans_get_mvm(iwl_trans); // To verify the internal state of MVM driver
+
+ // Add 1st interface
+ ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
+ ASSERT_EQ(iface_id, 0);
+ ASSERT_EQ(mvm->mvmvif[iface_id]->mac_role, WLAN_MAC_ROLE_CLIENT);
+ ASSERT_EQ(fake_parent_->descendant_count(), 2);
+ device_->parent()->GetLatestChild()->InitOp();
+
+ // Add 2nd interface
+ ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
+ ASSERT_EQ(iface_id, 1);
+ ASSERT_NE(mvm->mvmvif[iface_id], nullptr);
+ ASSERT_EQ(mvm->mvmvif[iface_id]->mac_role, WLAN_MAC_ROLE_CLIENT);
+ ASSERT_EQ(fake_parent_->descendant_count(), 3);
+ device_->parent()->GetLatestChild()->InitOp();
+
+ // Add 3rd interface
+ ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
+ ASSERT_EQ(iface_id, 2);
+ ASSERT_NE(mvm->mvmvif[iface_id], nullptr);
+ ASSERT_EQ(mvm->mvmvif[iface_id]->mac_role, WLAN_MAC_ROLE_CLIENT);
+ ASSERT_EQ(fake_parent_->descendant_count(), 4);
+ device_->parent()->GetLatestChild()->InitOp();
+
+ // Remove the 2nd interface
+ ASSERT_EQ(device_->WlanphyImplDestroyIface(1), ZX_OK);
+ mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
+ ASSERT_EQ(mvm->mvmvif[1], nullptr);
+ ASSERT_EQ(fake_parent_->descendant_count(), 3);
+
+ // Add a new interface and it should be the 2nd one.
+ ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
+ ASSERT_EQ(iface_id, 1);
+ ASSERT_NE(mvm->mvmvif[iface_id], nullptr);
+ ASSERT_EQ(mvm->mvmvif[iface_id]->mac_role, WLAN_MAC_ROLE_CLIENT);
+ ASSERT_EQ(fake_parent_->descendant_count(), 4);
+ device_->parent()->GetLatestChild()->InitOp();
+
+ // Add 4th interface
+ ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_OK);
+ ASSERT_EQ(iface_id, 3);
+ ASSERT_NE(mvm->mvmvif[iface_id], nullptr);
+ ASSERT_EQ(mvm->mvmvif[iface_id]->mac_role, WLAN_MAC_ROLE_CLIENT);
+ ASSERT_EQ(fake_parent_->descendant_count(), 5);
+ device_->parent()->GetLatestChild()->InitOp();
+
+ // Add 5th interface and it should fail
+ ASSERT_EQ(device_->WlanphyImplCreateIface(&req, &iface_id), ZX_ERR_NO_RESOURCES);
+ ASSERT_EQ(fake_parent_->descendant_count(), 5);
+
+ // Remove the 2nd interface
+ ASSERT_EQ(device_->WlanphyImplDestroyIface(1), ZX_OK);
+ mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
+ ASSERT_EQ(mvm->mvmvif[1], nullptr);
+ ASSERT_EQ(fake_parent_->descendant_count(), 4);
+
+ // Remove the 3rd interface
+ ASSERT_EQ(device_->WlanphyImplDestroyIface(2), ZX_OK);
+ mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
+ ASSERT_EQ(mvm->mvmvif[2], nullptr);
+ ASSERT_EQ(fake_parent_->descendant_count(), 3);
+
+ // Remove the 4th interface
+ ASSERT_EQ(device_->WlanphyImplDestroyIface(3), ZX_OK);
+ mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
+ ASSERT_EQ(mvm->mvmvif[3], nullptr);
+ ASSERT_EQ(fake_parent_->descendant_count(), 2);
+
+ // Remove the 1st interface
+ ASSERT_EQ(device_->WlanphyImplDestroyIface(0), ZX_OK);
+ mock_ddk::ReleaseFlaggedDevices(fake_parent_.get());
+ ASSERT_EQ(mvm->mvmvif[0], nullptr);
+ ASSERT_EQ(fake_parent_->descendant_count(), 1);
+
+ // Remove the 1st interface again and it should fail.
+ ASSERT_EQ(device_->WlanphyImplDestroyIface(0), ZX_ERR_NOT_FOUND);
+ ASSERT_EQ(fake_parent_->descendant_count(), 1);
+}
+
+} // namespace
+} // namespace wlan::testing