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 <rasesh.mody@cavium.com>
This commit is contained in:
Rasesh Mody 2017-03-29 13:36:48 -07:00 committed by Ferruh Yigit
parent 6da551eeac
commit 49ca6a7bcb
4 changed files with 499 additions and 178 deletions

View 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 */

View 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;
case ECORE_ILT:
mfw_res_id = RESOURCE_ILT_E;
break;
case ECORE_LL2_QUEUE:
mfw_res_id = RESOURCE_LL2_QUEUE_E;
break;
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:
/* 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";
}
}
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;
}
return mfw_res_id;
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)
static enum _ecore_status_t
__ecore_hw_set_resc_info(struct ecore_hwfn *p_hwfn, enum ecore_resources res_id,
bool drv_resc_alloc)
{
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)
{
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

View 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,

View 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__ */