aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/cxgb3/adapter.h5
-rw-r--r--drivers/net/cxgb3/common.h6
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c123
-rw-r--r--drivers/net/cxgb3/regs.h13
-rw-r--r--drivers/net/cxgb3/t3_hw.c134
-rw-r--r--drivers/net/cxgb3/xgmac.c13
6 files changed, 285 insertions, 9 deletions
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index 66ce456614a8..71eaa431371d 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -68,6 +68,8 @@ struct port_info {
68 struct net_device_stats netstats; 68 struct net_device_stats netstats;
69 int activity; 69 int activity;
70 __be32 iscsi_ipv4addr; 70 __be32 iscsi_ipv4addr;
71
72 int link_fault; /* link fault was detected */
71}; 73};
72 74
73enum { /* adapter flags */ 75enum { /* adapter flags */
@@ -241,6 +243,7 @@ struct adapter {
241 struct delayed_work adap_check_task; 243 struct delayed_work adap_check_task;
242 struct work_struct ext_intr_handler_task; 244 struct work_struct ext_intr_handler_task;
243 struct work_struct fatal_error_handler_task; 245 struct work_struct fatal_error_handler_task;
246 struct work_struct link_fault_handler_task;
244 247
245 struct dentry *debugfs_root; 248 struct dentry *debugfs_root;
246 249
@@ -283,6 +286,8 @@ void t3_os_ext_intr_handler(struct adapter *adapter);
283void t3_os_link_changed(struct adapter *adapter, int port_id, int link_status, 286void t3_os_link_changed(struct adapter *adapter, int port_id, int link_status,
284 int speed, int duplex, int fc); 287 int speed, int duplex, int fc);
285void t3_os_phymod_changed(struct adapter *adap, int port_id); 288void t3_os_phymod_changed(struct adapter *adap, int port_id);
289void t3_os_link_fault(struct adapter *adapter, int port_id, int state);
290void t3_os_link_fault_handler(struct adapter *adapter, int port_id);
286 291
287void t3_sge_start(struct adapter *adap); 292void t3_sge_start(struct adapter *adap);
288void t3_sge_stop(struct adapter *adap); 293void t3_sge_stop(struct adapter *adap);
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index db4f4f575b6a..9ee021e750c8 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -280,6 +280,7 @@ struct mac_stats {
280 unsigned long num_toggled; /* # times toggled TxEn due to stuck TX */ 280 unsigned long num_toggled; /* # times toggled TxEn due to stuck TX */
281 unsigned long num_resets; /* # times reset due to stuck TX */ 281 unsigned long num_resets; /* # times reset due to stuck TX */
282 282
283 unsigned long link_faults; /* # detected link faults */
283}; 284};
284 285
285struct tp_mib_stats { 286struct tp_mib_stats {
@@ -701,6 +702,8 @@ int t3_phy_lasi_intr_handler(struct cphy *phy);
701void t3_intr_enable(struct adapter *adapter); 702void t3_intr_enable(struct adapter *adapter);
702void t3_intr_disable(struct adapter *adapter); 703void t3_intr_disable(struct adapter *adapter);
703void t3_intr_clear(struct adapter *adapter); 704void t3_intr_clear(struct adapter *adapter);
705void t3_xgm_intr_enable(struct adapter *adapter, int idx);
706void t3_xgm_intr_disable(struct adapter *adapter, int idx);
704void t3_port_intr_enable(struct adapter *adapter, int idx); 707void t3_port_intr_enable(struct adapter *adapter, int idx);
705void t3_port_intr_disable(struct adapter *adapter, int idx); 708void t3_port_intr_disable(struct adapter *adapter, int idx);
706void t3_port_intr_clear(struct adapter *adapter, int idx); 709void t3_port_intr_clear(struct adapter *adapter, int idx);
@@ -708,6 +711,7 @@ int t3_slow_intr_handler(struct adapter *adapter);
708int t3_phy_intr_handler(struct adapter *adapter); 711int t3_phy_intr_handler(struct adapter *adapter);
709 712
710void t3_link_changed(struct adapter *adapter, int port_id); 713void t3_link_changed(struct adapter *adapter, int port_id);
714void t3_link_fault(struct adapter *adapter, int port_id);
711int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc); 715int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc);
712const struct adapter_info *t3_get_adapter_info(unsigned int board_id); 716const struct adapter_info *t3_get_adapter_info(unsigned int board_id);
713int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data); 717int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data);
@@ -744,6 +748,8 @@ int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n,
744 748
745int t3_mac_reset(struct cmac *mac); 749int t3_mac_reset(struct cmac *mac);
746void t3b_pcs_reset(struct cmac *mac); 750void t3b_pcs_reset(struct cmac *mac);
751void t3_mac_disable_exact_filters(struct cmac *mac);
752void t3_mac_enable_exact_filters(struct cmac *mac);
747int t3_mac_enable(struct cmac *mac, int which); 753int t3_mac_enable(struct cmac *mac, int which);
748int t3_mac_disable(struct cmac *mac, int which); 754int t3_mac_disable(struct cmac *mac, int which);
749int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu); 755int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu);
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 9ff0452fcddd..d8be89621bf7 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -170,6 +170,40 @@ static void link_report(struct net_device *dev)
170 } 170 }
171} 171}
172 172
173void t3_os_link_fault(struct adapter *adap, int port_id, int state)
174{
175 struct net_device *dev = adap->port[port_id];
176 struct port_info *pi = netdev_priv(dev);
177
178 if (state == netif_carrier_ok(dev))
179 return;
180
181 if (state) {
182 struct cmac *mac = &pi->mac;
183
184 netif_carrier_on(dev);
185
186 /* Clear local faults */
187 t3_xgm_intr_disable(adap, pi->port_id);
188 t3_read_reg(adap, A_XGM_INT_STATUS +
189 pi->mac.offset);
190 t3_write_reg(adap,
191 A_XGM_INT_CAUSE + pi->mac.offset,
192 F_XGM_INT);
193
194 t3_set_reg_field(adap,
195 A_XGM_INT_ENABLE +
196 pi->mac.offset,
197 F_XGM_INT, F_XGM_INT);
198 t3_xgm_intr_enable(adap, pi->port_id);
199
200 t3_mac_enable(mac, MAC_DIRECTION_TX);
201 } else
202 netif_carrier_off(dev);
203
204 link_report(dev);
205}
206
173/** 207/**
174 * t3_os_link_changed - handle link status changes 208 * t3_os_link_changed - handle link status changes
175 * @adapter: the adapter associated with the link change 209 * @adapter: the adapter associated with the link change
@@ -197,10 +231,34 @@ void t3_os_link_changed(struct adapter *adapter, int port_id, int link_stat,
197 if (link_stat != netif_carrier_ok(dev)) { 231 if (link_stat != netif_carrier_ok(dev)) {
198 if (link_stat) { 232 if (link_stat) {
199 t3_mac_enable(mac, MAC_DIRECTION_RX); 233 t3_mac_enable(mac, MAC_DIRECTION_RX);
234
235 /* Clear local faults */
236 t3_xgm_intr_disable(adapter, pi->port_id);
237 t3_read_reg(adapter, A_XGM_INT_STATUS +
238 pi->mac.offset);
239 t3_write_reg(adapter,
240 A_XGM_INT_CAUSE + pi->mac.offset,
241 F_XGM_INT);
242
243 t3_set_reg_field(adapter,
244 A_XGM_INT_ENABLE + pi->mac.offset,
245 F_XGM_INT, F_XGM_INT);
246 t3_xgm_intr_enable(adapter, pi->port_id);
247
200 netif_carrier_on(dev); 248 netif_carrier_on(dev);
201 } else { 249 } else {
202 netif_carrier_off(dev); 250 netif_carrier_off(dev);
203 pi->phy.ops->power_down(&pi->phy, 1); 251
252 t3_xgm_intr_disable(adapter, pi->port_id);
253 t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset);
254 t3_set_reg_field(adapter,
255 A_XGM_INT_ENABLE + pi->mac.offset,
256 F_XGM_INT, 0);
257
258 if (is_10G(adapter))
259 pi->phy.ops->power_down(&pi->phy, 1);
260
261 t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset);
204 t3_mac_disable(mac, MAC_DIRECTION_RX); 262 t3_mac_disable(mac, MAC_DIRECTION_RX);
205 t3_link_start(&pi->phy, mac, &pi->link_config); 263 t3_link_start(&pi->phy, mac, &pi->link_config);
206 } 264 }
@@ -1173,6 +1231,10 @@ static int cxgb_close(struct net_device *dev)
1173 struct port_info *pi = netdev_priv(dev); 1231 struct port_info *pi = netdev_priv(dev);
1174 struct adapter *adapter = pi->adapter; 1232 struct adapter *adapter = pi->adapter;
1175 1233
1234 /* Stop link fault interrupts */
1235 t3_xgm_intr_disable(adapter, pi->port_id);
1236 t3_read_reg(adapter, A_XGM_INT_STATUS + pi->mac.offset);
1237
1176 t3_port_intr_disable(adapter, pi->port_id); 1238 t3_port_intr_disable(adapter, pi->port_id);
1177 netif_tx_stop_all_queues(dev); 1239 netif_tx_stop_all_queues(dev);
1178 pi->phy.ops->power_down(&pi->phy, 1); 1240 pi->phy.ops->power_down(&pi->phy, 1);
@@ -1299,6 +1361,7 @@ static char stats_strings[][ETH_GSTRING_LEN] = {
1299 "CheckTXEnToggled ", 1361 "CheckTXEnToggled ",
1300 "CheckResets ", 1362 "CheckResets ",
1301 1363
1364 "LinkFaults ",
1302}; 1365};
1303 1366
1304static int get_sset_count(struct net_device *dev, int sset) 1367static int get_sset_count(struct net_device *dev, int sset)
@@ -1431,6 +1494,8 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
1431 1494
1432 *data++ = s->num_toggled; 1495 *data++ = s->num_toggled;
1433 *data++ = s->num_resets; 1496 *data++ = s->num_resets;
1497
1498 *data++ = s->link_faults;
1434} 1499}
1435 1500
1436static inline void reg_block_dump(struct adapter *ap, void *buf, 1501static inline void reg_block_dump(struct adapter *ap, void *buf,
@@ -2425,8 +2490,20 @@ static void check_link_status(struct adapter *adapter)
2425 struct net_device *dev = adapter->port[i]; 2490 struct net_device *dev = adapter->port[i];
2426 struct port_info *p = netdev_priv(dev); 2491 struct port_info *p = netdev_priv(dev);
2427 2492
2428 if (!(p->phy.caps & SUPPORTED_IRQ) && netif_running(dev)) 2493 spin_lock_irq(&adapter->work_lock);
2494 if (p->link_fault) {
2495 spin_unlock_irq(&adapter->work_lock);
2496 continue;
2497 }
2498 spin_unlock_irq(&adapter->work_lock);
2499
2500 if (!(p->phy.caps & SUPPORTED_IRQ) && netif_running(dev)) {
2501 t3_xgm_intr_disable(adapter, i);
2502 t3_read_reg(adapter, A_XGM_INT_STATUS + p->mac.offset);
2503
2429 t3_link_changed(adapter, i); 2504 t3_link_changed(adapter, i);
2505 t3_xgm_intr_enable(adapter, i);
2506 }
2430 } 2507 }
2431} 2508}
2432 2509
@@ -2553,9 +2630,23 @@ static void ext_intr_task(struct work_struct *work)
2553{ 2630{
2554 struct adapter *adapter = container_of(work, struct adapter, 2631 struct adapter *adapter = container_of(work, struct adapter,
2555 ext_intr_handler_task); 2632 ext_intr_handler_task);
2633 int i;
2634
2635 /* Disable link fault interrupts */
2636 for_each_port(adapter, i) {
2637 struct net_device *dev = adapter->port[i];
2638 struct port_info *p = netdev_priv(dev);
2639
2640 t3_xgm_intr_disable(adapter, i);
2641 t3_read_reg(adapter, A_XGM_INT_STATUS + p->mac.offset);
2642 }
2556 2643
2644 /* Re-enable link fault interrupts */
2557 t3_phy_intr_handler(adapter); 2645 t3_phy_intr_handler(adapter);
2558 2646
2647 for_each_port(adapter, i)
2648 t3_xgm_intr_enable(adapter, i);
2649
2559 /* Now reenable external interrupts */ 2650 /* Now reenable external interrupts */
2560 spin_lock_irq(&adapter->work_lock); 2651 spin_lock_irq(&adapter->work_lock);
2561 if (adapter->slow_intr_mask) { 2652 if (adapter->slow_intr_mask) {
@@ -2588,6 +2679,32 @@ void t3_os_ext_intr_handler(struct adapter *adapter)
2588 spin_unlock(&adapter->work_lock); 2679 spin_unlock(&adapter->work_lock);
2589} 2680}
2590 2681
2682static void link_fault_task(struct work_struct *work)
2683{
2684 struct adapter *adapter = container_of(work, struct adapter,
2685 link_fault_handler_task);
2686 int i;
2687
2688 for_each_port(adapter, i) {
2689 struct net_device *netdev = adapter->port[i];
2690 struct port_info *pi = netdev_priv(netdev);
2691
2692 if (pi->link_fault)
2693 t3_link_fault(adapter, i);
2694 }
2695}
2696
2697void t3_os_link_fault_handler(struct adapter *adapter, int port_id)
2698{
2699 struct net_device *netdev = adapter->port[port_id];
2700 struct port_info *pi = netdev_priv(netdev);
2701
2702 spin_lock(&adapter->work_lock);
2703 pi->link_fault = 1;
2704 queue_work(cxgb3_wq, &adapter->link_fault_handler_task);
2705 spin_unlock(&adapter->work_lock);
2706}
2707
2591static int t3_adapter_error(struct adapter *adapter, int reset) 2708static int t3_adapter_error(struct adapter *adapter, int reset)
2592{ 2709{
2593 int i, ret = 0; 2710 int i, ret = 0;
@@ -2704,7 +2821,6 @@ void t3_fatal_err(struct adapter *adapter)
2704 CH_ALERT(adapter, "FW status: 0x%x, 0x%x, 0x%x, 0x%x\n", 2821 CH_ALERT(adapter, "FW status: 0x%x, 0x%x, 0x%x, 0x%x\n",
2705 fw_status[0], fw_status[1], 2822 fw_status[0], fw_status[1],
2706 fw_status[2], fw_status[3]); 2823 fw_status[2], fw_status[3]);
2707
2708} 2824}
2709 2825
2710/** 2826/**
@@ -2962,6 +3078,7 @@ static int __devinit init_one(struct pci_dev *pdev,
2962 3078
2963 INIT_LIST_HEAD(&adapter->adapter_list); 3079 INIT_LIST_HEAD(&adapter->adapter_list);
2964 INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task); 3080 INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task);
3081 INIT_WORK(&adapter->link_fault_handler_task, link_fault_task);
2965 INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task); 3082 INIT_WORK(&adapter->fatal_error_handler_task, fatal_error_task);
2966 INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task); 3083 INIT_DELAYED_WORK(&adapter->adap_check_task, t3_adap_check_task);
2967 3084
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
index aa08550ee998..1b5327b5a965 100644
--- a/drivers/net/cxgb3/regs.h
+++ b/drivers/net/cxgb3/regs.h
@@ -2215,6 +2215,15 @@
2215 2215
2216#define A_XGM_RX_EXACT_MATCH_LOW_8 0x854 2216#define A_XGM_RX_EXACT_MATCH_LOW_8 0x854
2217 2217
2218#define A_XGM_INT_STATUS 0x86c
2219
2220#define S_LINKFAULTCHANGE 9
2221#define V_LINKFAULTCHANGE(x) ((x) << S_LINKFAULTCHANGE)
2222#define F_LINKFAULTCHANGE V_LINKFAULTCHANGE(1U)
2223
2224#define A_XGM_XGM_INT_ENABLE 0x874
2225#define A_XGM_XGM_INT_DISABLE 0x878
2226
2218#define A_XGM_STAT_CTRL 0x880 2227#define A_XGM_STAT_CTRL 0x880
2219 2228
2220#define S_CLRSTATS 2 2229#define S_CLRSTATS 2
@@ -2413,6 +2422,10 @@
2413#define V_XAUIPCSALIGNCHANGE(x) ((x) << S_XAUIPCSALIGNCHANGE) 2422#define V_XAUIPCSALIGNCHANGE(x) ((x) << S_XAUIPCSALIGNCHANGE)
2414#define F_XAUIPCSALIGNCHANGE V_XAUIPCSALIGNCHANGE(1U) 2423#define F_XAUIPCSALIGNCHANGE V_XAUIPCSALIGNCHANGE(1U)
2415 2424
2425#define S_XGM_INT 0
2426#define V_XGM_INT(x) ((x) << S_XGM_INT)
2427#define F_XGM_INT V_XGM_INT(1U)
2428
2416#define A_XGM_INT_CAUSE 0x8d8 2429#define A_XGM_INT_CAUSE 0x8d8
2417 2430
2418#define A_XGM_XAUI_ACT_CTRL 0x8dc 2431#define A_XGM_XAUI_ACT_CTRL 0x8dc
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index 7c6ee0c9b6fc..ff262a04ded0 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -1153,6 +1153,38 @@ int t3_cim_ctl_blk_read(struct adapter *adap, unsigned int addr,
1153 return ret; 1153 return ret;
1154} 1154}
1155 1155
1156static void t3_gate_rx_traffic(struct cmac *mac, u32 *rx_cfg,
1157 u32 *rx_hash_high, u32 *rx_hash_low)
1158{
1159 /* stop Rx unicast traffic */
1160 t3_mac_disable_exact_filters(mac);
1161
1162 /* stop broadcast, multicast, promiscuous mode traffic */
1163 *rx_cfg = t3_read_reg(mac->adapter, A_XGM_RX_CFG);
1164 t3_set_reg_field(mac->adapter, A_XGM_RX_CFG,
1165 F_ENHASHMCAST | F_DISBCAST | F_COPYALLFRAMES,
1166 F_DISBCAST);
1167
1168 *rx_hash_high = t3_read_reg(mac->adapter, A_XGM_RX_HASH_HIGH);
1169 t3_write_reg(mac->adapter, A_XGM_RX_HASH_HIGH, 0);
1170
1171 *rx_hash_low = t3_read_reg(mac->adapter, A_XGM_RX_HASH_LOW);
1172 t3_write_reg(mac->adapter, A_XGM_RX_HASH_LOW, 0);
1173
1174 /* Leave time to drain max RX fifo */
1175 msleep(1);
1176}
1177
1178static void t3_open_rx_traffic(struct cmac *mac, u32 rx_cfg,
1179 u32 rx_hash_high, u32 rx_hash_low)
1180{
1181 t3_mac_enable_exact_filters(mac);
1182 t3_set_reg_field(mac->adapter, A_XGM_RX_CFG,
1183 F_ENHASHMCAST | F_DISBCAST | F_COPYALLFRAMES,
1184 rx_cfg);
1185 t3_write_reg(mac->adapter, A_XGM_RX_HASH_HIGH, rx_hash_high);
1186 t3_write_reg(mac->adapter, A_XGM_RX_HASH_LOW, rx_hash_low);
1187}
1156 1188
1157/** 1189/**
1158 * t3_link_changed - handle interface link changes 1190 * t3_link_changed - handle interface link changes
@@ -1170,9 +1202,32 @@ void t3_link_changed(struct adapter *adapter, int port_id)
1170 struct cphy *phy = &pi->phy; 1202 struct cphy *phy = &pi->phy;
1171 struct cmac *mac = &pi->mac; 1203 struct cmac *mac = &pi->mac;
1172 struct link_config *lc = &pi->link_config; 1204 struct link_config *lc = &pi->link_config;
1205 int force_link_down = 0;
1173 1206
1174 phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); 1207 phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
1175 1208
1209 if (!lc->link_ok && link_ok) {
1210 u32 rx_cfg, rx_hash_high, rx_hash_low;
1211 u32 status;
1212
1213 t3_xgm_intr_enable(adapter, port_id);
1214 t3_gate_rx_traffic(mac, &rx_cfg, &rx_hash_high, &rx_hash_low);
1215 t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0);
1216 t3_mac_enable(mac, MAC_DIRECTION_RX);
1217
1218 status = t3_read_reg(adapter, A_XGM_INT_STATUS + mac->offset);
1219 if (status & F_LINKFAULTCHANGE) {
1220 mac->stats.link_faults++;
1221 force_link_down = 1;
1222 }
1223 t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low);
1224
1225 if (force_link_down) {
1226 t3_os_link_fault_handler(adapter, port_id);
1227 return;
1228 }
1229 }
1230
1176 if (lc->requested_fc & PAUSE_AUTONEG) 1231 if (lc->requested_fc & PAUSE_AUTONEG)
1177 fc &= lc->requested_fc; 1232 fc &= lc->requested_fc;
1178 else 1233 else
@@ -1202,6 +1257,57 @@ void t3_link_changed(struct adapter *adapter, int port_id)
1202 t3_os_link_changed(adapter, port_id, link_ok, speed, duplex, fc); 1257 t3_os_link_changed(adapter, port_id, link_ok, speed, duplex, fc);
1203} 1258}
1204 1259
1260void t3_link_fault(struct adapter *adapter, int port_id)
1261{
1262 struct port_info *pi = adap2pinfo(adapter, port_id);
1263 struct cmac *mac = &pi->mac;
1264 struct cphy *phy = &pi->phy;
1265 struct link_config *lc = &pi->link_config;
1266 int link_ok, speed, duplex, fc, link_fault;
1267 u32 rx_cfg, rx_hash_high, rx_hash_low;
1268
1269 t3_gate_rx_traffic(mac, &rx_cfg, &rx_hash_high, &rx_hash_low);
1270
1271 if (adapter->params.rev > 0 && uses_xaui(adapter))
1272 t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset, 0);
1273
1274 t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, 0);
1275 t3_mac_enable(mac, MAC_DIRECTION_RX);
1276
1277 t3_open_rx_traffic(mac, rx_cfg, rx_hash_high, rx_hash_low);
1278
1279 link_fault = t3_read_reg(adapter,
1280 A_XGM_INT_STATUS + mac->offset);
1281 link_fault &= F_LINKFAULTCHANGE;
1282
1283 phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
1284
1285 if (link_fault) {
1286 lc->link_ok = 0;
1287 lc->speed = SPEED_INVALID;
1288 lc->duplex = DUPLEX_INVALID;
1289
1290 t3_os_link_fault(adapter, port_id, 0);
1291
1292 /* Account link faults only when the phy reports a link up */
1293 if (link_ok)
1294 mac->stats.link_faults++;
1295
1296 msleep(1000);
1297 t3_os_link_fault_handler(adapter, port_id);
1298 } else {
1299 if (link_ok)
1300 t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset,
1301 F_TXACTENABLE | F_RXEN);
1302
1303 pi->link_fault = 0;
1304 lc->link_ok = (unsigned char)link_ok;
1305 lc->speed = speed < 0 ? SPEED_INVALID : speed;
1306 lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
1307 t3_os_link_fault(adapter, port_id, link_ok);
1308 }
1309}
1310
1205/** 1311/**
1206 * t3_link_start - apply link configuration to MAC/PHY 1312 * t3_link_start - apply link configuration to MAC/PHY
1207 * @phy: the PHY to setup 1313 * @phy: the PHY to setup
@@ -1360,11 +1466,11 @@ static int t3_handle_intr_status(struct adapter *adapter, unsigned int reg,
1360 V_TX1TPPARERRENB(M_TX1TPPARERRENB) | \ 1466 V_TX1TPPARERRENB(M_TX1TPPARERRENB) | \
1361 V_RXTPPARERRENB(M_RXTPPARERRENB) | \ 1467 V_RXTPPARERRENB(M_RXTPPARERRENB) | \
1362 V_MCAPARERRENB(M_MCAPARERRENB)) 1468 V_MCAPARERRENB(M_MCAPARERRENB))
1469#define XGM_EXTRA_INTR_MASK (F_LINKFAULTCHANGE)
1363#define PL_INTR_MASK (F_T3DBG | F_XGMAC0_0 | F_XGMAC0_1 | F_MC5A | F_PM1_TX | \ 1470#define PL_INTR_MASK (F_T3DBG | F_XGMAC0_0 | F_XGMAC0_1 | F_MC5A | F_PM1_TX | \
1364 F_PM1_RX | F_ULP2_TX | F_ULP2_RX | F_TP1 | F_CIM | \ 1471 F_PM1_RX | F_ULP2_TX | F_ULP2_RX | F_TP1 | F_CIM | \
1365 F_MC7_CM | F_MC7_PMTX | F_MC7_PMRX | F_SGE3 | F_PCIM0 | \ 1472 F_MC7_CM | F_MC7_PMTX | F_MC7_PMRX | F_SGE3 | F_PCIM0 | \
1366 F_MPS0 | F_CPL_SWITCH) 1473 F_MPS0 | F_CPL_SWITCH)
1367
1368/* 1474/*
1369 * Interrupt handler for the PCIX1 module. 1475 * Interrupt handler for the PCIX1 module.
1370 */ 1476 */
@@ -1722,10 +1828,20 @@ static int mac_intr_handler(struct adapter *adap, unsigned int idx)
1722 mac->stats.xaui_pcs_ctc_err++; 1828 mac->stats.xaui_pcs_ctc_err++;
1723 if (cause & F_XAUIPCSALIGNCHANGE) 1829 if (cause & F_XAUIPCSALIGNCHANGE)
1724 mac->stats.xaui_pcs_align_change++; 1830 mac->stats.xaui_pcs_align_change++;
1831 if (cause & F_XGM_INT) {
1832 t3_set_reg_field(adap,
1833 A_XGM_INT_ENABLE + mac->offset,
1834 F_XGM_INT, 0);
1835 mac->stats.link_faults++;
1836
1837 t3_os_link_fault_handler(adap, idx);
1838 }
1725 1839
1726 t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause); 1840 t3_write_reg(adap, A_XGM_INT_CAUSE + mac->offset, cause);
1841
1727 if (cause & XGM_INTR_FATAL) 1842 if (cause & XGM_INTR_FATAL)
1728 t3_fatal_err(adap); 1843 t3_fatal_err(adap);
1844
1729 return cause != 0; 1845 return cause != 0;
1730} 1846}
1731 1847
@@ -1931,6 +2047,22 @@ void t3_intr_clear(struct adapter *adapter)
1931 t3_read_reg(adapter, A_PL_INT_CAUSE0); /* flush */ 2047 t3_read_reg(adapter, A_PL_INT_CAUSE0); /* flush */
1932} 2048}
1933 2049
2050void t3_xgm_intr_enable(struct adapter *adapter, int idx)
2051{
2052 struct port_info *pi = adap2pinfo(adapter, idx);
2053
2054 t3_write_reg(adapter, A_XGM_XGM_INT_ENABLE + pi->mac.offset,
2055 XGM_EXTRA_INTR_MASK);
2056}
2057
2058void t3_xgm_intr_disable(struct adapter *adapter, int idx)
2059{
2060 struct port_info *pi = adap2pinfo(adapter, idx);
2061
2062 t3_write_reg(adapter, A_XGM_XGM_INT_DISABLE + pi->mac.offset,
2063 0x7ff);
2064}
2065
1934/** 2066/**
1935 * t3_port_intr_enable - enable port-specific interrupts 2067 * t3_port_intr_enable - enable port-specific interrupts
1936 * @adapter: associated adapter 2068 * @adapter: associated adapter
diff --git a/drivers/net/cxgb3/xgmac.c b/drivers/net/cxgb3/xgmac.c
index 4bd0901a97a6..f87f9435049f 100644
--- a/drivers/net/cxgb3/xgmac.c
+++ b/drivers/net/cxgb3/xgmac.c
@@ -218,6 +218,9 @@ static int t3b2_mac_reset(struct cmac *mac)
218 /* re-enable nic traffic */ 218 /* re-enable nic traffic */
219 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1); 219 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1);
220 220
221 /* Set: re-enable NIC traffic */
222 t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1);
223
221 return 0; 224 return 0;
222} 225}
223 226
@@ -258,7 +261,7 @@ int t3_mac_set_num_ucast(struct cmac *mac, int n)
258 return 0; 261 return 0;
259} 262}
260 263
261static void disable_exact_filters(struct cmac *mac) 264void t3_mac_disable_exact_filters(struct cmac *mac)
262{ 265{
263 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1; 266 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_LOW_1;
264 267
@@ -269,7 +272,7 @@ static void disable_exact_filters(struct cmac *mac)
269 t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */ 272 t3_read_reg(mac->adapter, A_XGM_RX_EXACT_MATCH_LOW_1); /* flush */
270} 273}
271 274
272static void enable_exact_filters(struct cmac *mac) 275void t3_mac_enable_exact_filters(struct cmac *mac)
273{ 276{
274 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1; 277 unsigned int i, reg = mac->offset + A_XGM_RX_EXACT_MATCH_HIGH_1;
275 278
@@ -356,7 +359,7 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
356 359
357 if (adap->params.rev >= T3_REV_B2 && 360 if (adap->params.rev >= T3_REV_B2 &&
358 (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) { 361 (t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
359 disable_exact_filters(mac); 362 t3_mac_disable_exact_filters(mac);
360 v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset); 363 v = t3_read_reg(adap, A_XGM_RX_CFG + mac->offset);
361 t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset, 364 t3_set_reg_field(adap, A_XGM_RX_CFG + mac->offset,
362 F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST); 365 F_ENHASHMCAST | F_COPYALLFRAMES, F_DISBCAST);
@@ -368,14 +371,14 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
368 if (t3_wait_op_done(adap, reg + mac->offset, 371 if (t3_wait_op_done(adap, reg + mac->offset,
369 F_RXFIFO_EMPTY, 1, 20, 5)) { 372 F_RXFIFO_EMPTY, 1, 20, 5)) {
370 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); 373 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
371 enable_exact_filters(mac); 374 t3_mac_enable_exact_filters(mac);
372 return -EIO; 375 return -EIO;
373 } 376 }
374 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, 377 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
375 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), 378 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),
376 V_RXMAXPKTSIZE(mtu)); 379 V_RXMAXPKTSIZE(mtu));
377 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v); 380 t3_write_reg(adap, A_XGM_RX_CFG + mac->offset, v);
378 enable_exact_filters(mac); 381 t3_mac_enable_exact_filters(mac);
379 } else 382 } else
380 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset, 383 t3_set_reg_field(adap, A_XGM_RX_MAX_PKT_SIZE + mac->offset,
381 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE), 384 V_RXMAXPKTSIZE(M_RXMAXPKTSIZE),