diff options
author | Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com> | 2012-07-11 23:57:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-12 11:16:46 -0400 |
commit | f67ef7bae8dd025086fdf8186958865bceb44595 (patch) | |
tree | 9f2d253cf391438c016fba93e689c2f047ee7602 /drivers/net/ethernet/emulex | |
parent | bf99e50dc2ec49fc1256f9499987699a3f7f158b (diff) |
be2net: Activate new FW after FW download for Lancer
After FW download, activate new FW by invoking FW reset.
Recreate rings once new FW is operational.
Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.h | 15 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_hw.h | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 203 |
5 files changed, 180 insertions, 78 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 748e870958af..e2dfe3114eb1 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
@@ -389,6 +389,7 @@ struct be_adapter { | |||
389 | struct delayed_work work; | 389 | struct delayed_work work; |
390 | u16 work_counter; | 390 | u16 work_counter; |
391 | 391 | ||
392 | struct delayed_work func_recovery_work; | ||
392 | u32 flags; | 393 | u32 flags; |
393 | /* Ethtool knobs and info */ | 394 | /* Ethtool knobs and info */ |
394 | char fw_ver[FW_VER_LEN]; | 395 | char fw_ver[FW_VER_LEN]; |
@@ -396,9 +397,10 @@ struct be_adapter { | |||
396 | u32 *pmac_id; /* MAC addr handle used by BE card */ | 397 | u32 *pmac_id; /* MAC addr handle used by BE card */ |
397 | u32 beacon_state; /* for set_phys_id */ | 398 | u32 beacon_state; /* for set_phys_id */ |
398 | 399 | ||
399 | bool eeh_err; | 400 | bool eeh_error; |
400 | bool ue_detected; | ||
401 | bool fw_timeout; | 401 | bool fw_timeout; |
402 | bool hw_error; | ||
403 | |||
402 | u32 port_num; | 404 | u32 port_num; |
403 | bool promiscuous; | 405 | bool promiscuous; |
404 | u32 function_mode; | 406 | u32 function_mode; |
@@ -599,7 +601,19 @@ static inline bool be_multi_rxq(const struct be_adapter *adapter) | |||
599 | 601 | ||
600 | static inline bool be_error(struct be_adapter *adapter) | 602 | static inline bool be_error(struct be_adapter *adapter) |
601 | { | 603 | { |
602 | return adapter->eeh_err || adapter->ue_detected || adapter->fw_timeout; | 604 | return adapter->eeh_error || adapter->hw_error || adapter->fw_timeout; |
605 | } | ||
606 | |||
607 | static inline bool be_crit_error(struct be_adapter *adapter) | ||
608 | { | ||
609 | return adapter->eeh_error || adapter->hw_error; | ||
610 | } | ||
611 | |||
612 | static inline void be_clear_all_error(struct be_adapter *adapter) | ||
613 | { | ||
614 | adapter->eeh_error = false; | ||
615 | adapter->hw_error = false; | ||
616 | adapter->fw_timeout = false; | ||
603 | } | 617 | } |
604 | 618 | ||
605 | static inline bool be_is_wol_excluded(struct be_adapter *adapter) | 619 | static inline bool be_is_wol_excluded(struct be_adapter *adapter) |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 431f7749eea2..34dfc0c5c774 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
@@ -349,7 +349,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) | |||
349 | if (msecs > 4000) { | 349 | if (msecs > 4000) { |
350 | dev_err(&adapter->pdev->dev, "FW not responding\n"); | 350 | dev_err(&adapter->pdev->dev, "FW not responding\n"); |
351 | adapter->fw_timeout = true; | 351 | adapter->fw_timeout = true; |
352 | be_detect_dump_ue(adapter); | 352 | be_detect_error(adapter); |
353 | return -1; | 353 | return -1; |
354 | } | 354 | } |
355 | 355 | ||
@@ -1869,8 +1869,9 @@ err: | |||
1869 | } | 1869 | } |
1870 | 1870 | ||
1871 | int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, | 1871 | int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, |
1872 | u32 data_size, u32 data_offset, const char *obj_name, | 1872 | u32 data_size, u32 data_offset, |
1873 | u32 *data_written, u8 *addn_status) | 1873 | const char *obj_name, u32 *data_written, |
1874 | u8 *change_status, u8 *addn_status) | ||
1874 | { | 1875 | { |
1875 | struct be_mcc_wrb *wrb; | 1876 | struct be_mcc_wrb *wrb; |
1876 | struct lancer_cmd_req_write_object *req; | 1877 | struct lancer_cmd_req_write_object *req; |
@@ -1926,10 +1927,12 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, | |||
1926 | status = adapter->flash_status; | 1927 | status = adapter->flash_status; |
1927 | 1928 | ||
1928 | resp = embedded_payload(wrb); | 1929 | resp = embedded_payload(wrb); |
1929 | if (!status) | 1930 | if (!status) { |
1930 | *data_written = le32_to_cpu(resp->actual_write_len); | 1931 | *data_written = le32_to_cpu(resp->actual_write_len); |
1931 | else | 1932 | *change_status = resp->change_status; |
1933 | } else { | ||
1932 | *addn_status = resp->additional_status; | 1934 | *addn_status = resp->additional_status; |
1935 | } | ||
1933 | 1936 | ||
1934 | return status; | 1937 | return status; |
1935 | 1938 | ||
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index cfc0620b747b..c1324e74ba19 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h | |||
@@ -1163,6 +1163,8 @@ struct lancer_cmd_req_write_object { | |||
1163 | u32 addr_high; | 1163 | u32 addr_high; |
1164 | }; | 1164 | }; |
1165 | 1165 | ||
1166 | #define LANCER_NO_RESET_NEEDED 0x00 | ||
1167 | #define LANCER_FW_RESET_NEEDED 0x02 | ||
1166 | struct lancer_cmd_resp_write_object { | 1168 | struct lancer_cmd_resp_write_object { |
1167 | u8 opcode; | 1169 | u8 opcode; |
1168 | u8 subsystem; | 1170 | u8 subsystem; |
@@ -1173,6 +1175,8 @@ struct lancer_cmd_resp_write_object { | |||
1173 | u32 resp_len; | 1175 | u32 resp_len; |
1174 | u32 actual_resp_len; | 1176 | u32 actual_resp_len; |
1175 | u32 actual_write_len; | 1177 | u32 actual_write_len; |
1178 | u8 change_status; | ||
1179 | u8 rsvd3[3]; | ||
1176 | }; | 1180 | }; |
1177 | 1181 | ||
1178 | /************************ Lancer Read FW info **************/ | 1182 | /************************ Lancer Read FW info **************/ |
@@ -1718,10 +1722,11 @@ extern int be_cmd_write_flashrom(struct be_adapter *adapter, | |||
1718 | struct be_dma_mem *cmd, u32 flash_oper, | 1722 | struct be_dma_mem *cmd, u32 flash_oper, |
1719 | u32 flash_opcode, u32 buf_size); | 1723 | u32 flash_opcode, u32 buf_size); |
1720 | extern int lancer_cmd_write_object(struct be_adapter *adapter, | 1724 | extern int lancer_cmd_write_object(struct be_adapter *adapter, |
1721 | struct be_dma_mem *cmd, | 1725 | struct be_dma_mem *cmd, |
1722 | u32 data_size, u32 data_offset, | 1726 | u32 data_size, u32 data_offset, |
1723 | const char *obj_name, | 1727 | const char *obj_name, |
1724 | u32 *data_written, u8 *addn_status); | 1728 | u32 *data_written, u8 *change_status, |
1729 | u8 *addn_status); | ||
1725 | int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, | 1730 | int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd, |
1726 | u32 data_size, u32 data_offset, const char *obj_name, | 1731 | u32 data_size, u32 data_offset, const char *obj_name, |
1727 | u32 *data_read, u32 *eof, u8 *addn_status); | 1732 | u32 *data_read, u32 *eof, u8 *addn_status); |
@@ -1744,7 +1749,7 @@ extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, | |||
1744 | u8 loopback_type, u8 enable); | 1749 | u8 loopback_type, u8 enable); |
1745 | extern int be_cmd_get_phy_info(struct be_adapter *adapter); | 1750 | extern int be_cmd_get_phy_info(struct be_adapter *adapter); |
1746 | extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); | 1751 | extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain); |
1747 | extern void be_detect_dump_ue(struct be_adapter *adapter); | 1752 | extern void be_detect_error(struct be_adapter *adapter); |
1748 | extern int be_cmd_get_die_temperature(struct be_adapter *adapter); | 1753 | extern int be_cmd_get_die_temperature(struct be_adapter *adapter); |
1749 | extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); | 1754 | extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); |
1750 | extern int be_cmd_req_native_mode(struct be_adapter *adapter); | 1755 | extern int be_cmd_req_native_mode(struct be_adapter *adapter); |
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index 7c8a710eac2f..b755f7061dce 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h | |||
@@ -45,18 +45,19 @@ | |||
45 | #define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */ | 45 | #define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */ |
46 | 46 | ||
47 | 47 | ||
48 | /* Lancer SLIPORT_CONTROL SLIPORT_STATUS registers */ | 48 | /* Lancer SLIPORT registers */ |
49 | #define SLIPORT_STATUS_OFFSET 0x404 | 49 | #define SLIPORT_STATUS_OFFSET 0x404 |
50 | #define SLIPORT_CONTROL_OFFSET 0x408 | 50 | #define SLIPORT_CONTROL_OFFSET 0x408 |
51 | #define SLIPORT_ERROR1_OFFSET 0x40C | 51 | #define SLIPORT_ERROR1_OFFSET 0x40C |
52 | #define SLIPORT_ERROR2_OFFSET 0x410 | 52 | #define SLIPORT_ERROR2_OFFSET 0x410 |
53 | #define PHYSDEV_CONTROL_OFFSET 0x414 | ||
53 | 54 | ||
54 | #define SLIPORT_STATUS_ERR_MASK 0x80000000 | 55 | #define SLIPORT_STATUS_ERR_MASK 0x80000000 |
55 | #define SLIPORT_STATUS_RN_MASK 0x01000000 | 56 | #define SLIPORT_STATUS_RN_MASK 0x01000000 |
56 | #define SLIPORT_STATUS_RDY_MASK 0x00800000 | 57 | #define SLIPORT_STATUS_RDY_MASK 0x00800000 |
57 | |||
58 | |||
59 | #define SLI_PORT_CONTROL_IP_MASK 0x08000000 | 58 | #define SLI_PORT_CONTROL_IP_MASK 0x08000000 |
59 | #define PHYSDEV_CONTROL_FW_RESET_MASK 0x00000002 | ||
60 | #define PHYSDEV_CONTROL_INP_MASK 0x40000000 | ||
60 | 61 | ||
61 | /********* Memory BAR register ************/ | 62 | /********* Memory BAR register ************/ |
62 | #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc | 63 | #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index a3641baa8604..9e7dbd59b57e 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -155,7 +155,7 @@ static void be_intr_set(struct be_adapter *adapter, bool enable) | |||
155 | { | 155 | { |
156 | u32 reg, enabled; | 156 | u32 reg, enabled; |
157 | 157 | ||
158 | if (adapter->eeh_err) | 158 | if (adapter->eeh_error) |
159 | return; | 159 | return; |
160 | 160 | ||
161 | pci_read_config_dword(adapter->pdev, PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, | 161 | pci_read_config_dword(adapter->pdev, PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET, |
@@ -201,7 +201,7 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, | |||
201 | val |= ((qid & DB_EQ_RING_ID_EXT_MASK) << | 201 | val |= ((qid & DB_EQ_RING_ID_EXT_MASK) << |
202 | DB_EQ_RING_ID_EXT_MASK_SHIFT); | 202 | DB_EQ_RING_ID_EXT_MASK_SHIFT); |
203 | 203 | ||
204 | if (adapter->eeh_err) | 204 | if (adapter->eeh_error) |
205 | return; | 205 | return; |
206 | 206 | ||
207 | if (arm) | 207 | if (arm) |
@@ -220,7 +220,7 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) | |||
220 | val |= ((qid & DB_CQ_RING_ID_EXT_MASK) << | 220 | val |= ((qid & DB_CQ_RING_ID_EXT_MASK) << |
221 | DB_CQ_RING_ID_EXT_MASK_SHIFT); | 221 | DB_CQ_RING_ID_EXT_MASK_SHIFT); |
222 | 222 | ||
223 | if (adapter->eeh_err) | 223 | if (adapter->eeh_error) |
224 | return; | 224 | return; |
225 | 225 | ||
226 | if (arm) | 226 | if (arm) |
@@ -2098,13 +2098,13 @@ int be_poll(struct napi_struct *napi, int budget) | |||
2098 | return max_work; | 2098 | return max_work; |
2099 | } | 2099 | } |
2100 | 2100 | ||
2101 | void be_detect_dump_ue(struct be_adapter *adapter) | 2101 | void be_detect_error(struct be_adapter *adapter) |
2102 | { | 2102 | { |
2103 | u32 ue_lo = 0, ue_hi = 0, ue_lo_mask = 0, ue_hi_mask = 0; | 2103 | u32 ue_lo = 0, ue_hi = 0, ue_lo_mask = 0, ue_hi_mask = 0; |
2104 | u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; | 2104 | u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; |
2105 | u32 i; | 2105 | u32 i; |
2106 | 2106 | ||
2107 | if (adapter->eeh_err || adapter->ue_detected) | 2107 | if (be_crit_error(adapter)) |
2108 | return; | 2108 | return; |
2109 | 2109 | ||
2110 | if (lancer_chip(adapter)) { | 2110 | if (lancer_chip(adapter)) { |
@@ -2125,16 +2125,24 @@ void be_detect_dump_ue(struct be_adapter *adapter) | |||
2125 | pci_read_config_dword(adapter->pdev, | 2125 | pci_read_config_dword(adapter->pdev, |
2126 | PCICFG_UE_STATUS_HI_MASK, &ue_hi_mask); | 2126 | PCICFG_UE_STATUS_HI_MASK, &ue_hi_mask); |
2127 | 2127 | ||
2128 | ue_lo = (ue_lo & (~ue_lo_mask)); | 2128 | ue_lo = (ue_lo & ~ue_lo_mask); |
2129 | ue_hi = (ue_hi & (~ue_hi_mask)); | 2129 | ue_hi = (ue_hi & ~ue_hi_mask); |
2130 | } | 2130 | } |
2131 | 2131 | ||
2132 | if (ue_lo || ue_hi || | 2132 | if (ue_lo || ue_hi || |
2133 | sliport_status & SLIPORT_STATUS_ERR_MASK) { | 2133 | sliport_status & SLIPORT_STATUS_ERR_MASK) { |
2134 | adapter->ue_detected = true; | 2134 | adapter->hw_error = true; |
2135 | adapter->eeh_err = true; | ||
2136 | dev_err(&adapter->pdev->dev, | 2135 | dev_err(&adapter->pdev->dev, |
2137 | "Unrecoverable error in the card\n"); | 2136 | "Error detected in the card\n"); |
2137 | } | ||
2138 | |||
2139 | if (sliport_status & SLIPORT_STATUS_ERR_MASK) { | ||
2140 | dev_err(&adapter->pdev->dev, | ||
2141 | "ERR: sliport status 0x%x\n", sliport_status); | ||
2142 | dev_err(&adapter->pdev->dev, | ||
2143 | "ERR: sliport error1 0x%x\n", sliport_err1); | ||
2144 | dev_err(&adapter->pdev->dev, | ||
2145 | "ERR: sliport error2 0x%x\n", sliport_err2); | ||
2138 | } | 2146 | } |
2139 | 2147 | ||
2140 | if (ue_lo) { | 2148 | if (ue_lo) { |
@@ -2144,6 +2152,7 @@ void be_detect_dump_ue(struct be_adapter *adapter) | |||
2144 | "UE: %s bit set\n", ue_status_low_desc[i]); | 2152 | "UE: %s bit set\n", ue_status_low_desc[i]); |
2145 | } | 2153 | } |
2146 | } | 2154 | } |
2155 | |||
2147 | if (ue_hi) { | 2156 | if (ue_hi) { |
2148 | for (i = 0; ue_hi; ue_hi >>= 1, i++) { | 2157 | for (i = 0; ue_hi; ue_hi >>= 1, i++) { |
2149 | if (ue_hi & 1) | 2158 | if (ue_hi & 1) |
@@ -2152,14 +2161,6 @@ void be_detect_dump_ue(struct be_adapter *adapter) | |||
2152 | } | 2161 | } |
2153 | } | 2162 | } |
2154 | 2163 | ||
2155 | if (sliport_status & SLIPORT_STATUS_ERR_MASK) { | ||
2156 | dev_err(&adapter->pdev->dev, | ||
2157 | "sliport status 0x%x\n", sliport_status); | ||
2158 | dev_err(&adapter->pdev->dev, | ||
2159 | "sliport error1 0x%x\n", sliport_err1); | ||
2160 | dev_err(&adapter->pdev->dev, | ||
2161 | "sliport error2 0x%x\n", sliport_err2); | ||
2162 | } | ||
2163 | } | 2164 | } |
2164 | 2165 | ||
2165 | static void be_msix_disable(struct be_adapter *adapter) | 2166 | static void be_msix_disable(struct be_adapter *adapter) |
@@ -3067,6 +3068,40 @@ static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) | |||
3067 | return 0; | 3068 | return 0; |
3068 | } | 3069 | } |
3069 | 3070 | ||
3071 | static int lancer_wait_idle(struct be_adapter *adapter) | ||
3072 | { | ||
3073 | #define SLIPORT_IDLE_TIMEOUT 30 | ||
3074 | u32 reg_val; | ||
3075 | int status = 0, i; | ||
3076 | |||
3077 | for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) { | ||
3078 | reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET); | ||
3079 | if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0) | ||
3080 | break; | ||
3081 | |||
3082 | ssleep(1); | ||
3083 | } | ||
3084 | |||
3085 | if (i == SLIPORT_IDLE_TIMEOUT) | ||
3086 | status = -1; | ||
3087 | |||
3088 | return status; | ||
3089 | } | ||
3090 | |||
3091 | static int lancer_fw_reset(struct be_adapter *adapter) | ||
3092 | { | ||
3093 | int status = 0; | ||
3094 | |||
3095 | status = lancer_wait_idle(adapter); | ||
3096 | if (status) | ||
3097 | return status; | ||
3098 | |||
3099 | iowrite32(PHYSDEV_CONTROL_FW_RESET_MASK, adapter->db + | ||
3100 | PHYSDEV_CONTROL_OFFSET); | ||
3101 | |||
3102 | return status; | ||
3103 | } | ||
3104 | |||
3070 | static int lancer_fw_download(struct be_adapter *adapter, | 3105 | static int lancer_fw_download(struct be_adapter *adapter, |
3071 | const struct firmware *fw) | 3106 | const struct firmware *fw) |
3072 | { | 3107 | { |
@@ -3081,6 +3116,7 @@ static int lancer_fw_download(struct be_adapter *adapter, | |||
3081 | u32 offset = 0; | 3116 | u32 offset = 0; |
3082 | int status = 0; | 3117 | int status = 0; |
3083 | u8 add_status = 0; | 3118 | u8 add_status = 0; |
3119 | u8 change_status; | ||
3084 | 3120 | ||
3085 | if (!IS_ALIGNED(fw->size, sizeof(u32))) { | 3121 | if (!IS_ALIGNED(fw->size, sizeof(u32))) { |
3086 | dev_err(&adapter->pdev->dev, | 3122 | dev_err(&adapter->pdev->dev, |
@@ -3113,9 +3149,10 @@ static int lancer_fw_download(struct be_adapter *adapter, | |||
3113 | memcpy(dest_image_ptr, data_ptr, chunk_size); | 3149 | memcpy(dest_image_ptr, data_ptr, chunk_size); |
3114 | 3150 | ||
3115 | status = lancer_cmd_write_object(adapter, &flash_cmd, | 3151 | status = lancer_cmd_write_object(adapter, &flash_cmd, |
3116 | chunk_size, offset, LANCER_FW_DOWNLOAD_LOCATION, | 3152 | chunk_size, offset, |
3117 | &data_written, &add_status); | 3153 | LANCER_FW_DOWNLOAD_LOCATION, |
3118 | 3154 | &data_written, &change_status, | |
3155 | &add_status); | ||
3119 | if (status) | 3156 | if (status) |
3120 | break; | 3157 | break; |
3121 | 3158 | ||
@@ -3127,8 +3164,10 @@ static int lancer_fw_download(struct be_adapter *adapter, | |||
3127 | if (!status) { | 3164 | if (!status) { |
3128 | /* Commit the FW written */ | 3165 | /* Commit the FW written */ |
3129 | status = lancer_cmd_write_object(adapter, &flash_cmd, | 3166 | status = lancer_cmd_write_object(adapter, &flash_cmd, |
3130 | 0, offset, LANCER_FW_DOWNLOAD_LOCATION, | 3167 | 0, offset, |
3131 | &data_written, &add_status); | 3168 | LANCER_FW_DOWNLOAD_LOCATION, |
3169 | &data_written, &change_status, | ||
3170 | &add_status); | ||
3132 | } | 3171 | } |
3133 | 3172 | ||
3134 | dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, | 3173 | dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, |
@@ -3141,6 +3180,20 @@ static int lancer_fw_download(struct be_adapter *adapter, | |||
3141 | goto lancer_fw_exit; | 3180 | goto lancer_fw_exit; |
3142 | } | 3181 | } |
3143 | 3182 | ||
3183 | if (change_status == LANCER_FW_RESET_NEEDED) { | ||
3184 | status = lancer_fw_reset(adapter); | ||
3185 | if (status) { | ||
3186 | dev_err(&adapter->pdev->dev, | ||
3187 | "Adapter busy for FW reset.\n" | ||
3188 | "New FW will not be active.\n"); | ||
3189 | goto lancer_fw_exit; | ||
3190 | } | ||
3191 | } else if (change_status != LANCER_NO_RESET_NEEDED) { | ||
3192 | dev_err(&adapter->pdev->dev, | ||
3193 | "System reboot required for new FW" | ||
3194 | " to be active\n"); | ||
3195 | } | ||
3196 | |||
3144 | dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); | 3197 | dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n"); |
3145 | lancer_fw_exit: | 3198 | lancer_fw_exit: |
3146 | return status; | 3199 | return status; |
@@ -3469,6 +3522,8 @@ static void __devexit be_remove(struct pci_dev *pdev) | |||
3469 | 3522 | ||
3470 | be_roce_dev_remove(adapter); | 3523 | be_roce_dev_remove(adapter); |
3471 | 3524 | ||
3525 | cancel_delayed_work_sync(&adapter->func_recovery_work); | ||
3526 | |||
3472 | unregister_netdev(adapter->netdev); | 3527 | unregister_netdev(adapter->netdev); |
3473 | 3528 | ||
3474 | be_clear(adapter); | 3529 | be_clear(adapter); |
@@ -3625,53 +3680,68 @@ static int be_dev_type_check(struct be_adapter *adapter) | |||
3625 | return 0; | 3680 | return 0; |
3626 | } | 3681 | } |
3627 | 3682 | ||
3628 | static void lancer_test_and_recover_fn_err(struct be_adapter *adapter) | 3683 | static int lancer_recover_func(struct be_adapter *adapter) |
3629 | { | 3684 | { |
3630 | int status; | 3685 | int status; |
3631 | u32 sliport_status; | ||
3632 | 3686 | ||
3633 | if (adapter->eeh_err || adapter->ue_detected) | 3687 | status = lancer_test_and_set_rdy_state(adapter); |
3634 | return; | 3688 | if (status) |
3689 | goto err; | ||
3635 | 3690 | ||
3636 | sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); | 3691 | if (netif_running(adapter->netdev)) |
3692 | be_close(adapter->netdev); | ||
3637 | 3693 | ||
3638 | if (sliport_status & SLIPORT_STATUS_ERR_MASK) { | 3694 | be_clear(adapter); |
3639 | dev_err(&adapter->pdev->dev, | 3695 | |
3640 | "Adapter in error state." | 3696 | adapter->hw_error = false; |
3641 | "Trying to recover.\n"); | 3697 | adapter->fw_timeout = false; |
3698 | |||
3699 | status = be_setup(adapter); | ||
3700 | if (status) | ||
3701 | goto err; | ||
3642 | 3702 | ||
3643 | status = lancer_test_and_set_rdy_state(adapter); | 3703 | if (netif_running(adapter->netdev)) { |
3704 | status = be_open(adapter->netdev); | ||
3644 | if (status) | 3705 | if (status) |
3645 | goto err; | 3706 | goto err; |
3707 | } | ||
3646 | 3708 | ||
3647 | netif_device_detach(adapter->netdev); | 3709 | dev_err(&adapter->pdev->dev, |
3710 | "Adapter SLIPORT recovery succeeded\n"); | ||
3711 | return 0; | ||
3712 | err: | ||
3713 | dev_err(&adapter->pdev->dev, | ||
3714 | "Adapter SLIPORT recovery failed\n"); | ||
3648 | 3715 | ||
3649 | if (netif_running(adapter->netdev)) | 3716 | return status; |
3650 | be_close(adapter->netdev); | 3717 | } |
3718 | |||
3719 | static void be_func_recovery_task(struct work_struct *work) | ||
3720 | { | ||
3721 | struct be_adapter *adapter = | ||
3722 | container_of(work, struct be_adapter, func_recovery_work.work); | ||
3723 | int status; | ||
3651 | 3724 | ||
3652 | be_clear(adapter); | 3725 | be_detect_error(adapter); |
3653 | 3726 | ||
3654 | adapter->fw_timeout = false; | 3727 | if (adapter->hw_error && lancer_chip(adapter)) { |
3655 | 3728 | ||
3656 | status = be_setup(adapter); | 3729 | if (adapter->eeh_error) |
3657 | if (status) | 3730 | goto out; |
3658 | goto err; | ||
3659 | 3731 | ||
3660 | if (netif_running(adapter->netdev)) { | 3732 | rtnl_lock(); |
3661 | status = be_open(adapter->netdev); | 3733 | netif_device_detach(adapter->netdev); |
3662 | if (status) | 3734 | rtnl_unlock(); |
3663 | goto err; | ||
3664 | } | ||
3665 | 3735 | ||
3666 | netif_device_attach(adapter->netdev); | 3736 | status = lancer_recover_func(adapter); |
3667 | 3737 | ||
3668 | dev_err(&adapter->pdev->dev, | 3738 | if (!status) |
3669 | "Adapter error recovery succeeded\n"); | 3739 | netif_device_attach(adapter->netdev); |
3670 | } | 3740 | } |
3671 | return; | 3741 | |
3672 | err: | 3742 | out: |
3673 | dev_err(&adapter->pdev->dev, | 3743 | schedule_delayed_work(&adapter->func_recovery_work, |
3674 | "Adapter error recovery failed\n"); | 3744 | msecs_to_jiffies(1000)); |
3675 | } | 3745 | } |
3676 | 3746 | ||
3677 | static void be_worker(struct work_struct *work) | 3747 | static void be_worker(struct work_struct *work) |
@@ -3682,11 +3752,6 @@ static void be_worker(struct work_struct *work) | |||
3682 | struct be_eq_obj *eqo; | 3752 | struct be_eq_obj *eqo; |
3683 | int i; | 3753 | int i; |
3684 | 3754 | ||
3685 | if (lancer_chip(adapter)) | ||
3686 | lancer_test_and_recover_fn_err(adapter); | ||
3687 | |||
3688 | be_detect_dump_ue(adapter); | ||
3689 | |||
3690 | /* when interrupts are not yet enabled, just reap any pending | 3755 | /* when interrupts are not yet enabled, just reap any pending |
3691 | * mcc completions */ | 3756 | * mcc completions */ |
3692 | if (!netif_running(adapter->netdev)) { | 3757 | if (!netif_running(adapter->netdev)) { |
@@ -3805,6 +3870,7 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
3805 | goto stats_clean; | 3870 | goto stats_clean; |
3806 | 3871 | ||
3807 | INIT_DELAYED_WORK(&adapter->work, be_worker); | 3872 | INIT_DELAYED_WORK(&adapter->work, be_worker); |
3873 | INIT_DELAYED_WORK(&adapter->func_recovery_work, be_func_recovery_task); | ||
3808 | adapter->rx_fc = adapter->tx_fc = true; | 3874 | adapter->rx_fc = adapter->tx_fc = true; |
3809 | 3875 | ||
3810 | status = be_setup(adapter); | 3876 | status = be_setup(adapter); |
@@ -3818,6 +3884,8 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
3818 | 3884 | ||
3819 | be_roce_dev_add(adapter); | 3885 | be_roce_dev_add(adapter); |
3820 | 3886 | ||
3887 | schedule_delayed_work(&adapter->func_recovery_work, | ||
3888 | msecs_to_jiffies(1000)); | ||
3821 | dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev), | 3889 | dev_info(&pdev->dev, "%s: %s port %d\n", netdev->name, nic_name(pdev), |
3822 | adapter->port_num); | 3890 | adapter->port_num); |
3823 | 3891 | ||
@@ -3851,6 +3919,8 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3851 | if (adapter->wol) | 3919 | if (adapter->wol) |
3852 | be_setup_wol(adapter, true); | 3920 | be_setup_wol(adapter, true); |
3853 | 3921 | ||
3922 | cancel_delayed_work_sync(&adapter->func_recovery_work); | ||
3923 | |||
3854 | netif_device_detach(netdev); | 3924 | netif_device_detach(netdev); |
3855 | if (netif_running(netdev)) { | 3925 | if (netif_running(netdev)) { |
3856 | rtnl_lock(); | 3926 | rtnl_lock(); |
@@ -3891,6 +3961,9 @@ static int be_resume(struct pci_dev *pdev) | |||
3891 | be_open(netdev); | 3961 | be_open(netdev); |
3892 | rtnl_unlock(); | 3962 | rtnl_unlock(); |
3893 | } | 3963 | } |
3964 | |||
3965 | schedule_delayed_work(&adapter->func_recovery_work, | ||
3966 | msecs_to_jiffies(1000)); | ||
3894 | netif_device_attach(netdev); | 3967 | netif_device_attach(netdev); |
3895 | 3968 | ||
3896 | if (adapter->wol) | 3969 | if (adapter->wol) |
@@ -3910,6 +3983,7 @@ static void be_shutdown(struct pci_dev *pdev) | |||
3910 | return; | 3983 | return; |
3911 | 3984 | ||
3912 | cancel_delayed_work_sync(&adapter->work); | 3985 | cancel_delayed_work_sync(&adapter->work); |
3986 | cancel_delayed_work_sync(&adapter->func_recovery_work); | ||
3913 | 3987 | ||
3914 | netif_device_detach(adapter->netdev); | 3988 | netif_device_detach(adapter->netdev); |
3915 | 3989 | ||
@@ -3929,9 +4003,13 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, | |||
3929 | 4003 | ||
3930 | dev_err(&adapter->pdev->dev, "EEH error detected\n"); | 4004 | dev_err(&adapter->pdev->dev, "EEH error detected\n"); |
3931 | 4005 | ||
3932 | adapter->eeh_err = true; | 4006 | adapter->eeh_error = true; |
4007 | |||
4008 | cancel_delayed_work_sync(&adapter->func_recovery_work); | ||
3933 | 4009 | ||
4010 | rtnl_lock(); | ||
3934 | netif_device_detach(netdev); | 4011 | netif_device_detach(netdev); |
4012 | rtnl_unlock(); | ||
3935 | 4013 | ||
3936 | if (netif_running(netdev)) { | 4014 | if (netif_running(netdev)) { |
3937 | rtnl_lock(); | 4015 | rtnl_lock(); |
@@ -3959,9 +4037,7 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) | |||
3959 | int status; | 4037 | int status; |
3960 | 4038 | ||
3961 | dev_info(&adapter->pdev->dev, "EEH reset\n"); | 4039 | dev_info(&adapter->pdev->dev, "EEH reset\n"); |
3962 | adapter->eeh_err = false; | 4040 | be_clear_all_error(adapter); |
3963 | adapter->ue_detected = false; | ||
3964 | adapter->fw_timeout = false; | ||
3965 | 4041 | ||
3966 | status = pci_enable_device(pdev); | 4042 | status = pci_enable_device(pdev); |
3967 | if (status) | 4043 | if (status) |
@@ -4007,6 +4083,9 @@ static void be_eeh_resume(struct pci_dev *pdev) | |||
4007 | if (status) | 4083 | if (status) |
4008 | goto err; | 4084 | goto err; |
4009 | } | 4085 | } |
4086 | |||
4087 | schedule_delayed_work(&adapter->func_recovery_work, | ||
4088 | msecs_to_jiffies(1000)); | ||
4010 | netif_device_attach(netdev); | 4089 | netif_device_attach(netdev); |
4011 | return; | 4090 | return; |
4012 | err: | 4091 | err: |