diff options
author | Divy Le Ray <divy@chelsio.com> | 2009-07-07 19:48:32 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-07-08 10:54:27 -0700 |
commit | 34701fde8f4bf207ca96d10b8700a8667157854c (patch) | |
tree | 9d587019df540965231e045688db348ffde5ef2f /drivers/net/cxgb3/cxgb3_main.c | |
parent | 88045b3cf0f8981129cb489c7b6bc36c21dd33a7 (diff) |
cxgb3: Drain Mac Tx fifo when the port goes down.
Drain the MAC TX fifos when a port goes down.
Back pressure might otherwise occur, leading to both
ports of the same adapter to hang.
Signed-off-by: Divy Le Ray <divy@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cxgb3/cxgb3_main.c')
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index d4c4076cf08..8c381c696a3 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -172,6 +172,23 @@ static void link_report(struct net_device *dev) } } +static void enable_tx_fifo_drain(struct adapter *adapter, + struct port_info *pi) +{ + t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + pi->mac.offset, 0, + F_ENDROPPKT); + t3_write_reg(adapter, A_XGM_RX_CTRL + pi->mac.offset, 0); + t3_write_reg(adapter, A_XGM_TX_CTRL + pi->mac.offset, F_TXEN); + t3_write_reg(adapter, A_XGM_RX_CTRL + pi->mac.offset, F_RXEN); +} + +static void disable_tx_fifo_drain(struct adapter *adapter, + struct port_info *pi) +{ + t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + pi->mac.offset, + F_ENDROPPKT, 0); +} + void t3_os_link_fault(struct adapter *adap, int port_id, int state) { struct net_device *dev = adap->port[port_id]; @@ -185,6 +202,8 @@ void t3_os_link_fault(struct adapter *adap, int port_id, int state) netif_carrier_on(dev); + disable_tx_fifo_drain(adap, pi); + /* Clear local faults */ t3_xgm_intr_disable(adap, pi->port_id); t3_read_reg(adap, A_XGM_INT_STATUS + @@ -200,9 +219,12 @@ void t3_os_link_fault(struct adapter *adap, int port_id, int state) t3_xgm_intr_enable(adap, pi->port_id); t3_mac_enable(mac, MAC_DIRECTION_TX); - } else + } else { netif_carrier_off(dev); + /* Flush TX FIFO */ + enable_tx_fifo_drain(adap, pi); + } link_report(dev); } @@ -232,6 +254,8 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, if (link_stat != netif_carrier_ok(dev)) { if (link_stat) { + disable_tx_fifo_drain(adapter, pi); + t3_mac_enable(mac, MAC_DIRECTION_RX); /* Clear local faults */ @@ -263,6 +287,9 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat, t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset); t3_mac_disable(mac, MAC_DIRECTION_RX); t3_link_start(&pi->phy, mac, &pi->link_config); + + /* Flush TX FIFO */ + enable_tx_fifo_drain(adapter, pi); } link_report(dev); |