forked from Minki/linux
net: hns3: Add support for serdes loopback selftest
This patch adds support for serdes loopback selftest in hns3 driver. Signed-off-by: Yunsheng Lin <linyunsheng@huawei.com> Signed-off-by: Peng Li <lipeng321@huawei.com> Signed-off-by: Salil Mehta <salil.mehta@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1bbf3aed25
commit
5fd50ac38f
@ -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_SELF_TEST_TPYE_NUM 1
|
||||
#define HNS3_SELF_TEST_TYPE_NUM 2
|
||||
#define HNS3_NIC_LB_TEST_PKT_NUM 1
|
||||
#define HNS3_NIC_LB_TEST_RING_ID 0
|
||||
#define HNS3_NIC_LB_TEST_PACKET_SIZE 128
|
||||
@ -78,6 +78,7 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (loop) {
|
||||
case HNAE3_MAC_INTER_LOOP_SERDES:
|
||||
case HNAE3_MAC_INTER_LOOP_MAC:
|
||||
ret = h->ae_algo->ops->set_loopback(h, loop, en);
|
||||
break;
|
||||
@ -287,7 +288,7 @@ static void hns3_self_test(struct net_device *ndev,
|
||||
{
|
||||
struct hns3_nic_priv *priv = netdev_priv(ndev);
|
||||
struct hnae3_handle *h = priv->ae_handle;
|
||||
int st_param[HNS3_SELF_TEST_TPYE_NUM][2];
|
||||
int st_param[HNS3_SELF_TEST_TYPE_NUM][2];
|
||||
bool if_running = netif_running(ndev);
|
||||
#if IS_ENABLED(CONFIG_VLAN_8021Q)
|
||||
bool dis_vlan_filter;
|
||||
@ -303,6 +304,10 @@ static void hns3_self_test(struct net_device *ndev,
|
||||
st_param[HNAE3_MAC_INTER_LOOP_MAC][1] =
|
||||
h->flags & HNAE3_SUPPORT_MAC_LOOPBACK;
|
||||
|
||||
st_param[HNAE3_MAC_INTER_LOOP_SERDES][0] = HNAE3_MAC_INTER_LOOP_SERDES;
|
||||
st_param[HNAE3_MAC_INTER_LOOP_SERDES][1] =
|
||||
h->flags & HNAE3_SUPPORT_SERDES_LOOPBACK;
|
||||
|
||||
if (if_running)
|
||||
dev_close(ndev);
|
||||
|
||||
@ -316,7 +321,7 @@ static void hns3_self_test(struct net_device *ndev,
|
||||
|
||||
set_bit(HNS3_NIC_STATE_TESTING, &priv->state);
|
||||
|
||||
for (i = 0; i < HNS3_SELF_TEST_TPYE_NUM; i++) {
|
||||
for (i = 0; i < HNS3_SELF_TEST_TYPE_NUM; i++) {
|
||||
enum hnae3_loop loop_type = (enum hnae3_loop)st_param[i][0];
|
||||
|
||||
if (!st_param[i][1])
|
||||
|
@ -94,6 +94,7 @@ enum hclge_opcode_type {
|
||||
HCLGE_OPC_QUERY_LINK_STATUS = 0x0307,
|
||||
HCLGE_OPC_CONFIG_MAX_FRM_SIZE = 0x0308,
|
||||
HCLGE_OPC_CONFIG_SPEED_DUP = 0x0309,
|
||||
HCLGE_OPC_SERDES_LOOPBACK = 0x0315,
|
||||
|
||||
/* PFC/Pause commands */
|
||||
HCLGE_OPC_CFG_MAC_PAUSE_EN = 0x0701,
|
||||
@ -775,6 +776,17 @@ struct hclge_reset_cmd {
|
||||
u8 fun_reset_vfid;
|
||||
u8 rsv[22];
|
||||
};
|
||||
|
||||
#define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0)
|
||||
#define HCLGE_CMD_SERDES_DONE_B BIT(0)
|
||||
#define HCLGE_CMD_SERDES_SUCCESS_B BIT(1)
|
||||
struct hclge_serdes_lb_cmd {
|
||||
u8 mask;
|
||||
u8 enable;
|
||||
u8 result;
|
||||
u8 rsv[21];
|
||||
};
|
||||
|
||||
#define HCLGE_DEFAULT_TX_BUF 0x4000 /* 16k bytes */
|
||||
#define HCLGE_TOTAL_PKT_BUF 0x108000 /* 1.03125M bytes */
|
||||
#define HCLGE_DEFAULT_DV 0xA000 /* 40k byte */
|
||||
|
@ -787,9 +787,10 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset)
|
||||
hdev->hw.mac.speed == HCLGE_MAC_SPEED_1G) {
|
||||
count += 1;
|
||||
handle->flags |= HNAE3_SUPPORT_MAC_LOOPBACK;
|
||||
} else {
|
||||
count = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
count++;
|
||||
handle->flags |= HNAE3_SUPPORT_SERDES_LOOPBACK;
|
||||
} else if (stringset == ETH_SS_STATS) {
|
||||
count = ARRAY_SIZE(g_mac_stats_string) +
|
||||
ARRAY_SIZE(g_all_32bit_stats_string) +
|
||||
@ -3670,6 +3671,55 @@ static int hclge_set_mac_loopback(struct hclge_dev *hdev, bool en)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hclge_set_serdes_loopback(struct hclge_dev *hdev, bool en)
|
||||
{
|
||||
#define HCLGE_SERDES_RETRY_MS 10
|
||||
#define HCLGE_SERDES_RETRY_NUM 100
|
||||
struct hclge_serdes_lb_cmd *req;
|
||||
struct hclge_desc desc;
|
||||
int ret, i = 0;
|
||||
|
||||
req = (struct hclge_serdes_lb_cmd *)&desc.data[0];
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, false);
|
||||
|
||||
if (en) {
|
||||
req->enable = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
|
||||
req->mask = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
|
||||
} else {
|
||||
req->mask = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
|
||||
}
|
||||
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"serdes loopback set fail, ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
do {
|
||||
msleep(HCLGE_SERDES_RETRY_MS);
|
||||
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK,
|
||||
true);
|
||||
ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
||||
if (ret) {
|
||||
dev_err(&hdev->pdev->dev,
|
||||
"serdes loopback get, ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
} while (++i < HCLGE_SERDES_RETRY_NUM &&
|
||||
!(req->result & HCLGE_CMD_SERDES_DONE_B));
|
||||
|
||||
if (!(req->result & HCLGE_CMD_SERDES_DONE_B)) {
|
||||
dev_err(&hdev->pdev->dev, "serdes loopback set timeout\n");
|
||||
return -EBUSY;
|
||||
} else if (!(req->result & HCLGE_CMD_SERDES_SUCCESS_B)) {
|
||||
dev_err(&hdev->pdev->dev, "serdes loopback set failed in fw\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hclge_set_loopback(struct hnae3_handle *handle,
|
||||
enum hnae3_loop loop_mode, bool en)
|
||||
{
|
||||
@ -3681,6 +3731,9 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
|
||||
case HNAE3_MAC_INTER_LOOP_MAC:
|
||||
ret = hclge_set_mac_loopback(hdev, en);
|
||||
break;
|
||||
case HNAE3_MAC_INTER_LOOP_SERDES:
|
||||
ret = hclge_set_serdes_loopback(hdev, en);
|
||||
break;
|
||||
default:
|
||||
ret = -ENOTSUPP;
|
||||
dev_err(&hdev->pdev->dev,
|
||||
|
Loading…
Reference in New Issue
Block a user