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

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
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -85,7 +85,8 @@ struct hnae3_queue {
/*hnae3 loop mode*/
enum hnae3_loop {
	HNAE3_LOOP_APP,
	HNAE3_LOOP_SERDES,
	HNAE3_LOOP_SERIAL_SERDES,
	HNAE3_LOOP_PARALLEL_SERDES,
	HNAE3_LOOP_PHY,
	HNAE3_LOOP_NONE,
};
@@ -480,8 +481,9 @@ struct hnae3_unic_private_info {

#define HNAE3_SUPPORT_APP_LOOPBACK    BIT(0)
#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_SERDES_PARALLEL_LOOPBACK	BIT(4)

struct hnae3_handle {
	struct hnae3_client *client;
+11 −5
Original line number Diff line number Diff line
@@ -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_TYPE_NUM		2
#define HNS3_SELF_TEST_TPYE_NUM         3
#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,7 +78,8 @@ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en)
		return -EOPNOTSUPP;

	switch (loop) {
	case HNAE3_LOOP_SERDES:
	case HNAE3_LOOP_SERIAL_SERDES:
	case HNAE3_LOOP_PARALLEL_SERDES:
	case HNAE3_LOOP_APP:
		ret = h->ae_algo->ops->set_loopback(h, loop, en);
		break;
@@ -290,9 +291,14 @@ static void hns3_self_test(struct net_device *ndev,
	st_param[HNAE3_LOOP_APP][1] =
			h->flags & HNAE3_SUPPORT_APP_LOOPBACK;

	st_param[HNAE3_LOOP_SERDES][0] = HNAE3_LOOP_SERDES;
	st_param[HNAE3_LOOP_SERDES][1] =
			h->flags & HNAE3_SUPPORT_SERDES_LOOPBACK;
	st_param[HNAE3_LOOP_SERIAL_SERDES][0] = HNAE3_LOOP_SERIAL_SERDES;
	st_param[HNAE3_LOOP_SERIAL_SERDES][1] =
			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)
		ndev->netdev_ops->ndo_stop(ndev);
+1 −0
Original line number Diff line number Diff line
@@ -778,6 +778,7 @@ struct hclge_reset_cmd {
};

#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_SUCCESS_B		BIT(1)
struct hclge_serdes_lb_cmd {
+41 −13
Original line number Diff line number Diff line
@@ -50,7 +50,8 @@ MODULE_DEVICE_TABLE(pci, ae_algo_pci_tbl);

static const char hns3_nic_test_strs[][ETH_GSTRING_LEN] = {
	"App    Loopback test",
	"Serdes Loopback test",
	"Serdes serial Loopback test",
	"Serdes parallel Loopback test",
	"Phy    Loopback test"
};

@@ -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)
{
#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_dev *hdev = vport->back;
@@ -489,15 +493,17 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset)
	if (stringset == ETH_SS_TEST) {
		/* clear loopback bit flags at first */
		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_1G) {
			count += 1;
			handle->flags |= HNAE3_SUPPORT_APP_LOOPBACK;
		}

		count++;
		handle->flags |= HNAE3_SUPPORT_SERDES_LOOPBACK;
		count += 2;
		handle->flags |= HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK;
		handle->flags |= HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK;
	} else if (stringset == ETH_SS_STATS) {
		count = ARRAY_SIZE(g_mac_stats_string) +
			hclge_tqps_get_sset_count(handle, stringset);
@@ -527,9 +533,15 @@ static void hclge_get_strings(struct hnae3_handle *handle,
			       ETH_GSTRING_LEN);
			p += ETH_GSTRING_LEN;
		}
		if (handle->flags & HNAE3_SUPPORT_SERDES_LOOPBACK) {
		if (handle->flags & HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK) {
			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);
			p += ETH_GSTRING_LEN;
		}
@@ -3381,22 +3393,37 @@ static int hclge_set_app_loopback(struct hclge_dev *hdev, bool en)
	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_NUM	100
	struct hclge_serdes_lb_cmd *req;
	struct hclge_desc desc;
	int ret, i = 0;
	u8 loop_mode_b;

	req = (struct hclge_serdes_lb_cmd *)desc.data;
	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) {
		req->enable = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
		req->mask = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
		req->enable = loop_mode_b;
		req->mask = loop_mode_b;
	} else {
		req->mask = HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
		req->mask = loop_mode_b;
	}

	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
@@ -3462,8 +3489,9 @@ static int hclge_set_loopback(struct hnae3_handle *handle,
	case HNAE3_LOOP_APP:
		ret = hclge_set_app_loopback(hdev, en);
		break;
	case HNAE3_LOOP_SERDES:
		ret = hclge_set_serdes_loopback(hdev, en);
	case HNAE3_LOOP_SERIAL_SERDES:
	case HNAE3_LOOP_PARALLEL_SERDES:
		ret = hclge_set_serdes_loopback(hdev, en, loop_mode);
		break;
	default:
		ret = -ENOTSUPP;