be2net: Bug fix to config NIC appropriately before loopback test
authorSarveshwar Bandi <sarveshwarb@serverengines.com>
Wed, 23 Dec 2009 04:41:44 +0000 (04:41 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 24 Dec 2009 04:58:14 +0000 (20:58 -0800)
NIC controller has to be set to an appropriate mode before doing a loopback
test. Test will fail otherwise.

Signed-off-by: Sarveshwar Bandi <sarveshwarb@serverengines.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/benet/be_cmds.c
drivers/net/benet/be_cmds.h
drivers/net/benet/be_ethtool.c

index a27fdb35eebf1357546d2d5d5ee230dc3a28694d..102ade13416526066e3639519beaf4f497bc8830 100644 (file)
@@ -1479,6 +1479,41 @@ err:
        return status;
 }
 
+int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
+                       u8 loopback_type, u8 enable)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_set_lmode *req;
+       int status;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = embedded_payload(wrb);
+
+       be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+                               OPCODE_LOWLEVEL_SET_LOOPBACK_MODE);
+
+       be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_LOWLEVEL,
+                       OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
+                       sizeof(*req));
+
+       req->src_port = port_num;
+       req->dest_port = port_num;
+       req->loopback_type = loopback_type;
+       req->loopback_state = enable;
+
+       status = be_mcc_notify_wait(adapter);
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
 int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
                u32 loopback_type, u32 pkt_size, u32 num_pkts, u64 pattern)
 {
index 92b87ef156ed912f8ff998cb3c7db7135aa8b6af..c002b8391b4dc18c24e0a6e4b48a8e39ff9549b1 100644 (file)
@@ -155,6 +155,7 @@ struct be_mcc_mailbox {
 
 #define OPCODE_LOWLEVEL_HOST_DDR_DMA                    17
 #define OPCODE_LOWLEVEL_LOOPBACK_TEST                   18
+#define OPCODE_LOWLEVEL_SET_LOOPBACK_MODE              19
 
 struct be_cmd_req_hdr {
        u8 opcode;              /* dword 0 */
@@ -821,6 +822,19 @@ struct be_cmd_resp_loopback_test {
        u32    ticks_compl;
 };
 
+struct be_cmd_req_set_lmode {
+       struct be_cmd_req_hdr hdr;
+       u8 src_port;
+       u8 dest_port;
+       u8 loopback_type;
+       u8 loopback_state;
+};
+
+struct be_cmd_resp_set_lmode {
+       struct be_cmd_resp_hdr resp_hdr;
+       u8 rsvd0[4];
+};
+
 /********************** DDR DMA test *********************/
 struct be_cmd_req_ddrdma_test {
        struct be_cmd_req_hdr hdr;
@@ -912,3 +926,5 @@ extern int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num,
                                u32 num_pkts, u64 pattern);
 extern int be_cmd_ddr_dma_test(struct be_adapter *adapter, u64 pattern,
                        u32 byte_cnt, struct be_dma_mem *cmd);
+extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
+                               u8 loopback_type, u8 enable);
index 298b92cbd68948e3d54893a7e8f11885bda7c01c..da66d15e22231f3205d25b4795d02a47f0472efb 100644 (file)
@@ -118,6 +118,7 @@ static const char et_self_tests[][ETH_GSTRING_LEN] = {
 #define BE_MAC_LOOPBACK 0x0
 #define BE_PHY_LOOPBACK 0x1
 #define BE_ONE_PORT_EXT_LOOPBACK 0x2
+#define BE_NO_LOOPBACK 0xff
 
 static void
 be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
@@ -489,6 +490,19 @@ err:
        return ret;
 }
 
+static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type,
+                               u64 *status)
+{
+       be_cmd_set_loopback(adapter, adapter->port_num,
+                               loopback_type, 1);
+       *status = be_cmd_loopback_test(adapter, adapter->port_num,
+                               loopback_type, 1500,
+                               2, 0xabc);
+       be_cmd_set_loopback(adapter, adapter->port_num,
+                               BE_NO_LOOPBACK, 1);
+       return *status;
+}
+
 static void
 be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
 {
@@ -497,23 +511,18 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
        memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM);
 
        if (test->flags & ETH_TEST_FL_OFFLINE) {
-               data[0] = be_cmd_loopback_test(adapter, adapter->port_num,
-                                               BE_MAC_LOOPBACK, 1500,
-                                               2, 0xabc);
-               if (data[0] != 0)
+               if (be_loopback_test(adapter, BE_MAC_LOOPBACK,
+                                               &data[0]) != 0) {
                        test->flags |= ETH_TEST_FL_FAILED;
-
-               data[1] = be_cmd_loopback_test(adapter, adapter->port_num,
-                                               BE_PHY_LOOPBACK, 1500,
-                                               2, 0xabc);
-               if (data[1] != 0)
+               }
+               if (be_loopback_test(adapter, BE_PHY_LOOPBACK,
+                                               &data[1]) != 0) {
                        test->flags |= ETH_TEST_FL_FAILED;
-
-               data[2] = be_cmd_loopback_test(adapter, adapter->port_num,
-                                               BE_ONE_PORT_EXT_LOOPBACK,
-                                               1500, 2, 0xabc);
-               if (data[2] != 0)
+               }
+               if (be_loopback_test(adapter, BE_ONE_PORT_EXT_LOOPBACK,
+                                               &data[2]) != 0) {
                        test->flags |= ETH_TEST_FL_FAILED;
+               }
 
                data[3] = be_test_ddr_dma(adapter);
                if (data[3] != 0)