From 49ca6a7bcb6c019262edb066cd9e21af0d920a8d Mon Sep 17 00:00:00 2001 From: Rasesh Mody Date: Wed, 29 Mar 2017 13:36:48 -0700 Subject: [PATCH] net/qede/base: set max values for soft resources Add support for the new interface with the Management FW for setting max values of "soft" resources. Signed-off-by: Rasesh Mody --- drivers/net/qede/base/ecore.h | 2 + drivers/net/qede/base/ecore_dev.c | 282 ++++++++++++++++++----------- drivers/net/qede/base/ecore_mcp.c | 287 +++++++++++++++++++++++++----- drivers/net/qede/base/ecore_mcp.h | 104 ++++++++--- 4 files changed, 498 insertions(+), 177 deletions(-) diff --git a/drivers/net/qede/base/ecore.h b/drivers/net/qede/base/ecore.h index 25b6c4e7bb..7379b3ff25 100644 --- a/drivers/net/qede/base/ecore.h +++ b/drivers/net/qede/base/ecore.h @@ -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 */ diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c index d5a8a902cb..3191ee434f 100644 --- a/drivers/net/qede/base/ecore_dev.c +++ b/drivers/net/qede/base/ecore_dev.c @@ -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 diff --git a/drivers/net/qede/base/ecore_mcp.c b/drivers/net/qede/base/ecore_mcp.c index 15f3ea010c..3efe0a0ba2 100644 --- a/drivers/net/qede/base/ecore_mcp.c +++ b/drivers/net/qede/base/ecore_mcp.c @@ -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, diff --git a/drivers/net/qede/base/ecore_mcp.h b/drivers/net/qede/base/ecore_mcp.h index 4138a12c06..f5dac9d522 100644 --- a/drivers/net/qede/base/ecore_mcp.h +++ b/drivers/net/qede/base/ecore_mcp.h @@ -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__ */ -- 2.20.1