qlcnic: add external loopback support
authorAmit Kumar Salecha <amit.salecha@qlogic.com>
Wed, 29 Jun 2011 20:00:50 +0000 (20:00 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 1 Jul 2011 05:32:50 +0000 (22:32 -0700)
o Add external loopback test in self test:
  - Send set external loopback mode request to fw.
     To quiscent other storage functions.
  - Perform test
  - Send unset loopback mode request to fw.

o Rename ilb to lb.
o Update driver version 5.0.20.

Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/qlcnic/qlcnic.h
drivers/net/qlcnic/qlcnic_ethtool.c
drivers/net/qlcnic/qlcnic_init.c

index e5454502df6be5923d4dad5779513c80a8707f74..9899a7947718583415de652e8dd155eacc59e99e 100644 (file)
@@ -36,8 +36,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 19
-#define QLCNIC_LINUX_VERSIONID  "5.0.19"
+#define _QLCNIC_LINUX_SUBVERSION 20
+#define QLCNIC_LINUX_VERSIONID  "5.0.20"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
                 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -782,6 +782,7 @@ struct qlcnic_mac_list_s {
 #define QLCNIC_IP_DOWN         3
 
 #define QLCNIC_ILB_MODE                0x1
+#define QLCNIC_ELB_MODE                0x2
 
 #define QLCNIC_LINKEVENT       0x1
 #define QLCNIC_LB_RESPONSE     0x2
index 743035e4538de7f6eb9a41f052d7e900e852a2ce..3ea04e7da91744135988d8c65a30248755738582 100644 (file)
@@ -85,7 +85,8 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
        "Register_Test_on_offline",
        "Link_Test_on_offline",
        "Interrupt_Test_offline",
-       "Loopback_Test_offline"
+       "Internal_Loopback_offline",
+       "External_Loopback_offline"
 };
 
 #define QLCNIC_TEST_LEN        ARRAY_SIZE(qlcnic_gstrings_test)
@@ -709,7 +710,7 @@ int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
        return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
 }
 
-static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter)
+static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
        struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
@@ -735,19 +736,19 @@ static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter)
                dev_kfree_skb_any(skb);
 
                if (!adapter->diag_cnt)
-                       dev_warn(&adapter->pdev->dev, "ILB Test: %dth packet"
+                       dev_warn(&adapter->pdev->dev, "LB Test: %dth packet"
                                " not recevied\n", i + 1);
                else
                        cnt++;
        }
        if (cnt != i) {
-               dev_warn(&adapter->pdev->dev, "ILB Test failed\n");
+               dev_warn(&adapter->pdev->dev, "LB Test failed\n");
                return -1;
        }
        return 0;
 }
 
-static int qlcnic_iloopback_test(struct net_device *netdev)
+static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        int max_sds_rings = adapter->max_sds_rings;
@@ -755,7 +756,8 @@ static int qlcnic_iloopback_test(struct net_device *netdev)
        int loop = 0;
        int ret;
 
-       netdev_info(netdev, "%s:  in progress\n", __func__);
+       netdev_info(netdev, "%s loopback test in progress\n",
+                  mode == QLCNIC_ILB_MODE ? "internal" : "external");
        if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
                netdev_warn(netdev, "Loopback test not supported for non "
                                "privilege function\n");
@@ -772,7 +774,7 @@ static int qlcnic_iloopback_test(struct net_device *netdev)
 
        sds_ring = &adapter->recv_ctx->sds_rings[0];
 
-       ret = qlcnic_set_lb_mode(adapter, QLCNIC_ILB_MODE);
+       ret = qlcnic_set_lb_mode(adapter, mode);
        if (ret)
                goto free_res;
 
@@ -790,7 +792,7 @@ static int qlcnic_iloopback_test(struct net_device *netdev)
                goto free_res;
        }
 
-       ret = qlcnic_do_ilb_test(adapter);
+       ret = qlcnic_do_lb_test(adapter);
 
        qlcnic_clear_lb_mode(adapter);
 
@@ -822,10 +824,16 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
                if (data[2])
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
-               data[3] = qlcnic_iloopback_test(dev);
+               data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
                if (data[3])
                        eth_test->flags |= ETH_TEST_FL_FAILED;
 
+               if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
+                       data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
+                       if (data[4])
+                               eth_test->flags |= ETH_TEST_FL_FAILED;
+                       eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
+               }
        }
 }
 
index 9d5bee03a587b5690d5f253fb7285d66b190c8cd..6ec1baa85f6a59891f24b58bd3eb3d7baf49c161 100644 (file)
@@ -1303,7 +1303,8 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
                dev_info(&netdev->dev, "unsupported cable length %d\n",
                                cable_len);
 
-       if (!link_status && (lb_status == 1))
+       if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
+           lb_status == QLCNIC_ELB_MODE))
                adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
 
        qlcnic_advert_link_change(adapter, link_status);