Commit 8970b2e4 authored by Merav Sicron's avatar Merav Sicron Committed by David S. Miller

bnx2x: Add support for external LB

This change enables to do self-test with external loopback via ethtool.
Signed-off-by: default avatarMerav Sicron <meravs@broadcom.com>
Signed-off-by: default avatarEilon Greenstein <eilong@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b31525d1
...@@ -1817,6 +1817,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, ...@@ -1817,6 +1817,7 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define LOAD_NORMAL 0 #define LOAD_NORMAL 0
#define LOAD_OPEN 1 #define LOAD_OPEN 1
#define LOAD_DIAG 2 #define LOAD_DIAG 2
#define LOAD_LOOPBACK_EXT 3
#define UNLOAD_NORMAL 0 #define UNLOAD_NORMAL 0
#define UNLOAD_CLOSE 1 #define UNLOAD_CLOSE 1
#define UNLOAD_RECOVERY 2 #define UNLOAD_RECOVERY 2
...@@ -1900,12 +1901,14 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms, ...@@ -1900,12 +1901,14 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
#define PCICFG_LINK_SPEED_SHIFT 16 #define PCICFG_LINK_SPEED_SHIFT 16
#define BNX2X_NUM_TESTS 7 #define BNX2X_NUM_TESTS 8
#define BNX2X_PHY_LOOPBACK 0 #define BNX2X_PHY_LOOPBACK 0
#define BNX2X_MAC_LOOPBACK 1 #define BNX2X_MAC_LOOPBACK 1
#define BNX2X_EXT_LOOPBACK 2
#define BNX2X_PHY_LOOPBACK_FAILED 1 #define BNX2X_PHY_LOOPBACK_FAILED 1
#define BNX2X_MAC_LOOPBACK_FAILED 2 #define BNX2X_MAC_LOOPBACK_FAILED 2
#define BNX2X_EXT_LOOPBACK_FAILED 3
#define BNX2X_LOOPBACK_FAILED (BNX2X_MAC_LOOPBACK_FAILED | \ #define BNX2X_LOOPBACK_FAILED (BNX2X_MAC_LOOPBACK_FAILED | \
BNX2X_PHY_LOOPBACK_FAILED) BNX2X_PHY_LOOPBACK_FAILED)
......
...@@ -2176,6 +2176,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) ...@@ -2176,6 +2176,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
break; break;
case LOAD_DIAG: case LOAD_DIAG:
case LOAD_LOOPBACK_EXT:
bp->state = BNX2X_STATE_DIAG; bp->state = BNX2X_STATE_DIAG;
break; break;
...@@ -2215,7 +2216,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) ...@@ -2215,7 +2216,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
return -EBUSY; return -EBUSY;
} }
bnx2x_dcbx_init(bp); if (bp->state != BNX2X_STATE_DIAG)
bnx2x_dcbx_init(bp);
return 0; return 0;
#ifndef BNX2X_STOP_ON_ERROR #ifndef BNX2X_STOP_ON_ERROR
......
...@@ -1538,7 +1538,8 @@ static const struct { ...@@ -1538,7 +1538,8 @@ static const struct {
} bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = { } bnx2x_tests_str_arr[BNX2X_NUM_TESTS] = {
{ "register_test (offline)" }, { "register_test (offline)" },
{ "memory_test (offline)" }, { "memory_test (offline)" },
{ "loopback_test (offline)" }, { "int_loopback_test (offline)" },
{ "ext_loopback_test (offline)" },
{ "nvram_test (online)" }, { "nvram_test (online)" },
{ "interrupt_test (online)" }, { "interrupt_test (online)" },
{ "link_test (online)" }, { "link_test (online)" },
...@@ -1943,6 +1944,14 @@ static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes) ...@@ -1943,6 +1944,14 @@ static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up, u8 is_serdes)
if (cnt <= 0 && bnx2x_link_test(bp, is_serdes)) if (cnt <= 0 && bnx2x_link_test(bp, is_serdes))
DP(BNX2X_MSG_ETHTOOL, "Timeout waiting for link up\n"); 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");
} }
} }
...@@ -1968,13 +1977,16 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) ...@@ -1968,13 +1977,16 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
u16 len; u16 len;
int rc = -ENODEV; int rc = -ENODEV;
u8 *data; 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 */ /* check the loopback mode */
switch (loopback_mode) { switch (loopback_mode) {
case BNX2X_PHY_LOOPBACK: 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; return -EINVAL;
}
break; break;
case BNX2X_MAC_LOOPBACK: case BNX2X_MAC_LOOPBACK:
if (CHIP_IS_E3(bp)) { if (CHIP_IS_E3(bp)) {
...@@ -1991,6 +2003,13 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode) ...@@ -1991,6 +2003,13 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode)
bnx2x_phy_init(&bp->link_params, &bp->link_vars); bnx2x_phy_init(&bp->link_params, &bp->link_vars);
break; 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: default:
DP(BNX2X_MSG_ETHTOOL, "Command parameters not supported\n"); DP(BNX2X_MSG_ETHTOOL, "Command parameters not supported\n");
return -EINVAL; return -EINVAL;
...@@ -2162,6 +2181,38 @@ static int bnx2x_test_loopback(struct bnx2x *bp) ...@@ -2162,6 +2181,38 @@ static int bnx2x_test_loopback(struct bnx2x *bp)
return rc; 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 #define CRC32_RESIDUAL 0xdebb20e3
static int bnx2x_test_nvram(struct bnx2x *bp) static int bnx2x_test_nvram(struct bnx2x *bp)
...@@ -2263,6 +2314,10 @@ static void bnx2x_self_test(struct net_device *dev, ...@@ -2263,6 +2314,10 @@ static void bnx2x_self_test(struct net_device *dev,
etest->flags |= ETH_TEST_FL_FAILED; etest->flags |= ETH_TEST_FL_FAILED;
return; 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); memset(buf, 0, sizeof(u64) * BNX2X_NUM_TESTS);
...@@ -2300,10 +2355,17 @@ static void bnx2x_self_test(struct net_device *dev, ...@@ -2300,10 +2355,17 @@ static void bnx2x_self_test(struct net_device *dev,
etest->flags |= ETH_TEST_FL_FAILED; etest->flags |= ETH_TEST_FL_FAILED;
} }
buf[2] = bnx2x_test_loopback(bp); buf[2] = bnx2x_test_loopback(bp); /* internal LB */
if (buf[2] != 0) if (buf[2] != 0)
etest->flags |= ETH_TEST_FL_FAILED; 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); bnx2x_nic_unload(bp, UNLOAD_NORMAL);
/* restore input for TX port IF */ /* restore input for TX port IF */
...@@ -2314,16 +2376,16 @@ static void bnx2x_self_test(struct net_device *dev, ...@@ -2314,16 +2376,16 @@ static void bnx2x_self_test(struct net_device *dev,
bnx2x_wait_for_link(bp, link_up, is_serdes); bnx2x_wait_for_link(bp, link_up, is_serdes);
} }
if (bnx2x_test_nvram(bp) != 0) { if (bnx2x_test_nvram(bp) != 0) {
buf[3] = 1; buf[4] = 1;
etest->flags |= ETH_TEST_FL_FAILED; etest->flags |= ETH_TEST_FL_FAILED;
} }
if (bnx2x_test_intr(bp) != 0) { if (bnx2x_test_intr(bp) != 0) {
buf[4] = 1; buf[5] = 1;
etest->flags |= ETH_TEST_FL_FAILED; etest->flags |= ETH_TEST_FL_FAILED;
} }
if (bnx2x_link_test(bp, is_serdes) != 0) { if (bnx2x_link_test(bp, is_serdes) != 0) {
buf[5] = 1; buf[6] = 1;
etest->flags |= ETH_TEST_FL_FAILED; etest->flags |= ETH_TEST_FL_FAILED;
} }
......
...@@ -2124,6 +2124,11 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) ...@@ -2124,6 +2124,11 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
} }
} }
if (load_mode == LOAD_LOOPBACK_EXT) {
struct link_params *lp = &bp->link_params;
lp->loopback_mode = LOOPBACK_EXT;
}
rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars); rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
bnx2x_release_phy_lock(bp); bnx2x_release_phy_lock(bp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment