diff options
Diffstat (limited to 'drivers/net/cxgb3/cxgb3_main.c')
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index fb5df5c6203e..8b3e76c1cf52 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -172,6 +172,23 @@ static void link_report(struct net_device *dev) | |||
172 | } | 172 | } |
173 | } | 173 | } |
174 | 174 | ||
175 | static void enable_tx_fifo_drain(struct adapter *adapter, | ||
176 | struct port_info *pi) | ||
177 | { | ||
178 | t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + pi->mac.offset, 0, | ||
179 | F_ENDROPPKT); | ||
180 | t3_write_reg(adapter, A_XGM_RX_CTRL + pi->mac.offset, 0); | ||
181 | t3_write_reg(adapter, A_XGM_TX_CTRL + pi->mac.offset, F_TXEN); | ||
182 | t3_write_reg(adapter, A_XGM_RX_CTRL + pi->mac.offset, F_RXEN); | ||
183 | } | ||
184 | |||
185 | static void disable_tx_fifo_drain(struct adapter *adapter, | ||
186 | struct port_info *pi) | ||
187 | { | ||
188 | t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + pi->mac.offset, | ||
189 | F_ENDROPPKT, 0); | ||
190 | } | ||
191 | |||
175 | void t3_os_link_fault(struct adapter *adap, int port_id, int state) | 192 | void t3_os_link_fault(struct adapter *adap, int port_id, int state) |
176 | { | 193 | { |
177 | struct net_device *dev = adap->port[port_id]; | 194 | struct net_device *dev = adap->port[port_id]; |
@@ -185,6 +202,8 @@ void t3_os_link_fault(struct adapter *adap, int port_id, int state) | |||
185 | 202 | ||
186 | netif_carrier_on(dev); | 203 | netif_carrier_on(dev); |
187 | 204 | ||
205 | disable_tx_fifo_drain(adap, pi); | ||
206 | |||
188 | /* Clear local faults */ | 207 | /* Clear local faults */ |
189 | t3_xgm_intr_disable(adap, pi->port_id); | 208 | t3_xgm_intr_disable(adap, pi->port_id); |
190 | t3_read_reg(adap, A_XGM_INT_STATUS + | 209 | t3_read_reg(adap, A_XGM_INT_STATUS + |
@@ -200,9 +219,12 @@ void t3_os_link_fault(struct adapter *adap, int port_id, int state) | |||
200 | t3_xgm_intr_enable(adap, pi->port_id); | 219 | t3_xgm_intr_enable(adap, pi->port_id); |
201 | 220 | ||
202 | t3_mac_enable(mac, MAC_DIRECTION_TX); | 221 | t3_mac_enable(mac, MAC_DIRECTION_TX); |
203 | } else | 222 | } else { |
204 | netif_carrier_off(dev); | 223 | netif_carrier_off(dev); |
205 | 224 | ||
225 | /* Flush TX FIFO */ | ||
226 | enable_tx_fifo_drain(adap, pi); | ||
227 | } | ||
206 | link_report(dev); | 228 | link_report(dev); |
207 | } | 229 | } |
208 | 230 | ||
@@ -232,6 +254,8 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, | |||
232 | 254 | ||
233 | if (link_stat != netif_carrier_ok(dev)) { | 255 | if (link_stat != netif_carrier_ok(dev)) { |
234 | if (link_stat) { | 256 | if (link_stat) { |
257 | disable_tx_fifo_drain(adapter, pi); | ||
258 | |||
235 | t3_mac_enable(mac, MAC_DIRECTION_RX); | 259 | t3_mac_enable(mac, MAC_DIRECTION_RX); |
236 | 260 | ||
237 | /* Clear local faults */ | 261 | /* Clear local faults */ |
@@ -263,6 +287,9 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, | |||
263 | t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset); | 287 | t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset); |
264 | t3_mac_disable(mac, MAC_DIRECTION_RX); | 288 | t3_mac_disable(mac, MAC_DIRECTION_RX); |
265 | t3_link_start(&pi->phy, mac, &pi->link_config); | 289 | t3_link_start(&pi->phy, mac, &pi->link_config); |
290 | |||
291 | /* Flush TX FIFO */ | ||
292 | enable_tx_fifo_drain(adapter, pi); | ||
266 | } | 293 | } |
267 | 294 | ||
268 | link_report(dev); | 295 | link_report(dev); |
@@ -443,6 +470,7 @@ static int init_tp_parity(struct adapter *adap) | |||
443 | memset(req, 0, sizeof(*req)); | 470 | memset(req, 0, sizeof(*req)); |
444 | req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); | 471 | req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); |
445 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, i)); | 472 | OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SMT_WRITE_REQ, i)); |
473 | req->mtu_idx = NMTUS - 1; | ||
446 | req->iff = i; | 474 | req->iff = i; |
447 | t3_mgmt_tx(adap, skb); | 475 | t3_mgmt_tx(adap, skb); |
448 | if (skb == adap->nofail_skb) { | 476 | if (skb == adap->nofail_skb) { |
@@ -963,6 +991,75 @@ static int bind_qsets(struct adapter *adap) | |||
963 | 991 | ||
964 | #define FW_FNAME "cxgb3/t3fw-%d.%d.%d.bin" | 992 | #define FW_FNAME "cxgb3/t3fw-%d.%d.%d.bin" |
965 | #define TPSRAM_NAME "cxgb3/t3%c_psram-%d.%d.%d.bin" | 993 | #define TPSRAM_NAME "cxgb3/t3%c_psram-%d.%d.%d.bin" |
994 | #define AEL2005_OPT_EDC_NAME "cxgb3/ael2005_opt_edc.bin" | ||
995 | #define AEL2005_TWX_EDC_NAME "cxgb3/ael2005_twx_edc.bin" | ||
996 | #define AEL2020_TWX_EDC_NAME "cxgb3/ael2020_twx_edc.bin" | ||
997 | |||
998 | static inline const char *get_edc_fw_name(int edc_idx) | ||
999 | { | ||
1000 | const char *fw_name = NULL; | ||
1001 | |||
1002 | switch (edc_idx) { | ||
1003 | case EDC_OPT_AEL2005: | ||
1004 | fw_name = AEL2005_OPT_EDC_NAME; | ||
1005 | break; | ||
1006 | case EDC_TWX_AEL2005: | ||
1007 | fw_name = AEL2005_TWX_EDC_NAME; | ||
1008 | break; | ||
1009 | case EDC_TWX_AEL2020: | ||
1010 | fw_name = AEL2020_TWX_EDC_NAME; | ||
1011 | break; | ||
1012 | } | ||
1013 | return fw_name; | ||
1014 | } | ||
1015 | |||
1016 | int t3_get_edc_fw(struct cphy *phy, int edc_idx, int size) | ||
1017 | { | ||
1018 | struct adapter *adapter = phy->adapter; | ||
1019 | const struct firmware *fw; | ||
1020 | char buf[64]; | ||
1021 | u32 csum; | ||
1022 | const __be32 *p; | ||
1023 | u16 *cache = phy->phy_cache; | ||
1024 | int i, ret; | ||
1025 | |||
1026 | snprintf(buf, sizeof(buf), get_edc_fw_name(edc_idx)); | ||
1027 | |||
1028 | ret = request_firmware(&fw, buf, &adapter->pdev->dev); | ||
1029 | if (ret < 0) { | ||
1030 | dev_err(&adapter->pdev->dev, | ||
1031 | "could not upgrade firmware: unable to load %s\n", | ||
1032 | buf); | ||
1033 | return ret; | ||
1034 | } | ||
1035 | |||
1036 | /* check size, take checksum in account */ | ||
1037 | if (fw->size > size + 4) { | ||
1038 | CH_ERR(adapter, "firmware image too large %u, expected %d\n", | ||
1039 | (unsigned int)fw->size, size + 4); | ||
1040 | ret = -EINVAL; | ||
1041 | } | ||
1042 | |||
1043 | /* compute checksum */ | ||
1044 | p = (const __be32 *)fw->data; | ||
1045 | for (csum = 0, i = 0; i < fw->size / sizeof(csum); i++) | ||
1046 | csum += ntohl(p[i]); | ||
1047 | |||
1048 | if (csum != 0xffffffff) { | ||
1049 | CH_ERR(adapter, "corrupted firmware image, checksum %u\n", | ||
1050 | csum); | ||
1051 | ret = -EINVAL; | ||
1052 | } | ||
1053 | |||
1054 | for (i = 0; i < size / 4 ; i++) { | ||
1055 | *cache++ = (be32_to_cpu(p[i]) & 0xffff0000) >> 16; | ||
1056 | *cache++ = be32_to_cpu(p[i]) & 0xffff; | ||
1057 | } | ||
1058 | |||
1059 | release_firmware(fw); | ||
1060 | |||
1061 | return ret; | ||
1062 | } | ||
966 | 1063 | ||
967 | static int upgrade_fw(struct adapter *adap) | 1064 | static int upgrade_fw(struct adapter *adap) |
968 | { | 1065 | { |