diff options
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed.h | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_dev.c | 158 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_dev_api.h | 12 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_hsi.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_hw.c | 11 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_int.c | 126 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_int.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_main.c | 30 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_mcp.c | 115 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_mcp.h | 42 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_reg_addr.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_spq.c | 22 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_sriov.c | 9 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qede/qede.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qede/qede_main.c | 300 | ||||
| -rw-r--r-- | drivers/net/ethernet/qlogic/qede/qede_rdma.c | 64 | ||||
| -rw-r--r-- | include/linux/qed/qed_if.h | 20 | ||||
| -rw-r--r-- | include/linux/qed/qede_rdma.h | 21 |
18 files changed, 202 insertions, 743 deletions
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h index 3b0955d34716..24a90163775e 100644 --- a/drivers/net/ethernet/qlogic/qed/qed.h +++ b/drivers/net/ethernet/qlogic/qed/qed.h | |||
| @@ -554,6 +554,7 @@ struct qed_hwfn { | |||
| 554 | u8 dp_level; | 554 | u8 dp_level; |
| 555 | char name[NAME_SIZE]; | 555 | char name[NAME_SIZE]; |
| 556 | 556 | ||
| 557 | bool first_on_engine; | ||
| 557 | bool hw_init_done; | 558 | bool hw_init_done; |
| 558 | 559 | ||
| 559 | u8 num_funcs_on_engine; | 560 | u8 num_funcs_on_engine; |
| @@ -804,9 +805,6 @@ struct qed_dev { | |||
| 804 | 805 | ||
| 805 | u32 mcp_nvm_resp; | 806 | u32 mcp_nvm_resp; |
| 806 | 807 | ||
| 807 | /* Recovery */ | ||
| 808 | bool recov_in_prog; | ||
| 809 | |||
| 810 | /* Linux specific here */ | 808 | /* Linux specific here */ |
| 811 | struct qede_dev *edev; | 809 | struct qede_dev *edev; |
| 812 | struct pci_dev *pdev; | 810 | struct pci_dev *pdev; |
| @@ -946,7 +944,6 @@ void qed_link_update(struct qed_hwfn *hwfn, struct qed_ptt *ptt); | |||
| 946 | u32 qed_unzip_data(struct qed_hwfn *p_hwfn, | 944 | u32 qed_unzip_data(struct qed_hwfn *p_hwfn, |
| 947 | u32 input_len, u8 *input_buf, | 945 | u32 input_len, u8 *input_buf, |
| 948 | u32 max_size, u8 *unzip_buf); | 946 | u32 max_size, u8 *unzip_buf); |
| 949 | void qed_schedule_recovery_handler(struct qed_hwfn *p_hwfn); | ||
| 950 | void qed_get_protocol_stats(struct qed_dev *cdev, | 947 | void qed_get_protocol_stats(struct qed_dev *cdev, |
| 951 | enum qed_mcp_protocol_type type, | 948 | enum qed_mcp_protocol_type type, |
| 952 | union qed_mcp_protocol_stats *stats); | 949 | union qed_mcp_protocol_stats *stats); |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index b17003d9066c..8f6551421945 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c | |||
| @@ -1959,6 +1959,11 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, | |||
| 1959 | (p_hwfn->hw_info.personality == QED_PCI_FCOE) ? 1 : 0); | 1959 | (p_hwfn->hw_info.personality == QED_PCI_FCOE) ? 1 : 0); |
| 1960 | STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_ROCE_RT_OFFSET, 0); | 1960 | STORE_RT_REG(p_hwfn, PRS_REG_SEARCH_ROCE_RT_OFFSET, 0); |
| 1961 | 1961 | ||
| 1962 | /* Cleanup chip from previous driver if such remains exist */ | ||
| 1963 | rc = qed_final_cleanup(p_hwfn, p_ptt, rel_pf_id, false); | ||
| 1964 | if (rc) | ||
| 1965 | return rc; | ||
| 1966 | |||
| 1962 | /* Sanity check before the PF init sequence that uses DMAE */ | 1967 | /* Sanity check before the PF init sequence that uses DMAE */ |
| 1963 | rc = qed_dmae_sanity(p_hwfn, p_ptt, "pf_phase"); | 1968 | rc = qed_dmae_sanity(p_hwfn, p_ptt, "pf_phase"); |
| 1964 | if (rc) | 1969 | if (rc) |
| @@ -2002,15 +2007,17 @@ static int qed_hw_init_pf(struct qed_hwfn *p_hwfn, | |||
| 2002 | return rc; | 2007 | return rc; |
| 2003 | } | 2008 | } |
| 2004 | 2009 | ||
| 2005 | int qed_pglueb_set_pfid_enable(struct qed_hwfn *p_hwfn, | 2010 | static int qed_change_pci_hwfn(struct qed_hwfn *p_hwfn, |
| 2006 | struct qed_ptt *p_ptt, bool b_enable) | 2011 | struct qed_ptt *p_ptt, |
| 2012 | u8 enable) | ||
| 2007 | { | 2013 | { |
| 2008 | u32 delay_idx = 0, val, set_val = b_enable ? 1 : 0; | 2014 | u32 delay_idx = 0, val, set_val = enable ? 1 : 0; |
| 2009 | 2015 | ||
| 2010 | /* Configure the PF's internal FID_enable for master transactions */ | 2016 | /* Change PF in PXP */ |
| 2011 | qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, set_val); | 2017 | qed_wr(p_hwfn, p_ptt, |
| 2018 | PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, set_val); | ||
| 2012 | 2019 | ||
| 2013 | /* Wait until value is set - try for 1 second every 50us */ | 2020 | /* wait until value is set - try for 1 second every 50us */ |
| 2014 | for (delay_idx = 0; delay_idx < 20000; delay_idx++) { | 2021 | for (delay_idx = 0; delay_idx < 20000; delay_idx++) { |
| 2015 | val = qed_rd(p_hwfn, p_ptt, | 2022 | val = qed_rd(p_hwfn, p_ptt, |
| 2016 | PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER); | 2023 | PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER); |
| @@ -2064,19 +2071,13 @@ static int qed_vf_start(struct qed_hwfn *p_hwfn, | |||
| 2064 | return 0; | 2071 | return 0; |
| 2065 | } | 2072 | } |
| 2066 | 2073 | ||
| 2067 | static void qed_pglueb_clear_err(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | ||
| 2068 | { | ||
| 2069 | qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_WAS_ERROR_PF_31_0_CLR, | ||
| 2070 | BIT(p_hwfn->abs_pf_id)); | ||
| 2071 | } | ||
| 2072 | |||
| 2073 | int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) | 2074 | int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) |
| 2074 | { | 2075 | { |
| 2075 | struct qed_load_req_params load_req_params; | 2076 | struct qed_load_req_params load_req_params; |
| 2076 | u32 load_code, resp, param, drv_mb_param; | 2077 | u32 load_code, resp, param, drv_mb_param; |
| 2077 | bool b_default_mtu = true; | 2078 | bool b_default_mtu = true; |
| 2078 | struct qed_hwfn *p_hwfn; | 2079 | struct qed_hwfn *p_hwfn; |
| 2079 | int rc = 0, i; | 2080 | int rc = 0, mfw_rc, i; |
| 2080 | u16 ether_type; | 2081 | u16 ether_type; |
| 2081 | 2082 | ||
| 2082 | if ((p_params->int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) { | 2083 | if ((p_params->int_mode == QED_INT_MODE_MSI) && (cdev->num_hwfns > 1)) { |
| @@ -2091,7 +2092,7 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) | |||
| 2091 | } | 2092 | } |
| 2092 | 2093 | ||
| 2093 | for_each_hwfn(cdev, i) { | 2094 | for_each_hwfn(cdev, i) { |
| 2094 | p_hwfn = &cdev->hwfns[i]; | 2095 | struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; |
| 2095 | 2096 | ||
| 2096 | /* If management didn't provide a default, set one of our own */ | 2097 | /* If management didn't provide a default, set one of our own */ |
| 2097 | if (!p_hwfn->hw_info.mtu) { | 2098 | if (!p_hwfn->hw_info.mtu) { |
| @@ -2104,6 +2105,9 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) | |||
| 2104 | continue; | 2105 | continue; |
| 2105 | } | 2106 | } |
| 2106 | 2107 | ||
| 2108 | /* Enable DMAE in PXP */ | ||
| 2109 | rc = qed_change_pci_hwfn(p_hwfn, p_hwfn->p_main_ptt, true); | ||
| 2110 | |||
| 2107 | rc = qed_calc_hw_mode(p_hwfn); | 2111 | rc = qed_calc_hw_mode(p_hwfn); |
| 2108 | if (rc) | 2112 | if (rc) |
| 2109 | return rc; | 2113 | return rc; |
| @@ -2140,43 +2144,12 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) | |||
| 2140 | "Load request was sent. Load code: 0x%x\n", | 2144 | "Load request was sent. Load code: 0x%x\n", |
| 2141 | load_code); | 2145 | load_code); |
| 2142 | 2146 | ||
| 2143 | /* Only relevant for recovery: | ||
| 2144 | * Clear the indication after LOAD_REQ is responded by the MFW. | ||
| 2145 | */ | ||
| 2146 | cdev->recov_in_prog = false; | ||
| 2147 | |||
| 2148 | qed_mcp_set_capabilities(p_hwfn, p_hwfn->p_main_ptt); | 2147 | qed_mcp_set_capabilities(p_hwfn, p_hwfn->p_main_ptt); |
| 2149 | 2148 | ||
| 2150 | qed_reset_mb_shadow(p_hwfn, p_hwfn->p_main_ptt); | 2149 | qed_reset_mb_shadow(p_hwfn, p_hwfn->p_main_ptt); |
| 2151 | 2150 | ||
| 2152 | /* Clean up chip from previous driver if such remains exist. | 2151 | p_hwfn->first_on_engine = (load_code == |
| 2153 | * This is not needed when the PF is the first one on the | 2152 | FW_MSG_CODE_DRV_LOAD_ENGINE); |
| 2154 | * engine, since afterwards we are going to init the FW. | ||
| 2155 | */ | ||
| 2156 | if (load_code != FW_MSG_CODE_DRV_LOAD_ENGINE) { | ||
| 2157 | rc = qed_final_cleanup(p_hwfn, p_hwfn->p_main_ptt, | ||
| 2158 | p_hwfn->rel_pf_id, false); | ||
| 2159 | if (rc) { | ||
| 2160 | DP_NOTICE(p_hwfn, "Final cleanup failed\n"); | ||
| 2161 | goto load_err; | ||
| 2162 | } | ||
| 2163 | } | ||
| 2164 | |||
| 2165 | /* Log and clear previous pglue_b errors if such exist */ | ||
| 2166 | qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_main_ptt); | ||
| 2167 | |||
| 2168 | /* Enable the PF's internal FID_enable in the PXP */ | ||
| 2169 | rc = qed_pglueb_set_pfid_enable(p_hwfn, p_hwfn->p_main_ptt, | ||
| 2170 | true); | ||
| 2171 | if (rc) | ||
| 2172 | goto load_err; | ||
| 2173 | |||
| 2174 | /* Clear the pglue_b was_error indication. | ||
| 2175 | * In E4 it must be done after the BME and the internal | ||
| 2176 | * FID_enable for the PF are set, since VDMs may cause the | ||
| 2177 | * indication to be set again. | ||
| 2178 | */ | ||
| 2179 | qed_pglueb_clear_err(p_hwfn, p_hwfn->p_main_ptt); | ||
| 2180 | 2153 | ||
| 2181 | switch (load_code) { | 2154 | switch (load_code) { |
| 2182 | case FW_MSG_CODE_DRV_LOAD_ENGINE: | 2155 | case FW_MSG_CODE_DRV_LOAD_ENGINE: |
| @@ -2207,29 +2180,39 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) | |||
| 2207 | break; | 2180 | break; |
| 2208 | } | 2181 | } |
| 2209 | 2182 | ||
| 2210 | if (rc) { | 2183 | if (rc) |
| 2211 | DP_NOTICE(p_hwfn, | 2184 | DP_NOTICE(p_hwfn, |
| 2212 | "init phase failed for loadcode 0x%x (rc %d)\n", | 2185 | "init phase failed for loadcode 0x%x (rc %d)\n", |
| 2213 | load_code, rc); | 2186 | load_code, rc); |
| 2214 | goto load_err; | ||
| 2215 | } | ||
| 2216 | 2187 | ||
| 2217 | rc = qed_mcp_load_done(p_hwfn, p_hwfn->p_main_ptt); | 2188 | /* ACK mfw regardless of success or failure of initialization */ |
| 2189 | mfw_rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, | ||
| 2190 | DRV_MSG_CODE_LOAD_DONE, | ||
| 2191 | 0, &load_code, ¶m); | ||
| 2218 | if (rc) | 2192 | if (rc) |
| 2219 | return rc; | 2193 | return rc; |
| 2194 | if (mfw_rc) { | ||
| 2195 | DP_NOTICE(p_hwfn, "Failed sending LOAD_DONE command\n"); | ||
| 2196 | return mfw_rc; | ||
| 2197 | } | ||
| 2198 | |||
| 2199 | /* Check if there is a DID mismatch between nvm-cfg/efuse */ | ||
| 2200 | if (param & FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR) | ||
| 2201 | DP_NOTICE(p_hwfn, | ||
| 2202 | "warning: device configuration is not supported on this board type. The device may not function as expected.\n"); | ||
| 2220 | 2203 | ||
| 2221 | /* send DCBX attention request command */ | 2204 | /* send DCBX attention request command */ |
| 2222 | DP_VERBOSE(p_hwfn, | 2205 | DP_VERBOSE(p_hwfn, |
| 2223 | QED_MSG_DCB, | 2206 | QED_MSG_DCB, |
| 2224 | "sending phony dcbx set command to trigger DCBx attention handling\n"); | 2207 | "sending phony dcbx set command to trigger DCBx attention handling\n"); |
| 2225 | rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, | 2208 | mfw_rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt, |
| 2226 | DRV_MSG_CODE_SET_DCBX, | 2209 | DRV_MSG_CODE_SET_DCBX, |
| 2227 | 1 << DRV_MB_PARAM_DCBX_NOTIFY_SHIFT, | 2210 | 1 << DRV_MB_PARAM_DCBX_NOTIFY_SHIFT, |
| 2228 | &resp, ¶m); | 2211 | &load_code, ¶m); |
| 2229 | if (rc) { | 2212 | if (mfw_rc) { |
| 2230 | DP_NOTICE(p_hwfn, | 2213 | DP_NOTICE(p_hwfn, |
| 2231 | "Failed to send DCBX attention request\n"); | 2214 | "Failed to send DCBX attention request\n"); |
| 2232 | return rc; | 2215 | return mfw_rc; |
| 2233 | } | 2216 | } |
| 2234 | 2217 | ||
| 2235 | p_hwfn->hw_init_done = true; | 2218 | p_hwfn->hw_init_done = true; |
| @@ -2278,12 +2261,6 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) | |||
| 2278 | } | 2261 | } |
| 2279 | 2262 | ||
| 2280 | return 0; | 2263 | return 0; |
| 2281 | |||
| 2282 | load_err: | ||
| 2283 | /* The MFW load lock should be released also when initialization fails. | ||
| 2284 | */ | ||
| 2285 | qed_mcp_load_done(p_hwfn, p_hwfn->p_main_ptt); | ||
| 2286 | return rc; | ||
| 2287 | } | 2264 | } |
| 2288 | 2265 | ||
| 2289 | #define QED_HW_STOP_RETRY_LIMIT (10) | 2266 | #define QED_HW_STOP_RETRY_LIMIT (10) |
| @@ -2296,9 +2273,6 @@ static void qed_hw_timers_stop(struct qed_dev *cdev, | |||
| 2296 | qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_CONN, 0x0); | 2273 | qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_CONN, 0x0); |
| 2297 | qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, 0x0); | 2274 | qed_wr(p_hwfn, p_ptt, TM_REG_PF_ENABLE_TASK, 0x0); |
| 2298 | 2275 | ||
| 2299 | if (cdev->recov_in_prog) | ||
| 2300 | return; | ||
| 2301 | |||
| 2302 | for (i = 0; i < QED_HW_STOP_RETRY_LIMIT; i++) { | 2276 | for (i = 0; i < QED_HW_STOP_RETRY_LIMIT; i++) { |
| 2303 | if ((!qed_rd(p_hwfn, p_ptt, | 2277 | if ((!qed_rd(p_hwfn, p_ptt, |
| 2304 | TM_REG_PF_SCAN_ACTIVE_CONN)) && | 2278 | TM_REG_PF_SCAN_ACTIVE_CONN)) && |
| @@ -2361,14 +2335,12 @@ int qed_hw_stop(struct qed_dev *cdev) | |||
| 2361 | p_hwfn->hw_init_done = false; | 2335 | p_hwfn->hw_init_done = false; |
| 2362 | 2336 | ||
| 2363 | /* Send unload command to MCP */ | 2337 | /* Send unload command to MCP */ |
| 2364 | if (!cdev->recov_in_prog) { | 2338 | rc = qed_mcp_unload_req(p_hwfn, p_ptt); |
| 2365 | rc = qed_mcp_unload_req(p_hwfn, p_ptt); | 2339 | if (rc) { |
| 2366 | if (rc) { | 2340 | DP_NOTICE(p_hwfn, |
| 2367 | DP_NOTICE(p_hwfn, | 2341 | "Failed sending a UNLOAD_REQ command. rc = %d.\n", |
| 2368 | "Failed sending a UNLOAD_REQ command. rc = %d.\n", | 2342 | rc); |
| 2369 | rc); | 2343 | rc2 = -EINVAL; |
| 2370 | rc2 = -EINVAL; | ||
| 2371 | } | ||
| 2372 | } | 2344 | } |
| 2373 | 2345 | ||
| 2374 | qed_slowpath_irq_sync(p_hwfn); | 2346 | qed_slowpath_irq_sync(p_hwfn); |
| @@ -2410,31 +2382,27 @@ int qed_hw_stop(struct qed_dev *cdev) | |||
| 2410 | qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_DB_ENABLE, 0); | 2382 | qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_DB_ENABLE, 0); |
| 2411 | qed_wr(p_hwfn, p_ptt, QM_REG_PF_EN, 0); | 2383 | qed_wr(p_hwfn, p_ptt, QM_REG_PF_EN, 0); |
| 2412 | 2384 | ||
| 2413 | if (!cdev->recov_in_prog) { | 2385 | qed_mcp_unload_done(p_hwfn, p_ptt); |
| 2414 | rc = qed_mcp_unload_done(p_hwfn, p_ptt); | 2386 | if (rc) { |
| 2415 | if (rc) { | 2387 | DP_NOTICE(p_hwfn, |
| 2416 | DP_NOTICE(p_hwfn, | 2388 | "Failed sending a UNLOAD_DONE command. rc = %d.\n", |
| 2417 | "Failed sending a UNLOAD_DONE command. rc = %d.\n", | 2389 | rc); |
| 2418 | rc); | 2390 | rc2 = -EINVAL; |
| 2419 | rc2 = -EINVAL; | ||
| 2420 | } | ||
| 2421 | } | 2391 | } |
| 2422 | } | 2392 | } |
| 2423 | 2393 | ||
| 2424 | if (IS_PF(cdev) && !cdev->recov_in_prog) { | 2394 | if (IS_PF(cdev)) { |
| 2425 | p_hwfn = QED_LEADING_HWFN(cdev); | 2395 | p_hwfn = QED_LEADING_HWFN(cdev); |
| 2426 | p_ptt = QED_LEADING_HWFN(cdev)->p_main_ptt; | 2396 | p_ptt = QED_LEADING_HWFN(cdev)->p_main_ptt; |
| 2427 | 2397 | ||
| 2428 | /* Clear the PF's internal FID_enable in the PXP. | 2398 | /* Disable DMAE in PXP - in CMT, this should only be done for |
| 2429 | * In CMT this should only be done for first hw-function, and | 2399 | * first hw-function, and only after all transactions have |
| 2430 | * only after all transactions have stopped for all active | 2400 | * stopped for all active hw-functions. |
| 2431 | * hw-functions. | ||
| 2432 | */ | 2401 | */ |
| 2433 | rc = qed_pglueb_set_pfid_enable(p_hwfn, p_ptt, false); | 2402 | rc = qed_change_pci_hwfn(p_hwfn, p_ptt, false); |
| 2434 | if (rc) { | 2403 | if (rc) { |
| 2435 | DP_NOTICE(p_hwfn, | 2404 | DP_NOTICE(p_hwfn, |
| 2436 | "qed_pglueb_set_pfid_enable() failed. rc = %d.\n", | 2405 | "qed_change_pci_hwfn failed. rc = %d.\n", rc); |
| 2437 | rc); | ||
| 2438 | rc2 = -EINVAL; | 2406 | rc2 = -EINVAL; |
| 2439 | } | 2407 | } |
| 2440 | } | 2408 | } |
| @@ -2534,8 +2502,9 @@ static void qed_hw_hwfn_prepare(struct qed_hwfn *p_hwfn) | |||
| 2534 | PGLUE_B_REG_PGL_ADDR_94_F0_BB, 0); | 2502 | PGLUE_B_REG_PGL_ADDR_94_F0_BB, 0); |
| 2535 | } | 2503 | } |
| 2536 | 2504 | ||
| 2537 | /* Clean previous pglue_b errors if such exist */ | 2505 | /* Clean Previous errors if such exist */ |
| 2538 | qed_pglueb_clear_err(p_hwfn, p_hwfn->p_main_ptt); | 2506 | qed_wr(p_hwfn, p_hwfn->p_main_ptt, |
| 2507 | PGLUE_B_REG_WAS_ERROR_PF_31_0_CLR, 1 << p_hwfn->abs_pf_id); | ||
| 2539 | 2508 | ||
| 2540 | /* enable internal target-read */ | 2509 | /* enable internal target-read */ |
| 2541 | qed_wr(p_hwfn, p_hwfn->p_main_ptt, | 2510 | qed_wr(p_hwfn, p_hwfn->p_main_ptt, |
| @@ -3471,7 +3440,6 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn, | |||
| 3471 | void __iomem *p_doorbells, | 3440 | void __iomem *p_doorbells, |
| 3472 | enum qed_pci_personality personality) | 3441 | enum qed_pci_personality personality) |
| 3473 | { | 3442 | { |
| 3474 | struct qed_dev *cdev = p_hwfn->cdev; | ||
| 3475 | int rc = 0; | 3443 | int rc = 0; |
| 3476 | 3444 | ||
| 3477 | /* Split PCI bars evenly between hwfns */ | 3445 | /* Split PCI bars evenly between hwfns */ |
| @@ -3524,7 +3492,7 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn, | |||
| 3524 | /* Sending a mailbox to the MFW should be done after qed_get_hw_info() | 3492 | /* Sending a mailbox to the MFW should be done after qed_get_hw_info() |
| 3525 | * is called as it sets the ports number in an engine. | 3493 | * is called as it sets the ports number in an engine. |
| 3526 | */ | 3494 | */ |
| 3527 | if (IS_LEAD_HWFN(p_hwfn) && !cdev->recov_in_prog) { | 3495 | if (IS_LEAD_HWFN(p_hwfn)) { |
| 3528 | rc = qed_mcp_initiate_pf_flr(p_hwfn, p_hwfn->p_main_ptt); | 3496 | rc = qed_mcp_initiate_pf_flr(p_hwfn, p_hwfn->p_main_ptt); |
| 3529 | if (rc) | 3497 | if (rc) |
| 3530 | DP_NOTICE(p_hwfn, "Failed to initiate PF FLR\n"); | 3498 | DP_NOTICE(p_hwfn, "Failed to initiate PF FLR\n"); |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h index e4b4e3b78e8a..acccd85170aa 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev_api.h +++ b/drivers/net/ethernet/qlogic/qed/qed_dev_api.h | |||
| @@ -473,18 +473,6 @@ int | |||
| 473 | qed_set_queue_coalesce(u16 rx_coal, u16 tx_coal, void *p_handle); | 473 | qed_set_queue_coalesce(u16 rx_coal, u16 tx_coal, void *p_handle); |
| 474 | 474 | ||
| 475 | /** | 475 | /** |
| 476 | * @brief qed_pglueb_set_pfid_enable - Enable or disable PCI BUS MASTER | ||
| 477 | * | ||
| 478 | * @param p_hwfn | ||
| 479 | * @param p_ptt | ||
| 480 | * @param b_enable - true/false | ||
| 481 | * | ||
| 482 | * @return int | ||
| 483 | */ | ||
| 484 | int qed_pglueb_set_pfid_enable(struct qed_hwfn *p_hwfn, | ||
| 485 | struct qed_ptt *p_ptt, bool b_enable); | ||
| 486 | |||
| 487 | /** | ||
| 488 | * @brief db_recovery_add - add doorbell information to the doorbell | 476 | * @brief db_recovery_add - add doorbell information to the doorbell |
| 489 | * recovery mechanism. | 477 | * recovery mechanism. |
| 490 | * | 478 | * |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 417121e74ee9..b13cfb449d8f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h | |||
| @@ -12827,7 +12827,7 @@ enum MFW_DRV_MSG_TYPE { | |||
| 12827 | MFW_DRV_MSG_LLDP_DATA_UPDATED, | 12827 | MFW_DRV_MSG_LLDP_DATA_UPDATED, |
| 12828 | MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED, | 12828 | MFW_DRV_MSG_DCBX_REMOTE_MIB_UPDATED, |
| 12829 | MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED, | 12829 | MFW_DRV_MSG_DCBX_OPERATIONAL_MIB_UPDATED, |
| 12830 | MFW_DRV_MSG_ERROR_RECOVERY, | 12830 | MFW_DRV_MSG_RESERVED4, |
| 12831 | MFW_DRV_MSG_BW_UPDATE, | 12831 | MFW_DRV_MSG_BW_UPDATE, |
| 12832 | MFW_DRV_MSG_S_TAG_UPDATE, | 12832 | MFW_DRV_MSG_S_TAG_UPDATE, |
| 12833 | MFW_DRV_MSG_GET_LAN_STATS, | 12833 | MFW_DRV_MSG_GET_LAN_STATS, |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hw.c b/drivers/net/ethernet/qlogic/qed/qed_hw.c index 72ec1c6bdf70..70504dcf4087 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hw.c +++ b/drivers/net/ethernet/qlogic/qed/qed_hw.c | |||
| @@ -703,17 +703,6 @@ static int qed_dmae_execute_command(struct qed_hwfn *p_hwfn, | |||
| 703 | int qed_status = 0; | 703 | int qed_status = 0; |
| 704 | u32 offset = 0; | 704 | u32 offset = 0; |
| 705 | 705 | ||
| 706 | if (p_hwfn->cdev->recov_in_prog) { | ||
| 707 | DP_VERBOSE(p_hwfn, | ||
| 708 | NETIF_MSG_HW, | ||
| 709 | "Recovery is in progress. Avoid DMAE transaction [{src: addr 0x%llx, type %d}, {dst: addr 0x%llx, type %d}, size %d].\n", | ||
| 710 | src_addr, src_type, dst_addr, dst_type, | ||
| 711 | size_in_dwords); | ||
| 712 | |||
| 713 | /* Let the flow complete w/o any error handling */ | ||
| 714 | return 0; | ||
| 715 | } | ||
| 716 | |||
| 717 | qed_dmae_opcode(p_hwfn, | 706 | qed_dmae_opcode(p_hwfn, |
| 718 | (src_type == QED_DMAE_ADDRESS_GRC), | 707 | (src_type == QED_DMAE_ADDRESS_GRC), |
| 719 | (dst_type == QED_DMAE_ADDRESS_GRC), | 708 | (dst_type == QED_DMAE_ADDRESS_GRC), |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index e23980e301b6..92340919d852 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c | |||
| @@ -255,114 +255,112 @@ out: | |||
| 255 | #define PGLUE_ATTENTION_ICPL_VALID (1 << 23) | 255 | #define PGLUE_ATTENTION_ICPL_VALID (1 << 23) |
| 256 | #define PGLUE_ATTENTION_ZLR_VALID (1 << 25) | 256 | #define PGLUE_ATTENTION_ZLR_VALID (1 << 25) |
| 257 | #define PGLUE_ATTENTION_ILT_VALID (1 << 23) | 257 | #define PGLUE_ATTENTION_ILT_VALID (1 << 23) |
| 258 | 258 | static int qed_pglub_rbc_attn_cb(struct qed_hwfn *p_hwfn) | |
| 259 | int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, | ||
| 260 | struct qed_ptt *p_ptt) | ||
| 261 | { | 259 | { |
| 262 | u32 tmp; | 260 | u32 tmp; |
| 263 | 261 | ||
| 264 | tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS2); | 262 | tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 263 | PGLUE_B_REG_TX_ERR_WR_DETAILS2); | ||
| 265 | if (tmp & PGLUE_ATTENTION_VALID) { | 264 | if (tmp & PGLUE_ATTENTION_VALID) { |
| 266 | u32 addr_lo, addr_hi, details; | 265 | u32 addr_lo, addr_hi, details; |
| 267 | 266 | ||
| 268 | addr_lo = qed_rd(p_hwfn, p_ptt, | 267 | addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 269 | PGLUE_B_REG_TX_ERR_WR_ADD_31_0); | 268 | PGLUE_B_REG_TX_ERR_WR_ADD_31_0); |
| 270 | addr_hi = qed_rd(p_hwfn, p_ptt, | 269 | addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 271 | PGLUE_B_REG_TX_ERR_WR_ADD_63_32); | 270 | PGLUE_B_REG_TX_ERR_WR_ADD_63_32); |
| 272 | details = qed_rd(p_hwfn, p_ptt, | 271 | details = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 273 | PGLUE_B_REG_TX_ERR_WR_DETAILS); | 272 | PGLUE_B_REG_TX_ERR_WR_DETAILS); |
| 274 | 273 | ||
| 275 | DP_NOTICE(p_hwfn, | 274 | DP_INFO(p_hwfn, |
| 276 | "Illegal write by chip to [%08x:%08x] blocked.\n" | 275 | "Illegal write by chip to [%08x:%08x] blocked.\n" |
| 277 | "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n" | 276 | "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n" |
| 278 | "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n", | 277 | "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n", |
| 279 | addr_hi, addr_lo, details, | 278 | addr_hi, addr_lo, details, |
| 280 | (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID), | 279 | (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID), |
| 281 | (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID), | 280 | (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID), |
| 282 | GET_FIELD(details, | 281 | GET_FIELD(details, |
| 283 | PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0, | 282 | PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0, |
| 284 | tmp, | 283 | tmp, |
| 285 | GET_FIELD(tmp, | 284 | GET_FIELD(tmp, |
| 286 | PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0, | 285 | PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0, |
| 287 | GET_FIELD(tmp, | 286 | GET_FIELD(tmp, |
| 288 | PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0, | 287 | PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0, |
| 289 | GET_FIELD(tmp, | 288 | GET_FIELD(tmp, |
| 290 | PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0); | 289 | PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0); |
| 291 | } | 290 | } |
| 292 | 291 | ||
| 293 | tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_RD_DETAILS2); | 292 | tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 293 | PGLUE_B_REG_TX_ERR_RD_DETAILS2); | ||
| 294 | if (tmp & PGLUE_ATTENTION_RD_VALID) { | 294 | if (tmp & PGLUE_ATTENTION_RD_VALID) { |
| 295 | u32 addr_lo, addr_hi, details; | 295 | u32 addr_lo, addr_hi, details; |
| 296 | 296 | ||
| 297 | addr_lo = qed_rd(p_hwfn, p_ptt, | 297 | addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 298 | PGLUE_B_REG_TX_ERR_RD_ADD_31_0); | 298 | PGLUE_B_REG_TX_ERR_RD_ADD_31_0); |
| 299 | addr_hi = qed_rd(p_hwfn, p_ptt, | 299 | addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 300 | PGLUE_B_REG_TX_ERR_RD_ADD_63_32); | 300 | PGLUE_B_REG_TX_ERR_RD_ADD_63_32); |
| 301 | details = qed_rd(p_hwfn, p_ptt, | 301 | details = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 302 | PGLUE_B_REG_TX_ERR_RD_DETAILS); | 302 | PGLUE_B_REG_TX_ERR_RD_DETAILS); |
| 303 | 303 | ||
| 304 | DP_NOTICE(p_hwfn, | 304 | DP_INFO(p_hwfn, |
| 305 | "Illegal read by chip from [%08x:%08x] blocked.\n" | 305 | "Illegal read by chip from [%08x:%08x] blocked.\n" |
| 306 | "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n" | 306 | " Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n" |
| 307 | "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n", | 307 | " Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n", |
| 308 | addr_hi, addr_lo, details, | 308 | addr_hi, addr_lo, details, |
| 309 | (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID), | 309 | (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID), |
| 310 | (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID), | 310 | (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID), |
| 311 | GET_FIELD(details, | 311 | GET_FIELD(details, |
| 312 | PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0, | 312 | PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0, |
| 313 | tmp, | 313 | tmp, |
| 314 | GET_FIELD(tmp, | 314 | GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 |
| 315 | PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0, | 315 | : 0, |
| 316 | GET_FIELD(tmp, | 316 | GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0, |
| 317 | PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0, | 317 | GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 |
| 318 | GET_FIELD(tmp, | 318 | : 0); |
| 319 | PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0); | ||
| 320 | } | 319 | } |
| 321 | 320 | ||
| 322 | tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS_ICPL); | 321 | tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 322 | PGLUE_B_REG_TX_ERR_WR_DETAILS_ICPL); | ||
| 323 | if (tmp & PGLUE_ATTENTION_ICPL_VALID) | 323 | if (tmp & PGLUE_ATTENTION_ICPL_VALID) |
| 324 | DP_NOTICE(p_hwfn, "ICPL error - %08x\n", tmp); | 324 | DP_INFO(p_hwfn, "ICPL error - %08x\n", tmp); |
| 325 | 325 | ||
| 326 | tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_MASTER_ZLR_ERR_DETAILS); | 326 | tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 327 | PGLUE_B_REG_MASTER_ZLR_ERR_DETAILS); | ||
| 327 | if (tmp & PGLUE_ATTENTION_ZLR_VALID) { | 328 | if (tmp & PGLUE_ATTENTION_ZLR_VALID) { |
| 328 | u32 addr_hi, addr_lo; | 329 | u32 addr_hi, addr_lo; |
| 329 | 330 | ||
| 330 | addr_lo = qed_rd(p_hwfn, p_ptt, | 331 | addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 331 | PGLUE_B_REG_MASTER_ZLR_ERR_ADD_31_0); | 332 | PGLUE_B_REG_MASTER_ZLR_ERR_ADD_31_0); |
| 332 | addr_hi = qed_rd(p_hwfn, p_ptt, | 333 | addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 333 | PGLUE_B_REG_MASTER_ZLR_ERR_ADD_63_32); | 334 | PGLUE_B_REG_MASTER_ZLR_ERR_ADD_63_32); |
| 334 | 335 | ||
| 335 | DP_NOTICE(p_hwfn, "ZLR error - %08x [Address %08x:%08x]\n", | 336 | DP_INFO(p_hwfn, "ZLR eror - %08x [Address %08x:%08x]\n", |
| 336 | tmp, addr_hi, addr_lo); | 337 | tmp, addr_hi, addr_lo); |
| 337 | } | 338 | } |
| 338 | 339 | ||
| 339 | tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_VF_ILT_ERR_DETAILS2); | 340 | tmp = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 341 | PGLUE_B_REG_VF_ILT_ERR_DETAILS2); | ||
| 340 | if (tmp & PGLUE_ATTENTION_ILT_VALID) { | 342 | if (tmp & PGLUE_ATTENTION_ILT_VALID) { |
| 341 | u32 addr_hi, addr_lo, details; | 343 | u32 addr_hi, addr_lo, details; |
| 342 | 344 | ||
| 343 | addr_lo = qed_rd(p_hwfn, p_ptt, | 345 | addr_lo = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 344 | PGLUE_B_REG_VF_ILT_ERR_ADD_31_0); | 346 | PGLUE_B_REG_VF_ILT_ERR_ADD_31_0); |
| 345 | addr_hi = qed_rd(p_hwfn, p_ptt, | 347 | addr_hi = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 346 | PGLUE_B_REG_VF_ILT_ERR_ADD_63_32); | 348 | PGLUE_B_REG_VF_ILT_ERR_ADD_63_32); |
| 347 | details = qed_rd(p_hwfn, p_ptt, | 349 | details = qed_rd(p_hwfn, p_hwfn->p_dpc_ptt, |
| 348 | PGLUE_B_REG_VF_ILT_ERR_DETAILS); | 350 | PGLUE_B_REG_VF_ILT_ERR_DETAILS); |
| 349 | 351 | ||
| 350 | DP_NOTICE(p_hwfn, | 352 | DP_INFO(p_hwfn, |
| 351 | "ILT error - Details %08x Details2 %08x [Address %08x:%08x]\n", | 353 | "ILT error - Details %08x Details2 %08x [Address %08x:%08x]\n", |
| 352 | details, tmp, addr_hi, addr_lo); | 354 | details, tmp, addr_hi, addr_lo); |
| 353 | } | 355 | } |
| 354 | 356 | ||
| 355 | /* Clear the indications */ | 357 | /* Clear the indications */ |
| 356 | qed_wr(p_hwfn, p_ptt, PGLUE_B_REG_LATCHED_ERRORS_CLR, BIT(2)); | 358 | qed_wr(p_hwfn, p_hwfn->p_dpc_ptt, |
| 359 | PGLUE_B_REG_LATCHED_ERRORS_CLR, (1 << 2)); | ||
| 357 | 360 | ||
| 358 | return 0; | 361 | return 0; |
| 359 | } | 362 | } |
| 360 | 363 | ||
| 361 | static int qed_pglueb_rbc_attn_cb(struct qed_hwfn *p_hwfn) | ||
| 362 | { | ||
| 363 | return qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_dpc_ptt); | ||
| 364 | } | ||
| 365 | |||
| 366 | #define QED_DORQ_ATTENTION_REASON_MASK (0xfffff) | 364 | #define QED_DORQ_ATTENTION_REASON_MASK (0xfffff) |
| 367 | #define QED_DORQ_ATTENTION_OPAQUE_MASK (0xffff) | 365 | #define QED_DORQ_ATTENTION_OPAQUE_MASK (0xffff) |
| 368 | #define QED_DORQ_ATTENTION_OPAQUE_SHIFT (0x0) | 366 | #define QED_DORQ_ATTENTION_OPAQUE_SHIFT (0x0) |
| @@ -542,7 +540,7 @@ static struct aeu_invert_reg aeu_descs[NUM_ATTN_REGS] = { | |||
| 542 | {"PGLUE misc_flr", ATTENTION_SINGLE, | 540 | {"PGLUE misc_flr", ATTENTION_SINGLE, |
| 543 | NULL, MAX_BLOCK_ID}, | 541 | NULL, MAX_BLOCK_ID}, |
| 544 | {"PGLUE B RBC", ATTENTION_PAR_INT, | 542 | {"PGLUE B RBC", ATTENTION_PAR_INT, |
| 545 | qed_pglueb_rbc_attn_cb, BLOCK_PGLUE_B}, | 543 | qed_pglub_rbc_attn_cb, BLOCK_PGLUE_B}, |
| 546 | {"PGLUE misc_mctp", ATTENTION_SINGLE, | 544 | {"PGLUE misc_mctp", ATTENTION_SINGLE, |
| 547 | NULL, MAX_BLOCK_ID}, | 545 | NULL, MAX_BLOCK_ID}, |
| 548 | {"Flash event", ATTENTION_SINGLE, NULL, MAX_BLOCK_ID}, | 546 | {"Flash event", ATTENTION_SINGLE, NULL, MAX_BLOCK_ID}, |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.h b/drivers/net/ethernet/qlogic/qed/qed_int.h index 1f356ed4f761..d81a62ebd524 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.h +++ b/drivers/net/ethernet/qlogic/qed/qed_int.h | |||
| @@ -431,7 +431,4 @@ int qed_int_set_timer_res(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, | |||
| 431 | 431 | ||
| 432 | #define QED_MAPPING_MEMORY_SIZE(dev) (NUM_OF_SBS(dev)) | 432 | #define QED_MAPPING_MEMORY_SIZE(dev) (NUM_OF_SBS(dev)) |
| 433 | 433 | ||
| 434 | int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, | ||
| 435 | struct qed_ptt *p_ptt); | ||
| 436 | |||
| 437 | #endif | 434 | #endif |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index b47352643fb5..6adf5bda9811 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c | |||
| @@ -359,8 +359,6 @@ static struct qed_dev *qed_probe(struct pci_dev *pdev, | |||
| 359 | 359 | ||
| 360 | qed_init_dp(cdev, params->dp_module, params->dp_level); | 360 | qed_init_dp(cdev, params->dp_module, params->dp_level); |
| 361 | 361 | ||
| 362 | cdev->recov_in_prog = params->recov_in_prog; | ||
| 363 | |||
| 364 | rc = qed_init_pci(cdev, pdev); | 362 | rc = qed_init_pci(cdev, pdev); |
| 365 | if (rc) { | 363 | if (rc) { |
| 366 | DP_ERR(cdev, "init pci failed\n"); | 364 | DP_ERR(cdev, "init pci failed\n"); |
| @@ -2205,15 +2203,6 @@ static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type, | |||
| 2205 | return qed_mcp_get_nvm_image(hwfn, type, buf, len); | 2203 | return qed_mcp_get_nvm_image(hwfn, type, buf, len); |
| 2206 | } | 2204 | } |
| 2207 | 2205 | ||
| 2208 | void qed_schedule_recovery_handler(struct qed_hwfn *p_hwfn) | ||
| 2209 | { | ||
| 2210 | struct qed_common_cb_ops *ops = p_hwfn->cdev->protocol_ops.common; | ||
| 2211 | void *cookie = p_hwfn->cdev->ops_cookie; | ||
| 2212 | |||
| 2213 | if (ops && ops->schedule_recovery_handler) | ||
| 2214 | ops->schedule_recovery_handler(cookie); | ||
| 2215 | } | ||
| 2216 | |||
| 2217 | static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal, | 2206 | static int qed_set_coalesce(struct qed_dev *cdev, u16 rx_coal, u16 tx_coal, |
| 2218 | void *handle) | 2207 | void *handle) |
| 2219 | { | 2208 | { |
| @@ -2237,23 +2226,6 @@ static int qed_set_led(struct qed_dev *cdev, enum qed_led_mode mode) | |||
| 2237 | return status; | 2226 | return status; |
| 2238 | } | 2227 | } |
| 2239 | 2228 | ||
| 2240 | static int qed_recovery_process(struct qed_dev *cdev) | ||
| 2241 | { | ||
| 2242 | struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); | ||
| 2243 | struct qed_ptt *p_ptt; | ||
| 2244 | int rc = 0; | ||
| 2245 | |||
| 2246 | p_ptt = qed_ptt_acquire(p_hwfn); | ||
| 2247 | if (!p_ptt) | ||
| 2248 | return -EAGAIN; | ||
| 2249 | |||
| 2250 | rc = qed_start_recovery_process(p_hwfn, p_ptt); | ||
| 2251 | |||
| 2252 | qed_ptt_release(p_hwfn, p_ptt); | ||
| 2253 | |||
| 2254 | return rc; | ||
| 2255 | } | ||
| 2256 | |||
| 2257 | static int qed_update_wol(struct qed_dev *cdev, bool enabled) | 2229 | static int qed_update_wol(struct qed_dev *cdev, bool enabled) |
| 2258 | { | 2230 | { |
| 2259 | struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); | 2231 | struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); |
| @@ -2408,8 +2380,6 @@ const struct qed_common_ops qed_common_ops_pass = { | |||
| 2408 | .nvm_get_image = &qed_nvm_get_image, | 2380 | .nvm_get_image = &qed_nvm_get_image, |
| 2409 | .set_coalesce = &qed_set_coalesce, | 2381 | .set_coalesce = &qed_set_coalesce, |
| 2410 | .set_led = &qed_set_led, | 2382 | .set_led = &qed_set_led, |
| 2411 | .recovery_process = &qed_recovery_process, | ||
| 2412 | .recovery_prolog = &qed_recovery_prolog, | ||
| 2413 | .update_drv_state = &qed_update_drv_state, | 2383 | .update_drv_state = &qed_update_drv_state, |
| 2414 | .update_mac = &qed_update_mac, | 2384 | .update_mac = &qed_update_mac, |
| 2415 | .update_mtu = &qed_update_mtu, | 2385 | .update_mtu = &qed_update_mtu, |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index bb8541847aa5..e7f18e34ff0d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c | |||
| @@ -1070,27 +1070,6 @@ int qed_mcp_load_req(struct qed_hwfn *p_hwfn, | |||
| 1070 | return 0; | 1070 | return 0; |
| 1071 | } | 1071 | } |
| 1072 | 1072 | ||
| 1073 | int qed_mcp_load_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | ||
| 1074 | { | ||
| 1075 | u32 resp = 0, param = 0; | ||
| 1076 | int rc; | ||
| 1077 | |||
| 1078 | rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_LOAD_DONE, 0, &resp, | ||
| 1079 | ¶m); | ||
| 1080 | if (rc) { | ||
| 1081 | DP_NOTICE(p_hwfn, | ||
| 1082 | "Failed to send a LOAD_DONE command, rc = %d\n", rc); | ||
| 1083 | return rc; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | /* Check if there is a DID mismatch between nvm-cfg/efuse */ | ||
| 1087 | if (param & FW_MB_PARAM_LOAD_DONE_DID_EFUSE_ERROR) | ||
| 1088 | DP_NOTICE(p_hwfn, | ||
| 1089 | "warning: device configuration is not supported on this board type. The device may not function as expected.\n"); | ||
| 1090 | |||
| 1091 | return 0; | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | 1073 | int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) |
| 1095 | { | 1074 | { |
| 1096 | struct qed_mcp_mb_params mb_params; | 1075 | struct qed_mcp_mb_params mb_params; |
| @@ -1549,60 +1528,6 @@ int qed_mcp_set_link(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, bool b_up) | |||
| 1549 | return 0; | 1528 | return 0; |
| 1550 | } | 1529 | } |
| 1551 | 1530 | ||
| 1552 | u32 qed_get_process_kill_counter(struct qed_hwfn *p_hwfn, | ||
| 1553 | struct qed_ptt *p_ptt) | ||
| 1554 | { | ||
| 1555 | u32 path_offsize_addr, path_offsize, path_addr, proc_kill_cnt; | ||
| 1556 | |||
| 1557 | if (IS_VF(p_hwfn->cdev)) | ||
| 1558 | return -EINVAL; | ||
| 1559 | |||
| 1560 | path_offsize_addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, | ||
| 1561 | PUBLIC_PATH); | ||
| 1562 | path_offsize = qed_rd(p_hwfn, p_ptt, path_offsize_addr); | ||
| 1563 | path_addr = SECTION_ADDR(path_offsize, QED_PATH_ID(p_hwfn)); | ||
| 1564 | |||
| 1565 | proc_kill_cnt = qed_rd(p_hwfn, p_ptt, | ||
| 1566 | path_addr + | ||
| 1567 | offsetof(struct public_path, process_kill)) & | ||
| 1568 | PROCESS_KILL_COUNTER_MASK; | ||
| 1569 | |||
| 1570 | return proc_kill_cnt; | ||
| 1571 | } | ||
| 1572 | |||
| 1573 | static void qed_mcp_handle_process_kill(struct qed_hwfn *p_hwfn, | ||
| 1574 | struct qed_ptt *p_ptt) | ||
| 1575 | { | ||
| 1576 | struct qed_dev *cdev = p_hwfn->cdev; | ||
| 1577 | u32 proc_kill_cnt; | ||
| 1578 | |||
| 1579 | /* Prevent possible attentions/interrupts during the recovery handling | ||
| 1580 | * and till its load phase, during which they will be re-enabled. | ||
| 1581 | */ | ||
| 1582 | qed_int_igu_disable_int(p_hwfn, p_ptt); | ||
| 1583 | |||
| 1584 | DP_NOTICE(p_hwfn, "Received a process kill indication\n"); | ||
| 1585 | |||
| 1586 | /* The following operations should be done once, and thus in CMT mode | ||
| 1587 | * are carried out by only the first HW function. | ||
| 1588 | */ | ||
| 1589 | if (p_hwfn != QED_LEADING_HWFN(cdev)) | ||
| 1590 | return; | ||
| 1591 | |||
| 1592 | if (cdev->recov_in_prog) { | ||
| 1593 | DP_NOTICE(p_hwfn, | ||
| 1594 | "Ignoring the indication since a recovery process is already in progress\n"); | ||
| 1595 | return; | ||
| 1596 | } | ||
| 1597 | |||
| 1598 | cdev->recov_in_prog = true; | ||
| 1599 | |||
| 1600 | proc_kill_cnt = qed_get_process_kill_counter(p_hwfn, p_ptt); | ||
| 1601 | DP_NOTICE(p_hwfn, "Process kill counter: %d\n", proc_kill_cnt); | ||
| 1602 | |||
| 1603 | qed_schedule_recovery_handler(p_hwfn); | ||
| 1604 | } | ||
| 1605 | |||
| 1606 | static void qed_mcp_send_protocol_stats(struct qed_hwfn *p_hwfn, | 1531 | static void qed_mcp_send_protocol_stats(struct qed_hwfn *p_hwfn, |
| 1607 | struct qed_ptt *p_ptt, | 1532 | struct qed_ptt *p_ptt, |
| 1608 | enum MFW_DRV_MSG_TYPE type) | 1533 | enum MFW_DRV_MSG_TYPE type) |
| @@ -1833,9 +1758,6 @@ int qed_mcp_handle_events(struct qed_hwfn *p_hwfn, | |||
| 1833 | case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE: | 1758 | case MFW_DRV_MSG_TRANSCEIVER_STATE_CHANGE: |
| 1834 | qed_mcp_handle_transceiver_change(p_hwfn, p_ptt); | 1759 | qed_mcp_handle_transceiver_change(p_hwfn, p_ptt); |
| 1835 | break; | 1760 | break; |
| 1836 | case MFW_DRV_MSG_ERROR_RECOVERY: | ||
| 1837 | qed_mcp_handle_process_kill(p_hwfn, p_ptt); | ||
| 1838 | break; | ||
| 1839 | case MFW_DRV_MSG_GET_LAN_STATS: | 1761 | case MFW_DRV_MSG_GET_LAN_STATS: |
| 1840 | case MFW_DRV_MSG_GET_FCOE_STATS: | 1762 | case MFW_DRV_MSG_GET_FCOE_STATS: |
| 1841 | case MFW_DRV_MSG_GET_ISCSI_STATS: | 1763 | case MFW_DRV_MSG_GET_ISCSI_STATS: |
| @@ -2381,43 +2303,6 @@ int qed_mcp_get_flash_size(struct qed_hwfn *p_hwfn, | |||
| 2381 | return 0; | 2303 | return 0; |
| 2382 | } | 2304 | } |
| 2383 | 2305 | ||
| 2384 | int qed_start_recovery_process(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) | ||
| 2385 | { | ||
| 2386 | struct qed_dev *cdev = p_hwfn->cdev; | ||
| 2387 | |||
| 2388 | if (cdev->recov_in_prog) { | ||
| 2389 | DP_NOTICE(p_hwfn, | ||
| 2390 | "Avoid triggering a recovery since such a process is already in progress\n"); | ||
| 2391 | return -EAGAIN; | ||
| 2392 | } | ||
| 2393 | |||
| 2394 | DP_NOTICE(p_hwfn, "Triggering a recovery process\n"); | ||
| 2395 | qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_GENERAL_ATTN_35, 0x1); | ||
| 2396 | |||
| 2397 | return 0; | ||
| 2398 | } | ||
| 2399 | |||
| 2400 | #define QED_RECOVERY_PROLOG_SLEEP_MS 100 | ||
| 2401 | |||
| 2402 | int qed_recovery_prolog(struct qed_dev *cdev) | ||
| 2403 | { | ||
| 2404 | struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); | ||
| 2405 | struct qed_ptt *p_ptt = p_hwfn->p_main_ptt; | ||
| 2406 | int rc; | ||
| 2407 | |||
| 2408 | /* Allow ongoing PCIe transactions to complete */ | ||
| 2409 | msleep(QED_RECOVERY_PROLOG_SLEEP_MS); | ||
| 2410 | |||
| 2411 | /* Clear the PF's internal FID_enable in the PXP */ | ||
| 2412 | rc = qed_pglueb_set_pfid_enable(p_hwfn, p_ptt, false); | ||
| 2413 | if (rc) | ||
| 2414 | DP_NOTICE(p_hwfn, | ||
| 2415 | "qed_pglueb_set_pfid_enable() failed. rc = %d.\n", | ||
| 2416 | rc); | ||
| 2417 | |||
| 2418 | return rc; | ||
| 2419 | } | ||
| 2420 | |||
| 2421 | static int | 2306 | static int |
| 2422 | qed_mcp_config_vf_msix_bb(struct qed_hwfn *p_hwfn, | 2307 | qed_mcp_config_vf_msix_bb(struct qed_hwfn *p_hwfn, |
| 2423 | struct qed_ptt *p_ptt, u8 vf_id, u8 num) | 2308 | struct qed_ptt *p_ptt, u8 vf_id, u8 num) |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h index 6e1d72a669ae..eddf67798d6f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h | |||
| @@ -441,38 +441,6 @@ qed_mcp_send_drv_version(struct qed_hwfn *p_hwfn, | |||
| 441 | struct qed_mcp_drv_version *p_ver); | 441 | struct qed_mcp_drv_version *p_ver); |
| 442 | 442 | ||
| 443 | /** | 443 | /** |
| 444 | * @brief Read the MFW process kill counter | ||
| 445 | * | ||
| 446 | * @param p_hwfn | ||
| 447 | * @param p_ptt | ||
| 448 | * | ||
| 449 | * @return u32 | ||
| 450 | */ | ||
| 451 | u32 qed_get_process_kill_counter(struct qed_hwfn *p_hwfn, | ||
| 452 | struct qed_ptt *p_ptt); | ||
| 453 | |||
| 454 | /** | ||
| 455 | * @brief Trigger a recovery process | ||
| 456 | * | ||
| 457 | * @param p_hwfn | ||
| 458 | * @param p_ptt | ||
| 459 | * | ||
| 460 | * @return int | ||
| 461 | */ | ||
| 462 | int qed_start_recovery_process(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); | ||
| 463 | |||
| 464 | /** | ||
| 465 | * @brief A recovery handler must call this function as its first step. | ||
| 466 | * It is assumed that the handler is not run from an interrupt context. | ||
| 467 | * | ||
| 468 | * @param cdev | ||
| 469 | * @param p_ptt | ||
| 470 | * | ||
| 471 | * @return int | ||
| 472 | */ | ||
| 473 | int qed_recovery_prolog(struct qed_dev *cdev); | ||
| 474 | |||
| 475 | /** | ||
| 476 | * @brief Notify MFW about the change in base device properties | 444 | * @brief Notify MFW about the change in base device properties |
| 477 | * | 445 | * |
| 478 | * @param p_hwfn | 446 | * @param p_hwfn |
| @@ -833,16 +801,6 @@ int qed_mcp_load_req(struct qed_hwfn *p_hwfn, | |||
| 833 | struct qed_load_req_params *p_params); | 801 | struct qed_load_req_params *p_params); |
| 834 | 802 | ||
| 835 | /** | 803 | /** |
| 836 | * @brief Sends a LOAD_DONE message to the MFW | ||
| 837 | * | ||
| 838 | * @param p_hwfn | ||
| 839 | * @param p_ptt | ||
| 840 | * | ||
| 841 | * @return int - 0 - Operation was successful. | ||
| 842 | */ | ||
| 843 | int qed_mcp_load_done(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); | ||
| 844 | |||
| 845 | /** | ||
| 846 | * @brief Sends a UNLOAD_REQ message to the MFW | 804 | * @brief Sends a UNLOAD_REQ message to the MFW |
| 847 | * | 805 | * |
| 848 | * @param p_hwfn | 806 | * @param p_hwfn |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h index 5ce825ca5f24..8939ed6e08b7 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h | |||
| @@ -518,8 +518,6 @@ | |||
| 518 | 0x180824UL | 518 | 0x180824UL |
| 519 | #define MISC_REG_AEU_GENERAL_ATTN_0 \ | 519 | #define MISC_REG_AEU_GENERAL_ATTN_0 \ |
| 520 | 0x008400UL | 520 | 0x008400UL |
| 521 | #define MISC_REG_AEU_GENERAL_ATTN_35 \ | ||
| 522 | 0x00848cUL | ||
| 523 | #define CAU_REG_SB_ADDR_MEMORY \ | 521 | #define CAU_REG_SB_ADDR_MEMORY \ |
| 524 | 0x1c8000UL | 522 | 0x1c8000UL |
| 525 | #define CAU_REG_SB_VAR_MEMORY \ | 523 | #define CAU_REG_SB_VAR_MEMORY \ |
diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c index 3e0f7c46bb1b..eb88bbc6b193 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c | |||
| @@ -790,17 +790,6 @@ static int qed_spq_pend_post(struct qed_hwfn *p_hwfn) | |||
| 790 | SPQ_HIGH_PRI_RESERVE_DEFAULT); | 790 | SPQ_HIGH_PRI_RESERVE_DEFAULT); |
| 791 | } | 791 | } |
| 792 | 792 | ||
| 793 | static void qed_spq_recov_set_ret_code(struct qed_spq_entry *p_ent, | ||
| 794 | u8 *fw_return_code) | ||
| 795 | { | ||
| 796 | if (!fw_return_code) | ||
| 797 | return; | ||
| 798 | |||
| 799 | if (p_ent->elem.hdr.protocol_id == PROTOCOLID_ROCE || | ||
| 800 | p_ent->elem.hdr.protocol_id == PROTOCOLID_IWARP) | ||
| 801 | *fw_return_code = RDMA_RETURN_OK; | ||
| 802 | } | ||
| 803 | |||
| 804 | /* Avoid overriding of SPQ entries when getting out-of-order completions, by | 793 | /* Avoid overriding of SPQ entries when getting out-of-order completions, by |
| 805 | * marking the completions in a bitmap and increasing the chain consumer only | 794 | * marking the completions in a bitmap and increasing the chain consumer only |
| 806 | * for the first successive completed entries. | 795 | * for the first successive completed entries. |
| @@ -836,17 +825,6 @@ int qed_spq_post(struct qed_hwfn *p_hwfn, | |||
| 836 | return -EINVAL; | 825 | return -EINVAL; |
| 837 | } | 826 | } |
| 838 | 827 | ||
| 839 | if (p_hwfn->cdev->recov_in_prog) { | ||
| 840 | DP_VERBOSE(p_hwfn, | ||
| 841 | QED_MSG_SPQ, | ||
| 842 | "Recovery is in progress. Skip spq post [cmd %02x protocol %02x]\n", | ||
| 843 | p_ent->elem.hdr.cmd_id, p_ent->elem.hdr.protocol_id); | ||
| 844 | |||
| 845 | /* Let the flow complete w/o any error handling */ | ||
| 846 | qed_spq_recov_set_ret_code(p_ent, fw_return_code); | ||
| 847 | return 0; | ||
| 848 | } | ||
| 849 | |||
| 850 | /* Complete the entry */ | 828 | /* Complete the entry */ |
| 851 | rc = qed_spq_fill_entry(p_hwfn, p_ent); | 829 | rc = qed_spq_fill_entry(p_hwfn, p_ent); |
| 852 | 830 | ||
diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index 71e28be58102..ca6290fa0f30 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c | |||
| @@ -4447,13 +4447,6 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled) | |||
| 4447 | if (cdev->p_iov_info && cdev->p_iov_info->num_vfs && pci_enabled) | 4447 | if (cdev->p_iov_info && cdev->p_iov_info->num_vfs && pci_enabled) |
| 4448 | pci_disable_sriov(cdev->pdev); | 4448 | pci_disable_sriov(cdev->pdev); |
| 4449 | 4449 | ||
| 4450 | if (cdev->recov_in_prog) { | ||
| 4451 | DP_VERBOSE(cdev, | ||
| 4452 | QED_MSG_IOV, | ||
| 4453 | "Skip SRIOV disable operations in the device since a recovery is in progress\n"); | ||
| 4454 | goto out; | ||
| 4455 | } | ||
| 4456 | |||
| 4457 | for_each_hwfn(cdev, i) { | 4450 | for_each_hwfn(cdev, i) { |
| 4458 | struct qed_hwfn *hwfn = &cdev->hwfns[i]; | 4451 | struct qed_hwfn *hwfn = &cdev->hwfns[i]; |
| 4459 | struct qed_ptt *ptt = qed_ptt_acquire(hwfn); | 4452 | struct qed_ptt *ptt = qed_ptt_acquire(hwfn); |
| @@ -4493,7 +4486,7 @@ int qed_sriov_disable(struct qed_dev *cdev, bool pci_enabled) | |||
| 4493 | 4486 | ||
| 4494 | qed_ptt_release(hwfn, ptt); | 4487 | qed_ptt_release(hwfn, ptt); |
| 4495 | } | 4488 | } |
| 4496 | out: | 4489 | |
| 4497 | qed_iov_set_vfs_to_disable(cdev, false); | 4490 | qed_iov_set_vfs_to_disable(cdev, false); |
| 4498 | 4491 | ||
| 4499 | return 0; | 4492 | return 0; |
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index 843416404aeb..613249d1e967 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h | |||
| @@ -162,7 +162,6 @@ struct qede_rdma_dev { | |||
| 162 | struct list_head entry; | 162 | struct list_head entry; |
| 163 | struct list_head rdma_event_list; | 163 | struct list_head rdma_event_list; |
| 164 | struct workqueue_struct *rdma_wq; | 164 | struct workqueue_struct *rdma_wq; |
| 165 | bool exp_recovery; | ||
| 166 | }; | 165 | }; |
| 167 | 166 | ||
| 168 | struct qede_ptp; | 167 | struct qede_ptp; |
| @@ -265,7 +264,6 @@ struct qede_dev { | |||
| 265 | enum QEDE_STATE { | 264 | enum QEDE_STATE { |
| 266 | QEDE_STATE_CLOSED, | 265 | QEDE_STATE_CLOSED, |
| 267 | QEDE_STATE_OPEN, | 266 | QEDE_STATE_OPEN, |
| 268 | QEDE_STATE_RECOVERY, | ||
| 269 | }; | 267 | }; |
| 270 | 268 | ||
| 271 | #define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo)) | 269 | #define HILO_U64(hi, lo) ((((u64)(hi)) << 32) + (lo)) |
| @@ -464,7 +462,6 @@ struct qede_fastpath { | |||
| 464 | #define QEDE_CSUM_UNNECESSARY BIT(1) | 462 | #define QEDE_CSUM_UNNECESSARY BIT(1) |
| 465 | #define QEDE_TUNN_CSUM_UNNECESSARY BIT(2) | 463 | #define QEDE_TUNN_CSUM_UNNECESSARY BIT(2) |
| 466 | 464 | ||
| 467 | #define QEDE_SP_RECOVERY 0 | ||
| 468 | #define QEDE_SP_RX_MODE 1 | 465 | #define QEDE_SP_RX_MODE 1 |
| 469 | 466 | ||
| 470 | #ifdef CONFIG_RFS_ACCEL | 467 | #ifdef CONFIG_RFS_ACCEL |
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index de955f2b2980..5a74fcbdbc2b 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c | |||
| @@ -133,12 +133,23 @@ static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id); | |||
| 133 | static void qede_remove(struct pci_dev *pdev); | 133 | static void qede_remove(struct pci_dev *pdev); |
| 134 | static void qede_shutdown(struct pci_dev *pdev); | 134 | static void qede_shutdown(struct pci_dev *pdev); |
| 135 | static void qede_link_update(void *dev, struct qed_link_output *link); | 135 | static void qede_link_update(void *dev, struct qed_link_output *link); |
| 136 | static void qede_schedule_recovery_handler(void *dev); | ||
| 137 | static void qede_recovery_handler(struct qede_dev *edev); | ||
| 138 | static void qede_get_eth_tlv_data(void *edev, void *data); | 136 | static void qede_get_eth_tlv_data(void *edev, void *data); |
| 139 | static void qede_get_generic_tlv_data(void *edev, | 137 | static void qede_get_generic_tlv_data(void *edev, |
| 140 | struct qed_generic_tlvs *data); | 138 | struct qed_generic_tlvs *data); |
| 141 | 139 | ||
| 140 | /* The qede lock is used to protect driver state change and driver flows that | ||
| 141 | * are not reentrant. | ||
| 142 | */ | ||
| 143 | void __qede_lock(struct qede_dev *edev) | ||
| 144 | { | ||
| 145 | mutex_lock(&edev->qede_lock); | ||
| 146 | } | ||
| 147 | |||
| 148 | void __qede_unlock(struct qede_dev *edev) | ||
| 149 | { | ||
| 150 | mutex_unlock(&edev->qede_lock); | ||
| 151 | } | ||
| 152 | |||
| 142 | #ifdef CONFIG_QED_SRIOV | 153 | #ifdef CONFIG_QED_SRIOV |
| 143 | static int qede_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan, u8 qos, | 154 | static int qede_set_vf_vlan(struct net_device *ndev, int vf, u16 vlan, u8 qos, |
| 144 | __be16 vlan_proto) | 155 | __be16 vlan_proto) |
| @@ -220,7 +231,6 @@ static struct qed_eth_cb_ops qede_ll_ops = { | |||
| 220 | .arfs_filter_op = qede_arfs_filter_op, | 231 | .arfs_filter_op = qede_arfs_filter_op, |
| 221 | #endif | 232 | #endif |
| 222 | .link_update = qede_link_update, | 233 | .link_update = qede_link_update, |
| 223 | .schedule_recovery_handler = qede_schedule_recovery_handler, | ||
| 224 | .get_generic_tlv_data = qede_get_generic_tlv_data, | 234 | .get_generic_tlv_data = qede_get_generic_tlv_data, |
| 225 | .get_protocol_tlv_data = qede_get_eth_tlv_data, | 235 | .get_protocol_tlv_data = qede_get_eth_tlv_data, |
| 226 | }, | 236 | }, |
| @@ -940,57 +950,11 @@ err: | |||
| 940 | return -ENOMEM; | 950 | return -ENOMEM; |
| 941 | } | 951 | } |
| 942 | 952 | ||
| 943 | /* The qede lock is used to protect driver state change and driver flows that | ||
| 944 | * are not reentrant. | ||
| 945 | */ | ||
| 946 | void __qede_lock(struct qede_dev *edev) | ||
| 947 | { | ||
| 948 | mutex_lock(&edev->qede_lock); | ||
| 949 | } | ||
| 950 | |||
| 951 | void __qede_unlock(struct qede_dev *edev) | ||
| 952 | { | ||
| 953 | mutex_unlock(&edev->qede_lock); | ||
| 954 | } | ||
| 955 | |||
| 956 | /* This version of the lock should be used when acquiring the RTNL lock is also | ||
| 957 | * needed in addition to the internal qede lock. | ||
| 958 | */ | ||
| 959 | void qede_lock(struct qede_dev *edev) | ||
| 960 | { | ||
| 961 | rtnl_lock(); | ||
| 962 | __qede_lock(edev); | ||
| 963 | } | ||
| 964 | |||
| 965 | void qede_unlock(struct qede_dev *edev) | ||
| 966 | { | ||
| 967 | __qede_unlock(edev); | ||
| 968 | rtnl_unlock(); | ||
| 969 | } | ||
| 970 | |||
| 971 | static void qede_sp_task(struct work_struct *work) | 953 | static void qede_sp_task(struct work_struct *work) |
| 972 | { | 954 | { |
| 973 | struct qede_dev *edev = container_of(work, struct qede_dev, | 955 | struct qede_dev *edev = container_of(work, struct qede_dev, |
| 974 | sp_task.work); | 956 | sp_task.work); |
| 975 | 957 | ||
| 976 | /* The locking scheme depends on the specific flag: | ||
| 977 | * In case of QEDE_SP_RECOVERY, acquiring the RTNL lock is required to | ||
| 978 | * ensure that ongoing flows are ended and new ones are not started. | ||
| 979 | * In other cases - only the internal qede lock should be acquired. | ||
| 980 | */ | ||
| 981 | |||
| 982 | if (test_and_clear_bit(QEDE_SP_RECOVERY, &edev->sp_flags)) { | ||
| 983 | #ifdef CONFIG_QED_SRIOV | ||
| 984 | /* SRIOV must be disabled outside the lock to avoid a deadlock. | ||
| 985 | * The recovery of the active VFs is currently not supported. | ||
| 986 | */ | ||
| 987 | qede_sriov_configure(edev->pdev, 0); | ||
| 988 | #endif | ||
| 989 | qede_lock(edev); | ||
| 990 | qede_recovery_handler(edev); | ||
| 991 | qede_unlock(edev); | ||
| 992 | } | ||
| 993 | |||
| 994 | __qede_lock(edev); | 958 | __qede_lock(edev); |
| 995 | 959 | ||
| 996 | if (test_and_clear_bit(QEDE_SP_RX_MODE, &edev->sp_flags)) | 960 | if (test_and_clear_bit(QEDE_SP_RX_MODE, &edev->sp_flags)) |
| @@ -1067,13 +1031,8 @@ static void qede_log_probe(struct qede_dev *edev) | |||
| 1067 | 1031 | ||
| 1068 | enum qede_probe_mode { | 1032 | enum qede_probe_mode { |
| 1069 | QEDE_PROBE_NORMAL, | 1033 | QEDE_PROBE_NORMAL, |
| 1070 | QEDE_PROBE_RECOVERY, | ||
| 1071 | }; | 1034 | }; |
| 1072 | 1035 | ||
| 1073 | #define QEDE_RDMA_PROBE_MODE(mode) \ | ||
| 1074 | ((mode) == QEDE_PROBE_NORMAL ? QEDE_RDMA_PROBE_NORMAL \ | ||
| 1075 | : QEDE_RDMA_PROBE_RECOVERY) | ||
| 1076 | |||
| 1077 | static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, | 1036 | static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, |
| 1078 | bool is_vf, enum qede_probe_mode mode) | 1037 | bool is_vf, enum qede_probe_mode mode) |
| 1079 | { | 1038 | { |
| @@ -1092,7 +1051,6 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, | |||
| 1092 | probe_params.dp_module = dp_module; | 1051 | probe_params.dp_module = dp_module; |
| 1093 | probe_params.dp_level = dp_level; | 1052 | probe_params.dp_level = dp_level; |
| 1094 | probe_params.is_vf = is_vf; | 1053 | probe_params.is_vf = is_vf; |
| 1095 | probe_params.recov_in_prog = (mode == QEDE_PROBE_RECOVERY); | ||
| 1096 | cdev = qed_ops->common->probe(pdev, &probe_params); | 1054 | cdev = qed_ops->common->probe(pdev, &probe_params); |
| 1097 | if (!cdev) { | 1055 | if (!cdev) { |
| 1098 | rc = -ENODEV; | 1056 | rc = -ENODEV; |
| @@ -1120,20 +1078,11 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, | |||
| 1120 | if (rc) | 1078 | if (rc) |
| 1121 | goto err2; | 1079 | goto err2; |
| 1122 | 1080 | ||
| 1123 | if (mode != QEDE_PROBE_RECOVERY) { | 1081 | edev = qede_alloc_etherdev(cdev, pdev, &dev_info, dp_module, |
| 1124 | edev = qede_alloc_etherdev(cdev, pdev, &dev_info, dp_module, | 1082 | dp_level); |
| 1125 | dp_level); | 1083 | if (!edev) { |
| 1126 | if (!edev) { | 1084 | rc = -ENOMEM; |
| 1127 | rc = -ENOMEM; | 1085 | goto err2; |
| 1128 | goto err2; | ||
| 1129 | } | ||
| 1130 | } else { | ||
| 1131 | struct net_device *ndev = pci_get_drvdata(pdev); | ||
| 1132 | |||
| 1133 | edev = netdev_priv(ndev); | ||
| 1134 | edev->cdev = cdev; | ||
| 1135 | memset(&edev->stats, 0, sizeof(edev->stats)); | ||
| 1136 | memcpy(&edev->dev_info, &dev_info, sizeof(dev_info)); | ||
| 1137 | } | 1086 | } |
| 1138 | 1087 | ||
| 1139 | if (is_vf) | 1088 | if (is_vf) |
| @@ -1141,31 +1090,28 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, | |||
| 1141 | 1090 | ||
| 1142 | qede_init_ndev(edev); | 1091 | qede_init_ndev(edev); |
| 1143 | 1092 | ||
| 1144 | rc = qede_rdma_dev_add(edev, QEDE_RDMA_PROBE_MODE(mode)); | 1093 | rc = qede_rdma_dev_add(edev); |
| 1145 | if (rc) | 1094 | if (rc) |
| 1146 | goto err3; | 1095 | goto err3; |
| 1147 | 1096 | ||
| 1148 | if (mode != QEDE_PROBE_RECOVERY) { | 1097 | /* Prepare the lock prior to the registration of the netdev, |
| 1149 | /* Prepare the lock prior to the registration of the netdev, | 1098 | * as once it's registered we might reach flows requiring it |
| 1150 | * as once it's registered we might reach flows requiring it | 1099 | * [it's even possible to reach a flow needing it directly |
| 1151 | * [it's even possible to reach a flow needing it directly | 1100 | * from there, although it's unlikely]. |
| 1152 | * from there, although it's unlikely]. | 1101 | */ |
| 1153 | */ | 1102 | INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task); |
| 1154 | INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task); | 1103 | mutex_init(&edev->qede_lock); |
| 1155 | mutex_init(&edev->qede_lock); | 1104 | rc = register_netdev(edev->ndev); |
| 1156 | 1105 | if (rc) { | |
| 1157 | rc = register_netdev(edev->ndev); | 1106 | DP_NOTICE(edev, "Cannot register net-device\n"); |
| 1158 | if (rc) { | 1107 | goto err4; |
| 1159 | DP_NOTICE(edev, "Cannot register net-device\n"); | ||
| 1160 | goto err4; | ||
| 1161 | } | ||
| 1162 | } | 1108 | } |
| 1163 | 1109 | ||
| 1164 | edev->ops->common->set_name(cdev, edev->ndev->name); | 1110 | edev->ops->common->set_name(cdev, edev->ndev->name); |
| 1165 | 1111 | ||
| 1166 | /* PTP not supported on VFs */ | 1112 | /* PTP not supported on VFs */ |
| 1167 | if (!is_vf) | 1113 | if (!is_vf) |
| 1168 | qede_ptp_enable(edev, (mode == QEDE_PROBE_NORMAL)); | 1114 | qede_ptp_enable(edev, true); |
| 1169 | 1115 | ||
| 1170 | edev->ops->register_ops(cdev, &qede_ll_ops, edev); | 1116 | edev->ops->register_ops(cdev, &qede_ll_ops, edev); |
| 1171 | 1117 | ||
| @@ -1180,7 +1126,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, | |||
| 1180 | return 0; | 1126 | return 0; |
| 1181 | 1127 | ||
| 1182 | err4: | 1128 | err4: |
| 1183 | qede_rdma_dev_remove(edev, QEDE_RDMA_PROBE_MODE(mode)); | 1129 | qede_rdma_dev_remove(edev); |
| 1184 | err3: | 1130 | err3: |
| 1185 | free_netdev(edev->ndev); | 1131 | free_netdev(edev->ndev); |
| 1186 | err2: | 1132 | err2: |
| @@ -1216,13 +1162,8 @@ static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 1216 | 1162 | ||
| 1217 | enum qede_remove_mode { | 1163 | enum qede_remove_mode { |
| 1218 | QEDE_REMOVE_NORMAL, | 1164 | QEDE_REMOVE_NORMAL, |
| 1219 | QEDE_REMOVE_RECOVERY, | ||
| 1220 | }; | 1165 | }; |
| 1221 | 1166 | ||
| 1222 | #define QEDE_RDMA_REMOVE_MODE(mode) \ | ||
| 1223 | ((mode) == QEDE_REMOVE_NORMAL ? QEDE_RDMA_REMOVE_NORMAL \ | ||
| 1224 | : QEDE_RDMA_REMOVE_RECOVERY) | ||
| 1225 | |||
| 1226 | static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) | 1167 | static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) |
| 1227 | { | 1168 | { |
| 1228 | struct net_device *ndev = pci_get_drvdata(pdev); | 1169 | struct net_device *ndev = pci_get_drvdata(pdev); |
| @@ -1231,19 +1172,15 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) | |||
| 1231 | 1172 | ||
| 1232 | DP_INFO(edev, "Starting qede_remove\n"); | 1173 | DP_INFO(edev, "Starting qede_remove\n"); |
| 1233 | 1174 | ||
| 1234 | qede_rdma_dev_remove(edev, QEDE_RDMA_REMOVE_MODE(mode)); | 1175 | qede_rdma_dev_remove(edev); |
| 1235 | 1176 | unregister_netdev(ndev); | |
| 1236 | if (mode != QEDE_REMOVE_RECOVERY) { | 1177 | cancel_delayed_work_sync(&edev->sp_task); |
| 1237 | unregister_netdev(ndev); | ||
| 1238 | 1178 | ||
| 1239 | cancel_delayed_work_sync(&edev->sp_task); | 1179 | qede_ptp_disable(edev); |
| 1240 | 1180 | ||
| 1241 | edev->ops->common->set_power_state(cdev, PCI_D0); | 1181 | edev->ops->common->set_power_state(cdev, PCI_D0); |
| 1242 | 1182 | ||
| 1243 | pci_set_drvdata(pdev, NULL); | 1183 | pci_set_drvdata(pdev, NULL); |
| 1244 | } | ||
| 1245 | |||
| 1246 | qede_ptp_disable(edev); | ||
| 1247 | 1184 | ||
| 1248 | /* Use global ops since we've freed edev */ | 1185 | /* Use global ops since we've freed edev */ |
| 1249 | qed_ops->common->slowpath_stop(cdev); | 1186 | qed_ops->common->slowpath_stop(cdev); |
| @@ -1257,8 +1194,7 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) | |||
| 1257 | * [e.g., QED register callbacks] won't break anything when | 1194 | * [e.g., QED register callbacks] won't break anything when |
| 1258 | * accessing the netdevice. | 1195 | * accessing the netdevice. |
| 1259 | */ | 1196 | */ |
| 1260 | if (mode != QEDE_REMOVE_RECOVERY) | 1197 | free_netdev(ndev); |
| 1261 | free_netdev(ndev); | ||
| 1262 | 1198 | ||
| 1263 | dev_info(&pdev->dev, "Ending qede_remove successfully\n"); | 1199 | dev_info(&pdev->dev, "Ending qede_remove successfully\n"); |
| 1264 | } | 1200 | } |
| @@ -1603,58 +1539,6 @@ static int qede_alloc_mem_load(struct qede_dev *edev) | |||
| 1603 | return 0; | 1539 | return 0; |
| 1604 | } | 1540 | } |
| 1605 | 1541 | ||
| 1606 | static void qede_empty_tx_queue(struct qede_dev *edev, | ||
| 1607 | struct qede_tx_queue *txq) | ||
| 1608 | { | ||
| 1609 | unsigned int pkts_compl = 0, bytes_compl = 0; | ||
| 1610 | struct netdev_queue *netdev_txq; | ||
| 1611 | int rc, len = 0; | ||
| 1612 | |||
| 1613 | netdev_txq = netdev_get_tx_queue(edev->ndev, txq->ndev_txq_id); | ||
| 1614 | |||
| 1615 | while (qed_chain_get_cons_idx(&txq->tx_pbl) != | ||
| 1616 | qed_chain_get_prod_idx(&txq->tx_pbl)) { | ||
| 1617 | DP_VERBOSE(edev, NETIF_MSG_IFDOWN, | ||
| 1618 | "Freeing a packet on tx queue[%d]: chain_cons 0x%x, chain_prod 0x%x\n", | ||
| 1619 | txq->index, qed_chain_get_cons_idx(&txq->tx_pbl), | ||
| 1620 | qed_chain_get_prod_idx(&txq->tx_pbl)); | ||
| 1621 | |||
| 1622 | rc = qede_free_tx_pkt(edev, txq, &len); | ||
| 1623 | if (rc) { | ||
| 1624 | DP_NOTICE(edev, | ||
| 1625 | "Failed to free a packet on tx queue[%d]: chain_cons 0x%x, chain_prod 0x%x\n", | ||
| 1626 | txq->index, | ||
| 1627 | qed_chain_get_cons_idx(&txq->tx_pbl), | ||
| 1628 | qed_chain_get_prod_idx(&txq->tx_pbl)); | ||
| 1629 | break; | ||
| 1630 | } | ||
| 1631 | |||
| 1632 | bytes_compl += len; | ||
| 1633 | pkts_compl++; | ||
| 1634 | txq->sw_tx_cons++; | ||
| 1635 | } | ||
| 1636 | |||
| 1637 | netdev_tx_completed_queue(netdev_txq, pkts_compl, bytes_compl); | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | static void qede_empty_tx_queues(struct qede_dev *edev) | ||
| 1641 | { | ||
| 1642 | int i; | ||
| 1643 | |||
| 1644 | for_each_queue(i) | ||
| 1645 | if (edev->fp_array[i].type & QEDE_FASTPATH_TX) { | ||
| 1646 | int cos; | ||
| 1647 | |||
| 1648 | for_each_cos_in_txq(edev, cos) { | ||
| 1649 | struct qede_fastpath *fp; | ||
| 1650 | |||
| 1651 | fp = &edev->fp_array[i]; | ||
| 1652 | qede_empty_tx_queue(edev, | ||
| 1653 | &fp->txq[cos]); | ||
| 1654 | } | ||
| 1655 | } | ||
| 1656 | } | ||
| 1657 | |||
| 1658 | /* This function inits fp content and resets the SB, RXQ and TXQ structures */ | 1542 | /* This function inits fp content and resets the SB, RXQ and TXQ structures */ |
| 1659 | static void qede_init_fp(struct qede_dev *edev) | 1543 | static void qede_init_fp(struct qede_dev *edev) |
| 1660 | { | 1544 | { |
| @@ -2169,7 +2053,6 @@ out: | |||
| 2169 | 2053 | ||
| 2170 | enum qede_unload_mode { | 2054 | enum qede_unload_mode { |
| 2171 | QEDE_UNLOAD_NORMAL, | 2055 | QEDE_UNLOAD_NORMAL, |
| 2172 | QEDE_UNLOAD_RECOVERY, | ||
| 2173 | }; | 2056 | }; |
| 2174 | 2057 | ||
| 2175 | static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, | 2058 | static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, |
| @@ -2185,8 +2068,7 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, | |||
| 2185 | 2068 | ||
| 2186 | clear_bit(QEDE_FLAGS_LINK_REQUESTED, &edev->flags); | 2069 | clear_bit(QEDE_FLAGS_LINK_REQUESTED, &edev->flags); |
| 2187 | 2070 | ||
| 2188 | if (mode != QEDE_UNLOAD_RECOVERY) | 2071 | edev->state = QEDE_STATE_CLOSED; |
| 2189 | edev->state = QEDE_STATE_CLOSED; | ||
| 2190 | 2072 | ||
| 2191 | qede_rdma_dev_event_close(edev); | 2073 | qede_rdma_dev_event_close(edev); |
| 2192 | 2074 | ||
| @@ -2194,21 +2076,18 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, | |||
| 2194 | netif_tx_disable(edev->ndev); | 2076 | netif_tx_disable(edev->ndev); |
| 2195 | netif_carrier_off(edev->ndev); | 2077 | netif_carrier_off(edev->ndev); |
| 2196 | 2078 | ||
| 2197 | if (mode != QEDE_UNLOAD_RECOVERY) { | 2079 | /* Reset the link */ |
| 2198 | /* Reset the link */ | 2080 | memset(&link_params, 0, sizeof(link_params)); |
| 2199 | memset(&link_params, 0, sizeof(link_params)); | 2081 | link_params.link_up = false; |
| 2200 | link_params.link_up = false; | 2082 | edev->ops->common->set_link(edev->cdev, &link_params); |
| 2201 | edev->ops->common->set_link(edev->cdev, &link_params); | 2083 | rc = qede_stop_queues(edev); |
| 2202 | 2084 | if (rc) { | |
| 2203 | rc = qede_stop_queues(edev); | 2085 | qede_sync_free_irqs(edev); |
| 2204 | if (rc) { | 2086 | goto out; |
| 2205 | qede_sync_free_irqs(edev); | ||
| 2206 | goto out; | ||
| 2207 | } | ||
| 2208 | |||
| 2209 | DP_INFO(edev, "Stopped Queues\n"); | ||
| 2210 | } | 2087 | } |
| 2211 | 2088 | ||
| 2089 | DP_INFO(edev, "Stopped Queues\n"); | ||
| 2090 | |||
| 2212 | qede_vlan_mark_nonconfigured(edev); | 2091 | qede_vlan_mark_nonconfigured(edev); |
| 2213 | edev->ops->fastpath_stop(edev->cdev); | 2092 | edev->ops->fastpath_stop(edev->cdev); |
| 2214 | 2093 | ||
| @@ -2223,26 +2102,18 @@ static void qede_unload(struct qede_dev *edev, enum qede_unload_mode mode, | |||
| 2223 | 2102 | ||
| 2224 | qede_napi_disable_remove(edev); | 2103 | qede_napi_disable_remove(edev); |
| 2225 | 2104 | ||
| 2226 | if (mode == QEDE_UNLOAD_RECOVERY) | ||
| 2227 | qede_empty_tx_queues(edev); | ||
| 2228 | |||
| 2229 | qede_free_mem_load(edev); | 2105 | qede_free_mem_load(edev); |
| 2230 | qede_free_fp_array(edev); | 2106 | qede_free_fp_array(edev); |
| 2231 | 2107 | ||
| 2232 | out: | 2108 | out: |
| 2233 | if (!is_locked) | 2109 | if (!is_locked) |
| 2234 | __qede_unlock(edev); | 2110 | __qede_unlock(edev); |
| 2235 | |||
| 2236 | if (mode != QEDE_UNLOAD_RECOVERY) | ||
| 2237 | DP_NOTICE(edev, "Link is down\n"); | ||
| 2238 | |||
| 2239 | DP_INFO(edev, "Ending qede unload\n"); | 2111 | DP_INFO(edev, "Ending qede unload\n"); |
| 2240 | } | 2112 | } |
| 2241 | 2113 | ||
| 2242 | enum qede_load_mode { | 2114 | enum qede_load_mode { |
| 2243 | QEDE_LOAD_NORMAL, | 2115 | QEDE_LOAD_NORMAL, |
| 2244 | QEDE_LOAD_RELOAD, | 2116 | QEDE_LOAD_RELOAD, |
| 2245 | QEDE_LOAD_RECOVERY, | ||
| 2246 | }; | 2117 | }; |
| 2247 | 2118 | ||
| 2248 | static int qede_load(struct qede_dev *edev, enum qede_load_mode mode, | 2119 | static int qede_load(struct qede_dev *edev, enum qede_load_mode mode, |
| @@ -2422,77 +2293,6 @@ static void qede_link_update(void *dev, struct qed_link_output *link) | |||
| 2422 | } | 2293 | } |
| 2423 | } | 2294 | } |
| 2424 | 2295 | ||
| 2425 | static void qede_schedule_recovery_handler(void *dev) | ||
| 2426 | { | ||
| 2427 | struct qede_dev *edev = dev; | ||
| 2428 | |||
| 2429 | if (edev->state == QEDE_STATE_RECOVERY) { | ||
| 2430 | DP_NOTICE(edev, | ||
| 2431 | "Avoid scheduling a recovery handling since already in recovery state\n"); | ||
| 2432 | return; | ||
| 2433 | } | ||
| 2434 | |||
| 2435 | set_bit(QEDE_SP_RECOVERY, &edev->sp_flags); | ||
| 2436 | schedule_delayed_work(&edev->sp_task, 0); | ||
| 2437 | |||
| 2438 | DP_INFO(edev, "Scheduled a recovery handler\n"); | ||
| 2439 | } | ||
| 2440 | |||
| 2441 | static void qede_recovery_failed(struct qede_dev *edev) | ||
| 2442 | { | ||
| 2443 | netdev_err(edev->ndev, "Recovery handling has failed. Power cycle is needed.\n"); | ||
| 2444 | |||
| 2445 | netif_device_detach(edev->ndev); | ||
| 2446 | |||
| 2447 | if (edev->cdev) | ||
| 2448 | edev->ops->common->set_power_state(edev->cdev, PCI_D3hot); | ||
| 2449 | } | ||
| 2450 | |||
| 2451 | static void qede_recovery_handler(struct qede_dev *edev) | ||
| 2452 | { | ||
| 2453 | u32 curr_state = edev->state; | ||
| 2454 | int rc; | ||
| 2455 | |||
| 2456 | DP_NOTICE(edev, "Starting a recovery process\n"); | ||
| 2457 | |||
| 2458 | /* No need to acquire first the qede_lock since is done by qede_sp_task | ||
| 2459 | * before calling this function. | ||
| 2460 | */ | ||
| 2461 | edev->state = QEDE_STATE_RECOVERY; | ||
| 2462 | |||
| 2463 | edev->ops->common->recovery_prolog(edev->cdev); | ||
| 2464 | |||
| 2465 | if (curr_state == QEDE_STATE_OPEN) | ||
| 2466 | qede_unload(edev, QEDE_UNLOAD_RECOVERY, true); | ||
| 2467 | |||
| 2468 | __qede_remove(edev->pdev, QEDE_REMOVE_RECOVERY); | ||
| 2469 | |||
| 2470 | rc = __qede_probe(edev->pdev, edev->dp_module, edev->dp_level, | ||
| 2471 | IS_VF(edev), QEDE_PROBE_RECOVERY); | ||
| 2472 | if (rc) { | ||
| 2473 | edev->cdev = NULL; | ||
| 2474 | goto err; | ||
| 2475 | } | ||
| 2476 | |||
| 2477 | if (curr_state == QEDE_STATE_OPEN) { | ||
| 2478 | rc = qede_load(edev, QEDE_LOAD_RECOVERY, true); | ||
| 2479 | if (rc) | ||
| 2480 | goto err; | ||
| 2481 | |||
| 2482 | qede_config_rx_mode(edev->ndev); | ||
| 2483 | udp_tunnel_get_rx_info(edev->ndev); | ||
| 2484 | } | ||
| 2485 | |||
| 2486 | edev->state = curr_state; | ||
| 2487 | |||
| 2488 | DP_NOTICE(edev, "Recovery handling is done\n"); | ||
| 2489 | |||
| 2490 | return; | ||
| 2491 | |||
| 2492 | err: | ||
| 2493 | qede_recovery_failed(edev); | ||
| 2494 | } | ||
| 2495 | |||
| 2496 | static bool qede_is_txq_full(struct qede_dev *edev, struct qede_tx_queue *txq) | 2296 | static bool qede_is_txq_full(struct qede_dev *edev, struct qede_tx_queue *txq) |
| 2497 | { | 2297 | { |
| 2498 | struct netdev_queue *netdev_txq; | 2298 | struct netdev_queue *netdev_txq; |
diff --git a/drivers/net/ethernet/qlogic/qede/qede_rdma.c b/drivers/net/ethernet/qlogic/qede/qede_rdma.c index 9668e5e47d5f..1900bf7e67d1 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_rdma.c +++ b/drivers/net/ethernet/qlogic/qede/qede_rdma.c | |||
| @@ -50,8 +50,6 @@ static void _qede_rdma_dev_add(struct qede_dev *edev) | |||
| 50 | if (!qedr_drv) | 50 | if (!qedr_drv) |
| 51 | return; | 51 | return; |
| 52 | 52 | ||
| 53 | /* Leftovers from previous error recovery */ | ||
| 54 | edev->rdma_info.exp_recovery = false; | ||
| 55 | edev->rdma_info.qedr_dev = qedr_drv->add(edev->cdev, edev->pdev, | 53 | edev->rdma_info.qedr_dev = qedr_drv->add(edev->cdev, edev->pdev, |
| 56 | edev->ndev); | 54 | edev->ndev); |
| 57 | } | 55 | } |
| @@ -89,26 +87,21 @@ static void qede_rdma_destroy_wq(struct qede_dev *edev) | |||
| 89 | destroy_workqueue(edev->rdma_info.rdma_wq); | 87 | destroy_workqueue(edev->rdma_info.rdma_wq); |
| 90 | } | 88 | } |
| 91 | 89 | ||
| 92 | int qede_rdma_dev_add(struct qede_dev *edev, enum qede_rdma_probe_mode mode) | 90 | int qede_rdma_dev_add(struct qede_dev *edev) |
| 93 | { | 91 | { |
| 94 | int rc; | 92 | int rc = 0; |
| 95 | 93 | ||
| 96 | if (!qede_rdma_supported(edev)) | 94 | if (qede_rdma_supported(edev)) { |
| 97 | return 0; | 95 | rc = qede_rdma_create_wq(edev); |
| 98 | 96 | if (rc) | |
| 99 | /* Cannot start qedr while recovering since it wasn't fully stopped */ | 97 | return rc; |
| 100 | if (mode == QEDE_RDMA_PROBE_RECOVERY) | ||
| 101 | return 0; | ||
| 102 | |||
| 103 | rc = qede_rdma_create_wq(edev); | ||
| 104 | if (rc) | ||
| 105 | return rc; | ||
| 106 | 98 | ||
| 107 | INIT_LIST_HEAD(&edev->rdma_info.entry); | 99 | INIT_LIST_HEAD(&edev->rdma_info.entry); |
| 108 | mutex_lock(&qedr_dev_list_lock); | 100 | mutex_lock(&qedr_dev_list_lock); |
| 109 | list_add_tail(&edev->rdma_info.entry, &qedr_dev_list); | 101 | list_add_tail(&edev->rdma_info.entry, &qedr_dev_list); |
| 110 | _qede_rdma_dev_add(edev); | 102 | _qede_rdma_dev_add(edev); |
| 111 | mutex_unlock(&qedr_dev_list_lock); | 103 | mutex_unlock(&qedr_dev_list_lock); |
| 104 | } | ||
| 112 | 105 | ||
| 113 | return rc; | 106 | return rc; |
| 114 | } | 107 | } |
| @@ -117,31 +110,19 @@ static void _qede_rdma_dev_remove(struct qede_dev *edev) | |||
| 117 | { | 110 | { |
| 118 | if (qedr_drv && qedr_drv->remove && edev->rdma_info.qedr_dev) | 111 | if (qedr_drv && qedr_drv->remove && edev->rdma_info.qedr_dev) |
| 119 | qedr_drv->remove(edev->rdma_info.qedr_dev); | 112 | qedr_drv->remove(edev->rdma_info.qedr_dev); |
| 113 | edev->rdma_info.qedr_dev = NULL; | ||
| 120 | } | 114 | } |
| 121 | 115 | ||
| 122 | void qede_rdma_dev_remove(struct qede_dev *edev, | 116 | void qede_rdma_dev_remove(struct qede_dev *edev) |
| 123 | enum qede_rdma_remove_mode mode) | ||
| 124 | { | 117 | { |
| 125 | if (!qede_rdma_supported(edev)) | 118 | if (!qede_rdma_supported(edev)) |
| 126 | return; | 119 | return; |
| 127 | 120 | ||
| 128 | /* Cannot remove qedr while recovering since it wasn't fully stopped */ | 121 | qede_rdma_destroy_wq(edev); |
| 129 | if (mode == QEDE_RDMA_REMOVE_NORMAL) { | 122 | mutex_lock(&qedr_dev_list_lock); |
| 130 | qede_rdma_destroy_wq(edev); | 123 | _qede_rdma_dev_remove(edev); |
| 131 | mutex_lock(&qedr_dev_list_lock); | 124 | list_del(&edev->rdma_info.entry); |
| 132 | if (!edev->rdma_info.exp_recovery) | 125 | mutex_unlock(&qedr_dev_list_lock); |
| 133 | _qede_rdma_dev_remove(edev); | ||
| 134 | edev->rdma_info.qedr_dev = NULL; | ||
| 135 | list_del(&edev->rdma_info.entry); | ||
| 136 | mutex_unlock(&qedr_dev_list_lock); | ||
| 137 | } else { | ||
| 138 | if (!edev->rdma_info.exp_recovery) { | ||
| 139 | mutex_lock(&qedr_dev_list_lock); | ||
| 140 | _qede_rdma_dev_remove(edev); | ||
| 141 | mutex_unlock(&qedr_dev_list_lock); | ||
| 142 | } | ||
| 143 | edev->rdma_info.exp_recovery = true; | ||
| 144 | } | ||
| 145 | } | 126 | } |
| 146 | 127 | ||
| 147 | static void _qede_rdma_dev_open(struct qede_dev *edev) | 128 | static void _qede_rdma_dev_open(struct qede_dev *edev) |
| @@ -223,8 +204,7 @@ void qede_rdma_unregister_driver(struct qedr_driver *drv) | |||
| 223 | 204 | ||
| 224 | mutex_lock(&qedr_dev_list_lock); | 205 | mutex_lock(&qedr_dev_list_lock); |
| 225 | list_for_each_entry(edev, &qedr_dev_list, rdma_info.entry) { | 206 | list_for_each_entry(edev, &qedr_dev_list, rdma_info.entry) { |
| 226 | /* If device has experienced recovery it was already removed */ | 207 | if (edev->rdma_info.qedr_dev) |
| 227 | if (edev->rdma_info.qedr_dev && !edev->rdma_info.exp_recovery) | ||
| 228 | _qede_rdma_dev_remove(edev); | 208 | _qede_rdma_dev_remove(edev); |
| 229 | } | 209 | } |
| 230 | qedr_drv = NULL; | 210 | qedr_drv = NULL; |
| @@ -304,10 +284,6 @@ static void qede_rdma_add_event(struct qede_dev *edev, | |||
| 304 | { | 284 | { |
| 305 | struct qede_rdma_event_work *event_node; | 285 | struct qede_rdma_event_work *event_node; |
| 306 | 286 | ||
| 307 | /* If a recovery was experienced avoid adding the event */ | ||
| 308 | if (edev->rdma_info.exp_recovery) | ||
| 309 | return; | ||
| 310 | |||
| 311 | if (!edev->rdma_info.qedr_dev) | 287 | if (!edev->rdma_info.qedr_dev) |
| 312 | return; | 288 | return; |
| 313 | 289 | ||
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h index c2a1b7dbe4eb..91c536a01b56 100644 --- a/include/linux/qed/qed_if.h +++ b/include/linux/qed/qed_if.h | |||
| @@ -764,7 +764,6 @@ struct qed_probe_params { | |||
| 764 | u32 dp_module; | 764 | u32 dp_module; |
| 765 | u8 dp_level; | 765 | u8 dp_level; |
| 766 | bool is_vf; | 766 | bool is_vf; |
| 767 | bool recov_in_prog; | ||
| 768 | }; | 767 | }; |
| 769 | 768 | ||
| 770 | #define QED_DRV_VER_STR_SIZE 12 | 769 | #define QED_DRV_VER_STR_SIZE 12 |
| @@ -811,7 +810,6 @@ struct qed_common_cb_ops { | |||
| 811 | void (*arfs_filter_op)(void *dev, void *fltr, u8 fw_rc); | 810 | void (*arfs_filter_op)(void *dev, void *fltr, u8 fw_rc); |
| 812 | void (*link_update)(void *dev, | 811 | void (*link_update)(void *dev, |
| 813 | struct qed_link_output *link); | 812 | struct qed_link_output *link); |
| 814 | void (*schedule_recovery_handler)(void *dev); | ||
| 815 | void (*dcbx_aen)(void *dev, struct qed_dcbx_get *get, u32 mib_type); | 813 | void (*dcbx_aen)(void *dev, struct qed_dcbx_get *get, u32 mib_type); |
| 816 | void (*get_generic_tlv_data)(void *dev, struct qed_generic_tlvs *data); | 814 | void (*get_generic_tlv_data)(void *dev, struct qed_generic_tlvs *data); |
| 817 | void (*get_protocol_tlv_data)(void *dev, void *data); | 815 | void (*get_protocol_tlv_data)(void *dev, void *data); |
| @@ -1060,24 +1058,6 @@ struct qed_common_ops { | |||
| 1060 | void __iomem *db_addr, void *db_data); | 1058 | void __iomem *db_addr, void *db_data); |
| 1061 | 1059 | ||
| 1062 | /** | 1060 | /** |
| 1063 | * @brief recovery_process - Trigger a recovery process | ||
| 1064 | * | ||
| 1065 | * @param cdev | ||
| 1066 | * | ||
| 1067 | * @return 0 on success, error otherwise. | ||
| 1068 | */ | ||
| 1069 | int (*recovery_process)(struct qed_dev *cdev); | ||
| 1070 | |||
| 1071 | /** | ||
| 1072 | * @brief recovery_prolog - Execute the prolog operations of a recovery process | ||
| 1073 | * | ||
| 1074 | * @param cdev | ||
| 1075 | * | ||
| 1076 | * @return 0 on success, error otherwise. | ||
| 1077 | */ | ||
| 1078 | int (*recovery_prolog)(struct qed_dev *cdev); | ||
| 1079 | |||
| 1080 | /** | ||
| 1081 | * @brief update_drv_state - API to inform the change in the driver state. | 1061 | * @brief update_drv_state - API to inform the change in the driver state. |
| 1082 | * | 1062 | * |
| 1083 | * @param cdev | 1063 | * @param cdev |
diff --git a/include/linux/qed/qede_rdma.h b/include/linux/qed/qede_rdma.h index e29d7199c10e..9904617a9730 100644 --- a/include/linux/qed/qede_rdma.h +++ b/include/linux/qed/qede_rdma.h | |||
| @@ -55,16 +55,6 @@ struct qede_rdma_event_work { | |||
| 55 | enum qede_rdma_event event; | 55 | enum qede_rdma_event event; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | enum qede_rdma_probe_mode { | ||
| 59 | QEDE_RDMA_PROBE_NORMAL, | ||
| 60 | QEDE_RDMA_PROBE_RECOVERY, | ||
| 61 | }; | ||
| 62 | |||
| 63 | enum qede_rdma_remove_mode { | ||
| 64 | QEDE_RDMA_REMOVE_NORMAL, | ||
| 65 | QEDE_RDMA_REMOVE_RECOVERY, | ||
| 66 | }; | ||
| 67 | |||
| 68 | struct qedr_driver { | 58 | struct qedr_driver { |
| 69 | unsigned char name[32]; | 59 | unsigned char name[32]; |
| 70 | 60 | ||
| @@ -84,24 +74,21 @@ void qede_rdma_unregister_driver(struct qedr_driver *drv); | |||
| 84 | bool qede_rdma_supported(struct qede_dev *dev); | 74 | bool qede_rdma_supported(struct qede_dev *dev); |
| 85 | 75 | ||
| 86 | #if IS_ENABLED(CONFIG_QED_RDMA) | 76 | #if IS_ENABLED(CONFIG_QED_RDMA) |
| 87 | int qede_rdma_dev_add(struct qede_dev *dev, enum qede_rdma_probe_mode mode); | 77 | int qede_rdma_dev_add(struct qede_dev *dev); |
| 88 | void qede_rdma_dev_event_open(struct qede_dev *dev); | 78 | void qede_rdma_dev_event_open(struct qede_dev *dev); |
| 89 | void qede_rdma_dev_event_close(struct qede_dev *dev); | 79 | void qede_rdma_dev_event_close(struct qede_dev *dev); |
| 90 | void qede_rdma_dev_remove(struct qede_dev *dev, | 80 | void qede_rdma_dev_remove(struct qede_dev *dev); |
| 91 | enum qede_rdma_remove_mode mode); | ||
| 92 | void qede_rdma_event_changeaddr(struct qede_dev *edr); | 81 | void qede_rdma_event_changeaddr(struct qede_dev *edr); |
| 93 | 82 | ||
| 94 | #else | 83 | #else |
| 95 | static inline int qede_rdma_dev_add(struct qede_dev *dev, | 84 | static inline int qede_rdma_dev_add(struct qede_dev *dev) |
| 96 | enum qede_rdma_probe_mode mode) | ||
| 97 | { | 85 | { |
| 98 | return 0; | 86 | return 0; |
| 99 | } | 87 | } |
| 100 | 88 | ||
| 101 | static inline void qede_rdma_dev_event_open(struct qede_dev *dev) {} | 89 | static inline void qede_rdma_dev_event_open(struct qede_dev *dev) {} |
| 102 | static inline void qede_rdma_dev_event_close(struct qede_dev *dev) {} | 90 | static inline void qede_rdma_dev_event_close(struct qede_dev *dev) {} |
| 103 | static inline void qede_rdma_dev_remove(struct qede_dev *dev, | 91 | static inline void qede_rdma_dev_remove(struct qede_dev *dev) {} |
| 104 | enum qede_rdma_remove_mode mode) {} | ||
| 105 | static inline void qede_rdma_event_changeaddr(struct qede_dev *edr) {} | 92 | static inline void qede_rdma_event_changeaddr(struct qede_dev *edr) {} |
| 106 | #endif | 93 | #endif |
| 107 | #endif | 94 | #endif |
