aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb3
diff options
context:
space:
mode:
authorDivy Le Ray <divy@chelsio.com>2007-04-09 23:10:27 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-11 11:54:43 -0400
commit59cf81076a85e1df273155298c462574b49cc0fe (patch)
treed03245a0621b241fe5afa0e86bc65c8db28001e1 /drivers/net/cxgb3
parentf2d961c9827bab4b64a1b4ea30c68cf5ab2b2330 (diff)
cxgb3 - MAC watchdog update
The MAC watchdog was failing if the peer interface was brought down. Signed-off-by: Divy Le Ray <divy@chelsio.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/cxgb3')
-rw-r--r--drivers/net/cxgb3/common.h7
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c10
-rw-r--r--drivers/net/cxgb3/xgmac.c107
3 files changed, 89 insertions, 35 deletions
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index 97128d88eaef..8d1379633698 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -478,8 +478,11 @@ struct cmac {
478 struct adapter *adapter; 478 struct adapter *adapter;
479 unsigned int offset; 479 unsigned int offset;
480 unsigned int nucast; /* # of address filters for unicast MACs */ 480 unsigned int nucast; /* # of address filters for unicast MACs */
481 unsigned int tcnt; 481 unsigned int tx_tcnt;
482 unsigned int xcnt; 482 unsigned int tx_xcnt;
483 u64 tx_mcnt;
484 unsigned int rx_xcnt;
485 u64 rx_mcnt;
483 unsigned int toggle_cnt; 486 unsigned int toggle_cnt;
484 unsigned int txen; 487 unsigned int txen;
485 struct mac_stats stats; 488 struct mac_stats stats;
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index c6ebe25464ca..d6eb9824a10c 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -194,15 +194,13 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
194 194
195 if (link_stat != netif_carrier_ok(dev)) { 195 if (link_stat != netif_carrier_ok(dev)) {
196 if (link_stat) { 196 if (link_stat) {
197 t3_set_reg_field(adapter, 197 t3_mac_enable(mac, MAC_DIRECTION_RX);
198 A_XGM_TXFIFO_CFG + mac->offset,
199 F_ENDROPPKT, 0);
200 netif_carrier_on(dev); 198 netif_carrier_on(dev);
201 } else { 199 } else {
202 netif_carrier_off(dev); 200 netif_carrier_off(dev);
203 t3_set_reg_field(adapter, 201 pi->phy.ops->power_down(&pi->phy, 1);
204 A_XGM_TXFIFO_CFG + mac->offset, 202 t3_mac_disable(mac, MAC_DIRECTION_RX);
205 F_ENDROPPKT, F_ENDROPPKT); 203 t3_link_start(&pi->phy, mac, &pi->link_config);
206 } 204 }
207 205
208 link_report(dev); 206 link_report(dev);
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c
index 94aaff005a35..a506792f9575 100644
--- a/drivers/net/cxgb3/xgmac.c
+++ b/drivers/net/cxgb3/xgmac.c
@@ -367,7 +367,8 @@ int t3_mac_enable(struct cmac *mac, int which)
367 int idx = macidx(mac); 367 int idx = macidx(mac);
368 struct adapter *adap = mac->adapter; 368 struct adapter *adap = mac->adapter;
369 unsigned int oft = mac->offset; 369 unsigned int oft = mac->offset;
370 370 struct mac_stats *s = &mac->stats;
371
371 if (which & MAC_DIRECTION_TX) { 372 if (which & MAC_DIRECTION_TX) {
372 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); 373 t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
373 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx); 374 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
@@ -376,10 +377,16 @@ int t3_mac_enable(struct cmac *mac, int which)
376 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); 377 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx);
377 378
378 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx); 379 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
379 mac->tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, 380 mac->tx_mcnt = s->tx_frames;
380 A_TP_PIO_DATA))); 381 mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
381 mac->xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, 382 A_TP_PIO_DATA)));
382 A_XGM_TX_SPI4_SOP_EOP_CNT))); 383 mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
384 A_XGM_TX_SPI4_SOP_EOP_CNT +
385 oft)));
386 mac->rx_mcnt = s->rx_frames;
387 mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
388 A_XGM_RX_SPI4_SOP_EOP_CNT +
389 oft)));
383 mac->txen = F_TXEN; 390 mac->txen = F_TXEN;
384 mac->toggle_cnt = 0; 391 mac->toggle_cnt = 0;
385 } 392 }
@@ -392,6 +399,7 @@ int t3_mac_disable(struct cmac *mac, int which)
392{ 399{
393 int idx = macidx(mac); 400 int idx = macidx(mac);
394 struct adapter *adap = mac->adapter; 401 struct adapter *adap = mac->adapter;
402 int val;
395 403
396 if (which & MAC_DIRECTION_TX) { 404 if (which & MAC_DIRECTION_TX) {
397 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); 405 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
@@ -401,44 +409,89 @@ int t3_mac_disable(struct cmac *mac, int which)
401 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); 409 t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx);
402 mac->txen = 0; 410 mac->txen = 0;
403 } 411 }
404 if (which & MAC_DIRECTION_RX) 412 if (which & MAC_DIRECTION_RX) {
413 t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
414 F_PCS_RESET_, 0);
415 msleep(100);
405 t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); 416 t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
417 val = F_MAC_RESET_;
418 if (is_10G(adap))
419 val |= F_PCS_RESET_;
420 else if (uses_xaui(adap))
421 val |= F_PCS_RESET_ | F_XG2G_RESET_;
422 else
423 val |= F_RGMII_RESET_ | F_XG2G_RESET_;
424 t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val);
425 }
406 return 0; 426 return 0;
407} 427}
408 428
409int t3b2_mac_watchdog_task(struct cmac *mac) 429int t3b2_mac_watchdog_task(struct cmac *mac)
410{ 430{
411 struct adapter *adap = mac->adapter; 431 struct adapter *adap = mac->adapter;
412 unsigned int tcnt, xcnt; 432 struct mac_stats *s = &mac->stats;
433 unsigned int tx_tcnt, tx_xcnt;
434 unsigned int tx_mcnt = s->tx_frames;
435 unsigned int rx_mcnt = s->rx_frames;
436 unsigned int rx_xcnt;
413 int status; 437 int status;
414 438
415 t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + macidx(mac)); 439 if (tx_mcnt == mac->tx_mcnt) {
416 tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, A_TP_PIO_DATA))); 440 tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
417 xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, 441 A_XGM_TX_SPI4_SOP_EOP_CNT +
418 A_XGM_TX_SPI4_SOP_EOP_CNT + 442 mac->offset)));
419 mac->offset))); 443 if (tx_xcnt == 0) {
420 444 t3_write_reg(adap, A_TP_PIO_ADDR,
421 if (tcnt != mac->tcnt && xcnt == 0 && mac->xcnt == 0) { 445 A_TP_TX_DROP_CNT_CH0 + macidx(mac));
422 if (mac->toggle_cnt > 4) { 446 tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
423 t3b2_mac_reset(mac); 447 A_TP_PIO_DATA)));
448 } else {
424 mac->toggle_cnt = 0; 449 mac->toggle_cnt = 0;
450 return 0;
451 }
452 } else {
453 mac->toggle_cnt = 0;
454 return 0;
455 }
456
457 if (((tx_tcnt != mac->tx_tcnt) &&
458 (tx_xcnt == 0) && (mac->tx_xcnt == 0)) ||
459 ((mac->tx_mcnt == tx_mcnt) &&
460 (tx_xcnt != 0) && (mac->tx_xcnt != 0))) {
461 if (mac->toggle_cnt > 4)
425 status = 2; 462 status = 2;
426 } else { 463 else
427 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
428 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset);
429 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset,
430 mac->txen);
431 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset);
432 mac->toggle_cnt++;
433 status = 1; 464 status = 1;
434 }
435 } else { 465 } else {
436 mac->toggle_cnt = 0; 466 mac->toggle_cnt = 0;
437 status = 0; 467 return 0;
438 } 468 }
439 mac->tcnt = tcnt;
440 mac->xcnt = xcnt;
441 469
470 if (rx_mcnt != mac->rx_mcnt)
471 rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
472 A_XGM_RX_SPI4_SOP_EOP_CNT +
473 mac->offset)));
474 else
475 return 0;
476
477 if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && mac->rx_xcnt == 0)
478 status = 2;
479
480 mac->tx_tcnt = tx_tcnt;
481 mac->tx_xcnt = tx_xcnt;
482 mac->tx_mcnt = s->tx_frames;
483 mac->rx_xcnt = rx_xcnt;
484 mac->rx_mcnt = s->rx_frames;
485 if (status == 1) {
486 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
487 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
488 t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen);
489 t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
490 mac->toggle_cnt++;
491 } else if (status == 2) {
492 t3b2_mac_reset(mac);
493 mac->toggle_cnt = 0;
494 }
442 return status; 495 return status;
443} 496}
444 497