linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sasha Levin <Alexander.Levin@microsoft.com>
To: "stable@vger.kernel.org" <stable@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Cc: Tomer Tayar <Tomer.Tayar@cavium.com>,
	Ariel Elior <Ariel.Elior@cavium.com>,
	"David S . Miller" <davem@davemloft.net>,
	Sasha Levin <Alexander.Levin@microsoft.com>
Subject: [PATCH AUTOSEL 4.14 03/25] qed: Prevent a possible deadlock during driver load and unload
Date: Thu, 20 Sep 2018 02:48:16 +0000	[thread overview]
Message-ID: <20180920024810.58594-3-alexander.levin@microsoft.com> (raw)
In-Reply-To: <20180920024810.58594-1-alexander.levin@microsoft.com>

From: Tomer Tayar <Tomer.Tayar@cavium.com>

[ Upstream commit eaa50fc59e5841910987e90b0438b2643041f508 ]

The MFW manages an internal lock to prevent concurrent hardware
(de)initialization of different PFs.
This, together with the busy-waiting for the MFW's responses for commands,
might lead to a deadlock during concurrent load or unload of PFs.
This patch adds the option to sleep within the busy-waiting, and uses it
for the (un)load requests (which are not sent from an interrupt context) to
prevent the possible deadlock.

Signed-off-by: Tomer Tayar <Tomer.Tayar@cavium.com>
Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
---
 drivers/net/ethernet/qlogic/qed/qed_mcp.c | 43 ++++++++++++++++-------
 drivers/net/ethernet/qlogic/qed/qed_mcp.h | 21 ++++++-----
 2 files changed, 44 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 5748bcb26d40..a1e1092fa3ce 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -47,7 +47,7 @@
 #include "qed_reg_addr.h"
 #include "qed_sriov.h"
 
-#define CHIP_MCP_RESP_ITER_US 10
+#define QED_MCP_RESP_ITER_US	10
 
 #define QED_DRV_MB_MAX_RETRIES	(500 * 1000)	/* Account for 5 sec */
 #define QED_MCP_RESET_RETRIES	(50 * 1000)	/* Account for 500 msec */
@@ -316,7 +316,7 @@ static void qed_mcp_reread_offsets(struct qed_hwfn *p_hwfn,
 
 int qed_mcp_reset(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
-	u32 org_mcp_reset_seq, seq, delay = CHIP_MCP_RESP_ITER_US, cnt = 0;
+	u32 org_mcp_reset_seq, seq, delay = QED_MCP_RESP_ITER_US, cnt = 0;
 	int rc = 0;
 
 	/* Ensure that only a single thread is accessing the mailbox */
@@ -448,10 +448,10 @@ static int
 _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
 		       struct qed_ptt *p_ptt,
 		       struct qed_mcp_mb_params *p_mb_params,
-		       u32 max_retries, u32 delay)
+		       u32 max_retries, u32 usecs)
 {
+	u32 cnt = 0, msecs = DIV_ROUND_UP(usecs, 1000);
 	struct qed_mcp_cmd_elem *p_cmd_elem;
-	u32 cnt = 0;
 	u16 seq_num;
 	int rc = 0;
 
@@ -474,7 +474,11 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
 			goto err;
 
 		spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock);
-		udelay(delay);
+
+		if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP))
+			msleep(msecs);
+		else
+			udelay(usecs);
 	} while (++cnt < max_retries);
 
 	if (cnt >= max_retries) {
@@ -503,7 +507,11 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
 		 * The spinlock stays locked until the list element is removed.
 		 */
 
-		udelay(delay);
+		if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP))
+			msleep(msecs);
+		else
+			udelay(usecs);
+
 		spin_lock_bh(&p_hwfn->mcp_info->cmd_lock);
 
 		if (p_cmd_elem->b_is_completed)
@@ -538,7 +546,7 @@ _qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
 		   "MFW mailbox: response 0x%08x param 0x%08x [after %d.%03d ms]\n",
 		   p_mb_params->mcp_resp,
 		   p_mb_params->mcp_param,
-		   (cnt * delay) / 1000, (cnt * delay) % 1000);
+		   (cnt * usecs) / 1000, (cnt * usecs) % 1000);
 
 	/* Clear the sequence number from the MFW response */
 	p_mb_params->mcp_resp &= FW_MSG_CODE_MASK;
@@ -556,7 +564,7 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
 {
 	size_t union_data_size = sizeof(union drv_union_data);
 	u32 max_retries = QED_DRV_MB_MAX_RETRIES;
-	u32 delay = CHIP_MCP_RESP_ITER_US;
+	u32 usecs = QED_MCP_RESP_ITER_US;
 
 	/* MCP not initialized */
 	if (!qed_mcp_is_init(p_hwfn)) {
@@ -573,8 +581,13 @@ static int qed_mcp_cmd_and_union(struct qed_hwfn *p_hwfn,
 		return -EINVAL;
 	}
 
+	if (QED_MB_FLAGS_IS_SET(p_mb_params, CAN_SLEEP)) {
+		max_retries = DIV_ROUND_UP(max_retries, 1000);
+		usecs *= 1000;
+	}
+
 	return _qed_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, max_retries,
-				      delay);
+				      usecs);
 }
 
 int qed_mcp_cmd(struct qed_hwfn *p_hwfn,
@@ -763,6 +776,7 @@ __qed_mcp_load_req(struct qed_hwfn *p_hwfn,
 	mb_params.data_src_size = sizeof(load_req);
 	mb_params.p_data_dst = &load_rsp;
 	mb_params.data_dst_size = sizeof(load_rsp);
+	mb_params.flags = QED_MB_FLAG_CAN_SLEEP;
 
 	DP_VERBOSE(p_hwfn, QED_MSG_SP,
 		   "Load Request: param 0x%08x [init_hw %d, drv_type %d, hsi_ver %d, pda 0x%04x]\n",
@@ -984,7 +998,8 @@ int qed_mcp_load_req(struct qed_hwfn *p_hwfn,
 
 int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 {
-	u32 wol_param, mcp_resp, mcp_param;
+	struct qed_mcp_mb_params mb_params;
+	u32 wol_param;
 
 	switch (p_hwfn->cdev->wol_config) {
 	case QED_OV_WOL_DISABLED:
@@ -1002,8 +1017,12 @@ int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 		wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP;
 	}
 
-	return qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_UNLOAD_REQ, wol_param,
-			   &mcp_resp, &mcp_param);
+	memset(&mb_params, 0, sizeof(mb_params));
+	mb_params.cmd = DRV_MSG_CODE_UNLOAD_REQ;
+	mb_params.param = wol_param;
+	mb_params.flags = QED_MB_FLAG_CAN_SLEEP;
+
+	return qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
 }
 
 int qed_mcp_unload_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index c7ec2395d1ce..e5d0483f3c44 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -565,14 +565,19 @@ struct qed_mcp_info {
 };
 
 struct qed_mcp_mb_params {
-	u32			cmd;
-	u32			param;
-	void			*p_data_src;
-	u8			data_src_size;
-	void			*p_data_dst;
-	u8			data_dst_size;
-	u32			mcp_resp;
-	u32			mcp_param;
+	u32 cmd;
+	u32 param;
+	void *p_data_src;
+	void *p_data_dst;
+	u8 data_src_size;
+	u8 data_dst_size;
+	u32 mcp_resp;
+	u32 mcp_param;
+	u32 flags;
+#define QED_MB_FLAG_CAN_SLEEP	(0x1 << 0)
+#define QED_MB_FLAGS_IS_SET(params, flag) \
+	({ typeof(params) __params = (params); \
+	   (__params && (__params->flags & QED_MB_FLAG_ ## flag)); })
 };
 
 /**
-- 
2.17.1

  parent reply	other threads:[~2018-09-20  2:52 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-20  2:48 [PATCH AUTOSEL 4.14 01/25] qed: Wait for ready indication before rereading the shmem Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 02/25] qed: Wait for MCP halt and resume commands to take place Sasha Levin
2018-09-20  2:48 ` Sasha Levin [this message]
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 05/25] thermal: of-thermal: disable passive polling when thermal zone is disabled Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 04/25] qed: Avoid sending mailbox commands when MFW is not responsive Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 06/25] isofs: reject hardware sector size > 2048 bytes Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 07/25] tls: possible hang when do_tcp_sendpages hits sndbuf is full case Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 08/25] bpf: sockmap: write_space events need to be passed to TCP handler Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 09/25] net: hns: fix length and page_offset overflow when CONFIG_ARM64_64K_PAGES Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 10/25] net: hns: fix skb->truesize underestimation Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 11/25] e1000: check on netif_running() before calling e1000_up() Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 12/25] e1000: ensure to free old tx/rx rings in set_ringparam() Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 13/25] crypto: cavium/nitrox - fix for command corruption in queue full case with backlog submissions Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 14/25] hwmon: (ina2xx) fix sysfs shunt resistor read access Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 15/25] hwmon: (adt7475) Make adt7475_read_word() return errors Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 16/25] Revert "ARM: dts: imx7d: Invert legacy PCI irq mapping" Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 17/25] drm/amdgpu: Enable/disable gfx PG feature in rlc safe mode Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 18/25] drm/amdgpu: Update power state at the end of smu hw_init Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 19/25] ata: ftide010: Add a quirk for SQ201 Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 20/25] nvme-fcloop: Fix dropped LS's to removed target port Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 21/25] ARM: dts: omap4-droid4: Fix emmc errors seen on some devices Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 22/25] arm/arm64: smccc-1.1: Make return values unsigned long Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 24/25] i2c: i801: Allow ACPI AML access I/O ports not reserved for SMBus Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 23/25] arm/arm64: smccc-1.1: Handle function result as parameters Sasha Levin
2018-09-20  2:48 ` [PATCH AUTOSEL 4.14 25/25] x86/pti: Fix section mismatch warning/error 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=20180920024810.58594-3-alexander.levin@microsoft.com \
    --to=alexander.levin@microsoft.com \
    --cc=Ariel.Elior@cavium.com \
    --cc=Tomer.Tayar@cavium.com \
    --cc=davem@davemloft.net \
    --cc=linux-kernel@vger.kernel.org \
    --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).