} bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = {
        { "register_test (offline)" },
        { "memory_test (offline)" },
-       { "loopback_test (offline)" },
+       { "int_loopback_test (offline)" },
+       { "ext_loopback_test (offline)" },
        { "nvram_test (online)" },
        { "interrupt_test (online)" },
        { "link_test (online)" },
 
                if (cnt <= 0 && bnx2x_link_test(bp, is_serdes))
                        DP(BNX2X_MSG_ETHTOOL, "Timeout waiting for link up\n");
+
+               cnt = 1400;
+               while (!bp->link_vars.link_up && cnt--)
+                       msleep(20);
+
+               if (cnt <= 0 && !bp->link_vars.link_up)
+                       DP(BNX2X_MSG_ETHTOOL,
+                          "Timeout waiting for link init\n");
        }
 }
 
        u16 len;
        int rc = -ENODEV;
        u8 *data;
-       struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txdata->txq_index);
+       struct netdev_queue *txq = netdev_get_tx_queue(bp->dev,
+                                                      txdata->txq_index);
 
        /* check the loopback mode */
        switch (loopback_mode) {
        case BNX2X_PHY_LOOPBACK:
-               if (bp->link_params.loopback_mode != LOOPBACK_XGXS)
+               if (bp->link_params.loopback_mode != LOOPBACK_XGXS) {
+                       DP(BNX2X_MSG_ETHTOOL, "PHY loopback not supported\n");
                        return -EINVAL;
+               }
                break;
        case BNX2X_MAC_LOOPBACK:
                if (CHIP_IS_E3(bp)) {
 
                bnx2x_phy_init(&bp->link_params, &bp->link_vars);
                break;
+       case BNX2X_EXT_LOOPBACK:
+               if (bp->link_params.loopback_mode != LOOPBACK_EXT) {
+                       DP(BNX2X_MSG_ETHTOOL,
+                          "Can't configure external loopback\n");
+                       return -EINVAL;
+               }
+               break;
        default:
                DP(BNX2X_MSG_ETHTOOL, "Command parameters not supported\n");
                return -EINVAL;
        return rc;
 }
 
+static int bnx2x_test_ext_loopback(struct bnx2x *bp)
+{
+       int rc;
+       u8 is_serdes =
+               (bp->link_vars.link_status & LINK_STATUS_SERDES_LINK) > 0;
+
+       if (BP_NOMCP(bp))
+               return -ENODEV;
+
+       if (!netif_running(bp->dev))
+               return BNX2X_EXT_LOOPBACK_FAILED;
+
+       bnx2x_nic_unload(bp, UNLOAD_NORMAL);
+       rc = bnx2x_nic_load(bp, LOAD_LOOPBACK_EXT);
+       if (rc) {
+               DP(BNX2X_MSG_ETHTOOL,
+                  "Can't perform self-test, nic_load (for external lb) failed\n");
+               return -ENODEV;
+       }
+       bnx2x_wait_for_link(bp, 1, is_serdes);
+
+       bnx2x_netif_stop(bp, 1);
+
+       rc = bnx2x_run_loopback(bp, BNX2X_EXT_LOOPBACK);
+       if (rc)
+               DP(BNX2X_MSG_ETHTOOL, "EXT loopback failed  (res %d)\n", rc);
+
+       bnx2x_netif_start(bp);
+
+       return rc;
+}
+
 #define CRC32_RESIDUAL                 0xdebb20e3
 
 static int bnx2x_test_nvram(struct bnx2x *bp)
                etest->flags |= ETH_TEST_FL_FAILED;
                return;
        }
+       DP(BNX2X_MSG_ETHTOOL,
+          "Self-test command parameters: offline = %d, external_lb = %d\n",
+          (etest->flags & ETH_TEST_FL_OFFLINE),
+          (etest->flags & ETH_TEST_FL_EXTERNAL_LB)>>2);
 
        memset(buf, 0, sizeof(u64) * BNX2X_NUM_TESTS);
 
                        etest->flags |= ETH_TEST_FL_FAILED;
                }
 
-               buf[2] = bnx2x_test_loopback(bp);
+               buf[2] = bnx2x_test_loopback(bp); /* internal LB */
                if (buf[2] != 0)
                        etest->flags |= ETH_TEST_FL_FAILED;
 
+               if (etest->flags & ETH_TEST_FL_EXTERNAL_LB) {
+                       buf[3] = bnx2x_test_ext_loopback(bp); /* external LB */
+                       if (buf[3] != 0)
+                               etest->flags |= ETH_TEST_FL_FAILED;
+                       etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
+               }
+
                bnx2x_nic_unload(bp, UNLOAD_NORMAL);
 
                /* restore input for TX port IF */
                bnx2x_wait_for_link(bp, link_up, is_serdes);
        }
        if (bnx2x_test_nvram(bp) != 0) {
-               buf[3] = 1;
+               buf[4] = 1;
                etest->flags |= ETH_TEST_FL_FAILED;
        }
        if (bnx2x_test_intr(bp) != 0) {
-               buf[4] = 1;
+               buf[5] = 1;
                etest->flags |= ETH_TEST_FL_FAILED;
        }
 
        if (bnx2x_link_test(bp, is_serdes) != 0) {
-               buf[5] = 1;
+               buf[6] = 1;
                etest->flags |= ETH_TEST_FL_FAILED;
        }