Commit 59cf8107 authored by Divy Le Ray's avatar Divy Le Ray Committed by Jeff Garzik

cxgb3 - MAC watchdog update

The MAC watchdog was failing if the peer interface was brought down.
Signed-off-by: default avatarDivy Le Ray <divy@chelsio.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent f2d961c9
...@@ -478,8 +478,11 @@ struct cmac { ...@@ -478,8 +478,11 @@ struct cmac {
struct adapter *adapter; struct adapter *adapter;
unsigned int offset; unsigned int offset;
unsigned int nucast; /* # of address filters for unicast MACs */ unsigned int nucast; /* # of address filters for unicast MACs */
unsigned int tcnt; unsigned int tx_tcnt;
unsigned int xcnt; unsigned int tx_xcnt;
u64 tx_mcnt;
unsigned int rx_xcnt;
u64 rx_mcnt;
unsigned int toggle_cnt; unsigned int toggle_cnt;
unsigned int txen; unsigned int txen;
struct mac_stats stats; struct mac_stats stats;
......
...@@ -194,15 +194,13 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, ...@@ -194,15 +194,13 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
if (link_stat != netif_carrier_ok(dev)) { if (link_stat != netif_carrier_ok(dev)) {
if (link_stat) { if (link_stat) {
t3_set_reg_field(adapter, t3_mac_enable(mac, MAC_DIRECTION_RX);
A_XGM_TXFIFO_CFG + mac->offset,
F_ENDROPPKT, 0);
netif_carrier_on(dev); netif_carrier_on(dev);
} else { } else {
netif_carrier_off(dev); netif_carrier_off(dev);
t3_set_reg_field(adapter, pi->phy.ops->power_down(&pi->phy, 1);
A_XGM_TXFIFO_CFG + mac->offset, t3_mac_disable(mac, MAC_DIRECTION_RX);
F_ENDROPPKT, F_ENDROPPKT); t3_link_start(&pi->phy, mac, &pi->link_config);
} }
link_report(dev); link_report(dev);
......
...@@ -367,6 +367,7 @@ int t3_mac_enable(struct cmac *mac, int which) ...@@ -367,6 +367,7 @@ int t3_mac_enable(struct cmac *mac, int which)
int idx = macidx(mac); int idx = macidx(mac);
struct adapter *adap = mac->adapter; struct adapter *adap = mac->adapter;
unsigned int oft = mac->offset; unsigned int oft = mac->offset;
struct mac_stats *s = &mac->stats;
if (which & MAC_DIRECTION_TX) { if (which & MAC_DIRECTION_TX) {
t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN); t3_write_reg(adap, A_XGM_TX_CTRL + oft, F_TXEN);
...@@ -376,10 +377,16 @@ int t3_mac_enable(struct cmac *mac, int which) ...@@ -376,10 +377,16 @@ int t3_mac_enable(struct cmac *mac, int which)
t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx);
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx); t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + idx);
mac->tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, mac->tx_mcnt = s->tx_frames;
mac->tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
A_TP_PIO_DATA))); A_TP_PIO_DATA)));
mac->xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap, mac->tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
A_XGM_TX_SPI4_SOP_EOP_CNT))); A_XGM_TX_SPI4_SOP_EOP_CNT +
oft)));
mac->rx_mcnt = s->rx_frames;
mac->rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
A_XGM_RX_SPI4_SOP_EOP_CNT +
oft)));
mac->txen = F_TXEN; mac->txen = F_TXEN;
mac->toggle_cnt = 0; mac->toggle_cnt = 0;
} }
...@@ -392,6 +399,7 @@ int t3_mac_disable(struct cmac *mac, int which) ...@@ -392,6 +399,7 @@ int t3_mac_disable(struct cmac *mac, int which)
{ {
int idx = macidx(mac); int idx = macidx(mac);
struct adapter *adap = mac->adapter; struct adapter *adap = mac->adapter;
int val;
if (which & MAC_DIRECTION_TX) { if (which & MAC_DIRECTION_TX) {
t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); 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,44 +409,89 @@ int t3_mac_disable(struct cmac *mac, int which)
t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx); t3_set_reg_field(adap, A_TP_PIO_DATA, 1 << idx, 1 << idx);
mac->txen = 0; mac->txen = 0;
} }
if (which & MAC_DIRECTION_RX) if (which & MAC_DIRECTION_RX) {
t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
F_PCS_RESET_, 0);
msleep(100);
t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0); t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
val = F_MAC_RESET_;
if (is_10G(adap))
val |= F_PCS_RESET_;
else if (uses_xaui(adap))
val |= F_PCS_RESET_ | F_XG2G_RESET_;
else
val |= F_RGMII_RESET_ | F_XG2G_RESET_;
t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val);
}
return 0; return 0;
} }
int t3b2_mac_watchdog_task(struct cmac *mac) int t3b2_mac_watchdog_task(struct cmac *mac)
{ {
struct adapter *adap = mac->adapter; struct adapter *adap = mac->adapter;
unsigned int tcnt, xcnt; struct mac_stats *s = &mac->stats;
unsigned int tx_tcnt, tx_xcnt;
unsigned int tx_mcnt = s->tx_frames;
unsigned int rx_mcnt = s->rx_frames;
unsigned int rx_xcnt;
int status; int status;
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CNT_CH0 + macidx(mac)); if (tx_mcnt == mac->tx_mcnt) {
tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap, A_TP_PIO_DATA))); tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
A_XGM_TX_SPI4_SOP_EOP_CNT + A_XGM_TX_SPI4_SOP_EOP_CNT +
mac->offset))); mac->offset)));
if (tx_xcnt == 0) {
if (tcnt != mac->tcnt && xcnt == 0 && mac->xcnt == 0) { t3_write_reg(adap, A_TP_PIO_ADDR,
if (mac->toggle_cnt > 4) { A_TP_TX_DROP_CNT_CH0 + macidx(mac));
t3b2_mac_reset(mac); tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
A_TP_PIO_DATA)));
} else {
mac->toggle_cnt = 0; mac->toggle_cnt = 0;
status = 2; return 0;
}
} else { } else {
t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0); mac->toggle_cnt = 0;
t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); return 0;
t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset,
mac->txen);
t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset);
mac->toggle_cnt++;
status = 1;
} }
if (((tx_tcnt != mac->tx_tcnt) &&
(tx_xcnt == 0) && (mac->tx_xcnt == 0)) ||
((mac->tx_mcnt == tx_mcnt) &&
(tx_xcnt != 0) && (mac->tx_xcnt != 0))) {
if (mac->toggle_cnt > 4)
status = 2;
else
status = 1;
} else { } else {
mac->toggle_cnt = 0; mac->toggle_cnt = 0;
status = 0; return 0;
} }
mac->tcnt = tcnt;
mac->xcnt = xcnt;
if (rx_mcnt != mac->rx_mcnt)
rx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
A_XGM_RX_SPI4_SOP_EOP_CNT +
mac->offset)));
else
return 0;
if (mac->rx_mcnt != s->rx_frames && rx_xcnt == 0 && mac->rx_xcnt == 0)
status = 2;
mac->tx_tcnt = tx_tcnt;
mac->tx_xcnt = tx_xcnt;
mac->tx_mcnt = s->tx_frames;
mac->rx_xcnt = rx_xcnt;
mac->rx_mcnt = s->rx_frames;
if (status == 1) {
t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, 0);
t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
t3_write_reg(adap, A_XGM_TX_CTRL + mac->offset, mac->txen);
t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
mac->toggle_cnt++;
} else if (status == 2) {
t3b2_mac_reset(mac);
mac->toggle_cnt = 0;
}
return status; return status;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment