aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb3/cxgb3_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/cxgb3/cxgb3_main.c')
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c99
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
175static 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
185static 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
175void t3_os_link_fault(struct adapter *adap, int port_id, int state) 192void 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
998static 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
1016int 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
967static int upgrade_fw(struct adapter *adap) 1064static int upgrade_fw(struct adapter *adap)
968{ 1065{