diff options
| -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 | ||
