net/qede/base: set max values for soft resources
authorRasesh Mody <rasesh.mody@cavium.com>
Wed, 29 Mar 2017 20:36:48 +0000 (13:36 -0700)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 4 Apr 2017 17:02:53 +0000 (19:02 +0200)
Add support for the new interface with the Management FW for setting
max values of "soft" resources.

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

index 25b6c4e..7379b3f 100644 (file)
@@ -856,4 +856,6 @@ u16 ecore_init_qm_get_num_pqs(struct ecore_hwfn *p_hwfn);
 
 #define ECORE_LEADING_HWFN(dev)        (&dev->hwfns[0])
 
+const char *ecore_hw_get_resc_name(enum ecore_resources res_id);
+
 #endif /* __ECORE_H */
index d5a8a90..3191ee4 100644 (file)
@@ -2420,64 +2420,109 @@ static void ecore_hw_set_feat(struct ecore_hwfn *p_hwfn)
                   RESC_NUM(p_hwfn, ECORE_SB));
 }
 
-static enum resource_id_enum
-ecore_hw_get_mfw_res_id(enum ecore_resources res_id)
+const char *ecore_hw_get_resc_name(enum ecore_resources res_id)
 {
-       enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID;
-
        switch (res_id) {
        case ECORE_SB:
-               mfw_res_id = RESOURCE_NUM_SB_E;
-               break;
+               return "SB";
        case ECORE_L2_QUEUE:
-               mfw_res_id = RESOURCE_NUM_L2_QUEUE_E;
-               break;
+               return "L2_QUEUE";
        case ECORE_VPORT:
-               mfw_res_id = RESOURCE_NUM_VPORT_E;
-               break;
+               return "VPORT";
        case ECORE_RSS_ENG:
-               mfw_res_id = RESOURCE_NUM_RSS_ENGINES_E;
-               break;
+               return "RSS_ENG";
        case ECORE_PQ:
-               mfw_res_id = RESOURCE_NUM_PQ_E;
-               break;
+               return "PQ";
        case ECORE_RL:
-               mfw_res_id = RESOURCE_NUM_RL_E;
-               break;
+               return "RL";
        case ECORE_MAC:
+               return "MAC";
        case ECORE_VLAN:
-               /* Each VFC resource can accommodate both a MAC and a VLAN */
-               mfw_res_id = RESOURCE_VFC_FILTER_E;
-               break;
+               return "VLAN";
+       case ECORE_RDMA_CNQ_RAM:
+               return "RDMA_CNQ_RAM";
        case ECORE_ILT:
-               mfw_res_id = RESOURCE_ILT_E;
-               break;
+               return "ILT";
        case ECORE_LL2_QUEUE:
-               mfw_res_id = RESOURCE_LL2_QUEUE_E;
-               break;
-       case ECORE_RDMA_CNQ_RAM:
+               return "LL2_QUEUE";
        case ECORE_CMDQS_CQS:
-               /* CNQ/CMDQS are the same resource */
-               mfw_res_id = RESOURCE_CQS_E;
-               break;
+               return "CMDQS_CQS";
        case ECORE_RDMA_STATS_QUEUE:
-               mfw_res_id = RESOURCE_RDMA_STATS_QUEUE_E;
-               break;
+               return "RDMA_STATS_QUEUE";
        case ECORE_BDQ:
-               mfw_res_id = RESOURCE_BDQ_E;
-               break;
+               return "BDQ";
        default:
-               break;
+               return "UNKNOWN_RESOURCE";
        }
+}
 
-       return mfw_res_id;
+static enum _ecore_status_t
+__ecore_hw_set_soft_resc_size(struct ecore_hwfn *p_hwfn,
+                             enum ecore_resources res_id, u32 resc_max_val,
+                             u32 *p_mcp_resp)
+{
+       enum _ecore_status_t rc;
+
+       rc = ecore_mcp_set_resc_max_val(p_hwfn, p_hwfn->p_main_ptt, res_id,
+                                       resc_max_val, p_mcp_resp);
+       if (rc != ECORE_SUCCESS) {
+               DP_NOTICE(p_hwfn, true,
+                         "MFW response failure for a max value setting of resource %d [%s]\n",
+                         res_id, ecore_hw_get_resc_name(res_id));
+               return rc;
+       }
+
+       if (*p_mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK)
+               DP_INFO(p_hwfn,
+                       "Failed to set the max value of resource %d [%s]. mcp_resp = 0x%08x.\n",
+                       res_id, ecore_hw_get_resc_name(res_id), *p_mcp_resp);
+
+       return ECORE_SUCCESS;
+}
+
+static enum _ecore_status_t
+ecore_hw_set_soft_resc_size(struct ecore_hwfn *p_hwfn)
+{
+       bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
+       u32 resc_max_val, mcp_resp;
+       u8 res_id;
+       enum _ecore_status_t rc;
+
+       for (res_id = 0; res_id < ECORE_MAX_RESC; res_id++) {
+               /* @DPDK */
+               switch (res_id) {
+               case ECORE_LL2_QUEUE:
+               case ECORE_RDMA_CNQ_RAM:
+               case ECORE_RDMA_STATS_QUEUE:
+               case ECORE_BDQ:
+                       resc_max_val = 0;
+                       break;
+               default:
+                       continue;
+               }
+
+               rc = __ecore_hw_set_soft_resc_size(p_hwfn, res_id,
+                                                  resc_max_val, &mcp_resp);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+
+               /* There's no point to continue to the next resource if the
+                * command is not supported by the MFW.
+                * We do continue if the command is supported but the resource
+                * is unknown to the MFW. Such a resource will be later
+                * configured with the default allocation values.
+                */
+               if (mcp_resp == FW_MSG_CODE_UNSUPPORTED)
+                       return ECORE_NOTIMPL;
+       }
+
+       return ECORE_SUCCESS;
 }
 
 static
 enum _ecore_status_t ecore_hw_get_dflt_resc(struct ecore_hwfn *p_hwfn,
                                            enum ecore_resources res_id,
-                                           u32 *p_resc_num,
-                                           u32 *p_resc_start)
+                                           u32 *p_resc_num, u32 *p_resc_start)
 {
        u8 num_funcs = p_hwfn->num_funcs_on_engine;
        bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
@@ -2553,56 +2598,19 @@ enum _ecore_status_t ecore_hw_get_dflt_resc(struct ecore_hwfn *p_hwfn,
        return ECORE_SUCCESS;
 }
 
-static const char *ecore_hw_get_resc_name(enum ecore_resources res_id)
-{
-       switch (res_id) {
-       case ECORE_SB:
-               return "SB";
-       case ECORE_L2_QUEUE:
-               return "L2_QUEUE";
-       case ECORE_VPORT:
-               return "VPORT";
-       case ECORE_RSS_ENG:
-               return "RSS_ENG";
-       case ECORE_PQ:
-               return "PQ";
-       case ECORE_RL:
-               return "RL";
-       case ECORE_MAC:
-               return "MAC";
-       case ECORE_VLAN:
-               return "VLAN";
-       case ECORE_RDMA_CNQ_RAM:
-               return "RDMA_CNQ_RAM";
-       case ECORE_ILT:
-               return "ILT";
-       case ECORE_LL2_QUEUE:
-               return "LL2_QUEUE";
-       case ECORE_CMDQS_CQS:
-               return "CMDQS_CQS";
-       case ECORE_RDMA_STATS_QUEUE:
-               return "RDMA_STATS_QUEUE";
-       case ECORE_BDQ:
-               return "BDQ";
-       default:
-               return "UNKNOWN_RESOURCE";
-       }
-}
-
-static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
-                                                  enum ecore_resources res_id,
-                                                  bool drv_resc_alloc)
+static enum _ecore_status_t
+__ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn, enum ecore_resources res_id,
+                        bool drv_resc_alloc)
 {
-       u32 dflt_resc_num = 0, dflt_resc_start = 0, mcp_resp, mcp_param;
-       u32 *p_resc_num, *p_resc_start;
-       struct resource_info resc_info;
+       u32 dflt_resc_num = 0, dflt_resc_start = 0;
+       u32 mcp_resp, *p_resc_num, *p_resc_start;
        enum _ecore_status_t rc;
 
        p_resc_num = &RESC_NUM(p_hwfn, res_id);
        p_resc_start = &RESC_START(p_hwfn, res_id);
 
-       rc = ecore_hw_get_dflt_resc(p_hwfn, res_id,
-                                   &dflt_resc_num, &dflt_resc_start);
+       rc = ecore_hw_get_dflt_resc(p_hwfn, res_id, &dflt_resc_num,
+                                   &dflt_resc_start);
        if (rc != ECORE_SUCCESS) {
                DP_ERR(p_hwfn,
                       "Failed to get default amount for resource %d [%s]\n",
@@ -2618,17 +2626,8 @@ static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
        }
 #endif
 
-       OSAL_MEM_ZERO(&resc_info, sizeof(resc_info));
-       resc_info.res_id = ecore_hw_get_mfw_res_id(res_id);
-       if (resc_info.res_id == RESOURCE_NUM_INVALID) {
-               DP_ERR(p_hwfn,
-                      "Failed to match resource %d with MFW resources\n",
-                      res_id);
-               return ECORE_INVAL;
-       }
-
-       rc = ecore_mcp_get_resc_info(p_hwfn, p_hwfn->p_main_ptt, &resc_info,
-                                    &mcp_resp, &mcp_param);
+       rc = ecore_mcp_get_resc_info(p_hwfn, p_hwfn->p_main_ptt, res_id,
+                                    &mcp_resp, p_resc_num, p_resc_start);
        if (rc != ECORE_SUCCESS) {
                DP_NOTICE(p_hwfn, true,
                          "MFW response failure for an allocation request for"
@@ -2642,13 +2641,11 @@ static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
         * - There is an internal error in the MFW while processing the request
         * - The resource ID is unknown to the MFW
         */
-       if (mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK &&
-           mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_DEPRECATED) {
-               /* @DPDK */
+       if (mcp_resp != FW_MSG_CODE_RESOURCE_ALLOC_OK) {
                DP_INFO(p_hwfn,
-                       "Resource %d [%s]: No allocation info was received"
-                       " [mcp_resp 0x%x]. Applying default values"
-                       " [num %d, start %d].\n",
+                       "Failed to receive allocation info for resource %d [%s]."
+                       " mcp_resp = 0x%x. Applying default values"
+                       " [%d,%d].\n",
                        res_id, ecore_hw_get_resc_name(res_id), mcp_resp,
                        dflt_resc_num, dflt_resc_start);
 
@@ -2660,16 +2657,13 @@ static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
        /* TBD - remove this when revising the handling of the SB resource */
        if (res_id == ECORE_SB) {
                /* Excluding the slowpath SB */
-               resc_info.size -= 1;
-               resc_info.offset -= p_hwfn->enabled_func_idx;
+               *p_resc_num -= 1;
+               *p_resc_start -= p_hwfn->enabled_func_idx;
        }
 
-       *p_resc_num = resc_info.size;
-       *p_resc_start = resc_info.offset;
-
        if (*p_resc_num != dflt_resc_num || *p_resc_start != dflt_resc_start) {
                DP_INFO(p_hwfn,
-                       "Resource %d [%s]: MFW allocation [num %d, start %d] differs from default values [num %d, start %d]%s\n",
+                       "MFW allocation for resource %d [%s] differs from default values [%d,%d vs. %d,%d]%s\n",
                        res_id, ecore_hw_get_resc_name(res_id), *p_resc_num,
                        *p_resc_start, dflt_resc_num, dflt_resc_start,
                        drv_resc_alloc ? " - Applying default values" : "");
@@ -2682,12 +2676,32 @@ out:
        return ECORE_SUCCESS;
 }
 
+static enum _ecore_status_t ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn,
+                                                  bool drv_resc_alloc)
+{
+       enum _ecore_status_t rc;
+       u8 res_id;
+
+       for (res_id = 0; res_id < ECORE_MAX_RESC; res_id++) {
+               rc = __ecore_hw_set_resc_info(p_hwfn, res_id, drv_resc_alloc);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+       }
+
+       return ECORE_SUCCESS;
+}
+
+#define ECORE_RESC_ALLOC_LOCK_RETRY_CNT                10
+#define ECORE_RESC_ALLOC_LOCK_RETRY_INTVL_US   10000 /* 10 msec */
+
 static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
                                              bool drv_resc_alloc)
 {
+       struct ecore_resc_unlock_params resc_unlock_params;
+       struct ecore_resc_lock_params resc_lock_params;
        bool b_ah = ECORE_IS_AH(p_hwfn->p_dev);
-       enum _ecore_status_t rc;
        u8 res_id;
+       enum _ecore_status_t rc;
 #ifndef ASIC_ONLY
        u32 *resc_start = p_hwfn->hw_info.resc_start;
        u32 *resc_num = p_hwfn->hw_info.resc_num;
@@ -2700,10 +2714,62 @@ static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
        u32 roce_min_ilt_lines = PXP_NUM_ILT_RECORDS_BB / MAX_NUM_PFS_BB;
 #endif
 
-       for (res_id = 0; res_id < ECORE_MAX_RESC; res_id++) {
-               rc = ecore_hw_set_resc_info(p_hwfn, res_id, drv_resc_alloc);
+       /* Setting the max values of the soft resources and the following
+        * resources allocation queries should be atomic. Since several PFs can
+        * run in parallel - a resource lock is needed.
+        * If either the resource lock or resource set value commands are not
+        * supported - skip the the max values setting, release the lock if
+        * needed, and proceed to the queries. Other failures, including a
+        * failure to acquire the lock, will cause this function to fail.
+        * Old drivers that don't acquire the lock can run in parallel, and
+        * their allocation values won't be affected by the updated max values.
+        */
+       OSAL_MEM_ZERO(&resc_lock_params, sizeof(resc_lock_params));
+       resc_lock_params.resource = ECORE_RESC_LOCK_RESC_ALLOC;
+       resc_lock_params.retry_num = ECORE_RESC_ALLOC_LOCK_RETRY_CNT;
+       resc_lock_params.retry_interval = ECORE_RESC_ALLOC_LOCK_RETRY_INTVL_US;
+       resc_lock_params.sleep_b4_retry = true;
+       OSAL_MEM_ZERO(&resc_unlock_params, sizeof(resc_unlock_params));
+       resc_unlock_params.resource = ECORE_RESC_LOCK_RESC_ALLOC;
+
+       rc = ecore_mcp_resc_lock(p_hwfn, p_hwfn->p_main_ptt, &resc_lock_params);
+       if (rc != ECORE_SUCCESS && rc != ECORE_NOTIMPL) {
+               return rc;
+       } else if (rc == ECORE_NOTIMPL) {
+               DP_INFO(p_hwfn,
+                       "Skip the max values setting of the soft resources since the resource lock is not supported by the MFW\n");
+       } else if (rc == ECORE_SUCCESS && !resc_lock_params.b_granted) {
+               DP_NOTICE(p_hwfn, false,
+                         "Failed to acquire the resource lock for the resource allocation commands\n");
+               rc = ECORE_BUSY;
+               goto unlock_and_exit;
+       } else {
+               rc = ecore_hw_set_soft_resc_size(p_hwfn);
+               if (rc != ECORE_SUCCESS && rc != ECORE_NOTIMPL) {
+                       DP_NOTICE(p_hwfn, false,
+                                 "Failed to set the max values of the soft resources\n");
+                       goto unlock_and_exit;
+               } else if (rc == ECORE_NOTIMPL) {
+                       DP_INFO(p_hwfn,
+                               "Skip the max values setting of the soft resources since it is not supported by the MFW\n");
+                       rc = ecore_mcp_resc_unlock(p_hwfn, p_hwfn->p_main_ptt,
+                                                  &resc_unlock_params);
+                       if (rc != ECORE_SUCCESS)
+                               DP_INFO(p_hwfn,
+                                       "Failed to release the resource lock for the resource allocation commands\n");
+               }
+       }
+
+       rc = ecore_hw_set_resc_info(p_hwfn, drv_resc_alloc);
+       if (rc != ECORE_SUCCESS)
+               goto unlock_and_exit;
+
+       if (resc_lock_params.b_granted && !resc_unlock_params.b_released) {
+               rc = ecore_mcp_resc_unlock(p_hwfn, p_hwfn->p_main_ptt,
+                                          &resc_unlock_params);
                if (rc != ECORE_SUCCESS)
-                       return rc;
+                       DP_INFO(p_hwfn,
+                               "Failed to release the resource lock for the resource allocation commands\n");
        }
 
 #ifndef ASIC_ONLY
@@ -2756,6 +2822,10 @@ static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
                           RESC_START(p_hwfn, res_id));
 
        return ECORE_SUCCESS;
+
+unlock_and_exit:
+       ecore_mcp_resc_unlock(p_hwfn, p_hwfn->p_main_ptt, &resc_unlock_params);
+       return rc;
 }
 
 static enum _ecore_status_t
index 15f3ea0..3efe0a0 100644 (file)
@@ -2768,7 +2768,60 @@ enum _ecore_status_t ecore_mcp_mem_ecc_events(struct ecore_hwfn *p_hwfn,
                             0, &rsp, (u32 *)num_events);
 }
 
-#define ECORE_RESC_ALLOC_VERSION_MAJOR 1
+static enum resource_id_enum
+ecore_mcp_get_mfw_res_id(enum ecore_resources res_id)
+{
+       enum resource_id_enum mfw_res_id = RESOURCE_NUM_INVALID;
+
+       switch (res_id) {
+       case ECORE_SB:
+               mfw_res_id = RESOURCE_NUM_SB_E;
+               break;
+       case ECORE_L2_QUEUE:
+               mfw_res_id = RESOURCE_NUM_L2_QUEUE_E;
+               break;
+       case ECORE_VPORT:
+               mfw_res_id = RESOURCE_NUM_VPORT_E;
+               break;
+       case ECORE_RSS_ENG:
+               mfw_res_id = RESOURCE_NUM_RSS_ENGINES_E;
+               break;
+       case ECORE_PQ:
+               mfw_res_id = RESOURCE_NUM_PQ_E;
+               break;
+       case ECORE_RL:
+               mfw_res_id = RESOURCE_NUM_RL_E;
+               break;
+       case ECORE_MAC:
+       case ECORE_VLAN:
+               /* Each VFC resource can accommodate both a MAC and a VLAN */
+               mfw_res_id = RESOURCE_VFC_FILTER_E;
+               break;
+       case ECORE_ILT:
+               mfw_res_id = RESOURCE_ILT_E;
+               break;
+       case ECORE_LL2_QUEUE:
+               mfw_res_id = RESOURCE_LL2_QUEUE_E;
+               break;
+       case ECORE_RDMA_CNQ_RAM:
+       case ECORE_CMDQS_CQS:
+               /* CNQ/CMDQS are the same resource */
+               mfw_res_id = RESOURCE_CQS_E;
+               break;
+       case ECORE_RDMA_STATS_QUEUE:
+               mfw_res_id = RESOURCE_RDMA_STATS_QUEUE_E;
+               break;
+       case ECORE_BDQ:
+               mfw_res_id = RESOURCE_BDQ_E;
+               break;
+       default:
+               break;
+       }
+
+       return mfw_res_id;
+}
+
+#define ECORE_RESC_ALLOC_VERSION_MAJOR 2
 #define ECORE_RESC_ALLOC_VERSION_MINOR 0
 #define ECORE_RESC_ALLOC_VERSION                               \
        ((ECORE_RESC_ALLOC_VERSION_MAJOR <<                     \
@@ -2776,36 +2829,146 @@ enum _ecore_status_t ecore_mcp_mem_ecc_events(struct ecore_hwfn *p_hwfn,
         (ECORE_RESC_ALLOC_VERSION_MINOR <<                     \
          DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR_SHIFT))
 
-enum _ecore_status_t ecore_mcp_get_resc_info(struct ecore_hwfn *p_hwfn,
-                                            struct ecore_ptt *p_ptt,
-                                            struct resource_info *p_resc_info,
-                                            u32 *p_mcp_resp, u32 *p_mcp_param)
+struct ecore_resc_alloc_in_params {
+       u32 cmd;
+       enum ecore_resources res_id;
+       u32 resc_max_val;
+};
+
+struct ecore_resc_alloc_out_params {
+       u32 mcp_resp;
+       u32 mcp_param;
+       u32 resc_num;
+       u32 resc_start;
+       u32 vf_resc_num;
+       u32 vf_resc_start;
+       u32 flags;
+};
+
+static enum _ecore_status_t
+ecore_mcp_resc_allocation_msg(struct ecore_hwfn *p_hwfn,
+                             struct ecore_ptt *p_ptt,
+                             struct ecore_resc_alloc_in_params *p_in_params,
+                             struct ecore_resc_alloc_out_params *p_out_params)
 {
+       struct resource_info *p_mfw_resc_info;
        struct ecore_mcp_mb_params mb_params;
        union drv_union_data union_data;
        enum _ecore_status_t rc;
 
+       p_mfw_resc_info = &union_data.resource;
+       OSAL_MEM_ZERO(p_mfw_resc_info, sizeof(*p_mfw_resc_info));
+
+       p_mfw_resc_info->res_id = ecore_mcp_get_mfw_res_id(p_in_params->res_id);
+       if (p_mfw_resc_info->res_id == RESOURCE_NUM_INVALID) {
+               DP_ERR(p_hwfn,
+                      "Failed to match resource %d [%s] with the MFW resources\n",
+                      p_in_params->res_id,
+                      ecore_hw_get_resc_name(p_in_params->res_id));
+               return ECORE_INVAL;
+       }
+
+       switch (p_in_params->cmd) {
+       case DRV_MSG_SET_RESOURCE_VALUE_MSG:
+               p_mfw_resc_info->size = p_in_params->resc_max_val;
+               /* Fallthrough */
+       case DRV_MSG_GET_RESOURCE_ALLOC_MSG:
+               break;
+       default:
+               DP_ERR(p_hwfn, "Unexpected resource alloc command [0x%08x]\n",
+                      p_in_params->cmd);
+               return ECORE_INVAL;
+       }
+
        OSAL_MEM_ZERO(&mb_params, sizeof(mb_params));
-       mb_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG;
+       mb_params.cmd = p_in_params->cmd;
        mb_params.param = ECORE_RESC_ALLOC_VERSION;
-       OSAL_MEMCPY(&union_data.resource, p_resc_info, sizeof(*p_resc_info));
        mb_params.p_data_src = &union_data;
        mb_params.p_data_dst = &union_data;
+
+       DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
+                  "Resource message request: cmd 0x%08x, res_id %d [%s], hsi_version %d.%d, val 0x%x\n",
+                  p_in_params->cmd, p_in_params->res_id,
+                  ecore_hw_get_resc_name(p_in_params->res_id),
+                  ECORE_MFW_GET_FIELD(mb_params.param,
+                          DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR),
+                  ECORE_MFW_GET_FIELD(mb_params.param,
+                          DRV_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR),
+                  p_in_params->resc_max_val);
+
        rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
        if (rc != ECORE_SUCCESS)
                return rc;
 
-       *p_mcp_resp = mb_params.mcp_resp;
-       *p_mcp_param = mb_params.mcp_param;
-
-       OSAL_MEMCPY(p_resc_info, &union_data.resource, sizeof(*p_resc_info));
+       p_out_params->mcp_resp = mb_params.mcp_resp;
+       p_out_params->mcp_param = mb_params.mcp_param;
+       p_out_params->resc_num = p_mfw_resc_info->size;
+       p_out_params->resc_start = p_mfw_resc_info->offset;
+       p_out_params->vf_resc_num = p_mfw_resc_info->vf_size;
+       p_out_params->vf_resc_start = p_mfw_resc_info->vf_offset;
+       p_out_params->flags = p_mfw_resc_info->flags;
 
        DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
-                  "MFW resource_info: version 0x%x, res_id 0x%x, size 0x%x,"
-                  " offset 0x%x, vf_size 0x%x, vf_offset 0x%x, flags 0x%x\n",
-                  *p_mcp_param, p_resc_info->res_id, p_resc_info->size,
-                  p_resc_info->offset, p_resc_info->vf_size,
-                  p_resc_info->vf_offset, p_resc_info->flags);
+                  "Resource message response: mfw_hsi_version %d.%d, num 0x%x, start 0x%x, vf_num 0x%x, vf_start 0x%x, flags 0x%08x\n",
+                  ECORE_MFW_GET_FIELD(p_out_params->mcp_param,
+                          FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MAJOR),
+                  ECORE_MFW_GET_FIELD(p_out_params->mcp_param,
+                          FW_MB_PARAM_RESOURCE_ALLOC_VERSION_MINOR),
+                  p_out_params->resc_num, p_out_params->resc_start,
+                  p_out_params->vf_resc_num, p_out_params->vf_resc_start,
+                  p_out_params->flags);
+
+       return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t
+ecore_mcp_set_resc_max_val(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                          enum ecore_resources res_id, u32 resc_max_val,
+                          u32 *p_mcp_resp)
+{
+       struct ecore_resc_alloc_out_params out_params;
+       struct ecore_resc_alloc_in_params in_params;
+       enum _ecore_status_t rc;
+
+       OSAL_MEM_ZERO(&in_params, sizeof(in_params));
+       in_params.cmd = DRV_MSG_SET_RESOURCE_VALUE_MSG;
+       in_params.res_id = res_id;
+       in_params.resc_max_val = resc_max_val;
+       OSAL_MEM_ZERO(&out_params, sizeof(out_params));
+       rc = ecore_mcp_resc_allocation_msg(p_hwfn, p_ptt, &in_params,
+                                          &out_params);
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       *p_mcp_resp = out_params.mcp_resp;
+
+       return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t
+ecore_mcp_get_resc_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                       enum ecore_resources res_id, u32 *p_mcp_resp,
+                       u32 *p_resc_num, u32 *p_resc_start)
+{
+       struct ecore_resc_alloc_out_params out_params;
+       struct ecore_resc_alloc_in_params in_params;
+       enum _ecore_status_t rc;
+
+       OSAL_MEM_ZERO(&in_params, sizeof(in_params));
+       in_params.cmd = DRV_MSG_GET_RESOURCE_ALLOC_MSG;
+       in_params.res_id = res_id;
+       OSAL_MEM_ZERO(&out_params, sizeof(out_params));
+       rc = ecore_mcp_resc_allocation_msg(p_hwfn, p_ptt, &in_params,
+                                          &out_params);
+       if (rc != ECORE_SUCCESS)
+               return rc;
+
+       *p_mcp_resp = out_params.mcp_resp;
+
+       if (*p_mcp_resp == FW_MSG_CODE_RESOURCE_ALLOC_OK) {
+               *p_resc_num = out_params.resc_num;
+               *p_resc_start = out_params.resc_start;
+       }
 
        return ECORE_SUCCESS;
 }
@@ -2831,8 +2994,11 @@ static enum _ecore_status_t ecore_mcp_resource_cmd(struct ecore_hwfn *p_hwfn,
        if (rc != ECORE_SUCCESS)
                return rc;
 
-       if (*p_mcp_resp == FW_MSG_CODE_UNSUPPORTED)
+       if (*p_mcp_resp == FW_MSG_CODE_UNSUPPORTED) {
+               DP_INFO(p_hwfn,
+                       "The resource command is unsupported by the MFW\n");
                return ECORE_NOTIMPL;
+       }
 
        if (*p_mcp_param == RESOURCE_OPCODE_UNKNOWN_CMD) {
                u8 opcode = ECORE_MFW_GET_FIELD(param, RESOURCE_CMD_REQ_OPCODE);
@@ -2846,36 +3012,35 @@ static enum _ecore_status_t ecore_mcp_resource_cmd(struct ecore_hwfn *p_hwfn,
        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)
+enum _ecore_status_t
+__ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                     struct ecore_resc_lock_params *p_params)
 {
        u32 param = 0, mcp_resp, mcp_param;
        u8 opcode;
        enum _ecore_status_t rc;
 
-       switch (timeout) {
+       switch (p_params->timeout) {
        case ECORE_MCP_RESC_LOCK_TO_DEFAULT:
                opcode = RESOURCE_OPCODE_REQ;
-               timeout = 0;
+               p_params->timeout = 0;
                break;
        case ECORE_MCP_RESC_LOCK_TO_NONE:
                opcode = RESOURCE_OPCODE_REQ_WO_AGING;
-               timeout = 0;
+               p_params->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_RESC, p_params->resource);
        ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_OPCODE, opcode);
-       ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_AGE, timeout);
+       ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_AGE, p_params->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);
+                  "Resource lock request: param 0x%08x [age %d, opcode %d, resource %d]\n",
+                  param, p_params->timeout, opcode, p_params->resource);
 
        /* Attempt to acquire the resource */
        rc = ecore_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp,
@@ -2884,19 +3049,20 @@ enum _ecore_status_t ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn,
                return rc;
 
        /* Analyze the response */
-       *p_owner = ECORE_MFW_GET_FIELD(mcp_param, RESOURCE_CMD_RSP_OWNER);
+       p_params->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);
+                  mcp_param, opcode, p_params->owner);
 
        switch (opcode) {
        case RESOURCE_OPCODE_GNT:
-               *p_granted = true;
+               p_params->b_granted = true;
                break;
        case RESOURCE_OPCODE_BUSY:
-               *p_granted = false;
+               p_params->b_granted = false;
                break;
        default:
                DP_NOTICE(p_hwfn, false,
@@ -2908,23 +3074,54 @@ enum _ecore_status_t ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn,
        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)
+enum _ecore_status_t
+ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                   struct ecore_resc_lock_params *p_params)
+{
+       u32 retry_cnt = 0;
+       enum _ecore_status_t rc;
+
+       do {
+               /* No need for an interval before the first iteration */
+               if (retry_cnt) {
+                       if (p_params->sleep_b4_retry) {
+                               u16 retry_interval_in_ms =
+                                       DIV_ROUND_UP(p_params->retry_interval,
+                                                    1000);
+
+                               OSAL_MSLEEP(retry_interval_in_ms);
+                       } else {
+                               OSAL_UDELAY(p_params->retry_interval);
+                       }
+               }
+
+               rc = __ecore_mcp_resc_lock(p_hwfn, p_ptt, p_params);
+               if (rc != ECORE_SUCCESS)
+                       return rc;
+
+               if (p_params->b_granted)
+                       break;
+       } while (retry_cnt++ < p_params->retry_num);
+
+       return ECORE_SUCCESS;
+}
+
+enum _ecore_status_t
+ecore_mcp_resc_unlock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                     struct ecore_resc_unlock_params *p_params)
 {
        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);
+       opcode = p_params->b_force ? RESOURCE_OPCODE_FORCE_RELEASE
+                                  : RESOURCE_OPCODE_RELEASE;
+       ECORE_MFW_SET_FIELD(param, RESOURCE_CMD_REQ_RESC, p_params->resource);
        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);
+                  "Resource unlock request: param 0x%08x [opcode %d, resource %d]\n",
+                  param, opcode, p_params->resource);
 
        /* Attempt to release the resource */
        rc = ecore_mcp_resource_cmd(p_hwfn, p_ptt, param, &mcp_resp,
@@ -2942,14 +3139,14 @@ enum _ecore_status_t ecore_mcp_resc_unlock(struct ecore_hwfn *p_hwfn,
        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);
+                       "Resource unlock request for an already released resource [%d]\n",
+                       p_params->resource);
                /* Fallthrough */
        case RESOURCE_OPCODE_RELEASED:
-               *p_released = true;
+               p_params->b_released = true;
                break;
        case RESOURCE_OPCODE_WRONG_OWNER:
-               *p_released = false;
+               p_params->b_released = false;
                break;
        default:
                DP_NOTICE(p_hwfn, false,
index 4138a12..f5dac9d 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "bcm_osal.h"
 #include "mcp_public.h"
+#include "ecore.h"
 #include "ecore_mcp_api.h"
 
 /* Using hwfn number (and not pf_num) is required since in CMT mode,
@@ -338,21 +339,38 @@ enum _ecore_status_t ecore_mcp_mdump_set_values(struct ecore_hwfn *p_hwfn,
 enum _ecore_status_t ecore_mcp_mdump_trigger(struct ecore_hwfn *p_hwfn,
                                             struct ecore_ptt *p_ptt);
 
+/**
+ * @brief - Sets the MFW's max value for the given resource
+ *
+ *  @param p_hwfn
+ *  @param p_ptt
+ *  @param res_id
+ *  @param resc_max_val
+ *  @param p_mcp_resp
+ *
+ * @return enum _ecore_status_t - ECORE_SUCCESS - operation was successful.
+ */
+enum _ecore_status_t
+ecore_mcp_set_resc_max_val(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                          enum ecore_resources res_id, u32 resc_max_val,
+                          u32 *p_mcp_resp);
+
 /**
  * @brief - Gets the MFW allocation info for the given resource
  *
  *  @param p_hwfn
  *  @param p_ptt
- *  @param p_resc_info
+ *  @param res_id
  *  @param p_mcp_resp
- *  @param p_mcp_param
+ *  @param p_resc_num
+ *  @param p_resc_start
  *
  * @return enum _ecore_status_t - ECORE_SUCCESS - operation was successful.
  */
-enum _ecore_status_t ecore_mcp_get_resc_info(struct ecore_hwfn *p_hwfn,
-                                            struct ecore_ptt *p_ptt,
-                                            struct resource_info *p_resc_info,
-                                            u32 *p_mcp_resp, u32 *p_mcp_param);
+enum _ecore_status_t
+ecore_mcp_get_resc_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                       enum ecore_resources res_id, u32 *p_mcp_resp,
+                       u32 *p_resc_num, u32 *p_resc_start);
 
 /**
  * @brief - Initiates PF FLR
@@ -365,45 +383,79 @@ 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_MIN_VAL    RESOURCE_DUMP /* 0 */
+#define ECORE_MCP_RESC_LOCK_MAX_VAL    31
+
+enum ecore_resc_lock {
+       ECORE_RESC_LOCK_DBG_DUMP = ECORE_MCP_RESC_LOCK_MIN_VAL,
+       /* Locks that the MFW is aware of should be added here downwards */
+
+       /* Ecore only locks should be added here upwards */
+       ECORE_RESC_LOCK_RESC_ALLOC = ECORE_MCP_RESC_LOCK_MAX_VAL
+};
+
+struct ecore_resc_lock_params {
+       /* Resource number [valid values are 0..31] */
+       u8 resource;
+
+       /* Lock timeout value in seconds [default, none or 1..254] */
+       u8 timeout;
 #define ECORE_MCP_RESC_LOCK_TO_DEFAULT 0
 #define ECORE_MCP_RESC_LOCK_TO_NONE    255
 
+       /* Number of times to retry locking */
+       u8 retry_num;
+
+       /* The interval in usec between retries */
+       u16 retry_interval;
+
+       /* Use sleep or delay between retries */
+       bool sleep_b4_retry;
+
+       /* Will be set as true if the resource is free and granted */
+       bool b_granted;
+
+       /* Will be filled with the resource owner.
+        * [0..15 = PF0-15, 16 = MFW, 17 = diag over serial]
+        */
+       u8 owner;
+};
+
 /**
  * @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).
+ *  @param p_params
  *
  * @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);
+enum _ecore_status_t
+ecore_mcp_resc_lock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                   struct ecore_resc_lock_params *p_params);
+
+struct ecore_resc_unlock_params {
+       /* Resource number [valid values are 0..31] */
+       u8 resource;
+
+       /* Allow to release a resource even if belongs to another PF */
+       bool b_force;
+
+       /* Will be set as true if the resource is released */
+       bool b_released;
+};
 
 /**
  * @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.
+ *  @param p_params
  *
  * @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);
+enum _ecore_status_t
+ecore_mcp_resc_unlock(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                     struct ecore_resc_unlock_params *p_params);
 
 #endif /* __ECORE_MCP_H__ */