net/qede/base: add API for using MFW resource lock
authorRasesh Mody <rasesh.mody@cavium.com>
Wed, 29 Mar 2017 20:36:36 +0000 (13:36 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 4 Apr 2017 17:02:52 +0000 (19:02 +0200)
Add base driver API for using the Management FW resource lock

Signed-off-by: Rasesh Mody <rasesh.mody@cavium.com>
drivers/net/qede/base/ecore.h
drivers/net/qede/base/ecore_dcbx.h
drivers/net/qede/base/ecore_mcp.c
drivers/net/qede/base/ecore_mcp.h

index c9b1b5a..acf2244 100644 (file)
@@ -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) |
index 2ce4465..0830014 100644 (file)
@@ -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];
index 2b9c819..30cb76e 100644 (file)
@@ -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;
+}
index 0708923..7a81516 100644 (file)
@@ -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__ */