summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/mvm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-09-18 22:34:53 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2019-09-18 22:34:53 +0300
commit81160dda9a7aad13c04e78bb2cfd3c4630e3afab (patch)
tree4bf79ffa9fc7dc5e2915ff978778c3402c491113 /drivers/net/wireless/intel/iwlwifi/mvm
parent8b53c76533aa4356602aea98f98a2f3b4051464c (diff)
parent1bab8d4c488be22d57f9dd09968c90a0ddc413bf (diff)
downloadlinux-81160dda9a7aad13c04e78bb2cfd3c4630e3afab.tar.xz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from David Miller: 1) Support IPV6 RA Captive Portal Identifier, from Maciej Żenczykowski. 2) Use bio_vec in the networking instead of custom skb_frag_t, from Matthew Wilcox. 3) Make use of xmit_more in r8169 driver, from Heiner Kallweit. 4) Add devmap_hash to xdp, from Toke Høiland-Jørgensen. 5) Support all variants of 5750X bnxt_en chips, from Michael Chan. 6) More RTNL avoidance work in the core and mlx5 driver, from Vlad Buslov. 7) Add TCP syn cookies bpf helper, from Petar Penkov. 8) Add 'nettest' to selftests and use it, from David Ahern. 9) Add extack support to drop_monitor, add packet alert mode and support for HW drops, from Ido Schimmel. 10) Add VLAN offload to stmmac, from Jose Abreu. 11) Lots of devm_platform_ioremap_resource() conversions, from YueHaibing. 12) Add IONIC driver, from Shannon Nelson. 13) Several kTLS cleanups, from Jakub Kicinski. * git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1930 commits) mlxsw: spectrum_buffers: Add the ability to query the CPU port's shared buffer mlxsw: spectrum: Register CPU port with devlink mlxsw: spectrum_buffers: Prevent changing CPU port's configuration net: ena: fix incorrect update of intr_delay_resolution net: ena: fix retrieval of nonadaptive interrupt moderation intervals net: ena: fix update of interrupt moderation register net: ena: remove all old adaptive rx interrupt moderation code from ena_com net: ena: remove ena_restore_ethtool_params() and relevant fields net: ena: remove old adaptive interrupt moderation code from ena_netdev net: ena: remove code duplication in ena_com_update_nonadaptive_moderation_interval _*() net: ena: enable the interrupt_moderation in driver_supported_features net: ena: reimplement set/get_coalesce() net: ena: switch to dim algorithm for rx adaptive interrupt moderation net: ena: add intr_moder_rx_interval to struct ena_com_dev and use it net: phy: adin: implement Energy Detect Powerdown mode via phy-tunable ethtool: implement Energy Detect Powerdown support via phy-tunable xen-netfront: do not assume sk_buff_head list is empty in error handling s390/ctcm: Delete unnecessary checks before the macro call “dev_kfree_skb” net: ena: don't wake up tx queue when down drop_monitor: Better sanitize notified packets ...
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/constants.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c224
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c154
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/fw.c183
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/led.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c427
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mvm.h150
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/nvm.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c480
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c11
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/power.c82
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c19
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rx.c18
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c115
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c98
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c29
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tdls.c9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/time-event.c8
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tt.c12
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c9
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/utils.c19
23 files changed, 640 insertions, 1440 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
index 915b172da57a..60aff2ecec12 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -153,5 +153,6 @@
#define IWL_MVM_FTM_INITIATOR_DYNACK true
#define IWL_MVM_D3_DEBUG false
#define IWL_MVM_USE_TWT false
+#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 10
#endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index cec40855a641..86c2c587e755 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -735,40 +735,16 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
return 0;
}
-static void
-iwl_mvm_iter_d0i3_ap_keys(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- void (*iter)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key,
- void *data),
- void *data)
-{
- struct ieee80211_sta *ap_sta;
-
- rcu_read_lock();
-
- ap_sta = rcu_dereference(mvm->fw_id_to_mac_id[mvm->d0i3_ap_sta_id]);
- if (IS_ERR_OR_NULL(ap_sta))
- goto out;
-
- ieee80211_iter_keys_rcu(mvm->hw, vif, iter, data);
-out:
- rcu_read_unlock();
-}
-
-int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- bool d0i3,
- u32 cmd_flags)
+static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ u32 cmd_flags)
{
struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
bool unified = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
struct wowlan_key_data key_data = {
- .configure_keys = !d0i3 && !unified,
+ .configure_keys = !unified,
.use_rsc_tsc = false,
.tkip = &tkip_cmd,
.use_tkip = false,
@@ -784,25 +760,16 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
* if we have to configure keys, call ieee80211_iter_keys(),
* as we need non-atomic context in order to take the
* required locks.
- * for the d0i3 we can't use ieee80211_iter_keys(), as
- * taking (almost) any mutex might result in deadlock.
*/
- if (!d0i3) {
- /*
- * Note that currently we don't propagate cmd_flags
- * to the iterator. In case of key_data.configure_keys,
- * all the configured commands are SYNC, and
- * iwl_mvm_wowlan_program_keys() will take care of
- * locking/unlocking mvm->mutex.
- */
- ieee80211_iter_keys(mvm->hw, vif,
- iwl_mvm_wowlan_program_keys,
- &key_data);
- } else {
- iwl_mvm_iter_d0i3_ap_keys(mvm, vif,
- iwl_mvm_wowlan_program_keys,
- &key_data);
- }
+ /*
+ * Note that currently we don't propagate cmd_flags
+ * to the iterator. In case of key_data.configure_keys,
+ * all the configured commands are SYNC, and
+ * iwl_mvm_wowlan_program_keys() will take care of
+ * locking/unlocking mvm->mutex.
+ */
+ ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_program_keys,
+ &key_data);
if (key_data.error) {
ret = -EIO;
@@ -830,7 +797,7 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
}
/* configure rekey data only if offloaded rekey is supported (d3) */
- if (mvmvif->rekey_data.valid && !d0i3) {
+ if (mvmvif->rekey_data.valid) {
memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
memcpy(kek_kck_cmd.kck, mvmvif->rekey_data.kck,
NL80211_KCK_LEN);
@@ -864,6 +831,8 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
+ mvm->offload_tid = wowlan_config_cmd->offloading_tid;
+
if (!unified_image) {
ret = iwl_mvm_switch_to_d3(mvm);
if (ret)
@@ -881,8 +850,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
* that isn't really a problem though.
*/
mutex_unlock(&mvm->mutex);
- ret = iwl_mvm_wowlan_config_key_params(mvm, vif, false,
- CMD_ASYNC);
+ ret = iwl_mvm_wowlan_config_key_params(mvm, vif, CMD_ASYNC);
mutex_lock(&mvm->mutex);
if (ret)
return ret;
@@ -936,6 +904,8 @@ iwl_mvm_netdetect_config(struct iwl_mvm *mvm,
wowlan_config_cmd.wakeup_filter |=
cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
+ wowlan_config_cmd.sta_id = mvm->aux_sta.sta_id;
+
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
sizeof(wowlan_config_cmd),
&wowlan_config_cmd);
@@ -1043,6 +1013,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
} else {
struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
+ wowlan_config_cmd.sta_id = mvmvif->ap_sta_id;
+
ap_sta = rcu_dereference_protected(
mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
lockdep_is_held(&mvm->mutex));
@@ -1082,8 +1054,8 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
* recording before entering D3. In later devices the FW stops the
* recording automatically.
*/
- if (mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_9000)
- iwl_fw_dbg_stop_recording(mvm->trans, NULL);
+ if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)
+ iwl_fw_dbg_stop_restart_recording(&mvm->fwrt, NULL, true);
/* must be last -- this switches firmware state */
ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);
@@ -1100,13 +1072,12 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
- iwl_trans_d3_suspend(mvm->trans, test, !unified_image);
+ ret = iwl_trans_d3_suspend(mvm->trans, test, !unified_image);
out:
if (ret < 0) {
iwl_mvm_free_nd(mvm);
if (!unified_image) {
- iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
if (mvm->fw_restart > 0) {
mvm->fw_restart--;
ieee80211_restart_hw(mvm->hw);
@@ -1119,37 +1090,12 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
return ret;
}
-static int iwl_mvm_enter_d0i3_sync(struct iwl_mvm *mvm)
-{
- struct iwl_notification_wait wait_d3;
- static const u16 d3_notif[] = { D3_CONFIG_CMD };
- int ret;
-
- iwl_init_notification_wait(&mvm->notif_wait, &wait_d3,
- d3_notif, ARRAY_SIZE(d3_notif),
- NULL, NULL);
-
- ret = iwl_mvm_enter_d0i3(mvm->hw->priv);
- if (ret)
- goto remove_notif;
-
- ret = iwl_wait_notification(&mvm->notif_wait, &wait_d3, HZ);
- WARN_ON_ONCE(ret);
- return ret;
-
-remove_notif:
- iwl_remove_notification(&mvm->notif_wait, &wait_d3);
- return ret;
-}
-
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_trans *trans = mvm->trans;
int ret;
- /* make sure the d0i3 exit work is not pending */
- flush_work(&mvm->d0i3_exit_work);
iwl_mvm_pause_tcm(mvm, true);
iwl_fw_runtime_suspend(&mvm->fwrt);
@@ -1158,25 +1104,6 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
if (ret)
return ret;
- if (wowlan->any) {
- trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3;
-
- if (iwl_mvm_enter_d0i3_on_suspend(mvm)) {
- ret = iwl_mvm_enter_d0i3_sync(mvm);
-
- if (ret)
- return ret;
- }
-
- mutex_lock(&mvm->d0i3_suspend_mutex);
- __set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
- mutex_unlock(&mvm->d0i3_suspend_mutex);
-
- iwl_trans_d3_suspend(trans, false, false);
-
- return 0;
- }
-
trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
return __iwl_mvm_suspend(hw, wowlan, false);
@@ -1735,6 +1662,13 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
mvm_ap_sta->tid_data[i].seq_number = seq;
}
+ if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+ i = mvm->offload_tid;
+ iwl_trans_set_q_ptrs(mvm->trans,
+ mvm_ap_sta->tid_data[i].txq_id,
+ mvm_ap_sta->tid_data[i].seq_number >> 4);
+ }
+
/* now we have all the data we need, unlock to avoid mac80211 issues */
mutex_unlock(&mvm->mutex);
@@ -1752,30 +1686,6 @@ out_unlock:
return false;
}
-void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct iwl_wowlan_status *status)
-{
- struct iwl_mvm_d3_gtk_iter_data gtkdata = {
- .mvm = mvm,
- .status = status,
- };
-
- /*
- * rekey handling requires taking locks that can't be taken now.
- * however, d0i3 doesn't offload rekey, so we're fine.
- */
- if (WARN_ON_ONCE(status->num_of_gtk_rekeys))
- return;
-
- /* find last GTK that we used initially, if any */
- gtkdata.find_phase = true;
- iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata);
-
- gtkdata.find_phase = false;
- iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata);
-}
-
#define ND_QUERY_BUF_LEN (sizeof(struct iwl_scan_offload_profile_match) * \
IWL_SCAN_MAX_PROFILES)
@@ -2024,15 +1934,6 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
if (IS_ERR_OR_NULL(vif))
goto err;
- ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !unified_image);
- if (ret)
- goto err;
-
- if (d3_status != IWL_D3_STATUS_ALIVE) {
- IWL_INFO(mvm, "Device was reset during suspend\n");
- goto err;
- }
-
iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);
if (iwl_mvm_check_rt_status(mvm, vif)) {
@@ -2044,6 +1945,15 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
goto err;
}
+ ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !unified_image);
+ if (ret)
+ goto err;
+
+ if (d3_status != IWL_D3_STATUS_ALIVE) {
+ IWL_INFO(mvm, "Device was reset during suspend\n");
+ goto err;
+ }
+
if (d0i3_first) {
ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, 0, 0, NULL);
if (ret < 0) {
@@ -2059,6 +1969,9 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
*/
iwl_mvm_update_changed_regdom(mvm);
+ /* Re-configure PPAG settings */
+ iwl_mvm_ppag_send_cmd(mvm);
+
if (!unified_image)
/* Re-configure default SAR profile */
iwl_mvm_sar_select_profile(mvm, 1, 1);
@@ -2115,14 +2028,6 @@ out:
* 2. We are using a unified image but had an error while exiting D3
*/
set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
- /*
- * When switching images we return 1, which causes mac80211
- * to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART.
- * This type of reconfig calls iwl_mvm_restart_complete(),
- * where we unref the IWL_MVM_REF_UCODE_DOWN, so we need
- * to take the reference here.
- */
- iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
return 1;
}
@@ -2134,53 +2039,12 @@ static int iwl_mvm_resume_d3(struct iwl_mvm *mvm)
return __iwl_mvm_resume(mvm, false);
}
-static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm)
-{
- bool exit_now;
- enum iwl_d3_status d3_status;
- struct iwl_trans *trans = mvm->trans;
-
- iwl_trans_d3_resume(trans, &d3_status, false, false);
-
- /*
- * make sure to clear D0I3_DEFER_WAKEUP before
- * calling iwl_trans_resume(), which might wait
- * for d0i3 exit completion.
- */
- mutex_lock(&mvm->d0i3_suspend_mutex);
- __clear_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
- exit_now = __test_and_clear_bit(D0I3_PENDING_WAKEUP,
- &mvm->d0i3_suspend_flags);
- mutex_unlock(&mvm->d0i3_suspend_mutex);
- if (exit_now) {
- IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n");
- _iwl_mvm_exit_d0i3(mvm);
- }
-
- iwl_trans_resume(trans);
-
- if (iwl_mvm_enter_d0i3_on_suspend(mvm)) {
- int ret = iwl_mvm_exit_d0i3(mvm->hw->priv);
-
- if (ret)
- return ret;
- /*
- * d0i3 exit will be deferred until reconfig_complete.
- * make sure there we are out of d0i3.
- */
- }
- return 0;
-}
-
int iwl_mvm_resume(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
- if (mvm->trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3)
- ret = iwl_mvm_resume_d0i3(mvm);
- else
- ret = iwl_mvm_resume_d3(mvm);
+ ret = iwl_mvm_resume_d3(mvm);
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
index 0c188a82cfc1..ad18c2f1a806 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -1056,19 +1056,11 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
- int ret;
-
if (!iwl_mvm_firmware_running(mvm))
return -EIO;
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
- if (ret)
- return ret;
-
iwl_force_nmi(mvm->trans);
- iwl_mvm_unref(mvm, IWL_MVM_REF_NMI);
-
return count;
}
@@ -1181,8 +1173,8 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
struct iwl_rx_mpdu_desc *desc;
int bin_len = count / 2;
int ret = -EINVAL;
- size_t mpdu_cmd_hdr_size =
- (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) ?
+ size_t mpdu_cmd_hdr_size = (mvm->trans->trans_cfg->device_family >=
+ IWL_DEVICE_FAMILY_22560) ?
sizeof(struct iwl_rx_mpdu_desc) :
IWL_RX_DESC_SIZE_V1;
@@ -1190,7 +1182,7 @@ static ssize_t iwl_dbgfs_inject_packet_write(struct iwl_mvm *mvm,
return -EIO;
/* supporting only 9000 descriptor */
- if (!mvm->trans->cfg->mq_rx_supported)
+ if (!mvm->trans->trans_cfg->mq_rx_supported)
return -ENOTSUPP;
rxb._page = alloc_pages(GFP_ATOMIC, 0);
@@ -1380,19 +1372,12 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
char *buf, size_t count,
loff_t *ppos)
{
- int ret;
-
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
- if (ret)
- return ret;
if (count == 0)
return 0;
iwl_fw_dbg_collect(&mvm->fwrt, FW_DBG_TRIGGER_USER, buf,
(count - 1), NULL);
- iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
-
return count;
}
@@ -1579,87 +1564,6 @@ static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
}
#endif
-#define PRINT_MVM_REF(ref) do { \
- if (mvm->refs[ref]) \
- pos += scnprintf(buf + pos, bufsz - pos, \
- "\t(0x%lx): %d %s\n", \
- BIT(ref), mvm->refs[ref], #ref); \
-} while (0)
-
-static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_mvm *mvm = file->private_data;
- int i, pos = 0;
- char buf[256];
- const size_t bufsz = sizeof(buf);
- u32 refs = 0;
-
- for (i = 0; i < IWL_MVM_REF_COUNT; i++)
- if (mvm->refs[i])
- refs |= BIT(i);
-
- pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n",
- refs);
-
- PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
- PRINT_MVM_REF(IWL_MVM_REF_SCAN);
- PRINT_MVM_REF(IWL_MVM_REF_ROC);
- PRINT_MVM_REF(IWL_MVM_REF_ROC_AUX);
- PRINT_MVM_REF(IWL_MVM_REF_P2P_CLIENT);
- PRINT_MVM_REF(IWL_MVM_REF_AP_IBSS);
- PRINT_MVM_REF(IWL_MVM_REF_USER);
- PRINT_MVM_REF(IWL_MVM_REF_TX);
- PRINT_MVM_REF(IWL_MVM_REF_TX_AGG);
- PRINT_MVM_REF(IWL_MVM_REF_ADD_IF);
- PRINT_MVM_REF(IWL_MVM_REF_START_AP);
- PRINT_MVM_REF(IWL_MVM_REF_BSS_CHANGED);
- PRINT_MVM_REF(IWL_MVM_REF_PREPARE_TX);
- PRINT_MVM_REF(IWL_MVM_REF_PROTECT_TDLS);
- PRINT_MVM_REF(IWL_MVM_REF_CHECK_CTKILL);
- PRINT_MVM_REF(IWL_MVM_REF_PRPH_READ);
- PRINT_MVM_REF(IWL_MVM_REF_PRPH_WRITE);
- PRINT_MVM_REF(IWL_MVM_REF_NMI);
- PRINT_MVM_REF(IWL_MVM_REF_TM_CMD);
- PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK);
- PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA);
- PRINT_MVM_REF(IWL_MVM_REF_FW_DBG_COLLECT);
- PRINT_MVM_REF(IWL_MVM_REF_INIT_UCODE);
- PRINT_MVM_REF(IWL_MVM_REF_SENDING_CMD);
- PRINT_MVM_REF(IWL_MVM_REF_RX);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
- size_t count, loff_t *ppos)
-{
- unsigned long value;
- int ret;
- bool taken;
-
- ret = kstrtoul(buf, 10, &value);
- if (ret < 0)
- return ret;
-
- mutex_lock(&mvm->mutex);
-
- taken = mvm->refs[IWL_MVM_REF_USER];
- if (value == 1 && !taken)
- iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
- else if (value == 0 && taken)
- iwl_mvm_unref(mvm, IWL_MVM_REF_USER);
- else
- ret = -EINVAL;
-
- mutex_unlock(&mvm->mutex);
-
- if (ret < 0)
- return ret;
- return count;
-}
-
#define MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz) \
_MVM_DEBUGFS_WRITE_FILE_OPS(name, bufsz, struct iwl_mvm)
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) \
@@ -1692,21 +1596,14 @@ iwl_dbgfs_prph_reg_read(struct file *file,
int pos = 0;
char buf[32];
const size_t bufsz = sizeof(buf);
- int ret;
if (!mvm->dbgfs_prph_reg_addr)
return -EINVAL;
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ);
- if (ret)
- return ret;
-
pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
mvm->dbgfs_prph_reg_addr,
iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
- iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ);
-
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -1716,7 +1613,6 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
{
u8 args;
u32 value;
- int ret;
args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
/* if we only want to set the reg address - nothing more to do */
@@ -1727,13 +1623,8 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
if (args != 2)
return -EINVAL;
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
- if (ret)
- return ret;
-
iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
- iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
out:
return count;
}
@@ -1867,6 +1758,38 @@ iwl_dbgfs_uapsd_noagg_bssids_read(struct file *file, char __user *user_buf,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
+static ssize_t
+iwl_dbgfs_ltr_config_write(struct iwl_mvm *mvm,
+ char *buf, size_t count, loff_t *ppos)
+{
+ int ret;
+ struct iwl_ltr_config_cmd ltr_config = {0};
+
+ if (!iwl_mvm_firmware_running(mvm))
+ return -EIO;
+
+ if (sscanf(buf, "%x,%x,%x,%x,%x,%x,%x",
+ &ltr_config.flags,
+ &ltr_config.static_long,
+ &ltr_config.static_short,
+ &ltr_config.ltr_cfg_values[0],
+ &ltr_config.ltr_cfg_values[1],
+ &ltr_config.ltr_cfg_values[2],
+ &ltr_config.ltr_cfg_values[3]) != 7) {
+ return -EINVAL;
+ }
+
+ mutex_lock(&mvm->mutex);
+ ret = iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, sizeof(ltr_config),
+ &ltr_config);
+ mutex_unlock(&mvm->mutex);
+
+ if (ret)
+ IWL_ERR(mvm, "failed to send ltr configuration cmd\n");
+
+ return ret ?: count;
+}
+
MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64);
/* Device wide debugfs entries */
@@ -1892,7 +1815,6 @@ MVM_DEBUGFS_WRITE_FILE_OPS(fw_nmi, 10);
MVM_DEBUGFS_WRITE_FILE_OPS(bt_tx_prio, 10);
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);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl,
@@ -1916,6 +1838,8 @@ MVM_DEBUGFS_READ_WRITE_STA_FILE_OPS(amsdu_len, 16);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(he_sniffer_params, 32);
+MVM_DEBUGFS_WRITE_FILE_OPS(ltr_config, 512);
+
static ssize_t iwl_dbgfs_mem_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -2091,7 +2015,6 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(bt_force_ant, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(scan_ant_rxchain, mvm->debugfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE(prph_reg, mvm->debugfs_dir, 0600);
- MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, 0600);
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, 0200);
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, 0200);
@@ -2104,6 +2027,9 @@ void iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
#endif
MVM_DEBUGFS_ADD_FILE(he_sniffer_params, mvm->debugfs_dir, 0600);
+ if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2))
+ MVM_DEBUGFS_ADD_FILE(ltr_config, mvm->debugfs_dir, 0200);
+
debugfs_create_bool("enable_scan_iteration_notif", 0600,
mvm->debugfs_dir, &mvm->scan_iter_notif_enabled);
debugfs_create_bool("drop_bcn_ap_mode", 0600, mvm->debugfs_dir,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 5de54d1559dd..014eca6596e2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -357,13 +357,14 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
iwl_fw_dbg_error_collect(&mvm->fwrt,
FW_DBG_TRIGGER_ALIVE_TIMEOUT);
- if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000)
+ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000)
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
iwl_read_umac_prph(trans,
UMAG_SB_CPU_2_STATUS));
- else if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000)
+ else if (trans->trans_cfg->device_family >=
+ IWL_DEVICE_FAMILY_8000)
IWL_ERR(mvm,
"SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
iwl_read_prph(trans, SB_CPU_1_STATUS),
@@ -430,7 +431,7 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
iwl_wait_init_complete,
NULL);
- iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY);
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_EARLY, NULL);
/* Will also start the device */
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
@@ -438,7 +439,8 @@ static int iwl_run_unified_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
IWL_ERR(mvm, "Failed to start RT ucode: %d\n", ret);
goto error;
}
- iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE);
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
+ NULL);
/* Send init config command to mark that we are sending NVM access
* commands
@@ -557,7 +559,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
goto remove_notif;
}
- if (mvm->cfg->device_family < IWL_DEVICE_FAMILY_8000) {
+ if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000) {
ret = iwl_mvm_send_bt_init_conf(mvm);
if (ret)
goto remove_notif;
@@ -1002,6 +1004,113 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, sizeof(cmd), &cmd);
}
+static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
+{
+ union acpi_object *wifi_pkg, *data, *enabled;
+ int i, j, ret, tbl_rev;
+ int idx = 2;
+
+ mvm->ppag_table.enabled = cpu_to_le32(0);
+ data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD);
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
+ ACPI_PPAG_WIFI_DATA_SIZE, &tbl_rev);
+
+ if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
+ ret = PTR_ERR(wifi_pkg);
+ goto out_free;
+ }
+
+ enabled = &wifi_pkg->package.elements[1];
+ if (enabled->type != ACPI_TYPE_INTEGER ||
+ (enabled->integer.value != 0 && enabled->integer.value != 1)) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+
+ mvm->ppag_table.enabled = cpu_to_le32(enabled->integer.value);
+ if (!mvm->ppag_table.enabled) {
+ ret = 0;
+ goto out_free;
+ }
+
+ /*
+ * read, verify gain values and save them into the PPAG table.
+ * first sub-band (j=0) corresponds to Low-Band (2.4GHz), and the
+ * following sub-bands to High-Band (5GHz).
+ */
+ for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) {
+ for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) {
+ union acpi_object *ent;
+
+ ent = &wifi_pkg->package.elements[idx++];
+ if (ent->type != ACPI_TYPE_INTEGER ||
+ (j == 0 && ent->integer.value > ACPI_PPAG_MAX_LB) ||
+ (j == 0 && ent->integer.value < ACPI_PPAG_MIN_LB) ||
+ (j != 0 && ent->integer.value > ACPI_PPAG_MAX_HB) ||
+ (j != 0 && ent->integer.value < ACPI_PPAG_MIN_HB)) {
+ mvm->ppag_table.enabled = cpu_to_le32(0);
+ ret = -EINVAL;
+ goto out_free;
+ }
+ mvm->ppag_table.gain[i][j] = ent->integer.value;
+ }
+ }
+ ret = 0;
+out_free:
+ kfree(data);
+ return ret;
+}
+
+int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
+{
+ int i, j, ret;
+
+ if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
+ IWL_DEBUG_RADIO(mvm,
+ "PPAG capability not supported by FW, command not sent.\n");
+ return 0;
+ }
+
+ IWL_DEBUG_RADIO(mvm, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
+ IWL_DEBUG_RADIO(mvm, "PPAG is %s\n",
+ mvm->ppag_table.enabled ? "enabled" : "disabled");
+
+ for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) {
+ for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) {
+ IWL_DEBUG_RADIO(mvm,
+ "PPAG table: chain[%d] band[%d]: gain = %d\n",
+ i, j, mvm->ppag_table.gain[i][j]);
+ }
+ }
+
+ ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP,
+ PER_PLATFORM_ANT_GAIN_CMD),
+ 0, sizeof(mvm->ppag_table),
+ &mvm->ppag_table);
+ if (ret < 0)
+ IWL_ERR(mvm, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
+ ret);
+
+ return ret;
+}
+
+static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
+{
+ int ret;
+
+ ret = iwl_mvm_get_ppag_table(mvm);
+ if (ret < 0) {
+ IWL_DEBUG_RADIO(mvm,
+ "PPAG BIOS table invalid or unavailable. (%d)\n",
+ ret);
+ return 0;
+ }
+ return iwl_mvm_ppag_send_cmd(mvm);
+}
+
#else /* CONFIG_ACPI */
static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
{
@@ -1033,6 +1142,16 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
{
return -ENOENT;
}
+
+int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
+{
+ return -ENOENT;
+}
+
+static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
+{
+ return -ENOENT;
+}
#endif /* CONFIG_ACPI */
void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
@@ -1140,17 +1259,13 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
return ret;
}
- /*
- * Stop and start the transport without entering low power
- * mode. This will save the state of other components on the
- * device that are triggered by the INIT firwmare (MFUART).
- */
- _iwl_trans_stop_device(mvm->trans, false);
- ret = _iwl_trans_start_hw(mvm->trans, false);
+ iwl_fw_dbg_stop_sync(&mvm->fwrt);
+ iwl_trans_stop_device(mvm->trans);
+ ret = iwl_trans_start_hw(mvm->trans);
if (ret)
return ret;
- iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_EARLY);
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_EARLY, NULL);
mvm->rfkill_safe_init_done = false;
ret = iwl_mvm_load_ucode_wait_alive(mvm, IWL_UCODE_REGULAR);
@@ -1159,7 +1274,8 @@ static int iwl_mvm_load_rt_fw(struct iwl_mvm *mvm)
mvm->rfkill_safe_init_done = true;
- iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_AFTER_ALIVE);
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_AFTER_ALIVE,
+ NULL);
return iwl_init_paging(&mvm->fwrt, mvm->fwrt.cur_fw_img);
}
@@ -1169,6 +1285,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
int ret, i;
struct ieee80211_channel *chan;
struct cfg80211_chan_def chandef;
+ struct ieee80211_supported_band *sband = NULL;
lockdep_assert_held(&mvm->mutex);
@@ -1191,7 +1308,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret)
IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
- if (!mvm->trans->dbg.ini_valid) {
+ if (!iwl_trans_dbg_ini_valid(mvm->trans)) {
mvm->fwrt.dump.conf = FW_DBG_INVALID;
/* if we have a destination, assume EARLY START */
if (mvm->fw->dbg.dest_tlv)
@@ -1219,7 +1336,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
/* Init RSS configuration */
- if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
+ if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {
ret = iwl_configure_rxq(mvm);
if (ret) {
IWL_ERR(mvm, "Failed to configure RX queues: %d\n",
@@ -1246,9 +1363,11 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
/* reset quota debouncing buffer - 0xff will yield invalid data */
memset(&mvm->last_quota_cmd, 0xff, sizeof(mvm->last_quota_cmd));
- ret = iwl_mvm_send_dqa_cmd(mvm);
- if (ret)
- goto error;
+ if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_DQA_SUPPORT)) {
+ ret = iwl_mvm_send_dqa_cmd(mvm);
+ if (ret)
+ goto error;
+ }
/* Add auxiliary station for scanning */
ret = iwl_mvm_add_aux_sta(mvm);
@@ -1256,7 +1375,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
/* Add all the PHY contexts */
- chan = &mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[0];
+ i = 0;
+ while (!sband && i < NUM_NL80211_BANDS)
+ sband = mvm->hw->wiphy->bands[i++];
+
+ if (WARN_ON_ONCE(!sband))
+ goto error;
+
+ chan = &sband->channels[0];
+
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
for (i = 0; i < NUM_PHY_CTX; i++) {
/*
@@ -1270,7 +1397,6 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
}
-#ifdef CONFIG_THERMAL
if (iwl_mvm_is_tt_in_fw(mvm)) {
/* in order to give the responsibility of ct-kill and
* TX backoff to FW we need to send empty temperature reporting
@@ -1282,6 +1408,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
iwl_mvm_tt_tx_backoff(mvm, 0);
}
+#ifdef CONFIG_THERMAL
/* TODO: read the budget from BIOS / Platform NVM */
/*
@@ -1294,12 +1421,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret)
goto error;
}
-#else
- /* Initialize tx backoffs to the minimal possible */
- iwl_mvm_tt_tx_backoff(mvm, 0);
#endif
- WARN_ON(iwl_mvm_config_ltr(mvm));
+ if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_LTR_GEN2))
+ WARN_ON(iwl_mvm_config_ltr(mvm));
ret = iwl_mvm_power_update_device(mvm);
if (ret)
@@ -1323,16 +1448,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error;
}
- /* allow FW/transport low power modes if not during restart */
- if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
- iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
-
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB);
if (iwl_acpi_get_eckv(mvm->dev, &mvm->ext_clock_valid))
IWL_DEBUG_INFO(mvm, "ECKV table doesn't exist in BIOS\n");
+ ret = iwl_mvm_ppag_init(mvm);
+ if (ret)
+ goto error;
+
ret = iwl_mvm_sar_init(mvm);
if (ret == 0) {
ret = iwl_mvm_sar_geo_init(mvm);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/led.c b/drivers/net/wireless/intel/iwlwifi/mvm/led.c
index 4348bb00e761..d104da9170ca 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/led.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/led.c
@@ -7,7 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -29,7 +29,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -156,7 +156,7 @@ void iwl_mvm_leds_sync(struct iwl_mvm *mvm)
* if we control through the register, we're doing it
* even when the firmware isn't up, so no need to sync
*/
- if (mvm->cfg->device_family < IWL_DEVICE_FAMILY_8000)
+ if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
return;
iwl_mvm_led_set(mvm, mvm->led.brightness > 0);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index fe776e35b9d0..9c417dd06291 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1431,6 +1431,9 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
else if (rx_missed_bcon_since_rx > IWL_MVM_MISSED_BEACONS_THRESHOLD)
ieee80211_beacon_loss(vif);
+ iwl_dbg_tlv_time_point(&mvm->fwrt,
+ IWL_FW_INI_TIME_POINT_MISSED_BEACONS, NULL);
+
trigger = iwl_fw_dbg_trigger_on(&mvm->fwrt, ieee80211_vif_to_wdev(vif),
FW_DBG_TRIGGER_MISSED_BEACONS);
if (!trigger)
@@ -1447,8 +1450,6 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm,
rx_missed_bcon >= stop_trig_missed_bcon)
iwl_fw_dbg_collect_trig(&mvm->fwrt, trigger, NULL);
- iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_MISSED_BEACONS);
-
out:
rcu_read_unlock();
}
@@ -1594,7 +1595,9 @@ void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
RCU_INIT_POINTER(mvm->csa_vif, NULL);
return;
case NL80211_IFTYPE_STATION:
- iwl_mvm_csa_client_absent(mvm, vif);
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
+ iwl_mvm_csa_client_absent(mvm, vif);
cancel_delayed_work(&mvmvif->csa_work);
ieee80211_chswitch_done(vif, true);
break;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index a7bc00d1296f..cd1b10042fbf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -213,91 +213,6 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key);
-void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
-{
- if (!iwl_mvm_is_d0i3_supported(mvm))
- return;
-
- IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type);
- spin_lock_bh(&mvm->refs_lock);
- mvm->refs[ref_type]++;
- spin_unlock_bh(&mvm->refs_lock);
- iwl_trans_ref(mvm->trans);
-}
-
-void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
-{
- if (!iwl_mvm_is_d0i3_supported(mvm))
- return;
-
- IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type);
- spin_lock_bh(&mvm->refs_lock);
- if (WARN_ON(!mvm->refs[ref_type])) {
- spin_unlock_bh(&mvm->refs_lock);
- return;
- }
- mvm->refs[ref_type]--;
- spin_unlock_bh(&mvm->refs_lock);
- iwl_trans_unref(mvm->trans);
-}
-
-static void iwl_mvm_unref_all_except(struct iwl_mvm *mvm,
- enum iwl_mvm_ref_type except_ref)
-{
- int i, j;
-
- if (!iwl_mvm_is_d0i3_supported(mvm))
- return;
-
- spin_lock_bh(&mvm->refs_lock);
- for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
- if (except_ref == i || !mvm->refs[i])
- continue;
-
- IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d (%d)\n",
- i, mvm->refs[i]);
- for (j = 0; j < mvm->refs[i]; j++)
- iwl_trans_unref(mvm->trans);
- mvm->refs[i] = 0;
- }
- spin_unlock_bh(&mvm->refs_lock);
-}
-
-bool iwl_mvm_ref_taken(struct iwl_mvm *mvm)
-{
- int i;
- bool taken = false;
-
- if (!iwl_mvm_is_d0i3_supported(mvm))
- return true;
-
- spin_lock_bh(&mvm->refs_lock);
- for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
- if (mvm->refs[i]) {
- taken = true;
- break;
- }
- }
- spin_unlock_bh(&mvm->refs_lock);
-
- return taken;
-}
-
-int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
-{
- iwl_mvm_ref(mvm, ref_type);
-
- if (!wait_event_timeout(mvm->d0i3_exit_waitq,
- !test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status),
- HZ)) {
- WARN_ON_ONCE(1);
- iwl_mvm_unref(mvm, ref_type);
- return -EIO;
- }
-
- return 0;
-}
-
static void iwl_mvm_reset_phy_ctxts(struct iwl_mvm *mvm)
{
int i;
@@ -485,7 +400,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
* for older devices. We also don't see this issue on any newer
* devices.
*/
- if (mvm->cfg->device_family >= IWL_DEVICE_FAMILY_9000)
+ if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000)
ieee80211_hw_set(hw, TX_AMSDU);
ieee80211_hw_set(hw, TX_FRAG_LIST);
@@ -762,12 +677,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
#ifdef CONFIG_PM_SLEEP
- if (iwl_mvm_is_d0i3_supported(mvm) &&
- device_can_wakeup(mvm->trans->dev)) {
- mvm->wowlan.flags = WIPHY_WOWLAN_ANY;
- hw->wiphy->wowlan = &mvm->wowlan;
- }
-
if ((unified || mvm->fw->img[IWL_UCODE_WOWLAN].num_sec) &&
mvm->trans->ops->d3_suspend &&
mvm->trans->ops->d3_resume &&
@@ -833,46 +742,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
return ret;
}
-static bool iwl_mvm_defer_tx(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta,
- struct sk_buff *skb)
-{
- struct iwl_mvm_sta *mvmsta;
- bool defer = false;
-
- /*
- * double check the IN_D0I3 flag both before and after
- * taking the spinlock, in order to prevent taking
- * the spinlock when not needed.
- */
- if (likely(!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)))
- return false;
-
- spin_lock(&mvm->d0i3_tx_lock);
- /*
- * testing the flag again ensures the skb dequeue
- * loop (on d0i3 exit) hasn't run yet.
- */
- if (!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status))
- goto out;
-
- mvmsta = iwl_mvm_sta_from_mac80211(sta);
- if (mvmsta->sta_id == IWL_MVM_INVALID_STA ||
- mvmsta->sta_id != mvm->d0i3_ap_sta_id)
- goto out;
-
- __skb_queue_tail(&mvm->d0i3_tx, skb);
-
- /* trigger wakeup */
- iwl_mvm_ref(mvm, IWL_MVM_REF_TX);
- iwl_mvm_unref(mvm, IWL_MVM_REF_TX);
-
- defer = true;
-out:
- spin_unlock(&mvm->d0i3_tx_lock);
- return defer;
-}
-
static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
@@ -917,8 +786,6 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
}
if (sta) {
- if (iwl_mvm_defer_tx(mvm, sta, skb))
- return;
if (iwl_mvm_tx_skb(mvm, skb, sta))
goto drop;
return;
@@ -1086,7 +953,6 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
- bool tx_agg_ref = false;
struct ieee80211_sta *sta = params->sta;
enum ieee80211_ampdu_mlme_action action = params->action;
u16 tid = params->tid;
@@ -1101,31 +967,6 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
if (!(mvm->nvm_data->sku_cap_11n_enable))
return -EACCES;
- /* return from D0i3 before starting a new Tx aggregation */
- switch (action) {
- case IEEE80211_AMPDU_TX_START:
- case IEEE80211_AMPDU_TX_STOP_CONT:
- case IEEE80211_AMPDU_TX_STOP_FLUSH:
- case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
- case IEEE80211_AMPDU_TX_OPERATIONAL:
- /*
- * for tx start, wait synchronously until D0i3 exit to
- * get the correct sequence number for the tid.
- * additionally, some other ampdu actions use direct
- * target access, which is not handled automatically
- * by the trans layer (unlike commands), so wait for
- * d0i3 exit in these cases as well.
- */
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_TX_AGG);
- if (ret)
- return ret;
-
- tx_agg_ref = true;
- break;
- default:
- break;
- }
-
mutex_lock(&mvm->mutex);
switch (action) {
@@ -1186,13 +1027,6 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
}
mutex_unlock(&mvm->mutex);
- /*
- * If the tid is marked as started, we won't use it for offloaded
- * traffic on the next D0i3 entry. It's safe to unref.
- */
- if (tx_agg_ref)
- iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG);
-
return ret;
}
@@ -1216,11 +1050,6 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{
- /* cleanup all stale references (scan, roc), but keep the
- * ucode_down ref until reconfig is complete
- */
- iwl_mvm_unref_all_except(mvm, IWL_MVM_REF_UCODE_DOWN);
-
iwl_mvm_stop_device(mvm);
mvm->cur_aid = 0;
@@ -1242,7 +1071,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_cleanup_iterator, mvm);
mvm->p2p_device_vif = NULL;
- mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
iwl_mvm_reset_phy_ctxts(mvm);
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
@@ -1251,9 +1079,6 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
ieee80211_wake_queues(mvm->hw);
- /* clear any stale d0i3 state */
- clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
-
mvm->vif_count = 0;
mvm->rx_ba_sessions = 0;
mvm->fwrt.dump.conf = FW_DBG_INVALID;
@@ -1278,18 +1103,13 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
clear_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);
/* Clean up some internal and mac80211 state on restart */
iwl_mvm_restart_cleanup(mvm);
- } else {
- /* Hold the reference to prevent runtime suspend while
- * the start procedure runs. It's a bit confusing
- * that the UCODE_DOWN reference is taken, but it just
- * means "UCODE is not UP yet". ( TODO: rename this
- * reference).
- */
- iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
}
ret = iwl_mvm_up(mvm);
- iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_POST_INIT);
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_POST_INIT,
+ NULL);
+ iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_PERIODIC,
+ NULL);
if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
/* Something went wrong - we need to finish some cleanup
@@ -1297,9 +1117,6 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
* would do.
*/
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
-#ifdef CONFIG_PM
- iwl_mvm_d0i3_enable_tx(mvm, NULL);
-#endif
}
return ret;
@@ -1310,19 +1127,6 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw)
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
- /* Some hw restart cleanups must not hold the mutex */
- if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
- /*
- * Make sure we are out of d0i3. This is needed
- * to make sure the reference accounting is correct
- * (and there is no stale d0i3_exit_work).
- */
- wait_event_timeout(mvm->d0i3_exit_waitq,
- !test_bit(IWL_MVM_STATUS_IN_D0I3,
- &mvm->status),
- HZ);
- }
-
mutex_lock(&mvm->mutex);
ret = __iwl_mvm_mac_start(mvm);
mutex_unlock(&mvm->mutex);
@@ -1337,17 +1141,12 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
mutex_lock(&mvm->mutex);
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
-#ifdef CONFIG_PM
- iwl_mvm_d0i3_enable_tx(mvm, NULL);
-#endif
+
ret = iwl_mvm_update_quotas(mvm, true, NULL);
if (ret)
IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n",
ret);
- /* allow transport/FW low power modes */
- iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
-
iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_END_OF_RECOVERY);
/*
@@ -1359,17 +1158,6 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
mutex_unlock(&mvm->mutex);
}
-static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
-{
- if (iwl_mvm_is_d0i3_supported(mvm) &&
- iwl_mvm_enter_d0i3_on_suspend(mvm))
- WARN_ONCE(!wait_event_timeout(mvm->d0i3_exit_waitq,
- !test_bit(IWL_MVM_STATUS_IN_D0I3,
- &mvm->status),
- HZ),
- "D0i3 exit on resume timed out\n");
-}
-
static void
iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
enum ieee80211_reconfig_type reconfig_type)
@@ -1381,7 +1169,6 @@ iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
iwl_mvm_restart_complete(mvm);
break;
case IEEE80211_RECONFIG_TYPE_SUSPEND:
- iwl_mvm_resume_complete(mvm);
break;
}
}
@@ -1443,7 +1230,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- flush_work(&mvm->d0i3_exit_work);
flush_work(&mvm->async_handlers_wk);
flush_work(&mvm->add_stream_wk);
@@ -1457,7 +1243,6 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw)
*/
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
- iwl_fw_cancel_dumps(&mvm->fwrt);
cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork);
cancel_delayed_work_sync(&mvm->scan_timeout_dwork);
iwl_fw_free_dump_desc(&mvm->fwrt);
@@ -1543,15 +1328,20 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
goto out_unlock;
}
- iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
+ iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
- ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
- if (ret)
- goto out_unlock;
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
+ ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
+ if (ret)
+ goto out_unlock;
- iwl_mvm_stop_session_protection(mvm, vif);
+ iwl_mvm_stop_session_protection(mvm, vif);
+ }
}
mvmvif->ps_disabled = false;
@@ -1612,15 +1402,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
RCU_INIT_POINTER(mvmvif->probe_resp_data, NULL);
/*
- * make sure D0i3 exit is completed, otherwise a target access
- * during tx queue configuration could be done when still in
- * D0i3 state.
- */
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_ADD_IF);
- if (ret)
- return ret;
-
- /*
* Not much to do here. The stack will not allow interface
* types or combinations that we didn't advertise, so we
* don't really have to check the types.
@@ -1755,8 +1536,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
out_unlock:
mutex_unlock(&mvm->mutex);
- iwl_mvm_unref(mvm, IWL_MVM_REF_ADD_IF);
-
return ret;
}
@@ -2254,6 +2033,10 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
flags = 0;
+ /* Block 26-tone RU OFDMA transmissions */
+ if (mvmvif->he_ru_2mhz_block)
+ flags |= STA_CTXT_HE_RU_2MHZ_BLOCK;
+
/* HTC flags */
if (sta->he_cap.he_cap_elem.mac_cap_info[0] &
IEEE80211_HE_MAC_CAP0_HTC_HE)
@@ -2520,7 +2303,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
iwl_mvm_sf_update(mvm, vif, false);
iwl_mvm_power_vif_assoc(mvm, vif);
if (vif->p2p) {
- iwl_mvm_ref(mvm, IWL_MVM_REF_P2P_CLIENT);
iwl_mvm_update_smps(mvm, vif,
IWL_MVM_SMPS_REQ_PROT,
IEEE80211_SMPS_DYNAMIC);
@@ -2556,9 +2338,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
IWL_ERR(mvm,
"failed to remove AP station\n");
- if (mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id)
- mvm->d0i3_ap_sta_id =
- IWL_MVM_INVALID_STA;
mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
}
@@ -2567,9 +2346,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
if (ret)
IWL_ERR(mvm, "failed to update quotas\n");
- if (vif->p2p)
- iwl_mvm_unref(mvm, IWL_MVM_REF_P2P_CLIENT);
-
/* this will take the cleared BSSID from bss_conf */
ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
if (ret)
@@ -2657,14 +2433,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret, i;
- /*
- * iwl_mvm_mac_ctxt_add() might read directly from the device
- * (the system time), so make sure it is available.
- */
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_START_AP);
- if (ret)
- return ret;
-
mutex_lock(&mvm->mutex);
/* Send the beacon template */
@@ -2760,8 +2528,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (vif->p2p && mvm->p2p_device_vif)
iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL);
- iwl_mvm_ref(mvm, IWL_MVM_REF_AP_IBSS);
-
iwl_mvm_bt_coex_vif_change(mvm);
/* we don't support TDLS during DCM */
@@ -2783,7 +2549,6 @@ out_remove:
iwl_mvm_mac_ctxt_remove(mvm, vif);
out_unlock:
mutex_unlock(&mvm->mutex);
- iwl_mvm_unref(mvm, IWL_MVM_REF_START_AP);
return ret;
}
@@ -2821,8 +2586,6 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_bt_coex_vif_change(mvm);
- iwl_mvm_unref(mvm, IWL_MVM_REF_AP_IBSS);
-
/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
if (vif->p2p && mvm->p2p_device_vif)
iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL);
@@ -2896,14 +2659,6 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- /*
- * iwl_mvm_bss_info_changed_station() might call
- * iwl_mvm_protect_session(), which reads directly from
- * the device (the system time), so make sure it is available.
- */
- if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_BSS_CHANGED))
- return;
-
mutex_lock(&mvm->mutex);
if (changes & BSS_CHANGED_IDLE && !bss_conf->idle)
@@ -2927,7 +2682,6 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
}
mutex_unlock(&mvm->mutex);
- iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED);
}
static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
@@ -3205,6 +2959,51 @@ iwl_mvm_tdls_check_trigger(struct iwl_mvm *mvm,
peer_addr, action);
}
+struct iwl_mvm_he_obss_narrow_bw_ru_data {
+ bool tolerated;
+};
+
+static void iwl_mvm_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy,
+ struct cfg80211_bss *bss,
+ void *_data)
+{
+ struct iwl_mvm_he_obss_narrow_bw_ru_data *data = _data;
+ const struct element *elem;
+
+ elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, bss->ies->data,
+ bss->ies->len);
+
+ if (!elem || elem->datalen < 10 ||
+ !(elem->data[10] &
+ WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT)) {
+ data->tolerated = false;
+ }
+}
+
+static void iwl_mvm_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm_he_obss_narrow_bw_ru_data iter_data = {
+ .tolerated = true,
+ };
+
+ if (!(vif->bss_conf.chandef.chan->flags & IEEE80211_CHAN_RADAR)) {
+ mvmvif->he_ru_2mhz_block = false;
+ return;
+ }
+
+ cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chandef,
+ iwl_mvm_check_he_obss_narrow_bw_ru_iter,
+ &iter_data);
+
+ /*
+ * If there is at least one AP on radar channel that cannot
+ * tolerate 26-tone RU UL OFDMA transmissions using HE TB PPDU.
+ */
+ mvmvif->he_ru_2mhz_block = !iter_data.tolerated;
+}
+
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -3306,6 +3105,11 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
iwl_mvm_cfg_he_sta(mvm, vif, mvm_sta->sta_id);
} else if (vif->type == NL80211_IFTYPE_STATION) {
vif->bss_conf.he_support = sta->he_cap.has_he;
+
+ mvmvif->he_ru_2mhz_block = false;
+ if (sta->he_cap.has_he)
+ iwl_mvm_check_he_obss_narrow_bw_ru(hw, vif);
+
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
}
@@ -3447,13 +3251,6 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
- /*
- * iwl_mvm_protect_session() reads directly from the device
- * (the system time), so make sure it is available.
- */
- if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX))
- return;
-
if (req_duration > duration)
duration = req_duration;
@@ -3461,8 +3258,6 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
/* Try really hard to protect the session and hear a beacon */
iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500, false);
mutex_unlock(&mvm->mutex);
-
- iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX);
}
static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
@@ -3537,7 +3332,7 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
switch (key->cipher) {
case WLAN_CIPHER_SUITE_TKIP:
- if (!mvm->trans->cfg->gen2) {
+ if (!mvm->trans->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) {
@@ -4045,7 +3840,8 @@ out_unlock:
return ret;
}
-static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw)
+static int iwl_mvm_cancel_roc(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
@@ -4277,23 +4073,12 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
u32 duration = 3 * vif->bss_conf.beacon_int;
-
- /* iwl_mvm_protect_session() reads directly from the
- * device (the system time), so make sure it is
- * available.
- */
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
- if (ret)
- goto out_remove_binding;
-
/* Protect the session to make sure we hear the first
* beacon on the new channel.
*/
iwl_mvm_protect_session(mvm, vif, duration, duration,
vif->bss_conf.beacon_int / 2,
true);
-
- iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
}
iwl_mvm_update_quotas(mvm, false, NULL);
@@ -4643,6 +4428,42 @@ static int iwl_mvm_schedule_client_csa(struct iwl_mvm *mvm,
0, sizeof(cmd), &cmd);
}
+static int iwl_mvm_old_pre_chan_sw_sta(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel_switch *chsw)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ u32 apply_time;
+
+ /* Schedule the time event to a bit before beacon 1,
+ * to make sure we're in the new channel when the
+ * GO/AP arrives. In case count <= 1 immediately schedule the
+ * TE (this might result with some packet loss or connection
+ * loss).
+ */
+ if (chsw->count <= 1)
+ apply_time = 0;
+ else
+ apply_time = chsw->device_timestamp +
+ ((vif->bss_conf.beacon_int * (chsw->count - 1) -
+ IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
+
+ if (chsw->block_tx)
+ iwl_mvm_csa_client_absent(mvm, vif);
+
+ if (mvmvif->bf_data.bf_enabled) {
+ int ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
+
+ if (ret)
+ return ret;
+ }
+
+ iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int,
+ apply_time);
+
+ return 0;
+}
+
#define IWL_MAX_CSA_BLOCK_TX 1500
static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -4651,7 +4472,6 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct ieee80211_vif *csa_vif;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u32 apply_time;
int ret;
mutex_lock(&mvm->mutex);
@@ -4695,21 +4515,7 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
break;
case NL80211_IFTYPE_STATION:
- /* Schedule the time event to a bit before beacon 1,
- * to make sure we're in the new channel when the
- * GO/AP arrives. In case count <= 1 immediately schedule the
- * TE (this might result with some packet loss or connection
- * loss).
- */
- if (chsw->count <= 1)
- apply_time = 0;
- else
- apply_time = chsw->device_timestamp +
- ((vif->bss_conf.beacon_int * (chsw->count - 1) -
- IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
-
if (chsw->block_tx) {
- iwl_mvm_csa_client_absent(mvm, vif);
/*
* In case of undetermined / long time with immediate
* quiet monitor status to gracefully disconnect
@@ -4721,19 +4527,14 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
msecs_to_jiffies(IWL_MAX_CSA_BLOCK_TX));
}
- if (mvmvif->bf_data.bf_enabled) {
- ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
+ if (!fw_has_capa(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD)) {
+ ret = iwl_mvm_old_pre_chan_sw_sta(mvm, vif, chsw);
if (ret)
goto out_unlock;
- }
-
- if (fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD))
+ } else {
iwl_mvm_schedule_client_csa(mvm, vif, chsw);
- else
- iwl_mvm_schedule_csa_period(mvm, vif,
- vif->bss_conf.beacon_int,
- apply_time);
+ }
mvmvif->csa_count = chsw->count;
mvmvif->csa_misbehave = false;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index a263cc629d75..843d00bf2bd5 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -258,38 +258,6 @@ enum iwl_mvm_smps_type_request {
NUM_IWL_MVM_SMPS_REQ,
};
-enum iwl_mvm_ref_type {
- IWL_MVM_REF_UCODE_DOWN,
- IWL_MVM_REF_SCAN,
- IWL_MVM_REF_ROC,
- IWL_MVM_REF_ROC_AUX,
- IWL_MVM_REF_P2P_CLIENT,
- IWL_MVM_REF_AP_IBSS,
- IWL_MVM_REF_USER,
- IWL_MVM_REF_TX,
- IWL_MVM_REF_TX_AGG,
- IWL_MVM_REF_ADD_IF,
- IWL_MVM_REF_START_AP,
- IWL_MVM_REF_BSS_CHANGED,
- IWL_MVM_REF_PREPARE_TX,
- IWL_MVM_REF_PROTECT_TDLS,
- IWL_MVM_REF_CHECK_CTKILL,
- IWL_MVM_REF_PRPH_READ,
- IWL_MVM_REF_PRPH_WRITE,
- IWL_MVM_REF_NMI,
- IWL_MVM_REF_TM_CMD,
- IWL_MVM_REF_EXIT_WORK,
- IWL_MVM_REF_PROTECT_CSA,
- IWL_MVM_REF_FW_DBG_COLLECT,
- IWL_MVM_REF_INIT_UCODE,
- IWL_MVM_REF_SENDING_CMD,
- IWL_MVM_REF_RX,
-
- /* update debugfs.c when changing this */
-
- IWL_MVM_REF_COUNT,
-};
-
enum iwl_bt_force_ant_mode {
BT_FORCE_ANT_DIS = 0,
BT_FORCE_ANT_AUTO,
@@ -504,6 +472,9 @@ struct iwl_mvm_vif {
/* we can only have 2 GTK + 2 IGTK active at a time */
struct ieee80211_key_conf *ap_early_keys[4];
+
+ /* 26-tone RU OFDMA transmissions should be blocked */
+ bool he_ru_2mhz_block;
};
static inline struct iwl_mvm_vif *
@@ -617,11 +588,6 @@ struct iwl_mvm_frame_stats {
int last_frame_idx;
};
-enum {
- D0I3_DEFER_WAKEUP,
- D0I3_PENDING_WAKEUP,
-};
-
#define IWL_MVM_DEBUG_SET_TEMPERATURE_DISABLE 0xff
#define IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -100
#define IWL_MVM_DEBUG_SET_TEMPERATURE_MAX 200
@@ -695,6 +661,12 @@ struct iwl_mvm_tcm {
* @valid: reordering is valid for this queue
* @lock: protect reorder buffer internal state
* @mvm: mvm pointer, needed for frame timer context
+ * @consec_oldsn_drops: consecutive drops due to old SN
+ * @consec_oldsn_ampdu_gp2: A-MPDU GP2 timestamp to track
+ * when to apply old SN consecutive drop workaround
+ * @consec_oldsn_prev_drop: track whether or not an MPDU
+ * that was single/part of the previous A-MPDU was
+ * dropped due to old SN
*/
struct iwl_mvm_reorder_buffer {
u16 head_sn;
@@ -708,6 +680,9 @@ struct iwl_mvm_reorder_buffer {
bool valid;
spinlock_t lock;
struct iwl_mvm *mvm;
+ unsigned int consec_oldsn_drops;
+ u32 consec_oldsn_ampdu_gp2;
+ unsigned int consec_oldsn_prev_drop:1;
} ____cacheline_aligned_in_smp;
/**
@@ -1011,10 +986,6 @@ struct iwl_mvm {
unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
u8 fw_key_deleted[STA_KEY_MAX_NUM];
- /* references taken by the driver and spinlock protecting them */
- spinlock_t refs_lock;
- u8 refs[IWL_MVM_REF_COUNT];
-
u8 vif_count;
struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER];
@@ -1039,6 +1010,7 @@ struct iwl_mvm {
struct ieee80211_channel **nd_channels;
int n_nd_channels;
bool net_detect;
+ u8 offload_tid;
#ifdef CONFIG_IWLWIFI_DEBUGFS
bool d3_wake_sysassert;
bool d3_test_active;
@@ -1048,17 +1020,6 @@ struct iwl_mvm {
#endif
#endif
- /* d0i3 */
- u8 d0i3_ap_sta_id;
- bool d0i3_offloading;
- struct work_struct d0i3_exit_work;
- struct sk_buff_head d0i3_tx;
- /* protect d0i3_suspend_flags */
- struct mutex d0i3_suspend_mutex;
- unsigned long d0i3_suspend_flags;
- /* sync d0i3_tx queue and IWL_MVM_STATUS_IN_D0I3 status flag */
- spinlock_t d0i3_tx_lock;
- wait_queue_head_t d0i3_exit_waitq;
wait_queue_head_t rx_sync_waitq;
/* BT-Coex */
@@ -1184,6 +1145,8 @@ struct iwl_mvm {
struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
u32 geo_rev;
+ struct iwl_ppag_table_cmd ppag_table;
+ u32 ppag_rev;
#endif
};
@@ -1201,7 +1164,6 @@ struct iwl_mvm {
* @IWL_MVM_STATUS_ROC_RUNNING: remain-on-channel is running
* @IWL_MVM_STATUS_HW_RESTART_REQUESTED: HW restart was requested
* @IWL_MVM_STATUS_IN_HW_RESTART: HW restart is active
- * @IWL_MVM_STATUS_IN_D0I3: NIC is in D0i3
* @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running
* @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
* @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA
@@ -1212,7 +1174,6 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_ROC_RUNNING,
IWL_MVM_STATUS_HW_RESTART_REQUESTED,
IWL_MVM_STATUS_IN_HW_RESTART,
- IWL_MVM_STATUS_IN_D0I3,
IWL_MVM_STATUS_ROC_AUX_RUNNING,
IWL_MVM_STATUS_FIRMWARE_RUNNING,
IWL_MVM_STATUS_NEED_FLUSH_P2P,
@@ -1291,13 +1252,6 @@ iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu)
lockdep_is_held(&mvm->mutex));
}
-static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm)
-{
- return !iwlwifi_mod_params.d0i3_disable &&
- fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_D0I3_SUPPORT);
-}
-
static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm)
{
return fw_has_api(&mvm->fw->ucode_capa,
@@ -1333,19 +1287,6 @@ static inline bool iwl_mvm_is_short_beacon_notif_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_API_SHORT_BEACON_NOTIF);
}
-static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm)
-{
- /* For now we only use this mode to differentiate between
- * slave transports, which handle D0i3 entry in suspend by
- * themselves in conjunction with runtime PM D0i3. So, this
- * function is used to check whether we need to do anything
- * when entering suspend or if the transport layer has already
- * done it.
- */
- return (mvm->trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3) &&
- (mvm->trans->runtime_pm_mode != IWL_PLAT_PM_MODE_D0I3);
-}
-
static inline bool iwl_mvm_is_dqa_data_queue(struct iwl_mvm *mvm, u8 queue)
{
return (queue >= IWL_MVM_DQA_MIN_DATA_QUEUE) &&
@@ -1424,13 +1365,13 @@ static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm)
static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm)
{
/* TODO - replace with TLV once defined */
- return mvm->trans->cfg->use_tfh;
+ return mvm->trans->trans_cfg->use_tfh;
}
static inline bool iwl_mvm_has_unified_ucode(struct iwl_mvm *mvm)
{
/* TODO - better define this */
- return mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000;
+ return mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000;
}
static inline bool iwl_mvm_is_cdb_supported(struct iwl_mvm *mvm)
@@ -1455,7 +1396,13 @@ static inline bool iwl_mvm_cdb_scan_api(struct iwl_mvm *mvm)
* but then there's a little bit of code in scan that won't make
* any sense...
*/
- return mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000;
+ return mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000;
+}
+
+static inline bool iwl_mvm_is_scan_ext_chan_supported(struct iwl_mvm *mvm)
+{
+ return fw_has_api(&mvm->fw->ucode_capa,
+ IWL_UCODE_TLV_API_SCAN_EXT_CHAN_VER);
}
static inline bool iwl_mvm_has_new_rx_stats_api(struct iwl_mvm *mvm)
@@ -1487,7 +1434,6 @@ iwl_mvm_get_agg_status(struct iwl_mvm *mvm, void *tx_resp)
static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm)
{
-#ifdef CONFIG_THERMAL
/* these two TLV are redundant since the responsibility to CT-kill by
* FW happens only after we send at least one command of
* temperature THs report.
@@ -1496,9 +1442,6 @@ static inline bool iwl_mvm_is_tt_in_fw(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_CT_KILL_BY_FW) &&
fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_TEMP_THS_REPORT_SUPPORT);
-#else /* CONFIG_THERMAL */
- return false;
-#endif /* CONFIG_THERMAL */
}
static inline bool iwl_mvm_is_ctdp_supported(struct iwl_mvm *mvm)
@@ -1663,6 +1606,8 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
+void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb, int queue);
int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
const u8 *data, u32 count, bool async);
void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
@@ -1863,30 +1808,9 @@ void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw,
extern const struct file_operations iwl_dbgfs_d3_test_ops;
struct iwl_wowlan_status *iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm);
#ifdef CONFIG_PM
-int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- bool host_awake,
- u32 cmd_flags);
-void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct iwl_wowlan_status *status);
void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
#else
-static inline int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- bool host_awake,
- u32 cmd_flags)
-{
- return 0;
-}
-
-static inline void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct iwl_wowlan_status *status)
-{
-}
-
static inline void
iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
@@ -1900,19 +1824,6 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
bool offload_ns,
u32 cmd_flags);
-/* D0i3 */
-void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
-void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
-int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
-bool iwl_mvm_ref_taken(struct iwl_mvm *mvm);
-
-#ifdef CONFIG_PM
-void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
-int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode);
-int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode);
-int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
-#endif
-
/* BT Coex */
int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm);
void iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
@@ -1943,9 +1854,6 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
struct iwl_beacon_filter_cmd *cmd)
{}
#endif
-int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- bool enable, u32 flags);
int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 flags);
@@ -2025,7 +1933,7 @@ void iwl_mvm_vif_set_low_latency(struct iwl_mvm_vif *mvmvif, bool set,
*/
static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
{
- return ((BIT(mvm->cfg->base_params->num_of_queues) - 1) &
+ return ((BIT(mvm->trans->trans_cfg->base_params->num_of_queues) - 1) &
~BIT(IWL_MVM_DQA_CMD_QUEUE));
}
@@ -2034,7 +1942,8 @@ static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
iwl_fw_cancel_timestamp(&mvm->fwrt);
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
- iwl_fwrt_stop_device(&mvm->fwrt);
+ iwl_fw_dbg_stop_sync(&mvm->fwrt);
+ iwl_trans_stop_device(mvm->trans);
iwl_free_fw_paging(&mvm->fwrt);
iwl_fw_dump_conf_clear(&mvm->fwrt);
}
@@ -2154,6 +2063,7 @@ void iwl_mvm_event_frame_timeout_callback(struct iwl_mvm *mvm,
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b);
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm);
+int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm);
#ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_mvm_sta_add_debugfs(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
index a9bb43a2f27b..945c1ea5cda8 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
@@ -249,7 +249,7 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
while (ret == length) {
/* Check no memory assumptions fail and cause an overflow */
if ((size_read + offset + length) >
- mvm->cfg->base_params->eeprom_size) {
+ mvm->trans->trans_cfg->base_params->eeprom_size) {
IWL_ERR(mvm, "EEPROM size is too small for NVM\n");
return -ENOBUFS;
}
@@ -372,7 +372,7 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
/* Read From FW NVM */
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
- nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
+ nvm_buffer = kmalloc(mvm->trans->trans_cfg->base_params->eeprom_size,
GFP_KERNEL);
if (!nvm_buffer)
return -ENOMEM;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index 4888054dc3d8..3acbd5b7ab4b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -173,7 +173,7 @@ static void iwl_mvm_nic_config(struct iwl_op_mode *op_mode)
* unrelated errors. Need to further investigate this, but for now
* we'll separate cases.
*/
- if (mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_8000)
+ if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_8000)
reg_val |= CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI;
if (iwl_fw_dbg_is_d3_debug_enabled(&mvm->fwrt))
@@ -389,6 +389,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC),
HCMD_NAME(REPLY_RX_PHY_CMD),
HCMD_NAME(REPLY_RX_MPDU_CMD),
+ HCMD_NAME(BAR_FRAME_RELEASE),
HCMD_NAME(FRAME_RELEASE),
HCMD_NAME(BA_NOTIF),
HCMD_NAME(MCC_UPDATE_CMD),
@@ -414,6 +415,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(SCAN_ITERATION_COMPLETE),
HCMD_NAME(D0I3_END_CMD),
HCMD_NAME(LTR_CONFIG),
+ HCMD_NAME(LDBG_CONFIG_CMD),
};
/* Please keep this array *SORTED* by hex value.
@@ -465,6 +467,8 @@ static const struct iwl_hcmd_names iwl_mvm_data_path_names[] = {
* Access is done through binary search
*/
static const struct iwl_hcmd_names iwl_mvm_debug_names[] = {
+ HCMD_NAME(DBGC_SUSPEND_RESUME),
+ HCMD_NAME(BUFFER_ALLOCATION),
HCMD_NAME(MFU_ASSERT_DUMP_NTF),
};
@@ -514,9 +518,6 @@ static const struct iwl_hcmd_arr iwl_mvm_groups[] = {
/* this forward declaration can avoid to export the function */
static void iwl_mvm_async_handlers_wk(struct work_struct *wk);
-#ifdef CONFIG_PM
-static void iwl_mvm_d0i3_exit_work(struct work_struct *wk);
-#endif
static u32 iwl_mvm_min_backoff(struct iwl_mvm *mvm)
{
@@ -564,23 +565,16 @@ unlock:
static int iwl_mvm_fwrt_dump_start(void *ctx)
{
struct iwl_mvm *mvm = ctx;
- int ret = 0;
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
- if (ret)
- mutex_unlock(&mvm->mutex);
-
- return ret;
+ return 0;
}
static void iwl_mvm_fwrt_dump_end(void *ctx)
{
struct iwl_mvm *mvm = ctx;
- iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
-
mutex_unlock(&mvm->mutex);
}
@@ -672,7 +666,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (iwl_mvm_has_new_rx_api(mvm)) {
op_mode->ops = &iwl_mvm_ops_mq;
trans->rx_mpdu_cmd_hdr_size =
- (trans->cfg->device_family >=
+ (trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560) ?
sizeof(struct iwl_rx_mpdu_desc) :
IWL_RX_DESC_SIZE_V1;
@@ -700,7 +694,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mvm->drop_bcn_ap_mode = true;
mutex_init(&mvm->mutex);
- mutex_init(&mvm->d0i3_suspend_mutex);
spin_lock_init(&mvm->async_handlers_lock);
INIT_LIST_HEAD(&mvm->time_event_list);
INIT_LIST_HEAD(&mvm->aux_roc_te_list);
@@ -710,18 +703,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk);
INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk);
-#ifdef CONFIG_PM
- INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
-#endif
INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work);
INIT_DELAYED_WORK(&mvm->scan_timeout_dwork, iwl_mvm_scan_timeout_wk);
INIT_WORK(&mvm->add_stream_wk, iwl_mvm_add_new_dqa_stream_wk);
INIT_LIST_HEAD(&mvm->add_stream_txqs);
- spin_lock_init(&mvm->d0i3_tx_lock);
- spin_lock_init(&mvm->refs_lock);
- skb_queue_head_init(&mvm->d0i3_tx);
- init_waitqueue_head(&mvm->d0i3_exit_waitq);
init_waitqueue_head(&mvm->rx_sync_waitq);
atomic_set(&mvm->queue_sync_counter, 0);
@@ -744,7 +730,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
- if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+ if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
rb_size_default = IWL_AMSDU_2K;
else
rb_size_default = IWL_AMSDU_4K;
@@ -768,12 +754,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
trans_cfg.rx_buf_size = rb_size_default;
}
- BUILD_BUG_ON(sizeof(struct iwl_ldbg_config_cmd) !=
- LDBG_CFG_COMMAND_SIZE);
-
trans->wide_cmd_header = true;
trans_cfg.bc_table_dword =
- mvm->trans->cfg->device_family < IWL_DEVICE_FAMILY_22560;
+ mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22560;
trans_cfg.command_groups = iwl_mvm_groups;
trans_cfg.command_groups_size = ARRAY_SIZE(iwl_mvm_groups);
@@ -832,13 +815,11 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
goto out_free;
mutex_lock(&mvm->mutex);
- iwl_mvm_ref(mvm, IWL_MVM_REF_INIT_UCODE);
err = iwl_run_init_mvm_ucode(mvm, true);
if (err && err != -ERFKILL)
iwl_fw_dbg_error_collect(&mvm->fwrt, FW_DBG_TRIGGER_DRIVER);
if (!iwlmvm_mod_params.init_dbg || !err)
iwl_mvm_stop_device(mvm);
- iwl_mvm_unref(mvm, IWL_MVM_REF_INIT_UCODE);
mutex_unlock(&mvm->mutex);
if (err < 0) {
IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", err);
@@ -870,11 +851,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
else
memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
- /* The transport always starts with a taken reference, we can
- * release it now if d0i3 is supported */
- if (iwl_mvm_is_d0i3_supported(mvm))
- iwl_trans_unref(mvm->trans);
-
iwl_mvm_toggle_tx_ant(mvm, &mvm->mgmt_last_antenna_idx);
return op_mode;
@@ -898,13 +874,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
int i;
- /* If d0i3 is supported, we have released the reference that
- * the transport started with, so we should take it back now
- * that we are leaving.
- */
- if (iwl_mvm_is_d0i3_supported(mvm))
- iwl_trans_ref(mvm->trans);
-
iwl_mvm_leds_exit(mvm);
iwl_mvm_thermal_exit(mvm);
@@ -931,7 +900,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
iwl_fw_runtime_free(&mvm->fwrt);
mutex_destroy(&mvm->mutex);
- mutex_destroy(&mvm->d0i3_suspend_mutex);
ieee80211_free_hw(mvm->hw);
}
@@ -1020,7 +988,10 @@ static void iwl_mvm_rx_common(struct iwl_mvm *mvm,
struct iwl_rx_packet *pkt)
{
int i;
+ union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt };
+ iwl_dbg_tlv_time_point(&mvm->fwrt,
+ IWL_FW_INI_TIME_POINT_FW_RSP_OR_NOTIF, &tp_data);
iwl_mvm_rx_check_trigger(mvm, pkt);
/*
@@ -1091,6 +1062,8 @@ static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode,
iwl_mvm_rx_queue_notif(mvm, napi, rxb, 0);
else if (cmd == WIDE_ID(LEGACY_GROUP, FRAME_RELEASE))
iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
+ else if (cmd == WIDE_ID(LEGACY_GROUP, BAR_FRAME_RELEASE))
+ iwl_mvm_rx_bar_frame_release(mvm, napi, rxb, 0);
else if (cmd == WIDE_ID(DATA_PATH_GROUP, RX_NO_DATA_NOTIF))
iwl_mvm_rx_monitor_no_data(mvm, napi, rxb, 0);
else
@@ -1234,8 +1207,7 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
* Stop the device if we run OPERATIONAL firmware or if we are in the
* middle of the calibrations.
*/
- return state && (mvm->fwrt.cur_fw_img != IWL_UCODE_INIT ||
- rfkill_safe_init_done);
+ return state && rfkill_safe_init_done;
}
static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
@@ -1267,7 +1239,7 @@ static void iwl_mvm_reprobe_wk(struct work_struct *wk)
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
{
iwl_abort_notification_waits(&mvm->notif_wait);
- del_timer(&mvm->fwrt.dump.periodic_trig);
+ iwl_dbg_tlv_del_timers(mvm->trans);
/*
* This is a bit racy, but worst case we tell mac80211 about
@@ -1319,9 +1291,6 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error)
} else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR &&
mvm->hw_registered &&
!test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) {
- /* don't let the transport/FW power down */
- iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
-
if (mvm->fw->ucode_capa.error_log_size) {
u32 src_size = mvm->fw->ucode_capa.error_log_size;
u32 src_addr = mvm->fw->ucode_capa.error_log_addr;
@@ -1363,422 +1332,6 @@ static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
iwl_mvm_nic_restart(mvm, true);
}
-#ifdef CONFIG_PM
-struct iwl_d0i3_iter_data {
- struct iwl_mvm *mvm;
- struct ieee80211_vif *connected_vif;
- u8 ap_sta_id;
- u8 vif_count;
- u8 offloading_tid;
- bool disable_offloading;
-};
-
-static bool iwl_mvm_disallow_offloading(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct iwl_d0i3_iter_data *iter_data)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_sta *mvmsta;
- u32 available_tids = 0;
- u8 tid;
-
- if (WARN_ON(vif->type != NL80211_IFTYPE_STATION ||
- mvmvif->ap_sta_id == IWL_MVM_INVALID_STA))
- return false;
-
- mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id);
- if (!mvmsta)
- return false;
-
- spin_lock_bh(&mvmsta->lock);
- for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
- struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
-
- /*
- * in case of pending tx packets, don't use this tid
- * for offloading in order to prevent reuse of the same
- * qos seq counters.
- */
- if (iwl_mvm_tid_queued(mvm, tid_data))
- continue;
-
- if (tid_data->state != IWL_AGG_OFF)
- continue;
-
- available_tids |= BIT(tid);
- }
- spin_unlock_bh(&mvmsta->lock);
-
- /*
- * disallow protocol offloading if we have no available tid
- * (with no pending frames and no active aggregation,
- * as we don't handle "holes" properly - the scheduler needs the
- * frame's seq number and TFD index to match)
- */
- if (!available_tids)
- return true;
-
- /* for simplicity, just use the first available tid */
- iter_data->offloading_tid = ffs(available_tids) - 1;
- return false;
-}
-
-static void iwl_mvm_enter_d0i3_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_d0i3_iter_data *data = _data;
- struct iwl_mvm *mvm = data->mvm;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE;
-
- IWL_DEBUG_RPM(mvm, "entering D0i3 - vif %pM\n", vif->addr);
- if (vif->type != NL80211_IFTYPE_STATION ||
- !vif->bss_conf.assoc)
- return;
-
- /*
- * in case of pending tx packets or active aggregations,
- * avoid offloading features in order to prevent reuse of
- * the same qos seq counters.
- */
- if (iwl_mvm_disallow_offloading(mvm, vif, data))
- data->disable_offloading = true;
-
- iwl_mvm_update_d0i3_power_mode(mvm, vif, true, flags);
- iwl_mvm_send_proto_offload(mvm, vif, data->disable_offloading,
- false, flags);
-
- /*
- * on init/association, mvm already configures POWER_TABLE_CMD
- * and REPLY_MCAST_FILTER_CMD, so currently don't
- * reconfigure them (we might want to use different
- * params later on, though).
- */
- data->ap_sta_id = mvmvif->ap_sta_id;
- data->vif_count++;
-
- /*
- * no new commands can be sent at this stage, so it's safe
- * to save the vif pointer during d0i3 entrance.
- */
- data->connected_vif = vif;
-}
-
-static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
- struct iwl_wowlan_config_cmd *cmd,
- struct iwl_d0i3_iter_data *iter_data)
-{
- struct ieee80211_sta *ap_sta;
- struct iwl_mvm_sta *mvm_ap_sta;
-
- if (iter_data->ap_sta_id == IWL_MVM_INVALID_STA)
- return;
-
- rcu_read_lock();
-
- ap_sta = rcu_dereference(mvm->fw_id_to_mac_id[iter_data->ap_sta_id]);
- if (IS_ERR_OR_NULL(ap_sta))
- goto out;
-
- mvm_ap_sta = iwl_mvm_sta_from_mac80211(ap_sta);
- cmd->is_11n_connection = ap_sta->ht_cap.ht_supported;
- cmd->offloading_tid = iter_data->offloading_tid;
- cmd->flags = ENABLE_L3_FILTERING | ENABLE_NBNS_FILTERING |
- ENABLE_DHCP_FILTERING | ENABLE_STORE_BEACON;
- /*
- * The d0i3 uCode takes care of the nonqos counters,
- * so configure only the qos seq ones.
- */
- iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, cmd);
-out:
- rcu_read_unlock();
-}
-
-int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode)
-{
- struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
- u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE;
- int ret;
- struct iwl_d0i3_iter_data d0i3_iter_data = {
- .mvm = mvm,
- };
- struct iwl_wowlan_config_cmd wowlan_config_cmd = {
- .wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME |
- IWL_WOWLAN_WAKEUP_BEACON_MISS |
- IWL_WOWLAN_WAKEUP_LINK_CHANGE),
- };
- struct iwl_d3_manager_config d3_cfg_cmd = {
- .min_sleep_time = cpu_to_le32(1000),
- .wakeup_flags = cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR),
- };
-
- IWL_DEBUG_RPM(mvm, "MVM entering D0i3\n");
-
- if (WARN_ON_ONCE(mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR))
- return -EINVAL;
-
- set_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
-
- /*
- * iwl_mvm_ref_sync takes a reference before checking the flag.
- * so by checking there is no held reference we prevent a state
- * in which iwl_mvm_ref_sync continues successfully while we
- * configure the firmware to enter d0i3
- */
- if (iwl_mvm_ref_taken(mvm)) {
- IWL_DEBUG_RPM(mvm->trans, "abort d0i3 due to taken ref\n");
- clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
- wake_up(&mvm->d0i3_exit_waitq);
- return 1;
- }
-
- ieee80211_iterate_active_interfaces_atomic(mvm->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_enter_d0i3_iterator,
- &d0i3_iter_data);
- if (d0i3_iter_data.vif_count == 1) {
- mvm->d0i3_ap_sta_id = d0i3_iter_data.ap_sta_id;
- mvm->d0i3_offloading = !d0i3_iter_data.disable_offloading;
- } else {
- WARN_ON_ONCE(d0i3_iter_data.vif_count > 1);
- mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
- mvm->d0i3_offloading = false;
- }
-
- iwl_mvm_pause_tcm(mvm, true);
- /* make sure we have no running tx while configuring the seqno */
- synchronize_net();
-
- /* Flush the hw queues, in case something got queued during entry */
- /* TODO new tx api */
- if (iwl_mvm_has_new_tx_api(mvm)) {
- WARN_ONCE(1, "d0i3: Need to implement flush TX queue\n");
- } else {
- ret = iwl_mvm_flush_tx_path(mvm, iwl_mvm_flushable_queues(mvm),
- flags);
- if (ret)
- return ret;
- }
-
- /* configure wowlan configuration only if needed */
- if (mvm->d0i3_ap_sta_id != IWL_MVM_INVALID_STA) {
- /* wake on beacons only if beacon storing isn't supported */
- if (!fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_BEACON_STORING))
- wowlan_config_cmd.wakeup_filter |=
- cpu_to_le32(IWL_WOWLAN_WAKEUP_BCN_FILTERING);
-
- iwl_mvm_wowlan_config_key_params(mvm,
- d0i3_iter_data.connected_vif,
- true, flags);
-
- iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd,
- &d0i3_iter_data);
-
- ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags,
- sizeof(wowlan_config_cmd),
- &wowlan_config_cmd);
- if (ret)
- return ret;
- }
-
- return iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD,
- flags | CMD_MAKE_TRANS_IDLE,
- sizeof(d3_cfg_cmd), &d3_cfg_cmd);
-}
-
-static void iwl_mvm_exit_d0i3_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm *mvm = _data;
- u32 flags = CMD_ASYNC | CMD_HIGH_PRIO;
-
- IWL_DEBUG_RPM(mvm, "exiting D0i3 - vif %pM\n", vif->addr);
- if (vif->type != NL80211_IFTYPE_STATION ||
- !vif->bss_conf.assoc)
- return;
-
- iwl_mvm_update_d0i3_power_mode(mvm, vif, false, flags);
-}
-
-struct iwl_mvm_d0i3_exit_work_iter_data {
- struct iwl_mvm *mvm;
- struct iwl_wowlan_status *status;
- u32 wakeup_reasons;
-};
-
-static void iwl_mvm_d0i3_exit_work_iter(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_d0i3_exit_work_iter_data *data = _data;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u32 reasons = data->wakeup_reasons;
-
- /* consider only the relevant station interface */
- if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc ||
- data->mvm->d0i3_ap_sta_id != mvmvif->ap_sta_id)
- return;
-
- if (reasons & IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)
- iwl_mvm_connection_loss(data->mvm, vif, "D0i3");
- else if (reasons & IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON)
- ieee80211_beacon_loss(vif);
- else
- iwl_mvm_d0i3_update_keys(data->mvm, vif, data->status);
-}
-
-void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq)
-{
- struct ieee80211_sta *sta = NULL;
- struct iwl_mvm_sta *mvm_ap_sta;
- int i;
- bool wake_queues = false;
-
- lockdep_assert_held(&mvm->mutex);
-
- spin_lock_bh(&mvm->d0i3_tx_lock);
-
- if (mvm->d0i3_ap_sta_id == IWL_MVM_INVALID_STA)
- goto out;
-
- IWL_DEBUG_RPM(mvm, "re-enqueue packets\n");
-
- /* get the sta in order to update seq numbers and re-enqueue skbs */
- sta = rcu_dereference_protected(
- mvm->fw_id_to_mac_id[mvm->d0i3_ap_sta_id],
- lockdep_is_held(&mvm->mutex));
-
- if (IS_ERR_OR_NULL(sta)) {
- sta = NULL;
- goto out;
- }
-
- if (mvm->d0i3_offloading && qos_seq) {
- /* update qos seq numbers if offloading was enabled */
- mvm_ap_sta = iwl_mvm_sta_from_mac80211(sta);
- for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
- u16 seq = le16_to_cpu(qos_seq[i]);
- /* firmware stores last-used one, we store next one */
- seq += 0x10;
- mvm_ap_sta->tid_data[i].seq_number = seq;
- }
- }
-out:
- /* re-enqueue (or drop) all packets */
- while (!skb_queue_empty(&mvm->d0i3_tx)) {
- struct sk_buff *skb = __skb_dequeue(&mvm->d0i3_tx);
-
- if (!sta || iwl_mvm_tx_skb(mvm, skb, sta))
- ieee80211_free_txskb(mvm->hw, skb);
-
- /* if the skb_queue is not empty, we need to wake queues */
- wake_queues = true;
- }
- clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
- wake_up(&mvm->d0i3_exit_waitq);
- mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
- if (wake_queues)
- ieee80211_wake_queues(mvm->hw);
-
- spin_unlock_bh(&mvm->d0i3_tx_lock);
-}
-
-static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
-{
- struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, d0i3_exit_work);
- struct iwl_mvm_d0i3_exit_work_iter_data iter_data = {
- .mvm = mvm,
- };
-
- struct iwl_wowlan_status *status;
- u32 wakeup_reasons = 0;
- __le16 *qos_seq = NULL;
-
- mutex_lock(&mvm->mutex);
-
- status = iwl_mvm_send_wowlan_get_status(mvm);
- if (IS_ERR_OR_NULL(status)) {
- /* set to NULL so we don't need to check before kfree'ing */
- status = NULL;
- goto out;
- }
-
- wakeup_reasons = le32_to_cpu(status->wakeup_reasons);
- qos_seq = status->qos_seq_ctr;
-
- IWL_DEBUG_RPM(mvm, "wakeup reasons: 0x%x\n", wakeup_reasons);
-
- iter_data.wakeup_reasons = wakeup_reasons;
- iter_data.status = status;
- ieee80211_iterate_active_interfaces(mvm->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_d0i3_exit_work_iter,
- &iter_data);
-out:
- iwl_mvm_d0i3_enable_tx(mvm, qos_seq);
-
- IWL_DEBUG_INFO(mvm, "d0i3 exit completed (wakeup reasons: 0x%x)\n",
- wakeup_reasons);
-
- /* qos_seq might point inside resp_pkt, so free it only now */
- kfree(status);
-
- /* the FW might have updated the regdomain */
- iwl_mvm_update_changed_regdom(mvm);
-
- iwl_mvm_resume_tcm(mvm);
- iwl_mvm_unref(mvm, IWL_MVM_REF_EXIT_WORK);
- mutex_unlock(&mvm->mutex);
-}
-
-int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm)
-{
- u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE |
- CMD_WAKE_UP_TRANS;
- int ret;
-
- IWL_DEBUG_RPM(mvm, "MVM exiting D0i3\n");
-
- if (WARN_ON_ONCE(mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR))
- return -EINVAL;
-
- mutex_lock(&mvm->d0i3_suspend_mutex);
- if (test_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags)) {
- IWL_DEBUG_RPM(mvm, "Deferring d0i3 exit until resume\n");
- __set_bit(D0I3_PENDING_WAKEUP, &mvm->d0i3_suspend_flags);
- mutex_unlock(&mvm->d0i3_suspend_mutex);
- return 0;
- }
- mutex_unlock(&mvm->d0i3_suspend_mutex);
-
- ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL);
- if (ret)
- goto out;
-
- ieee80211_iterate_active_interfaces_atomic(mvm->hw,
- IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_exit_d0i3_iterator,
- mvm);
-out:
- schedule_work(&mvm->d0i3_exit_work);
- return ret;
-}
-
-int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
-{
- struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
-
- iwl_mvm_ref(mvm, IWL_MVM_REF_EXIT_WORK);
- return _iwl_mvm_exit_d0i3(mvm);
-}
-
-#define IWL_MVM_D0I3_OPS \
- .enter_d0i3 = iwl_mvm_enter_d0i3, \
- .exit_d0i3 = iwl_mvm_exit_d0i3,
-#else /* CONFIG_PM */
-#define IWL_MVM_D0I3_OPS
-#endif /* CONFIG_PM */
-
#define IWL_MVM_COMMON_OPS \
/* these could be differentiated */ \
.async_cb = iwl_mvm_async_cb, \
@@ -1789,7 +1342,6 @@ int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode)
.nic_error = iwl_mvm_nic_error, \
.cmd_queue_full = iwl_mvm_cmd_queue_full, \
.nic_config = iwl_mvm_nic_config, \
- IWL_MVM_D0I3_OPS \
/* as we only register one, these MUST be common! */ \
.start = iwl_op_mode_mvm_start, \
.stop = iwl_op_mode_mvm_stop
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
index 86e40bae57e3..0243dbe8ac49 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c
@@ -289,8 +289,17 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt)
if (ctxt->ref == 0) {
struct ieee80211_channel *chan;
struct cfg80211_chan_def chandef;
+ struct ieee80211_supported_band *sband = NULL;
+ enum nl80211_band band = NL80211_BAND_2GHZ;
+
+ while (!sband && band < NUM_NL80211_BANDS)
+ sband = mvm->hw->wiphy->bands[band++];
+
+ if (WARN_ON(!sband))
+ return;
+
+ chan = &sband->channels[0];
- chan = &mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[0];
cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT);
iwl_mvm_phy_ctxt_changed(mvm, ctxt, &chandef, 1, 1);
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/power.c b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
index 36f5fa1ee793..22136e4832ea 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -127,12 +127,11 @@ int iwl_mvm_beacon_filter_send_cmd(struct iwl_mvm *mvm,
static
void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- struct iwl_beacon_filter_cmd *cmd,
- bool d0i3)
+ struct iwl_beacon_filter_cmd *cmd)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- if (vif->bss_conf.cqm_rssi_thold && !d0i3) {
+ if (vif->bss_conf.cqm_rssi_thold) {
cmd->bf_energy_delta =
cpu_to_le32(vif->bss_conf.cqm_rssi_hyst);
/* fw uses an absolute value for this */
@@ -849,8 +848,7 @@ iwl_mvm_beacon_filter_debugfs_parameters(struct ieee80211_vif *vif,
static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_beacon_filter_cmd *cmd,
- u32 cmd_flags,
- bool d0i3)
+ u32 cmd_flags)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
@@ -859,13 +857,11 @@ static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return 0;
- iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd, d0i3);
- if (!d0i3)
- iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
+ iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, cmd);
+ iwl_mvm_beacon_filter_debugfs_parameters(vif, cmd);
ret = iwl_mvm_beacon_filter_send_cmd(mvm, cmd, cmd_flags);
- /* don't change bf_enabled in case of temporary d0i3 configuration */
- if (!ret && !d0i3)
+ if (!ret)
mvmvif->bf_data.bf_enabled = true;
return ret;
@@ -880,12 +876,12 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
.bf_enable_beacon_filter = cpu_to_le32(1),
};
- return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false);
+ return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags);
}
static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
- u32 flags, bool d0i3)
+ u32 flags)
{
struct iwl_beacon_filter_cmd cmd = {};
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -896,8 +892,7 @@ static int _iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
ret = iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, flags);
- /* don't change bf_enabled in case of temporary d0i3 configuration */
- if (!ret && !d0i3)
+ if (!ret)
mvmvif->bf_data.bf_enabled = false;
return ret;
@@ -907,7 +902,7 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 flags)
{
- return _iwl_mvm_disable_beacon_filter(mvm, vif, flags, false);
+ return _iwl_mvm_disable_beacon_filter(mvm, vif, flags);
}
static int iwl_mvm_power_set_ps(struct iwl_mvm *mvm)
@@ -958,7 +953,7 @@ static int iwl_mvm_power_set_ba(struct iwl_mvm *mvm,
!vif->bss_conf.ps ||
iwl_mvm_vif_low_latency(mvmvif));
- return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false);
+ return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0);
}
int iwl_mvm_power_update_ps(struct iwl_mvm *mvm)
@@ -1022,58 +1017,3 @@ int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
return 0;
}
-
-int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- bool enable, u32 flags)
-{
- int ret;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mac_power_cmd cmd = {};
-
- if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
- return 0;
-
- if (!vif->bss_conf.assoc)
- return 0;
-
- iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable);
-
- iwl_mvm_power_log(mvm, &cmd);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
- memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd));
-#endif
- ret = iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, flags,
- sizeof(cmd), &cmd);
- if (ret)
- return ret;
-
- /* configure beacon filtering */
- if (mvmvif != mvm->bf_allowed_vif)
- return 0;
-
- if (enable) {
- struct iwl_beacon_filter_cmd cmd_bf = {
- IWL_BF_CMD_CONFIG_D0I3,
- .bf_enable_beacon_filter = cpu_to_le32(1),
- };
- /*
- * When beacon storing is supported - disable beacon filtering
- * altogether - the latest beacon will be sent when exiting d0i3
- */
- if (fw_has_capa(&mvm->fw->ucode_capa,
- IWL_UCODE_TLV_CAPA_BEACON_STORING))
- ret = _iwl_mvm_disable_beacon_filter(mvm, vif, flags,
- true);
- else
- ret = _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd_bf,
- flags, true);
- } else {
- if (mvmvif->bf_data.bf_enabled)
- ret = iwl_mvm_enable_beacon_filter(mvm, vif, flags);
- else
- ret = iwl_mvm_disable_beacon_filter(mvm, vif, flags);
- }
-
- return ret;
-}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
index 08b67812e94e..8f50e2b121bd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -193,7 +193,7 @@ rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
int i, highest_mcs;
for (i = 0; i < sta->rx_nss; i++) {
- if (i == MAX_NSS)
+ if (i == IWL_TLC_NSS_MAX)
break;
highest_mcs = rs_fw_vht_highest_rx_mcs_index(vht_cap, i + 1);
@@ -204,9 +204,10 @@ rs_fw_vht_set_enabled_rates(const struct ieee80211_sta *sta,
if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
supp &= ~BIT(IWL_TLC_MNG_HT_RATE_MCS9);
- cmd->ht_rates[i][0] = cpu_to_le16(supp);
+ cmd->ht_rates[i][IWL_TLC_HT_BW_NONE_160] = cpu_to_le16(supp);
if (sta->bandwidth == IEEE80211_STA_RX_BW_160)
- cmd->ht_rates[i][1] = cmd->ht_rates[i][0];
+ cmd->ht_rates[i][IWL_TLC_HT_BW_160] =
+ cmd->ht_rates[i][IWL_TLC_HT_BW_NONE_160];
}
}
@@ -241,7 +242,7 @@ rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160);
int i;
- for (i = 0; i < sta->rx_nss && i < MAX_NSS; i++) {
+ for (i = 0; i < sta->rx_nss && i < IWL_TLC_NSS_MAX; i++) {
u16 _mcs_160 = (mcs_160 >> (2 * i)) & 0x3;
u16 _mcs_80 = (mcs_80 >> (2 * i)) & 0x3;
u16 _tx_mcs_160 = (tx_mcs_160 >> (2 * i)) & 0x3;
@@ -255,7 +256,7 @@ rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
}
if (_mcs_80 > _tx_mcs_80)
_mcs_80 = _tx_mcs_80;
- cmd->ht_rates[i][0] =
+ cmd->ht_rates[i][IWL_TLC_HT_BW_NONE_160] =
cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_80));
/* If one side doesn't support - mark both as not supporting */
@@ -266,7 +267,7 @@ rs_fw_he_set_enabled_rates(const struct ieee80211_sta *sta,
}
if (_mcs_160 > _tx_mcs_160)
_mcs_160 = _tx_mcs_160;
- cmd->ht_rates[i][1] =
+ cmd->ht_rates[i][IWL_TLC_HT_BW_160] =
cpu_to_le16(rs_fw_he_ieee80211_mcs_to_rs_mcs(_mcs_160));
}
}
@@ -300,8 +301,10 @@ static void rs_fw_set_supp_rates(struct ieee80211_sta *sta,
rs_fw_vht_set_enabled_rates(sta, vht_cap, cmd);
} else if (ht_cap->ht_supported) {
cmd->mode = IWL_TLC_MNG_MODE_HT;
- cmd->ht_rates[0][0] = cpu_to_le16(ht_cap->mcs.rx_mask[0]);
- cmd->ht_rates[1][0] = cpu_to_le16(ht_cap->mcs.rx_mask[1]);
+ cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_HT_BW_NONE_160] =
+ cpu_to_le16(ht_cap->mcs.rx_mask[0]);
+ cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_HT_BW_NONE_160] =
+ cpu_to_le16(ht_cap->mcs.rx_mask[1]);
}
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index d3f04acfbacb..42d525e46e80 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -3079,11 +3079,7 @@ static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_lq_sta *lq_sta = &mvmsta->lq_sta.rs_drv;
- /* Treat uninitialized rate scaling data same as non-existing. */
- if (!lq_sta) {
- IWL_DEBUG_RATE(mvm, "Station rate scaling not created yet.\n");
- return;
- } else if (!lq_sta->pers.drv) {
+ if (!lq_sta->pers.drv) {
IWL_DEBUG_RATE(mvm, "Rate scaling not initialized yet.\n");
return;
}
@@ -3342,7 +3338,7 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
if (num_of_ant(ant) == 1)
lq_cmd->single_stream_ant_msk = ant;
- if (!mvm->trans->cfg->gen2)
+ if (!mvm->trans->trans_cfg->gen2)
lq_cmd->agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
else
lq_cmd->agg_frame_cnt_limit =
@@ -4127,10 +4123,6 @@ static void rs_drv_add_sta_debugfs(void *mvm, void *priv_sta,
MVM_DEBUGFS_ADD_FILE_RS(ss_force, dir, 0600);
}
-
-void rs_remove_sta_debugfs(void *mvm, void *mvm_sta)
-{
-}
#endif
/*
@@ -4158,7 +4150,6 @@ static const struct rate_control_ops rs_mvm_ops_drv = {
.rate_update = rs_drv_rate_update,
#ifdef CONFIG_MAC80211_DEBUGFS
.add_sta_debugfs = rs_drv_add_sta_debugfs,
- .remove_sta_debugfs = rs_remove_sta_debugfs,
#endif
.capa = RATE_CTRL_CAPA_VHT_EXT_NSS_BW,
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
index 160b0db27103..0ad8ed23a455 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -8,6 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -29,6 +30,8 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
+ * Copyright(c) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -349,7 +352,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
u32 rate_n_flags;
u32 rx_pkt_status;
u8 crypt_len = 0;
- bool take_ref;
phy_info = &mvm->last_phy_info;
rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data;
@@ -557,22 +559,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
ieee80211_is_probe_resp(hdr->frame_control)))
rx_status->boottime_ns = ktime_get_boottime_ns();
- /* Take a reference briefly to kick off a d0i3 entry delay so
- * we can handle bursts of RX packets without toggling the
- * state too often. But don't do this for beacons if we are
- * going to idle because the beacon filtering changes we make
- * cause the firmware to send us collateral beacons. */
- take_ref = !(test_bit(STATUS_TRANS_GOING_IDLE, &mvm->trans->status) &&
- ieee80211_is_beacon(hdr->frame_control));
-
- if (take_ref)
- iwl_mvm_ref(mvm, IWL_MVM_REF_RX);
-
iwl_mvm_pass_packet_to_mac80211(mvm, sta, napi, skb, hdr, len,
crypt_len, rxb);
-
- if (take_ref)
- iwl_mvm_unref(mvm, IWL_MVM_REF_RX);
}
struct iwl_mvm_stat_data {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
index 854edd7d7103..77b03b757193 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -349,7 +349,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
!(status & IWL_RX_MPDU_RES_STATUS_TTAK_OK))
return 0;
- if (mvm->trans->cfg->gen2 &&
+ if (mvm->trans->trans_cfg->gen2 &&
!(status & RX_MPDU_RES_STATUS_MIC_OK))
stats->flag |= RX_FLAG_MMIC_ERROR;
@@ -366,7 +366,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
if (pkt_flags & FH_RSCSR_RADA_EN) {
stats->flag |= RX_FLAG_ICV_STRIPPED;
- if (mvm->trans->cfg->gen2)
+ if (mvm->trans->trans_cfg->gen2)
stats->flag |= RX_FLAG_MMIC_STRIPPED;
}
@@ -377,8 +377,16 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
stats->flag |= RX_FLAG_DECRYPTED;
return 0;
default:
- /* Expected in monitor (not having the keys) */
- if (!mvm->monitor_on)
+ /*
+ * Sometimes we can get frames that were not decrypted
+ * because the firmware didn't have the keys yet. This can
+ * happen after connection where we can get multicast frames
+ * before the GTK is installed.
+ * Silently drop those frames.
+ * Also drop un-decrypted frames in monitor mode.
+ */
+ if (!is_multicast_ether_addr(hdr->addr1) &&
+ !mvm->monitor_on && net_ratelimit())
IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status);
}
@@ -781,6 +789,55 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
wake_up(&mvm->rx_sync_waitq);
}
+static void iwl_mvm_oldsn_workaround(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta, int tid,
+ struct iwl_mvm_reorder_buffer *buffer,
+ u32 reorder, u32 gp2, int queue)
+{
+ struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+
+ if (gp2 != buffer->consec_oldsn_ampdu_gp2) {
+ /* we have a new (A-)MPDU ... */
+
+ /*
+ * reset counter to 0 if we didn't have any oldsn in
+ * the last A-MPDU (as detected by GP2 being identical)
+ */
+ if (!buffer->consec_oldsn_prev_drop)
+ buffer->consec_oldsn_drops = 0;
+
+ /* either way, update our tracking state */
+ buffer->consec_oldsn_ampdu_gp2 = gp2;
+ } else if (buffer->consec_oldsn_prev_drop) {
+ /*
+ * tracking state didn't change, and we had an old SN
+ * indication before - do nothing in this case, we
+ * already noted this one down and are waiting for the
+ * next A-MPDU (by GP2)
+ */
+ return;
+ }
+
+ /* return unless this MPDU has old SN */
+ if (!(reorder & IWL_RX_MPDU_REORDER_BA_OLD_SN))
+ return;
+
+ /* update state */
+ buffer->consec_oldsn_prev_drop = 1;
+ buffer->consec_oldsn_drops++;
+
+ /* if limit is reached, send del BA and reset state */
+ if (buffer->consec_oldsn_drops == IWL_MVM_AMPDU_CONSEC_DROPS_DELBA) {
+ IWL_WARN(mvm,
+ "reached %d old SN frames from %pM on queue %d, stopping BA session on TID %d\n",
+ IWL_MVM_AMPDU_CONSEC_DROPS_DELBA,
+ sta->addr, queue, tid);
+ ieee80211_stop_rx_ba_session(mvmsta->vif, BIT(tid), sta->addr);
+ buffer->consec_oldsn_prev_drop = 0;
+ buffer->consec_oldsn_drops = 0;
+ }
+}
+
/*
* Returns true if the MPDU was buffered\dropped, false if it should be passed
* to upper layer.
@@ -792,6 +849,7 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
struct sk_buff *skb,
struct iwl_rx_mpdu_desc *desc)
{
+ struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = iwl_mvm_skb_get_hdr(skb);
struct iwl_mvm_sta *mvm_sta;
struct iwl_mvm_baid_data *baid_data;
@@ -894,6 +952,9 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm,
min_sn, IWL_MVM_RELEASE_SEND_RSS_SYNC);
}
+ iwl_mvm_oldsn_workaround(mvm, sta, tid, buffer, reorder,
+ rx_status->device_timestamp, queue);
+
/* drop any oudated packets */
if (ieee80211_sn_less(sn, buffer->head_sn))
goto drop;
@@ -1504,7 +1565,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
return;
- if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
+ if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
channel = desc->v3.channel;
gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
@@ -1605,7 +1666,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
if (likely(!(phy_info & IWL_RX_MPDU_PHY_TSF_OVERLOAD))) {
u64 tsf_on_air_rise;
- if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+ if (mvm->trans->trans_cfg->device_family >=
+ IWL_DEVICE_FAMILY_22560)
tsf_on_air_rise = le64_to_cpu(desc->v3.tsf_on_air_rise);
else
tsf_on_air_rise = le64_to_cpu(desc->v1.tsf_on_air_rise);
@@ -1731,7 +1793,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
*qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
- if (mvm->trans->cfg->device_family ==
+ if (mvm->trans->trans_cfg->device_family ==
IWL_DEVICE_FAMILY_9000) {
iwl_mvm_flip_address(hdr->addr3);
@@ -1960,3 +2022,42 @@ void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
le16_to_cpu(release->nssn),
queue, 0);
}
+
+void iwl_mvm_rx_bar_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
+ struct iwl_rx_cmd_buffer *rxb, int queue)
+{
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_bar_frame_release *release = (void *)pkt->data;
+ unsigned int baid = le32_get_bits(release->ba_info,
+ IWL_BAR_FRAME_RELEASE_BAID_MASK);
+ unsigned int nssn = le32_get_bits(release->ba_info,
+ IWL_BAR_FRAME_RELEASE_NSSN_MASK);
+ unsigned int sta_id = le32_get_bits(release->sta_tid,
+ IWL_BAR_FRAME_RELEASE_STA_MASK);
+ unsigned int tid = le32_get_bits(release->sta_tid,
+ IWL_BAR_FRAME_RELEASE_TID_MASK);
+ struct iwl_mvm_baid_data *baid_data;
+
+ if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID ||
+ baid >= ARRAY_SIZE(mvm->baid_map)))
+ return;
+
+ rcu_read_lock();
+ baid_data = rcu_dereference(mvm->baid_map[baid]);
+ if (!baid_data) {
+ IWL_DEBUG_RX(mvm,
+ "Got valid BAID %d but not allocated, invalid BAR release!\n",
+ baid);
+ goto out;
+ }
+
+ if (WARN(tid != baid_data->tid || sta_id != baid_data->sta_id,
+ "baid 0x%x is mapped to sta:%d tid:%d, but BAR release received for sta:%d tid:%d\n",
+ baid, baid_data->sta_id, baid_data->tid, sta_id,
+ tid))
+ goto out;
+
+ iwl_mvm_release_frames_from_notif(mvm, napi, baid, nssn, queue, 0);
+out:
+ rcu_read_unlock();
+}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index c284e6975b1b..f6b3045badbd 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -77,7 +77,10 @@
#define IWL_SCAN_DWELL_FRAGMENTED 44
#define IWL_SCAN_DWELL_EXTENDED 90
#define IWL_SCAN_NUM_OF_FRAGS 3
+#define IWL_SCAN_LAST_2_4_CHN 14
+#define IWL_SCAN_BAND_5_2 0
+#define IWL_SCAN_BAND_2_4 1
/* adaptive dwell max budget time [TU] for full scan */
#define IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300
@@ -512,7 +515,6 @@ void iwl_mvm_rx_lmac_scan_complete_notif(struct iwl_mvm *mvm,
mvm->scan_status &= ~IWL_MVM_SCAN_REGULAR;
ieee80211_scan_completed(mvm->hw, &info);
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
cancel_delayed_work(&mvm->scan_timeout_dwork);
iwl_mvm_resume_tcm(mvm);
} else {
@@ -957,11 +959,24 @@ static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm,
return flags;
}
+static void
+iwl_mvm_scan_set_legacy_probe_req(struct iwl_scan_probe_req_v1 *p_req,
+ struct iwl_scan_probe_req *src_p_req)
+{
+ int i;
+
+ p_req->mac_header = src_p_req->mac_header;
+ for (i = 0; i < SCAN_NUM_BAND_PROBE_DATA_V_1; i++)
+ p_req->band_data[i] = src_p_req->band_data[i];
+ p_req->common_data = src_p_req->common_data;
+ memcpy(p_req->buf, src_p_req->buf, sizeof(p_req->buf));
+}
+
static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_mvm_scan_params *params)
{
struct iwl_scan_req_lmac *cmd = mvm->scan_cmd;
- struct iwl_scan_probe_req *preq =
+ struct iwl_scan_probe_req_v1 *preq =
(void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
mvm->fw->ucode_capa.n_scan_channels);
u32 ssid_bitmap = 0;
@@ -1031,7 +1046,7 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_lmac_scan_cfg_channels(mvm, params->channels,
params->n_channels, ssid_bitmap, cmd);
- *preq = params->preq;
+ iwl_mvm_scan_set_legacy_probe_req(preq, &params->preq);
return 0;
}
@@ -1205,7 +1220,7 @@ int iwl_mvm_config_scan(struct iwl_mvm *mvm)
cmd_size = sizeof(struct iwl_scan_config);
else
cmd_size = sizeof(struct iwl_scan_config_v1);
- cmd_size += mvm->fw->ucode_capa.n_scan_channels;
+ cmd_size += num_channels;
cfg = kzalloc(cmd_size, GFP_KERNEL);
if (!cfg)
@@ -1385,9 +1400,17 @@ iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
for (i = 0; i < n_channels; i++) {
channel_cfg[i].flags = cpu_to_le32(ssid_bitmap);
- channel_cfg[i].channel_num = channels[i]->hw_value;
- channel_cfg[i].iter_count = 1;
- channel_cfg[i].iter_interval = 0;
+ channel_cfg[i].v1.channel_num = channels[i]->hw_value;
+ if (iwl_mvm_is_scan_ext_chan_supported(mvm)) {
+ channel_cfg[i].v2.band =
+ channels[i]->hw_value <= IWL_SCAN_LAST_2_4_CHN ?
+ IWL_SCAN_BAND_2_4 : IWL_SCAN_BAND_5_2;
+ channel_cfg[i].v2.iter_count = 1;
+ channel_cfg[i].v2.iter_interval = 0;
+ } else {
+ channel_cfg[i].v1.iter_count = 1;
+ channel_cfg[i].v1.iter_interval = 0;
+ }
}
}
@@ -1477,9 +1500,12 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
struct iwl_scan_umac_chan_param *chan_param;
void *cmd_data = iwl_mvm_get_scan_req_umac_data(mvm);
- struct iwl_scan_req_umac_tail *sec_part = cmd_data +
- sizeof(struct iwl_scan_channel_cfg_umac) *
- mvm->fw->ucode_capa.n_scan_channels;
+ void *sec_part = cmd_data + sizeof(struct iwl_scan_channel_cfg_umac) *
+ mvm->fw->ucode_capa.n_scan_channels;
+ struct iwl_scan_req_umac_tail_v2 *tail_v2 =
+ (struct iwl_scan_req_umac_tail_v2 *)sec_part;
+ struct iwl_scan_req_umac_tail_v1 *tail_v1;
+ struct iwl_ssid_ie *direct_scan;
int uid, i;
u32 ssid_bitmap = 0;
u8 channel_flags = 0;
@@ -1541,18 +1567,12 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
chan_param->flags = channel_flags;
chan_param->count = params->n_channels;
- iwl_scan_build_ssids(params, sec_part->direct_scan, &ssid_bitmap);
-
- iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
- params->n_channels, ssid_bitmap,
- cmd_data);
-
for (i = 0; i < params->n_scan_plans; i++) {
struct cfg80211_sched_scan_plan *scan_plan =
&params->scan_plans[i];
- sec_part->schedule[i].iter_count = scan_plan->iterations;
- sec_part->schedule[i].interval =
+ tail_v2->schedule[i].iter_count = scan_plan->iterations;
+ tail_v2->schedule[i].interval =
cpu_to_le16(scan_plan->interval);
}
@@ -1562,12 +1582,24 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* For example, when regular scan is requested the driver sets one scan
* plan with one iteration.
*/
- if (!sec_part->schedule[i - 1].iter_count)
- sec_part->schedule[i - 1].iter_count = 0xff;
+ if (!tail_v2->schedule[i - 1].iter_count)
+ tail_v2->schedule[i - 1].iter_count = 0xff;
- sec_part->delay = cpu_to_le16(params->delay);
- sec_part->preq = params->preq;
+ tail_v2->delay = cpu_to_le16(params->delay);
+ if (iwl_mvm_is_scan_ext_chan_supported(mvm)) {
+ tail_v2->preq = params->preq;
+ direct_scan = tail_v2->direct_scan;
+ } else {
+ tail_v1 = (struct iwl_scan_req_umac_tail_v1 *)sec_part;
+ iwl_mvm_scan_set_legacy_probe_req(&tail_v1->preq,
+ &params->preq);
+ direct_scan = tail_v1->direct_scan;
+ }
+ iwl_scan_build_ssids(params, direct_scan, &ssid_bitmap);
+ iwl_mvm_umac_scan_cfg_channels(mvm, params->channels,
+ params->n_channels, ssid_bitmap,
+ cmd_data);
return 0;
}
@@ -1758,7 +1790,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n");
mvm->scan_status |= IWL_MVM_SCAN_REGULAR;
mvm->scan_vif = iwl_mvm_vif_from_mac80211(vif);
- iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
schedule_delayed_work(&mvm->scan_timeout_dwork,
msecs_to_jiffies(SCAN_TIMEOUT));
@@ -1884,7 +1915,6 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
memcpy(info.tsf_bssid, mvm->scan_vif->bssid, ETH_ALEN);
ieee80211_scan_completed(mvm->hw, &info);
mvm->scan_vif = NULL;
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
cancel_delayed_work(&mvm->scan_timeout_dwork);
iwl_mvm_resume_tcm(mvm);
} else if (mvm->scan_uid_status[uid] == IWL_MVM_SCAN_SCHED) {
@@ -1909,8 +1939,6 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
mvm->last_ebs_successful = false;
mvm->scan_uid_status[uid] = 0;
-
- iwl_fw_dbg_apply_point(&mvm->fwrt, IWL_FW_INI_APPLY_SCAN_COMPLETE);
}
void iwl_mvm_rx_umac_scan_iter_complete_notif(struct iwl_mvm *mvm,
@@ -1999,6 +2027,7 @@ static int iwl_mvm_scan_stop_wait(struct iwl_mvm *mvm, int type)
int iwl_mvm_scan_size(struct iwl_mvm *mvm)
{
int base_size = IWL_SCAN_REQ_UMAC_SIZE_V1;
+ int tail_size;
if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm))
base_size = IWL_SCAN_REQ_UMAC_SIZE_V8;
@@ -2007,16 +2036,21 @@ int iwl_mvm_scan_size(struct iwl_mvm *mvm)
else if (iwl_mvm_cdb_scan_api(mvm))
base_size = IWL_SCAN_REQ_UMAC_SIZE_V6;
- if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN))
+ if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
+ if (iwl_mvm_is_scan_ext_chan_supported(mvm))
+ tail_size = sizeof(struct iwl_scan_req_umac_tail_v2);
+ else
+ tail_size = sizeof(struct iwl_scan_req_umac_tail_v1);
+
return base_size +
sizeof(struct iwl_scan_channel_cfg_umac) *
mvm->fw->ucode_capa.n_scan_channels +
- sizeof(struct iwl_scan_req_umac_tail);
-
+ tail_size;
+ }
return sizeof(struct iwl_scan_req_lmac) +
sizeof(struct iwl_scan_channel_cfg_lmac) *
mvm->fw->ucode_capa.n_scan_channels +
- sizeof(struct iwl_scan_probe_req);
+ sizeof(struct iwl_scan_probe_req_v1);
}
/*
@@ -2099,10 +2133,6 @@ out:
mvm->scan_status &= ~type;
if (type == IWL_MVM_SCAN_REGULAR) {
- /* Since the rx handler won't do anything now, we have
- * to release the scan reference here.
- */
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
cancel_delayed_work(&mvm->scan_timeout_dwork);
if (notify) {
struct cfg80211_scan_info info = {
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 10f18536dd0d..0bedba4c61f2 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -67,14 +67,6 @@
#include "sta.h"
#include "rs.h"
-static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm);
-
-static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
- u32 sta_id,
- struct ieee80211_key_conf *key, bool mcast,
- u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags,
- u8 key_offset, bool mfp);
-
/*
* New version of ADD_STA_sta command added new fields at the end of the
* structure, so sending the size of the relevant API's structure is enough to
@@ -1612,7 +1604,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
mvm_sta->mac_id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color);
mvm_sta->vif = vif;
- if (!mvm->trans->cfg->gen2)
+ if (!mvm->trans->trans_cfg->gen2)
mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
else
mvm_sta->max_agg_bufsize = LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF;
@@ -1895,10 +1887,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
/* unassoc - go ahead - remove the AP STA now */
mvmvif->ap_sta_id = IWL_MVM_INVALID_STA;
-
- /* clear d0i3_ap_sta_id if no longer relevant */
- if (mvm->d0i3_ap_sta_id == sta_id)
- mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA;
}
/*
@@ -1966,8 +1954,8 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 *queue,
u8 sta_id, u8 fifo)
{
unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ?
- mvm->cfg->base_params->wd_timeout :
- IWL_WATCHDOG_DISABLED;
+ mvm->trans->trans_cfg->base_params->wd_timeout :
+ IWL_WATCHDOG_DISABLED;
if (iwl_mvm_has_new_tx_api(mvm)) {
int tvqm_queue =
@@ -2771,13 +2759,6 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
spin_lock_bh(&mvmsta->lock);
- /* possible race condition - we entered D0i3 while starting agg */
- if (test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)) {
- spin_unlock_bh(&mvmsta->lock);
- IWL_ERR(mvm, "Entered D0i3 while starting Tx agg\n");
- return -EIO;
- }
-
/*
* Note the possible cases:
* 1. An enabled TXQ - TXQ needs to become agg'ed
@@ -2832,7 +2813,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
* to align the wrap around of ssn so we compare relevant values.
*/
normalized_ssn = tid_data->ssn;
- if (mvm->trans->cfg->gen2)
+ if (mvm->trans->trans_cfg->gen2)
normalized_ssn &= 0xff;
if (normalized_ssn == tid_data->next_reclaimed) {
@@ -3872,7 +3853,7 @@ u16 iwl_mvm_tid_queued(struct iwl_mvm *mvm, struct iwl_mvm_tid_data *tid_data)
* In 22000 HW, the next_reclaimed index is only 8 bit, so we'll need
* to align the wrap around of ssn so we compare relevant values.
*/
- if (mvm->trans->cfg->gen2)
+ if (mvm->trans->trans_cfg->gen2)
sn &= 0xff;
return ieee80211_sn_sub(sn, tid_data->next_reclaimed);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
index 9df21a8d1fc1..1851719e9f4b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tdls.c
@@ -205,19 +205,10 @@ void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
- /*
- * iwl_mvm_protect_session() reads directly from the device
- * (the system time), so make sure it is available.
- */
- if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS))
- return;
-
mutex_lock(&mvm->mutex);
/* Protect the session to hear the TDLS setup response on the channel */
iwl_mvm_protect_session(mvm, vif, duration, duration, 100, true);
mutex_unlock(&mvm->mutex);
-
- iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
}
static const char *
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
index 4d34e5ab1bff..a06bc63fb516 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
@@ -106,10 +106,8 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* in the case that the time event actually completed in the firmware
* (which is handled in iwl_mvm_te_handle_notif).
*/
- if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
- iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
- if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
- iwl_mvm_unref(mvm, IWL_MVM_REF_ROC_AUX);
+ clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
+ clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
synchronize_net();
@@ -357,7 +355,6 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
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);
ieee80211_ready_on_channel(mvm->hw);
} else if (te_data->id == TE_CHANNEL_SWITCH_PERIOD) {
iwl_mvm_te_handle_notify_csa(mvm, te_data, notif);
@@ -405,7 +402,6 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
te_data->running = true;
- iwl_mvm_ref(mvm, IWL_MVM_REF_ROC_AUX);
ieee80211_ready_on_channel(mvm->hw); /* Start TE */
} else {
IWL_DEBUG_TE(mvm,
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index 0b3e5c99d316..32a708301cfc 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -5,7 +5,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2014, 2019 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
*
@@ -27,7 +27,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2012 - 2014, 2019 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2016 Intel Deutschland GmbH
* All rights reserved.
@@ -298,16 +298,8 @@ static void check_exit_ctkill(struct work_struct *work)
if (__iwl_mvm_mac_start(mvm))
goto reschedule;
- /* make sure the device is available for direct read/writes */
- if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL)) {
- __iwl_mvm_mac_stop(mvm);
- goto reschedule;
- }
-
ret = iwl_mvm_get_temp(mvm, &temp);
- iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL);
-
__iwl_mvm_mac_stop(mvm);
if (ret)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 6ac114a393cc..8a059da7a1fa 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -546,7 +546,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
hdr->frame_control);
}
- if (mvm->trans->cfg->device_family >=
+ if (mvm->trans->trans_cfg->device_family >=
IWL_DEVICE_FAMILY_22560) {
struct iwl_tx_cmd_gen3 *cmd = (void *)dev_cmd->payload;
@@ -1169,8 +1169,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb,
schedule_work(&mvm->add_stream_wk);
}
- IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x\n", mvmsta->sta_id,
- tid, txq_id, IEEE80211_SEQ_TO_SN(seq_number));
+ IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x len %d\n",
+ mvmsta->sta_id, tid, txq_id,
+ IEEE80211_SEQ_TO_SN(seq_number), skb->len);
/* From now on, we cannot access info->control */
iwl_mvm_skb_prepare_status(skb, dev_cmd);
@@ -1271,7 +1272,7 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
* to align the wrap around of ssn so we compare relevant values.
*/
normalized_ssn = tid_data->ssn;
- if (mvm->trans->cfg->gen2)
+ if (mvm->trans->trans_cfg->gen2)
normalized_ssn &= 0xff;
if (normalized_ssn != tid_data->next_reclaimed)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
index b8e20a01c192..8686107da116 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -88,17 +88,11 @@ int iwl_mvm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd)
* the mutex, this ensures we don't try to send two
* (or more) synchronous commands at a time.
*/
- if (!(cmd->flags & CMD_ASYNC)) {
+ if (!(cmd->flags & CMD_ASYNC))
lockdep_assert_held(&mvm->mutex);
- if (!(cmd->flags & CMD_SEND_IN_IDLE))
- 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)))
- iwl_mvm_unref(mvm, IWL_MVM_REF_SENDING_CMD);
-
/*
* If the caller wants the SKB, then don't hide any problems, the
* caller might access the response buffer which will be NULL if
@@ -537,7 +531,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num)
/* reset the device */
iwl_trans_sw_reset(trans);
- err = iwl_finish_nic_init(trans);
+ err = iwl_finish_nic_init(trans, trans->trans_cfg);
if (err)
return;
}
@@ -945,8 +939,9 @@ unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
{
struct iwl_fw_dbg_trigger_tlv *trigger;
struct iwl_fw_dbg_trigger_txq_timer *txq_timer;
- unsigned int default_timeout =
- cmd_q ? IWL_DEF_WD_TIMEOUT : mvm->cfg->base_params->wd_timeout;
+ unsigned int default_timeout = cmd_q ?
+ IWL_DEF_WD_TIMEOUT :
+ mvm->trans->trans_cfg->base_params->wd_timeout;
if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS)) {
/*
@@ -990,7 +985,7 @@ unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm,
return default_timeout;
default:
WARN_ON(1);
- return mvm->cfg->base_params->wd_timeout;
+ return mvm->trans->trans_cfg->base_params->wd_timeout;
}
}
@@ -1436,7 +1431,7 @@ u32 iwl_mvm_get_systime(struct iwl_mvm *mvm)
{
u32 reg_addr = DEVICE_SYSTEM_TIME_REG;
- if (mvm->trans->cfg->device_family >= IWL_DEVICE_FAMILY_22000 &&
+ if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000 &&
mvm->trans->cfg->gp2_reg_addr)
reg_addr = mvm->trans->cfg->gp2_reg_addr;