From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Johannes Berg <johannes.berg@intel.com>,
Benjamin Berg <benjamin.berg@intel.com>,
Jose Ignacio Tornos Martinez <jtornosm@redhat.com>,
Sasha Levin <sashal@kernel.org>,
gregory.greenman@intel.com, kvalo@kernel.org,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, avraham.stern@intel.com,
miriam.rachel.korenblit@intel.com, shaul.triebitz@intel.com,
quic_srirrama@quicinc.com, haim.dreyfuss@intel.com,
ilan.peer@intel.com, keescook@chromium.org,
daniel.lezcano@linaro.org, yedidya.ben.shimol@intel.com,
mordechay.goodstein@intel.com, rostedt@goodmis.org,
linux-wireless@vger.kernel.org, netdev@vger.kernel.org
Subject: [PATCH AUTOSEL 6.2 21/25] wifi: iwlwifi: mvm: protect TXQ list manipulation
Date: Fri, 31 Mar 2023 21:41:19 -0400 [thread overview]
Message-ID: <20230401014126.3356410-21-sashal@kernel.org> (raw)
In-Reply-To: <20230401014126.3356410-1-sashal@kernel.org>
From: Johannes Berg <johannes.berg@intel.com>
[ Upstream commit 923bf981eb6ecc027227716e30701bdcc1845fbf ]
Some recent upstream debugging uncovered the fact that in
iwlwifi, the TXQ list manipulation is racy.
Introduce a new state bit for when the TXQ is completely
ready and can be used without locking, and if that's not
set yet acquire the lock to check everything correctly.
Reviewed-by: Benjamin Berg <benjamin.berg@intel.com>
Tested-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../net/wireless/intel/iwlwifi/mvm/mac80211.c | 45 ++++++-------------
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 2 +
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 1 +
drivers/net/wireless/intel/iwlwifi/mvm/sta.c | 25 +++++++++--
4 files changed, 39 insertions(+), 34 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
index 5b4974181ff1c..1d46a2b345eb3 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -760,42 +760,25 @@ static void iwl_mvm_mac_wake_tx_queue(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_txq *mvmtxq = iwl_mvm_txq_from_mac80211(txq);
- /*
- * Please note that racing is handled very carefully here:
- * mvmtxq->txq_id is updated during allocation, and mvmtxq->list is
- * deleted afterwards.
- * This means that if:
- * mvmtxq->txq_id != INVALID_QUEUE && list_empty(&mvmtxq->list):
- * queue is allocated and we can TX.
- * mvmtxq->txq_id != INVALID_QUEUE && !list_empty(&mvmtxq->list):
- * a race, should defer the frame.
- * mvmtxq->txq_id == INVALID_QUEUE && list_empty(&mvmtxq->list):
- * need to allocate the queue and defer the frame.
- * mvmtxq->txq_id == INVALID_QUEUE && !list_empty(&mvmtxq->list):
- * queue is already scheduled for allocation, no need to allocate,
- * should defer the frame.
- */
-
- /* If the queue is allocated TX and return. */
- if (!txq->sta || mvmtxq->txq_id != IWL_MVM_INVALID_QUEUE) {
- /*
- * Check that list is empty to avoid a race where txq_id is
- * already updated, but the queue allocation work wasn't
- * finished
- */
- if (unlikely(txq->sta && !list_empty(&mvmtxq->list)))
- return;
-
+ if (likely(test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) ||
+ !txq->sta) {
iwl_mvm_mac_itxq_xmit(hw, txq);
return;
}
- /* The list is being deleted only after the queue is fully allocated. */
- if (!list_empty(&mvmtxq->list))
- return;
+ /* iwl_mvm_mac_itxq_xmit() will later be called by the worker
+ * to handle any packets we leave on the txq now
+ */
- list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
- schedule_work(&mvm->add_stream_wk);
+ spin_lock_bh(&mvm->add_stream_lock);
+ /* The list is being deleted only after the queue is fully allocated. */
+ if (list_empty(&mvmtxq->list) &&
+ /* recheck under lock */
+ !test_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state)) {
+ list_add_tail(&mvmtxq->list, &mvm->add_stream_txqs);
+ schedule_work(&mvm->add_stream_wk);
+ }
+ spin_unlock_bh(&mvm->add_stream_lock);
}
#define CHECK_BA_TRIGGER(_mvm, _trig, _tid_bm, _tid, _fmt...) \
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 3146b3d02bae8..157de77e129e4 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -731,6 +731,7 @@ struct iwl_mvm_txq {
atomic_t tx_request;
#define IWL_MVM_TXQ_STATE_STOP_FULL 0
#define IWL_MVM_TXQ_STATE_STOP_REDIRECT 1
+#define IWL_MVM_TXQ_STATE_READY 2
unsigned long state;
};
@@ -829,6 +830,7 @@ struct iwl_mvm {
struct iwl_mvm_tvqm_txq_info tvqm_info[IWL_MAX_TVQM_QUEUES];
};
struct work_struct add_stream_wk; /* To add streams to queues */
+ spinlock_t add_stream_lock;
const char *nvm_file_name;
struct iwl_nvm_data *nvm_data;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index f43e617fb451f..c49a2a1ee4867 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -1194,6 +1194,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
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->add_stream_lock);
init_waitqueue_head(&mvm->rx_sync_waitq);
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 21ad7b85c434c..9caae77995ca9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -384,8 +384,11 @@ static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct iwl_mvm_txq *mvmtxq =
iwl_mvm_txq_from_tid(sta, tid);
- mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+ spin_lock_bh(&mvm->add_stream_lock);
list_del_init(&mvmtxq->list);
+ clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+ mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+ spin_unlock_bh(&mvm->add_stream_lock);
}
/* Regardless if this is a reserved TXQ for a STA - mark it as false */
@@ -479,8 +482,11 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)
disable_agg_tids |= BIT(tid);
mvmsta->tid_data[tid].txq_id = IWL_MVM_INVALID_QUEUE;
- mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+ spin_lock_bh(&mvm->add_stream_lock);
list_del_init(&mvmtxq->list);
+ clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+ mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+ spin_unlock_bh(&mvm->add_stream_lock);
}
mvmsta->tfd_queue_msk &= ~BIT(queue); /* Don't use this queue anymore */
@@ -1444,12 +1450,22 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk)
* a queue in the function itself.
*/
if (iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid)) {
+ spin_lock_bh(&mvm->add_stream_lock);
list_del_init(&mvmtxq->list);
+ spin_unlock_bh(&mvm->add_stream_lock);
continue;
}
- list_del_init(&mvmtxq->list);
+ /* now we're ready, any remaining races/concurrency will be
+ * handled in iwl_mvm_mac_itxq_xmit()
+ */
+ set_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+
local_bh_disable();
+ spin_lock(&mvm->add_stream_lock);
+ list_del_init(&mvmtxq->list);
+ spin_unlock(&mvm->add_stream_lock);
+
iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
local_bh_enable();
}
@@ -1864,8 +1880,11 @@ static void iwl_mvm_disable_sta_queues(struct iwl_mvm *mvm,
struct iwl_mvm_txq *mvmtxq =
iwl_mvm_txq_from_mac80211(sta->txq[i]);
+ spin_lock_bh(&mvm->add_stream_lock);
mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
list_del_init(&mvmtxq->list);
+ clear_bit(IWL_MVM_TXQ_STATE_READY, &mvmtxq->state);
+ spin_unlock_bh(&mvm->add_stream_lock);
}
}
--
2.39.2
next prev parent reply other threads:[~2023-04-01 1:44 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-01 1:40 [PATCH AUTOSEL 6.2 01/25] ARM: 9290/1: uaccess: Fix KASAN false-positives Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 02/25] ARM: dts: qcom: apq8026-lg-lenok: add missing reserved memory Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 03/25] arm64: dts: qcom: sa8540p-ride: correct name of remoteproc_nsp0 firmware Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 04/25] power: supply: rk817: Fix unsigned comparison with less than zero Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 05/25] power: supply: cros_usbpd: reclassify "default case!" as debug Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 06/25] power: supply: axp288_fuel_gauge: Added check for negative values Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 07/25] selftests/bpf: Fix progs/find_vma_fail1.c build error Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 08/25] wifi: mwifiex: mark OF related data as maybe unused Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 09/25] i2c: imx-lpi2c: clean rx/tx buffers upon new message Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 10/25] i2c: hisi: Avoid redundant interrupts Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 11/25] efi: sysfb_efi: Add quirk for Lenovo Yoga Book X91F/L Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 12/25] block: ublk_drv: mark device as LIVE before adding disk Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 13/25] ACPI: video: Add backlight=native DMI quirk for Acer Aspire 3830TG Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 14/25] drm: panel-orientation-quirks: Add quirk for Lenovo Yoga Book X90F Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 15/25] hwmon: (peci/cputemp) Fix miscalculated DTS for SKX Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 16/25] hwmon: (xgene) Fix ioremap and memremap leak Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 17/25] verify_pefile: relax wrapper length check Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 18/25] asymmetric_keys: log on fatal failures in PE/pkcs7 Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 19/25] nvme: send Identify with CNS 06h only to I/O controllers Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 20/25] wifi: iwlwifi: mvm: fix mvmtxq->stopped handling Sasha Levin
2023-04-01 1:41 ` Sasha Levin [this message]
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 22/25] drm/amdgpu: add mes resume when do gfx post soft reset Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 23/25] drm/amdgpu: Force signal hw_fences that are embedded in non-sched jobs Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 24/25] drm/amdgpu/gfx: set cg flags to enter/exit safe mode Sasha Levin
2023-04-01 1:41 ` [PATCH AUTOSEL 6.2 25/25] ACPI: resource: Add Medion S17413 to IRQ override quirk Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230401014126.3356410-21-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=avraham.stern@intel.com \
--cc=benjamin.berg@intel.com \
--cc=daniel.lezcano@linaro.org \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=gregory.greenman@intel.com \
--cc=haim.dreyfuss@intel.com \
--cc=ilan.peer@intel.com \
--cc=johannes.berg@intel.com \
--cc=jtornosm@redhat.com \
--cc=keescook@chromium.org \
--cc=kuba@kernel.org \
--cc=kvalo@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=miriam.rachel.korenblit@intel.com \
--cc=mordechay.goodstein@intel.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=quic_srirrama@quicinc.com \
--cc=rostedt@goodmis.org \
--cc=shaul.triebitz@intel.com \
--cc=stable@vger.kernel.org \
--cc=yedidya.ben.shimol@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).