aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb3/cxgb3_main.c
diff options
context:
space:
mode:
authorDivy Le Ray <divy@chelsio.com>2007-03-18 16:10:12 -0400
committerJeff Garzik <jeff@garzik.org>2007-03-23 01:48:34 -0400
commitfc90664e3438c990d280f179ccb0642711d5c553 (patch)
tree8ece58a4eec002186f1c569385830f03336b50af /drivers/net/cxgb3/cxgb3_main.c
parent2e2839627a957714808f98a802d137a7a2a1df46 (diff)
cxgb3 - Fix potential MAC hang
Under rare conditions, the MAC might hang while generating a pause frame. This patch fine tunes the MAC settings to avoid the issue, allows for periodic MAC state check, and triggers a recovery if hung. Also fix one MAC statistics counter for the rev board T3B2. Signed-off-by: Divy Le Ray <divy@chelsio.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/cxgb3/cxgb3_main.c')
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index b9bcda821f7c..d55383610559 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -1056,7 +1056,11 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
1056 "VLANinsertions ", 1056 "VLANinsertions ",
1057 "TxCsumOffload ", 1057 "TxCsumOffload ",
1058 "RxCsumGood ", 1058 "RxCsumGood ",
1059 "RxDrops " 1059 "RxDrops ",
1060
1061 "CheckTXEnToggled ",
1062 "CheckResets ",
1063
1060}; 1064};
1061 1065
1062static int get_stats_count(struct net_device *dev) 1066static int get_stats_count(struct net_device *dev)
@@ -1170,6 +1174,9 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
1170 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM); 1174 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM);
1171 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD); 1175 *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD);
1172 *data++ = s->rx_cong_drops; 1176 *data++ = s->rx_cong_drops;
1177
1178 *data++ = s->num_toggled;
1179 *data++ = s->num_resets;
1173} 1180}
1174 1181
1175static inline void reg_block_dump(struct adapter *ap, void *buf, 1182static inline void reg_block_dump(struct adapter *ap, void *buf,
@@ -2095,6 +2102,40 @@ static void check_link_status(struct adapter *adapter)
2095 } 2102 }
2096} 2103}
2097 2104
2105static void check_t3b2_mac(struct adapter *adapter)
2106{
2107 int i;
2108
2109 rtnl_lock(); /* synchronize with ifdown */
2110 for_each_port(adapter, i) {
2111 struct net_device *dev = adapter->port[i];
2112 struct port_info *p = netdev_priv(dev);
2113 int status;
2114
2115 if (!netif_running(dev))
2116 continue;
2117
2118 status = 0;
2119 if (netif_running(dev))
2120 status = t3b2_mac_watchdog_task(&p->mac);
2121 if (status == 1)
2122 p->mac.stats.num_toggled++;
2123 else if (status == 2) {
2124 struct cmac *mac = &p->mac;
2125
2126 t3_mac_set_mtu(mac, dev->mtu);
2127 t3_mac_set_address(mac, 0, dev->dev_addr);
2128 cxgb_set_rxmode(dev);
2129 t3_link_start(&p->phy, mac, &p->link_config);
2130 t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
2131 t3_port_intr_enable(adapter, p->port_id);
2132 p->mac.stats.num_resets++;
2133 }
2134 }
2135 rtnl_unlock();
2136}
2137
2138
2098static void t3_adap_check_task(struct work_struct *work) 2139static void t3_adap_check_task(struct work_struct *work)
2099{ 2140{
2100 struct adapter *adapter = container_of(work, struct adapter, 2141 struct adapter *adapter = container_of(work, struct adapter,
@@ -2115,6 +2156,9 @@ static void t3_adap_check_task(struct work_struct *work)
2115 adapter->check_task_cnt = 0; 2156 adapter->check_task_cnt = 0;
2116 } 2157 }
2117 2158
2159 if (p->rev == T3_REV_B2)
2160 check_t3b2_mac(adapter);
2161
2118 /* Schedule the next check update if any port is active. */ 2162 /* Schedule the next check update if any port is active. */
2119 spin_lock(&adapter->work_lock); 2163 spin_lock(&adapter->work_lock);
2120 if (adapter->open_device_map & PORT_MASK) 2164 if (adapter->open_device_map & PORT_MASK)