Commit 4dc13b96 authored by Fuyun Liang's avatar Fuyun Liang Committed by David S. Miller

net: hns3: Add serdes parallel inner loopback support

This patch adds serdes parallel inner loopback support for self test.
Signed-off-by: default avatarFuyun Liang <liangfuyun1@huawei.com>
Signed-off-by: default avatarPeng Li <lipeng321@huawei.com>
Signed-off-by: default avatarSalil Mehta <salil.mehta@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eb66d503
...@@ -85,7 +85,8 @@ struct hnae3_queue { ...@@ -85,7 +85,8 @@ struct hnae3_queue {
/*hnae3 loop mode*/ /*hnae3 loop mode*/
enum hnae3_loop { enum hnae3_loop {
HNAE3_LOOP_APP, HNAE3_LOOP_APP,
HNAE3_LOOP_SERDES, HNAE3_LOOP_SERIAL_SERDES,
HNAE3_LOOP_PARALLEL_SERDES,
HNAE3_LOOP_PHY, HNAE3_LOOP_PHY,
HNAE3_LOOP_NONE, HNAE3_LOOP_NONE,
}; };
...@@ -480,8 +481,9 @@ struct hnae3_unic_private_info { ...@@ -480,8 +481,9 @@ struct hnae3_unic_private_info {
#define HNAE3_SUPPORT_APP_LOOPBACK BIT(0) #define HNAE3_SUPPORT_APP_LOOPBACK BIT(0)
#define HNAE3_SUPPORT_PHY_LOOPBACK BIT(1) #define HNAE3_SUPPORT_PHY_LOOPBACK BIT(1)
#define HNAE3_SUPPORT_SERDES_LOOPBACK BIT(2) #define HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK BIT(2)
#define HNAE3_SUPPORT_VF BIT(3) #define HNAE3_SUPPORT_VF BIT(3)
#define HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK BIT(4)
struct hnae3_handle { struct hnae3_handle {
struct hnae3_client *client; struct hnae3_client *client;
......
...@@ -53,7 +53,7 @@ static const struct hns3_stats hns3_rxq_stats[] = { ...@@ -53,7 +53,7 @@ static const struct hns3_stats hns3_rxq_stats[] = {
#define HNS3_TQP_STATS_COUNT (HNS3_TXQ_STATS_COUNT + HNS3_RXQ_STATS_COUNT) #define HNS3_TQP_STATS_COUNT (HNS3_TXQ_STATS_COUNT + HNS3_RXQ_STATS_COUNT)
#define HNS3_SELF_TEST_TYPE_NUM 2 #define HNS3_SELF_TEST_TPYE_NUM 3
#define HNS3_NIC_LB_TEST_PKT_NUM 1 #define HNS3_NIC_LB_TEST_PKT_NUM 1
#define HNS3_NIC_LB_TEST_RING_ID 0 #define HNS3_NIC_LB_TEST_RING_ID 0
#define HNS3_NIC_LB_TEST_PACKET_SIZE 128 #define HNS3_NIC_LB_TEST_PACKET_SIZE 128
...@@ -78,7 +78,8 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en) ...@@ -78,7 +78,8 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en)
return -EOPNOTSUPP; return -EOPNOTSUPP;
switch (loop) { switch (loop) {
case HNAE3_LOOP_SERDES: case HNAE3_LOOP_SERIAL_SERDES:
case HNAE3_LOOP_PARALLEL_SERDES:
case HNAE3_LOOP_APP: case HNAE3_LOOP_APP:
ret = h->ae_algo->ops->set_loopback(h, loop, en); ret = h->ae_algo->ops->set_loopback(h, loop, en);
break; break;
...@@ -290,9 +291,14 @@ static void hns3_self_test(struct net_device *ndev, ...@@ -290,9 +291,14 @@ static void hns3_self_test(struct net_device *ndev,
st_param[HNAE3_LOOP_APP][1] = st_param[HNAE3_LOOP_APP][1] =
h->flags & HNAE3_SUPPORT_APP_LOOPBACK; h->flags & HNAE3_SUPPORT_APP_LOOPBACK;
st_param[HNAE3_LOOP_SERDES][0] = HNAE3_LOOP_SERDES; st_param[HNAE3_LOOP_SERIAL_SERDES][0] = HNAE3_LOOP_SERIAL_SERDES;
st_param[HNAE3_LOOP_SERDES][1] = st_param[HNAE3_LOOP_SERIAL_SERDES][1] =
h->flags & HNAE3_SUPPORT_SERDES_LOOPBACK; h->flags & HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK;
st_param[HNAE3_LOOP_PARALLEL_SERDES][0] =
HNAE3_LOOP_PARALLEL_SERDES;
st_param[HNAE3_LOOP_PARALLEL_SERDES][1] =
h->flags & HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK;
if (if_running) if (if_running)
ndev->netdev_ops->ndo_stop(ndev); ndev->netdev_ops->ndo_stop(ndev);
......
...@@ -778,6 +778,7 @@ struct hclge_reset_cmd { ...@@ -778,6 +778,7 @@ struct hclge_reset_cmd {
}; };
#define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0) #define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0)
#define HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B BIT(2)
#define HCLGE_CMD_SERDES_DONE_B BIT(0) #define HCLGE_CMD_SERDES_DONE_B BIT(0)
#define HCLGE_CMD_SERDES_SUCCESS_B BIT(1) #define HCLGE_CMD_SERDES_SUCCESS_B BIT(1)
struct hclge_serdes_lb_cmd { struct hclge_serdes_lb_cmd {
......
...@@ -50,7 +50,8 @@ MODULE_DEVICE_TABLE(pci, ae_algo_pci_tbl); ...@@ -50,7 +50,8 @@ MODULE_DEVICE_TABLE(pci, ae_algo_pci_tbl);
static const char hns3_nic_test_strs[][ETH_GSTRING_LEN] = { static const char hns3_nic_test_strs[][ETH_GSTRING_LEN] = {
"App Loopback test", "App Loopback test",
"Serdes Loopback test", "Serdes serial Loopback test",
"Serdes parallel Loopback test",
"Phy Loopback test" "Phy Loopback test"
}; };
...@@ -475,7 +476,10 @@ static void hclge_update_stats(struct hnae3_handle *handle, ...@@ -475,7 +476,10 @@ static void hclge_update_stats(struct hnae3_handle *handle,
static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset) static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset)
{ {
#define HCLGE_LOOPBACK_TEST_FLAGS 0x7 #define HCLGE_LOOPBACK_TEST_FLAGS (HNAE3_SUPPORT_APP_LOOPBACK |\
HNAE3_SUPPORT_PHY_LOOPBACK |\
HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK |\
HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK)
struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_vport *vport = hclge_get_vport(handle);
struct hclge_dev *hdev = vport->back; struct hclge_dev *hdev = vport->back;
...@@ -489,15 +493,17 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset) ...@@ -489,15 +493,17 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset)
if (stringset == ETH_SS_TEST) { if (stringset == ETH_SS_TEST) {
/* clear loopback bit flags at first */ /* clear loopback bit flags at first */
handle->flags = (handle->flags & (~HCLGE_LOOPBACK_TEST_FLAGS)); handle->flags = (handle->flags & (~HCLGE_LOOPBACK_TEST_FLAGS));
if (hdev->hw.mac.speed == HCLGE_MAC_SPEED_10M || if (hdev->pdev->revision >= HNAE3_REVISION_ID_21 ||
hdev->hw.mac.speed == HCLGE_MAC_SPEED_10M ||
hdev->hw.mac.speed == HCLGE_MAC_SPEED_100M || hdev->hw.mac.speed == HCLGE_MAC_SPEED_100M ||
hdev->hw.mac.speed == HCLGE_MAC_SPEED_1G) { hdev->hw.mac.speed == HCLGE_MAC_SPEED_1G) {
count += 1; count += 1;
handle->flags |= HNAE3_SUPPORT_APP_LOOPBACK; handle->flags |= HNAE3_SUPPORT_APP_LOOPBACK;
} }
count++; count += 2;
handle->flags |= HNAE3_SUPPORT_SERDES_LOOPBACK; handle->flags |= HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK;
handle->flags |= HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK;
} else if (stringset == ETH_SS_STATS) { } else if (stringset == ETH_SS_STATS) {
count = ARRAY_SIZE(g_mac_stats_string) + count = ARRAY_SIZE(g_mac_stats_string) +
hclge_tqps_get_sset_count(handle, stringset); hclge_tqps_get_sset_count(handle, stringset);
...@@ -527,9 +533,15 @@ static void hclge_get_strings(struct hnae3_handle *handle, ...@@ -527,9 +533,15 @@ static void hclge_get_strings(struct hnae3_handle *handle,
ETH_GSTRING_LEN); ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
} }
if (handle->flags & HNAE3_SUPPORT_SERDES_LOOPBACK) { if (handle->flags & HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK) {
memcpy(p, memcpy(p,
hns3_nic_test_strs[HNAE3_LOOP_SERDES], hns3_nic_test_strs[HNAE3_LOOP_SERIAL_SERDES],
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
if (handle->flags & HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK) {
memcpy(p,
hns3_nic_test_strs[HNAE3_LOOP_PARALLEL_SERDES],
ETH_GSTRING_LEN); ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
} }
...@@ -3381,22 +3393,37 @@ static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en) ...@@ -3381,22 +3393,37 @@ static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en)
return ret; return ret;
} }
static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en) static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en,
enum hnae3_loop loop_mode)
{ {
#define HCLGE_SERDES_RETRY_MS 10 #define HCLGE_SERDES_RETRY_MS 10
#define HCLGE_SERDES_RETRY_NUM 100 #define HCLGE_SERDES_RETRY_NUM 100
struct hclge_serdes_lb_cmd *req; struct hclge_serdes_lb_cmd *req;
struct hclge_desc desc; struct hclge_desc desc;
int ret, i = 0; int ret, i = 0;
u8 loop_mode_b;
req = (struct hclge_serdes_lb_cmd *)desc.data; req = (struct hclge_serdes_lb_cmd *)desc.data;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, false); hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, false);
switch (loop_mode) {
case HNAE3_LOOP_SERIAL_SERDES:
loop_mode_b = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
break;
case HNAE3_LOOP_PARALLEL_SERDES:
loop_mode_b = HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B;
break;
default:
dev_err(&hdev->pdev->dev,
"unsupported serdes loopback mode %d\n", loop_mode);
return -ENOTSUPP;
}
if (en) { if (en) {
req->enable = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; req->enable = loop_mode_b;
req->mask = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; req->mask = loop_mode_b;
} else { } else {
req->mask = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; req->mask = loop_mode_b;
} }
ret = hclge_cmd_send(&hdev->hw, &desc, 1); ret = hclge_cmd_send(&hdev->hw, &desc, 1);
...@@ -3462,8 +3489,9 @@ static int hclge_set_loopback(struct hnae3_handle *handle, ...@@ -3462,8 +3489,9 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
case HNAE3_LOOP_APP: case HNAE3_LOOP_APP:
ret = hclge_set_app_loopback(hdev, en); ret = hclge_set_app_loopback(hdev, en);
break; break;
case HNAE3_LOOP_SERDES: case HNAE3_LOOP_SERIAL_SERDES:
ret = hclge_set_serdes_loopback(hdev, en); case HNAE3_LOOP_PARALLEL_SERDES:
ret = hclge_set_serdes_loopback(hdev, en, loop_mode);
break; break;
default: default:
ret = -ENOTSUPP; ret = -ENOTSUPP;
......
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