From 8a20e270f386f1a6cf183f39b8a07d9cf9d64999 Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Wed, 29 Mar 2017 13:36:36 -0700 Subject: [PATCH] net/qede/base: add API for using MFW resource lock Add base driver API for using the Management FW resource lock Signed-off-by: Rasesh Mody --- drivers/net/qede/base/ecore.h | 9 ++ drivers/net/qede/base/ecore_dcbx.h | 3 - drivers/net/qede/base/ecore_mcp.c | 143 +++++++++++++++++++++++++++++ drivers/net/qede/base/ecore_mcp.h | 41 +++++++++ 4 files changed, 193 insertions(+), 3 deletions(-) diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h index c9b1b5aa17..acf2244ca6 100644 --- a/drivers/net/qede/base/ecore.h +++ b/drivers/net/qede/base/ecore.h @@ -86,6 +86,15 @@ do { \ (((value) >> (name##_SHIFT)) & name##_MASK) #endif +#define ECORE_MFW_GET_FIELD(name, field) \ + (((name) & (field ## _MASK)) >> (field ## _SHIFT)) + +#define ECORE_MFW_SET_FIELD(name, field, value) \ +do { \ + (name) &= ~((field ## _MASK) << (field ## _SHIFT)); \ + (name) |= (((value) << (field ## _SHIFT)) & (field ## _MASK)); \ +} while (0) + static OSAL_INLINE u32 DB_ADDR(u32 cid, u32 DEMS) { u32 db_addr = FIELD_VALUE(DB_LEGACY_ADDR_DEMS, DEMS) | diff --git a/drivers/net/qede/base/ecore_dcbx.h b/drivers/net/qede/base/ecore_dcbx.h index 2ce4465977..0830014b72 100644 --- a/drivers/net/qede/base/ecore_dcbx.h +++ b/drivers/net/qede/base/ecore_dcbx.h @@ -17,9 +17,6 @@ #include "ecore_hsi_common.h" #include "ecore_dcbx_api.h" -#define ECORE_MFW_GET_FIELD(name, field) \ - (((name) & (field ## _MASK)) >> (field ## _SHIFT)) - struct ecore_dcbx_info { struct lldp_status_params_s lldp_remote[LLDP_MAX_LLDP_AGENTS]; struct lldp_config_params_s lldp_local[LLDP_MAX_LLDP_AGENTS]; diff --git a/drivers/net/qede/base/ecore_mcp.c b/drivers/net/qede/base/ecore_mcp.c index 2b9c819f90..30cb76edc5 100644 --- a/drivers/net/qede/base/ecore_mcp.c +++ b/drivers/net/qede/base/ecore_mcp.c @@ -2502,3 +2502,146 @@ enum _ecore_status_t ecore_mcp_initiate_pf_flr(struct ecore_hwfn *p_hwfn, return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_INITIATE_PF_FLR, 0, &mcp_resp, &mcp_param); } + +static enum _ecore_status_t ecore_mcp_resource_cmd(struct ecore_hwfn *p_hwfn, + struct ecore_ptt *p_ptt, + u32 param, u32 *p_mcp_resp, + u32 *p_mcp_param) +{ + enum _ecore_status_t rc; + + rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_RESOURCE_CMD, param, + p_mcp_resp, p_mcp_param); + if (rc != ECORE_SUCCESS) + return rc; + + /* A zero response implies that the resource command is not supported */ + if (!*p_mcp_resp) + return ECORE_NOTIMPL; + + if (*p_mcp_param == RESOURCE_OPCODE_UNKNOWN_CMD) { + u8 opcode = ECORE_MFW_GET_FIELD(param, RESOURCE_CMD_REQ_OPCODE); + + DP_NOTICE(p_hwfn, false, + "The resource command is unknown to the MFW [param 0x%08x, opcode %d]\n", + param, opcode); + return ECORE_INVAL; + } + + return rc; +} + +enum _ecore_status_t ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, + struct ecore_ptt *p_ptt, + u8 resource_num, u8 timeout, + bool *p_granted, u8 *p_owner) +{ + u32 param = 0, mcp_resp, mcp_param; + u8 opcode; + enum _ecore_status_t rc; + + switch (timeout) { + case ECORE_MCP_RESC_LOCK_TO_DEFAULT: + opcode = RESOURCE_OPCODE_REQ; + timeout = 0; + break; + case ECORE_MCP_RESC_LOCK_TO_NONE: + opcode = RESOURCE_OPCODE_REQ_WO_AGING; + timeout = 0; + break; + default: + opcode = RESOURCE_OPCODE_REQ_W_AGING; + break; + } + + ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_RESC, resource_num); + ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode); + ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_AGE, timeout); + + DP_VERBOSE(p_hwfn, ECORE_MSG_SP, + "Resource lock request: param 0x%08x [age %d, opcode %d, resc_num %d]\n", + param, timeout, opcode, resource_num); + + /* Attempt to acquire the resource */ + rc = ecore_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp, + &mcp_param); + if (rc != ECORE_SUCCESS) + return rc; + + /* Analyze the response */ + *p_owner = ECORE_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OWNER); + opcode = ECORE_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OPCODE); + + DP_VERBOSE(p_hwfn, ECORE_MSG_SP, + "Resource lock response: mcp_param 0x%08x [opcode %d, owner %d]\n", + mcp_param, opcode, *p_owner); + + switch (opcode) { + case RESOURCE_OPCODE_GNT: + *p_granted = true; + break; + case RESOURCE_OPCODE_BUSY: + *p_granted = false; + break; + default: + DP_NOTICE(p_hwfn, false, + "Unexpected opcode in resource lock response [mcp_param 0x%08x, opcode %d]\n", + mcp_param, opcode); + return ECORE_INVAL; + } + + return ECORE_SUCCESS; +} + +enum _ecore_status_t ecore_mcp_resc_unlock(struct ecore_hwfn *p_hwfn, + struct ecore_ptt *p_ptt, + u8 resource_num, bool force, + bool *p_released) +{ + u32 param = 0, mcp_resp, mcp_param; + u8 opcode; + enum _ecore_status_t rc; + + opcode = force ? RESOURCE_OPCODE_FORCE_RELEASE + : RESOURCE_OPCODE_RELEASE; + ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_RESC, resource_num); + ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode); + + DP_VERBOSE(p_hwfn, ECORE_MSG_SP, + "Resource unlock request: param 0x%08x [opcode %d, resc_num %d]\n", + param, opcode, resource_num); + + /* Attempt to release the resource */ + rc = ecore_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp, + &mcp_param); + if (rc != ECORE_SUCCESS) + return rc; + + /* Analyze the response */ + opcode = ECORE_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OPCODE); + + DP_VERBOSE(p_hwfn, ECORE_MSG_SP, + "Resource unlock response: mcp_param 0x%08x [opcode %d]\n", + mcp_param, opcode); + + switch (opcode) { + case RESOURCE_OPCODE_RELEASED_PREVIOUS: + DP_INFO(p_hwfn, + "Resource unlock request for an already released resource [resc_num %d]\n", + resource_num); + /* Fallthrough */ + case RESOURCE_OPCODE_RELEASED: + *p_released = true; + break; + case RESOURCE_OPCODE_WRONG_OWNER: + *p_released = false; + break; + default: + DP_NOTICE(p_hwfn, false, + "Unexpected opcode in resource unlock response [mcp_param 0x%08x, opcode %d]\n", + mcp_param, opcode); + return ECORE_INVAL; + } + + return ECORE_SUCCESS; +} diff --git a/drivers/net/qede/base/ecore_mcp.h b/drivers/net/qede/base/ecore_mcp.h index 07089239cd..7a8151617c 100644 --- a/drivers/net/qede/base/ecore_mcp.h +++ b/drivers/net/qede/base/ecore_mcp.h @@ -361,4 +361,45 @@ enum _ecore_status_t ecore_mcp_get_resc_info(struct ecore_hwfn *p_hwfn, enum _ecore_status_t ecore_mcp_initiate_pf_flr(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt); +#define ECORE_MCP_RESC_LOCK_TO_DEFAULT 0 +#define ECORE_MCP_RESC_LOCK_TO_NONE 255 + +/** + * @brief Acquires MFW generic resource lock + * + * @param p_hwfn + * @param p_ptt + * @param resource_num - valid values are 0..31 + * @param timeout - lock timeout value in seconds + * (1..254, '0' - default value, '255' - no timeout). + * @param p_granted - will be filled as true if the resource is free and + * granted, or false if it is busy. + * @param p_owner - A pointer to a variable to be filled with the resource + * owner (0..15 = PF0-15, 16 = MFW, 17 = diag over serial). + * + * @return enum _ecore_status_t - ECORE_SUCCESS - operation was successful. + */ +enum _ecore_status_t ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, + struct ecore_ptt *p_ptt, + u8 resource_num, u8 timeout, + bool *p_granted, u8 *p_owner); + +/** + * @brief Releases MFW generic resource lock + * + * @param p_hwfn + * @param p_ptt + * @param resource_num + * @param force - allows to release a reeource even if belongs to another PF + * @param p_released - will be filled as true if the resource is released (or + * has been already released), and false if the resource is + * acquired by another PF and the `force' flag was not set. + * + * @return enum _ecore_status_t - ECORE_SUCCESS - operation was successful. + */ +enum _ecore_status_t ecore_mcp_resc_unlock(struct ecore_hwfn *p_hwfn, + struct ecore_ptt *p_ptt, + u8 resource_num, bool force, + bool *p_released); + #endif /* __ECORE_MCP_H__ */ -- 2.20.1