summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig1
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/lib.c4
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-8000.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-config.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex.c13
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex_legacy.c14
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/constants.h5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c318
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c201
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c5
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c120
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h18
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c15
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c80
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c35
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tt.c4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c6
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c37
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c45
25 files changed, 587 insertions, 360 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 267e48a..139de90 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -59,6 +59,7 @@ config IWLDVM
config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
+ select BACKPORT_WANT_DEV_COREDUMP
help
This is the driver that supports the MVM firmware which is
currently only available for 7260 and 3160 devices.
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index 2191621..02e4ede 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -418,8 +418,8 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena)
static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg)
{
- return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >>
- BT_UART_MSG_FRAME3SCOESCO_POS;
+ return (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
+ BT_UART_MSG_FRAME3SCOESCO_POS;
}
static void iwlagn_bt_traffic_change_work(struct work_struct *work)
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index cae692f..47e64e8 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -941,6 +941,7 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
}
static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
struct ieee80211_channel_switch *ch_switch)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c
index d2b7234..896ea90 100644
--- a/drivers/net/wireless/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-8000.c
@@ -104,6 +104,7 @@ static const struct iwl_base_params iwl8000_base_params = {
};
static const struct iwl_ht_params iwl8000_ht_params = {
+ .stbc = true,
.ldpc = true,
.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 2ef83a3..f8aa9cf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -87,6 +87,16 @@ enum iwl_device_family {
IWL_DEVICE_FAMILY_8000,
};
+static inline bool iwl_has_secure_boot(u32 hw_rev,
+ enum iwl_device_family family)
+{
+ /* return 1 only for family 8000 B0 */
+ if ((family == IWL_DEVICE_FAMILY_8000) && (hw_rev & 0xC))
+ return 1;
+
+ return 0;
+}
+
/*
* LED mode
* IWL_LED_DEFAULT: use device default
@@ -246,6 +256,7 @@ struct iwl_pwr_tx_backoff {
* @nvm_hw_section_num: the ID of the HW NVM section
* @pwr_tx_backoffs: translation table between power limits and backoffs
* @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
+ * @max_tx_agg_size: max TX aggregation size of the ADDBA request/response
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
@@ -285,6 +296,7 @@ struct iwl_cfg {
const char *default_nvm_file;
unsigned int max_rx_agg_size;
bool disable_dummy_notification;
+ unsigned int max_tx_agg_size;
};
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 0f1084f..d9fa8e0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -807,19 +807,16 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
tlv_len);
drv->fw.mvm_fw = true;
- drv->fw.img[IWL_UCODE_REGULAR].is_secure = true;
break;
case IWL_UCODE_TLV_SECURE_SEC_INIT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT,
tlv_len);
drv->fw.mvm_fw = true;
- drv->fw.img[IWL_UCODE_INIT].is_secure = true;
break;
case IWL_UCODE_TLV_SECURE_SEC_WOWLAN:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN,
tlv_len);
drv->fw.mvm_fw = true;
- drv->fw.img[IWL_UCODE_WOWLAN].is_secure = true;
break;
case IWL_UCODE_TLV_NUM_OF_CPU:
if (tlv_len != sizeof(u32))
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index b894a84..649fdae 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -229,7 +229,6 @@ struct fw_desc {
struct fw_img {
struct fw_desc sec[IWL_UCODE_SECTION_MAX];
- bool is_secure;
bool is_dual_cpus;
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index d8fc548..0768f83e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -535,9 +535,7 @@ struct iwl_trans_ops {
void (*ref)(struct iwl_trans *trans);
void (*unref)(struct iwl_trans *trans);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans);
-#endif
};
/**
@@ -704,7 +702,6 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
trans->ops->unref(trans);
}
-#ifdef CONFIG_IWLWIFI_DEBUGFS
static inline struct iwl_trans_dump_data *
iwl_trans_dump_data(struct iwl_trans *trans)
{
@@ -712,7 +709,6 @@ iwl_trans_dump_data(struct iwl_trans *trans)
return NULL;
return trans->ops->dump_data(trans);
}
-#endif
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c
index da2ffb7..508c813 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex.c
@@ -72,8 +72,6 @@
#include "mvm.h"
#include "iwl-debug.h"
-#define BT_ANTENNA_COUPLING_THRESHOLD (30)
-
const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = {
[BT_KILL_MSK_DEFAULT] = 0xfffffc00,
[BT_KILL_MSK_NEVER] = 0xffffffff,
@@ -302,11 +300,6 @@ static const __le64 iwl_ci_mask[][3] = {
},
};
-static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
- cpu_to_le32(0x2e402280),
- cpu_to_le32(0x7711a751),
-};
-
struct corunning_block_luts {
u8 range;
__le32 lut20[BT_COEX_CORUN_LUT_SIZE];
@@ -605,7 +598,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
bt_cmd->max_kill = cpu_to_le32(5);
bt_cmd->bt4_antenna_isolation_thr =
- cpu_to_le32(BT_ANTENNA_COUPLING_THRESHOLD);
+ cpu_to_le32(IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS);
bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15);
bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15);
bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT);
@@ -638,8 +631,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost,
sizeof(iwl_bt_prio_boost));
- memcpy(&bt_cmd->multiprio_lut, iwl_bt_mprio_lut,
- sizeof(iwl_bt_mprio_lut));
+ bt_cmd->multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0);
+ bt_cmd->multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1);
send_cmd:
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
index 8a1d2f3..b571e1b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
@@ -102,8 +102,6 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
#undef EVENT_PRIO_ANT
-#define BT_ANTENNA_COUPLING_THRESHOLD (30)
-
static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
{
if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
@@ -290,11 +288,6 @@ static const __le64 iwl_ci_mask[][3] = {
},
};
-static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
- cpu_to_le32(0x2e402280),
- cpu_to_le32(0x7711a751),
-};
-
struct corunning_block_luts {
u8 range;
__le32 lut20[BT_COEX_CORUN_LUT_SIZE];
@@ -593,7 +586,8 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
}
bt_cmd->max_kill = 5;
- bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD;
+ bt_cmd->bt4_antenna_isolation_thr =
+ IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS;
bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
bt_cmd->bt4_tx_rx_max_freq0 = 15;
@@ -649,8 +643,8 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,
sizeof(iwl_bt_prio_boost));
- memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
- sizeof(iwl_bt_mprio_lut));
+ bt_cmd->bt4_multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0);
+ bt_cmd->bt4_multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1);
send_cmd:
memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h
index d4dfbe4..5c1ea80 100644
--- a/drivers/net/wireless/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/iwlwifi/mvm/constants.h
@@ -92,8 +92,13 @@
#define IWL_MVM_BT_COEX_SYNC2SCO 1
#define IWL_MVM_BT_COEX_CORUNNING 0
#define IWL_MVM_BT_COEX_MPLUT 1
+#define IWL_MVM_BT_COEX_MPLUT_REG0 0x2e402280
+#define IWL_MVM_BT_COEX_MPLUT_REG1 0x7711a751
+#define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30
#define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0
+#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0
#define IWL_MVM_QUOTA_THRESHOLD 8
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
+#define IWL_MVM_RS_DISABLE_MIMO 0
#endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index c17be0f..3bbb511 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -601,33 +601,6 @@ static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm,
return ret;
}
-struct iwl_d3_iter_data {
- struct iwl_mvm *mvm;
- struct ieee80211_vif *vif;
- bool error;
-};
-
-static void iwl_mvm_d3_iface_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_d3_iter_data *data = _data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
- return;
-
- if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
- return;
-
- if (data->vif) {
- IWL_ERR(data->mvm, "More than one managed interface active!\n");
- data->error = true;
- return;
- }
-
- data->vif = vif;
-}
-
static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *ap_sta)
{
@@ -783,6 +756,35 @@ void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
IWL_ERR(mvm, "failed to set non-QoS seqno\n");
}
+static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)
+{
+ iwl_mvm_cancel_scan(mvm);
+
+ iwl_trans_stop_device(mvm->trans);
+
+ /*
+ * Set the HW restart bit -- this is mostly true as we're
+ * going to load new firmware and reprogram that, though
+ * the reprogramming is going to be manual to avoid adding
+ * all the MACs that aren't support.
+ * We don't have to clear up everything though because the
+ * reprogramming is manual. When we resume, we'll actually
+ * go through a proper restart sequence again to switch
+ * back to the runtime firmware image.
+ */
+ set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
+
+ /* We reprogram keys and shouldn't allocate new key indices */
+ memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
+
+ mvm->ptk_ivlen = 0;
+ mvm->ptk_icvlen = 0;
+ mvm->ptk_ivlen = 0;
+ mvm->ptk_icvlen = 0;
+
+ return iwl_mvm_load_d3_fw(mvm);
+}
+
static int
iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm,
const struct iwl_wowlan_config_cmd_v3 *cmd)
@@ -797,116 +799,52 @@ iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm,
cmd_len, cmd);
}
-static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
- struct cfg80211_wowlan *wowlan,
- bool test)
+static int
+iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
+ struct cfg80211_wowlan *wowlan,
+ struct iwl_wowlan_config_cmd_v3 *wowlan_config_cmd,
+ struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
+ struct ieee80211_sta *ap_sta)
{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_d3_iter_data suspend_iter_data = {
- .mvm = mvm,
- };
- struct ieee80211_vif *vif;
- struct iwl_mvm_vif *mvmvif;
- struct ieee80211_sta *ap_sta;
- struct iwl_mvm_sta *mvm_ap_sta;
- struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {};
- struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
- struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
- struct iwl_d3_manager_config d3_cfg_cmd_data = {
- /*
- * Program the minimum sleep time to 10 seconds, as many
- * platforms have issues processing a wakeup signal while
- * still being in the process of suspending.
- */
- .min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
- };
- struct iwl_host_cmd d3_cfg_cmd = {
- .id = D3_CONFIG_CMD,
- .flags = CMD_WANT_SKB,
- .data[0] = &d3_cfg_cmd_data,
- .len[0] = sizeof(d3_cfg_cmd_data),
- };
- struct wowlan_key_data key_data = {
- .use_rsc_tsc = false,
- .tkip = &tkip_cmd,
- .use_tkip = false,
- };
int ret;
- int len __maybe_unused;
-
- if (!wowlan) {
- /*
- * mac80211 shouldn't get here, but for D3 test
- * it doesn't warrant a warning
- */
- WARN_ON(!test);
- return -EINVAL;
- }
-
- key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
- if (!key_data.rsc_tsc)
- return -ENOMEM;
-
- mutex_lock(&mvm->mutex);
-
- /* see if there's only a single BSS vif and it's associated */
- ieee80211_iterate_active_interfaces_atomic(
- mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_d3_iface_iterator, &suspend_iter_data);
-
- if (suspend_iter_data.error || !suspend_iter_data.vif) {
- ret = 1;
- goto out_noreset;
- }
-
- vif = suspend_iter_data.vif;
- mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- ap_sta = rcu_dereference_protected(
- mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
- lockdep_is_held(&mvm->mutex));
- if (IS_ERR_OR_NULL(ap_sta)) {
- ret = -EINVAL;
- goto out_noreset;
- }
-
- mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv;
+ struct iwl_mvm_sta *mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv;
- /* TODO: wowlan_config_cmd.common.wowlan_ba_teardown_tids */
+ /* TODO: wowlan_config_cmd->common.wowlan_ba_teardown_tids */
- wowlan_config_cmd.common.is_11n_connection =
+ wowlan_config_cmd->common.is_11n_connection =
ap_sta->ht_cap.ht_supported;
/* Query the last used seqno and set it */
ret = iwl_mvm_get_last_nonqos_seq(mvm, vif);
if (ret < 0)
- goto out_noreset;
- wowlan_config_cmd.common.non_qos_seq = cpu_to_le16(ret);
+ return ret;
- iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &wowlan_config_cmd.common);
+ wowlan_config_cmd->common.non_qos_seq = cpu_to_le16(ret);
+
+ iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &wowlan_config_cmd->common);
if (wowlan->disconnect)
- wowlan_config_cmd.common.wakeup_filter |=
+ wowlan_config_cmd->common.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |
IWL_WOWLAN_WAKEUP_LINK_CHANGE);
if (wowlan->magic_pkt)
- wowlan_config_cmd.common.wakeup_filter |=
+ wowlan_config_cmd->common.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET);
if (wowlan->gtk_rekey_failure)
- wowlan_config_cmd.common.wakeup_filter |=
+ wowlan_config_cmd->common.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
if (wowlan->eap_identity_req)
- wowlan_config_cmd.common.wakeup_filter |=
+ wowlan_config_cmd->common.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ);
if (wowlan->four_way_handshake)
- wowlan_config_cmd.common.wakeup_filter |=
+ wowlan_config_cmd->common.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
if (wowlan->n_patterns)
- wowlan_config_cmd.common.wakeup_filter |=
+ wowlan_config_cmd->common.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
if (wowlan->rfkill_release)
- wowlan_config_cmd.common.wakeup_filter |=
+ wowlan_config_cmd->common.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
if (wowlan->tcp) {
@@ -914,44 +852,39 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
* Set the "link change" (really "link lost") flag as well
* since that implies losing the TCP connection.
*/
- wowlan_config_cmd.common.wakeup_filter |=
+ wowlan_config_cmd->common.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE |
IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET |
IWL_WOWLAN_WAKEUP_LINK_CHANGE);
}
- iwl_mvm_cancel_scan(mvm);
-
- iwl_trans_stop_device(mvm->trans);
-
- /*
- * Set the HW restart bit -- this is mostly true as we're
- * going to load new firmware and reprogram that, though
- * the reprogramming is going to be manual to avoid adding
- * all the MACs that aren't support.
- * We don't have to clear up everything though because the
- * reprogramming is manual. When we resume, we'll actually
- * go through a proper restart sequence again to switch
- * back to the runtime firmware image.
- */
- set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
-
- /* We reprogram keys and shouldn't allocate new key indices */
- memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
-
- mvm->ptk_ivlen = 0;
- mvm->ptk_icvlen = 0;
- mvm->ptk_ivlen = 0;
- mvm->ptk_icvlen = 0;
+ return 0;
+}
- ret = iwl_mvm_load_d3_fw(mvm);
- if (ret)
- goto out;
+static int
+iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
+ struct cfg80211_wowlan *wowlan,
+ struct iwl_wowlan_config_cmd_v3 *wowlan_config_cmd,
+ struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
+ struct ieee80211_sta *ap_sta)
+{
+ struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
+ struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
+ struct wowlan_key_data key_data = {
+ .use_rsc_tsc = false,
+ .tkip = &tkip_cmd,
+ .use_tkip = false,
+ };
+ int ret;
ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta);
if (ret)
- goto out;
+ return ret;
+
+ key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
+ if (!key_data.rsc_tsc)
+ return -ENOMEM;
if (!iwlwifi_mod_params.sw_crypto) {
/*
@@ -1010,7 +943,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
}
}
- ret = iwl_mvm_send_wowlan_config_cmd(mvm, &wowlan_config_cmd);
+ ret = iwl_mvm_send_wowlan_config_cmd(mvm, wowlan_config_cmd);
if (ret)
goto out;
@@ -1023,8 +956,93 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
goto out;
ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp);
- if (ret)
- goto out;
+
+out:
+ kfree(key_data.rsc_tsc);
+ return ret;
+}
+
+static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
+ struct cfg80211_wowlan *wowlan,
+ bool test)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct ieee80211_vif *vif = NULL;
+ struct iwl_mvm_vif *mvmvif = NULL;
+ struct ieee80211_sta *ap_sta = NULL;
+ struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {};
+ struct iwl_d3_manager_config d3_cfg_cmd_data = {
+ /*
+ * Program the minimum sleep time to 10 seconds, as many
+ * platforms have issues processing a wakeup signal while
+ * still being in the process of suspending.
+ */
+ .min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
+ };
+ struct iwl_host_cmd d3_cfg_cmd = {
+ .id = D3_CONFIG_CMD,
+ .flags = CMD_WANT_SKB,
+ .data[0] = &d3_cfg_cmd_data,
+ .len[0] = sizeof(d3_cfg_cmd_data),
+ };
+ int ret;
+ int len __maybe_unused;
+
+ if (!wowlan) {
+ /*
+ * mac80211 shouldn't get here, but for D3 test
+ * it doesn't warrant a warning
+ */
+ WARN_ON(!test);
+ return -EINVAL;
+ }
+
+ mutex_lock(&mvm->mutex);
+
+ vif = iwl_mvm_get_bss_vif(mvm);
+ if (IS_ERR_OR_NULL(vif)) {
+ ret = 1;
+ goto out_noreset;
+ }
+
+ mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ /* if we're associated, this is wowlan */
+ if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
+ ap_sta = rcu_dereference_protected(
+ mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
+ lockdep_is_held(&mvm->mutex));
+ if (IS_ERR_OR_NULL(ap_sta)) {
+ ret = -EINVAL;
+ goto out_noreset;
+ }
+
+ ret = iwl_mvm_get_wowlan_config(mvm, wowlan, &wowlan_config_cmd,
+ vif, mvmvif, ap_sta);
+ if (ret)
+ goto out_noreset;
+
+ ret = iwl_mvm_switch_to_d3(mvm);
+ if (ret)
+ goto out;
+
+ ret = iwl_mvm_wowlan_config(mvm, wowlan, &wowlan_config_cmd,
+ vif, mvmvif, ap_sta);
+ if (ret)
+ goto out;
+ } else if (mvm->nd_config) {
+ ret = iwl_mvm_switch_to_d3(mvm);
+ if (ret)
+ goto out;
+
+ ret = iwl_mvm_scan_offload_start(mvm, vif, mvm->nd_config,
+ mvm->nd_ies);
+ if (ret)
+ goto out;
+ } else {
+ ret = 1;
+ goto out_noreset;
+ }
ret = iwl_mvm_power_update_device(mvm);
if (ret)
@@ -1060,8 +1078,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
if (ret < 0)
ieee80211_restart_hw(mvm->hw);
out_noreset:
- kfree(key_data.rsc_tsc);
-
mutex_unlock(&mvm->mutex);
return ret;
@@ -1592,9 +1608,6 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
{
- struct iwl_d3_iter_data resume_iter_data = {
- .mvm = mvm,
- };
struct ieee80211_vif *vif = NULL;
int ret;
enum iwl_d3_status d3_status;
@@ -1603,15 +1616,10 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
mutex_lock(&mvm->mutex);
/* get the BSS vif pointer again */
- ieee80211_iterate_active_interfaces_atomic(
- mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_d3_iface_iterator, &resume_iter_data);
-
- if (WARN_ON(resume_iter_data.error || !resume_iter_data.vif))
+ vif = iwl_mvm_get_bss_vif(mvm);
+ if (IS_ERR_OR_NULL(vif))
goto out_unlock;
- vif = resume_iter_data.vif;
-
ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test);
if (ret)
goto out_unlock;
@@ -1741,7 +1749,9 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
int remaining_time = 10;
mvm->d3_test_active = false;
+ rtnl_lock();
__iwl_mvm_resume(mvm, true);
+ rtnl_unlock();
iwl_abort_notification_waits(&mvm->notif_wait);
ieee80211_restart_hw(mvm->hw);
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 50527a9..51b7116 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -121,78 +121,6 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
return ret;
}
-static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file)
-{
- struct iwl_mvm *mvm = inode->i_private;
- int ret;
-
- if (!mvm)
- return -EINVAL;
-
- mutex_lock(&mvm->mutex);
- if (!mvm->fw_error_dump) {
- ret = -ENODATA;
- goto out;
- }
-
- file->private_data = mvm->fw_error_dump;
- mvm->fw_error_dump = NULL;
- ret = 0;
-
-out:
- mutex_unlock(&mvm->mutex);
- return ret;
-}
-
-static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
- ssize_t bytes_read = 0;
- ssize_t bytes_read_trans = 0;
-
- if (*ppos < dump_ptrs->op_mode_len)
- bytes_read +=
- simple_read_from_buffer(user_buf, count, ppos,
- dump_ptrs->op_mode_ptr,
- dump_ptrs->op_mode_len);
-
- if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len)
- return bytes_read;
-
- if (dump_ptrs->trans_ptr) {
- *ppos -= dump_ptrs->op_mode_len;
- bytes_read_trans =
- simple_read_from_buffer(user_buf + bytes_read,
- count - bytes_read, ppos,
- dump_ptrs->trans_ptr->data,
- dump_ptrs->trans_ptr->len);
- *ppos += dump_ptrs->op_mode_len;
-
- if (bytes_read_trans >= 0)
- bytes_read += bytes_read_trans;
- else if (!bytes_read)
- /* propagate the failure */
- return bytes_read_trans;
- }
-
- return bytes_read;
-
-}
-
-static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
- struct file *file)
-{
- struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
-
- vfree(dump_ptrs->op_mode_ptr);
- vfree(dump_ptrs->trans_ptr);
- kfree(dump_ptrs);
-
- return 0;
-}
-
static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1250,6 +1178,126 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
return ret;
}
+
+#define MAX_NUM_ND_MATCHSETS 10
+
+static ssize_t iwl_dbgfs_netdetect_write(struct iwl_mvm *mvm, char *buf,
+ size_t count, loff_t *ppos)
+{
+ const char *seps = ",\n";
+ char *buf_ptr = buf;
+ char *value_str = NULL;
+ int ret, i;
+
+ /* TODO: don't free if write is being called several times in one go */
+ if (mvm->nd_config) {
+ kfree(mvm->nd_config->match_sets);
+ kfree(mvm->nd_config);
+ mvm->nd_config = NULL;
+ kfree(mvm->nd_ies);
+ mvm->nd_ies = NULL;
+ }
+
+ mvm->nd_ies = kzalloc(sizeof(*mvm->nd_ies), GFP_KERNEL);
+ if (!mvm->nd_ies)
+ return -ENOMEM;
+
+ mvm->nd_config = kzalloc(sizeof(*mvm->nd_config) +
+ (11 * sizeof(struct ieee80211_channel *)),
+ GFP_KERNEL);
+ if (!mvm->nd_config) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+
+ mvm->nd_config->n_channels = 11;
+ mvm->nd_config->scan_width = NL80211_BSS_CHAN_WIDTH_20;
+ mvm->nd_config->interval = 5;
+ mvm->nd_config->min_rssi_thold = -80;
+ for (i = 0; i < mvm->nd_config->n_channels; i++)
+ mvm->nd_config->channels[i] = &mvm->nvm_data->channels[i];
+
+ mvm->nd_config->match_sets =
+ kcalloc(MAX_NUM_ND_MATCHSETS,
+ sizeof(*mvm->nd_config->match_sets),
+ GFP_KERNEL);
+ if (!mvm->nd_config->match_sets) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+
+ while ((value_str = strsep(&buf_ptr, seps)) &&
+ strlen(value_str)) {
+ struct cfg80211_match_set *set;
+
+ if (mvm->nd_config->n_match_sets >= MAX_NUM_ND_MATCHSETS) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+
+ set = &mvm->nd_config->match_sets[mvm->nd_config->n_match_sets];
+ set->ssid.ssid_len = strlen(value_str);
+
+ if (set->ssid.ssid_len > IEEE80211_MAX_SSID_LEN) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+
+ memcpy(set->ssid.ssid, value_str, set->ssid.ssid_len);
+
+ mvm->nd_config->n_match_sets++;
+ }
+
+ ret = count;
+
+ if (mvm->nd_config->n_match_sets)
+ goto out;
+
+out_free:
+ if (mvm->nd_config)
+ kfree(mvm->nd_config->match_sets);
+ kfree(mvm->nd_config);
+ mvm->nd_config = NULL;
+ kfree(mvm->nd_ies);
+ mvm->nd_ies = NULL;
+out:
+ return ret;
+}
+
+static ssize_t
+iwl_dbgfs_netdetect_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_mvm *mvm = file->private_data;
+ size_t bufsz, ret;
+ char *buf;
+ int i, n_match_sets, pos = 0;
+
+ n_match_sets = mvm->nd_config ? mvm->nd_config->n_match_sets : 0;
+
+ bufsz = n_match_sets * (IEEE80211_MAX_SSID_LEN + 1) + 1;
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ for (i = 0; i < n_match_sets; i++) {
+ if (pos +
+ mvm->nd_config->match_sets[i].ssid.ssid_len + 2 > bufsz) {
+ ret = -EIO;
+ goto out;
+ }
+
+ memcpy(buf + pos, mvm->nd_config->match_sets[i].ssid.ssid,
+ mvm->nd_config->match_sets[i].ssid.ssid_len);
+ pos += mvm->nd_config->match_sets[i].ssid.ssid_len;
+ buf[pos++] = '\n';
+ }
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+out:
+ kfree(buf);
+ return ret;
+}
#endif
#define PRINT_MVM_REF(ref) do { \
@@ -1415,12 +1463,6 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
-static const struct file_operations iwl_dbgfs_fw_error_dump_ops = {
- .open = iwl_dbgfs_fw_error_dump_open,
- .read = iwl_dbgfs_fw_error_dump_read,
- .release = iwl_dbgfs_fw_error_dump_release,
-};
-
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
@@ -1428,6 +1470,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
#ifdef CONFIG_PM_SLEEP
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
+MVM_DEBUGFS_READ_WRITE_FILE_OPS(netdetect, 384);
#endif
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
@@ -1446,7 +1489,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
S_IWUSR | S_IRUSR);
MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
- MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
@@ -1487,6 +1529,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR,
mvm->debugfs_dir, &mvm->d3_wake_sysassert))
goto err;
+ MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
#endif
if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 0c5c0b0..b8ab4a1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -197,8 +197,7 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
/*
* Get the mask of the queues used by the vif
*/
-u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
+u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif)
{
u32 qmask = 0, ac;
@@ -227,7 +226,7 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
}
/* Mark the queues used by the vif */
- data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(data->mvm, vif);
+ data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(vif);
/* Mark MAC IDs as used by clearing the available bit, and
* (below) mark TSFs as used if their existing use is not
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index b6d2683..1ee9dcd 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -69,6 +69,7 @@
#include <linux/etherdevice.h>
#include <linux/ip.h>
#include <linux/if_arp.h>
+#include <linux/devcoredump.h>
#include <net/mac80211.h>
#include <net/ieee80211_radiotap.h>
#include <net/tcp.h>
@@ -679,10 +680,51 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
}
-#ifdef CONFIG_IWLWIFI_DEBUGFS
+static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
+ const void *data, size_t datalen)
+{
+ const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
+ ssize_t bytes_read;
+ ssize_t bytes_read_trans;
+
+ if (offset < dump_ptrs->op_mode_len) {
+ bytes_read = min_t(ssize_t, count,
+ dump_ptrs->op_mode_len - offset);
+ memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
+ bytes_read);
+ offset += bytes_read;
+ count -= bytes_read;
+
+ if (count == 0)
+ return bytes_read;
+ } else {
+ bytes_read = 0;
+ }
+
+ if (!dump_ptrs->trans_ptr)
+ return bytes_read;
+
+ offset -= dump_ptrs->op_mode_len;
+ bytes_read_trans = min_t(ssize_t, count,
+ dump_ptrs->trans_ptr->len - offset);
+ memcpy(buffer + bytes_read,
+ (u8 *)dump_ptrs->trans_ptr->data + offset,
+ bytes_read_trans);
+
+ return bytes_read + bytes_read_trans;
+}
+
+static void iwl_mvm_free_coredump(const void *data)
+{
+ const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
+
+ vfree(fw_error_dump->op_mode_ptr);
+ vfree(fw_error_dump->trans_ptr);
+ kfree(fw_error_dump);
+}
+
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
{
- static char *env[] = { "DRIVER=iwlwifi", "EVENT=error_dump", NULL };
struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data;
struct iwl_fw_error_dump_info *dump_info;
@@ -695,10 +737,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
- if (mvm->fw_error_dump)
- return;
-
- fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL);
+ fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
if (!fw_error_dump)
return;
@@ -773,12 +812,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
if (fw_error_dump->trans_ptr)
file_len += fw_error_dump->trans_ptr->len;
dump_file->file_len = cpu_to_le32(file_len);
- mvm->fw_error_dump = fw_error_dump;
- /* notify the userspace about the error we had */
- kobject_uevent_env(&mvm->hw->wiphy->dev.kobj, KOBJ_CHANGE, env);
+ dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0,
+ GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump);
}
-#endif
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{
@@ -859,9 +896,8 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
return ret;
}
-static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw)
+static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
mutex_lock(&mvm->mutex);
@@ -879,6 +915,21 @@ static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw)
mutex_unlock(&mvm->mutex);
}
+static void
+iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
+ enum ieee80211_reconfig_type reconfig_type)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ switch (reconfig_type) {
+ case IEEE80211_RECONFIG_TYPE_RESTART:
+ iwl_mvm_restart_complete(mvm);
+ break;
+ case IEEE80211_RECONFIG_TYPE_SUSPEND:
+ break;
+ }
+}
+
void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
{
lockdep_assert_held(&mvm->mutex);
@@ -1087,7 +1138,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
- u32 tfd_msk = iwl_mvm_mac_get_queues_mask(mvm, vif);
+ u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif);
if (tfd_msk) {
mutex_lock(&mvm->mutex);
@@ -1383,6 +1434,9 @@ bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm,
.cmd = cmd,
};
+ if (IWL_MVM_FW_BCAST_FILTER_PASS_ALL)
+ return false;
+
memset(cmd, 0, sizeof(*cmd));
cmd->max_bcast_filters = ARRAY_SIZE(cmd->filters);
cmd->max_macs = ARRAY_SIZE(cmd->macs);
@@ -2171,25 +2225,9 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
mvm->scan_status = IWL_MVM_SCAN_SCHED;
- if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
- ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
- if (ret)
- goto err;
- }
-
- ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
+ ret = iwl_mvm_scan_offload_start(mvm, vif, req, ies);
if (ret)
- goto err;
-
- if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
- ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
- else
- ret = iwl_mvm_sched_scan_start(mvm, req);
-
- if (!ret)
- goto out;
-err:
- mvm->scan_status = IWL_MVM_SCAN_NONE;
+ mvm->scan_status = IWL_MVM_SCAN_NONE;
out:
mutex_unlock(&mvm->mutex);
return ret;
@@ -3017,25 +3055,31 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
mvmvif = iwl_mvm_vif_from_mac80211(vif);
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);
- if (WARN_ON_ONCE(!mvmsta))
- goto done;
+ if (WARN_ON_ONCE(!mvmsta)) {
+ mutex_unlock(&mvm->mutex);
+ return;
+ }
if (drop) {
if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true))
IWL_ERR(mvm, "flush request fail\n");
+ mutex_unlock(&mvm->mutex);
} else {
- iwl_trans_wait_tx_queue_empty(mvm->trans,
- mvmsta->tfd_queue_msk);
+ u32 tfd_queue_msk = mvmsta->tfd_queue_msk;
+ mutex_unlock(&mvm->mutex);
+
+ /* this can take a while, and we may need/want other operations
+ * to succeed while doing this, so do it without the mutex held
+ */
+ iwl_trans_wait_tx_queue_empty(mvm->trans, tfd_queue_msk);
}
-done:
- mutex_unlock(&mvm->mutex);
}
const struct ieee80211_ops iwl_mvm_hw_ops = {
.tx = iwl_mvm_mac_tx,
.ampdu_action = iwl_mvm_mac_ampdu_action,
.start = iwl_mvm_mac_start,
- .restart_complete = iwl_mvm_mac_restart_complete,
+ .reconfig_complete = iwl_mvm_mac_reconfig_complete,
.stop = iwl_mvm_mac_stop,
.add_interface = iwl_mvm_mac_add_interface,
.remove_interface = iwl_mvm_mac_remove_interface,
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 845429c..d015fac 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -649,7 +649,6 @@ struct iwl_mvm {
/* -1 for always, 0 for never, >0 for that many times */
s8 restart_fw;
struct work_struct fw_error_dump_wk;
- struct iwl_mvm_dump_ptrs *fw_error_dump;
#ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led;
@@ -660,6 +659,10 @@ struct iwl_mvm {
#ifdef CONFIG_PM_SLEEP
struct wiphy_wowlan_support wowlan;
int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
+
+ /* sched scan settings for net detect */
+ struct cfg80211_sched_scan_request *nd_config;
+ struct ieee80211_scan_ies *nd_ies;
#ifdef CONFIG_IWLWIFI_DEBUGFS
u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */
bool d3_test_active;
@@ -906,8 +909,7 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool force_assoc_off, const u8 *bssid_override);
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
-u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif);
+u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
@@ -950,6 +952,10 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
+int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct cfg80211_sched_scan_request *req,
+ struct ieee80211_scan_ies *ies);
int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify);
int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
@@ -1207,11 +1213,9 @@ void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
+struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
+
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
-#else
-static inline void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) {}
-#endif
#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 5b719ee..7a95785 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -403,6 +403,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (cfg->max_rx_agg_size)
hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size;
+ if (cfg->max_tx_agg_size)
+ hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size;
+
op_mode = hw->priv;
op_mode->ops = &iwl_mvm_ops;
@@ -585,16 +588,18 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
ieee80211_unregister_hw(mvm->hw);
kfree(mvm->scan_cmd);
- if (mvm->fw_error_dump) {
- vfree(mvm->fw_error_dump->op_mode_ptr);
- vfree(mvm->fw_error_dump->trans_ptr);
- kfree(mvm->fw_error_dump);
- }
kfree(mvm->mcast_filter_cmd);
mvm->mcast_filter_cmd = NULL;
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
kfree(mvm->d3_resume_sram);
+ if (mvm->nd_config) {
+ kfree(mvm->nd_config->match_sets);
+ kfree(mvm->nd_config);
+ mvm->nd_config = NULL;
+ kfree(mvm->nd_ies);
+ mvm->nd_ies = NULL;
+ }
#endif
iwl_trans_op_mode_leave(mvm->trans);
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index 18a5399..ce88484 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -505,10 +505,11 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type)
static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate,
const char *prefix)
{
- IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d\n",
+ IWL_DEBUG_RATE(mvm,
+ "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC %d\n",
prefix, rs_pretty_lq_type(rate->type),
rate->index, rs_pretty_ant(rate->ant),
- rate->bw, rate->sgi, rate->ldpc);
+ rate->bw, rate->sgi, rate->ldpc, rate->stbc);
}
static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
@@ -741,6 +742,12 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type);
}
+ if (is_siso(rate) && rate->stbc) {
+ /* To enable STBC we need to set both a flag and ANT_AB */
+ ucode_rate |= RATE_MCS_ANT_AB_MSK;
+ ucode_rate |= RATE_MCS_VHT_STBC_MSK;
+ }
+
ucode_rate |= rate->bw;
if (rate->sgi)
ucode_rate |= RATE_MCS_SGI_MSK;
@@ -785,6 +792,8 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
rate->sgi = true;
if (ucode_rate & RATE_MCS_LDPC_MSK)
rate->ldpc = true;
+ if (ucode_rate & RATE_MCS_VHT_STBC_MSK)
+ rate->stbc = true;
rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK;
@@ -794,7 +803,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
if (nss == 1) {
rate->type = LQ_HT_SISO;
- WARN_ON_ONCE(num_of_ant != 1);
+ WARN_ON_ONCE(!rate->stbc && num_of_ant != 1);
} else if (nss == 2) {
rate->type = LQ_HT_MIMO2;
WARN_ON_ONCE(num_of_ant != 2);
@@ -992,7 +1001,15 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
static inline bool rs_rate_match(struct rs_rate *a,
struct rs_rate *b)
{
- return (a->type == b->type) && (a->ant == b->ant) && (a->sgi == b->sgi);
+ bool ant_match;
+
+ if (a->stbc)
+ ant_match = (b->ant == ANT_A || b->ant == ANT_B);
+ else
+ ant_match = (a->ant == b->ant);
+
+ return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi)
+ && ant_match;
}
static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags)
@@ -1225,7 +1242,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
done:
/* See if there's a better rate or modulation mode to try. */
- if (sta && sta->supp_rates[info->band])
+ if (sta->supp_rates[info->band])
rs_rate_scale_perform(mvm, sta, lq_sta, tid);
}
@@ -1623,6 +1640,8 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
else
rate->type = LQ_LEGACY_G;
+ rate->bw = RATE_MCS_CHAN_WIDTH_20;
+ rate->ldpc = false;
rate_mask = lq_sta->active_legacy_rate;
} else if (column->mode == RS_SISO) {
rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO;
@@ -1634,8 +1653,11 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
WARN_ON_ONCE("Bad column mode");
}
- rate->bw = rs_bw_from_sta_bw(sta);
- rate->ldpc = lq_sta->ldpc;
+ if (column->mode != RS_LEGACY) {
+ rate->bw = rs_bw_from_sta_bw(sta);
+ rate->ldpc = lq_sta->ldpc;
+ }
+
search_tbl->column = col_id;
rs_set_expected_tpt_table(lq_sta, search_tbl);
@@ -1754,6 +1776,29 @@ out:
return action;
}
+static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ struct iwl_lq_sta *lq_sta)
+{
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+ struct ieee80211_vif *vif = mvmsta->vif;
+ bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION &&
+ !vif->bss_conf.ps);
+
+ /* Our chip supports Tx STBC and the peer is an HT/VHT STA which
+ * supports STBC of at least 1*SS
+ */
+ if (!lq_sta->stbc)
+ return false;
+
+ if (!mvm->ps_disabled && !sta_ps_disabled)
+ return false;
+
+ if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))
+ return false;
+
+ return true;
+}
+
static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index,
int *weaker, int *stronger)
{
@@ -2675,6 +2720,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (mvm->cfg->ht_params->ldpc &&
(ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING))
lq_sta->ldpc = true;
+
+ if (mvm->cfg->ht_params->stbc &&
+ (num_of_ant(mvm->fw->valid_tx_ant) > 1) &&
+ (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC))
+ lq_sta->stbc = true;
} else {
rs_vht_set_enabled_rates(sta, vht_cap, lq_sta);
lq_sta->is_vht = true;
@@ -2682,8 +2732,16 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (mvm->cfg->ht_params->ldpc &&
(vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))
lq_sta->ldpc = true;
+
+ if (mvm->cfg->ht_params->stbc &&
+ (num_of_ant(mvm->fw->valid_tx_ant) > 1) &&
+ (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK))
+ lq_sta->stbc = true;
}
+ if (IWL_MVM_RS_DISABLE_MIMO)
+ lq_sta->active_mimo2_rate = 0;
+
lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate,
BITS_PER_LONG);
lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate,
@@ -2692,11 +2750,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
BITS_PER_LONG);
IWL_DEBUG_RATE(mvm,
- "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d\n",
+ "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC%d\n",
lq_sta->active_legacy_rate,
lq_sta->active_siso_rate,
lq_sta->active_mimo2_rate,
- lq_sta->is_vht, lq_sta->ldpc);
+ lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc);
IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n",
lq_sta->max_legacy_rate_idx,
lq_sta->max_siso_rate_idx,
@@ -2820,6 +2878,7 @@ static void rs_fill_rates_for_column(struct iwl_mvm *mvm,
* rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps
*/
static void rs_build_rates_table(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
const struct rs_rate *initial_rate)
{
@@ -2832,6 +2891,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
memcpy(&rate, initial_rate, sizeof(rate));
valid_tx_ant = mvm->fw->valid_tx_ant;
+ rate.stbc = rs_stbc_allow(mvm, sta, lq_sta);
if (is_siso(&rate)) {
num_rates = RS_INITIAL_SISO_NUM_RATES;
@@ -2903,7 +2963,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(!sta || !initial_rate))
return;
- rs_build_rates_table(mvm, lq_sta, initial_rate);
+ rs_build_rates_table(mvm, sta, lq_sta, initial_rate);
if (num_of_ant(initial_rate->ant) == 1)
lq_cmd->single_stream_ant_msk = initial_rate->ant;
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index eb34c12..defd70a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -208,6 +208,7 @@ struct rs_rate {
u32 bw;
bool sgi;
bool ldpc;
+ bool stbc;
};
@@ -331,6 +332,7 @@ struct iwl_lq_sta {
u64 last_tx;
bool is_vht;
bool ldpc; /* LDPC Rx is supported by the STA */
+ bool stbc; /* Tx STBC is supported by chip and Rx by STA */
enum ieee80211_band band;
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 7554f70..fb2a862 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -270,7 +270,8 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
bool *global_bound = data;
- if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < MAX_PHYS)
+ if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt &&
+ mvmvif->phy_ctxt->id < MAX_PHYS)
*global_bound = true;
}
@@ -662,6 +663,7 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
mvm->scan_status = IWL_MVM_SCAN_NONE;
ieee80211_scan_completed(mvm->hw,
status == IWL_SCAN_OFFLOAD_ABORTED);
+ iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
}
mvm->last_ebs_successful = !ebs_status;
@@ -997,6 +999,31 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
sizeof(scan_req), &scan_req);
}
+int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct cfg80211_sched_scan_request *req,
+ struct ieee80211_scan_ies *ies)
+{
+ int ret;
+
+ if ((mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
+ ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
+ if (ret)
+ return ret;
+ ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
+ } else {
+ ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
+ if (ret)
+ return ret;
+ ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
+ if (ret)
+ return ret;
+ ret = iwl_mvm_sched_scan_start(mvm, req);
+ }
+
+ return ret;
+}
+
static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
{
int ret;
@@ -1071,8 +1098,12 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
/*
* Clear the scan status so the next scan requests will succeed. This
* also ensures the Rx handler doesn't do anything, as the scan was
- * stopped from above.
+ * stopped from above. Since the rx handler won't do anything now,
+ * we have to release the scan reference here.
*/
+ if (mvm->scan_status == IWL_MVM_SCAN_OS)
+ iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
+
mvm->scan_status = IWL_MVM_SCAN_NONE;
if (notify) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 1731c20..dd0dc5b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -609,7 +609,7 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex);
- qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
+ qmask = iwl_mvm_mac_get_queues_mask(vif);
/*
* The firmware defines the TFD queue mask to only be relevant
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index acca44a..d4f2c29 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -64,10 +64,6 @@
*****************************************************************************/
#include "mvm.h"
-#include "iwl-config.h"
-#include "iwl-io.h"
-#include "iwl-csr.h"
-#include "iwl-prph.h"
#define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index c6a517c..8d84873 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -189,8 +189,10 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
/* HT rate doesn't make sense for a non data frame */
WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS,
- "Got an HT rate for a non data frame 0x%x\n",
- info->control.rates[0].flags);
+ "Got an HT rate (flags:0x%x/mcs:%d) for a non data frame (fc:0x%x)\n",
+ info->control.rates[0].flags,
+ info->control.rates[0].idx,
+ le16_to_cpu(fc));
rate_idx = info->control.rates[0].idx;
/* if the rate isn't a well known legacy rate, take the lowest one */
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index 8021f6e..e56e77e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -734,3 +734,40 @@ bool iwl_mvm_is_idle(struct iwl_mvm *mvm)
return idle;
}
+
+struct iwl_bss_iter_data {
+ struct ieee80211_vif *vif;
+ bool error;
+};
+
+static void iwl_mvm_bss_iface_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_bss_iter_data *data = _data;
+
+ if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
+ return;
+
+ if (data->vif) {
+ data->error = true;
+ return;
+ }
+
+ data->vif = vif;
+}
+
+struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
+{
+ struct iwl_bss_iter_data bss_iter_data = {};
+
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_bss_iface_iterator, &bss_iter_data);
+
+ if (bss_iter_data.error) {
+ IWL_ERR(mvm, "More than one managed interface active!\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ return bss_iter_data.vif;
+}
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index dd2f3f8..ea8efed 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -133,7 +133,7 @@ static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans)
break;
}
- if (!page)
+ if (WARN_ON_ONCE(!page))
return;
trans_pcie->fw_mon_page = page;
@@ -747,14 +747,11 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
int first_ucode_section;
IWL_DEBUG_FW(trans,
- "working with %s image\n",
- image->is_secure ? "Secured" : "Non Secured");
- IWL_DEBUG_FW(trans,
"working with %s CPU\n",
image->is_dual_cpus ? "Dual" : "Single");
/* configure the ucode to be ready to get the secured image */
- if (image->is_secure) {
+ if (iwl_has_secure_boot(trans->hw_rev, trans->cfg->device_family)) {
/* set secure boot inspector addresses */
iwl_write_prph(trans,
LMPM_SECURE_INSPECTOR_CODE_ADDR,
@@ -790,7 +787,8 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
LMPM_SECURE_CPU2_HDR_MEM_SPACE);
/* load to FW the binary sections of CPU2 */
- if (image->is_secure)
+ if (iwl_has_secure_boot(trans->hw_rev,
+ trans->cfg->device_family))
ret = iwl_pcie_load_cpu_secured_sections(
trans, image, 2,
&first_ucode_section);
@@ -821,7 +819,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
else
iwl_write32(trans, CSR_RESET, 0);
- if (image->is_secure) {
+ if (iwl_has_secure_boot(trans->hw_rev, trans->cfg->device_family)) {
/* wait for image verification to complete */
ret = iwl_poll_prph_bit(trans,
LMPM_SECURE_BOOT_CPU1_STATUS_ADDR,
@@ -1023,14 +1021,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
return 0;
}
- iwl_pcie_set_pwr(trans, false);
-
- val = iwl_read32(trans, CSR_RESET);
- if (val & CSR_RESET_REG_FLAG_NEVO_RESET) {
- *status = IWL_D3_STATUS_RESET;
- return 0;
- }
-
/*
* Also enables interrupts - none will happen as the device doesn't
* know we're waking it up, only when the opmode actually tells it
@@ -1050,6 +1040,8 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
return ret;
}
+ iwl_pcie_set_pwr(trans, false);
+
iwl_trans_pcie_tx_reset(trans);
ret = iwl_pcie_rx_init(trans);
@@ -1058,7 +1050,12 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
return ret;
}
- *status = IWL_D3_STATUS_ALIVE;
+ val = iwl_read32(trans, CSR_RESET);
+ if (val & CSR_RESET_REG_FLAG_NEVO_RESET)
+ *status = IWL_D3_STATUS_RESET;
+ else
+ *status = IWL_D3_STATUS_ALIVE;
+
return 0;
}
@@ -1767,6 +1764,13 @@ err:
IWL_ERR(trans, "failed to create the trans debugfs entry\n");
return -ENOMEM;
}
+#else
+static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
+ struct dentry *dir)
+{
+ return 0;
+}
+#endif /*CONFIG_IWLWIFI_DEBUGFS */
static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
{
@@ -2044,13 +2048,6 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
return dump_data;
}
-#else
-static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
- struct dentry *dir)
-{
- return 0;
-}
-#endif /*CONFIG_IWLWIFI_DEBUGFS */
static const struct iwl_trans_ops trans_ops_pcie = {
.start_hw = iwl_trans_pcie_start_hw,
@@ -2087,9 +2084,7 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.release_nic_access = iwl_trans_pcie_release_nic_access,
.set_bits_mask = iwl_trans_pcie_set_bits_mask,
-#ifdef CONFIG_IWLWIFI_DEBUGFS
.dump_data = iwl_trans_pcie_dump_data,
-#endif
};
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
OpenPOWER on IntegriCloud