| @@ -140,7 +140,7 @@ static struct qed_mcp_cmd_elem *qed_mcp_cmd_get_elem(struct qed_hwfn *p_hwfn, · 139 unmodified lines |
| 140 | int qed_mcp_free(struct qed_hwfn *p_hwfn) | 140 | int qed_mcp_free(struct qed_hwfn *p_hwfn) |
| 141 | { | 141 | { |
| 142 | if (p_hwfn->mcp_info) { | 142 | if (p_hwfn->mcp_info) { |
| 143 | struct qed_mcp_cmd_elem *p_cmd_elem, *p_tmp; | 143 | struct qed_mcp_cmd_elem *p_cmd_elem = NULL, *p_tmp; |
| 144 | | 144 | |
| 145 | kfree(p_hwfn->mcp_info->mfw_mb_cur); | 145 | kfree(p_hwfn->mcp_info->mfw_mb_cur); |
| 146 | kfree(p_hwfn->mcp_info->mfw_mb_shadow); | 146 | kfree(p_hwfn->mcp_info->mfw_mb_shadow); |
| @@ -249,6 +249,7 @@ int qed_mcp_cmd_init(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) · 102 unmodified lines |
| 249 | /* Initialize the MFW spinlock */ | 249 | /* Initialize the MFW spinlock */ |
| 250 | spin_lock_init(&p_info->cmd_lock); | 250 | spin_lock_init(&p_info->cmd_lock); |
| 251 | spin_lock_init(&p_info->link_lock); | 251 | spin_lock_init(&p_info->link_lock); |
| | 252 | spin_lock_init(&p_info->unload_lock); |
| 252 | | 253 | |
| 253 | INIT_LIST_HEAD(&p_info->cmd_list); | 254 | INIT_LIST_HEAD(&p_info->cmd_list); |
| 254 | | 255 | |
| @@ -1095,10 +1096,15 @@ int qed_mcp_load_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) · 840 unmodified lines |
| 1095 | return 0; | 1096 | return 0; |
| 1096 | } | 1097 | } |
| 1097 | | 1098 | |
| | 1099 | #define MFW_COMPLETION_MAX_ITER 5000 |
| | 1100 | #define MFW_COMPLETION_INTERVAL_MS 1 |
| | 1101 | |
| 1098 | int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | 1102 | int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) |
| 1099 | { | 1103 | { |
| 1100 | struct qed_mcp_mb_params mb_params; | 1104 | struct qed_mcp_mb_params mb_params; |
| | 1105 | u32 cnt = MFW_COMPLETION_MAX_ITER; |
| 1101 | u32 wol_param; | 1106 | u32 wol_param; |
| | 1107 | int rc; |
| 1102 | | 1108 | |
| 1103 | switch (p_hwfn->cdev->wol_config) { | 1109 | switch (p_hwfn->cdev->wol_config) { |
| 1104 | case QED_OV_WOL_DISABLED: | 1110 | case QED_OV_WOL_DISABLED: |
| @@ -1121,7 +1127,23 @@ int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) · 16 unmodified lines |
| 1121 | mb_params.param = wol_param; | 1127 | mb_params.param = wol_param; |
| 1122 | mb_params.flags = QED_MB_FLAG_CAN_SLEEP | QED_MB_FLAG_AVOID_BLOCK; | 1128 | mb_params.flags = QED_MB_FLAG_CAN_SLEEP | QED_MB_FLAG_AVOID_BLOCK; |
| 1123 | | 1129 | |
| 1124 | return qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); | 1130 | spin_lock_bh(&p_hwfn->mcp_info->unload_lock); |
| | 1131 | set_bit(QED_MCP_BYPASS_PROC_BIT, |
| | 1132 | &p_hwfn->mcp_info->mcp_handling_status); |
| | 1133 | spin_unlock_bh(&p_hwfn->mcp_info->unload_lock); |
| | 1134 | |
| | 1135 | rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params); |
| | 1136 | |
| | 1137 | while (test_bit(QED_MCP_IN_PROCESSING_BIT, |
| | 1138 | &p_hwfn->mcp_info->mcp_handling_status) && --cnt) |
| | 1139 | msleep(MFW_COMPLETION_INTERVAL_MS); |
| | 1140 | |
| | 1141 | if (!cnt) |
| | 1142 | DP_NOTICE(p_hwfn, |
| | 1143 | "Failed to wait MFW event completion after %d msec\n", |
| | 1144 | MFW_COMPLETION_MAX_ITER * MFW_COMPLETION_INTERVAL_MS); |
| | 1145 | |
| | 1146 | return rc; |
| 1125 | } | 1147 | } |
| 1126 | | 1148 | |
| 1127 | int qed_mcp_unload_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | 1149 | int qed_mcp_unload_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) |
| @@ -2021,6 +2043,19 @@ int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, · 893 unmodified lines |
| 2021 | "Msg [%d] - old CMD 0x%02x, new CMD 0x%02x\n", | 2043 | "Msg [%d] - old CMD 0x%02x, new CMD 0x%02x\n", |
| 2022 | i, info->mfw_mb_shadow[i], info->mfw_mb_cur[i]); | 2044 | i, info->mfw_mb_shadow[i], info->mfw_mb_cur[i]); |
| 2023 | | 2045 | |
| | 2046 | spin_lock_bh(&p_hwfn->mcp_info->unload_lock); |
| | 2047 | if (test_bit(QED_MCP_BYPASS_PROC_BIT, |
| | 2048 | &p_hwfn->mcp_info->mcp_handling_status)) { |
| | 2049 | spin_unlock_bh(&p_hwfn->mcp_info->unload_lock); |
| | 2050 | DP_INFO(p_hwfn, |
| | 2051 | "Msg [%d] is bypassed on unload flow\n", i); |
| | 2052 | continue; |
| | 2053 | } |
| | 2054 | |
| | 2055 | set_bit(QED_MCP_IN_PROCESSING_BIT, |
| | 2056 | &p_hwfn->mcp_info->mcp_handling_status); |
| | 2057 | spin_unlock_bh(&p_hwfn->mcp_info->unload_lock); |
| | 2058 | |
| 2024 | switch (i) { | 2059 | switch (i) { |
| 2025 | case MFW_DRV_MSG_LINK_CHANGE: | 2060 | case MFW_DRV_MSG_LINK_CHANGE: |
| 2026 | qed_mcp_handle_link_change(p_hwfn, p_ptt, false); | 2061 | qed_mcp_handle_link_change(p_hwfn, p_ptt, false); |
| @@ -2074,6 +2109,9 @@ int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, · 47 unmodified lines |
| 2074 | DP_INFO(p_hwfn, "Unimplemented MFW message %d\n", i); | 2109 | DP_INFO(p_hwfn, "Unimplemented MFW message %d\n", i); |
| 2075 | rc = -EINVAL; | 2110 | rc = -EINVAL; |
| 2076 | } | 2111 | } |
| | 2112 | |
| | 2113 | clear_bit(QED_MCP_IN_PROCESSING_BIT, |
| | 2114 | &p_hwfn->mcp_info->mcp_handling_status); |
| 2077 | } | 2115 | } |
| 2078 | | 2116 | |
| 2079 | /* ACK everything */ | 2117 | /* ACK everything */ |