From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Stefan Assmann <sassmann@kpanic.de>,
Konrad Jankowski <konrad0.jankowski@intel.com>,
Tony Nguyen <anthony.l.nguyen@intel.com>,
Sasha Levin <sashal@kernel.org>,
intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org
Subject: [PATCH AUTOSEL 5.10 013/176] iavf: fix locking of critical sections
Date: Thu, 9 Sep 2021 07:48:35 -0400 [thread overview]
Message-ID: <20210909115118.146181-13-sashal@kernel.org> (raw)
In-Reply-To: <20210909115118.146181-1-sashal@kernel.org>
From: Stefan Assmann <sassmann@kpanic.de>
[ Upstream commit 226d528512cfac890a1619aea4301f3dd314fe60 ]
To avoid races between iavf_init_task(), iavf_reset_task(),
iavf_watchdog_task(), iavf_adminq_task() as well as the shutdown and
remove functions more locking is required.
The current protection by __IAVF_IN_CRITICAL_TASK is needed in
additional places.
- The reset task performs state transitions, therefore needs locking.
- The adminq task acts on replies from the PF in
iavf_virtchnl_completion() which may alter the states.
- The init task is not only run during probe but also if a VF gets stuck
to reinitialize it.
- The shutdown function performs a state transition.
- The remove function performs a state transition and also free's
resources.
iavf_lock_timeout() is introduced to avoid waiting infinitely
and cause a deadlock. Rather unlock and print a warning.
Signed-off-by: Stefan Assmann <sassmann@kpanic.de>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/intel/iavf/iavf_main.c | 57 ++++++++++++++++++---
1 file changed, 50 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index da401d5694bf..f06c079e812e 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -131,6 +131,30 @@ enum iavf_status iavf_free_virt_mem_d(struct iavf_hw *hw,
return 0;
}
+/**
+ * iavf_lock_timeout - try to set bit but give up after timeout
+ * @adapter: board private structure
+ * @bit: bit to set
+ * @msecs: timeout in msecs
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int iavf_lock_timeout(struct iavf_adapter *adapter,
+ enum iavf_critical_section_t bit,
+ unsigned int msecs)
+{
+ unsigned int wait, delay = 10;
+
+ for (wait = 0; wait < msecs; wait += delay) {
+ if (!test_and_set_bit(bit, &adapter->crit_section))
+ return 0;
+
+ msleep(delay);
+ }
+
+ return -1;
+}
+
/**
* iavf_schedule_reset - Set the flags and schedule a reset event
* @adapter: board private structure
@@ -2064,6 +2088,10 @@ static void iavf_reset_task(struct work_struct *work)
if (test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
return;
+ if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 200)) {
+ schedule_work(&adapter->reset_task);
+ return;
+ }
while (test_and_set_bit(__IAVF_IN_CLIENT_TASK,
&adapter->crit_section))
usleep_range(500, 1000);
@@ -2278,6 +2306,8 @@ static void iavf_adminq_task(struct work_struct *work)
if (!event.msg_buf)
goto out;
+ if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 200))
+ goto freedom;
do {
ret = iavf_clean_arq_element(hw, &event, &pending);
v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
@@ -2291,6 +2321,7 @@ static void iavf_adminq_task(struct work_struct *work)
if (pending != 0)
memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
} while (pending);
+ clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
if ((adapter->flags &
(IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
@@ -3593,6 +3624,10 @@ static void iavf_init_task(struct work_struct *work)
init_task.work);
struct iavf_hw *hw = &adapter->hw;
+ if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 5000)) {
+ dev_warn(&adapter->pdev->dev, "failed to set __IAVF_IN_CRITICAL_TASK in %s\n", __FUNCTION__);
+ return;
+ }
switch (adapter->state) {
case __IAVF_STARTUP:
if (iavf_startup(adapter) < 0)
@@ -3605,14 +3640,14 @@ static void iavf_init_task(struct work_struct *work)
case __IAVF_INIT_GET_RESOURCES:
if (iavf_init_get_resources(adapter) < 0)
goto init_failed;
- return;
+ goto out;
default:
goto init_failed;
}
queue_delayed_work(iavf_wq, &adapter->init_task,
msecs_to_jiffies(30));
- return;
+ goto out;
init_failed:
if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) {
dev_err(&adapter->pdev->dev,
@@ -3621,9 +3656,11 @@ static void iavf_init_task(struct work_struct *work)
iavf_shutdown_adminq(hw);
adapter->state = __IAVF_STARTUP;
queue_delayed_work(iavf_wq, &adapter->init_task, HZ * 5);
- return;
+ goto out;
}
queue_delayed_work(iavf_wq, &adapter->init_task, HZ);
+out:
+ clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
}
/**
@@ -3640,9 +3677,12 @@ static void iavf_shutdown(struct pci_dev *pdev)
if (netif_running(netdev))
iavf_close(netdev);
+ if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 5000))
+ dev_warn(&adapter->pdev->dev, "failed to set __IAVF_IN_CRITICAL_TASK in %s\n", __FUNCTION__);
/* Prevent the watchdog from running. */
adapter->state = __IAVF_REMOVE;
adapter->aq_required = 0;
+ clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
#ifdef CONFIG_PM
pci_save_state(pdev);
@@ -3870,10 +3910,6 @@ static void iavf_remove(struct pci_dev *pdev)
err);
}
- /* Shut down all the garbage mashers on the detention level */
- adapter->state = __IAVF_REMOVE;
- adapter->aq_required = 0;
- adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
iavf_request_reset(adapter);
msleep(50);
/* If the FW isn't responding, kick it once, but only once. */
@@ -3881,6 +3917,13 @@ static void iavf_remove(struct pci_dev *pdev)
iavf_request_reset(adapter);
msleep(50);
}
+ if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 5000))
+ dev_warn(&adapter->pdev->dev, "failed to set __IAVF_IN_CRITICAL_TASK in %s\n", __FUNCTION__);
+
+ /* Shut down all the garbage mashers on the detention level */
+ adapter->state = __IAVF_REMOVE;
+ adapter->aq_required = 0;
+ adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
iavf_free_all_tx_resources(adapter);
iavf_free_all_rx_resources(adapter);
iavf_misc_irq_disable(adapter);
--
2.30.2
next prev parent reply other threads:[~2021-09-09 12:32 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20210909115118.146181-1-sashal@kernel.org>
2021-09-09 11:48 ` [PATCH AUTOSEL 5.10 005/176] libbpf: Fix reuse of pinned map on older kernel Sasha Levin
2021-09-09 11:48 ` [PATCH AUTOSEL 5.10 009/176] tipc: keep the skb in rcv queue until the whole data is read Sasha Levin
2021-09-09 11:48 ` [PATCH AUTOSEL 5.10 010/176] net: phy: Fix data type in DP83822 dp8382x_disable_wol() Sasha Levin
2021-09-09 11:48 ` [PATCH AUTOSEL 5.10 012/176] iavf: do not override the adapter state in the watchdog task Sasha Levin
2021-09-09 11:48 ` Sasha Levin [this message]
2021-09-09 11:48 ` [PATCH AUTOSEL 5.10 016/176] netlink: Deal with ESRCH error in nlmsg_notify() Sasha Levin
2021-09-09 11:48 ` [PATCH AUTOSEL 5.10 022/176] igc: Check if num of q_vectors is smaller than max before array access Sasha Levin
2021-09-09 11:48 ` [PATCH AUTOSEL 5.10 037/176] nfp: fix return statement in nfp_net_parse_meta() Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 039/176] ethtool: improve compat ioctl handling Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 042/176] bpf/tests: Fix copy-and-paste error in double word test Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 043/176] bpf/tests: Do not PASS tests without actually testing the result Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 049/176] ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs() Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 050/176] flow_dissector: Fix out-of-bounds warnings Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 058/176] samples: bpf: Fix tracex7 error raised on the missing argument Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 059/176] libbpf: Fix race when pinning maps in parallel Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 062/176] Bluetooth: skip invalid hci_sync_conn_complete_evt Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 067/176] bonding: 3ad: fix the concurrency between __bond_release_one() and bond_3ad_state_machine_handler() Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 071/176] bpf: Fix off-by-one in tail call count limiting Sasha Levin
2021-09-09 11:49 ` [PATCH AUTOSEL 5.10 091/176] net: ethernet: stmmac: Do not use unreachable() in ipq806x_gmac_probe() Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 099/176] selftests/bpf: Fix xdp_tx.c prog section name Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 101/176] Bluetooth: schedule SCO timeouts with delayed_work Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 102/176] Bluetooth: avoid circular locks in sco_sock_connect Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 104/176] net/mlx5: Fix variable type to match 64bit Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 107/176] mac80211: Fix monitor MTU limit so that A-MSDUs get through Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 115/176] Bluetooth: Fix handling of LE Enhanced Connection Complete Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 119/176] tcp: enable data-less, empty-cookie SYN with TFO_SERVER_COOKIE_NOT_REQD Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 120/176] rpc: fix gss_svc_init cleanup on failure Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 121/176] selftests/bpf: Fix flaky send_signal test Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 124/176] net: Fix offloading indirect devices dependency on qdisc order creation Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 131/176] rtl8xxxu: Fix the handling of TX A-MPDU aggregation Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 132/176] rtw88: use read_poll_timeout instead of fixed sleep Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 133/176] rtw88: wow: build wow function only if CONFIG_PM is on Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 134/176] rtw88: wow: fix size access error of probe request Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 135/176] octeontx2-pf: Fix NIX1_RX interface backpressure Sasha Levin
2021-09-09 11:50 ` [PATCH AUTOSEL 5.10 149/176] selftests/bpf: Enlarge select() timeout for test_maps Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 160/176] iwlwifi: pcie: free RBs during configure Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 161/176] iwlwifi: mvm: fix a memory leak in iwl_mvm_mac_ctxt_beacon_changed Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 162/176] iwlwifi: mvm: avoid static queue number aliasing Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 163/176] iwlwifi: mvm: fix access to BSS elements Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 164/176] iwlwifi: fw: correctly limit to monitor dump Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 165/176] iwlwifi: mvm: Fix scan channel flags settings Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 166/176] net/mlx5: DR, fix a potential use-after-free bug Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 167/176] net/mlx5: DR, Enable QP retransmission Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 169/176] selftests/bpf: Fix potential unreleased lock Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 170/176] wcn36xx: Fix missing frame timestamp for beacon/probe-resp Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 171/176] ath9k: fix OOB read ar9300_eeprom_restore_internal Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 172/176] ath9k: fix sleeping in atomic context Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 173/176] net: fix NULL pointer reference in cipso_v4_doi_free Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 174/176] fix array-index-out-of-bounds in taprio_change Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 175/176] net: w5100: check return value after calling platform_get_resource() Sasha Levin
2021-09-09 11:51 ` [PATCH AUTOSEL 5.10 176/176] net: hns3: clean up a type mismatch warning 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=20210909115118.146181-13-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=anthony.l.nguyen@intel.com \
--cc=intel-wired-lan@lists.osuosl.org \
--cc=konrad0.jankowski@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=sassmann@kpanic.de \
--cc=stable@vger.kernel.org \
/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).