diff options
author | Divy Le Ray <divy@chelsio.com> | 2007-04-09 23:10:27 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-11 11:54:43 -0400 |
commit | 59cf81076a85e1df273155298c462574b49cc0fe (patch) | |
tree | d03245a0621b241fe5afa0e86bc65c8db28001e1 /drivers | |
parent | f2d961c9827bab4b64a1b4ea30c68cf5ab2b2330 (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')
-rw-r--r-- | drivers/net/cxgb3/common.h | 7 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 10 | ||||
-rw-r--r-- | drivers/net/cxgb3/xgmac.c | 107 |
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 | ||
409 | int t3b2_mac_watchdog_task(struct cmac *mac) | 429 | int 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 | ||