From 451458abb73f1a93eb9047e751cbc1cd11a71808 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 24 Jan 2019 19:03:30 +0100 Subject: [PATCH] 4.19-stable patches added patches: iwlwifi-mvm-send-lq-command-as-async-when-necessary.patch --- ...d-lq-command-as-async-when-necessary.patch | 176 ++++++++++++++++++ queue-4.19/series | 1 + 2 files changed, 177 insertions(+) create mode 100644 queue-4.19/iwlwifi-mvm-send-lq-command-as-async-when-necessary.patch diff --git a/queue-4.19/iwlwifi-mvm-send-lq-command-as-async-when-necessary.patch b/queue-4.19/iwlwifi-mvm-send-lq-command-as-async-when-necessary.patch new file mode 100644 index 00000000000..e1dfa074eaf --- /dev/null +++ b/queue-4.19/iwlwifi-mvm-send-lq-command-as-async-when-necessary.patch @@ -0,0 +1,176 @@ +From 3baf7528d6f832b28622d1ddadd2e47f6c2b5e08 Mon Sep 17 00:00:00 2001 +From: Avraham Stern +Date: Thu, 3 May 2018 15:02:16 +0300 +Subject: iwlwifi: mvm: Send LQ command as async when necessary + +From: Avraham Stern + +commit 3baf7528d6f832b28622d1ddadd2e47f6c2b5e08 upstream. + +The parameter that indicated whether the LQ command should be sent +as sync or async was removed, causing the LQ command to be sent as +sync from interrupt context (e.g. from the RX path). This resulted +in a kernel warning: "scheduling while atomic" and failing to send +the LQ command, which ultimately leads to a queue hang. + +Fix it by adding back the required parameter to send the command as +sync only when it is allowed. + +Fixes: d94c5a820d10 ("iwlwifi: mvm: open BA session only when sta is authorized") +Signed-off-by: Avraham Stern +Signed-off-by: Luca Coelho +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 6 ++++-- + drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +- + drivers/net/wireless/intel/iwlwifi/mvm/rs.c | 18 ++++++++---------- + drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 2 +- + drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 7 +++---- + 5 files changed, 17 insertions(+), 18 deletions(-) + +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +@@ -2938,7 +2938,8 @@ static int iwl_mvm_mac_sta_state(struct + iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); + } + +- iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band); ++ iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, ++ false); + ret = iwl_mvm_update_sta(mvm, vif, sta); + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTHORIZED) { +@@ -2954,7 +2955,8 @@ static int iwl_mvm_mac_sta_state(struct + /* enable beacon filtering */ + WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); + +- iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band); ++ iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, ++ true); + + ret = 0; + } else if (old_state == IEEE80211_STA_AUTHORIZED && +--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +@@ -1685,7 +1685,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm * + #endif /* CONFIG_IWLWIFI_DEBUGFS */ + + /* rate scaling */ +-int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init); ++int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool sync); + void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg); + int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate); + void rs_update_last_rssi(struct iwl_mvm *mvm, +--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +@@ -1280,7 +1280,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm + (unsigned long)(lq_sta->last_tx + + (IWL_MVM_RS_IDLE_TIMEOUT * HZ)))) { + IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n"); +- iwl_mvm_rs_rate_init(mvm, sta, info->band); ++ iwl_mvm_rs_rate_init(mvm, sta, info->band, true); + return; + } + lq_sta->last_tx = jiffies; +@@ -2870,9 +2870,8 @@ void rs_update_last_rssi(struct iwl_mvm + static void rs_initialize_lq(struct iwl_mvm *mvm, + struct ieee80211_sta *sta, + struct iwl_lq_sta *lq_sta, +- enum nl80211_band band) ++ enum nl80211_band band, bool update) + { +- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); + struct iwl_scale_tbl_info *tbl; + struct rs_rate *rate; + u8 active_tbl = 0; +@@ -2901,8 +2900,7 @@ static void rs_initialize_lq(struct iwl_ + rs_set_expected_tpt_table(lq_sta, tbl); + rs_fill_lq_cmd(mvm, sta, lq_sta, rate); + /* TODO restore station should remember the lq cmd */ +- iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, +- mvmsta->sta_state < IEEE80211_STA_AUTHORIZED); ++ iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, !update); + } + + static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta, +@@ -3155,7 +3153,7 @@ void iwl_mvm_update_frame_stats(struct i + * Called after adding a new station to initialize rate scaling + */ + static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, +- enum nl80211_band band) ++ enum nl80211_band band, bool update) + { + int i, j; + struct ieee80211_hw *hw = mvm->hw; +@@ -3235,7 +3233,7 @@ static void rs_drv_rate_init(struct iwl_ + #ifdef CONFIG_IWLWIFI_DEBUGFS + iwl_mvm_reset_frame_stats(mvm); + #endif +- rs_initialize_lq(mvm, sta, lq_sta, band); ++ rs_initialize_lq(mvm, sta, lq_sta, band, update); + } + + static void rs_drv_rate_update(void *mvm_r, +@@ -3255,7 +3253,7 @@ static void rs_drv_rate_update(void *mvm + for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) + ieee80211_stop_tx_ba_session(sta, tid); + +- iwl_mvm_rs_rate_init(mvm, sta, sband->band); ++ iwl_mvm_rs_rate_init(mvm, sta, sband->band, true); + } + + #ifdef CONFIG_MAC80211_DEBUGFS +@@ -4112,12 +4110,12 @@ static const struct rate_control_ops rs_ + }; + + void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, +- enum nl80211_band band) ++ enum nl80211_band band, bool update) + { + if (iwl_mvm_has_tlc_offload(mvm)) + rs_fw_rate_init(mvm, sta, band); + else +- rs_drv_rate_init(mvm, sta, band); ++ rs_drv_rate_init(mvm, sta, band, update); + } + + int iwl_mvm_rate_control_register(void) +--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.h ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.h +@@ -420,7 +420,7 @@ struct iwl_lq_sta { + + /* Initialize station's rate scaling information after adding station */ + void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, +- enum nl80211_band band); ++ enum nl80211_band band, bool init); + + /* Notify RS about Tx status */ + void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, +--- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +@@ -900,20 +900,19 @@ int iwl_mvm_disable_txq(struct iwl_mvm * + + /** + * iwl_mvm_send_lq_cmd() - Send link quality command +- * @init: This command is sent as part of station initialization right +- * after station has been added. ++ * @sync: This command can be sent synchronously. + * + * The link quality command is sent as the last step of station creation. + * This is the special case in which init is set and we call a callback in + * this case to clear the state indicating that station creation is in + * progress. + */ +-int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init) ++int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool sync) + { + struct iwl_host_cmd cmd = { + .id = LQ_CMD, + .len = { sizeof(struct iwl_lq_cmd), }, +- .flags = init ? 0 : CMD_ASYNC, ++ .flags = sync ? 0 : CMD_ASYNC, + .data = { lq, }, + }; + diff --git a/queue-4.19/series b/queue-4.19/series index 5b4181207ea..1083c50a6c4 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -97,3 +97,4 @@ mm-page-writeback.c-don-t-break-integrity-writeback-.patch mm-swap-use-nr_node_ids-for-avail_lists-in-swap_info.patch userfaultfd-clear-flag-if-remap-event-not-enabled.patch mm-proc-be-more-verbose-about-unstable-vma-flags-in-.patch +iwlwifi-mvm-send-lq-command-as-async-when-necessary.patch -- 2.47.2