aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDivy Le Ray <divy@chelsio.com>2009-03-12 17:14:14 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-13 14:30:46 -0400
commitcd40658a616050df0a50d0a3ded06e3ebcc0a04a (patch)
treecb83082f19bc2934fc84f774af745ab8206263ef
parentfc88219601aa3f94def89433a6afde154e8faa8c (diff)
cxgb3: Update Rev3 mac workaround
Update the heurstics workaround unlocking a hung mac: - reduce Tx mac toggling by enabling Tx drain before resetting the mac - Take Tx (lack of) activity in account only - Update the monitoring counter range to 64 bits Signed-off-by: Divy Le Ray <divy@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/cxgb3/xgmac.c72
1 files changed, 33 insertions, 39 deletions
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c
index 9d7786937aad..4bd0901a97a6 100644
--- a/drivers/net/cxgb3/xgmac.c
+++ b/drivers/net/cxgb3/xgmac.c
@@ -150,7 +150,8 @@ int t3_mac_reset(struct cmac *mac)
150static int t3b2_mac_reset(struct cmac *mac) 150static int t3b2_mac_reset(struct cmac *mac)
151{ 151{
152 struct adapter *adap = mac->adapter; 152 struct adapter *adap = mac->adapter;
153 unsigned int oft = mac->offset; 153 unsigned int oft = mac->offset, store;
154 int idx = macidx(mac);
154 u32 val; 155 u32 val;
155 156
156 if (!macidx(mac)) 157 if (!macidx(mac))
@@ -158,14 +159,28 @@ static int t3b2_mac_reset(struct cmac *mac)
158 else 159 else
159 t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0); 160 t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
160 161
162 /* Stop NIC traffic to reduce the number of TXTOGGLES */
163 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 0);
164 /* Ensure TX drains */
165 t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN, 0);
166
161 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_); 167 t3_write_reg(adap, A_XGM_RESET_CTRL + oft, F_MAC_RESET_);
162 t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */ 168 t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
163 169
170 /* Store A_TP_TX_DROP_CFG_CH0 */
171 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
172 store = t3_read_reg(adap, A_TP_TX_DROP_CFG_CH0 + idx);
173
164 msleep(10); 174 msleep(10);
165 175
176 /* Change DROP_CFG to 0xc0000011 */
177 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
178 t3_write_reg(adap, A_TP_PIO_DATA, 0xc0000011);
179
166 /* Check for xgm Rx fifo empty */ 180 /* Check for xgm Rx fifo empty */
181 /* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */
167 if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft, 182 if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
168 0x80000000, 1, 5, 2)) { 183 0x80000000, 1, 1000, 2)) {
169 CH_ERR(adap, "MAC %d Rx fifo drain failed\n", 184 CH_ERR(adap, "MAC %d Rx fifo drain failed\n",
170 macidx(mac)); 185 macidx(mac));
171 return -1; 186 return -1;
@@ -191,11 +206,18 @@ static int t3b2_mac_reset(struct cmac *mac)
191 F_DISPAUSEFRAMES | F_EN1536BFRAMES | 206 F_DISPAUSEFRAMES | F_EN1536BFRAMES |
192 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST); 207 F_RMFCS | F_ENJUMBO | F_ENHASHMCAST);
193 208
194 if (!macidx(mac)) 209 /* Restore the DROP_CFG */
210 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
211 t3_write_reg(adap, A_TP_PIO_DATA, store);
212
213 if (!idx)
195 t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE); 214 t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE);
196 else 215 else
197 t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE); 216 t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE);
198 217
218 /* re-enable nic traffic */
219 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1);
220
199 return 0; 221 return 0;
200} 222}
201 223
@@ -332,15 +354,6 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
332 return -EINVAL; 354 return -EINVAL;
333 t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu); 355 t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, mtu);
334 356
335 /*
336 * Adjust the PAUSE frame watermarks. We always set the LWM, and the
337 * HWM only if flow-control is enabled.
338 */
339 hwm = max_t(unsigned int, MAC_RXFIFO_SIZE - 3 * mtu,
340 MAC_RXFIFO_SIZE * 38 / 100);
341 hwm = min(hwm, MAC_RXFIFO_SIZE - 8192);
342 lwm = min(3 * (int)mtu, MAC_RXFIFO_SIZE / 4);
343
344 if (adap->params.rev >= T3_REV_B2 && 357 if (adap->params.rev >= T3_REV_B2 &&
345 (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) { 358 (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
346 disable_exact_filters(mac); 359 disable_exact_filters(mac);
@@ -452,9 +465,12 @@ int t3_mac_enable(struct cmac *mac, int which)
452 465
453 if (which & MAC_DIRECTION_TX) { 466 if (which & MAC_DIRECTION_TX) {
454 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 467 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
455 t3_write_reg(adap, A_TP_PIO_DATA, 0xc0ede401); 468 t3_write_reg(adap, A_TP_PIO_DATA,
469 adap->params.rev == T3_REV_C ?
470 0xc4ffff01 : 0xc0ede401);
456 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE); 471 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_MODE);
457 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); 472 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx,
473 adap->params.rev == T3_REV_C ? 0 : 1 << idx);
458 474
459 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); 475 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
460 476
@@ -510,15 +526,12 @@ int t3b2_mac_watchdog_task(struct cmac *mac)
510 struct adapter *adap = mac->adapter; 526 struct adapter *adap = mac->adapter;
511 struct mac_stats *s = &mac->stats; 527 struct mac_stats *s = &mac->stats;
512 unsigned int tx_tcnt, tx_xcnt; 528 unsigned int tx_tcnt, tx_xcnt;
513 unsigned int tx_mcnt = s->tx_frames; 529 u64 tx_mcnt = s->tx_frames;
514 unsigned int rx_mcnt = s->rx_frames;
515 unsigned int rx_xcnt;
516 int status; 530 int status;
517 531
518 status = 0; 532 status = 0;
519 tx_xcnt = 1; /* By default tx_xcnt is making progress */ 533 tx_xcnt = 1; /* By default tx_xcnt is making progress */
520 tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt */ 534 tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt */
521 rx_xcnt = 1; /* By default rx_xcnt is making progress */
522 if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) { 535 if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) {
523 tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, 536 tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
524 A_XGM_TX_SPI4_SOP_EOP_CNT + 537 A_XGM_TX_SPI4_SOP_EOP_CNT +
@@ -529,11 +542,11 @@ int t3b2_mac_watchdog_task(struct cmac *mac)
529 tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, 542 tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
530 A_TP_PIO_DATA))); 543 A_TP_PIO_DATA)));
531 } else { 544 } else {
532 goto rxcheck; 545 goto out;
533 } 546 }
534 } else { 547 } else {
535 mac->toggle_cnt = 0; 548 mac->toggle_cnt = 0;
536 goto rxcheck; 549 goto out;
537 } 550 }
538 551
539 if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) { 552 if ((tx_tcnt != mac->tx_tcnt) && (mac->tx_xcnt == 0)) {
@@ -546,23 +559,6 @@ int t3b2_mac_watchdog_task(struct cmac *mac)
546 } 559 }
547 } else { 560 } else {
548 mac->toggle_cnt = 0; 561 mac->toggle_cnt = 0;
549 goto rxcheck;
550 }
551
552rxcheck:
553 if (rx_mcnt != mac->rx_mcnt) {
554 rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
555 A_XGM_RX_SPI4_SOP_EOP_CNT +
556 mac->offset))) +
557 (s->rx_fifo_ovfl -
558 mac->rx_ocnt);
559 mac->rx_ocnt = s->rx_fifo_ovfl;
560 } else
561 goto out;
562
563 if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 &&
564 mac->rx_xcnt == 0) {
565 status = 2;
566 goto out; 562 goto out;
567 } 563 }
568 564
@@ -570,8 +566,6 @@ out:
570 mac->tx_tcnt = tx_tcnt; 566 mac->tx_tcnt = tx_tcnt;
571 mac->tx_xcnt = tx_xcnt; 567 mac->tx_xcnt = tx_xcnt;
572 mac->tx_mcnt = s->tx_frames; 568 mac->tx_mcnt = s->tx_frames;
573 mac->rx_xcnt = rx_xcnt;
574 mac->rx_mcnt = s->rx_frames;
575 mac->rx_pause = s->rx_pause; 569 mac->rx_pause = s->rx_pause;
576 if (status == 1) { 570 if (status == 1) {
577 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); 571 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);