aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb3/cxgb3_main.c
diff options
context:
space:
mode:
authorDivy Le Ray <divy@chelsio.com>2009-03-12 17:14:19 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-13 14:30:47 -0400
commitbf792094ef830117312b3990b63474320ec864c0 (patch)
treedb47894a787ec8eee78b34c500661fd17231229f /drivers/net/cxgb3/cxgb3_main.c
parentcd40658a616050df0a50d0a3ded06e3ebcc0a04a (diff)
cxgb3: detect mac link faults.
The driver currently ignores the local or remote link faults raised at the mac layer. This patch fixes it. Our mac however only advertizes link events, so wait for the phy to stabilize the link, then enable mac link events interrupts. 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.c123
1 files changed, 120 insertions, 3 deletions
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