From 0a16628212b8b0daac643b6a0f1caa4e9482afc8 Mon Sep 17 00:00:00 2001 From: Arend Van Spriel Date: Wed, 12 Jul 2017 10:32:48 +0100 Subject: [PATCH 1/9] brcmfmac: fix regression in brcmf_sdio_txpkt_hdalign() Recent change in brcmf_sdio_txpkt_hdalign() changed the behavior and now always returns 0. This resulted in a regression which basically renders the device useless. Fixes: 270a6c1f65fe ("brcmfmac: rework headroom check in .start_xmit()") Reported-by: S. Gilles Tested-by: S. Gilles Signed-off-by: Arend van Spriel Signed-off-by: Kalle Valo --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index fbcbb4325936..c3ecec673eb7 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -2053,12 +2053,13 @@ static int brcmf_sdio_txpkt_hdalign(struct brcmf_sdio *bus, struct sk_buff *pkt) atomic_inc(&stats->pktcow_failed); return -ENOMEM; } + head_pad = 0; } skb_push(pkt, head_pad); dat_buf = (u8 *)(pkt->data); } memset(dat_buf, 0, head_pad + bus->tx_hdrlen); - return 0; + return head_pad; } /** From 271612d72da5b46715447bc18add4a1cf7d87687 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 17 Jul 2017 09:34:19 -0500 Subject: [PATCH 2/9] Revert "rtlwifi: btcoex: rtl8723be: fix ant_sel not work" This reverts commit f95d95a7cd5514549dcf6ba754f0ee834cce3e1f. With commit f95d95a7cd55 ("rtlwifi: btcoex: rtl8723be: fix ant_sel not work"), the kernel has a NULL pointer dereference oops. This content and the proper fix will be included in a later patch. Fixes: f95d95a7cd55 ("rtlwifi: btcoex: rtl8723be: fix ant_sel not work") Signed-off-by: Larry Finger Cc: Ping-Ke Shih Cc: Yan-Hsuan Chuang Cc: Birming Chiu Cc: Shaofu Cc: Steven Ting Signed-off-by: Kalle Valo --- drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c | 3 --- drivers/net/wireless/realtek/rtlwifi/wifi.h | 1 - 2 files changed, 4 deletions(-) diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c index 2a7ad5ffe997..cd5dc6dcb19f 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c @@ -846,9 +846,6 @@ static bool _rtl8723be_init_mac(struct ieee80211_hw *hw) return false; } - if (rtlpriv->cfg->ops->get_btc_status()) - rtlpriv->btcoexist.btc_ops->btc_power_on_setting(rtlpriv); - bytetmp = rtl_read_byte(rtlpriv, REG_MULTI_FUNC_CTRL); rtl_write_byte(rtlpriv, REG_MULTI_FUNC_CTRL, bytetmp | BIT(3)); diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index fb1ebb01133f..70723e67b7d7 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -2547,7 +2547,6 @@ struct bt_coexist_info { struct rtl_btc_ops { void (*btc_init_variables) (struct rtl_priv *rtlpriv); void (*btc_init_hal_vars) (struct rtl_priv *rtlpriv); - void (*btc_power_on_setting)(struct rtl_priv *rtlpriv); void (*btc_init_hw_config) (struct rtl_priv *rtlpriv); void (*btc_ips_notify) (struct rtl_priv *rtlpriv, u8 type); void (*btc_lps_notify)(struct rtl_priv *rtlpriv, u8 type); From 0b0f934e92a8eaed2e6c48a50eae6f84661f74f3 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 8 Jun 2017 10:55:26 +0300 Subject: [PATCH 3/9] iwlwifi: dvm: prevent an out of bounds access iwlagn_check_ratid_empty takes the tid as a parameter, but it doesn't check that it is not IWL_TID_NON_QOS. Since IWL_TID_NON_QOS = 8 and iwl_priv::tid_data is an array with 8 entries, accessing iwl_priv::tid_data[IWL_TID_NON_QOS] is a bad idea. This happened in iwlagn_rx_reply_tx. Since iwlagn_check_ratid_empty is relevant only to check whether we can open A-MPDU, this flow is irrelevant if tid is IWL_TID_NON_QOS. Call iwlagn_check_ratid_empty only inside the if (tid != IWL_TID_NON_QOS) a few lines earlier in the function. Cc: Reported-by: Seraphime Kirkovski Tested-by: Seraphime Kirkovski Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/dvm/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c index adaa2f0097cc..fb40ddfced99 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/tx.c @@ -1189,11 +1189,11 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb) next_reclaimed; IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", next_reclaimed); + iwlagn_check_ratid_empty(priv, sta_id, tid); } iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); - iwlagn_check_ratid_empty(priv, sta_id, tid); freed = 0; /* process frames */ From f6eac740a9b6f3737a969bad82931633519a1cc5 Mon Sep 17 00:00:00 2001 From: Mordechai Goodstein Date: Sun, 11 Jun 2017 18:00:36 +0300 Subject: [PATCH 4/9] iwlwifi: pcie: fix unused txq NULL pointer dereference Before TVQM, all TX queues were allocated straight at init. With TVQM, queues are allocated on demand and hence we need to check if a queue exists before dereferencing it. Fixes: 66128fa08806 ("iwlwifi: move to TVQM mode") Signed-off-by: Mordechai Goodstein Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index de50418adae5..034bdb4a0b06 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -298,6 +298,9 @@ void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans) for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) { struct iwl_txq *txq = trans_pcie->txq[i]; + if (!test_bit(i, trans_pcie->queue_used)) + continue; + spin_lock_bh(&txq->lock); if (txq->need_update) { iwl_pcie_txq_inc_wr_ptr(trans, txq); From 61dd8a8a6a0c3cbfb6b02ab652c4f4efb93f3d79 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 12 Jun 2017 15:10:09 +0300 Subject: [PATCH 5/9] iwlwifi: mvm: fix a NULL pointer dereference of error in recovery Sometimes, we can have an firmware crash while trying to recover from a previous firmware problem. When that happens, lots of things can go wrong. For example the stations don't get added properly to mvm->fw_id_to_mac_id. Mac80211 tries to stop A-MPDU upon reconfig but in case of a firmware crash we will bail out fairly early and in the end, we won't delete the A-MPDU Rx timeout. When that timer expired after a double firmware crash, we end up dereferencing mvm->fw_id_to_mac_id[sta_id] which is NULL. Fixes: 10b2b2019d81 ("iwlwifi: mvm: add infrastructure for tracking BA session in driver") Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 4df5f13fcdae..4a6df45b73df 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -277,6 +277,18 @@ static void iwl_mvm_rx_agg_session_expired(unsigned long data) /* Timer expired */ sta = rcu_dereference(ba_data->mvm->fw_id_to_mac_id[ba_data->sta_id]); + + /* + * sta should be valid unless the following happens: + * The firmware asserts which triggers a reconfig flow, but + * the reconfig fails before we set the pointer to sta into + * the fw_id_to_mac_id pointer table. Mac80211 can't stop + * A-MDPU and hence the timer continues to run. Then, the + * timer expires and sta is NULL. + */ + if (!sta) + goto unlock; + mvm_sta = iwl_mvm_sta_from_mac80211(sta); ieee80211_stop_rx_ba_session_offl(mvm_sta->vif, sta->addr, ba_data->tid); From 2388bd7b133504fa0991f483db66fad3a0de8694 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 14 Jun 2017 13:44:51 +0300 Subject: [PATCH 6/9] iwlwifi: missing error code in iwl_trans_pcie_alloc() We don't set the error code here so we end up returning ERR_PTR(0) which is NULL. The caller doesn't expect that so it results in a NULL dereference. Fixes: 2e5d4a8f61dc ("iwlwifi: pcie: Add new configuration to enable MSIX") Signed-off-by: Dan Carpenter Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 92b3a55d0fbc..f95eec52508e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3150,7 +3150,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, init_waitqueue_head(&trans_pcie->d0i3_waitq); if (trans_pcie->msix_enabled) { - if (iwl_pcie_init_msix_handler(pdev, trans_pcie)) + ret = iwl_pcie_init_msix_handler(pdev, trans_pcie); + if (ret) goto out_no_pci; } else { ret = iwl_pcie_alloc_ict(trans); From 5462bcd8c9dc7e7ff2dd54c3f1bb5a9a729f7a73 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 14 Jun 2017 12:21:05 +0300 Subject: [PATCH 7/9] iwlwifi: fix tracing when tx only is enabled iwl_trace_data is somewhat confusing. It returns a bool that tells if the payload of the skb should be added to the tx_data event. If it returns false, then the payload of the skb is added to the tx event. The purpose is to be able to start tracing with -e iwlwifi and record non-data packets only which saves bandwidth. Since EAPOLs are important, seldom and not real data packet (despite being WiFi data packets), they are included in tx event and thus iwl_trace_data returns false on those. This last part was buggy, and because of that, all the data packets were included in the tx event. Fix that. Fixes: 0c4cb7314d15 ("iwlwifi: tracing: decouple from mac80211") Signed-off-by: Emmanuel Grumbach Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h index 545d14b0bc92..f5c1127253cb 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h @@ -55,8 +55,8 @@ static inline bool iwl_trace_data(struct sk_buff *skb) /* also account for the RFC 1042 header, of course */ offs += 6; - return skb->len > offs + 2 && - *(__be16 *)(skb->data + offs) == cpu_to_be16(ETH_P_PAE); + return skb->len <= offs + 2 || + *(__be16 *)(skb->data + offs) != cpu_to_be16(ETH_P_PAE); } static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans, From 7b758a111819006ba64dd23aa016d42a20ba8557 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Tue, 20 Jun 2017 13:40:03 +0300 Subject: [PATCH 8/9] iwlwifi: mvm: handle IBSS probe_queue in a few missing places When IBSS was implemented for DQA, we missid a few places where it should be handled in the same way as AP. Fixes: ee48b72211f8 ("iwlwifi: mvm: support ibss in dqa mode") Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 4a6df45b73df..ab66b4394dfc 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2027,7 +2027,8 @@ int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) IWL_MAX_TID_COUNT, wdg_timeout); - if (vif->type == NL80211_IFTYPE_AP) + if (vif->type == NL80211_IFTYPE_AP || + vif->type == NL80211_IFTYPE_ADHOC) mvm->probe_queue = queue; else if (vif->type == NL80211_IFTYPE_P2P_DEVICE) mvm->p2p_dev_queue = queue; From bf8b286f86fcc66d138fd992acfa37839340218d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Jun 2017 10:48:28 +0200 Subject: [PATCH 9/9] iwlwifi: mvm: defer setting IWL_MVM_STATUS_IN_HW_RESTART MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A hardware/firmware error may happen at any point in time. In particular, it might happen while mac80211 is in the middle of a flow. We observed the following situation: * mac80211 is in authentication flow, in ieee80211_prep_connection() * iwlwifi firmware crashes, but no error can be reported at this precise point (mostly because the driver method is void, but even if it wasn't we'd just shift to a race condition) * mac80211 continues the flow, trying to add the AP station * iwlwifi has already set its internal restart flag, and so thinks that adding the station is part of the restart and already set up, so it uses the information that's supposed to already be in the struct This can happen with any flow in mac80211 and with any information we try to preserve across hardware restarts. To fix this, only set a new HW_RESTART_REQUESTED flag and translate that to IN_HW_RESTART once mac80211 actually starts the restart by calling our start() method. As a consequence, any mac80211 flow in progress at the time of the restart will properly finish (certainly with errors), before the restart is attempted. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=195299. Reported-by: djagoo Reported-by: Ɓukasz Siudut Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho --- drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 8 +++++++- drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 ++ drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 6 +++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index bcde1ba0f1c8..c7b1e58e3384 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1084,7 +1084,13 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm) lockdep_assert_held(&mvm->mutex); - if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { + if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status)) { + /* + * Now convert the HW_RESTART_REQUESTED flag to IN_HW_RESTART + * so later code will - from now on - see that we're doing it. + */ + set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); + 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 { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index eaacfaf37206..ddd8719f27b8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1090,6 +1090,7 @@ struct iwl_mvm { * @IWL_MVM_STATUS_HW_RFKILL: HW RF-kill is asserted * @IWL_MVM_STATUS_HW_CTKILL: CT-kill is active * @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 @@ -1101,6 +1102,7 @@ enum iwl_mvm_status { IWL_MVM_STATUS_HW_RFKILL, IWL_MVM_STATUS_HW_CTKILL, 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, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 4d1188b8736a..9c175d5e9d67 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1235,9 +1235,8 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) */ if (!mvm->fw_restart && fw_error) { iwl_mvm_fw_dbg_collect_desc(mvm, &iwl_mvm_dump_desc_assert, - NULL); - } else if (test_and_set_bit(IWL_MVM_STATUS_IN_HW_RESTART, - &mvm->status)) { + NULL); + } else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { struct iwl_mvm_reprobe *reprobe; IWL_ERR(mvm, @@ -1268,6 +1267,7 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) if (fw_error && mvm->fw_restart > 0) mvm->fw_restart--; + set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); ieee80211_restart_hw(mvm->hw); } }