net/qede: fix device link structure
[dpdk.git] / drivers / net / qede / base / ecore_mcp.c
index 89c9864..8edd2e9 100644 (file)
@@ -156,6 +156,9 @@ enum _ecore_status_t ecore_mcp_free(struct ecore_hwfn *p_hwfn)
        if (p_hwfn->mcp_info) {
                struct ecore_mcp_cmd_elem *p_cmd_elem = OSAL_NULL, *p_tmp;
 
+               OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info->mfw_mb_cur);
+               OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info->mfw_mb_shadow);
+
                OSAL_SPIN_LOCK(&p_hwfn->mcp_info->cmd_lock);
                OSAL_LIST_FOR_EACH_ENTRY_SAFE(p_cmd_elem, p_tmp,
                                              &p_hwfn->mcp_info->cmd_list, list,
@@ -164,8 +167,6 @@ enum _ecore_status_t ecore_mcp_free(struct ecore_hwfn *p_hwfn)
                }
                OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->cmd_lock);
 
-               OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info->mfw_mb_cur);
-               OSAL_FREE(p_hwfn->p_dev, p_hwfn->mcp_info->mfw_mb_shadow);
 #ifdef CONFIG_ECORE_LOCK_ALLOC
                OSAL_SPIN_LOCK_DEALLOC(&p_hwfn->mcp_info->cmd_lock);
                OSAL_SPIN_LOCK_DEALLOC(&p_hwfn->mcp_info->link_lock);
@@ -244,6 +245,16 @@ enum _ecore_status_t ecore_mcp_cmd_init(struct ecore_hwfn *p_hwfn,
                goto err;
        p_info = p_hwfn->mcp_info;
 
+       /* Initialize the MFW spinlocks */
+#ifdef CONFIG_ECORE_LOCK_ALLOC
+       OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_info->cmd_lock);
+       OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_info->link_lock);
+#endif
+       OSAL_SPIN_LOCK_INIT(&p_info->cmd_lock);
+       OSAL_SPIN_LOCK_INIT(&p_info->link_lock);
+
+       OSAL_LIST_INIT(&p_info->cmd_list);
+
        if (ecore_load_mcp_offsets(p_hwfn, p_ptt) != ECORE_SUCCESS) {
                DP_NOTICE(p_hwfn, false, "MCP is not initialized\n");
                /* Do not free mcp_info here, since public_base indicate that
@@ -258,16 +269,6 @@ enum _ecore_status_t ecore_mcp_cmd_init(struct ecore_hwfn *p_hwfn,
        if (!p_info->mfw_mb_shadow || !p_info->mfw_mb_addr)
                goto err;
 
-       /* Initialize the MFW spinlocks */
-#ifdef CONFIG_ECORE_LOCK_ALLOC
-       OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_info->cmd_lock);
-       OSAL_SPIN_LOCK_ALLOC(p_hwfn, &p_info->link_lock);
-#endif
-       OSAL_SPIN_LOCK_INIT(&p_info->cmd_lock);
-       OSAL_SPIN_LOCK_INIT(&p_info->link_lock);
-
-       OSAL_LIST_INIT(&p_info->cmd_list);
-
        return ECORE_SUCCESS;
 
 err:
@@ -447,6 +448,24 @@ static void ecore_mcp_cmd_set_blocking(struct ecore_hwfn *p_hwfn,
                block_cmd ? "Block" : "Unblock");
 }
 
+void ecore_mcp_print_cpu_info(struct ecore_hwfn *p_hwfn,
+                             struct ecore_ptt *p_ptt)
+{
+       u32 cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2;
+
+       cpu_mode = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_MODE);
+       cpu_state = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_STATE);
+       cpu_pc_0 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
+       OSAL_UDELAY(CHIP_MCP_RESP_ITER_US);
+       cpu_pc_1 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
+       OSAL_UDELAY(CHIP_MCP_RESP_ITER_US);
+       cpu_pc_2 = ecore_rd(p_hwfn, p_ptt, MCP_REG_CPU_PROGRAM_COUNTER);
+
+       DP_NOTICE(p_hwfn, false,
+                 "MCP CPU info: mode 0x%08x, state 0x%08x, pc {0x%08x, 0x%08x, 0x%08x}\n",
+                 cpu_mode, cpu_state, cpu_pc_0, cpu_pc_1, cpu_pc_2);
+}
+
 static enum _ecore_status_t
 _ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
                         struct ecore_mcp_mb_params *p_mb_params,
@@ -477,6 +496,7 @@ _ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
 
                OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->cmd_lock);
                OSAL_UDELAY(delay);
+               OSAL_MFW_CMD_PREEMPT(p_hwfn);
        } while (++cnt < max_retries);
 
        if (cnt >= max_retries) {
@@ -518,12 +538,14 @@ _ecore_mcp_cmd_and_union(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
                        goto err;
 
                OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->cmd_lock);
+               OSAL_MFW_CMD_PREEMPT(p_hwfn);
        } while (++cnt < max_retries);
 
        if (cnt >= max_retries) {
                DP_NOTICE(p_hwfn, false,
                          "The MFW failed to respond to command 0x%08x [param 0x%08x].\n",
                          p_mb_params->cmd, p_mb_params->param);
+               ecore_mcp_print_cpu_info(p_hwfn, p_ptt);
 
                OSAL_SPIN_LOCK(&p_hwfn->mcp_info->cmd_lock);
                ecore_mcp_cmd_del_elem(p_hwfn, p_cmd_elem);
@@ -1068,8 +1090,6 @@ enum _ecore_status_t ecore_mcp_load_done(struct ecore_hwfn *p_hwfn,
                return rc;
        }
 
-#define FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR     (1 << 0)
-
        /* Check if there is a DID mismatch between nvm-cfg/efuse */
        if (param & FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR)
                DP_NOTICE(p_hwfn, false,
@@ -1197,6 +1217,8 @@ static void ecore_mcp_handle_transceiver_change(struct ecore_hwfn *p_hwfn,
                DP_NOTICE(p_hwfn, false, "Transceiver is present.\n");
        else
                DP_NOTICE(p_hwfn, false, "Transceiver is unplugged.\n");
+
+       OSAL_TRANSCEIVER_UPDATE(p_hwfn);
 }
 
 static void ecore_mcp_read_eee_config(struct ecore_hwfn *p_hwfn,
@@ -1222,6 +1244,28 @@ static void ecore_mcp_read_eee_config(struct ecore_hwfn *p_hwfn,
                p_link->eee_lp_adv_caps |= ECORE_EEE_10G_ADV;
 }
 
+static u32 ecore_mcp_get_shmem_func(struct ecore_hwfn *p_hwfn,
+                                   struct ecore_ptt *p_ptt,
+                                   struct public_func *p_data,
+                                   int pfid)
+{
+       u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
+                                       PUBLIC_FUNC);
+       u32 mfw_path_offsize = ecore_rd(p_hwfn, p_ptt, addr);
+       u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid);
+       u32 i, size;
+
+       OSAL_MEM_ZERO(p_data, sizeof(*p_data));
+
+       size = OSAL_MIN_T(u32, sizeof(*p_data),
+                         SECTION_SIZE(mfw_path_offsize));
+       for (i = 0; i < size / sizeof(u32); i++)
+               ((u32 *)p_data)[i] = ecore_rd(p_hwfn, p_ptt,
+                                             func_addr + (i << 2));
+
+       return size;
+}
+
 static void ecore_mcp_handle_link_change(struct ecore_hwfn *p_hwfn,
                                         struct ecore_ptt *p_ptt,
                                         bool b_reset)
@@ -1251,10 +1295,24 @@ static void ecore_mcp_handle_link_change(struct ecore_hwfn *p_hwfn,
                goto out;
        }
 
-       if (p_hwfn->b_drv_link_init)
-               p_link->link_up = !!(status & LINK_STATUS_LINK_UP);
-       else
+       if (p_hwfn->b_drv_link_init) {
+               /* Link indication with modern MFW arrives as per-PF
+                * indication.
+                */
+               if (p_hwfn->mcp_info->capabilities &
+                   FW_MB_PARAM_FEATURE_SUPPORT_VLINK) {
+                       struct public_func shmem_info;
+
+                       ecore_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info,
+                                                MCP_PF_ID(p_hwfn));
+                       p_link->link_up = !!(shmem_info.status &
+                                            FUNC_STATUS_VIRTUAL_LINK_UP);
+               } else {
+                       p_link->link_up = !!(status & LINK_STATUS_LINK_UP);
+               }
+       } else {
                p_link->link_up = false;
+       }
 
        p_link->full_duplex = true;
        switch ((status & LINK_STATUS_SPEED_AND_DUPLEX_MASK)) {
@@ -1301,7 +1359,7 @@ static void ecore_mcp_handle_link_change(struct ecore_hwfn *p_hwfn,
        __ecore_configure_pf_max_bandwidth(p_hwfn, p_ptt,
                                           p_link, max_bw);
 
-       /* Mintz bandwidth configuration */
+       /* Min bandwidth configuration */
        __ecore_configure_pf_min_bandwidth(p_hwfn, p_ptt,
                                           p_link, min_bw);
        ecore_configure_vp_wfq_on_link_change(p_hwfn->p_dev, p_ptt,
@@ -1362,7 +1420,7 @@ static void ecore_mcp_handle_link_change(struct ecore_hwfn *p_hwfn,
        if (p_hwfn->mcp_info->capabilities & FW_MB_PARAM_FEATURE_SUPPORT_EEE)
                ecore_mcp_read_eee_config(p_hwfn, p_ptt, p_link);
 
-       OSAL_LINK_UPDATE(p_hwfn, p_ptt);
+       OSAL_LINK_UPDATE(p_hwfn);
 out:
        OSAL_SPIN_UNLOCK(&p_hwfn->mcp_info->link_lock);
 }
@@ -1517,7 +1575,8 @@ static void ecore_mcp_send_protocol_stats(struct ecore_hwfn *p_hwfn,
                hsi_param = DRV_MSG_CODE_STATS_TYPE_LAN;
                break;
        default:
-               DP_INFO(p_hwfn, "Invalid protocol type %d\n", type);
+               DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
+                          "Invalid protocol type %d\n", type);
                return;
        }
 
@@ -1567,28 +1626,6 @@ static void ecore_read_pf_bandwidth(struct ecore_hwfn *p_hwfn,
        }
 }
 
-static u32 ecore_mcp_get_shmem_func(struct ecore_hwfn *p_hwfn,
-                                   struct ecore_ptt *p_ptt,
-                                   struct public_func *p_data,
-                                   int pfid)
-{
-       u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base,
-                                       PUBLIC_FUNC);
-       u32 mfw_path_offsize = ecore_rd(p_hwfn, p_ptt, addr);
-       u32 func_addr = SECTION_ADDR(mfw_path_offsize, pfid);
-       u32 i, size;
-
-       OSAL_MEM_ZERO(p_data, sizeof(*p_data));
-
-       size = OSAL_MIN_T(u32, sizeof(*p_data),
-                         SECTION_SIZE(mfw_path_offsize));
-       for (i = 0; i < size / sizeof(u32); i++)
-               ((u32 *)p_data)[i] = ecore_rd(p_hwfn, p_ptt,
-                                             func_addr + (i << 2));
-
-       return size;
-}
-
 static void
 ecore_mcp_update_bw(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt)
 {
@@ -1971,6 +2008,12 @@ enum _ecore_status_t ecore_mcp_handle_events(struct ecore_hwfn *p_hwfn,
                case MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED:
                        ecore_dcbx_mib_update_event(p_hwfn, p_ptt,
                                                    ECORE_DCBX_OPERATIONAL_MIB);
+                       /* clear the user-config cache */
+                       OSAL_MEMSET(&p_hwfn->p_dcbx_info->set, 0,
+                                   sizeof(struct ecore_dcbx_set));
+                       break;
+               case MFW_DRV_MSG_LLDP_RECEIVED_TLVS_UPDATED:
+                       ecore_lldp_mib_update_event(p_hwfn, p_ptt);
                        break;
                case MFW_DRV_MSG_OEM_CFG_UPDATE:
                        ecore_mcp_handle_ufp_event(p_hwfn, p_ptt);
@@ -2513,9 +2556,9 @@ ecore_mcp_ov_update_current_config(struct ecore_hwfn *p_hwfn,
                                   struct ecore_ptt *p_ptt,
                                   enum ecore_ov_client client)
 {
-       enum _ecore_status_t rc;
        u32 resp = 0, param = 0;
        u32 drv_mb_param;
+       enum _ecore_status_t rc;
 
        switch (client) {
        case ECORE_OV_CLIENT_DRV:
@@ -2545,9 +2588,9 @@ ecore_mcp_ov_update_driver_state(struct ecore_hwfn *p_hwfn,
                                 struct ecore_ptt *p_ptt,
                                 enum ecore_ov_driver_state drv_state)
 {
-       enum _ecore_status_t rc;
        u32 resp = 0, param = 0;
        u32 drv_mb_param;
+       enum _ecore_status_t rc;
 
        switch (drv_state) {
        case ECORE_OV_DRIVER_STATE_NOT_LOADED:
@@ -2919,11 +2962,16 @@ enum _ecore_status_t ecore_mcp_phy_sfp_read(struct ecore_hwfn *p_hwfn,
                                          DRV_MSG_CODE_TRANSCEIVER_READ,
                                          nvm_offset, &resp, &param, &buf_size,
                                          (u32 *)(p_buf + offset));
-               if ((resp & FW_MSG_CODE_MASK) ==
-                   FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT) {
+               if (rc != ECORE_SUCCESS) {
+                       DP_NOTICE(p_hwfn, false,
+                                 "Failed to send a transceiver read command to the MFW. rc = %d.\n",
+                                 rc);
+                       return rc;
+               }
+
+               if (resp == FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT)
                        return ECORE_NODEV;
-               } else if ((resp & FW_MSG_CODE_MASK) !=
-                          FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
+               else if (resp != FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
                        return ECORE_UNKNOWN_ERROR;
 
                offset += buf_size;
@@ -2957,11 +3005,16 @@ enum _ecore_status_t ecore_mcp_phy_sfp_write(struct ecore_hwfn *p_hwfn,
                                          DRV_MSG_CODE_TRANSCEIVER_WRITE,
                                          nvm_offset, &resp, &param, buf_size,
                                          (u32 *)&p_buf[buf_idx]);
-               if ((resp & FW_MSG_CODE_MASK) ==
-                   FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT) {
+               if (rc != ECORE_SUCCESS) {
+                       DP_NOTICE(p_hwfn, false,
+                                 "Failed to send a transceiver write command to the MFW. rc = %d.\n",
+                                 rc);
+                       return rc;
+               }
+
+               if (resp == FW_MSG_CODE_TRANSCEIVER_NOT_PRESENT)
                        return ECORE_NODEV;
-               } else if ((resp & FW_MSG_CODE_MASK) !=
-                          FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
+               else if (resp != FW_MSG_CODE_TRANSCEIVER_DIAG_OK)
                        return ECORE_UNKNOWN_ERROR;
 
                buf_idx += buf_size;
@@ -3669,7 +3722,8 @@ enum _ecore_status_t ecore_mcp_set_capabilities(struct ecore_hwfn *p_hwfn,
        u32 mcp_resp, mcp_param, features;
 
        features = DRV_MB_PARAM_FEATURE_SUPPORT_PORT_SMARTLINQ |
-                  DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE;
+                  DRV_MB_PARAM_FEATURE_SUPPORT_PORT_EEE |
+                  DRV_MB_PARAM_FEATURE_SUPPORT_FUNC_VLINK;
 
        return ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_FEATURE_SUPPORT,
                             features, &mcp_resp, &mcp_param);
@@ -3747,3 +3801,29 @@ ecore_mcp_drv_attribute(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
 
        return ECORE_SUCCESS;
 }
+
+void ecore_mcp_wol_wr(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
+                     u32 offset, u32 val)
+{
+       struct ecore_mcp_mb_params mb_params = {0};
+       enum _ecore_status_t       rc = ECORE_SUCCESS;
+       u32                        dword = val;
+
+       mb_params.cmd = DRV_MSG_CODE_WRITE_WOL_REG;
+       mb_params.param = offset;
+       mb_params.p_data_src = &dword;
+       mb_params.data_src_size = sizeof(dword);
+
+       rc = ecore_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
+       if (rc != ECORE_SUCCESS) {
+               DP_NOTICE(p_hwfn, false,
+                         "Failed to wol write request, rc = %d\n", rc);
+       }
+
+       if (mb_params.mcp_resp != FW_MSG_CODE_WOL_READ_WRITE_OK) {
+               DP_NOTICE(p_hwfn, false,
+                         "Failed to write value 0x%x to offset 0x%x [mcp_resp 0x%x]\n",
+                         val, offset, mb_params.mcp_resp);
+               rc = ECORE_UNKNOWN_ERROR;
+       }
+}