NetXen: Fix link status messages
authorMithlesh Thukral <mithlesh@netxen.com>
Mon, 11 Jun 2007 10:30:58 +0000 (03:30 -0700)
committerJeff Garzik <jeff@garzik.org>
Tue, 12 Jun 2007 22:58:58 +0000 (18:58 -0400)
NetXen: Fix incorrect link status even with switch turned OFF.
NetXen driver failed to accurately indicate when a link is up or down.
This was encountered during failover testing, when the first port
indicated that the link was up even when the 10G switch it was assigned
to in the Bladecenter was turned off completely.

Signed-off by: Wen Xiong <wenxiong@us.ibm.com>
Signed-off by: Mithlesh Thukral <mithlesh@netxen.com>

Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_init.c
drivers/net/netxen/netxen_nic_isr.c

index 272f8c3c954658e2c457dc09f1327dd228950868..91f25e0a638ea64c21fd42910e4c0a2880abf649 100644 (file)
@@ -1049,6 +1049,7 @@ int netxen_rom_se(struct netxen_adapter *adapter, int addr);
 int netxen_do_rom_se(struct netxen_adapter *adapter, int addr);
 
 /* Functions from netxen_nic_isr.c */
+int netxen_nic_link_ok(struct netxen_adapter *adapter);
 void netxen_nic_isr_other(struct netxen_adapter *adapter);
 void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 link);
 void netxen_handle_port_int(struct netxen_adapter *adapter, u32 enable);
index 8e7c4a5bc26a65fa056fe8bc26ca0a267be6bcca..bb23f4c360db39368db8681d8bb74289a5d760a7 100644 (file)
@@ -1037,18 +1037,23 @@ void netxen_watchdog_task(struct work_struct *work)
        if ((adapter->portnum  == 0) && netxen_nic_check_temp(adapter))
                return;
 
+       if (adapter->handle_phy_intr)
+               adapter->handle_phy_intr(adapter);
+
        netdev = adapter->netdev;
-       if ((netif_running(netdev)) && !netif_carrier_ok(netdev)) {
-               printk(KERN_INFO "%s port %d, %s carrier is now ok\n",
-                      netxen_nic_driver_name, adapter->portnum, netdev->name);
+       if ((netif_running(netdev)) && !netif_carrier_ok(netdev) &&
+                       netxen_nic_link_ok(adapter) ) {
+               printk(KERN_INFO "%s %s (port %d), Link is up\n",
+                              netxen_nic_driver_name, netdev->name, adapter->portnum);
                netif_carrier_on(netdev);
-       }
-
-       if (netif_queue_stopped(netdev))
                netif_wake_queue(netdev);
+       } else if(!(netif_running(netdev)) && netif_carrier_ok(netdev)) {
+               printk(KERN_ERR "%s %s Link is Down\n",
+                               netxen_nic_driver_name, netdev->name);
+               netif_carrier_off(netdev);
+               netif_stop_queue(netdev);
+       }
 
-       if (adapter->handle_phy_intr)
-               adapter->handle_phy_intr(adapter);
        mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
 }
 
index b213b062eb567fe777651c1c196ff5d716712a38..b2de6b6c2a7f1f2dc32a0414b823a272c10a1473 100644 (file)
@@ -169,6 +169,24 @@ void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter)
        netxen_nic_isr_other(adapter);
 }
 
+int netxen_nic_link_ok(struct netxen_adapter *adapter)
+{
+       switch (adapter->ahw.board_type) {
+       case NETXEN_NIC_GBE:
+               return ((adapter->ahw.qg_linksup) & 1);
+
+       case NETXEN_NIC_XGBE:
+               return ((adapter->ahw.xg_linkup) & 1);
+
+       default:
+               printk(KERN_ERR"%s: Function: %s, Unknown board type\n",
+                       netxen_nic_driver_name, __FUNCTION__);
+               break;
+       }
+
+       return 0;
+}
+
 void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
@@ -183,6 +201,10 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
                printk(KERN_INFO "%s: %s NIC Link is down\n",
                       netxen_nic_driver_name, netdev->name);
                adapter->ahw.xg_linkup = 0;
+               if (netif_running(netdev)) {
+                       netif_carrier_off(netdev);
+                       netif_stop_queue(netdev);
+               }
                /* read twice to clear sticky bits */
                /* WINDOW = 0 */
                netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1);
@@ -196,5 +218,7 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
                printk(KERN_INFO "%s: %s NIC Link is up\n",
                       netxen_nic_driver_name, netdev->name);
                adapter->ahw.xg_linkup = 1;
+               netif_carrier_on(netdev);
+               netif_wake_queue(netdev);
        }
 }