net: qed: critical err reporting to management firmware

On various critical errors, notification handler should also report
the err information into the management firmware.

MFW can interact with server/motherboard backend agents - these are
used by server manufacturers to monitor server HW health.

Thus, it is important for driver to report on any faulty conditions

Signed-off-by: Ariel Elior <ariel.elior@marvell.com>
Signed-off-by: Michal Kalderon <michal.kalderon@marvell.com>
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Igor Russkikh 2020-05-14 12:57:20 +03:00 committed by David S. Miller
parent 2ec276d5b2
commit d8d6c5a7be
4 changed files with 161 additions and 0 deletions

View File

@ -12492,6 +12492,8 @@ struct public_drv_mb {
#define DRV_MSG_CODE_GET_ENGINE_CONFIG 0x00370000
#define DRV_MSG_CODE_GET_PPFID_BITMAP 0x43000000
#define DRV_MSG_CODE_DEBUG_DATA_SEND 0xc0040000
#define RESOURCE_CMD_REQ_RESC_MASK 0x0000001F
#define RESOURCE_CMD_REQ_RESC_SHIFT 0
#define RESOURCE_CMD_REQ_OPCODE_MASK 0x000000E0
@ -12626,6 +12628,17 @@ struct public_drv_mb {
#define DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE 0x00000002
#define DRV_MB_PARAM_FEATURE_SUPPORT_FUNC_VLINK 0x00010000
/* DRV_MSG_CODE_DEBUG_DATA_SEND parameters */
#define DRV_MSG_CODE_DEBUG_DATA_SEND_SIZE_OFFSET 0
#define DRV_MSG_CODE_DEBUG_DATA_SEND_SIZE_MASK 0xFF
/* Driver attributes params */
#define DRV_MB_PARAM_ATTRIBUTE_KEY_OFFSET 0
#define DRV_MB_PARAM_ATTRIBUTE_KEY_MASK 0x00FFFFFF
#define DRV_MB_PARAM_ATTRIBUTE_CMD_OFFSET 24
#define DRV_MB_PARAM_ATTRIBUTE_CMD_MASK 0xFF000000
#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_OFFSET 0
#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_SHIFT 0
#define DRV_MB_PARAM_NVM_CFG_OPTION_ID_MASK 0x0000FFFF
#define DRV_MB_PARAM_NVM_CFG_OPTION_ALL_SHIFT 16
@ -12678,6 +12691,12 @@ struct public_drv_mb {
#define FW_MSG_CODE_DRV_CFG_PF_VFS_MSIX_DONE 0x00870000
#define FW_MSG_SEQ_NUMBER_MASK 0x0000ffff
#define FW_MSG_CODE_DEBUG_DATA_SEND_INV_ARG 0xb0070000
#define FW_MSG_CODE_DEBUG_DATA_SEND_BUF_FULL 0xb0080000
#define FW_MSG_CODE_DEBUG_DATA_SEND_NO_BUF 0xb0090000
#define FW_MSG_CODE_DEBUG_NOT_ENABLED 0xb00a0000
#define FW_MSG_CODE_DEBUG_DATA_SEND_OK 0xb00b0000
u32 fw_mb_param;
#define FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_MASK 0xFFFF0000
#define FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR_SHIFT 16

View File

@ -868,6 +868,9 @@ void qed_hw_err_notify(struct qed_hwfn *p_hwfn,
}
qed_hw_error_occurred(p_hwfn, err_type);
if (fmt)
qed_mcp_send_raw_debug_data(p_hwfn, p_ptt, buf, len);
}
int qed_dmae_sanity(struct qed_hwfn *p_hwfn,

View File

@ -3821,3 +3821,127 @@ int qed_mcp_nvm_set_cfg(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
DRV_MSG_CODE_SET_NVM_CFG_OPTION,
mb_param, &resp, &param, len, (u32 *)p_buf);
}
#define QED_MCP_DBG_DATA_MAX_SIZE MCP_DRV_NVM_BUF_LEN
#define QED_MCP_DBG_DATA_MAX_HEADER_SIZE sizeof(u32)
#define QED_MCP_DBG_DATA_MAX_PAYLOAD_SIZE \
(QED_MCP_DBG_DATA_MAX_SIZE - QED_MCP_DBG_DATA_MAX_HEADER_SIZE)
static int
__qed_mcp_send_debug_data(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u8 *p_buf, u8 size)
{
struct qed_mcp_mb_params mb_params;
int rc;
if (size > QED_MCP_DBG_DATA_MAX_SIZE) {
DP_ERR(p_hwfn,
"Debug data size is %d while it should not exceed %d\n",
size, QED_MCP_DBG_DATA_MAX_SIZE);
return -EINVAL;
}
memset(&mb_params, 0, sizeof(mb_params));
mb_params.cmd = DRV_MSG_CODE_DEBUG_DATA_SEND;
SET_MFW_FIELD(mb_params.param, DRV_MSG_CODE_DEBUG_DATA_SEND_SIZE, size);
mb_params.p_data_src = p_buf;
mb_params.data_src_size = size;
rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
if (rc)
return rc;
if (mb_params.mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
DP_INFO(p_hwfn,
"The DEBUG_DATA_SEND command is unsupported by the MFW\n");
return -EOPNOTSUPP;
} else if (mb_params.mcp_resp == (u32)FW_MSG_CODE_DEBUG_NOT_ENABLED) {
DP_INFO(p_hwfn, "The DEBUG_DATA_SEND command is not enabled\n");
return -EBUSY;
} else if (mb_params.mcp_resp != (u32)FW_MSG_CODE_DEBUG_DATA_SEND_OK) {
DP_NOTICE(p_hwfn,
"Failed to send debug data to the MFW [resp 0x%08x]\n",
mb_params.mcp_resp);
return -EINVAL;
}
return 0;
}
enum qed_mcp_dbg_data_type {
QED_MCP_DBG_DATA_TYPE_RAW,
};
/* Header format: [31:28] PFID, [27:20] flags, [19:12] type, [11:0] S/N */
#define QED_MCP_DBG_DATA_HDR_SN_OFFSET 0
#define QED_MCP_DBG_DATA_HDR_SN_MASK 0x00000fff
#define QED_MCP_DBG_DATA_HDR_TYPE_OFFSET 12
#define QED_MCP_DBG_DATA_HDR_TYPE_MASK 0x000ff000
#define QED_MCP_DBG_DATA_HDR_FLAGS_OFFSET 20
#define QED_MCP_DBG_DATA_HDR_FLAGS_MASK 0x0ff00000
#define QED_MCP_DBG_DATA_HDR_PF_OFFSET 28
#define QED_MCP_DBG_DATA_HDR_PF_MASK 0xf0000000
#define QED_MCP_DBG_DATA_HDR_FLAGS_FIRST 0x1
#define QED_MCP_DBG_DATA_HDR_FLAGS_LAST 0x2
static int
qed_mcp_send_debug_data(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
enum qed_mcp_dbg_data_type type, u8 *p_buf, u32 size)
{
u8 raw_data[QED_MCP_DBG_DATA_MAX_SIZE], *p_tmp_buf = p_buf;
u32 tmp_size = size, *p_header, *p_payload;
u8 flags = 0;
u16 seq;
int rc;
p_header = (u32 *)raw_data;
p_payload = (u32 *)(raw_data + QED_MCP_DBG_DATA_MAX_HEADER_SIZE);
seq = (u16)atomic_inc_return(&p_hwfn->mcp_info->dbg_data_seq);
/* First chunk is marked as 'first' */
flags |= QED_MCP_DBG_DATA_HDR_FLAGS_FIRST;
*p_header = 0;
SET_MFW_FIELD(*p_header, QED_MCP_DBG_DATA_HDR_SN, seq);
SET_MFW_FIELD(*p_header, QED_MCP_DBG_DATA_HDR_TYPE, type);
SET_MFW_FIELD(*p_header, QED_MCP_DBG_DATA_HDR_FLAGS, flags);
SET_MFW_FIELD(*p_header, QED_MCP_DBG_DATA_HDR_PF, p_hwfn->abs_pf_id);
while (tmp_size > QED_MCP_DBG_DATA_MAX_PAYLOAD_SIZE) {
memcpy(p_payload, p_tmp_buf, QED_MCP_DBG_DATA_MAX_PAYLOAD_SIZE);
rc = __qed_mcp_send_debug_data(p_hwfn, p_ptt, raw_data,
QED_MCP_DBG_DATA_MAX_SIZE);
if (rc)
return rc;
/* Clear the 'first' marking after sending the first chunk */
if (p_tmp_buf == p_buf) {
flags &= ~QED_MCP_DBG_DATA_HDR_FLAGS_FIRST;
SET_MFW_FIELD(*p_header, QED_MCP_DBG_DATA_HDR_FLAGS,
flags);
}
p_tmp_buf += QED_MCP_DBG_DATA_MAX_PAYLOAD_SIZE;
tmp_size -= QED_MCP_DBG_DATA_MAX_PAYLOAD_SIZE;
}
/* Last chunk is marked as 'last' */
flags |= QED_MCP_DBG_DATA_HDR_FLAGS_LAST;
SET_MFW_FIELD(*p_header, QED_MCP_DBG_DATA_HDR_FLAGS, flags);
memcpy(p_payload, p_tmp_buf, tmp_size);
/* Casting the left size to u8 is ok since at this point it is <= 32 */
return __qed_mcp_send_debug_data(p_hwfn, p_ptt, raw_data,
(u8)(QED_MCP_DBG_DATA_MAX_HEADER_SIZE +
tmp_size));
}
int
qed_mcp_send_raw_debug_data(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u8 *p_buf, u32 size)
{
return qed_mcp_send_debug_data(p_hwfn, p_ptt,
QED_MCP_DBG_DATA_TYPE_RAW, p_buf, size);
}

View File

@ -685,6 +685,18 @@ int qed_mcp_bist_nvm_get_image_att(struct qed_hwfn *p_hwfn,
*/
int qed_mfw_process_tlv_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
/**
* @brief Send raw debug data to the MFW
*
* @param p_hwfn
* @param p_ptt
* @param p_buf - raw debug data buffer
* @param size - buffer size
*/
int
qed_mcp_send_raw_debug_data(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt, u8 *p_buf, u32 size);
/* Using hwfn number (and not pf_num) is required since in CMT mode,
* same pf_num may be used by two different hwfn
* TODO - this shouldn't really be in .h file, but until all fields
@ -731,6 +743,9 @@ struct qed_mcp_info {
/* Capabilties negotiated with the MFW */
u32 capabilities;
/* S/N for debug data mailbox commands */
atomic_t dbg_data_seq;
};
struct qed_mcp_mb_params {