| @@ -140,7 +140,7 @@ static struct qed_mcp_cmd_elem *qed_mcp_cmd_get_elem(struct qed_hwfn *p_hwfn, · 139 unmodified lines |
| 140 | 140 | int qed_mcp_free(struct qed_hwfn *p_hwfn) |
| 141 | 141 | { |
| 142 | 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 | 145 | kfree(p_hwfn->mcp_info->mfw_mb_cur); |
| 146 | 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 | 249 | /* Initialize the MFW spinlock */ |
| 250 | 250 | spin_lock_init(&p_info->cmd_lock); |
| 251 | 251 | spin_lock_init(&p_info->link_lock); |
| 252 | + spin_lock_init(&p_info->unload_lock); |
| 252 | 253 | |
| 253 | 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 | 1096 | return 0; |
| 1096 | 1097 | } |
| 1097 | 1098 | |
| 1099 | +#define MFW_COMPLETION_MAX_ITER 5000 |
| 1100 | +#define MFW_COMPLETION_INTERVAL_MS 1 |
| 1101 | + |
| 1098 | 1102 | int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) |
| 1099 | 1103 | { |
| 1100 | 1104 | struct qed_mcp_mb_params mb_params; |
| 1105 | + u32 cnt = MFW_COMPLETION_MAX_ITER; |
| 1101 | 1106 | u32 wol_param; |
| 1107 | + int rc; |
| 1102 | 1108 | |
| 1103 | 1109 | switch (p_hwfn->cdev->wol_config) { |
| 1104 | 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 | 1127 | mb_params.param = wol_param; |
| 1122 | 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 | 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 | 2043 | "Msg [%d] - old CMD 0x%02x, new CMD 0x%02x\n", |
| 2022 | 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 | 2059 | switch (i) { |
| 2025 | 2060 | case MFW_DRV_MSG_LINK_CHANGE: |
| 2026 | 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 | 2109 | DP_INFO(p_hwfn, "Unimplemented MFW message %d\n", i); |
| 2075 | 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 | 2117 | /* ACK everything */ |