From a474d1c1e7e545990202d676b598f4214017cd4c Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Mon, 18 Sep 2017 18:30:06 -0700 Subject: [PATCH] net/qede/base: block mbox command to unresponsive MFW Block sending of mailbox command to the management FW if it is not responsive. Use MCP_REG_CPU_STATE_SOFT_HALTED register to verify the MCP is actually halted after sending the halt command and before proceeding further. Signed-off-by: Rasesh Mody --- drivers/net/qede/base/ecore_mcp.c | 74 +++++++++++++++++++++++++++---- drivers/net/qede/base/ecore_mcp.h | 3 ++ drivers/net/qede/base/reg_addr.h | 2 + 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/drivers/net/qede/base/ecore_mcp.c b/drivers/net/qede/base/ecore_mcp.c index 21eea49682..f1010ee480 100644 --- a/drivers/net/qede/base/ecore_mcp.c +++ b/drivers/net/qede/base/ecore_mcp.c @@ -304,6 +304,12 @@ enum _ecore_status_t ecore_mcp_reset(struct ecore_hwfn *p_hwfn, delay = EMUL_MCP_RESP_ITER_US; #endif + if (p_hwfn->mcp_info->b_block_cmd) { + DP_NOTICE(p_hwfn, false, + "The MFW is not responsive. Avoid sending MCP_RESET mailbox command.\n"); + return ECORE_ABORTED; + } + /* Ensure that only a single thread is accessing the mailbox */ OSAL_SPIN_LOCK(&p_hwfn->mcp_info->cmd_lock); @@ -431,6 +437,15 @@ static void __ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn, (p_mb_params->cmd | seq_num), p_mb_params->param); } +static void ecore_mcp_cmd_set_blocking(struct ecore_hwfn *p_hwfn, + bool block_cmd) +{ + p_hwfn->mcp_info->b_block_cmd = block_cmd; + + DP_INFO(p_hwfn, "%s sending of mailbox commands to the MFW\n", + block_cmd ? "Block" : "Unblock"); +} + static enum _ecore_status_t _ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, struct ecore_mcp_mb_params *p_mb_params, @@ -513,6 +528,7 @@ _ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, ecore_mcp_cmd_del_elem(p_hwfn, p_cmd_elem); OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->cmd_lock); + ecore_mcp_cmd_set_blocking(p_hwfn, true); ecore_hw_err_notify(p_hwfn, ECORE_HW_ERR_MFW_RESP_FAIL); return ECORE_AGAIN; } @@ -567,6 +583,13 @@ ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn, return ECORE_INVAL; } + if (p_hwfn->mcp_info->b_block_cmd) { + DP_NOTICE(p_hwfn, false, + "The MFW is not responsive. Avoid sending mailbox command 0x%08x [param 0x%08x].\n", + p_mb_params->cmd, p_mb_params->param); + return ECORE_ABORTED; + } + return _ecore_mcp_cmd_and_union(p_hwfn, p_ptt, p_mb_params, max_retries, delay); } @@ -2354,33 +2377,68 @@ ecore_mcp_send_drv_version(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, return rc; } +/* A maximal 100 msec waiting time for the MCP to halt */ +#define ECORE_MCP_HALT_SLEEP_MS 10 +#define ECORE_MCP_HALT_MAX_RETRIES 10 + enum _ecore_status_t ecore_mcp_halt(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt) { + u32 resp = 0, param = 0, cpu_state, cnt = 0; enum _ecore_status_t rc; - u32 resp = 0, param = 0; rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_MCP_HALT, 0, &resp, ¶m); - if (rc != ECORE_SUCCESS) + if (rc != ECORE_SUCCESS) { DP_ERR(p_hwfn, "MCP response failure, aborting\n"); + return rc; + } - return rc; + do { + OSAL_MSLEEP(ECORE_MCP_HALT_SLEEP_MS); + cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE); + if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED) + break; + } while (++cnt < ECORE_MCP_HALT_MAX_RETRIES); + + if (cnt == ECORE_MCP_HALT_MAX_RETRIES) { + DP_NOTICE(p_hwfn, false, + "Failed to halt the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n", + ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE), cpu_state); + return ECORE_BUSY; + } + + ecore_mcp_cmd_set_blocking(p_hwfn, true); + + return ECORE_SUCCESS; } +#define ECORE_MCP_RESUME_SLEEP_MS 10 + enum _ecore_status_t ecore_mcp_resume(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt) { - u32 value, cpu_mode; + u32 cpu_mode, cpu_state; ecore_wr(p_hwfn, p_ptt, MCP_REG_CPU_STATE, 0xffffffff); - value = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); - value &= ~MCP_REG_CPU_MODE_SOFT_HALT; - ecore_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, value); cpu_mode = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE); + cpu_mode &= ~MCP_REG_CPU_MODE_SOFT_HALT; + ecore_wr(p_hwfn, p_ptt, MCP_REG_CPU_MODE, cpu_mode); + + OSAL_MSLEEP(ECORE_MCP_RESUME_SLEEP_MS); + cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE); + + if (cpu_state & MCP_REG_CPU_STATE_SOFT_HALTED) { + DP_NOTICE(p_hwfn, false, + "Failed to resume the MCP [CPU_MODE = 0x%08x, CPU_STATE = 0x%08x]\n", + cpu_mode, cpu_state); + return ECORE_BUSY; + } - return (cpu_mode & MCP_REG_CPU_MODE_SOFT_HALT) ? -1 : 0; + ecore_mcp_cmd_set_blocking(p_hwfn, false); + + return ECORE_SUCCESS; } enum _ecore_status_t diff --git a/drivers/net/qede/base/ecore_mcp.h b/drivers/net/qede/base/ecore_mcp.h index df80e11b93..f69b425961 100644 --- a/drivers/net/qede/base/ecore_mcp.h +++ b/drivers/net/qede/base/ecore_mcp.h @@ -40,6 +40,9 @@ struct ecore_mcp_info { */ osal_spinlock_t cmd_lock; + /* Flag to indicate whether sending a MFW mailbox command is blocked */ + bool b_block_cmd; + /* Spinlock used for syncing SW link-changes and link-changes * originating from attention context. */ diff --git a/drivers/net/qede/base/reg_addr.h b/drivers/net/qede/base/reg_addr.h index 9048581d0e..299efbc39e 100644 --- a/drivers/net/qede/base/reg_addr.h +++ b/drivers/net/qede/base/reg_addr.h @@ -1218,3 +1218,5 @@ #define DORQ_REG_DB_DROP_DETAILS_REL 0x100a28UL #define DORQ_REG_INT_STS_WR 0x100188UL #define DORQ_REG_DB_DROP_DETAILS_REASON 0x100a20UL +#define MCP_REG_CPU_PROGRAM_COUNTER 0xe0501cUL + #define MCP_REG_CPU_STATE_SOFT_HALTED (0x1 << 10) -- 2.20.1