aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDivy Le Ray <divy@chelsio.com>2009-07-07 15:48:32 -0400
committerDavid S. Miller <davem@davemloft.net>2009-07-08 13:54:27 -0400
commit34701fde8f4bf207ca96d10b8700a8667157854c (patch)
tree9d587019df540965231e045688db348ffde5ef2f /drivers
parent88045b3cf0f8981129cb489c7b6bc36c21dd33a7 (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')
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index d4c4076cf087..8c381c696a3d 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)
172 } 172 }
173} 173}
174 174
175static void enable_tx_fifo_drain(struct adapter *adapter,
176 struct port_info *pi)
177{
178 t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + pi->mac.offset, 0,
179 F_ENDROPPKT);
180 t3_write_reg(adapter, A_XGM_RX_CTRL + pi->mac.offset, 0);
181 t3_write_reg(adapter, A_XGM_TX_CTRL + pi->mac.offset, F_TXEN);
182 t3_write_reg(adapter, A_XGM_RX_CTRL + pi->mac.offset, F_RXEN);
183}
184
185static void disable_tx_fifo_drain(struct adapter *adapter,
186 struct port_info *pi)
187{
188 t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + pi->mac.offset,
189 F_ENDROPPKT, 0);
190}
191
175void t3_os_link_fault(struct adapter *adap, int port_id, int state) 192void t3_os_link_fault(struct adapter *adap, int port_id, int state)
176{ 193{
177 struct net_device *dev = adap->port[port_id]; 194 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)
185 202
186 netif_carrier_on(dev); 203 netif_carrier_on(dev);
187 204
205 disable_tx_fifo_drain(adap, pi);
206
188 /* Clear local faults */ 207 /* Clear local faults */
189 t3_xgm_intr_disable(adap, pi->port_id); 208 t3_xgm_intr_disable(adap, pi->port_id);
190 t3_read_reg(adap, A_XGM_INT_STATUS + 209 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)
200 t3_xgm_intr_enable(adap, pi->port_id); 219 t3_xgm_intr_enable(adap, pi->port_id);
201 220
202 t3_mac_enable(mac, MAC_DIRECTION_TX); 221 t3_mac_enable(mac, MAC_DIRECTION_TX);
203 } else 222 } else {
204 netif_carrier_off(dev); 223 netif_carrier_off(dev);
205 224
225 /* Flush TX FIFO */
226 enable_tx_fifo_drain(adap, pi);
227 }
206 link_report(dev); 228 link_report(dev);
207} 229}
208 230
@@ -232,6 +254,8 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
232 254
233 if (link_stat != netif_carrier_ok(dev)) { 255 if (link_stat != netif_carrier_ok(dev)) {
234 if (link_stat) { 256 if (link_stat) {
257 disable_tx_fifo_drain(adapter, pi);
258
235 t3_mac_enable(mac, MAC_DIRECTION_RX); 259 t3_mac_enable(mac, MAC_DIRECTION_RX);
236 260
237 /* Clear local faults */ 261 /* Clear local faults */
@@ -263,6 +287,9 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
263 t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset); 287 t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset);
264 t3_mac_disable(mac, MAC_DIRECTION_RX); 288 t3_mac_disable(mac, MAC_DIRECTION_RX);
265 t3_link_start(&pi->phy, mac, &pi->link_config); 289 t3_link_start(&pi->phy, mac, &pi->link_config);
290
291 /* Flush TX FIFO */
292 enable_tx_fifo_drain(adapter, pi);
266 } 293 }
267 294
268 link_report(dev); 295 link_report(dev);