[dpdk-dev] [PATCH 17/61] net/qede/base: allow probe to succeed with minor HW-issues
Rasesh Mody
rasesh.mody at cavium.com
Mon Feb 27 08:56:33 CET 2017
Allow probe to succeed with various 'minor' HW-issues [if requested]
Signed-off-by: Rasesh Mody <rasesh.mody at cavium.com>
---
drivers/net/qede/base/ecore_dev.c | 71 +++++++++++++++++++++++++++------
drivers/net/qede/base/ecore_dev_api.h | 40 ++++++++++++++++---
2 files changed, 94 insertions(+), 17 deletions(-)
diff --git a/drivers/net/qede/base/ecore_dev.c b/drivers/net/qede/base/ecore_dev.c
index 82a41a3..99d8f15 100644
--- a/drivers/net/qede/base/ecore_dev.c
+++ b/drivers/net/qede/base/ecore_dev.c
@@ -2453,12 +2453,15 @@ static enum _ecore_status_t ecore_hw_get_resc(struct ecore_hwfn *p_hwfn,
return ECORE_SUCCESS;
}
-static enum _ecore_status_t ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
- struct ecore_ptt *p_ptt)
+static enum _ecore_status_t
+ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
+ struct ecore_ptt *p_ptt,
+ struct ecore_hw_prepare_params *p_params)
{
u32 nvm_cfg1_offset, mf_mode, addr, generic_cont0, core_cfg, dcbx_mode;
u32 port_cfg_addr, link_temp, nvm_cfg_addr, device_capabilities;
struct ecore_mcp_link_params *link;
+ enum _ecore_status_t rc;
/* Read global nvm_cfg address */
nvm_cfg_addr = ecore_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0);
@@ -2466,6 +2469,8 @@ static enum _ecore_status_t ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
/* Verify MCP has initialized it */
if (!nvm_cfg_addr) {
DP_NOTICE(p_hwfn, false, "Shared memory not initialized\n");
+ if (p_params->b_relaxed_probe)
+ p_params->p_relaxed_res = ECORE_HW_PREPARE_FAILED_NVM;
return ECORE_INVAL;
}
@@ -2651,7 +2656,13 @@ static enum _ecore_status_t ecore_hw_get_nvm_info(struct ecore_hwfn *p_hwfn,
OSAL_SET_BIT(ECORE_DEV_CAP_IWARP,
&p_hwfn->hw_info.device_capabilities);
- return ecore_mcp_fill_shmem_func_info(p_hwfn, p_ptt);
+ rc = ecore_mcp_fill_shmem_func_info(p_hwfn, p_ptt);
+ if (rc != ECORE_SUCCESS && p_params->b_relaxed_probe) {
+ rc = ECORE_SUCCESS;
+ p_params->p_relaxed_res = ECORE_HW_PREPARE_BAD_MCP;
+ }
+
+ return rc;
}
static void ecore_get_num_funcs(struct ecore_hwfn *p_hwfn,
@@ -2805,15 +2816,22 @@ static void ecore_hw_info_port_num(struct ecore_hwfn *p_hwfn,
static enum _ecore_status_t
ecore_get_hw_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
- enum ecore_pci_personality personality, bool drv_resc_alloc)
+ enum ecore_pci_personality personality,
+ struct ecore_hw_prepare_params *p_params)
{
+ bool drv_resc_alloc = p_params->drv_resc_alloc;
enum _ecore_status_t rc;
/* Since all information is common, only first hwfns should do this */
if (IS_LEAD_HWFN(p_hwfn)) {
rc = ecore_iov_hw_info(p_hwfn);
- if (rc != ECORE_SUCCESS)
- return rc;
+ if (rc != ECORE_SUCCESS) {
+ if (p_params->b_relaxed_probe)
+ p_params->p_relaxed_res =
+ ECORE_HW_PREPARE_BAD_IOV;
+ else
+ return rc;
+ }
}
/* TODO In get_hw_info, amoungst others:
@@ -2828,7 +2846,7 @@ static void ecore_hw_info_port_num(struct ecore_hwfn *p_hwfn,
#ifndef ASIC_ONLY
if (CHIP_REV_IS_ASIC(p_hwfn->p_dev)) {
#endif
- rc = ecore_hw_get_nvm_info(p_hwfn, p_ptt);
+ rc = ecore_hw_get_nvm_info(p_hwfn, p_ptt, p_params);
if (rc != ECORE_SUCCESS)
return rc;
#ifndef ASIC_ONLY
@@ -2836,8 +2854,12 @@ static void ecore_hw_info_port_num(struct ecore_hwfn *p_hwfn,
#endif
rc = ecore_int_igu_read_cam(p_hwfn, p_ptt);
- if (rc != ECORE_SUCCESS)
- return rc;
+ if (rc != ECORE_SUCCESS) {
+ if (p_params->b_relaxed_probe)
+ p_params->p_relaxed_res = ECORE_HW_PREPARE_BAD_IGU;
+ else
+ return rc;
+ }
#ifndef ASIC_ONLY
if (CHIP_REV_IS_ASIC(p_hwfn->p_dev) && ecore_mcp_is_init(p_hwfn)) {
@@ -2904,7 +2926,13 @@ static void ecore_hw_info_port_num(struct ecore_hwfn *p_hwfn,
* the resources/features depends on them.
* This order is not harmful if not forcing.
*/
- return ecore_hw_get_resc(p_hwfn, drv_resc_alloc);
+ rc = ecore_hw_get_resc(p_hwfn, drv_resc_alloc);
+ if (rc != ECORE_SUCCESS && p_params->b_relaxed_probe) {
+ rc = ECORE_SUCCESS;
+ p_params->p_relaxed_res = ECORE_HW_PREPARE_BAD_MCP;
+ }
+
+ return rc;
}
static enum _ecore_status_t ecore_get_dev_info(struct ecore_dev *p_dev)
@@ -3036,6 +3064,8 @@ void ecore_prepare_hibernate(struct ecore_dev *p_dev)
if (REG_RD(p_hwfn, PXP_PF_ME_OPAQUE_ADDR) == 0xffffffff) {
DP_ERR(p_hwfn,
"Reading the ME register returns all Fs; Preventing further chip access\n");
+ if (p_params->b_relaxed_probe)
+ p_params->p_relaxed_res = ECORE_HW_PREPARE_FAILED_ME;
return ECORE_INVAL;
}
@@ -3045,6 +3075,8 @@ void ecore_prepare_hibernate(struct ecore_dev *p_dev)
rc = ecore_ptt_pool_alloc(p_hwfn);
if (rc) {
DP_NOTICE(p_hwfn, true, "Failed to prepare hwfn's hw\n");
+ if (p_params->b_relaxed_probe)
+ p_params->p_relaxed_res = ECORE_HW_PREPARE_FAILED_MEM;
goto err0;
}
@@ -3054,8 +3086,12 @@ void ecore_prepare_hibernate(struct ecore_dev *p_dev)
/* First hwfn learns basic information, e.g., number of hwfns */
if (!p_hwfn->my_id) {
rc = ecore_get_dev_info(p_dev);
- if (rc != ECORE_SUCCESS)
+ if (rc != ECORE_SUCCESS) {
+ if (p_params->b_relaxed_probe)
+ p_params->p_relaxed_res =
+ ECORE_HW_PREPARE_FAILED_DEV;
goto err1;
+ }
}
ecore_hw_hwfn_prepare(p_hwfn);
@@ -3064,12 +3100,14 @@ void ecore_prepare_hibernate(struct ecore_dev *p_dev)
rc = ecore_mcp_cmd_init(p_hwfn, p_hwfn->p_main_ptt);
if (rc) {
DP_NOTICE(p_hwfn, true, "Failed initializing mcp command\n");
+ if (p_params->b_relaxed_probe)
+ p_params->p_relaxed_res = ECORE_HW_PREPARE_FAILED_MEM;
goto err1;
}
/* Read the device configuration information from the HW and SHMEM */
rc = ecore_get_hw_info(p_hwfn, p_hwfn->p_main_ptt,
- p_params->personality, p_params->drv_resc_alloc);
+ p_params->personality, p_params);
if (rc) {
DP_NOTICE(p_hwfn, true, "Failed to get HW information\n");
goto err2;
@@ -3102,6 +3140,8 @@ void ecore_prepare_hibernate(struct ecore_dev *p_dev)
rc = ecore_init_alloc(p_hwfn);
if (rc) {
DP_NOTICE(p_hwfn, true, "Failed to allocate the init array\n");
+ if (p_params->b_relaxed_probe)
+ p_params->p_relaxed_res = ECORE_HW_PREPARE_FAILED_MEM;
goto err2;
}
#ifndef ASIC_ONLY
@@ -3137,6 +3177,9 @@ enum _ecore_status_t ecore_hw_prepare(struct ecore_dev *p_dev,
p_dev->chk_reg_fifo = p_params->chk_reg_fifo;
+ if (p_params->b_relaxed_probe)
+ p_params->p_relaxed_res = ECORE_HW_PREPARE_SUCCESS;
+
/* Store the precompiled init data ptrs */
if (IS_PF(p_dev))
ecore_init_iro_array(p_dev);
@@ -3172,6 +3215,10 @@ enum _ecore_status_t ecore_hw_prepare(struct ecore_dev *p_dev,
* initiliazed hwfn 0.
*/
if (rc != ECORE_SUCCESS) {
+ if (p_params->b_relaxed_probe)
+ p_params->p_relaxed_res =
+ ECORE_HW_PREPARE_FAILED_ENG2;
+
if (IS_PF(p_dev)) {
ecore_init_free(p_hwfn);
ecore_mcp_free(p_hwfn);
diff --git a/drivers/net/qede/base/ecore_dev_api.h b/drivers/net/qede/base/ecore_dev_api.h
index e7332ac..74a15ef 100644
--- a/drivers/net/qede/base/ecore_dev_api.h
+++ b/drivers/net/qede/base/ecore_dev_api.h
@@ -138,17 +138,47 @@ enum _ecore_status_t ecore_hw_init(struct ecore_dev *p_dev,
*/
enum _ecore_status_t ecore_hw_reset(struct ecore_dev *p_dev);
+enum ecore_hw_prepare_result {
+ ECORE_HW_PREPARE_SUCCESS,
+
+ /* FAILED results indicate probe has failed & cleaned up */
+ ECORE_HW_PREPARE_FAILED_ENG2,
+ ECORE_HW_PREPARE_FAILED_ME,
+ ECORE_HW_PREPARE_FAILED_MEM,
+ ECORE_HW_PREPARE_FAILED_DEV,
+ ECORE_HW_PREPARE_FAILED_NVM,
+
+ /* BAD results indicate probe is passed even though some wrongness
+ * has occurred; Trying to actually use [I.e., hw_init()] might have
+ * dire reprecautions.
+ */
+ ECORE_HW_PREPARE_BAD_IOV,
+ ECORE_HW_PREPARE_BAD_MCP,
+ ECORE_HW_PREPARE_BAD_IGU,
+};
+
struct ecore_hw_prepare_params {
- /* personality to initialize */
+ /* Personality to initialize */
int personality;
- /* force the driver's default resource allocation */
+
+ /* Force the driver's default resource allocation */
bool drv_resc_alloc;
- /* check the reg_fifo after any register access */
+
+ /* Check the reg_fifo after any register access */
bool chk_reg_fifo;
- /* request the MFW to initiate PF FLR */
+
+ /* Request the MFW to initiate PF FLR */
bool initiate_pf_flr;
- /* the OS Epoch time in seconds */
+
+ /* The OS Epoch time in seconds */
u32 epoch;
+
+ /* Allow prepare to pass even if some initializations are failing.
+ * If set, the `p_prepare_res' field would be set with the return,
+ * and might allow probe to pass even if there are certain issues.
+ */
+ bool b_relaxed_probe;
+ enum ecore_hw_prepare_result p_relaxed_res;
};
/**
--
1.7.10.3
More information about the dev
mailing list